diff --git a/src/app/login/onboarding-agree/page.tsx b/src/app/login/onboarding-agree/page.tsx index 728ca84e..918d9e78 100644 --- a/src/app/login/onboarding-agree/page.tsx +++ b/src/app/login/onboarding-agree/page.tsx @@ -1,5 +1,4 @@ import OnBoardingAgree from '@/features/onBoarding/components/OnBoardingAgree' -import OnBoardingInfo from '@/features/onBoarding/components/OnBoardingInfo' import OnBoaridngHeader from '@/features/onBoarding/components/OnBoaridngHeader' export default function OnBoardingAgreePage() { diff --git a/src/features/onBoarding/api/memberApi.tsx b/src/features/onBoarding/api/memberApi.tsx index c390b4a6..d0186a88 100644 --- a/src/features/onBoarding/api/memberApi.tsx +++ b/src/features/onBoarding/api/memberApi.tsx @@ -24,3 +24,29 @@ export async function submitMemberInfo(data: MemberInfo, accessToken: string) { console.error('Error submitting member info:', error) } } + +// src/features/member/api/memberApi.ts + +import { ConsentInfo } from '../types/memberTypes' + +export async function submitConsentInfo(data: ConsentInfo, accessToken: string) { + try { + const response = await fetch(`${process.env.NEXT_PUBLIC_LINKIT_SERVER_URL}/api/v1/member/consent`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json;charset=UTF-8', + Authorization: `Bearer ${accessToken}`, + }, + body: JSON.stringify(data), + credentials: 'include', + }) + + if (!response.ok) { + throw new Error(`Error submitting consent info: ${response.statusText}`) + } + + return await response.json() + } catch (error) { + console.error('Error submitting consent info:', error) + } +} diff --git a/src/features/onBoarding/components/OnBoardingAgree.tsx b/src/features/onBoarding/components/OnBoardingAgree.tsx index 113dfb4c..1b762f69 100644 --- a/src/features/onBoarding/components/OnBoardingAgree.tsx +++ b/src/features/onBoarding/components/OnBoardingAgree.tsx @@ -1,30 +1,12 @@ 'use client' -import { useState } from 'react' import { Button } from '@/shared/ui/Button/Button' import Image from 'next/image' +import { useOnBoardingAgree } from '../hooks/useOnBoardingAgree' export default function OnBoardingAgree() { - const [allChecked, setAllChecked] = useState(false) // "모두 동의하기" 상태 - const [checkedItems, setCheckedItems] = useState([false, false, false, false]) // 개별 항목 체크 상태 - - // 필수 항목 (첫 3개 항목) 체크 여부 확인 - const isNextEnabled = checkedItems.slice(0, 3).every(Boolean) - - // 개별 체크박스 클릭 핸들러 - const handleCheckClick = (index: number) => { - const updatedItems = [...checkedItems] - updatedItems[index] = !updatedItems[index] - setCheckedItems(updatedItems) - setAllChecked(updatedItems.every(Boolean)) - } - - // 모두 동의하기 버튼 클릭 핸들러 - const handleAllCheckClick = () => { - const newState = !allChecked - setAllChecked(newState) - setCheckedItems(checkedItems.map(() => newState)) - } + const { allChecked, checkedItems, isNextEnabled, handleCheckClick, handleAllCheckClick, submitConsentInfoHandler } = + useOnBoardingAgree() return (
@@ -55,7 +37,7 @@ export default function OnBoardingAgree() { '(필수) 만 14세 이상입니다', '(선택) 광고성 정보 수신 동의', ].map((item, index) => ( -
+
handleCheckClick(index)} className="flex cursor-pointer items-center gap-6">
다음 diff --git a/src/features/onBoarding/components/OnBoardingComplete.tsx b/src/features/onBoarding/components/OnBoardingComplete.tsx index 22726e86..a26e63f3 100644 --- a/src/features/onBoarding/components/OnBoardingComplete.tsx +++ b/src/features/onBoarding/components/OnBoardingComplete.tsx @@ -1,5 +1,6 @@ import { Button } from '@/shared/ui/Button/Button' import Image from 'next/image' +import Link from 'next/link' export default function OnBoardingComplete() { return ( @@ -13,10 +14,14 @@ export default function OnBoardingComplete() {

나머지 정보를 입력해 프로필을 완성해 보세요

- -

나중에 입력하기

+ + + + + 나중에 입력하기 +
diff --git a/src/features/onBoarding/hooks/useOnBoardingAgree.ts b/src/features/onBoarding/hooks/useOnBoardingAgree.ts new file mode 100644 index 00000000..416f0b30 --- /dev/null +++ b/src/features/onBoarding/hooks/useOnBoardingAgree.ts @@ -0,0 +1,57 @@ +// src/features/member/hooks/useOnBoardingAgree.ts + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import { useSetRecoilState } from 'recoil' +import { accessTokenState } from '@/context/recoil-context' +import { submitConsentInfo } from '../api/memberApi' +import { ConsentInfo } from '../types/memberTypes' + +export function useOnBoardingAgree() { + const router = useRouter() + const setAccessToken = useSetRecoilState(accessTokenState) + const [allChecked, setAllChecked] = useState(false) + const [checkedItems, setCheckedItems] = useState([false, false, false, false]) + + const isNextEnabled = checkedItems.slice(0, 3).every(Boolean) + + const handleCheckClick = (index: number) => { + const updatedItems = [...checkedItems] + updatedItems[index] = !updatedItems[index] + setCheckedItems(updatedItems) + setAllChecked(updatedItems.every(Boolean)) + } + + const handleAllCheckClick = () => { + const newState = !allChecked + setAllChecked(newState) + setCheckedItems(checkedItems.map(() => newState)) + } + + const submitConsentInfoHandler = async () => { + const accessToken = sessionStorage.getItem('accessToken') || '' + + const data: ConsentInfo = { + isServiceUseAgree: checkedItems[0], + isPrivateInformAgree: checkedItems[1], + isAgeCheck: checkedItems[2], + isMarketingAgree: checkedItems[3], + } + + const result = await submitConsentInfo(data, accessToken) + + if (result) { + setAccessToken(accessToken) // Recoil 상태에 액세스 토큰 저장 + router.push('/login/onboarding-complete') // 온보딩 완료 페이지로 이동 + } + } + + return { + allChecked, + checkedItems, + isNextEnabled, + handleCheckClick, + handleAllCheckClick, + submitConsentInfoHandler, + } +} diff --git a/src/features/onBoarding/types/memberTypes.ts b/src/features/onBoarding/types/memberTypes.ts index 997cd428..f493efc5 100644 --- a/src/features/onBoarding/types/memberTypes.ts +++ b/src/features/onBoarding/types/memberTypes.ts @@ -2,3 +2,17 @@ export interface MemberInfo { memberName: string contact: string } + +// src/features/member/types/memberTypes.ts + +export interface ConsentInfo { + isServiceUseAgree: boolean + isPrivateInformAgree: boolean + isAgeCheck: boolean + isMarketingAgree: boolean +} + +export interface ConsentRequest { + data: ConsentInfo + accessToken: string +}