Avance del programa
This commit is contained in:
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import '../../core/app_colors.dart';
|
||||
import '../shared/reporte_chat_screen.dart';
|
||||
import '../../database/db_helper.dart';
|
||||
import '../../models/models.dart';
|
||||
import '../../services/auth_service.dart';
|
||||
@@ -66,32 +67,44 @@ class _CitizenReporteScreenState extends State<CitizenReporteScreen> {
|
||||
|
||||
Future<void> _send() async {
|
||||
final auth = context.read<AuthService>();
|
||||
if (auth.currentUser == null || _desc.text.trim().isEmpty) {
|
||||
if (auth.currentUser == null) return;
|
||||
if (_desc.text.trim().isEmpty) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text('Describe el problema'),
|
||||
content: Text('Describe el problema para poder enviar el reporte'),
|
||||
backgroundColor: AppColors.rojoError));
|
||||
return;
|
||||
}
|
||||
setState(() => _loading = true);
|
||||
|
||||
final db = await DbHelper.database;
|
||||
await db.insert('reportes', {
|
||||
'user_id': auth.currentUser!.id,
|
||||
'tipo': _tipo,
|
||||
'descripcion': _desc.text.trim(),
|
||||
'colonia': auth.primaryDomicilio?.colonia ?? '',
|
||||
'route_id': auth.primaryDomicilio?.routeId ?? '',
|
||||
'fecha': DateTime.now().toIso8601String(),
|
||||
'estado': 'PENDIENTE',
|
||||
'calificacion': _calif,
|
||||
'foto_path': _foto?.path,
|
||||
});
|
||||
try {
|
||||
// Insertar reporte directo en la BD
|
||||
final db = await DbHelper.database;
|
||||
final id = await db.insert('reportes', {
|
||||
'user_id': auth.currentUser!.id,
|
||||
'tipo': _tipo,
|
||||
'descripcion': _desc.text.trim(),
|
||||
'colonia': auth.primaryDomicilio?.colonia ?? 'Sin colonia',
|
||||
'route_id': auth.primaryDomicilio?.routeId ?? '',
|
||||
'fecha': DateTime.now().toIso8601String(),
|
||||
'estado': 'PENDIENTE',
|
||||
'calificacion': _calif,
|
||||
'foto_path': _foto?.path,
|
||||
});
|
||||
|
||||
await _load();
|
||||
if (!mounted) return;
|
||||
setState(() { _loading = false; _sent = true; _desc.clear(); _foto = null; });
|
||||
await Future.delayed(const Duration(seconds: 2));
|
||||
if (mounted) setState(() => _sent = false);
|
||||
if (id <= 0) throw Exception('No se pudo guardar el reporte');
|
||||
|
||||
await _load();
|
||||
_desc.clear();
|
||||
setState(() { _foto = null; _loading = false; _sent = true; });
|
||||
await Future.delayed(const Duration(seconds: 3));
|
||||
if (mounted) setState(() => _sent = false);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() => _loading = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
||||
content: Text('Error al enviar: $e'),
|
||||
backgroundColor: AppColors.rojoError));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -104,12 +117,18 @@ class _CitizenReporteScreenState extends State<CitizenReporteScreen> {
|
||||
child: Container(height: 4, color: AppColors.dorado))),
|
||||
body: _sent
|
||||
? Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||
const Icon(Icons.check_circle, color: AppColors.verdeExito, size: 64),
|
||||
const SizedBox(height: 12),
|
||||
const Text('Reporte enviado', style: TextStyle(fontSize: 20,
|
||||
const Icon(Icons.check_circle, color: AppColors.verdeExito, size: 72),
|
||||
const SizedBox(height: 16),
|
||||
const Text('Reporte enviado', style: TextStyle(fontSize: 22,
|
||||
fontWeight: FontWeight.bold, color: AppColors.verdeExito)),
|
||||
const Text('El Ayuntamiento lo revisara pronto.',
|
||||
const SizedBox(height: 8),
|
||||
const Text('El Ayuntamiento revisara tu reporte pronto.',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: AppColors.grisTexto)),
|
||||
const SizedBox(height: 8),
|
||||
const Text('Podras chatear con ellos desde "Mis Reportes".',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: AppColors.grisTexto, fontSize: 12)),
|
||||
]))
|
||||
: SingleChildScrollView(padding: const EdgeInsets.all(16), child: Column(children: [
|
||||
Card(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
@@ -190,21 +209,45 @@ class _CitizenReporteScreenState extends State<CitizenReporteScreen> {
|
||||
child: Text('Mis Reportes', style: TextStyle(fontWeight: FontWeight.bold,
|
||||
color: AppColors.guindaPrimary, fontSize: 15))),
|
||||
const SizedBox(height: 8),
|
||||
..._reportes.map((r) => Card(margin: const EdgeInsets.only(bottom: 6),
|
||||
child: ListTile(dense: true,
|
||||
..._reportes.map((r) {
|
||||
final isClosed = r.estado == 'COMPLETADO';
|
||||
final id = r.id ?? 0;
|
||||
final folio = 'RPT-${id.toString().padLeft(5, "0")}';
|
||||
return Card(margin: const EdgeInsets.only(bottom: 6),
|
||||
child: Column(children: [
|
||||
ListTile(dense: true,
|
||||
leading: CircleAvatar(backgroundColor: AppColors.guindaPrimary, radius: 16,
|
||||
child: const Icon(Icons.report, color: Colors.white, size: 16)),
|
||||
title: Text(_tipos[r.tipo] ?? r.tipo,
|
||||
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600)),
|
||||
subtitle: Text(r.descripcion, maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
title: Row(children: [
|
||||
Expanded(child: Text(_tipos[r.tipo] ?? r.tipo,
|
||||
style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600))),
|
||||
Text(folio, style: const TextStyle(fontSize: 9, color: AppColors.grisTexto)),
|
||||
]),
|
||||
subtitle: Text(r.descripcion, maxLines: 1, overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(fontSize: 11)),
|
||||
trailing: Container(padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: _estadoColor(r.estado).withOpacity(0.15),
|
||||
decoration: BoxDecoration(color: _estadoColor(r.estado).withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(10)),
|
||||
child: Text(r.estado, style: TextStyle(fontSize: 9,
|
||||
color: _estadoColor(r.estado), fontWeight: FontWeight.bold)))))),
|
||||
child: Text(r.estado.replaceAll('_',' '),
|
||||
style: TextStyle(fontSize: 9, color: _estadoColor(r.estado),
|
||||
fontWeight: FontWeight.bold)))),
|
||||
if (r.id != null) Padding(
|
||||
padding: const EdgeInsets.fromLTRB(14, 0, 14, 8),
|
||||
child: SizedBox(width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () => Navigator.push(context, MaterialPageRoute(
|
||||
builder: (_) => ReporteChatScreen(
|
||||
reporteId: r.id!, folio: folio, isClosed: isClosed))),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: isClosed ? AppColors.grisTexto : AppColors.guindaPrimary,
|
||||
side: BorderSide(color: isClosed ? AppColors.grisTexto : AppColors.guindaPrimary),
|
||||
padding: const EdgeInsets.symmetric(vertical: 6),
|
||||
minimumSize: Size.zero),
|
||||
icon: Icon(isClosed ? Icons.lock : Icons.chat_bubble_outline, size: 14),
|
||||
label: Text(isClosed ? 'Chat cerrado' : 'Escribir al Ayuntamiento',
|
||||
style: const TextStyle(fontSize: 11))))),
|
||||
]));
|
||||
}),
|
||||
],
|
||||
])),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user