From 0f3e7b8a56fa3b5bc470caf9392e4e5d2ce51588 Mon Sep 17 00:00:00 2001 From: skytek_xinliang Date: Fri, 18 Sep 2026 09:58:52 +0800 Subject: [PATCH] feat: bmi --- .../src/api/physical-fitness.ts | 10 + app/citizen-frontend/src/api/types.ts | 10 + .../body-composition/BmiAnalysisCard.vue | 206 ++++++++++++++++++ .../body-composition/BodyFatAnalysisCard.vue | 73 +++++++ .../src/components/layout/DefaultLayout.vue | 9 + .../src/components/layout/PageHeading.vue | 56 +++++ app/citizen-frontend/src/config/features.ts | 12 +- .../src/data/who-bmi-standards.json | 17 ++ .../src/data/whoBmiStandards.ts | 10 + .../src/pages/body-composition.vue | 87 ++++++++ app/citizen-frontend/src/pages/course.vue | 15 +- app/citizen-frontend/src/pages/index.vue | 8 + .../src/pages/introduction.vue | 10 +- app/citizen-frontend/src/router/index.ts | 18 ++ .../src/utils/body-composition-status.ts | 19 ++ 15 files changed, 534 insertions(+), 26 deletions(-) create mode 100644 app/citizen-frontend/src/components/body-composition/BmiAnalysisCard.vue create mode 100644 app/citizen-frontend/src/components/body-composition/BodyFatAnalysisCard.vue create mode 100644 app/citizen-frontend/src/components/layout/PageHeading.vue create mode 100644 app/citizen-frontend/src/data/who-bmi-standards.json create mode 100644 app/citizen-frontend/src/data/whoBmiStandards.ts create mode 100644 app/citizen-frontend/src/pages/body-composition.vue create mode 100644 app/citizen-frontend/src/utils/body-composition-status.ts diff --git a/app/citizen-frontend/src/api/physical-fitness.ts b/app/citizen-frontend/src/api/physical-fitness.ts index c60a525..4792d48 100644 --- a/app/citizen-frontend/src/api/physical-fitness.ts +++ b/app/citizen-frontend/src/api/physical-fitness.ts @@ -1,4 +1,5 @@ import type { + BodyCompositionResponse, GeneratePhysicalFitnessResponse, PhysicalFitnessResponse, } from "./types"; @@ -21,3 +22,12 @@ export function generatePhysicalFitness( .post(`v1/physical-fitness/generate/${encodeURIComponent(userID)}`) .json(); } + +/** 取得指定使用者的身體組成分析。 */ +export function fetchBodyComposition( + userCode: string, +): Promise { + return api + .get(`v1/physical-fitness/body-composition/${encodeURIComponent(userCode)}`) + .json(); +} diff --git a/app/citizen-frontend/src/api/types.ts b/app/citizen-frontend/src/api/types.ts index 4d06ef9..ffea34c 100644 --- a/app/citizen-frontend/src/api/types.ts +++ b/app/citizen-frontend/src/api/types.ts @@ -28,6 +28,16 @@ export interface GeneratePhysicalFitnessResponse { message: string; } +/** PhysicalFitnessController 回傳的身體組成分析。 */ +export interface BodyCompositionResponse { + heightCm: number; + weightKg: number; + bmi: number; + bmiStatus: string; + bodyFatPercent: number; + bodyFatRange: string; +} + /** 性別 */ export type Gender = "male" | "female"; diff --git a/app/citizen-frontend/src/components/body-composition/BmiAnalysisCard.vue b/app/citizen-frontend/src/components/body-composition/BmiAnalysisCard.vue new file mode 100644 index 0000000..51bff7c --- /dev/null +++ b/app/citizen-frontend/src/components/body-composition/BmiAnalysisCard.vue @@ -0,0 +1,206 @@ + + + + + diff --git a/app/citizen-frontend/src/components/body-composition/BodyFatAnalysisCard.vue b/app/citizen-frontend/src/components/body-composition/BodyFatAnalysisCard.vue new file mode 100644 index 0000000..4b7a557 --- /dev/null +++ b/app/citizen-frontend/src/components/body-composition/BodyFatAnalysisCard.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/app/citizen-frontend/src/components/layout/DefaultLayout.vue b/app/citizen-frontend/src/components/layout/DefaultLayout.vue index 08aa01b..173f720 100644 --- a/app/citizen-frontend/src/components/layout/DefaultLayout.vue +++ b/app/citizen-frontend/src/components/layout/DefaultLayout.vue @@ -109,6 +109,15 @@ @click="drawer = false" /> + + +withDefaults( + defineProps<{ + title: string; + backTo?: string; + }>(), + { + backTo: "/", + }, +); + + + + + diff --git a/app/citizen-frontend/src/config/features.ts b/app/citizen-frontend/src/config/features.ts index b4abef6..a1d80ec 100644 --- a/app/citizen-frontend/src/config/features.ts +++ b/app/citizen-frontend/src/config/features.ts @@ -1,6 +1,6 @@ -export const APPOINTMENT_ENABLED = false -export const BOTTOM_NAVIGATION_ENABLED = false -export const CHECKIN_ENABLED = false -export const EXERCISE_DURATION_RECOMMENDATION_ENABLED = false -export const RADAR_ENABLED = false -export const SELF_ASSESSMENT_ENABLED = false +export const APPOINTMENT_ENABLED = false; +export const BOTTOM_NAVIGATION_ENABLED = false; +export const CHECKIN_ENABLED = false; +export const EXERCISE_DURATION_RECOMMENDATION_ENABLED = false; +export const RADAR_ENABLED = false; +export const SELF_ASSESSMENT_ENABLED = false; diff --git a/app/citizen-frontend/src/data/who-bmi-standards.json b/app/citizen-frontend/src/data/who-bmi-standards.json new file mode 100644 index 0000000..0fb7632 --- /dev/null +++ b/app/citizen-frontend/src/data/who-bmi-standards.json @@ -0,0 +1,17 @@ +[ + { + "label": "正常", + "range": "18.5–24.9", + "tone": "normal" + }, + { + "label": "過重", + "range": "25.0–29.9", + "tone": "caution" + }, + { + "label": "肥胖", + "range": "30.0以上", + "tone": "danger" + } +] diff --git a/app/citizen-frontend/src/data/whoBmiStandards.ts b/app/citizen-frontend/src/data/whoBmiStandards.ts new file mode 100644 index 0000000..811d0c2 --- /dev/null +++ b/app/citizen-frontend/src/data/whoBmiStandards.ts @@ -0,0 +1,10 @@ +import whoBmiStandards from "./who-bmi-standards.json"; +import type { BodyCompositionTone } from "@/utils/body-composition-status"; + +export interface WhoBmiStandard { + label: string; + range: string; + tone: BodyCompositionTone; +} + +export const WHO_BMI_STANDARDS = whoBmiStandards as WhoBmiStandard[]; diff --git a/app/citizen-frontend/src/pages/body-composition.vue b/app/citizen-frontend/src/pages/body-composition.vue new file mode 100644 index 0000000..5d9b22f --- /dev/null +++ b/app/citizen-frontend/src/pages/body-composition.vue @@ -0,0 +1,87 @@ + + + diff --git a/app/citizen-frontend/src/pages/course.vue b/app/citizen-frontend/src/pages/course.vue index a031ff3..8a904a9 100644 --- a/app/citizen-frontend/src/pages/course.vue +++ b/app/citizen-frontend/src/pages/course.vue @@ -2,19 +2,7 @@