From f1293f13cc47629bac8c143d63319ee2fd0698db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=A1=B0=EC=98=88=EC=A7=84?= Date: Mon, 19 Aug 2024 00:40:22 +0900 Subject: [PATCH] feat: save info in uploadPage --- src/app/routes/form.$key.tsx | 36 +++++++++++++---- .../profile/model/convertProfileToDto.ts | 2 +- src/pages/form/complete/UploadLoadingPage.tsx | 40 ++++++++++++++++--- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/app/routes/form.$key.tsx b/src/app/routes/form.$key.tsx index eb06e74..6b3d8f6 100644 --- a/src/app/routes/form.$key.tsx +++ b/src/app/routes/form.$key.tsx @@ -10,18 +10,19 @@ import { CompletePage } from 'src/pages/form/complete/CompletePage'; import { useProfileFirstName } from 'src/entities/profile/lib/useProfileFirstName'; import { Shortcut } from 'src/processes/shortcut/Shortcut'; import styles from 'src/app/styles/form.module.css'; -import { validateLink } from 'src/types'; -import { json, LoaderFunctionArgs } from '@remix-run/node'; +import { saveInfo, validateLink } from 'src/types'; +import { ActionFunctionArgs, json, LoaderFunctionArgs } from '@remix-run/node'; +import { useLoaderData } from '@remix-run/react'; const MAX_STEP_COUNT = 7; -const createFormPageStep = ({ name, increase }: { name: string; increase: () => void }) => ({ +const createFormPageStep = ({ name, linkKey, increase }: { name: string; linkKey: string; increase: () => void }) => ({ 0: , 1: , 2: , 3: , 4: , - 5: , + 5: , 6: , }); @@ -32,18 +33,39 @@ export const loader = async ({ params }: LoaderFunctionArgs) => { const { data } = await validateLink(key); if (!data.isValid) throw new Response('', { status: 404 }); - return json({ linkId: data.linkId }); + return json({ linkKey: key }); }; -export const action = async () => {}; +export const action = async ({ request }: ActionFunctionArgs) => { + const body = await request.formData(); + const linkKey = body.get('linkKey'); + if (typeof linkKey !== 'string') return { status: 400 }; + + const { data, status } = await saveInfo( + // TODO: zod로 타입 체크 + // TODO: 이미지 업로드 + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + { userInfo: JSON.parse(body.get('userInfo')), idealPartner: JSON.parse(body.get('idealPartner')) }, + { linkKey }, + { + headers: { + Authorization: `Bearer ${import.meta.env.VITE_DEV_JWT_TOKEN}`, + }, + }, + ); + + return { status, data }; +}; export default function ProfileFormPage() { + const { linkKey } = useLoaderData(); const name = useProfileFirstName(); const [step, setStep] = useState(0); const increase = () => setStep((prev) => (prev + 1 < MAX_STEP_COUNT ? prev + 1 : prev)); - const formPageStep = useMemo(() => createFormPageStep({ name, increase }), [name]); + const formPageStep = useMemo(() => createFormPageStep({ name, linkKey, increase }), [linkKey, name]); const showShortcut = [1, 3, 4].includes(step); diff --git a/src/entities/profile/model/convertProfileToDto.ts b/src/entities/profile/model/convertProfileToDto.ts index 98e3aa1..6feb8b9 100644 --- a/src/entities/profile/model/convertProfileToDto.ts +++ b/src/entities/profile/model/convertProfileToDto.ts @@ -5,7 +5,7 @@ import { convertDateObjectToDate } from 'src/shared/vo/date'; export const convertProfileToDto = (profile: MyProfile, images: ImageDto[]): UserInfoRequest => { return { name: profile.name, - birthDate: convertDateObjectToDate(profile.birthDate).toString(), + birthDate: convertDateObjectToDate(profile.birthDate).toISOString(), drinking: profile.drinking, // TODO: 오타 고쳐지면 삼항연산자 부분 삭제 gender: profile.gender === 'FEMALE' ? 'FEAMLE' : 'MALE', diff --git a/src/pages/form/complete/UploadLoadingPage.tsx b/src/pages/form/complete/UploadLoadingPage.tsx index eaa13e3..66cbafb 100644 --- a/src/pages/form/complete/UploadLoadingPage.tsx +++ b/src/pages/form/complete/UploadLoadingPage.tsx @@ -1,15 +1,45 @@ import { InfoBox } from 'src/shared/ui/InfoBox/InfoBox'; import styles from './UploadLoadingPage.module.css'; import { useEffect } from 'react'; +import { useActionData, useSubmit } from '@remix-run/react'; +import { action } from 'src/app/routes/form.$key'; +import { convertProfileToDto } from 'src/entities/profile/model/convertProfileToDto'; +import { convertIdealPartnerToDto } from 'src/entities/ideal_partner/model/convertIdealPartnerToDto'; +import { useMyProfileStore } from 'src/entities/profile/model/myProfileStore'; +import { useIdealPartnerStore } from 'src/entities/ideal_partner/model/idealPartnerStore'; + +export const UploadLoadingPage = ({ + name, + linkKey, + onComplete, +}: { + name: string; + linkKey: string; + onComplete: () => void; +}) => { + const result = useActionData(); + const submit = useSubmit(); + + const profile = useMyProfileStore((state) => state); + const idealPartner = useIdealPartnerStore((state) => state); -export const UploadLoadingPage = ({ name, onComplete }: { name: string; onComplete: () => void }) => { useEffect(() => { - const timer = setTimeout(onComplete, 5_000); - return () => { - clearTimeout(timer); - }; + submit( + { + linkKey, + userInfo: JSON.stringify(convertProfileToDto(profile, [])), + idealPartner: JSON.stringify(convertIdealPartnerToDto(idealPartner, [])), + }, + { method: 'post' }, + ); }, []); + useEffect(() => { + if (result?.status === 200) { + onComplete(); + } + }, [onComplete, result?.status]); + return (