import 'package:flutter/material.dart'; import '../../core/app_colors.dart'; import '../../core/app_theme.dart'; import '../../core/navigation_provider.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../providers/auth_provider.dart'; import '../../providers/data_providers.dart'; class MedicationCheckInPage extends ConsumerStatefulWidget { final String? medId; // 可选:指定药品,null 显示全部 const MedicationCheckInPage({super.key, this.medId}); @override ConsumerState createState() => _MedicationCheckInPageState(); } class _MedicationCheckInPageState extends ConsumerState { Future>>? _future; @override void initState() { super.initState(); _load(); } void _load() => setState(() { _future = ref.read(medicationReminderProvider.future); }); Future _toggleDose(String medId, String time, bool taken) async { try { final api = ref.read(apiClientProvider); if (taken) { // 取消打卡:删掉对应 log await api.delete('/api/medications/$medId/confirm-dose/$time'); } else { // 打卡 await api.post('/api/medications/$medId/confirm-dose', data: {'scheduledTime': time, 'status': 'taken'}); } ref.invalidate(medicationReminderProvider); ref.invalidate(medicationListProvider); _load(); } catch (e) { debugPrint('[MedCheckIn] 打卡失败: $e'); } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.bg, appBar: AppBar(leading: IconButton(icon: const Icon(Icons.arrow_back), onPressed: () => popRoute(ref)), title: const Text('服药打卡'), centerTitle: true), body: FutureBuilder>>( future: _future, builder: (ctx, snap) { if (snap.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator(color: AppTheme.primary)); } final reminders = snap.data ?? []; if (reminders.isEmpty) { return Center( child: Column(mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.check_circle_outline, size: 64, color: AppTheme.textHint), const SizedBox(height: 12), const Text('今天所有用药已打卡', style: TextStyle(fontSize: 19, color: AppColors.textSecondary)), ]), ); } // 如果指定了 medId,只显示该药品 var filtered = reminders; if (widget.medId != null) { filtered = reminders.where((r) => r['id']?.toString() == widget.medId).toList(); } // 按药品分组 final grouped = >>{}; for (final r in filtered) { final name = r['name']?.toString() ?? '药品'; grouped.putIfAbsent(name, () => []).add(r); } return RefreshIndicator( onRefresh: () async => _load(), child: ListView( padding: const EdgeInsets.all(14), children: grouped.entries.map((entry) { final medName = entry.key; final doses = entry.value; final dosage = doses.first['dosage']?.toString() ?? ''; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: AppTheme.surface, borderRadius: BorderRadius.circular(AppTheme.rLg), boxShadow: [AppTheme.shadowCard], ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Container( width: 40, height: 40, decoration: BoxDecoration(color: AppColors.warningLight, borderRadius: BorderRadius.circular(10)), child: const Center(child: Text('💊', style: TextStyle(fontSize: 23))), ), const SizedBox(width: 12), Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(medName, style: const TextStyle(fontSize: 19, fontWeight: FontWeight.w700)), if (dosage.isNotEmpty) Text(dosage, style: const TextStyle(fontSize: 16, color: AppColors.textSecondary)), ]), ]), const SizedBox(height: 14), ...doses.map((d) { final time = d['scheduledTime']?.toString() ?? ''; final status = d['status']?.toString() ?? 'pending'; final isTaken = status == 'taken'; final medId = d['id']?.toString() ?? ''; return Padding( padding: const EdgeInsets.only(bottom: 8), child: Row(children: [ Icon( isTaken ? Icons.check_circle : Icons.radio_button_unchecked, size: 23, color: isTaken ? AppTheme.success : AppTheme.border, ), const SizedBox(width: 10), Text(time, style: TextStyle( fontSize: 18, fontWeight: FontWeight.w500, color: isTaken ? AppTheme.textSub : AppTheme.text, )), const Spacer(), GestureDetector( onTap: () => _toggleDose(medId, time, isTaken), child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), decoration: BoxDecoration( color: isTaken ? AppColors.successLight : AppTheme.primary, borderRadius: BorderRadius.circular(20), ), child: Text(isTaken ? '已打卡' : '打卡', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: isTaken ? AppTheme.success : AppColors.textOnGradient)), ), ), ]), ); }), ]), ); }).toList(), ), ); }, ), ); } }