Skip to content

Commit 2d15baa

Browse files
committed
fix: merge confict 해결
2 parents 6f503e4 + f33fa1d commit 2d15baa

File tree

4 files changed

+225
-11
lines changed

4 files changed

+225
-11
lines changed

frontend/components/applicant/Board.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import Board from "@/components/common/board/Board";
44
import { getApplicantByPageWithGeneration } from "@/src/apis/applicant";
55
import ApplicantDetailRight from "./DetailRight.component";
6-
import ApplicantDetailLeft from "./DetailLeft.component";
76
import { useState } from "react";
87
import { ApplicantReq } from "@/src/apis/application";
98
import { applicantDataFinder } from "@/src/functions/finder";
@@ -12,6 +11,8 @@ import { useSearchParams } from "next/navigation";
1211
import { ORDER_MENU } from "@/src/constants";
1312
import { useSearchQuery } from "@/src/hooks/useSearchQuery";
1413
import { type ApplicantPassState } from "../../src/apis/kanban";
14+
import ApplicantDetailLeft from "./_applicant/ApplicantDetailLeft";
15+
import { findApplicantState } from "@/src/utils/applicant";
1516

1617
interface ApplicantBoardProps {
1718
generation: string;
@@ -74,9 +75,10 @@ const ApplicantBoard = ({ generation }: ApplicantBoardProps) => {
7475
Number(applicantDataFinder(value, "uploadDate"))
7576
).toLocaleString("ko-KR", { dateStyle: "short" }),
7677
],
77-
passState: `${
78-
applicantDataFinder(value, "passState").passState
79-
}` as ApplicantPassState,
78+
passState: `${applicantDataFinder(
79+
value,
80+
"passState"
81+
)}` as ApplicantPassState,
8082
}));
8183

