import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'package:intl/intl.dart'; import '../../core/auth_provider.dart'; import '../../models/child.dart'; const _bg = Color(0xFF0D1117); const _card = Color(0xFF161B22); const _blue = Color(0xFF4FC3F7); const _green = Color(0xFF2ECC71); const _amber = Color(0xFFFFB300); const _red = Color(0xFFE74C3C); // OpΓ§Γ΅es de refeiΓ§Γ£o const _mealOpts = ['bem', 'pouco', 'nao_aceita']; const _mealLabels = {'bem': '😊 Bem', 'pouco': '😐 Pouco', 'nao_aceita': '😞 NΓ£o aceita'}; const _hygieneOpts = ['normal', 'diarreia', 'rastoso']; const _hygieneLabels = {'normal': 'βœ… Normal', 'diarreia': '⚠️ Diarreia', 'rastoso': '😷 Rastoso'}; class NewDiaryScreen extends ConsumerStatefulWidget { final String? childId; const NewDiaryScreen({super.key, this.childId}); @override ConsumerState createState() => _State(); } class _State extends ConsumerState { final _actCtrl = TextEditingController(); final _notesCtrl = TextEditingController(); final _instNotesCtrl = TextEditingController(); // notas da instituiΓ§Γ£o String? _childId; List _children = []; bool _loading = false; bool _loadingChildren = true; // Sono bool _sleepMorning = false; bool _sleepAfternoon = false; // AlimentaΓ§Γ£o String _breakfast = ''; String _lunch = ''; String _snackMeal = ''; // Higiene int _hygieneFreq = 0; String _hygieneState = ''; @override void initState() { super.initState(); _childId = widget.childId; _loadChildren(); } @override void dispose() { _actCtrl.dispose(); _notesCtrl.dispose(); _instNotesCtrl.dispose(); super.dispose(); } Future _loadChildren() async { try { final sb = Supabase.instance.client; final data = await sb.from('children').select().order('full_name'); setState(() { _children = data.map((d) => Child.fromMap(d)).toList(); _loadingChildren = false; }); } catch (_) { setState(() => _loadingChildren = false); } } Future _save() async { if (_childId == null) { _snack('Selecciona uma crianΓ§a.'); return; } if (_actCtrl.text.trim().isEmpty) { _snack('Descreve as actividades do dia.'); return; } setState(() => _loading = true); try { final sb = Supabase.instance.client; final profile = await ref.read(currentProfileProvider.future); if (profile == null) throw Exception('Perfil nΓ£o encontrado'); final today = DateTime.now().toIso8601String().split('T')[0]; // 1. Criar/actualizar diΓ‘rio final existing = await sb.from('daily_diaries').select('id') .eq('child_id', _childId!).eq('date', today).maybeSingle(); String diaryId; if (existing != null) { diaryId = existing['id'] as String; await sb.from('daily_diaries').update({ 'activities': _actCtrl.text.trim(), 'notes': _notesCtrl.text.trim(), 'institution_notes': _instNotesCtrl.text.trim(), 'teacher_id': profile.id, }).eq('id', diaryId); } else { final res = await sb.from('daily_diaries').insert({ 'child_id': _childId, 'teacher_id': profile.id, 'date': today, 'activities': _actCtrl.text.trim(), 'notes': _notesCtrl.text.trim(), 'institution_notes': _instNotesCtrl.text.trim(), }).select('id').single(); diaryId = res['id'] as String; } // 2. Sono await sb.from('sleep_records').upsert({ 'child_id': _childId, 'diary_id': diaryId, 'date': today, 'morning': _sleepMorning, 'afternoon': _sleepAfternoon, }, onConflict: 'child_id,date'); // 3. AlimentaΓ§Γ£o if (_breakfast.isNotEmpty || _lunch.isNotEmpty || _snackMeal.isNotEmpty) { await sb.from('meal_records').upsert({ 'child_id': _childId, 'diary_id': diaryId, 'date': today, 'breakfast': _breakfast, 'lunch': _lunch, 'snack': _snackMeal, }, onConflict: 'child_id,date'); } // 4. Higiene if (_hygieneFreq > 0 || _hygieneState.isNotEmpty) { await sb.from('hygiene_records').upsert({ 'child_id': _childId, 'diary_id': diaryId, 'date': today, 'frequency': _hygieneFreq, 'state': _hygieneState, }, onConflict: 'child_id,date'); } if (mounted) { _snack('DiΓ‘rio guardado! βœ“', ok: true); await Future.delayed(const Duration(milliseconds: 600)); if (mounted) context.pop(); } } 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) { final today = DateFormat('d MMMM yyyy', 'pt_PT').format(DateTime.now()); return Scaffold( backgroundColor: _bg, appBar: AppBar( backgroundColor: _card, elevation: 0, title: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('DiΓ‘rio do Dia', style: TextStyle(color: _blue, fontSize: 16, fontWeight: FontWeight.bold)), Text(today, style: TextStyle(color: Colors.white.withOpacity(0.4), fontSize: 11)), ]), actions: [ TextButton.icon( icon: _loading ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator(color: _blue, strokeWidth: 2)) : const Icon(Icons.save_outlined, color: _blue, size: 18), label: const Text('Guardar', style: TextStyle(color: _blue, fontWeight: FontWeight.bold)), onPressed: _loading ? null : _save, ), ], ), body: _loadingChildren ? const Center(child: CircularProgressIndicator(color: _blue)) : SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column(children: [ // ── Seleccionar crianΓ§a ───────────────────────── _Card(title: 'πŸ‘Ά CrianΓ§a', children: [ DropdownButtonFormField( value: _childId, dropdownColor: _card, style: const TextStyle(color: Colors.white), decoration: _dec('Selecciona a crianΓ§a', 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: 12), // ── Actividades ───────────────────────────────── _Card(title: '🎨 Actividades do Dia', children: [ TextField( controller: _actCtrl, maxLines: 4, style: const TextStyle(color: Colors.white, fontSize: 14), decoration: _dec('Descreve as actividades, brincadeiras, aprendizagens...', Icons.edit_note), ), ]), const SizedBox(height: 12), // ── Controlo de Sono ──────────────────────────── _Card(title: '😴 Controlo de Sono', children: [ Row(children: [ Expanded(child: _CheckTile( label: 'ManhΓ£', value: _sleepMorning, onChanged: (v) => setState(() => _sleepMorning = v), )), const SizedBox(width: 12), Expanded(child: _CheckTile( label: 'Tarde', value: _sleepAfternoon, onChanged: (v) => setState(() => _sleepAfternoon = v), )), ]), ]), const SizedBox(height: 12), // ── AlimentaΓ§Γ£o ───────────────────────────────── _Card(title: '🍽️ AlimentaΓ§Γ£o', children: [ _MealRow(label: 'Pequeno AlmoΓ§o', value: _breakfast, onChanged: (v) => setState(() => _breakfast = v)), const SizedBox(height: 10), _MealRow(label: 'AlmoΓ§o', value: _lunch, onChanged: (v) => setState(() => _lunch = v)), const SizedBox(height: 10), _MealRow(label: 'Lanche', value: _snackMeal, onChanged: (v) => setState(() => _snackMeal = v)), ]), const SizedBox(height: 12), // ── Higiene/EvacuaΓ§Γ£o ─────────────────────────── _Card(title: '🚿 Higiene & EvacuaΓ§Γ£o', children: [ Row(children: [ const Text('FrequΓͺncia:', style: TextStyle(color: Color(0xFF888888), fontSize: 13)), const SizedBox(width: 12), IconButton( onPressed: () => setState(() => _hygieneFreq = (_hygieneFreq - 1).clamp(0, 20)), icon: const Icon(Icons.remove_circle_outline, color: _red), ), Text('$_hygieneFreq x', style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold)), IconButton( onPressed: () => setState(() => _hygieneFreq++), icon: const Icon(Icons.add_circle_outline, color: _green), ), ]), const SizedBox(height: 10), const Text('Estado:', style: TextStyle(color: Color(0xFF888888), fontSize: 13)), const SizedBox(height: 8), Wrap(spacing: 8, children: _hygieneOpts.map((opt) { final sel = _hygieneState == opt; return GestureDetector( onTap: () => setState(() => _hygieneState = sel ? '' : opt), child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 7), decoration: BoxDecoration( color: sel ? _blue.withOpacity(0.2) : Colors.white.withOpacity(0.05), borderRadius: BorderRadius.circular(20), border: Border.all(color: sel ? _blue : Colors.white.withOpacity(0.1)), ), child: Text(_hygieneLabels[opt]!, style: TextStyle(color: sel ? _blue : Colors.white70, fontSize: 13)), ), ); }).toList()), ]), const SizedBox(height: 12), // ── Notas da Educadora ────────────────────────── _Card(title: 'πŸ“ Notas da Educadora', children: [ TextField( controller: _notesCtrl, maxLines: 3, style: const TextStyle(color: Colors.white, fontSize: 14), decoration: _dec('ObservaΓ§Γ΅es, comportamento, necessidades especiais...', Icons.notes), ), ]), const SizedBox(height: 12), // ── Notas da InstituiΓ§Γ£o ──────────────────────── _Card(title: '🏫 Notas da InstituiΓ§Γ£o', children: [ TextField( controller: _instNotesCtrl, maxLines: 3, style: const TextStyle(color: Colors.white, fontSize: 14), decoration: _dec('Comunicado para o encarregado de educaΓ§Γ£o...', Icons.business_outlined), ), ]), const SizedBox(height: 80), ]), ), floatingActionButton: FloatingActionButton.extended( backgroundColor: _blue, onPressed: _loading ? null : _save, icon: _loading ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2)) : const Icon(Icons.save, color: Colors.white), label: const Text('Guardar DiΓ‘rio', style: TextStyle(color: Colors.white, 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), ); } class _Card extends StatelessWidget { final String title; final List children; const _Card({required this.title, required this.children}); @override Widget build(BuildContext context) => Container( padding: const EdgeInsets.all(16), decoration: BoxDecoration(color: _card, borderRadius: BorderRadius.circular(16), border: Border.all(color: Colors.white.withOpacity(0.07))), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(title, style: const TextStyle(color: Colors.white, fontSize: 13, fontWeight: FontWeight.bold)), const SizedBox(height: 12), ...children, ]), ); } class _CheckTile extends StatelessWidget { final String label; final bool value; final ValueChanged onChanged; const _CheckTile({required this.label, required this.value, required this.onChanged}); @override Widget build(BuildContext context) => GestureDetector( onTap: () => onChanged(!value), child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), decoration: BoxDecoration( color: value ? _blue.withOpacity(0.12) : Colors.white.withOpacity(0.04), borderRadius: BorderRadius.circular(12), border: Border.all(color: value ? _blue.withOpacity(0.4) : Colors.white.withOpacity(0.09)), ), child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(value ? Icons.check_circle : Icons.circle_outlined, color: value ? _blue : Colors.white38, size: 18), const SizedBox(width: 8), Text(label, style: TextStyle(color: value ? _blue : Colors.white60, fontWeight: FontWeight.w500)), ]), ), ); } class _MealRow extends StatelessWidget { final String label, value; final ValueChanged onChanged; const _MealRow({required this.label, required this.value, required this.onChanged}); @override Widget build(BuildContext context) => Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle(color: Color(0xFF888888), fontSize: 12)), const SizedBox(height: 6), Row(children: _mealOpts.map((opt) { final sel = value == opt; Color c = opt == 'bem' ? const Color(0xFF2ECC71) : opt == 'pouco' ? const Color(0xFFFFB300) : const Color(0xFFE74C3C); return Expanded(child: GestureDetector( onTap: () => onChanged(sel ? '' : opt), child: Container( margin: const EdgeInsets.only(right: 6), padding: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: sel ? c.withOpacity(0.15) : Colors.white.withOpacity(0.04), borderRadius: BorderRadius.circular(10), border: Border.all(color: sel ? c.withOpacity(0.5) : Colors.white.withOpacity(0.08)), ), child: Text(_mealLabels[opt]!, textAlign: TextAlign.center, style: TextStyle(color: sel ? c : Colors.white54, fontSize: 11, fontWeight: FontWeight.w500)), ), )); }).toList()), ]); }