Skip to content

Commit b548b82

Browse files
πŸ”§ verificationFile νƒ€μž… 처리 κ°œμ„ 
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-Claude) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
1 parent 89c07be commit b548b82

3 files changed

Lines changed: 32 additions & 28 deletions

File tree

β€Žapps/web/src/app/my/apply-mentor/_components/UniversityScreen/index.tsxβ€Ž

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
import clsx from "clsx";
44
import { useMemo, useRef } from "react";
55
import { useFormContext } from "react-hook-form";
6+
import { z } from "zod";
67
import { useUniversitySearch } from "@/apis/universities";
78
import BlockBtn from "@/components/button/BlockBtn";
89

910
import { mentorRegionList } from "@/constants/regions";
1011
import { toast } from "@/lib/zustand/useToastStore";
11-
import type { MentorApplicationFormData } from "../../_lib/schema";
12+
import { mentorApplicationSchema } from "../../_lib/schema";
13+
14+
type FormValues = z.input<typeof mentorApplicationSchema>;
1215

1316
type UniversityScreenProps = {
1417
onNext: () => void;
@@ -20,7 +23,7 @@ const UniversityScreen = ({ onNext }: UniversityScreenProps) => {
2023
setValue,
2124
trigger,
2225
formState: { errors },
23-
} = useFormContext<MentorApplicationFormData>();
26+
} = useFormContext<FormValues>();
2427

2528
const fileInputRef = useRef<HTMLInputElement>(null);
2629

β€Žapps/web/src/app/my/apply-mentor/_lib/schema.tsβ€Ž

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
11
import { z } from "zod";
22

3+
const verificationFileSchema = z
4+
.union([z.instanceof(File), z.null(), z.undefined()])
5+
.refine((file) => file !== null && file !== undefined, {
6+
message: "증λͺ… μ„œλ₯˜(파일)λ₯Ό μ—…λ‘œλ“œν•΄ μ£Όμ„Έμš”.",
7+
})
8+
.refine(
9+
(file) => {
10+
if (!file) return false;
11+
const allowedTypes = ["image/png", "image/jpeg", "image/jpg", "application/pdf"];
12+
return allowedTypes.includes(file.type);
13+
},
14+
{
15+
message: "파일 ν˜•μ‹μ€ png, jpg, pdf만 ν—ˆμš©λ©λ‹ˆλ‹€.",
16+
},
17+
)
18+
.transform((file) => file!);
19+
320
export const mentorApplicationSchema = z.object({
421
// Step 1: 관심 κ΅­κ°€
522
interestedCountries: z.array(z.string()).min(1, "관심 κ΅­κ°€λ₯Ό ν•˜λ‚˜ 이상 μ„ νƒν•΄μ£Όμ„Έμš”."),
623

724
// Step 2: μˆ˜ν•™ 학ꡐ
825
country: z.string().min(1, "κ΅­κ°€λ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”."),
926
universityName: z.string().min(1, "학ꡐλ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”."),
10-
verificationFile: z
11-
.instanceof(File)
12-
.nullable()
13-
.refine((file) => file !== null, {
14-
message: "증λͺ… μ„œλ₯˜(파일)λ₯Ό μ—…λ‘œλ“œν•΄ μ£Όμ„Έμš”.",
15-
})
16-
.refine(
17-
(file) => {
18-
if (!file) return false;
19-
const allowedTypes = ["image/png", "image/jpeg", "image/jpg", "application/pdf"];
20-
return allowedTypes.includes(file.type);
21-
},
22-
{
23-
message: "파일 ν˜•μ‹μ€ png, jpg, pdf만 ν—ˆμš©λ©λ‹ˆλ‹€.",
24-
},
25-
),
27+
verificationFile: verificationFileSchema,
2628

2729
// Step 3: μ€€λΉ„ 단계
2830
studyStatus: z.enum(["PLANNING", "STUDYING", "COMPLETED"], {

β€Žapps/web/src/app/my/apply-mentor/page.tsxβ€Ž

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { zodResolver } from "@hookform/resolvers/zod";
44
import { useRouter } from "next/navigation";
55
import { useState } from "react";
66
import { FormProvider, useForm } from "react-hook-form";
7+
import { z } from "zod";
78
import { usePostMentorApplication } from "@/apis/mentor";
89
import TopDetailNavigation from "@/components/layout/TopDetailNavigation";
910
import { Progress } from "@/components/ui/Progress";
@@ -12,19 +13,22 @@ import CompletionScreen from "./_components/CompletionScreen";
1213
import InterestCountriesScreen from "./_components/InterestCountriesScreen";
1314
import StudyStatusScreen from "./_components/StudyStatusScreen";
1415
import UniversityScreen from "./_components/UniversityScreen";
15-
import { type MentorApplicationFormData, mentorApplicationSchema } from "./_lib/schema";
16+
import { mentorApplicationSchema } from "./_lib/schema";
17+
18+
type FormInputValues = z.input<typeof mentorApplicationSchema>;
19+
type FormOutputValues = z.output<typeof mentorApplicationSchema>;
1620

1721
const ApplyMentorPage = () => {
1822
const router = useRouter();
1923
const [step, setStep] = useState<number>(1);
2024

21-
const methods = useForm<MentorApplicationFormData>({
25+
const methods = useForm<FormInputValues>({
2226
resolver: zodResolver(mentorApplicationSchema),
2327
defaultValues: {
2428
interestedCountries: [],
2529
country: "",
2630
universityName: "",
27-
verificationFile: undefined as any,
31+
verificationFile: undefined,
2832
studyStatus: undefined,
2933
},
3034
mode: "onChange",
@@ -42,12 +46,7 @@ const ApplyMentorPage = () => {
4246

4347
const progress = ((step - 1) / 3) * 100;
4448

45-
const onSubmit = methods.handleSubmit((data) => {
46-
if (!data.verificationFile) {
47-
toast.error("증λͺ…μ„œ νŒŒμΌμ„ μ—…λ‘œλ“œν•΄μ£Όμ„Έμš”.");
48-
return;
49-
}
50-
49+
const onSubmit = methods.handleSubmit((data: FormOutputValues) => {
5150
postMentorApplication(
5251
{
5352
interestedCountries: data.interestedCountries,
@@ -59,7 +58,7 @@ const ApplyMentorPage = () => {
5958
{
6059
onSuccess: () => {
6160
toast.success("λ©˜ν†  신청이 μ™„λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.");
62-
goNextStep(); // Go to completion screen
61+
goNextStep();
6362
},
6463
},
6564
);

0 commit comments

Comments
Β (0)