Skip to content

Commit

Permalink
feat: 조각 별 상세 정보 구현 완료 (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
nebulaBdj authored Nov 27, 2024
1 parent 13c63d0 commit 7bb1ed7
Show file tree
Hide file tree
Showing 3 changed files with 255 additions and 106 deletions.
81 changes: 81 additions & 0 deletions src/app/archive/components/OverviewHeaderForDetail.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Button, IconLeft, IconRight } from '@/components'
import Modal from '@/components/common/Modal'
import MonthSelect from '@/components/ui/MonthSelect'
import { format } from 'date-fns'
import { useEffect, useState } from 'react'
import { useMonthTotalCount } from '@/store/monthCount'

interface OverviewHeaderProps {
currentDate: Date
setCurrentDate: (date: Date) => void
goToPreviousMonth: () => void
goToNextMonth: () => void
}

export default function OverviewHeaderForDetail({
currentDate,
setCurrentDate,
goToPreviousMonth,
goToNextMonth,
}: OverviewHeaderProps) {
const [isModalOpen, setIsModalOpen] = useState(false)
const { monthCount } = useMonthTotalCount()
const today = new Date()

const canMoveToNextMonth =
currentDate.getFullYear() < today.getFullYear() ||
(currentDate.getFullYear() === today.getFullYear() &&
currentDate.getMonth() < today.getMonth())

useEffect(() => {
setIsModalOpen(false)
}, [currentDate])

return (
<>
<header className="flex flex-row justify-between px-35">
<div className="flex gap-15 items-center">
<Button
onClick={goToPreviousMonth}
className="bg-primary_foundation-5 w-24 h-24 rounded-8"
>
<IconLeft height={13} />
</Button>
<button
type="button"
onClick={() => setIsModalOpen(true)}
className="text-18 font-[500] underline underline-offset-4"
>
{format(currentDate, 'yyyy년 MM월')}
</button>
<Button
onClick={goToNextMonth}
className="bg-primary_foundation-5 w-24 h-24 rounded-8"
disabled={!canMoveToNextMonth}
>
<IconRight
height={13}
color={!canMoveToNextMonth ? '#D1D1D3' : ''}
/>
</Button>
</div>

<span className="text-primary_foundation-60">
{monthCount}개의 조각
</span>
</header>

<Modal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="월 선택하기"
className="max-h-350 overflow-auto"
>
<MonthSelect
currentDate={currentDate}
setCurrentDate={setCurrentDate}
/>
</Modal>
</>
)
}
266 changes: 160 additions & 106 deletions src/app/archive/keyword-detail/page.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,177 @@
'use client'

import { useRouter } from 'next/navigation'
// import { useEffect, useState } from 'react'
// import { format, parseISO } from 'date-fns'
// import { ko } from 'date-fns/locale'
// import Cookies from 'js-cookie'
import { IconLeft } from '@/components'
// import { KeywordMonthDataResponse, MonthActivity } from './types/type'
// import { transKeyword } from '../components/Treemap/Treemap'
import { useRouter, useSearchParams } from 'next/navigation'
import Image from 'next/image'
import { useEffect, useState } from 'react'
import { format, getMonth, getYear, parseISO } from 'date-fns'
import { ko } from 'date-fns/locale'
import Cookies from 'js-cookie'
import { IconLeft, Clock } from '@/components'
import useUserInfo from '@/store/useUserInfo'
import { useMonthTotalCount } from '@/store/monthCount'
import { KeywordMonthDataResponse, MonthActivity } from './types/type'
import { transKeyword } from '../components/Treemap/Treemap'
import OverviewHeaderForDetail from '../components/OverviewHeaderForDetail'

