-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #125 from alkong-dalkong/feature/#84_heath_page
feat: 건강 페이지
- Loading branch information
Showing
54 changed files
with
1,269 additions
and
15 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+24.9 KB
.yarn/cache/@types-d3-interpolate-npm-3.0.4-e863f31b1c-066ebb8da5.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+247 KB
.yarn/cache/react-transition-group-npm-4.4.5-98ea4ef96e-2ba754ba74.zip
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,7 @@ | ||
import { BottomNav } from '@/components' | ||
import { HealthClientPage } from '@/features' | ||
|
||
export type HealthRouteParams = { | ||
params: { userId: string } | ||
} | ||
|
||
const Health = ({ params: { userId } }: HealthRouteParams) => { | ||
return ( | ||
<div> | ||
<h2>{userId}</h2> | ||
<BottomNav /> | ||
</div> | ||
) | ||
const Health = () => { | ||
return <HealthClientPage /> | ||
} | ||
|
||
export default Health |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,4 @@ | ||
export * from './clinic' | ||
export * from './medicine' | ||
export * from './slide' | ||
export * from './tos' | ||
export * from './zIndex' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use client' | ||
|
||
import { useMemo, useState } from 'react' | ||
|
||
import { useWeightInfo } from '@/features' | ||
|
||
export const useGraph = () => { | ||
const info = useWeightInfo() | ||
const [index, setIndex] = useState<number>(0) | ||
|
||
const quadGraphData = useMemo(() => { | ||
const groups = [] | ||
for (let i = 0; i < info.length; i += 4) { | ||
groups.push(info.slice(i, i + 4)) | ||
} | ||
return groups | ||
}, [info]) | ||
|
||
const increase = () => { | ||
if (index < quadGraphData.length - 1) { | ||
setIndex((prev) => prev + 1) | ||
} | ||
} | ||
|
||
const decrease = () => { | ||
if (index > 0) { | ||
setIndex((prev) => prev - 1) | ||
} | ||
} | ||
|
||
return { data: quadGraphData[index]?.toReversed(), increase, decrease } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { api } from '@/apis' | ||
import type { | ||
GetPhysicalRequest, | ||
GetPhysicalResponse, | ||
PostPhysicalRequest, | ||
PostPhysicalResponse, | ||
PutPhysicalRequest, | ||
PutPhysicalResponse, | ||
} from '@/types' | ||
|
||
export const getHealth = async ({ userId, period }: GetPhysicalRequest) => { | ||
return await api.get<GetPhysicalResponse>(`/physical/${userId}`, { | ||
params: { | ||
period, | ||
}, | ||
}) | ||
} | ||
|
||
export const postHealth = async (request: PostPhysicalRequest) => { | ||
return await api.post<PostPhysicalResponse>('/physical', request) | ||
} | ||
|
||
export const putHealth = async (weightId: number, request: PutPhysicalRequest) => { | ||
return await api.put<PutPhysicalResponse>(`/physical/${weightId}`, request) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const queryKeys = { | ||
all: ['health'] as const, | ||
page: (userId: string, period: string) => [...queryKeys.all, userId, period], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use client' | ||
|
||
import { useParams } from 'next/navigation' | ||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' | ||
|
||
import { getHealth, postHealth, putHealth } from '@/features' | ||
import { queryKeys } from '@/features' | ||
import { usePeriod } from '@/features/health/store/healthStore' | ||
import type { PutPhysicalRequest } from '@/types' | ||
|
||
export const useFetchHealth = () => { | ||
const period = usePeriod() | ||
const { userId } = useParams<{ userId: string }>() | ||
return useQuery({ | ||
queryKey: queryKeys.page(userId, period), | ||
queryFn: () => getHealth({ userId, period }), | ||
}) | ||
} | ||
|
||
export const useCreateHealth = () => { | ||
const queryClient = useQueryClient() | ||
return useMutation({ | ||
mutationFn: postHealth, | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: queryKeys.all }) | ||
}, | ||
}) | ||
} | ||
|
||
export const useEditHealth = () => { | ||
const queryClient = useQueryClient() | ||
return useMutation({ | ||
mutationFn: ({ weightId, request }: { weightId: number; request: PutPhysicalRequest }) => | ||
putHealth(weightId, request), | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ queryKey: queryKeys.all }) | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import dayjs from 'dayjs' | ||
|
||
import { usePhysicalId, useWeightId } from '@/features' | ||
import { useCreateHealth, useEditHealth } from '@/features' | ||
import { useSelectedWeight } from '@/store' | ||
|
||
export const useWeightSelectConfirm = (toggleShowing: VoidFunction) => { | ||
const weightId = useWeightId() | ||
const physicalId = usePhysicalId() | ||
const weight = Number(useSelectedWeight()) | ||
const { mutate: editWeight } = useEditHealth() | ||
const { mutate: createWeight } = useCreateHealth() | ||
const createdAt = dayjs().format('YYYY-MM-DD') | ||
|
||
const handleConfirm = () => { | ||
if (weightId) { | ||
editWeight({ | ||
weightId, | ||
request: { | ||
weight, | ||
createdAt, | ||
}, | ||
}) | ||
} else if (physicalId) { | ||
createWeight({ | ||
physicalId, | ||
weight, | ||
createdAt, | ||
}) | ||
} | ||
toggleShowing() | ||
} | ||
|
||
return handleConfirm | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { create } from 'zustand' | ||
|
||
import type { GetPhysicalResponse, HealthReportType, WeightInfoType } from '@/types' | ||
|
||
type PeriodType = 'weekly' | 'monthly' | ||
|
||
type HealthState = { | ||
period: PeriodType | ||
physicalId?: number | ||
weightId?: number | ||
weight?: number | ||
weightInfo: WeightInfoType | ||
healthreport?: HealthReportType | ||
actions: HealthActions | ||
} | ||
|
||
type HealthActions = { | ||
togglePeriod: VoidFunction | ||
syncFetchHealthData: (data: GetPhysicalResponse) => void | ||
} | ||
|
||
const useHealthStore = create<HealthState>((set, get) => ({ | ||
period: 'weekly', | ||
physicalId: undefined, | ||
weightId: undefined, | ||
weight: undefined, | ||
weightInfo: [], | ||
healthreport: undefined, | ||
actions: { | ||
togglePeriod: () => { | ||
const { period } = get() | ||
set({ period: period === 'weekly' ? 'monthly' : 'weekly' }) | ||
}, | ||
syncFetchHealthData: ({ data }: GetPhysicalResponse) => { | ||
set({ | ||
physicalId: data.physicalId, | ||
weightId: data.weight?.weightId, | ||
weight: data.weight?.weight, | ||
weightInfo: data.weightInfo, | ||
healthreport: data.healthReport, | ||
}) | ||
}, | ||
}, | ||
})) | ||
|
||
export const usePeriod = () => useHealthStore((state) => state.period) | ||
export const usePhysicalId = () => useHealthStore((state) => state.physicalId) | ||
export const useWeightId = () => useHealthStore((state) => state.weightId) | ||
export const useWeight = () => useHealthStore((state) => state.weight) | ||
export const useHealthReport = () => useHealthStore((state) => state.healthreport) | ||
export const useWeightInfo = () => useHealthStore((state) => state.weightInfo) | ||
export const useHealthActions = () => useHealthStore((state) => state.actions) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
.recharts-xAxis { | ||
display: none; | ||
} | ||
|
||
.recharts-cartesian-axis-line { | ||
display: none; | ||
} | ||
|
||
.recharts-cartesian-axis-tick-line { | ||
display: none; | ||
} | ||
|
||
.recharts-cartesian-grid-vertical { | ||
display: none; | ||
} | ||
|
||
.recharts-yAxis { | ||
width: 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
'use client' | ||
|
||
import { Icon } from '@/components' | ||
import Label from '@/components/label/Label' | ||
import { useHealthActions, usePeriod, useWeightInfo } from '@/features' | ||
|
||
import { useGraph } from '../hooks/useGraph' | ||
|
||
import { WeightChart } from './WeightChart' | ||
|
||
export const GraphSection = () => { | ||
const period = usePeriod() | ||
const WeightInfo = useWeightInfo() | ||
const { togglePeriod } = useHealthActions() | ||
const { data, increase, decrease } = useGraph() | ||
|
||
return ( | ||
<section className="mb-10 w-full"> | ||
{/** Label과 Toggle Button 렌더링 */} | ||
<div className="flex items-center gap-4"> | ||
<Label icon="check-label">체중 그래프</Label> | ||
<button | ||
className="body-M flex-center gap-2 rounded-full bg-gray-2 px-3 pb-[6px] pt-1 text-gray-7" | ||
onClick={togglePeriod} | ||
> | ||
<span>{period === 'weekly' ? '주간' : '월간'}</span> | ||
<span className="mt-[2px]"> | ||
<Icon name="arrow-down" /> | ||
</span> | ||
</button> | ||
</div> | ||
|
||
{/** 그래프 네비게이터 렌더링 */} | ||
<div className="mb-4 mt-[21px] flex items-center justify-between"> | ||
<button className="flex cursor-pointer items-center gap-2" onClick={increase}> | ||
<Icon name="arrow-left" color="#0E8763" /> | ||
<div className="subtitle-B text-gray-7">이전</div> | ||
</button> | ||
<button className="flex cursor-pointer items-center gap-2" onClick={decrease}> | ||
<div className="subtitle-B text-gray-7">다음</div> | ||
<Icon name="arrow-right" color="#0E8763" /> | ||
</button> | ||
</div> | ||
|
||
{/** 그래프 렌더링 */} | ||
<div className="h-[243px] w-full"> | ||
{WeightInfo.length !== 0 ? ( | ||
<WeightChart data={data} /> | ||
) : ( | ||
<div className="flex-center size-full whitespace-pre text-center text-gray-6"> | ||
{'체중을 입력하면\n그래프가 나타나요!'} | ||
</div> | ||
)} | ||
</div> | ||
</section> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
'use client' | ||
|
||
import { DashBoardTemplate } from '@/features' | ||
import { useHealthActions } from '@/features' | ||
import { useFetchHealth } from '@/features' | ||
|
||
import { GraphSection } from './GraphSection' | ||
import { ReportSection } from './ReportSection' | ||
import { WeightSection } from './WeightSection' | ||
|
||
export const HealthClientPage = () => { | ||
const { data } = useFetchHealth() | ||
const { syncFetchHealthData } = useHealthActions() | ||
|
||
if (!data) { | ||
return ( | ||
<DashBoardTemplate route="health"> | ||
{/* 추후 수정 */} | ||
<div>데이터를 불러오는데 실패하였습니다</div> | ||
</DashBoardTemplate> | ||
) | ||
} | ||
|
||
syncFetchHealthData({ ...data }) | ||
|
||
return ( | ||
<DashBoardTemplate route="health"> | ||
<GraphSection /> | ||
<WeightSection /> | ||
<ReportSection /> | ||
</DashBoardTemplate> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
'use client' | ||
|
||
import Label from '@/components/label/Label' | ||
import { useHealthReport } from '@/features' | ||
import { useUserStore } from '@/store' | ||
|
||
export const ReportSection = () => { | ||
const { | ||
user: { name }, | ||
} = useUserStore() | ||
const report = useHealthReport() | ||
|
||
return ( | ||
<section className="w-full"> | ||
<Label icon="health-label">건강 분석 리포트</Label> | ||
{report ? ( | ||
<> | ||
<div className="subtitle-M mt-2 whitespace-pre rounded-xl bg-mint-0 px-6 py-4"> | ||
{`${name}님과 같은 성별, 나이의 평균\n몸무게인 ${report.apiAvgWeight}kg보다 ${Math.abs(report.diffWeight).toFixed(2)}kg ${report.diffWeight > 0 ? '높아요' : '낮아요'}.`} | ||
</div> | ||
<div className="subtitle-M mt-2 whitespace-pre rounded-xl bg-mint-0 px-6 py-4"> | ||
{`${name}님의 평균 체중이\n지난주보다 ${Math.abs(report.lastweekWeight)}kg ${report.lastweekWeight > 0 ? '증가했어요' : '감소했어요'}.`} | ||
</div> | ||
</> | ||
) : ( | ||
<div className="subtitle-M mt-2 whitespace-pre rounded-xl bg-mint-0 px-6 py-4 text-gray-6"> | ||
{'체중을 입력하면\n리포트를 확인할 수 있어요!'} | ||
</div> | ||
)} | ||
</section> | ||
) | ||
} |
Oops, something went wrong.