Eliminar creche_app/lib/features/announcements/announcements_screen.dart

This commit is contained in:
Alberto 2026-03-11 19:22:50 +00:00
parent c47e27ddfd
commit 27f81e1b13
1 changed files with 0 additions and 309 deletions

View File

@ -1,309 +0,0 @@
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<AnnouncementsScreen> createState() =>
_AnnouncementsScreenState();
}
class _AnnouncementsScreenState extends ConsumerState<AnnouncementsScreen> {
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<String>(
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<void> _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<List<Map<String, dynamic>>>(
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)),
),
);
}
}