Files
soft/frontend-patient/src/pages/health/HealthCalendarPage.tsx
MingNian 435af55c4a Initial commit: HealthManager full-stack health management platform
Backend: .NET 10 + PostgreSQL + EF Core + JWT + SignalR
Frontend patient: React 19 + TypeScript + Vite (mobile H5)
Frontend doctor: React 19 + TypeScript + Vite (desktop web)
2026-05-20 16:18:56 +08:00

113 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useState, useMemo } from 'react';
import { PageHeader } from '@/components/layout/PageHeader';
import { Card } from '@/components/common/Card';
import type { CalendarDay } from '@/types';
import dayjs from 'dayjs';
import styles from './HealthCalendarPage.module.css';
const MARKER_COLORS: Record<string, string> = {
medication_taken: '#10B981',
medication_missed: '#EF4444',
follow_up: '#F59E0B',
measurement: '#2563EB',
};
export function HealthCalendarPage() {
const [currentDate, setCurrentDate] = useState(dayjs());
const calendarDays = useMemo(() => {
const startOfMonth = currentDate.startOf('month');
const endOfMonth = currentDate.endOf('month');
const startDay = startOfMonth.day();
const days: CalendarDay[] = [];
const today = dayjs().format('YYYY-MM-DD');
for (let i = startDay - 1; i >= 0; i--) {
const d = startOfMonth.subtract(i + 1, 'day');
days.push({
date: d.format('YYYY-MM-DD'),
year: d.year(),
month: d.month() + 1,
day: d.date(),
isCurrentMonth: false,
isToday: d.format('YYYY-MM-DD') === today,
markers: [],
});
}
for (let d = startOfMonth; d.isBefore(endOfMonth) || d.isSame(endOfMonth, 'day'); d = d.add(1, 'day')) {
const dateStr = d.format('YYYY-MM-DD');
const markers: CalendarDay['markers'] = [];
// Calendar markers would be populated from real API data
days.push({
date: dateStr,
year: d.year(),
month: d.month() + 1,
day: d.date(),
isCurrentMonth: true,
isToday: dateStr === today,
markers,
});
}
return days;
}, [currentDate]);
const weeks: CalendarDay[][] = [];
for (let i = 0; i < calendarDays.length; i += 7) {
weeks.push(calendarDays.slice(i, i + 7));
}
return (
<div className="page--no-tab">
<PageHeader title="健康日历" />
<div className={styles.monthNav}>
<button onClick={() => setCurrentDate((d) => d.subtract(1, 'month'))}></button>
<span className={styles.monthTitle}>{currentDate.format('YYYY年 M月')}</span>
<button onClick={() => setCurrentDate((d) => d.add(1, 'month'))}></button>
</div>
<div className={styles.weekdays}>
{['日', '一', '二', '三', '四', '五', '六'].map((w) => (
<span key={w} className={styles.weekday}>{w}</span>
))}
</div>
{weeks.map((week, wi) => (
<div key={wi} className={styles.week}>
{week.map((day) => (
<div
key={day.date}
className={`${styles.day} ${!day.isCurrentMonth ? styles.outside : ''} ${day.isToday ? styles.today : ''}`}
>
<span className={styles.dayNum}>{day.day}</span>
<div className={styles.markers}>
{day.markers.slice(0, 3).map((m, i) => (
<span
key={i}
className={styles.dot}
style={{ background: m.color }}
/>
))}
</div>
</div>
))}
</div>
))}
<Card className={styles.legend}>
<div className={styles.legendTitle}></div>
<div className={styles.legendItems}>
<span className={styles.legendItem}><span className={styles.dot} style={{ background: '#2563EB' }} /> </span>
<span className={styles.legendItem}><span className={styles.dot} style={{ background: '#10B981' }} /> </span>
<span className={styles.legendItem}><span className={styles.dot} style={{ background: '#EF4444' }} /> </span>
<span className={styles.legendItem}><span className={styles.dot} style={{ background: '#F59E0B' }} /> </span>
</div>
</Card>
</div>
);
}