import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:intl/intl.dart'; import 'package:uuid/uuid.dart'; import '/core/auth_provider.dart'; import '/models/child.dart'; const _bg = Color(0xFF0D1117); const _card = Color(0xFF161B22); const _blue = Color(0xFF4FC3F7); const _red = Color(0xFFE74C3C); const _green = Color(0xFF2ECC71); const _amber = Color(0xFFFFB300); class MedicationScreen extends ConsumerStatefulWidget { const MedicationScreen({super.key}); @override ConsumerState createState() => _State(); } class _State extends ConsumerState with SingleTickerProviderStateMixin { late TabController _tabs; @override void initState() { super.initState(); _tabs = TabController(length: 2, vsync: this); } @override void dispose() { _tabs.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final profile = ref.watch(currentProfileProvider).valueOrNull; final isParent = profile?.role == 'parent'; return Scaffold( backgroundColor: _bg, appBar: AppBar( backgroundColor: _card, elevation: 0, title: const Text('Medicação', style: TextStyle(color: _blue, fontWeight: FontWeight.bold)), bottom: TabBar( controller: _tabs, indicatorColor: _blue, labelColor: _blue, unselectedLabelColor: Colors.white38, tabs: [ const Tab(text: 'Activa'), Tab(text: isParent ? 'Registar' : 'Histórico', icon: null), ], ), ), body: TabBarView(controller: _tabs, children: [ _ActiveMeds(isParent: isParent ?? false), isParent ? const _AddMedication() : const _MedHistory(), ]), floatingActionButton: isParent == true ? null : FloatingActionButton.extended( backgroundColor: _amber, icon: const Icon(Icons.medication, color: Colors.white), label: const Text('Registar Toma', style: TextStyle(color: Colors.white)), onPressed: () => _showAdministerDialog(context), ), ); } void _showAdministerDialog(BuildContext ctx) { showModalBottomSheet(context: ctx, isScrollControlled: true, backgroundColor: _card, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20))), builder: (_) => const _AdministerForm()); } } // ── Lista medicação activa ───────────────────────────────────────── class _ActiveMeds extends ConsumerWidget { final bool isParent; const _ActiveMeds({required this.isParent}); @override Widget build(BuildContext context, WidgetRef ref) { final sb = Supabase.instance.client; final profile = ref.watch(currentProfileProvider).valueOrNull; return StreamBuilder>>( stream: sb.from('medications').stream(primaryKey: ['id']) .eq('active', true).order('child_id'), builder: (context, snapshot) { if (snapshot.hasError) return _err('Erro: ${snapshot.error}'); if (!snapshot.hasData) return const Center(child: CircularProgressIndicator(color: _blue)); final meds = snapshot.data!; if (meds.isEmpty) return _empty('Nenhuma medicação activa'); // Filtrar por encarregado se parent return FutureBuilder>( future: isParent ? _myChildIds(sb, profile?.id) : Future.value(null), builder: (ctx, childIds) { final filtered = childIds.data != null ? meds.where((m) => childIds.data!.contains(m['child_id'])).toList() : meds; if (filtered.isEmpty) return _empty('Sem medicação activa para os teus filhos'); return ListView.builder( padding: const EdgeInsets.all(16), itemCount: filtered.length, itemBuilder: (_, i) => _MedCard(med: filtered[i], isParent: isParent), ); }, ); }, ); } Future> _myChildIds(SupabaseClient sb, String? guardianId) async { if (guardianId == null) return []; final rows = await sb.from('child_guardians').select('child_id').eq('guardian_id', guardianId); return rows.map((r) => r['child_id'] as String).toList(); } } class _MedCard extends StatelessWidget { final Map med; final bool isParent; const _MedCard({required this.med, required this.isParent}); @override Widget build(BuildContext context) { final name = med['medication_name'] ?? ''; final dose = med['dosage'] ?? ''; final times = (med['schedule'] as List?)?.join(', ') ?? ''; final notes = med['notes'] ?? ''; final childName = med['child_name'] ?? 'Criança'; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: _card, borderRadius: BorderRadius.circular(16), border: Border.all(color: _amber.withOpacity(0.3)), boxShadow: [BoxShadow(color: _amber.withOpacity(0.05), blurRadius: 12)], ), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Row(children: [ Container( padding: const EdgeInsets.all(8), decoration: BoxDecoration(color: _amber.withOpacity(0.12), shape: BoxShape.circle), child: const Icon(Icons.medication, color: _amber, size: 20), ), const SizedBox(width: 12), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(name, style: const TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.bold)), Text(childName, style: const TextStyle(color: Color(0xFF888888), fontSize: 12)), ])), if (!isParent) Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration(color: _green.withOpacity(0.12), borderRadius: BorderRadius.circular(20)), child: const Text('Activa', style: TextStyle(color: _green, fontSize: 11)), ), ]), const SizedBox(height: 12), if (dose.isNotEmpty) _InfoRow(icon: Icons.scale, text: 'Dosagem: $dose'), if (times.isNotEmpty) _InfoRow(icon: Icons.schedule, text: 'Horários: $times'), if (notes.isNotEmpty) _InfoRow(icon: Icons.notes, text: notes), ]), ); } } class _InfoRow extends StatelessWidget { final IconData icon; final String text; const _InfoRow({required this.icon, required this.text}); @override Widget build(BuildContext context) => Padding( padding: const EdgeInsets.only(bottom: 4), child: Row(children: [ Icon(icon, size: 14, color: const Color(0xFF888888)), const SizedBox(width: 6), Expanded(child: Text(text, style: const TextStyle(color: Color(0xFF888888), fontSize: 12))), ]), ); } // ── Encarregado regista medicação ────────────────────────────────── class _AddMedication extends ConsumerStatefulWidget { const _AddMedication(); @override ConsumerState<_AddMedication> createState() => _AddMedState(); } class _AddMedState extends ConsumerState<_AddMedication> { final _nameCtrl = TextEditingController(); final _doseCtrl = TextEditingController(); final _notesCtrl = TextEditingController(); String? _childId; final List _schedules = []; final _timeCtrl = TextEditingController(); bool _loading = false; List _children = []; @override void initState() { super.initState(); _loadChildren(); } @override void dispose() { _nameCtrl.dispose(); _doseCtrl.dispose(); _notesCtrl.dispose(); _timeCtrl.dispose(); super.dispose(); } Future _loadChildren() async { final sb = Supabase.instance.client; final profile = await ref.read(currentProfileProvider.future); if (profile == null) return; final rows = await sb.from('child_guardians').select('children(*)').eq('guardian_id', profile.id); if (mounted) setState(() { _children = rows.map((r) => Child.fromMap(r['children'] as Map)).toList(); }); } Future _save() async { if (_childId == null || _nameCtrl.text.trim().isEmpty) { _snack('Preenche o medicamento e a criança.'); return; } setState(() => _loading = true); try { final sb = Supabase.instance.client; final profile = await ref.read(currentProfileProvider.future); await sb.from('medications').insert({ 'id': const Uuid().v4(), 'child_id': _childId, 'medication_name': _nameCtrl.text.trim(), 'dosage': _doseCtrl.text.trim(), 'schedule': _schedules, 'notes': _notesCtrl.text.trim(), 'reported_by': profile?.id, 'active': true, }); _nameCtrl.clear(); _doseCtrl.clear(); _notesCtrl.clear(); setState(() { _schedules.clear(); _childId = null; }); _snack('Medicação registada! A equipa foi notificada.', ok: true); } catch (e) { _snack('Erro: $e'); } finally { if (mounted) setState(() => _loading = false); } } void _snack(String msg, {bool ok = false}) => ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text(msg, style: const TextStyle(color: Colors.white)), backgroundColor: ok ? _green : _red, behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)))); @override Widget build(BuildContext context) => SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ _sec('👶 Criança'), DropdownButtonFormField( value: _childId, dropdownColor: _card, style: const TextStyle(color: Colors.white), decoration: _dec('Selecciona o teu filho', Icons.child_care), items: _children.map((c) => DropdownMenuItem(value: c.id, child: Text(c.fullName, style: const TextStyle(color: Colors.white)))).toList(), onChanged: (v) => setState(() => _childId = v), ), const SizedBox(height: 16), _sec('💊 Medicamento'), TextField(controller: _nameCtrl, style: const TextStyle(color: Colors.white), decoration: _dec('Nome do medicamento (ex: Paracetamol)', Icons.medication)), const SizedBox(height: 12), TextField(controller: _doseCtrl, style: const TextStyle(color: Colors.white), decoration: _dec('Dosagem (ex: 5ml, 1 comprimido)', Icons.scale)), const SizedBox(height: 16), _sec('⏰ Horários de Toma'), Row(children: [ Expanded(child: TextField( controller: _timeCtrl, style: const TextStyle(color: Colors.white), decoration: _dec('Ex: 08:00, depois do almoço', Icons.schedule), )), const SizedBox(width: 8), GestureDetector( onTap: () { if (_timeCtrl.text.trim().isNotEmpty) { setState(() { _schedules.add(_timeCtrl.text.trim()); _timeCtrl.clear(); }); }}, child: Container( padding: const EdgeInsets.all(14), decoration: const BoxDecoration(color: _blue, shape: BoxShape.circle), child: const Icon(Icons.add, color: Colors.white, size: 20), ), ), ]), if (_schedules.isNotEmpty) Wrap(spacing: 6, children: _schedules.asMap().entries.map((e) => Chip(label: Text(e.value, style: const TextStyle(color: Colors.white, fontSize: 12)), backgroundColor: _blue.withOpacity(0.2), deleteIconColor: Colors.white54, onDeleted: () => setState(() => _schedules.removeAt(e.key)))).toList()), const SizedBox(height: 12), _sec('📝 Observações (opcional)'), TextField(controller: _notesCtrl, maxLines: 3, style: const TextStyle(color: Colors.white), decoration: _dec('Instruções especiais, alergias, avisos...', Icons.notes)), const SizedBox(height: 24), GestureDetector( onTap: _loading ? null : _save, child: Container( height: 52, width: double.infinity, decoration: BoxDecoration( gradient: const LinearGradient(colors: [_amber, Color(0xFFFF8F00)]), borderRadius: BorderRadius.circular(14), boxShadow: [BoxShadow(color: _amber.withOpacity(0.3), blurRadius: 16, offset: const Offset(0,6))], ), child: Center(child: _loading ? const SizedBox(width: 22, height: 22, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2)) : const Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.send_outlined, color: Colors.white, size: 18), SizedBox(width: 10), Text('Enviar à Creche', style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold, fontSize: 15)), ])), ), ), const SizedBox(height: 32), ]), ); Widget _sec(String t) => Padding(padding: const EdgeInsets.only(bottom: 8), child: Text(t, style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold))); InputDecoration _dec(String hint, IconData icon) => InputDecoration( hintText: hint, hintStyle: const TextStyle(color: Color(0xFF555555), fontSize: 13), prefixIcon: Icon(icon, color: _blue.withOpacity(0.6), size: 18), filled: true, fillColor: Colors.white.withOpacity(0.04), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide(color: Colors.white.withOpacity(0.09))), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: _blue, width: 1.5)), contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), ); } // ── Histórico (staff) ────────────────────────────────────────────── class _MedHistory extends StatelessWidget { const _MedHistory(); @override Widget build(BuildContext context) { final sb = Supabase.instance.client; return StreamBuilder>>( stream: sb.from('medications').stream(primaryKey: ['id']).order('created_at', ascending: false), builder: (ctx, snap) { if (!snap.hasData) return const Center(child: CircularProgressIndicator(color: _blue)); if (snap.data!.isEmpty) return _empty('Sem registos de medicação'); return ListView.builder( padding: const EdgeInsets.all(16), itemCount: snap.data!.length, itemBuilder: (_, i) => _MedCard(med: snap.data![i], isParent: false), ); }, ); } } class _AdministerForm extends StatelessWidget { const _AdministerForm(); @override Widget build(BuildContext context) => const Padding( padding: EdgeInsets.all(20), child: Text('Formulário de toma (em breve)', style: TextStyle(color: Colors.white)), ); } Widget _empty(String msg) => Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.medication_outlined, size: 60, color: Colors.white.withOpacity(0.1)), const SizedBox(height: 12), Text(msg, style: const TextStyle(color: Color(0xFF888888), fontSize: 13)), ])); Widget _err(String msg) => Center(child: Text(msg, style: const TextStyle(color: Colors.red)));