From a9d70aa130b1aa934c96479eaf9427d2af47c367 Mon Sep 17 00:00:00 2001 From: MingNian <1281442923@qq.com> Date: Thu, 21 May 2026 16:43:43 +0800 Subject: [PATCH] fix: medication time slot picker, auto-expire, red dot logic, home greeting position --- frontend-patient/src/pages/home/HomePage.tsx | 5 +- .../pages/medication/MedicationEditPage.tsx | 70 ++++++++----------- .../pages/medication/MedicationListPage.tsx | 57 +++++++++++---- 3 files changed, 76 insertions(+), 56 deletions(-) diff --git a/frontend-patient/src/pages/home/HomePage.tsx b/frontend-patient/src/pages/home/HomePage.tsx index 8c96b13..c1f2fa2 100644 --- a/frontend-patient/src/pages/home/HomePage.tsx +++ b/frontend-patient/src/pages/home/HomePage.tsx @@ -40,10 +40,9 @@ export function HomePage() { return (
-
+
-
你好,{user?.nickname || '用户'}
-
今天感觉如何?
+
你好,{user?.nickname || '用户'}
+ ))}
- setDrugName(e.target.value)} /> + setDrugName(e.target.value)} />
- setDosage(e.target.value)} placeholder="100mg" /> + setDosage(e.target.value)} placeholder="如 100mg" />
- -
- {(['每日1次', '每日2次', '每日3次'] as const).map((f) => ( - - ))} -
+ + {timeSlots.map((slot, i) => ( +
+ updateTimeSlot(i, e.target.value)} + style={{ flex: 1, padding: '8px 12px', border: '1px solid #ddd', borderRadius: 8, fontSize: 14, fontFamily: 'inherit' }} /> + +
+ ))} +
setStartDate(e.target.value)} type="date" /> - setEndDate(e.target.value)} type="date" /> + setEndDate(e.target.value)} type="date" />
- setNotes(e.target.value)} /> + setNotes(e.target.value)} placeholder="如:饭后服用" /> - +
diff --git a/frontend-patient/src/pages/medication/MedicationListPage.tsx b/frontend-patient/src/pages/medication/MedicationListPage.tsx index 6a4ee0d..98df340 100644 --- a/frontend-patient/src/pages/medication/MedicationListPage.tsx +++ b/frontend-patient/src/pages/medication/MedicationListPage.tsx @@ -3,18 +3,40 @@ import { useNavigate } from 'react-router-dom'; import { PageHeader } from '@/components/layout/PageHeader'; import { Card } from '@/components/common/Card'; import { Empty } from '@/components/common/Empty'; -import { Badge } from '@/components/common/Badge'; import * as medicationService from '@/services/medication.service'; -import type { Medication } from '@/types'; +import type { Medication, MedicationRecord } from '@/types'; import styles from './MedicationListPage.module.css'; export function MedicationListPage() { const navigate = useNavigate(); const [medications, setMedications] = useState([]); + const [takenMap, setTakenMap] = useState>({}); const [tab, setTab] = useState<'active' | 'completed'>('active'); useEffect(() => { - medicationService.getMedications().then(setMedications); + medicationService.getMedications().then(async (meds) => { + const today = new Date().toISOString().split('T')[0]; + // Auto-expire: check endDate + const updated = meds.map((m) => { + if (m.status === 'active' && m.endDate && m.endDate < today) { + return { ...m, status: 'completed' as const }; + } + return m; + }); + setMedications(updated); + + // Check which meds have all slots taken today + const map: Record = {}; + for (const med of updated) { + if (med.status !== 'active') continue; + try { + const records = await medicationService.getMedicationRecords(med.id); + const todayRecords = records.filter((r) => r.takenAt?.startsWith(today) && r.isTaken); + map[med.id] = todayRecords.length >= med.timeSlots.length; + } catch { map[med.id] = true; } + } + setTakenMap(map); + }); }, []); const filtered = medications.filter((m) => @@ -32,16 +54,25 @@ export function MedicationListPage() { {filtered.length === 0 ? ( ) : ( - filtered.map((med) => ( - navigate(`/health/medications/${med.id}`)}> -
- {med.drugName} - {med.status === 'active' && } -
-
{med.dosage} · {med.timeSlots.join(', ')}
-
{med.notes}
-
- )) + filtered.map((med) => { + const allTaken = takenMap[med.id]; + return ( + navigate(`/health/medications/${med.id}`)}> +
+ {med.drugName} + {med.status === 'active' && !allTaken && } + {med.status === 'active' && allTaken && } +
+
{med.dosage} · {med.frequency} · {med.timeSlots.join(', ')}
+ {med.notes &&
{med.notes}
} + {med.status === 'active' && med.endDate && ( +
+ 至 {med.endDate} +
+ )} +
+ ); + }) )}