Files
soft/frontend-patient/src/pages/services/FollowUpListPage.tsx
MingNian 39ab6062b5 feat: medication reminders, follow-up/visit separation, health record page
Backend:
- MedicationService: today-summary with missed detection (local time)
- FollowUpService: doctor-initiated follow-ups filter, AddAsync supports Notes
- FollowUpController: type query param (followup/recheck)
- MedicationController: today-summary endpoint
- Auth: UpdateProfileRequest→class, StentDate/StentType, soft-delete fix

Patient frontend:
- HomePage: date display, medication reminder cards with missed status
- MedicationListPage: beautified with delete button, slot preview
- MedicationDetailPage: redesigned with progress bars, new CSS
- ProfilePage: beautified menu icons, health record link
- HealthRecordPage: new page with indicators, history, meds, reports
- ServicesHub: added doctor-visit card
- VisitListPage: doctor-initiated follow-ups view
- EditProfilePage: removed height/weight, added stent fields
- Fixed getProfile field mappings (nickname, height, weight, stent)

Doctor frontend:
- Layout: added 随访管理 sidebar item with SVG icon
- FollowUpListPage: recheck-only filter, complete/delete buttons, collapsed completed
- VisitListPage/EditPage: doctor follow-up management
- PatientListPage: added stentType column
- Dashboard: fixed pending reports endpoint
- ReportListPage/DetailPage: fixed uploadedAt field
- ChatPage: SignalR real-time, dynamic hostname
2026-05-25 14:48:05 +08:00

59 lines
2.3 KiB
TypeScript

import { useEffect, useState } from 'react';
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 * as followupService from '@/services/followup.service';
import type { FollowUp } from '@/types';
import { formatDate } from '@/utils/format';
import styles from './FollowUpListPage.module.css';
export function FollowUpListPage() {
const navigate = useNavigate();
const [followups, setFollowups] = useState<FollowUp[]>([]);
const [tab, setTab] = useState<'upcoming' | 'completed'>('upcoming');
useEffect(() => {
followupService.getFollowUps('recheck').then(setFollowups);
}, []);
const filtered = followups.filter((f) => tab === 'upcoming' ? f.status === 'upcoming' : f.status === 'completed');
const statusColor = (s: FollowUp['status']) => {
if (s === 'upcoming') return '#3B82F6';
if (s === 'completed') return '#10B981';
return '#EF4444';
};
return (
<div className="page--no-tab">
<PageHeader title="复查管理" />
<div className={styles.tabs}>
<button className={`${styles.tab} ${tab === 'upcoming' ? styles.tabActive : ''}`} onClick={() => setTab('upcoming')}></button>
<button className={`${styles.tab} ${tab === 'completed' ? styles.tabActive : ''}`} onClick={() => setTab('completed')}></button>
</div>
{filtered.length === 0 ? (
<Empty message="暂无复查计划" />
) : (
filtered.map((f) => (
<Card key={f.id} className={styles.card}>
<div className={styles.cardHeader}>
<span className={styles.title}>{f.title}</span>
<span className={styles.status} style={{ color: statusColor(f.status) }}>
{f.status === 'upcoming' ? '待复查' : '已完成'}
</span>
</div>
<div className={styles.meta}>
<span>{f.doctorName || '未分配'} · {f.patientName || ''}</span>
</div>
<div className={styles.meta}>
<span>{formatDate(f.scheduledAt, 'YYYY-MM-DD HH:mm')}</span>
</div>
</Card>
))
)}
<button className={styles.fab} onClick={() => navigate('/services/follow-ups/add')}>+ </button>
</div>
);
}