8284
return (
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"use client";
2+
3+
import { ApplicantReq } from "@/src/apis/applicant";
4+
import CustomResource from "./_applicantNode/CustomResource";
5+
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
6+
import {
7+
patchApplicantPassState,
8+
PatchApplicantPassStateParams,
9+
} from "@/src/apis/passState";
10+
import { applicantDataFinder } from "@/src/functions/finder";
11+
import { getMyInfo } from "@/src/apis/interview";
12+
import ApplicantLabel from "../applicantNode/Label.component";
13+
import ApplicantComment from "../applicantNode/comment/Comment.component";
14+
15+
interface DetailLeftProps {
16+
data: ApplicantReq[];
17+
generation: string;
18+
cardId: number;
19+
}
20+
const ApplicantDetailLeft = ({ data, cardId, generation }: DetailLeftProps) => {
21+
const queryClient = useQueryClient();
22+
const { mutate: updateApplicantPassState } = useMutation({
23+
mutationFn: (params: PatchApplicantPassStateParams) =>
24+
patchApplicantPassState(params),
25+
onSuccess: () => {
26+
queryClient.invalidateQueries({
27+
queryKey: [
28+
"allApplicantsWithPassState",
29+
applicantDataFinder(data, "generation"),
30+
],
31+
});
32+
},
33+
});
34+
const { data: userData } = useQuery(["user"], getMyInfo);
35+
36+
const postId = applicantDataFinder(data, "id");
37+
38+
const onClickPass = () => {
39+
const ok = confirm("합격 처리하시겠습니까?");
40+
if (!ok) return;
41+
updateApplicantPassState({
42+
applicantId: postId,
43+
afterState: "pass",
44+
});
45+
};
46+
47+
const onClickNonPass = () => {
48+
const ok = confirm("불합격 처리하시겠습니까?");
49+
if (!ok) return;
50+
updateApplicantPassState({
51+
applicantId: postId,
52+
afterState: "non-pass",
53+
});
54+
};
55+
56+
return (
57+
<>
58+
<CustomResource
59+
data={data}
60+
ableToEdit={
61+
userData?.role === "ROLE_OPERATION" ||
62+
userData?.role === "ROLE_PRESIDENT"
63+
}
64+
onClickPass={onClickPass}
65+
onClickNonPass={onClickNonPass}
66+
/>
67+
<ApplicantLabel postId={postId} generation={generation} />
68+
<ApplicantComment
69+
cardId={cardId}
70+
postId={postId}
71+
generation={generation}
72+
/>
73+
</>
74+
);
75+
};
76+
77+
export default ApplicantDetailLeft;
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { applicantDataFinder } from "@/src/functions/finder";
2+
import Portfolio from "../../applicantNode/Portfolio";
3+
import { ApplicantReq } from "@/src/apis/applicant";
4+
import Txt from "@/components/common/Txt.component";
5+
import { getApplicantPassState } from "@/src/functions/formatter";
6+
7+
interface CustomResourceProps {
8+
data: ApplicantReq[];
9+
ableToEdit?: boolean;
10+
onClickPass?: () => void;
11+
onClickNonPass?: () => void;
12+
}
13+
14+
const CustomResource = ({
15+
data,
16+
ableToEdit = false,
17+
onClickPass,
18+
onClickNonPass,
19+
}: CustomResourceProps) => {
20+
return (
21+
<>
22+
<div className="flex flex-col gap-1 mb-2">
23+
<Txt className="text-xl text-secondary-200 font-medium">
24+
{applicantDataFinder(data, "major")}
25+
</Txt>
26+
<div className="flex gap-8 items-center">
27+
<Txt typography="h2">{`[${applicantDataFinder(
28+
data,
29+
"field"
30+
)}] ${applicantDataFinder(data, "name")}`}</Txt>
31+
<div className="flex justify-between grow items-center">
32+
<Txt typography="h5" color="light_gray" className="truncate">
33+
{getApplicantPassState(applicantDataFinder(data, "passState")) ||
34+
"에러 발생"}
35+
</Txt>
36+
{ableToEdit && (
37+
<div className="flex gap-4">
38+
<button
39+
className="border rounded-lg px-4 py-2 truncate hover:bg-primary-100"
40+
onClick={onClickPass}
41+
>
42+
합격
43+
</button>
44+
<button
45+
className="border rounded-lg px-4 py-2 truncate hover:bg-primary-100"
46+
onClick={onClickNonPass}
47+
>
48+
불합격
49+
</button>
50+
</div>
51+
)}
52+
</div>
53+
</div>
54+
</div>
55+
<div className="flex gap-4 mb-8">
56+
<div className="flex gap-1">
57+
<Txt typography="h3" color="gray" className="font-normal">
58+
1지망:
59+
</Txt>
60+
<Txt typography="h3" color="blue">
61+
{applicantDataFinder(data, "field1")}
62+
</Txt>
63+
</div>
64+
<div className="flex gap-1">
65+
<Txt typography="h3" color="gray" className="font-normal">
66+
2지망:
67+
</Txt>
68+
<Txt typography="h3" color="blue">
69+
{applicantDataFinder(data, "field2")}
70+
</Txt>
71+
</div>
72+
</div>
73+
<div className="flex flex-col gap-4">
74+
<Portfolio data={data} />
75+
</div>
76+
</>
77+
);
78+
};
79+
80+
export default CustomResource;

frontend/src/apis/applicant/index.ts

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,46 @@ interface AllApplicantReq {
1212
[string: string]: string;
1313
}
1414

15+
interface ApplicantByPageReqAnswer {
16+
field: string;
17+
field1: string;
18+
field2: string;
19+
name: string;
20+
contacted: string;
21+
classOf: string;
22+
registered: string;
23+
grade: string;
24+
semester: string;
25+
major: string;
26+
doubleMajor: string;
27+
minor: string;
28+
activity: string;
29+
reason: string;
30+
future: string;
31+
experience: string;
32+
experienceTextarea: string;
33+
restoration: string;
34+
deep: string;
35+
collaboration: string;
36+
studyPlan: string;
37+
portfolio: string;
38+
fileUrl: string;
39+
email: string;
40+
check: string;
41+
personalInformationAgree: string;
42+
personalInformationAgreeForPortfolio: string;
43+
generation: string;
44+
uploadDate: string;
45+
channel: string;
46+
timeline: number[];
47+
id: string;
48+
year: number;
49+
created_at: string;
50+
passState: {
51+
passState: ApplicantPassState;
52+
};
53+
}
54+
1555
export const getApplicantByIdWithField = async (
1656
id: string,
1757
fields?: string[]
@@ -36,9 +76,29 @@ export interface PageInfo {
3676
boardLimit: number;
3777
}
3878

79+
function formatApplicantsDataToApplicantReq(
80+
applicants: ApplicantByPageReqAnswer[]
81+
) {
82+
return applicants.map(
83+
(applicant) =>
84+
Object.keys(applicant).map((key) => {
85+
if (key === "passState") {
86+
return {
87+
name: "passState",
88+
answer: applicant.passState.passState,
89+
};
90+
}
91+
return {
92+
name: key,
93+
answer: applicant[key as keyof ApplicantByPageReqAnswer],
94+
};
95+
}) as ApplicantReq[]
96+
);
97+
}
98+
3999
interface ApplicantByPageReq {
40100
pageInfo: PageInfo;
41-
answers: AllApplicantReq[];
101+
answers: ApplicantByPageReqAnswer[];
42102
}
43103

44104
export const getApplicantByPageWithGeneration = async (
@@ -54,12 +114,7 @@ export const getApplicantByPageWithGeneration = async (
54114

55115
return {
56116
maxPage: pageInfo.endPage,
57-
applicants: answers.map((applicant) =>
58-
Object.keys(applicant).map((key) => ({
59-
name: key,
60-
answer: applicant[key],
61-
}))
62-
),
117+
applicants: formatApplicantsDataToApplicantReq(answers),
63118
};
64119
};
65120

0 commit comments

Comments
 (0)