Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactor] 원서 작성 페이지 리펙토링 #167

Open
wants to merge 33 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a3deb39
feat : step enum 추가
gaoooon Jan 8, 2025
6c8f5ab
fix : step에 따른 schema로 변경
gaoooon Jan 8, 2025
c909fb4
del : zustand 제거
gaoooon Jan 8, 2025
c0be4c9
feat : getValuesByEnum util 추가
gaoooon Jan 8, 2025
72ea55b
fix : options parameter 옵셔널화
gaoooon Jan 8, 2025
7d56a47
fix : useStore 제거, 구조 변경, 컴포넌트 이름 변경
gaoooon Jan 8, 2025
8f7119d
del : score 타입 삭제
gaoooon Jan 8, 2025
e03ede5
fix : 상수 이름 변경
gaoooon Jan 8, 2025
e1b80a4
feat : MAX_SCORE, MIN_SCORE, GED_MAX_SCORE 상수 추가
gaoooon Jan 8, 2025
29f8fe3
feat : 원서 작성 값 enum 추가
gaoooon Jan 8, 2025
15d6746
del : semesterType 삭제
gaoooon Jan 8, 2025
7305915
fix : 원서 타입 수정
gaoooon Jan 8, 2025
e995563
fix : 모의성적 계산 페이지 구조 수정
gaoooon Jan 8, 2025
66eae07
fix : 바뀐 상수 이름에 맞게 변경
gaoooon Jan 8, 2025
10f5a22
del : zustand 로직 제거
gaoooon Jan 8, 2025
db4109f
Merge branch 'main' into refactor/oneseoWritingPage
gaoooon Jan 24, 2025
e6d0b22
feat : 계산후 dialog 추가
gaoooon Jan 31, 2025
1f92375
fix : 잘못된 조건식 수정
gaoooon Jan 31, 2025
70304dc
feat : ACHIEVEMENT_FIELD_LIST 상수 추가
gaoooon Jan 31, 2025
9c66225
feat : schema 재사용되는 부분 분리
gaoooon Jan 31, 2025
3b8a22e
feat : valueAsNumber 옵션 추가
gaoooon Jan 31, 2025
6a4f76b
fix : reset 제거하고 setValue로 변경
gaoooon Jan 31, 2025
6f7cfe8
fix : PostOneseoType null 타입을 옵셔널로 변경
gaoooon Jan 31, 2025
977e0da
feat : AchievementType 추가
gaoooon Jan 31, 2025
199190d
refactor : 구조 수정
gaoooon Jan 31, 2025
b5cbcbc
fix : map으로 반복되는 list props로 받도록 변경
gaoooon Jan 31, 2025
2bed128
fix : reset에서 setValue로 변경
gaoooon Jan 31, 2025
75be3c8
feat : baseUrl, handleCheckScoreButtonClick props 추가
gaoooon Jan 31, 2025
b4810c1
feat : api handling, dialog 추가
gaoooon Jan 31, 2025
d53e7d4
feat : dependency 업데이트
gaoooon Jan 31, 2025
8201c19
del : EditStep4Page 삭제
gaoooon Jan 31, 2025
d3f9ec6
Merge branch 'develop' of https://github.com/themoment-team/hellogsm-…
gaoooon Feb 1, 2025
6ddb2da
fix : setTimeout 두번쨰 인자 추가
gaoooon Feb 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions apps/admin/src/app/edit/[memberId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { redirect } from 'next/navigation';
import { StepsContainer } from 'shared';
import { StepWrapper } from 'shared';
import { StepEnum } from 'types';

import { getOneseoByMemberId } from 'admin/app/apis/oneseo/getOneseoById';

const LAST_STEP = 4;

interface EditProps {
params: { memberId: string };
searchParams?: { [key: string]: string | undefined };
Expand All @@ -14,9 +13,9 @@ export default async function Edit({ params: { memberId }, searchParams }: EditP
const step = searchParams?.step;
const id = Number(memberId);

if (!step || (step && Number(step) > LAST_STEP)) return redirect(`/edit/${memberId}?step=1`);
if (!step || !['1', '2', '3', '4'].includes(step)) redirect(`/register/${id}?step=1`);

const data = await getOneseoByMemberId(id);

return <StepsContainer data={data} type="admin" param={step} memberId={Number(memberId)} />;
return <StepWrapper data={data} type="admin" step={step as StepEnum} memberId={id} />;
}
25 changes: 0 additions & 25 deletions apps/admin/src/pageContainer/Edit/Step4Page/index.tsx

This file was deleted.

1 change: 0 additions & 1 deletion apps/admin/src/pageContainer/Edit/index.ts

This file was deleted.

7 changes: 4 additions & 3 deletions apps/client/src/app/register/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { getDate } from 'api';
import { redirect } from 'next/navigation';
import { StepEnum } from 'types';

import { getMyMemberInfo, getMyOneseo } from 'client/app/apis';
import { RegisterStepsPage } from 'client/pageContainer';
Expand Down Expand Up @@ -27,9 +28,9 @@ export default async function Register({ searchParams }: RegisterProps) {
currentTime < new Date(dateList.oneseoSubmissionEnd).getTime()
: false;

if (info === undefined || (data && !data.step) || !isOneseoWrite) redirect('/');
if (!info || (data && !data.step) || !isOneseoWrite) redirect('/');

if (!step) redirect('/register?step=1');
if (!step || !['1', '2', '3', '4'].includes(step)) redirect('/register?step=1');

return <RegisterStepsPage data={data} info={info} param={step} />;
return <RegisterStepsPage data={data} info={info} step={step as StepEnum} />;
}
119 changes: 100 additions & 19 deletions apps/client/src/pageContainer/CalculatePage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,101 @@
/* eslint-disable @typescript-eslint/naming-convention */
'use client';

import { useState } from 'react';

import { zodResolver } from '@hookform/resolvers/zod';
import { usePostMockScore } from 'api';
import Image from 'next/image';
import { Button, ScoreRegister, useStore } from 'shared';
import { GraduationType } from 'types';
import { useForm } from 'react-hook-form';
import { Button, ScoreCalculateDialog, Step4Register, step4Schema } from 'shared';
import {
GraduationTypeValueEnum,
LiberalSystemValueEnum,
MockScoreType,
Step4FormType,
} from 'types';

import { ComputerRecommendedPage } from 'client/pageContainer';

import { ARTS_PHYSICAL_SUBJECTS, GENERAL_SUBJECTS } from 'shared/constants';
import { cn } from 'shared/lib/utils';

const graduationArray: { text: string; value: GraduationType; img: string }[] = [
{ text: '졸업 예정', value: 'CANDIDATE', img: '/images/candidate.png' },
{ text: '졸업자', value: 'GRADUATE', img: '/images/graduate.png' },
{ text: '검정고시', value: 'GED', img: '/images/ged.png' },
const graduationArray = [
{ text: '졸업 예정', value: GraduationTypeValueEnum.CANDIDATE, img: '/images/candidate.png' },
{ text: '졸업자', value: GraduationTypeValueEnum.GRADUATE, img: '/images/graduate.png' },
{ text: '검정고시', value: GraduationTypeValueEnum.GED, img: '/images/ged.png' },
];

const CalculatePage = () => {
const { graduationType, setGraduationType } = useStore();
const [isClickable, setIsClickable] = useState(false);
const step4UseForm = useForm<Step4FormType>({
resolver: zodResolver(step4Schema),
defaultValues: {
liberalSystem: LiberalSystemValueEnum.FREE_GRADE,
},
});

const [graduationType, setGraduationType] = useState<GraduationTypeValueEnum | null>(null);
const [isDialog, setIsDialog] = useState<boolean>(false);
const [scoreCalculateDialogData, setScoreCalculateDialogData] = useState<MockScoreType | null>(
null,
);
const isCandidate = graduationType === GraduationTypeValueEnum.CANDIDATE;
const isGED = graduationType === GraduationTypeValueEnum.GED;
const isGraduate = graduationType === GraduationTypeValueEnum.GRADUATE;
Comment on lines +42 to +44
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GraduationTypeValueEnum.CANDIDATE처럼 Enum 값을 여러 번 직접 사용하는 대신, 상위에서 구조 분해 할당하여 사용하는 게 어떨까요?

const { CANDIDATE, GED, GRADUATE } = GraduationTypeValueEnum;

const isCandidate = graduationType === CANDIDATE;
const isGED = graduationType === GED;
const isGraduate = graduationType === GRADUATE;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum도 구조 분해 할당이 되는지는 몰랐네요
그치만 제 의견을 말씀드리자면 enum이 현재 대문자로 되어있는데 구조분해 할당을 하여 사용한다면 추후에 코드를 볼떄 상수를 사용하고 있다고 생각할수도 있을것 같습니다 그래서 구조 분해 할당을 사용하지 않는 방식이 enum을 사용하고 있다는 사실을 명확하게 나타내는것 같습니다
다른 분들의 의견도 여쭈어봐야 할것 같습니다

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 의견 감사합니다! 구조 분해 할당을 사용하면 코드가 간결해지긴 하지만, 말씀하신 대로 enum이 무엇을 나타내는지 명확하게 인지할 수 있는 점에서는 구조 분해 할당이 다소 혼동을 줄 수 있을 것 같습니다. 특히 대문자 상수와 비교했을 때 enum이라는 사실을 코드만 보고 구별하기 어려울 수 있겠네요.

해당 의견에 대해서 어떻게 생각하시는지 궁금합니다! @yoosion030 @frorong @hyeongrok7874

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋은 리뷰 주제네요, 코드를 보았을 때 네이밍에 enum이라는 것이 드러나기 때문에, 구조 분해 할당을 사용했을 때 enum이 상수처럼 보인다고 느껴지진 않는 것 같습니다.

저는 구조 분해 할당을 사용하여 가독성을 줄이는 관점 보다는 enum을 사용하는게 맞는 관점인지 먼저 논의해보면 좋을 것 같다고 생각해요. enum을 자주 사용해보진 않아서, 현재 케이스에 enum을 사용하는게 맞는지 의문이 들긴하거든요.

https://xpectation.tistory.com/218
해당 자료 참고하여 enum, const enum, as const 중에 어떠한 것으로 타입을 관리할 것인지 먼저 의논한 뒤에 코드 가독성에 대한 내용을 다루면 좋겠네요.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

글을 읽고 처음 생각했을때는 enum은 양방향 맵핑이 가능하다고 해서 현재 상황에서는 사용하지 않기 떄문에 as const를 사용하면 된다고 생각했었는데 조금 더 찾아보니 숫자형 enum만 양방향 맵핑이 가능해서 기존 코드를 그대로 유지해도 상관 없다고 생각합니다. 그리고 제가 enum을 도입한 이유를 말씀드리자면 기존의 방식은 유니온 타입으로 되어있었는데 값을 할당할때나 값을 비교할때 더 명시적으로 사용할수 있어 도입하게 되었습니다

const isStep4Success = step4Schema.safeParse(step4UseForm.watch()).success;

const { mutate: postMockScore } = usePostMockScore(graduationType!, {
onSuccess: (data) => {
setScoreCalculateDialogData(data);
setIsDialog(true);
},
});

const handleCalculateButtonClick = () => {
const {
liberalSystem,
achievement1_2,
achievement2_1,
achievement2_2,
achievement3_1,
achievement3_2,
newSubjects,
artsPhysicalAchievement,
absentDays,
attendanceDays,
volunteerTime,
freeSemester,
gedTotalScore,
} = step4UseForm.watch();

const body = isGED
? { gedTotalScore: gedTotalScore! }
: {
liberalSystem: liberalSystem,
achievement1_2: achievement1_2!,
achievement2_1: achievement2_1!,
achievement2_2: achievement2_2!,
achievement3_1: achievement3_1!,
achievement3_2: achievement3_2!,
newSubjects: newSubjects,
artsPhysicalAchievement: artsPhysicalAchievement!,
absentDays: absentDays!,
attendanceDays: attendanceDays!,
volunteerTime: volunteerTime!,
freeSemester: freeSemester,
generalSubjects: [...GENERAL_SUBJECTS],
artsPhysicalSubjects: [...ARTS_PHYSICAL_SUBJECTS],
};

postMockScore(body);
};

return (
<>
<ComputerRecommendedPage />
{graduationType ? (
<div className={cn('sm:flex', 'justify-center', 'rounded-[1.25rem]', 'hidden')}>
<div className={cn('pb-10', 'mb-40', 'bg-white', 'mt-[3.56rem]', 'rounded-[1.25rem]')}>
<div className={cn('mb-[3.56rem]', 'bg-white', 'mt-[3.56rem]', 'rounded-[1.25rem]')}>
<header
className={cn(
'w-266',
Expand All @@ -40,25 +110,29 @@ const CalculatePage = () => {
'border-gray-100',
)}
>
<Button onClick={() => setGraduationType(undefined)} variant="ghost">
<Button onClick={() => setGraduationType(null)} variant="ghost">
이전
</Button>
<Button
form="scoreForm"
type="submit"
variant={isClickable ? 'next' : 'submit'}
disabled={!isClickable}
variant={isStep4Success ? 'next' : 'submit'}
disabled={!isStep4Success}
onClick={handleCalculateButtonClick}
>
내 성적 계산하기
</Button>
</header>
<div className={cn('w-full', 'h-6')} />
<ScoreRegister
type="calculate"
data={undefined}
isStep4Clickable={isClickable}
setIsStep4Clickable={setIsClickable}
/>
<div className={cn('p-8', 'pt-6', 'pb-10')}>
<Step4Register
graduationType={graduationType}
isCandidate={isCandidate}
isGED={isGED}
isGraduate={isGraduate}
type="calculate"
{...step4UseForm}
/>
</div>
</div>
</div>
) : (
Expand Down Expand Up @@ -107,6 +181,13 @@ const CalculatePage = () => {
</div>
</div>
)}

<ScoreCalculateDialog
isDialog={isDialog}
setIsDialog={setIsDialog}
scoreCalculateDialogData={scoreCalculateDialogData}
type="score"
/>
</>
);
};
Expand Down
6 changes: 3 additions & 3 deletions apps/client/src/pageContainer/PrintPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cn } from 'client/lib/utils';

import { PrintIcon } from 'shared/assets';
import { Button } from 'shared/components';
import { artPhysicalSubjectArray, defaultSubjectArray } from 'shared/constants';
import { ARTS_PHYSICAL_SUBJECTS, GENERAL_SUBJECTS } from 'shared/constants';

import { useGetMyOneseo } from 'api/hooks';

Expand Down Expand Up @@ -296,7 +296,7 @@ const ApplicationPage = ({ initialData }: PrintPageProps) => {
<div className="h-[2.2vh] text-left">과목</div>
</div>
{[
...defaultSubjectArray,
...GENERAL_SUBJECTS,
...(oneseo.middleSchoolAchievement.newSubjects ?? []),
].map((subject) => (
<div
Expand Down Expand Up @@ -463,7 +463,7 @@ const ApplicationPage = ({ initialData }: PrintPageProps) => {
<div className="h-[2.2vh] text-right">학년</div>
<div className="h-[2.2vh] text-left">과목</div>
</div>
{[...artPhysicalSubjectArray].map((subject) => (
{[...ARTS_PHYSICAL_SUBJECTS].map((subject) => (
<div
key={subject}
className="flex items-center justify-center border-b border-black"
Expand Down
18 changes: 5 additions & 13 deletions apps/client/src/pageContainer/RegisterPage/StepsPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@

import { useEffect } from 'react';

import { StepsContainer, useStore } from 'shared';
import { GetMyOneseoType, MyMemberInfoType } from 'types';
import { StepWrapper } from 'shared';
import { GetMyOneseoType, MyMemberInfoType, StepEnum } from 'types';

import { ComputerRecommendedPage } from 'client/pageContainer';

interface RegisterStepsPageProps {
data: GetMyOneseoType | undefined;
info: MyMemberInfoType;
param: string;
step: StepEnum;
}

const RegisterStepsPage = ({ data, param, info }: RegisterStepsPageProps) => {
const { setAll } = useStore();

const RegisterStepsPage = ({ data, step, info }: RegisterStepsPageProps) => {
useEffect(() => {
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
event.preventDefault();
Expand All @@ -30,16 +28,10 @@ const RegisterStepsPage = ({ data, param, info }: RegisterStepsPageProps) => {
};
}, []);

useEffect(() => {
return () => {
setAll();
};
}, []);

return (
<>
<ComputerRecommendedPage />
<StepsContainer data={data} info={info} param={param} type="client" />;
<StepWrapper data={data} info={info} step={step} type="client" />;
</>
);
};
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/hooks/api/oneseo/usePostMockScore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { oneseoQueryKeys, oneseoUrl, post } from 'api/libs';

export const usePostMockScore = (
type: GraduationType,
options: UseMutationOptions<
options?: UseMutationOptions<
MockScoreType,
AxiosError,
MiddleSchoolAchievementType | GEDAchievementType
Expand Down
5 changes: 3 additions & 2 deletions packages/api/src/hooks/api/oneseo/usePostMyOneseo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { PostOneseoType } from 'types';

import { oneseoQueryKeys, oneseoUrl, post } from 'api/libs';

export const usePostMyOneseo = (options: UseMutationOptions<unknown, AxiosError, PostOneseoType>) =>
export const usePostMyOneseo = (
options?: UseMutationOptions<unknown, AxiosError, PostOneseoType>,
) =>
useMutation({
mutationKey: oneseoQueryKeys.postMyOneseo(),
mutationFn: (data: PostOneseoType) => post(oneseoUrl.postMyOneseo(), data),
...options,
});

2 changes: 1 addition & 1 deletion packages/api/src/hooks/api/oneseo/usePutOneseoById.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { oneseoQueryKeys, oneseoUrl, put } from 'api/libs';

export const usePutOneseoByMemberId = (
memberId: number,
options: UseMutationOptions<unknown, AxiosError, PostOneseoType>,
options?: UseMutationOptions<unknown, AxiosError, PostOneseoType>,
) =>
useMutation({
mutationKey: oneseoQueryKeys.putOneseoByMemberId(memberId),
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from "./src";
export * from './src';
3 changes: 1 addition & 2 deletions packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
"react-daum-postcode": "^3.1.3",
"tailwind-config": "workspace:^",
"types": "workspace:^",
"zod": "^3.23.8",
"zustand": "^4.5.5"
"zod": "^3.23.8"
},
"devDependencies": {
"eslint": "^8",
Expand Down
Loading