Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FE-84 ♻️ 마이페이지 감정 달력 코드 리팩토링 #192

Merged
merged 7 commits into from
Aug 4, 2024
12 changes: 10 additions & 2 deletions src/components/main/TodayEmotion.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React, { useState } from 'react';
import { useEmotionContext } from '@/context/EmotionContext';
import EmotionSelector from '../Emotion/EmotionSelector';

function TodayEmotion() {
interface TodayEmotionProps {
isMyPage?: boolean;
}

function TodayEmotion({ isMyPage = false }: TodayEmotionProps) {
const [isVisible, setIsVisible] = useState<boolean>(true);
// NOTE: 오늘의 감정 선택 시 감정 달력 및 감정 차트 동기화를 위한 context 추가
const { setShouldRefetch } = useEmotionContext();

const handleEmotionSaved = () => {
setIsVisible(false);
if (isMyPage) setShouldRefetch(true);
else setIsVisible(false);
};

if (!isVisible) return null;
Expand Down
18 changes: 14 additions & 4 deletions src/components/mypage/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import Image from 'next/image';
import { subMonths } from 'date-fns';
import { subMonths, isSameMonth, isSameDay } from 'date-fns';
import { EmotionLog, EmotionTypeEN } from '@/types/emotion';
import useCalendar from '../../hooks/useCalendar';
import { DAY_LIST, DATE_MONTH_FIXER, iconPaths } from '../../user/utill/constants';
Expand Down Expand Up @@ -64,12 +64,22 @@ export default function Calendar({ currentDate, setCurrentDate, monthlyEmotionLo
// eslint-disable-next-line react/no-array-index-key
<div key={weekIndex} className='flex'>
{week.map((day, dayIndex) => {
// 현재 날짜와 비교
const isToday = day === currentDate.getDate() && currentDate.getMonth() === new Date().getMonth() && currentDate.getFullYear() === new Date().getFullYear();
const date = new Date(currentDate.getFullYear(), currentDate.getMonth(), day);
const dateString = `${currentDate.getFullYear()}-${String(currentDate.getMonth() + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
const emotion: EmotionTypeEN = filteredEmotionMap[dateString]; // 날짜에 해당하는 감정 가져오기

// 현재 월의 날짜인지 확인
const isDateInCurrentMonth = isSameMonth(date, currentDate);

// 첫 주에 7보다 큰 날짜 또는 마지막 주에 7보다 작은 날짜는 감정 출력하지 않음
const isFirstWeek = weekIndex === 0 && day > 7;
const isLastWeek = weekIndex === weekCalendarList.length - 1 && day < 7;

const emotion = isDateInCurrentMonth && !isFirstWeek && !isLastWeek ? filteredEmotionMap[dateString] : undefined;
const iconPath = emotion && iconPaths[emotion] ? iconPaths[emotion].path : '/icon/BW/SmileFaceBWIcon.svg';

// 오늘 날짜 체크
const isToday = isSameDay(date, new Date());

return (
<div
// TODO: index 값 Lint error. 임시로 주석 사용. 추후 수정 예정
Expand Down
5 changes: 4 additions & 1 deletion src/components/mypage/CalendarHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,17 @@ interface CalendarHeaderProps {
}

export default function CalendarHeader({ currentDate, onPrevMonth, onNextMonth, onEmotionSelect, selectEmotion }: CalendarHeaderProps) {
// 드롭다운 버튼 텍스트 설정
const filterText = selectEmotion ? `필터: ${iconPaths[selectEmotion]?.name}` : '필터: 없음';

return (
<div className='w-full flex justify-between items-center'>
<div className='flex w-full h-[52px] justify-between items-center'>
<div className='text-neutral-700 text-2xl font-semibold leading-loose'>{`${currentDate.getFullYear()}년 ${currentDate.getMonth() + 1}월`}</div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant='outline' className='flex items-center gap-1 bg-slate-100 rounded-[14px] text-center text-stone-300 text-xl'>
필터: 감동
{filterText}
<div className='w-9 h-9 relative'>
<Image src={ARROW_BOTTOM_ICON} alt='필터 선택' width={36} height={36} />
</div>
Expand Down
23 changes: 23 additions & 0 deletions src/context/EmotionContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createContext, useState, useContext, ReactNode, useMemo } from 'react';

interface EmotionContextType {
shouldRefetch: boolean;
setShouldRefetch: (value: boolean) => void;
}

const EmotionContext = createContext<EmotionContextType>({
shouldRefetch: false,
setShouldRefetch: () => {},
});

export function EmotionProvider({ children }: { children: ReactNode }) {
const [shouldRefetch, setShouldRefetch] = useState(false);

const value = useMemo(() => ({ shouldRefetch, setShouldRefetch }), [shouldRefetch]);

return <EmotionContext.Provider value={value}>{children}</EmotionContext.Provider>;
}

export function useEmotionContext() {
return useContext(EmotionContext);
}
7 changes: 6 additions & 1 deletion src/hooks/useGetEmotion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@ import { EmotionType } from '@/types/emotion';
import { GetMonthlyEmotionLogsRequestType } from '@/schema/emotion';
import { useQuery } from '@tanstack/react-query';

export const useMonthlyEmotionLogs = (requset: GetMonthlyEmotionLogsRequestType) => useQuery(quries.emotion.getMonthlyEmotionLogs(requset));
export const useMonthlyEmotionLogs = (request: GetMonthlyEmotionLogsRequestType) =>
useQuery({
...quries.emotion.getMonthlyEmotionLogs(request),
refetchOnWindowFocus: false,
enabled: !!request,
});

export const useGetEmotion = () =>
useQuery<EmotionType | null, Error>({
Expand Down
16 changes: 15 additions & 1 deletion src/pageLayout/MypageLayout/EmotionMonthlyLogs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useMonthlyEmotionLogs } from '@/hooks/useGetEmotion';
import { Emotion } from '@/types/emotion';
import { useEffect, useState } from 'react';
import { useEmotionContext } from '@/context/EmotionContext';
import Calendar from '../../components/mypage/Calendar';
import Chart from '../../components/mypage/Chart';

Expand All @@ -12,6 +13,9 @@ export default function EmotionMonthlyLogs({ userId }: EmotionMonthlyLogsProps)
// 현재 날짜를 상태로 관리
const [currentDate, setCurrentDate] = useState<Date>(new Date());

// NOTE: 오늘의 감정 선택 시 감정 달력 및 감정 차트 동기화를 위한 context 추가
const { shouldRefetch, setShouldRefetch } = useEmotionContext();

// 감정 달력 객체 상태 추가
const [emotionRequest, setEmotionRequest] = useState<Emotion>({
userId,
Expand All @@ -29,7 +33,17 @@ export default function EmotionMonthlyLogs({ userId }: EmotionMonthlyLogsProps)
}, [currentDate]);

// 월별 감정 로그 조회
const { data: monthlyEmotionLogs = [] } = useMonthlyEmotionLogs(emotionRequest);
const { data: monthlyEmotionLogs = [], refetch } = useMonthlyEmotionLogs(emotionRequest);

useEffect(() => {
if (shouldRefetch) {
// 데이터 다시 조회 로직
refetch();

// 다시 조회 후 shouldRefetch를 false로 설정
setShouldRefetch(false);
}
}, [shouldRefetch, refetch, setShouldRefetch]);

return (
<div className='pb-[110px]'>
Expand Down
27 changes: 15 additions & 12 deletions src/pageLayout/MypageLayout/MyPageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import EmotionMonthlyLogs from '@/pageLayout/MypageLayout/EmotionMonthlyLogs';
import Profile from '@/components/mypage/Profile';
import { useRouter } from 'next/navigation';
import TodayEmotion from '@/components/main/TodayEmotion';
import { EmotionProvider } from '@/context/EmotionContext';
import MyContent from './MyContent';

export default function MyPageLayout() {
Expand All @@ -27,19 +28,21 @@ export default function MyPageLayout() {
}

return (
<div className='bg-background-100 w-full relative h-dvh'>
<NewHeader />
<div className='bg-background-100 w-full h-[200px]'></div>
<div className='w-full flex flex-col items-center bg-blue-100 rounded-3xl relative shadow-3xl'>
<Profile image={data.image} nickname={data.nickname} />
<div className='mt-[300px]'>
<TodayEmotion />
<EmotionProvider>
<div className='bg-background-100 w-full relative h-dvh'>
<NewHeader />
<div className='bg-background-100 w-full h-[200px]'></div>
<div className='w-full flex flex-col items-center bg-blue-100 rounded-3xl relative shadow-3xl'>
<Profile image={data.image} nickname={data.nickname} />
<div className='mt-[300px]'>
<TodayEmotion isMyPage />
</div>
<EmotionMonthlyLogs userId={data.id} />
</div>
<div className='bg-background-100 flex flex-col items-center w-full py-[100px]'>
<MyContent user={data} />
</div>
<EmotionMonthlyLogs userId={data.id} />
</div>
<div className='bg-background-100 flex flex-col items-center w-full py-[100px]'>
<MyContent user={data} />
</div>
</div>
</EmotionProvider>
);
}
Loading