Skip to content

Commit

Permalink
feat(admin): current-applicant-count form 페이지 적용 (#166)
Browse files Browse the repository at this point in the history
  • Loading branch information
saseungmin authored Aug 3, 2024
1 parent bc295ba commit 967259b
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 5 deletions.
41 changes: 37 additions & 4 deletions apps/admin/src/actions/count.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ import { revalidatePath } from 'next/cache';

import { put } from '@vercel/blob';

type TotalCountStatusStateType = {
type CountStateType = {
message: string;
messageType?: 'error' | 'success';
};

// eslint-disable-next-line import/prefer-default-export
export async function totalCountStatusAction(
_: TotalCountStatusStateType | null,
_: CountStateType | null,
formData: FormData,
): Promise<TotalCountStatusStateType> {
): Promise<CountStateType> {
try {
const requestForm = {
cumulativeApplicants: formData.get('cumulativeApplicants'),
Expand Down Expand Up @@ -45,3 +44,37 @@ export async function totalCountStatusAction(
};
}
}

export async function currentApplicantCountAction(
_: CountStateType | null,
formData: FormData,
): Promise<CountStateType> {
try {
const requestForm = {
designerApplicantCount: formData.get('designerApplicantCount'),
developerApplicantCount: formData.get('developerApplicantCount'),
};

const jsonString = JSON.stringify(requestForm);

const requestBlob = new Blob([jsonString], { type: 'application/json' });

await put('current_applicant_count.json', requestBlob, {
access: 'public',
token: process.env.DND_ACADEMY_V2_BLOB_READ_WRITE_TOKEN,
addRandomSuffix: false,
});

revalidatePath('/current-applicant-count');

return {
message: '수정사항이 반영되었습니다. 캐시 적용으로 실제 적용까지는 최대 5분정도 소요됩니다.',
messageType: 'success',
};
} catch (error) {
return {
message: '수정사항이 반영되지 않았습니다. 잠시 후 다시 시도해주세요.',
messageType: 'error',
};
}
}
7 changes: 7 additions & 0 deletions apps/admin/src/app/current-applicant-count/page.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.counter {
@include text('H6/Bold', 'primary');

@include xs {
@include text('body1/Bold');
}
}
34 changes: 34 additions & 0 deletions apps/admin/src/app/current-applicant-count/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { api, type CurrentApplicantCount } from '@dnd-academy/core';
import { Counter, PageTitle } from '@dnd-academy/ui';

import CurrentApplicantCountForm from '@/components/CurrentApplicantCountForm';

import styles from './page.module.scss';

async function page() {
const currentApplicantCountData = await api<CurrentApplicantCount>({
url: '/current_applicant_count.json',
method: 'GET',
});

const currentApplicantCount = currentApplicantCountData.designer
+ currentApplicantCountData.developer;

return (
<>
<PageTitle
title="현재 지원자 수"
subTitle="캐시 적용으로 실제 적용까지는 최대 5분정도 소요됩니다."
/>
<div className={styles.counter}>
오늘까지&nbsp;
<Counter count={currentApplicantCount} />
명이 지원했어요!
</div>
<CurrentApplicantCountForm initialApplicantCount={currentApplicantCountData} />
</>

);
}

export default page;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.applicantCountFormWrapper {
display: flex;
flex-direction: column;
gap: 20px;
margin-top: 20px;

.applicantCountForm {
display: flex;
flex-direction: row;
}

.message {
@include text('body1');

&.error {
color: color('tertiary');
}

&.success {
color: color('success');
}
}
}
50 changes: 50 additions & 0 deletions apps/admin/src/components/CurrentApplicantCountForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use client';

import { useFormState } from 'react-dom';

import { type CurrentApplicantCount } from '@dnd-academy/core';
import clsx from 'clsx';

import { currentApplicantCountAction } from '@/actions/count';
import SubmitButton from '@/components/common/SubmitButton';

import styles from './index.module.scss';

type Props = {
initialApplicantCount: CurrentApplicantCount;
};

function CurrentApplicantCountForm({ initialApplicantCount }: Props) {
const [state, formAction] = useFormState(currentApplicantCountAction, null);

return (
<div className={styles.applicantCountFormWrapper}>
<form action={formAction} className={styles.applicantCountForm}>
<div>
<label htmlFor="designer">
디자이너 지원자 수
<input type="number" id="designer" name="designerApplicantCount" defaultValue={initialApplicantCount.designer} />
</label>
</div>
<div>
<label htmlFor="developer">
개발자 지원자 수
<input type="number" id="developer" name="developerApplicantCount" defaultValue={initialApplicantCount.developer} />
</label>
</div>
<SubmitButton>업데이트하기</SubmitButton>
</form>
{state?.message && (
<div className={clsx(
styles.message,
state.messageType && styles[state.messageType],
)}
>
{state.message}
</div>
)}
</div>
);
}

export default CurrentApplicantCountForm;
3 changes: 2 additions & 1 deletion apps/admin/src/components/Navigator/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ function Navigator() {
<nav>
<ul>
<li>
<a href="/total-count-status">지원자 수 카드 섹션 정보 업데이트하기</a>
<a href="/current-applicant-count">현재 지원자 수 카운트 업데이트하기</a>
<a href="/total-count-status">총 지원자 수 카드 섹션 정보 업데이트하기</a>
</li>
</ul>
</nav>
Expand Down

0 comments on commit 967259b

Please sign in to comment.