Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/features/Redirection/Redirection.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
'use client';

import React, { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useRouter, useSearchParams } from 'next/navigation';

const Redirection = () => {
const router = useRouter();
const searchParams = useSearchParams();

// 쿠키 기반 로그인 상태 확인
useEffect(() => {
const accessToken = searchParams.get('accessToken');

if (accessToken) {
// accessToken 로컬스토리지에 저장
localStorage.setItem('accessToken', accessToken);
console.log('accessToken 저장 완료:', accessToken);
} else {
console.warn('accessToken 없음, 홈으로 이동');
router.replace('/');
return;
}

const checkLoginStatus = async () => {
try {
const res = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}auth/status`,
{
credentials: 'include',
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

const data = await res.json();
console.log('로그인 상태 응답:', data);

if (data.isLoggedIn) {
if (data.code === 200) {
router.replace('/match-usercode');
} else {
console.log('로그인 실패 → 홈으로 이동');
console.log('로그인 실패 → 홈으로');
router.replace('/');
}
} catch (err) {
Expand All @@ -33,7 +48,7 @@ const Redirection = () => {
};

checkLoginStatus();
}, [router]);
}, [router, searchParams]);

return (
<div className='flex h-screen items-center justify-center text-xl text-white'>
Expand Down
4 changes: 2 additions & 2 deletions src/features/components/LoginButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import React from 'react';

const LoginButton = () => {
const KAKAO_AUTH_URL = `${process.env.NEXT_PUBLIC_KAKAO_AUTH_URL}`;

const redirectUrl = encodeURIComponent('http://localhost:3000/Redirection');
const KAKAO_AUTH_URL = `${process.env.NEXT_PUBLIC_KAKAO_AUTH_URL}?redirectUrl=${redirectUrl}`;
const loginHandler = () => {
window.location.href = KAKAO_AUTH_URL;
};
Expand Down
63 changes: 57 additions & 6 deletions src/features/match-usercode/MatchUserCode.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,64 @@
'use client';

import { Button } from '@/components/atoms/button/Button';
import TextInput from '@/components/atoms/textInput/TextInput';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/navigation';
import Cookies from 'js-cookie';
import { TopBar } from '@/components/molecules/topBar/TopBar';

export default function MatchUserCode() {
const [inputValue, setInputValue] = useState<string>('');
const [userCode, setUserCode] = useState<string>('무서운츄러스145');
const [userCode, setUserCode] = useState<string>('');
const router = useRouter();

const handleInput = (value: string) => {
setInputValue(value);
};

const handleConnect = () => {
if (inputValue === '무서운츄러스145') router.push('/sign-nickname');
if (inputValue === userCode) router.push('/sign-nickname');
};

const getAccessToken = () => {
if (process.env.NODE_ENV === 'development') {
// 개발 환경에서는 localStorage
return localStorage.getItem('accessToken');
} else {
// 배포 환경에서는 쿠키에서 읽기
return Cookies.get('accessToken');
}
};

// 쿠키 기반 로그인 상태 확인
// 쿠키 기반 로그인 상태 확인 및 유저 코드 요청
useEffect(() => {
const accessToken = getAccessToken();

if (!accessToken) {
console.warn('Access token이 없습니다. 홈으로 이동합니다.');
router.replace('/');
return;
}

const checkLoginStatus = async () => {
try {
const res = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}auth/status`,
{
credentials: 'include',
headers: {
Authorization: `Bearer ${accessToken}`,
},
},
);

const data = await res.json();
const isValid = data.code;

console.log('로그인 상태 응답:', data);

if (data.isLoggedIn) {
router.replace('/match-usercode');
if (isValid === 200) {
fetchMatchCode(accessToken);
} else {
console.log('로그인 실패 → 홈으로 이동');
router.replace('/');
Expand All @@ -44,6 +69,32 @@ export default function MatchUserCode() {
}
};

const fetchMatchCode = async (token: string) => {
try {
const res = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}api/couple/match-code`,
{
credentials: 'include',
headers: {
Authorization: `Bearer ${token}`,
},
},
);

const data = await res.json();
const isValid = data.code;
console.log('매치 코드 응답:', data);

if (isValid === 200 && data.data?.matchCode) {
setUserCode(data.data.matchCode);
} else {
console.warn('매치 코드 응답 실패');
}
} catch (err) {
console.error('매치 코드 불러오기 실패:', err);
}
};

checkLoginStatus();
}, [router]);

Expand Down Expand Up @@ -71,7 +122,7 @@ export default function MatchUserCode() {
<div className='mb-6 w-full max-w-[350px] rounded-lg bg-gray-100 p-5 text-center font-medium'>
<p className='mb-1 text-sm text-gray-400'>내 코드</p>
<p className='text-lg text-primary-500 underline decoration-primary-500'>
{userCode}
{userCode || '코드 불러오는 중...'}
</p>
</div>

Expand Down
89 changes: 85 additions & 4 deletions src/features/sign-nickname/SignNickName.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,64 @@ import { Button } from '@/components/atoms/button/Button';
import TextInput from '@/components/atoms/textInput/TextInput';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import Cookies from 'js-cookie';
import { TopBar } from '@/components/molecules/topBar/TopBar';

export default function SignNickName() {
const [inputValue, setInputValue] = useState<string>('');
const [gender, setGender] = useState<string>('');
const router = useRouter();

const handleInput = (value: string) => {
setInputValue(value);
};

const handleConnect = () => {
if (inputValue.length > 0) router.push(`/home/${inputValue}`);
const getAccessToken = () => {
return process.env.NODE_ENV === 'development'
? localStorage.getItem('accessToken')
: Cookies.get('accessToken');
};

const handleConnect = async () => {
if (inputValue.length === 0 || gender === '') return;

const accessToken = getAccessToken();
if (!accessToken) {
console.warn('Access token이 없습니다. 다시 로그인해주세요.');
router.push('/');
return;
}

const mappedGender = gender === 'male' ? 'GROOM' : 'BRIDE';

// try {
const res = await fetch(
`${process.env.NEXT_PUBLIC_BACKEND_URL}api/couple`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
credentials: 'include',
body: JSON.stringify({
gender: mappedGender,
nickName: inputValue,
}),
},
);

const result = await res.json();
console.log('result:', result);

// if (result.code !== 200) {
// throw new Error(`요청 실패: ${result.message}`);
// }

router.push(`/home/${inputValue}`);
// } catch (error) {
// console.error('요청 중 오류 발생:', error);
// }
};

return (
Expand All @@ -28,6 +74,7 @@ export default function SignNickName() {
router.push('/match-usercode');
}}
/>

<div className='mx-auto flex w-full min-w-[360px] max-w-[430px] grow flex-col items-center bg-gray-50 px-6 py-10'>
<div className='mb-6 w-full text-left'>
<h2 className='text-lg font-semibold text-primary-500'>연결 완료!</h2>
Expand All @@ -47,15 +94,49 @@ export default function SignNickName() {
maxLength={2}
/>
</div>

<div className='mt-6 w-full max-w-[350px]'>
<div className='flex justify-between gap-4'>
{[
{ value: 'male', label: '남자' },
{ value: 'female', label: '여자' },
].map(({ value, label }) => {
const isSelected = gender === value;

return (
<label
key={value}
className={`flex-1 cursor-pointer rounded-full px-4 py-2 text-center font-semibold transition-all duration-150 ${
isSelected
? 'bg-primary-500 text-black'
: 'bg-black text-white'
} border-none`}
>
<input
type='radio'
name='gender'
value={value}
checked={isSelected}
onChange={(e) => setGender(e.target.value)}
className='hidden'
/>
{label}
</label>
);
})}
</div>
</div>
</div>

<div className='absolute bottom-10 left-0 flex w-full justify-center px-6'>
<Button
className='w-full max-w-[350px] rounded-lg py-3 text-lg text-white'
variant={inputValue.length > 0 ? 'primary_fill' : 'gray_fill'}
variant={
inputValue.length > 0 && gender ? 'primary_fill' : 'gray_fill'
}
rounded='lg'
onClick={handleConnect}
disabled={inputValue.length === 0}
disabled={inputValue.length === 0 || gender === ''}
>
연결하기
</Button>
Expand Down