import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:intl/intl.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import '/models/announcement.dart'; class AnnouncementsScreen extends ConsumerStatefulWidget { const AnnouncementsScreen({super.key}); @override ConsumerState createState() => _AnnouncementsScreenState(); } class _AnnouncementsScreenState extends ConsumerState { String? _filterRole; final _titleController = TextEditingController(); final _contentController = TextEditingController(); String? _targetRole; @override void dispose() { _titleController.dispose(); _contentController.dispose(); super.dispose(); } void _showNewAnnouncementDialog() { showModalBottomSheet( context: context, isScrollControlled: true, backgroundColor: const Color(0xFF16213E), shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (context) => Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, left: 20, right: 20, top: 20, ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('Novo Aviso', style: TextStyle( color: Colors.white, fontSize: 20, fontWeight: FontWeight.bold)), const SizedBox(height: 16), TextField( controller: _titleController, style: const TextStyle(color: Colors.white), decoration: _inputDec('Título', Icons.title), ), const SizedBox(height: 12), TextField( controller: _contentController, maxLines: 4, style: const TextStyle(color: Colors.white), decoration: _inputDec('Conteúdo do aviso...', Icons.message), ), const SizedBox(height: 12), DropdownButtonFormField( value: _targetRole, dropdownColor: const Color(0xFF16213E), style: const TextStyle(color: Colors.white), decoration: _inputDec('Público-alvo', Icons.group), items: const [ DropdownMenuItem(value: null, child: Text('Todos')), DropdownMenuItem(value: 'parent', child: Text('Encarregados')), DropdownMenuItem( value: 'teacher', child: Text('Educadoras')), DropdownMenuItem(value: 'staff', child: Text('Funcionários')), ], onChanged: (v) => setState(() => _targetRole = v), ), const SizedBox(height: 20), ElevatedButton( onPressed: _saveAnnouncement, style: ElevatedButton.styleFrom( backgroundColor: const Color(0xFF4FC3F7), minimumSize: const Size(double.infinity, 48), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12)), ), child: const Text('Publicar Aviso', style: TextStyle(color: Colors.white)), ), const SizedBox(height: 20), ], ), ), ); } Future _saveAnnouncement() async { if (_titleController.text.trim().isEmpty) return; final supabase = Supabase.instance.client; await supabase.from('announcements').insert({ 'title': _titleController.text.trim(), 'content': _contentController.text.trim(), 'target_role': _targetRole, }); _titleController.clear(); _contentController.clear(); if (mounted) Navigator.pop(context); } InputDecoration _inputDec(String hint, IconData icon) { return InputDecoration( hintText: hint, hintStyle: const TextStyle(color: Color(0xFF888888)), prefixIcon: Icon(icon, color: const Color(0xFF4FC3F7)), filled: true, fillColor: const Color(0xFF1A1A2E), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFF333366)), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(10), borderSide: const BorderSide(color: Color(0xFF4FC3F7), width: 2), ), ); } @override Widget build(BuildContext context) { final supabase = Supabase.instance.client; return Scaffold( backgroundColor: const Color(0xFF1A1A2E), appBar: AppBar( backgroundColor: const Color(0xFF16213E), title: const Text('Avisos', style: TextStyle(color: Color(0xFF4FC3F7))), ), body: Column( children: [ // Filtro tabs Container( color: const Color(0xFF16213E), padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: SingleChildScrollView( scrollDirection: Axis.horizontal, child: Row( children: [ _FilterChip( label: 'Todos', selected: _filterRole == null, onTap: () => setState(() => _filterRole = null)), const SizedBox(width: 8), _FilterChip( label: 'Encarregados', selected: _filterRole == 'parent', onTap: () => setState(() => _filterRole = 'parent')), const SizedBox(width: 8), _FilterChip( label: 'Funcionários', selected: _filterRole == 'teacher', onTap: () => setState(() => _filterRole = 'teacher')), ], ), ), ), // Lista Expanded( child: StreamBuilder>>( stream: supabase.from('announcements').stream(primaryKey: ['id']), builder: (context, snapshot) { if (!snapshot.hasData) { return const Center( child: CircularProgressIndicator( color: Color(0xFF4FC3F7))); } var list = snapshot.data! .map(Announcement.fromMap) .toList() ..sort((a, b) => b.createdAt.compareTo(a.createdAt)); if (_filterRole != null) { list = list .where((a) => a.targetRole == null || a.targetRole == _filterRole) .toList(); } if (list.isEmpty) { return const Center( child: Text('Sem avisos', style: TextStyle(color: Color(0xFF888888)))); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: list.length, itemBuilder: (context, i) { final ann = list[i]; return Container( margin: const EdgeInsets.only(bottom: 12), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: const Color(0xFF16213E), borderRadius: BorderRadius.circular(14), border: Border.all(color: const Color(0xFF333366)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Expanded( child: Text(ann.title, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, fontSize: 15)), ), if (ann.targetRole != null) Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 3), decoration: BoxDecoration( color: const Color(0xFF4FC3F7) .withOpacity(0.15), borderRadius: BorderRadius.circular(20), ), child: Text(ann.targetRole!, style: const TextStyle( color: Color(0xFF4FC3F7), fontSize: 11)), ), ], ), const SizedBox(height: 8), Text(ann.content, style: const TextStyle( color: Color(0xFF888888), fontSize: 13)), const SizedBox(height: 8), Text( DateFormat('d MMM yyyy, HH:mm', 'pt_PT') .format(ann.createdAt), style: const TextStyle( color: Color(0xFF555577), fontSize: 11), ), ], ), ); }, ); }, ), ), ], ), floatingActionButton: FloatingActionButton.extended( backgroundColor: const Color(0xFF4FC3F7), icon: const Icon(Icons.add, color: Colors.white), label: const Text('Novo Aviso', style: TextStyle(color: Colors.white)), onPressed: _showNewAnnouncementDialog, ), ); } } class _FilterChip extends StatelessWidget { final String label; final bool selected; final VoidCallback onTap; const _FilterChip( {required this.label, required this.selected, required this.onTap}); @override Widget build(BuildContext context) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), decoration: BoxDecoration( color: selected ? const Color(0xFF4FC3F7) : const Color(0xFF333366), borderRadius: BorderRadius.circular(20), ), child: Text(label, style: TextStyle( color: selected ? Colors.white : const Color(0xFF888888), fontSize: 13, fontWeight: selected ? FontWeight.bold : FontWeight.normal)), ), ); } }