diff --git a/frontend/components/applicant/Board.tsx b/frontend/components/applicant/Board.tsx index f24daec..56fdf87 100644 --- a/frontend/components/applicant/Board.tsx +++ b/frontend/components/applicant/Board.tsx @@ -3,7 +3,6 @@ import Board from "@/components/common/board/Board"; import { getApplicantByPageWithGeneration } from "@/src/apis/applicant"; import ApplicantDetailRight from "./DetailRight.component"; -import ApplicantDetailLeft from "./DetailLeft.component"; import { useState } from "react"; import { ApplicantReq } from "@/src/apis/application"; import { applicantDataFinder } from "@/src/functions/finder"; @@ -12,6 +11,8 @@ import { useSearchParams } from "next/navigation"; import { ORDER_MENU } from "@/src/constants"; import { useSearchQuery } from "@/src/hooks/useSearchQuery"; import { type ApplicantPassState } from "../../src/apis/kanban"; +import ApplicantDetailLeft from "./_applicant/ApplicantDetailLeft"; +import { findApplicantState } from "@/src/utils/applicant"; interface ApplicantBoardProps { generation: string; @@ -74,9 +75,10 @@ const ApplicantBoard = ({ generation }: ApplicantBoardProps) => { Number(applicantDataFinder(value, "uploadDate")) ).toLocaleString("ko-KR", { dateStyle: "short" }), ], - passState: `${ - applicantDataFinder(value, "passState").passState - }` as ApplicantPassState, + passState: `${applicantDataFinder( + value, + "passState" + )}` as ApplicantPassState, })); return ( diff --git a/frontend/components/applicant/_applicant/ApplicantDetailLeft.tsx b/frontend/components/applicant/_applicant/ApplicantDetailLeft.tsx new file mode 100644 index 0000000..57389b0 --- /dev/null +++ b/frontend/components/applicant/_applicant/ApplicantDetailLeft.tsx @@ -0,0 +1,77 @@ +"use client"; + +import { ApplicantReq } from "@/src/apis/applicant"; +import CustomResource from "./_applicantNode/CustomResource"; +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; +import { + patchApplicantPassState, + PatchApplicantPassStateParams, +} from "@/src/apis/passState"; +import { applicantDataFinder } from "@/src/functions/finder"; +import { getMyInfo } from "@/src/apis/interview"; +import ApplicantLabel from "../applicantNode/Label.component"; +import ApplicantComment from "../applicantNode/comment/Comment.component"; + +interface DetailLeftProps { + data: ApplicantReq[]; + generation: string; + cardId: number; +} +const ApplicantDetailLeft = ({ data, cardId, generation }: DetailLeftProps) => { + const queryClient = useQueryClient(); + const { mutate: updateApplicantPassState } = useMutation({ + mutationFn: (params: PatchApplicantPassStateParams) => + patchApplicantPassState(params), + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: [ + "allApplicantsWithPassState", + applicantDataFinder(data, "generation"), + ], + }); + }, + }); + const { data: userData } = useQuery(["user"], getMyInfo); + + const postId = applicantDataFinder(data, "id"); + + const onClickPass = () => { + const ok = confirm("합격 처리하시겠습니까?"); + if (!ok) return; + updateApplicantPassState({ + applicantId: postId, + afterState: "pass", + }); + }; + + const onClickNonPass = () => { + const ok = confirm("불합격 처리하시겠습니까?"); + if (!ok) return; + updateApplicantPassState({ + applicantId: postId, + afterState: "non-pass", + }); + }; + + return ( + <> + + + + + ); +}; + +export default ApplicantDetailLeft; diff --git a/frontend/components/applicant/_applicant/_applicantNode/CustomResource.tsx b/frontend/components/applicant/_applicant/_applicantNode/CustomResource.tsx new file mode 100644 index 0000000..cad15de --- /dev/null +++ b/frontend/components/applicant/_applicant/_applicantNode/CustomResource.tsx @@ -0,0 +1,80 @@ +import { applicantDataFinder } from "@/src/functions/finder"; +import Portfolio from "../../applicantNode/Portfolio"; +import { ApplicantReq } from "@/src/apis/applicant"; +import Txt from "@/components/common/Txt.component"; +import { getApplicantPassState } from "@/src/functions/formatter"; + +interface CustomResourceProps { + data: ApplicantReq[]; + ableToEdit?: boolean; + onClickPass?: () => void; + onClickNonPass?: () => void; +} + +const CustomResource = ({ + data, + ableToEdit = false, + onClickPass, + onClickNonPass, +}: CustomResourceProps) => { + return ( + <> +
+ + {applicantDataFinder(data, "major")} + +
+ {`[${applicantDataFinder( + data, + "field" + )}] ${applicantDataFinder(data, "name")}`} +
+ + {getApplicantPassState(applicantDataFinder(data, "passState")) || + "에러 발생"} + + {ableToEdit && ( +
+ + +
+ )} +
+
+
+
+
+ + 1지망: + + + {applicantDataFinder(data, "field1")} + +
+
+ + 2지망: + + + {applicantDataFinder(data, "field2")} + +
+
+
+ +
+ + ); +}; + +export default CustomResource; diff --git a/frontend/src/apis/applicant/index.ts b/frontend/src/apis/applicant/index.ts index f729c8c..a5e57f6 100644 --- a/frontend/src/apis/applicant/index.ts +++ b/frontend/src/apis/applicant/index.ts @@ -12,6 +12,46 @@ interface AllApplicantReq { [string: string]: string; } +interface ApplicantByPageReqAnswer { + field: string; + field1: string; + field2: string; + name: string; + contacted: string; + classOf: string; + registered: string; + grade: string; + semester: string; + major: string; + doubleMajor: string; + minor: string; + activity: string; + reason: string; + future: string; + experience: string; + experienceTextarea: string; + restoration: string; + deep: string; + collaboration: string; + studyPlan: string; + portfolio: string; + fileUrl: string; + email: string; + check: string; + personalInformationAgree: string; + personalInformationAgreeForPortfolio: string; + generation: string; + uploadDate: string; + channel: string; + timeline: number[]; + id: string; + year: number; + created_at: string; + passState: { + passState: ApplicantPassState; + }; +} + export const getApplicantByIdWithField = async ( id: string, fields?: string[] @@ -36,9 +76,29 @@ export interface PageInfo { boardLimit: number; } +function formatApplicantsDataToApplicantReq( + applicants: ApplicantByPageReqAnswer[] +) { + return applicants.map( + (applicant) => + Object.keys(applicant).map((key) => { + if (key === "passState") { + return { + name: "passState", + answer: applicant.passState.passState, + }; + } + return { + name: key, + answer: applicant[key as keyof ApplicantByPageReqAnswer], + }; + }) as ApplicantReq[] + ); +} + interface ApplicantByPageReq { pageInfo: PageInfo; - answers: AllApplicantReq[]; + answers: ApplicantByPageReqAnswer[]; } export const getApplicantByPageWithGeneration = async ( @@ -54,12 +114,7 @@ export const getApplicantByPageWithGeneration = async ( return { maxPage: pageInfo.endPage, - applicants: answers.map((applicant) => - Object.keys(applicant).map((key) => ({ - name: key, - answer: applicant[key], - })) - ), + applicants: formatApplicantsDataToApplicantReq(answers), }; };