From 6afbb10fbd28a50f9a1927f81d7a8ad7243b6330 Mon Sep 17 00:00:00 2001 From: Alberto Date: Wed, 11 Mar 2026 19:24:17 +0000 Subject: [PATCH] Eliminar creche_app/lib/features/chat/chat_screen.dart --- creche_app/lib/features/chat/chat_screen.dart | 266 ------------------ 1 file changed, 266 deletions(-) delete mode 100644 creche_app/lib/features/chat/chat_screen.dart diff --git a/creche_app/lib/features/chat/chat_screen.dart b/creche_app/lib/features/chat/chat_screen.dart deleted file mode 100644 index f943bfc..0000000 --- a/creche_app/lib/features/chat/chat_screen.dart +++ /dev/null @@ -1,266 +0,0 @@ -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 '/core/auth_provider.dart'; -import '/models/message.dart'; -import '/models/profile.dart'; - -const _bg = Color(0xFF0D1117); -const _card = Color(0xFF161B22); -const _blue = Color(0xFF4FC3F7); - -class ChatScreen extends ConsumerStatefulWidget { - final String toUserId; // profiles.id (não auth uid) - const ChatScreen({super.key, required this.toUserId}); - @override - ConsumerState createState() => _ChatScreenState(); -} - -class _ChatScreenState extends ConsumerState { - final _msgCtrl = TextEditingController(); - final _scrollCtrl = ScrollController(); - String? _myProfileId; - Profile? _otherProfile; - bool _loadingProfile = true; - - @override - void initState() { - super.initState(); - _loadProfiles(); - } - - @override - void dispose() { - _msgCtrl.dispose(); - _scrollCtrl.dispose(); - super.dispose(); - } - - Future _loadProfiles() async { - final sb = Supabase.instance.client; - final uid = sb.auth.currentUser?.id; - if (uid == null) return; - - // Buscar o meu profile id - final me = await sb.from('profiles').select('id').eq('user_id', uid).maybeSingle(); - // Buscar perfil do outro - final other = await sb.from('profiles').select().eq('id', widget.toUserId).maybeSingle(); - - if (mounted) { - setState(() { - _myProfileId = me?['id'] as String?; - _otherProfile = other != null ? Profile.fromMap(other) : null; - _loadingProfile = false; - }); - } - _scrollToBottom(); - } - - Future _send() async { - final text = _msgCtrl.text.trim(); - if (text.isEmpty || _myProfileId == null) return; - final sb = Supabase.instance.client; - _msgCtrl.clear(); - try { - await sb.from('messages').insert({ - 'from_user': _myProfileId, - 'to_user': widget.toUserId, - 'content': text, - 'is_read': false, - }); - _scrollToBottom(); - } catch (e) { - if (mounted) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('Erro ao enviar: $e'), - backgroundColor: Colors.red, behavior: SnackBarBehavior.floating)); - } - } - } - - void _scrollToBottom() { - WidgetsBinding.instance.addPostFrameCallback((_) { - if (_scrollCtrl.hasClients) { - _scrollCtrl.animateTo(_scrollCtrl.position.maxScrollExtent, - duration: const Duration(milliseconds: 300), curve: Curves.easeOut); - } - }); - } - - @override - Widget build(BuildContext context) { - if (_loadingProfile) { - return const Scaffold(backgroundColor: _bg, - body: Center(child: CircularProgressIndicator(color: _blue))); - } - if (_myProfileId == null) { - return const Scaffold(backgroundColor: _bg, - body: Center(child: Text('Perfil não encontrado.', style: TextStyle(color: Colors.white)))); - } - - final sb = Supabase.instance.client; - final myId = _myProfileId!; - - return Scaffold( - backgroundColor: _bg, - appBar: AppBar( - backgroundColor: _card, - elevation: 0, - title: Row(children: [ - CircleAvatar( - radius: 18, - backgroundColor: _blue.withOpacity(0.15), - backgroundImage: _otherProfile?.avatarUrl != null - ? NetworkImage(_otherProfile!.avatarUrl!) : null, - child: _otherProfile?.avatarUrl == null - ? Text((_otherProfile?.fullName ?? '?')[0].toUpperCase(), - style: const TextStyle(color: _blue, fontWeight: FontWeight.bold)) : null, - ), - const SizedBox(width: 10), - Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(_otherProfile?.fullName ?? 'Utilizador', - style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.bold)), - if (_otherProfile?.role != null) - Text(_otherProfile!.role, style: const TextStyle(color: Color(0xFF888888), fontSize: 11)), - ]), - ]), - ), - body: Column(children: [ - Expanded( - child: StreamBuilder>>( - stream: sb.from('messages').stream(primaryKey: ['id']).order('created_at'), - builder: (context, snapshot) { - if (snapshot.hasError) { - return Center(child: Text('Erro: ${snapshot.error}', - style: const TextStyle(color: Colors.red))); - } - if (!snapshot.hasData) { - return const Center(child: CircularProgressIndicator(color: _blue)); - } - - final msgs = snapshot.data! - .where((m) => - (m['from_user'] == myId && m['to_user'] == widget.toUserId) || - (m['from_user'] == widget.toUserId && m['to_user'] == myId)) - .map(Message.fromMap) - .toList(); - - if (msgs.isEmpty) { - return Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.chat_bubble_outline, color: Colors.white.withOpacity(0.15), size: 60), - const SizedBox(height: 12), - Text('Começa a conversa!', - style: TextStyle(color: Colors.white.withOpacity(0.3), fontSize: 14)), - ])); - } - - WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom()); - - return ListView.builder( - controller: _scrollCtrl, - padding: const EdgeInsets.all(16), - itemCount: msgs.length, - itemBuilder: (_, i) { - final msg = msgs[i]; - final isMe = msg.fromUser == myId; - return _Bubble(msg: msg, isMe: isMe); - }, - ); - }, - ), - ), - // Input - Container( - color: _card, - padding: EdgeInsets.only( - left: 12, right: 12, top: 10, - bottom: MediaQuery.of(context).viewInsets.bottom + 10, - ), - child: Row(children: [ - Expanded( - child: TextField( - controller: _msgCtrl, - style: const TextStyle(color: Colors.white, fontSize: 14), - maxLines: 4, minLines: 1, - textInputAction: TextInputAction.send, - onSubmitted: (_) => _send(), - decoration: InputDecoration( - hintText: 'Escreve uma mensagem...', - hintStyle: TextStyle(color: Colors.white.withOpacity(0.3), fontSize: 13), - filled: true, fillColor: Colors.white.withOpacity(0.05), - contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), - border: OutlineInputBorder(borderRadius: BorderRadius.circular(20), - borderSide: BorderSide.none), - ), - ), - ), - const SizedBox(width: 8), - GestureDetector( - onTap: _send, - child: Container( - width: 44, height: 44, - decoration: BoxDecoration( - gradient: const LinearGradient(colors: [_blue, Color(0xFF0288D1)]), - shape: BoxShape.circle, - boxShadow: [BoxShadow(color: _blue.withOpacity(0.3), blurRadius: 10)], - ), - child: const Icon(Icons.send_rounded, color: Colors.white, size: 20), - ), - ), - ]), - ), - ]), - ); - } -} - -class _Bubble extends StatelessWidget { - final Message msg; - final bool isMe; - const _Bubble({required this.msg, required this.isMe}); - - @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.only(bottom: 8), - child: Row( - mainAxisAlignment: isMe ? MainAxisAlignment.end : MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - if (!isMe) ...[ - CircleAvatar(radius: 14, backgroundColor: _blue.withOpacity(0.15), - child: const Icon(Icons.person, color: _blue, size: 14)), - const SizedBox(width: 6), - ], - Flexible( - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), - decoration: BoxDecoration( - color: isMe ? const Color(0xFF1A4A6A) : _card, - borderRadius: BorderRadius.only( - topLeft: const Radius.circular(16), - topRight: const Radius.circular(16), - bottomLeft: Radius.circular(isMe ? 16 : 4), - bottomRight: Radius.circular(isMe ? 4 : 16), - ), - border: Border.all( - color: isMe ? _blue.withOpacity(0.3) : Colors.white.withOpacity(0.07)), - ), - child: Column(crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text(msg.content, - style: const TextStyle(color: Colors.white, fontSize: 14, height: 1.4)), - const SizedBox(height: 4), - Text( - DateFormat('HH:mm').format(msg.createdAt.toLocal()), - style: TextStyle(color: Colors.white.withOpacity(0.35), fontSize: 10), - ), - ]), - ), - ), - if (isMe) const SizedBox(width: 4), - ], - ), - ); - } -}