export default function KeywordDetailPage() {
// const searchParams = useSearchParams()
const searchParams = useSearchParams()
const router = useRouter()
// const [accessToken, setAccessToken] = useState('')
// const [year, setYear] = useState(0)
// const [month, setMonth] = useState(0)
// const [keyword, setKeyword] = useState('')

// const [keywordData, setKeywordData] = useState<KeywordMonthDataResponse>()
// const [sortedDates, setSortedDates] = useState<string[]>()
// const [activitiesByDate, setActivitiesByDate] =
// useState<Record<string, MonthActivity[] | undefined>>()
// const [selectedDate, setSelectedDate] = useState<Date | undefined>()

// useEffect(() => {
// const token = Cookies.get('accessToken')
// if (token) {
// setAccessToken(token)
// }

// const queryYear = searchParams.get('year')
// const queryMonth = searchParams.get('month')
// const quertKeyword = searchParams.get('keyword')
// if (queryYear && queryMonth && quertKeyword) {
// const transYear = parseInt(queryYear, 10)
// const transMonth = parseInt(queryMonth, 10)

// setYear(transYear)
// setMonth(transMonth)
// setKeyword(quertKeyword)

// getMonthData(transYear, transMonth, quertKeyword)
// }
// }, [])

// const getMonthData = async (
// reqyear: number,
// reqmonth: number,
// reqkeyword: string,
// ) => {
// try {
// console.log('dddd', accessToken)
// const response = await fetch(
// `https://cnergy.p-e.kr/v1/activities?year=${reqyear}&month=${reqmonth}&keywordCategory=${reqkeyword}`,
// {
// method: 'GET',
// headers: {
// 'Content-Type': 'application/json',
// Authorization: `Bearer ${accessToken}`,
// },
// },
// )

// if (!response.ok) {
// throw new Error(`HTTP error! status: ${response.status}`)
// }

// const { data } = await response.json()
// console.log('받은 데이터', data)
// setKeywordData(data)
// } catch (error) {
// console.error('Error sending POST request:', error)
// }
// }

// useEffect(() => {
// const monthlyActivities = keywordData?.activities

// const filteredActivities = selectedDate
// ? monthlyActivities?.filter(
// (activity) =>
// format(parseISO(activity.dateOfActivity), 'yyyy-MM-dd') ===
// format(selectedDate, 'yyyy-MM-dd'),
// )
// : monthlyActivities

// const activitiesByDate =
// filteredActivities?.reduce(
// (acc, activity) => {
// const dateKey = format(
// parseISO(activity.dateOfActivity),
// 'yyyy-MM-dd',
// )
// if (!acc[dateKey]) {
// acc[dateKey] = []
// }
// acc[dateKey].push(activity)
// return acc
// },
// {} as Record<string, typeof monthlyActivities>,
// ) ?? {}

// const sortedDates = Object.keys(activitiesByDate)
// setActivitiesByDate(activitiesByDate)
// setSortedDates(sortedDates)
// }, [keywordData])
const { nickname } = useUserInfo().userInfo
const { setMonthCount } = useMonthTotalCount()

const [accessToken, setAccessToken] = useState('')
const [currentDate, setCurrentDate] = useState(new Date())
const [keyword, setKeyword] = useState('')
const [isInitialized, setIsInitialized] = useState(false)

const [keywordData, setKeywordData] = useState<KeywordMonthDataResponse>()
const [sortedDates, setSortedDates] = useState<string[]>()
const [activitiesByDate, setActivitiesByDate] =
useState<Record<string, MonthActivity[] | undefined>>()

useEffect(() => {
const token = Cookies.get('accessToken')

if (token) {
setAccessToken(token)
}

const queryYear = searchParams.get('year')
const queryMonth = searchParams.get('month')
const querytKeyword = searchParams.get('keyword')
if (queryYear && queryMonth && querytKeyword) {
const transYear = parseInt(queryYear, 10)
const transMonth = parseInt(queryMonth, 10)
const initialDate = new Date(transYear, transMonth - 1)

setCurrentDate(initialDate)
setKeyword(querytKeyword)

setIsInitialized(true)
}
}, [])

const getMonthData = async (
reqyear: number,
reqmonth: number,
reqkeyword: string,
) => {
try {
const response = await fetch(
`https://cnergy.p-e.kr/v1/activities?year=${reqyear}&month=${reqmonth}&keywordCategory=${reqkeyword}`,
{
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${accessToken}`,
},
},
)

if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}

const { data } = await response.json()

setMonthCount(data.totalActivityCountByKeywordInMonth)
setKeywordData(data)
} catch (error) {
console.error('Error sending POST request:', error)
}
}

useEffect(() => {
if (isInitialized) {
const year = getYear(currentDate)
const month = getMonth(currentDate) + 1
getMonthData(year, month, keyword)
}
}, [keyword, currentDate])

useEffect(() => {
const monthlyActivities = keywordData?.activities

const activitiesByDateSort =
monthlyActivities?.reduce(
(acc, activity) => {
const dateKey = format(
parseISO(activity.dateOfActivity),
'yyyy-MM-dd',
)
if (!acc[dateKey]) {
acc[dateKey] = []
}
acc[dateKey].push(activity)
return acc
},
{} as Record<string, typeof monthlyActivities>,
) ?? {}

const sortedDatesKeys = Object.keys(activitiesByDateSort)
setActivitiesByDate(activitiesByDateSort)
setSortedDates(sortedDatesKeys)
}, [keywordData])

const onBack = () => {
router.back()
}

const goToPreviousMonth = () => {
setCurrentDate((prev) => new Date(prev.getFullYear(), prev.getMonth() - 1))
}

const goToNextMonth = () => {
setCurrentDate((prev) => new Date(prev.getFullYear(), prev.getMonth() + 1))
}

return (
<div>
<div className="w-full">
<header className="relative font-semibold flex justify-center items-center py-4 min-h-52">
<IconLeft className="absolute left-20" onClick={onBack} />
<span>조각 별 상세정보</span>
</header>
{/* <section></section>
<section className="p-16 bg-primary_foundation-5">

<section>
<div className="flex flex-col mt-26 mb-10 w-350 mx-auto">
<p className="text-primary_foundation-60 text-14">
{nickname}님의 모은 시간
</p>
<div className="flex flex-col text-24 font-[500]">
<p className="flex items-center">
이달에
<span className="ml-12 mr-4 flex gap-4 items-center text-accent_100 text-28 font-[600] leading-34">
<Clock color="#FF4F38" />
{keywordData?.totalSavedTimeByKeywordInMonth}
</span>
</p>
<p>
{keywordData && transKeyword(keywordData.keyword.category)}
조각을 모았어요
</p>
</div>
</div>

<div className="w-390">
<Image
src={keywordData?.keyword.image || ''}
alt="keyword Image"
width={228}
height={228}
className="mx-auto"
/>
</div>
</section>

<OverviewHeaderForDetail
currentDate={currentDate}
setCurrentDate={setCurrentDate}
goToPreviousMonth={goToPreviousMonth}
goToNextMonth={goToNextMonth}
/>

<div className="p-16 bg-primary_foundation-5 mt-20">
{sortedDates?.map((date) => (
<div key={date} className="mb-20">
<h3 className="text-16 font-[500] mb-8 flex items-center">
Expand Down Expand Up @@ -145,7 +199,7 @@ export default function KeywordDetailPage() {
</div>
</div>
))}
</section> */}
</div>
</div>
)
}
14 changes: 14 additions & 0 deletions src/store/monthCount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { create } from 'zustand'

interface MonthCountState {
monthCount: number
setMonthCount: (newCount: number) => void
}

export const useMonthTotalCount = create<MonthCountState>((set) => ({
monthCount: 0,
setMonthCount: (newCount) =>
set({
monthCount: newCount,
}),
}))

0 comments on commit 7bb1ed7

Please sign in to comment.