Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/epigram5-9/epigram into fix…
Browse files Browse the repository at this point in the history
…/FE-54
  • Loading branch information
jisurk committed Aug 5, 2024
2 parents 0576ea1 + 81a9b01 commit cffc327
Show file tree
Hide file tree
Showing 10 changed files with 389 additions and 99 deletions.
317 changes: 307 additions & 10 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"react-dom": "^18",
"react-hook-form": "^7.52.1",
"react-toastify": "^10.0.5",
"recharts": "^2.12.7",
"sharp": "^0.33.4",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
Expand Down
7 changes: 7 additions & 0 deletions src/apis/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,10 @@ httpClient.interceptors.response.use(
);

export default httpClient;

export const logout = () => {
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');

window.location.href = '/auth/SignIn';
};
8 changes: 4 additions & 4 deletions src/apis/postGoogleOauth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import httpClient from '.';
const getGoogleIdToken = async (code: string) => {
const response = await axios.post('https://oauth2.googleapis.com/token', {
code,
client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID_TEST,
client_secret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET_TEST,
redirect_uri: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_TEST,
client_id: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID,
client_secret: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_SECRET,
redirect_uri: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI,
grant_type: 'authorization_code',
});

Expand All @@ -19,7 +19,7 @@ const postGoogleOauth = async (code: string) => {
const idToken = tokenResponse.id_token;

const response = await httpClient.post('/auth/signIn/GOOGLE', {
redirectUri: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_TEST,
redirectUri: process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI,
token: idToken,
});

Expand Down
83 changes: 41 additions & 42 deletions src/components/mypage/Chart.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EmotionLog, EmotionTypeEN } from '@/types/emotion';
import { PieChart, Pie, Cell, ResponsiveContainer } from 'recharts';
import Image from 'next/image';
import { iconPaths } from '../../user/utill/constants';

Expand All @@ -22,52 +23,51 @@ export default function Chart({ monthlyEmotionLogs }: ChartProps) {
// 감정 종류 및 총 감정 수 계산
const TOTAL_COUNT = monthlyEmotionLogs.length;
const EMOTIONS: EmotionTypeEN[] = ['MOVED', 'HAPPY', 'WORRIED', 'SAD', 'ANGRY'];
const RADIUS = 90; // 원의 반지름
const CIRCUMFERENCE = 2 * Math.PI * RADIUS;

// 가장 많이 나타나는 감정 찾기
const maxEmotion = EMOTIONS.reduce((max, emotion) => (emotionCounts[emotion] > emotionCounts[max] ? emotion : max), EMOTIONS[0]);

// 원형 차트의 각 감정에 대한 strokeDasharray와 strokeDashoffset 계산
let offset = 0;
// 원형 차트 데이터 생성 및 정렬 (가장 많은 감정부터)
const chartData = EMOTIONS.map((emotion) => ({
name: emotion,
value: emotionCounts[emotion] || 0,
})).sort((a, b) => b.value - a.value);

// 감정 색상 설정
const COLORS = {
MOVED: '#48BB98',
HAPPY: '#FBC85B',
WORRIED: '#C7D1E0',
SAD: '#E3E9F1',
ANGRY: '#EFF3F8',
};

return (
<div className='flex flex-col w-full lg:max-w-[640px] md:max-w-[640px] mt-[160px] space-y-0 md:mb-10 mb-5 gap-[48px]'>
<h2 className='text-neutral-700 text-2xl font-semibold leading-loose'>감정 차트</h2>
<div className='flex justify-between items-center px-[112px]'>
<div className='w-[200px] h-[200px] relative'>
<svg viewBox='0 0 200 200'>
<circle cx='100' cy='100' r={RADIUS} fill='none' stroke='beige' strokeWidth='20' />
{EMOTIONS.map((emotion) => {
const count = emotionCounts[emotion] || 0;
const percentage = TOTAL_COUNT > 0 ? count / TOTAL_COUNT : 0; // 0으로 나누기 방지
const strokeDasharray = `${CIRCUMFERENCE * percentage} ${CIRCUMFERENCE * (1 - percentage)}`;

// 색상 설정
let strokeColor;
switch (emotion) {
case 'HAPPY':
strokeColor = '#FBC85B';
break;
case 'SAD':
strokeColor = '#E3E9F1';
break;
case 'WORRIED':
strokeColor = '#C7D1E0';
break;
case 'ANGRY':
strokeColor = '#EFF3F8';
break;
default:
strokeColor = '#48BB98';
}

const circle = <circle key={emotion} cx='100' cy='100' r={RADIUS} fill='none' stroke={strokeColor} strokeWidth='20' strokeDasharray={strokeDasharray} strokeDashoffset={offset} />;

offset += CIRCUMFERENCE * percentage; // 다음 원을 위한 offset 업데이트
return circle;
})}
</svg>
<ResponsiveContainer width='100%' height='100%'>
<PieChart>
<Pie
data={chartData}
dataKey='value'
cx='50%'
cy='50%'
outerRadius={90}
innerRadius={70} // 도넛 차트를 위해 innerRadius 설정
startAngle={90} // 12시 방향에서 시작
endAngle={-270} // 시계 방향으로 회전
fill='#8884d8'
>
{chartData.map((emotion, index) => (
// TODO: index 값 Lint error. 임시로 주석 사용. 추후 수정 예정
// eslint-disable-next-line react/no-array-index-key
<Cell key={`cell-${index}`} fill={COLORS[emotion.name]} />
))}
</Pie>
</PieChart>
</ResponsiveContainer>
{/* 중앙에 가장 많이 나타나는 감정 출력 */}
<div className='absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 flex flex-col items-center gap-3'>
<Image src={iconPaths[maxEmotion].path} alt='감정' width={40} height={40} />
Expand All @@ -76,14 +76,13 @@ export default function Chart({ monthlyEmotionLogs }: ChartProps) {
</div>
<div>
<div className='flex flex-col gap-4'>
{EMOTIONS.map((emotion) => {
const count = emotionCounts[emotion] || 0;
const percentage = TOTAL_COUNT > 0 ? Math.floor((count / TOTAL_COUNT) * 100) : 0; // 퍼센트 계산 및 소수점 버리기
{chartData.map((emotion) => {
const percentage = TOTAL_COUNT > 0 ? Math.floor((emotion.value / TOTAL_COUNT) * 100) : 0;

return (
<div key={emotion} className='flex items-center gap-3'>
<p className={`${iconPaths[emotion].color} w-[16px] h-[16px]`}></p>
<Image src={iconPaths[emotion].path} alt='감정' width={24} height={24} />
<div key={emotion.name} className='flex items-center gap-3'>
<div style={{ backgroundColor: COLORS[emotion.name], width: '16px', height: '16px' }}></div>
<Image src={iconPaths[emotion.name].path} alt='감정' width={24} height={24} />
<p>{percentage}%</p>
</div>
);
Expand Down
27 changes: 11 additions & 16 deletions src/pages/auth/SignIn.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import Image from 'next/image';
import Link from 'next/link';
import { Input } from '@/components/ui/input';
Expand All @@ -7,12 +9,18 @@ import { zodResolver } from '@hookform/resolvers/zod';
import { Form, FormControl, FormField, FormItem, FormMessage } from '@/components/ui/form';
import { PostSigninRequest, PostSigninRequestType } from '@/schema/auth';
import useSigninMutation from '@/hooks/useSignInMutation';
import { useRouter } from 'next/router';

export default function SignIn() {
const mutationSignin = useSigninMutation();
const router = useRouter();

useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
if (accessToken) {
router.push('/epigrams');
}
}, [router]);

// 폼 정의
const form = useForm<PostSigninRequestType>({
resolver: zodResolver(PostSigninRequest),
Expand All @@ -27,19 +35,6 @@ export default function SignIn() {
form.setValue(fieldName, value.trim(), { shouldValidate: true, shouldDirty: true });
};

const handleSubmit = async (values: PostSigninRequestType) => {
try {
const result = await mutationSignin.mutateAsync(values);
localStorage.setItem('accessToken', result.accessToken);
localStorage.setItem('refreshToken', result.refreshToken);
router.push('/epigrams'); // 로그인 성공 후 이동할 페이지
} catch (error) {
// 로그인 실패 처리
/* eslint-disable no-console */
console.error('로그인 실패:', error);
}
};

return (
<div className='flex flex-col justify-center items-center bg-background-100 w-full h-screen'>
<header className='mb-[50px] md:mb-[60px]'>
Expand All @@ -48,7 +43,7 @@ export default function SignIn() {
</Link>
</header>
<Form {...form}>
<form onSubmit={form.handleSubmit(handleSubmit)} className='flex flex-col items-center lg:gap-6 gap-5 w-full px-6'>
<form onSubmit={form.handleSubmit((values: PostSigninRequestType) => mutationSignin.mutate(values))} className='flex flex-col items-center lg:gap-6 gap-5 w-full px-6'>
<div className='flex flex-col items-center lg:gap-4 gap-[10px] w-full lg:max-w-[640px] md:max-w-[384px]'>
<FormField
control={form.control}
Expand Down Expand Up @@ -125,7 +120,7 @@ export default function SignIn() {
<Image src='/logo-naver.svg' alt='logo-naver' width={60} height={60} className='md:size-[60px] size-10' />
</Link>
<Link
href={`https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID_TEST}&redirect_uri=${process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI_TEST}&response_type=code&scope=openid%20profile%20email`}
href={`https://accounts.google.com/o/oauth2/v2/auth?client_id=${process.env.NEXT_PUBLIC_GOOGLE_CLIENT_ID}&redirect_uri=${process.env.NEXT_PUBLIC_GOOGLE_REDIRECT_URI}&response_type=code&scope=openid%20profile%20email`}
>
<Image src='/logo-google.svg' alt='logo-google' width={60} height={60} className='md:size-[60px] size-10' />
</Link>
Expand Down
11 changes: 10 additions & 1 deletion src/pages/auth/SignUp.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import Image from 'next/image';
import Link from 'next/link';
import { zodResolver } from '@hookform/resolvers/zod';
Expand All @@ -11,6 +12,14 @@ import useRegisterMutation from '@/hooks/useRegisterMutation';

export default function SignUp() {
const [focusedField, setFocusedField] = useState<string | null>(null);
const router = useRouter();

useEffect(() => {
const accessToken = localStorage.getItem('accessToken');
if (accessToken) {
router.push('/epigrams');
}
}, [router]);

const form = useForm<PostSignUpRequestType>({
resolver: zodResolver(PostSignUpRequest),
Expand Down
8 changes: 3 additions & 5 deletions src/pages/auth/callback/google/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
import useGoogleLogin from '@/hooks/useGoogleLogin'; // useGoogleLogin 훅을 가져옵니다
import useGoogleLogin from '@/hooks/useGoogleLogin';

export default function Google() {
const searchParams = useSearchParams();
const code = searchParams.get('code'); // URL에서 'code' 값을 가져옵니다
const { mutate: login } = useGoogleLogin(); // useGoogleLogin 훅에서 mutate 함수를 가져옵니다
const code = searchParams.get('code');
const { mutate: login } = useGoogleLogin();

useEffect(() => {
if (code) {
Expand All @@ -15,6 +15,4 @@ export default function Google() {
console.log('No code found in URL parameters'); // code가 없을 때 콘솔에 출력
}
}, [code, login]);

return null; // 컴포넌트가 UI를 렌더링하지 않음
}
21 changes: 0 additions & 21 deletions src/pages/auth/redirect/google-callback/index.ts

This file was deleted.

5 changes: 5 additions & 0 deletions src/pages/mypage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import MyPageLayout from '@/pageLayout/MypageLayout/MyPageLayout';

export default function mypage() {
return <MyPageLayout />;
}

0 comments on commit cffc327

Please sign in to comment.