Skip to content

Commit

Permalink
Merge pull request #20 from NewMillenniumWorkout/dev/CalendarPage
Browse files Browse the repository at this point in the history
[DEV] CalendarPage 감정 라벨 추가 및 UI 개선
  • Loading branch information
LUCETE012 authored Dec 5, 2024
2 parents faf6063 + 673d762 commit 7913e7c
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 31 deletions.
126 changes: 116 additions & 10 deletions src/components/Calendar/CalendarPage.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import React, { useEffect, useState } from "react";
import React, { useEffect, useState, useRef } from "react";
import { WeeklyCalendar } from "./WeeklyCalendar";
import Card from "./Card";
import { API_CALENDAR } from "../../api/calendar";
import { formatToYYYYMM, formatToYYYYMMDD } from "../../utils/TimeFormatter";
import { FinalDiary } from "../../api/diary";
import { getEmotionColor } from "../../utils/GetEmotionColor";

const CalendarPage: React.FC = () => {
const [date, setDate] = useState<Date | undefined>(
new Date(new Date().getTime() - 9 * 60 * 60 * 1000)
);
const [date, setDate] = useState<Date | undefined>(new Date());
const [diaryDates, setDiaryDates] = useState<string[]>([]);
const [curDiary, setCurDiary] = useState<FinalDiary | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [isFlipped, setIsFlipped] = useState(false);
const [selectedEmotionId, setSelectedEmotionId] = useState<number | null>(
null
);

const containerRef = useRef<HTMLDivElement>(null);
const descriptionRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const loadInitialData = async () => {
if (!date) return;

const tempDate = new Date(date.getTime() - 9 * 60 * 60 * 1000);
try {
const formattedMonth = formatToYYYYMM(date);
const formattedMonth = formatToYYYYMM(tempDate);
const monthResponse = await API_CALENDAR.getMonthDiary(
formattedMonth
);
Expand All @@ -28,7 +34,7 @@ const CalendarPage: React.FC = () => {
);
setDiaryDates(diaryDates);

const formattedDate = formatToYYYYMMDD(date);
const formattedDate = formatToYYYYMMDD(tempDate);
if (diaryDates.includes(formattedDate)) {
const dateResponse = await API_CALENDAR.getDateDiary(
formattedDate
Expand All @@ -49,8 +55,9 @@ const CalendarPage: React.FC = () => {
useEffect(() => {
const loadDateDiary = async () => {
if (!date) return;
const tempDate = new Date(date.getTime() - 9 * 60 * 60 * 1000);

const formattedDate = formatToYYYYMMDD(date);
const formattedDate = formatToYYYYMMDD(tempDate);
if (!diaryDates.includes(formattedDate)) {
if (curDiary != null) setCurDiary(null);
return;
Expand All @@ -69,6 +76,43 @@ const CalendarPage: React.FC = () => {
}
}, [date, diaryDates]);

useEffect(() => {
if (containerRef.current) {
containerRef.current.scrollTo({
top: 0,
behavior: "smooth",
});
}
setSelectedEmotionId(null);
}, [date]);

useEffect(() => {
setSelectedEmotionId(null);
}, [isFlipped]);

useEffect(() => {
if (
selectedEmotionId !== null &&
descriptionRef.current &&
containerRef.current
) {
const descriptionPosition = descriptionRef.current.offsetTop;
const containerScrollPosition = containerRef.current.scrollTop;

const extraScroll = 50;

containerRef.current.scrollTo({
top:
descriptionPosition - containerScrollPosition + extraScroll,
behavior: "smooth",
});
}
}, [selectedEmotionId]);

const handleEmotionClick = (id: number) => {
setSelectedEmotionId((prevId) => (prevId === id ? null : id));
};

return (
<div className="flex flex-col w-full h-full bg-white-aneuk">
<div className="flex-shrink-0 w-full px-4 pt-4 pb-6 z-20 rounded-b-xl bg-white shadow-md">
Expand All @@ -80,8 +124,70 @@ const CalendarPage: React.FC = () => {
diaryDates={diaryDates}
/>
</div>
<div className="flex flex-col flex-grow justify-start items-center bg-white-aneuk overflow-y-auto">
{!isLoading && <Card curDiary={curDiary} />}
<div
ref={containerRef}
className="flex flex-col flex-grow justify-start items-center bg-white-aneuk pb-24 overflow-y-auto"
>
{!isLoading && (
<Card
curDiary={curDiary}
isFlipped={isFlipped}
setIsFlipped={setIsFlipped}
/>
)}
{isFlipped && (
<div className="flex flex-row flex-wrap justify-start items-start px-11 pt-6 w-full duration-500 ease-in-out animate-slide-up">
{curDiary &&
curDiary.data.emotionList.map((emotion) => {
const isSelected =
selectedEmotionId === emotion.id;
return (
<div
key={emotion.id}
className={`flex flex-col justify-start items-start ${
isSelected && "w-full"
}`}
>
<div
onClick={() =>
handleEmotionClick(emotion.id)
}
className={`flex flex-row space-x-2 mr-2 mb-2 justify-start items-center py-0.5 pl-1 pr-2.5 bg-white text-black-aneuk border rounded-full cursor-pointer ${
isSelected
? "font-gowun-bold shadow-custom-strong h-12 text-2xl"
: "font-gowun-regular text-xl"
} transition-all duration-300 ease-in-out`}
>
<div
className={`${getEmotionColor(
emotion.category
)} rounded-full ${
isSelected
? "w-9 h-9"
: "w-6 h-6"
}`}
/>
<div>{emotion.title}</div>
</div>

{isSelected && (
<div
ref={descriptionRef}
className="flex flex-col justify-center items-center w-full mt-2 mb-4 text-black-aneuk"
>
<div className="font-pretendard-regular text-lg text-black-aneuk mb-2 text-center">
{emotion.description}
</div>
<div className="font-pretendard text-base text-zinc-400 text-center">
"{emotion.example}"
</div>
</div>
)}
</div>
);
})}
</div>
)}
</div>
</div>
);
Expand Down
32 changes: 26 additions & 6 deletions src/components/Calendar/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { FinalDiary } from "../../api/diary";
import { format } from "date-fns";
import { ko } from "date-fns/locale";
import sampleImg from "/Users/minsik/Documents/Projects/A-Neuk-FE/src/assets/images/odocat.png";
import { getEmotionColor } from "../../utils/GetEmotionColor";

interface CardProps {
curDiary: FinalDiary | null;
isFlipped: boolean;
setIsFlipped: React.Dispatch<React.SetStateAction<boolean>>;
}

const Card: React.FC<CardProps> = ({ curDiary }) => {
const [isFlipped, setIsFlipped] = useState(false);

const Card: React.FC<CardProps> = ({ curDiary, isFlipped, setIsFlipped }) => {
const handleCardClick = () => {
setIsFlipped(!isFlipped);
};

useEffect(() => {
setIsFlipped(false);
}, [curDiary]);

const categories = curDiary?.data.emotionList.map(
(emotion) => emotion.category
);
const uniqueCategories = categories
? categories.filter(
(value, index, self) => self.indexOf(value) === index
)
: [];

if (curDiary === null) {
return (
<div className="flex flex-1 justify-center items-center">
Expand Down Expand Up @@ -43,8 +57,14 @@ const Card: React.FC<CardProps> = ({ curDiary }) => {
className="flex flex-col justify-center items-center w-[100%] h-[80%] rounded-[24px] object-cover"
/>
<div className="flex flex-row flex-1 justify-start items-start p-2 space-x-2">
<div className="aspect-square w-[8%] rounded-full bg-green-500" />
<div className="aspect-square w-[8%] rounded-full bg-blue-500" />
{uniqueCategories.map((category, index) => (
<div
key={index}
className={`aspect-square w-6 rounded-full ${getEmotionColor(
category
)}`}
/>
))}
</div>
</div>
<div
Expand Down
13 changes: 10 additions & 3 deletions src/components/Chat/ChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ const ChatPage: React.FC = () => {
setIsGenAble,
isGenStart,
setIsGenStart,
isSlide,
isGenComplete,
setIsGenComplete,
isEmotionSelectAble,
setIsEmotionSelectAble,
addMessage,
isLoading,
setIsLoading,
userImage,
} = useChatPage();
Expand All @@ -50,10 +50,9 @@ const ChatPage: React.FC = () => {
if (curChatId !== null) {
const emotionData = await API_DIARY.getEmotions(curChatId);
setEmotionData(emotionData);
console.log("gen complete");
}
} catch (error) {
console.log("Error gen");
console.error("Error get emotions: ", error);
}
setIsGenComplete(true);
};
Expand Down Expand Up @@ -139,6 +138,14 @@ const ChatPage: React.FC = () => {
}
}, [isEmotionSelectAble]);

useEffect(() => {
if (userImage && isGenComplete && isSlide) {
setIsEmotionSelectAble(true);
} else {
setIsEmotionSelectAble(false);
}
}, [userImage, isGenComplete, isSlide]);

return (
<div className="absolute inset-0 bg-white flex flex-col overflow-hidden">
<TopAppBar />
Expand Down
13 changes: 5 additions & 8 deletions src/components/Chat/ChatPageContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ interface ChatPageContextType {
setIsGenAble: React.Dispatch<React.SetStateAction<boolean>>;
isGenStart: boolean;
setIsGenStart: React.Dispatch<React.SetStateAction<boolean>>;
isSlide: boolean;
setIsSlide: React.Dispatch<React.SetStateAction<boolean>>;
isGenComplete: boolean;
setIsGenComplete: React.Dispatch<React.SetStateAction<boolean>>;
isEmotionSelectAble: boolean;
Expand Down Expand Up @@ -57,6 +59,7 @@ export const ChatPageProvider: React.FC<ChatPageProviderProps> = ({
const [isGenAble, setIsGenAble] = useState(false);
const [isGenStart, setIsGenStart] = useState(false);
const [isGenComplete, setIsGenComplete] = useState(false);
const [isSlide, setIsSlide] = useState(false);
const [isEmotionSelectAble, setIsEmotionSelectAble] = useState(false);
const [userImage, setUserImage] = useState<File | null>(null);
const [isLoading, setIsLoading] = useState(false);
Expand Down Expand Up @@ -87,14 +90,6 @@ export const ChatPageProvider: React.FC<ChatPageProviderProps> = ({
}
};

useEffect(() => {
if (userImage && isGenComplete) {
setIsEmotionSelectAble(true);
} else {
setIsEmotionSelectAble(false);
}
}, [userImage, isGenComplete]);

return (
<ChatPageContext.Provider
value={{
Expand All @@ -106,6 +101,8 @@ export const ChatPageProvider: React.FC<ChatPageProviderProps> = ({
setIsGenAble,
isGenStart,
setIsGenStart,
isSlide,
setIsSlide,
isGenComplete,
setIsGenComplete,
isEmotionSelectAble,
Expand Down
5 changes: 4 additions & 1 deletion src/components/Chat/SlideArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const SlideArea: React.FC = () => {
const sliderRef = useRef<HTMLDivElement>(null);
const [isDragging, setIsDragging] = useState(false);
const [sliderPos, setSliderPos] = useState(0);
const { curChatId, userImage, isLoading, setIsLoading } = useChatPage();
const { curChatId, userImage, setIsSlide, isLoading, setIsLoading } =
useChatPage();

const emojis = [
"🙂",
Expand Down Expand Up @@ -79,6 +80,8 @@ const SlideArea: React.FC = () => {
await API_CHAT.sendImage(curChatId!, userImage!);
} catch (error) {
console.error("Error sending image:", error);
} finally {
setIsSlide(true);
}
} else {
setSliderPos(0);
Expand Down
Loading

0 comments on commit 7913e7c

Please sign in to comment.