191 lines
8.3 KiB
Dart
191 lines
8.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../../core/app_colors.dart';
|
|
import '../../database/db_helper.dart';
|
|
import '../../models/models.dart';
|
|
import '../../services/auth_service.dart';
|
|
import '../../services/route_simulator_service.dart';
|
|
|
|
class ReviewScreen extends StatefulWidget {
|
|
final String routeId;
|
|
final String colonia;
|
|
const ReviewScreen({super.key, required this.routeId, required this.colonia});
|
|
@override State<ReviewScreen> createState() => _ReviewScreenState();
|
|
}
|
|
|
|
class _ReviewScreenState extends State<ReviewScreen> {
|
|
int _estrellas = 5;
|
|
final _comentCtrl = TextEditingController();
|
|
bool _loading = false;
|
|
bool _sent = false;
|
|
|
|
static const _labels = ['', 'Muy malo', 'Malo', 'Regular', 'Bueno', 'Excelente'];
|
|
static const _colors = [
|
|
Colors.transparent, AppColors.rojoError, AppColors.naranjaAlerta,
|
|
Colors.amber, AppColors.verdeExito, AppColors.verdeExito,
|
|
];
|
|
|
|
Future<void> _enviar() async {
|
|
final auth = context.read<AuthService>();
|
|
if (auth.currentUser == null) return;
|
|
|
|
// Verificar si ya calificó hoy
|
|
final yaCalificado = await DbHelper.hasReviewedRoute(
|
|
auth.currentUser!.id!, widget.routeId);
|
|
if (yaCalificado && mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
|
content: Text('Ya calificaste este servicio hoy'),
|
|
backgroundColor: AppColors.azulInfo));
|
|
return;
|
|
}
|
|
|
|
setState(() => _loading = true);
|
|
try {
|
|
await DbHelper.insertReview(ReviewModel(
|
|
userId: auth.currentUser!.id!,
|
|
colonia: widget.colonia,
|
|
routeId: widget.routeId,
|
|
estrellas: _estrellas,
|
|
comentario: _comentCtrl.text.trim().isEmpty
|
|
? 'Sin comentario' : _comentCtrl.text.trim(),
|
|
fecha: DateTime.now().toIso8601String(),
|
|
nombreUsuario: auth.currentUser!.nombre,
|
|
));
|
|
context.read<RouteSimulatorService>().clearReviewPrompt(widget.routeId);
|
|
if (!mounted) return;
|
|
setState(() { _loading = false; _sent = true; });
|
|
} catch (e) {
|
|
if (!mounted) return;
|
|
setState(() => _loading = false);
|
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
|
|
content: Text('Error al guardar: ${e.toString()}'),
|
|
backgroundColor: AppColors.rojoError));
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: AppColors.grisFondo,
|
|
appBar: AppBar(
|
|
backgroundColor: AppColors.guindaPrimary, foregroundColor: Colors.white,
|
|
title: const Text('Calificar el Servicio'),
|
|
bottom: PreferredSize(preferredSize: const Size.fromHeight(4),
|
|
child: Container(height: 4, color: AppColors.dorado)),
|
|
),
|
|
body: _sent
|
|
? Center(child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
|
|
const Text('⭐', style: TextStyle(fontSize: 64)),
|
|
const SizedBox(height: 16),
|
|
const Text('¡Gracias por tu calificación!',
|
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold,
|
|
color: AppColors.guindaPrimary)),
|
|
const SizedBox(height: 8),
|
|
const Text('Tu opinión ayuda a mejorar el servicio\nde recolección en Celaya.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(color: AppColors.grisTexto)),
|
|
const SizedBox(height: 24),
|
|
ElevatedButton(
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColors.guindaPrimary, foregroundColor: Colors.white),
|
|
onPressed: () => Navigator.pop(context),
|
|
child: const Text('Volver al inicio')),
|
|
]))
|
|
: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(children: [
|
|
// Header
|
|
Container(
|
|
width: double.infinity, padding: const EdgeInsets.all(16),
|
|
decoration: BoxDecoration(
|
|
color: AppColors.guindaPrimary.withOpacity(0.08),
|
|
borderRadius: BorderRadius.circular(12),
|
|
border: Border.all(color: AppColors.guindaPrimary.withOpacity(0.2))),
|
|
child: Column(children: [
|
|
const Icon(Icons.local_shipping, color: AppColors.guindaPrimary, size: 36),
|
|
const SizedBox(height: 8),
|
|
Text(widget.routeId, style: const TextStyle(
|
|
fontWeight: FontWeight.bold, color: AppColors.guindaPrimary)),
|
|
Text(widget.colonia, style: const TextStyle(
|
|
color: AppColors.grisTexto, fontSize: 12)),
|
|
]),
|
|
),
|
|
const SizedBox(height: 24),
|
|
|
|
// Estrellas
|
|
const Text('¿Cómo calificarías el servicio de hoy?',
|
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
|
|
const SizedBox(height: 16),
|
|
Row(mainAxisAlignment: MainAxisAlignment.center, children: List.generate(5, (i) {
|
|
final star = i + 1;
|
|
return GestureDetector(
|
|
onTap: () => setState(() => _estrellas = star),
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 6),
|
|
child: Icon(
|
|
_estrellas >= star ? Icons.star : Icons.star_border,
|
|
color: _estrellas >= star ? Colors.amber : Colors.grey,
|
|
size: 44,
|
|
),
|
|
),
|
|
);
|
|
})),
|
|
const SizedBox(height: 8),
|
|
Text(_labels[_estrellas],
|
|
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold,
|
|
color: _colors[_estrellas])),
|
|
const SizedBox(height: 24),
|
|
|
|
// Comentario
|
|
const Align(alignment: Alignment.centerLeft,
|
|
child: Text('Comentario (opcional)',
|
|
style: TextStyle(fontWeight: FontWeight.w600))),
|
|
const SizedBox(height: 8),
|
|
TextField(
|
|
controller: _comentCtrl,
|
|
maxLines: 4,
|
|
maxLength: 200,
|
|
decoration: const InputDecoration(
|
|
hintText: 'Cuéntanos cómo estuvo el servicio...',
|
|
border: OutlineInputBorder(),
|
|
filled: true, fillColor: Colors.white),
|
|
),
|
|
const SizedBox(height: 20),
|
|
|
|
// Aviso
|
|
Container(
|
|
padding: const EdgeInsets.all(10),
|
|
decoration: BoxDecoration(color: Colors.blue.shade50,
|
|
borderRadius: BorderRadius.circular(8),
|
|
border: Border.all(color: Colors.blue.shade200)),
|
|
child: const Row(children: [
|
|
Icon(Icons.info_outline, color: AppColors.azulInfo, size: 16),
|
|
SizedBox(width: 6),
|
|
Expanded(child: Text(
|
|
'Tu calificación es anónima para otros ciudadanos, '
|
|
'pero el Ayuntamiento la usará para mejorar el servicio.',
|
|
style: TextStyle(fontSize: 11, color: AppColors.azulInfo))),
|
|
]),
|
|
),
|
|
const SizedBox(height: 24),
|
|
|
|
SizedBox(width: double.infinity, height: 50,
|
|
child: ElevatedButton.icon(
|
|
onPressed: _loading ? null : _enviar,
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: AppColors.guindaPrimary, foregroundColor: Colors.white,
|
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))),
|
|
icon: _loading
|
|
? const SizedBox(width: 18, height: 18,
|
|
child: CircularProgressIndicator(color: Colors.white, strokeWidth: 2))
|
|
: const Icon(Icons.star),
|
|
label: const Text('ENVIAR CALIFICACIÓN',
|
|
style: TextStyle(fontWeight: FontWeight.bold)))),
|
|
]),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override void dispose() { _comentCtrl.dispose(); super.dispose(); }
|
|
}
|