From c8b0af4f86b5fcedae6c2a69f364ae803c897cfa Mon Sep 17 00:00:00 2001 From: lepitaaar Date: Mon, 18 Aug 2025 09:29:34 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20update=20=ED=9B=85=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=B4=20=EC=83=81=ED=83=9C=EB=A5=BC=20?= =?UTF-8?q?=EC=B5=9C=EC=8B=A0=ED=99=94=20=EC=8B=9C=ED=82=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../queries/applicants/useUpdateApplicant.ts | 18 +++++++++++ .../ApplicantDetailPage.tsx | 32 ++++++------------- 2 files changed, 28 insertions(+), 22 deletions(-) create mode 100644 frontend/src/hooks/queries/applicants/useUpdateApplicant.ts diff --git a/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts b/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts new file mode 100644 index 000000000..2553ceb5a --- /dev/null +++ b/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts @@ -0,0 +1,18 @@ +import updateApplicantDetail from "@/apis/application/updateApplicantDetail"; +import { ApplicationStatus } from "@/types/applicants"; +import { useMutation, useQueryClient } from "@tanstack/react-query" + +export const useUpdateApplicant = (clubId: string, appId: string) => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: ({memo, status}: { memo: string, status: ApplicationStatus }) => + updateApplicantDetail(memo, status, clubId, appId), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ["clubApplicants"] }); + }, + onError: (error) => { + console.log(`Error updating applicant detail: ${error}`); + } + }) +} \ No newline at end of file diff --git a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx index 9e5b8994d..185891e68 100644 --- a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx +++ b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx @@ -14,6 +14,7 @@ import mapStatusToGroup from '@/utils/mapStatusToGroup'; import { Question } from '@/types/application'; import PrevApplicantButton from '@/assets/images/icons/prev_applicant.svg'; import NextApplicantButton from '@/assets/images/icons/next_applicant.svg'; +import { useUpdateApplicant } from '@/hooks/queries/applicants/useUpdateApplicant'; const AVAILABLE_STATUSES = [ ApplicationStatus.SCREENING, // 서류검토 (SUBMITTED 포함) @@ -39,10 +40,11 @@ const ApplicantDetailPage = () => { const { questionId } = useParams<{ questionId: string }>(); const navigate = useNavigate(); const [applicantMemo, setAppMemo] = useState(''); - const [applicantStatus, setApplicantStatus] = useState(); - const { applicantsData, clubId, setApplicantsData } = useAdminClubContext(); + const [applicantStatus, setApplicantStatus] = useState(ApplicationStatus.SUBMITTED); + const { applicantsData, clubId } = useAdminClubContext(); const { data: formData, isLoading, isError } = useGetApplication(clubId!); + const { mutate: updateApplicant } = useUpdateApplicant(clubId!, questionId!); const { applicant, applicantIndex } = useMemo(() => { const index = @@ -61,12 +63,12 @@ const ApplicantDetailPage = () => { const updateApplicantDetail = useMemo( () => - debounce((memo: any, status: any) => { - updateApplicantMemo( - memo as string, - status as ApplicationStatus, - clubId!, - questionId!, + debounce((memo: string, status: ApplicationStatus) => { + updateApplicant( + { + memo, + status + } ); }, 400), [clubId, questionId], @@ -90,29 +92,15 @@ const ApplicantDetailPage = () => { .map((ans) => ans.value); }; - const updateApplicantInContext = ( - memo: string, - status: ApplicationStatus, - ) => { - if (!applicantsData || applicantIndex === -1) return; - - const updatedApplicants = [...applicantsData.applicants]; - updatedApplicants[applicantIndex] = { ...applicant, memo, status }; - - setApplicantsData({ ...applicantsData, applicants: updatedApplicants }); - }; - const handleMemoChange = (e: React.ChangeEvent) => { const newMemo = e.target.value; setAppMemo(newMemo); - updateApplicantInContext(newMemo, applicantStatus!); updateApplicantDetail(newMemo, applicantStatus); }; const handleStatusChange = (e: React.ChangeEvent) => { const newStatus = e.target.value as ApplicationStatus; setApplicantStatus(newStatus); - updateApplicantInContext(applicantMemo, newStatus); updateApplicantDetail(applicantMemo, newStatus); }; From 5403817e95136c2671478d7a5559ec5a8daecfc7 Mon Sep 17 00:00:00 2001 From: lepitaaar Date: Mon, 18 Aug 2025 09:45:28 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20debounce=EC=9D=98=20unkown=EC=97=90?= =?UTF-8?q?=20=EB=94=B0=EB=9D=BC=20=ED=83=80=EC=9E=85=EA=B0=80=EB=93=9C?= =?UTF-8?q?=EB=A5=BC=20=EC=B6=94=EA=B0=80=ED=96=88=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ApplicantDetailPage/ApplicantDetailPage.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx index 185891e68..16eda683b 100644 --- a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx +++ b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx @@ -63,7 +63,15 @@ const ApplicantDetailPage = () => { const updateApplicantDetail = useMemo( () => - debounce((memo: string, status: ApplicationStatus) => { + debounce((memo, status) => { + + function isApplicationStatus(v: unknown): v is ApplicationStatus { + return typeof v === 'string' && Object.values(ApplicationStatus).includes(v as ApplicationStatus); + } + + if (typeof memo !== 'string') return; + if (!isApplicationStatus(status)) return; + updateApplicant( { memo, From 40b5392184f3e67933bd94d658e3378301f378ca Mon Sep 17 00:00:00 2001 From: lepitaaar Date: Mon, 18 Aug 2025 10:03:18 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20legacy=20=EC=9E=84=ED=8F=AC?= =?UTF-8?q?=ED=8A=B8=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/hooks/queries/applicants/useUpdateApplicant.ts | 2 +- .../ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts b/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts index 2553ceb5a..5257d4966 100644 --- a/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts +++ b/frontend/src/hooks/queries/applicants/useUpdateApplicant.ts @@ -1,4 +1,4 @@ -import updateApplicantDetail from "@/apis/application/updateApplicantDetail"; +import { updateApplicantDetail } from "@/apis/application/updateApplicantDetail"; import { ApplicationStatus } from "@/types/applicants"; import { useMutation, useQueryClient } from "@tanstack/react-query" diff --git a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx index 16eda683b..4ec1117ca 100644 --- a/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx +++ b/frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantDetailPage/ApplicantDetailPage.tsx @@ -7,7 +7,6 @@ import QuestionContainer from '@/pages/ApplicationFormPage/components/QuestionCo import QuestionAnswerer from '@/pages/ApplicationFormPage/components/QuestionAnswerer/QuestionAnswerer'; import Spinner from '@/components/common/Spinner/Spinner'; import debounce from '@/utils/debounce'; -import updateApplicantMemo from '@/apis/application/updateApplicantDetail'; import { useGetApplication } from '@/hooks/queries/application/useGetApplication'; import { ApplicationStatus } from '@/types/applicants'; import mapStatusToGroup from '@/utils/mapStatusToGroup';