213 lines
8.2 KiB
Dart
213 lines
8.2 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:provider/provider.dart';
|
||
import '../../core/app_colors.dart';
|
||
import '../../data/celaya_colonias.dart';
|
||
import '../../data/colonies_data.dart';
|
||
import '../../database/db_helper.dart';
|
||
import '../../models/models.dart';
|
||
import '../../models/route_model.dart';
|
||
import '../../services/auth_service.dart';
|
||
|
||
class AddDomicilioScreen extends StatefulWidget {
|
||
final DomicilioModel? editing;
|
||
const AddDomicilioScreen({super.key, this.editing});
|
||
@override State<AddDomicilioScreen> createState() => _AddDomicilioScreenState();
|
||
}
|
||
|
||
class _AddDomicilioScreenState extends State<AddDomicilioScreen> {
|
||
final _calleCtrl = TextEditingController();
|
||
final _aliasCtrl = TextEditingController(text: 'Casa');
|
||
String? _coloniaSeleccionada;
|
||
ColonyModel? _coloniaData;
|
||
bool _loading = false;
|
||
String _searchQuery = '';
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
if (widget.editing != null) {
|
||
_calleCtrl.text = widget.editing!.calle;
|
||
_aliasCtrl.text = widget.editing!.alias;
|
||
_coloniaSeleccionada = widget.editing!.colonia;
|
||
_coloniaData = getColonyByName(widget.editing!.colonia);
|
||
}
|
||
}
|
||
|
||
List<String> get _filteredColonias {
|
||
if (_searchQuery.isEmpty) return celayaColonias;
|
||
return celayaColonias
|
||
.where((c) => c.toLowerCase().contains(_searchQuery.toLowerCase()))
|
||
.toList();
|
||
}
|
||
|
||
Future<void> _guardar() async {
|
||
if (_calleCtrl.text.trim().isEmpty || _coloniaSeleccionada == null) {
|
||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||
content: Text('Por favor completa todos los campos'),
|
||
backgroundColor: AppColors.rojoError));
|
||
return;
|
||
}
|
||
setState(() => _loading = true);
|
||
|
||
final auth = context.read<AuthService>();
|
||
|
||
// 1. Buscar primero en colonies_data (rutas predefinidas)
|
||
final staticData = getColonyByName(_coloniaSeleccionada!);
|
||
String routeId = staticData?.routeId ?? '';
|
||
String horario = staticData?.horarioEstimado ?? '';
|
||
|
||
// 2. Si no hay match estático, buscar en route_definitions del admin
|
||
if (routeId.isEmpty) {
|
||
final routeDefs = await DbHelper.getAllRouteDefinitions();
|
||
for (final rd in routeDefs) {
|
||
if (rd.colonias.any((c) =>
|
||
c.toLowerCase() == _coloniaSeleccionada!.toLowerCase())) {
|
||
routeId = rd.routeId;
|
||
horario = '${_turnoLabel(rd.turno)} (${rd.horaInicio}–${rd.horaFin})';
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 3. Fallback si no se encontró
|
||
if (routeId.isEmpty) {
|
||
routeId = 'RUTA-01';
|
||
horario = 'Matutino (06:00–08:00)';
|
||
}
|
||
|
||
if (widget.editing != null) {
|
||
await DbHelper.deleteDomicilio(widget.editing!.id!);
|
||
}
|
||
|
||
final dom = DomicilioModel(
|
||
userId: auth.currentUser!.id!,
|
||
alias: _aliasCtrl.text.trim(),
|
||
calle: _calleCtrl.text.trim(),
|
||
colonia: _coloniaSeleccionada!,
|
||
routeId: routeId,
|
||
horarioEstimado: horario,
|
||
);
|
||
await DbHelper.insertDomicilio(dom);
|
||
await auth.reloadDomicilios();
|
||
|
||
if (!mounted) return;
|
||
setState(() => _loading = false);
|
||
Navigator.pop(context, true);
|
||
}
|
||
|
||
String _turnoLabel(String t) =>
|
||
t == 'MATUTINO' ? 'Matutino' : t == 'VESPERTINO' ? 'Vespertino' : 'Nocturno';
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: AppColors.grisFondo,
|
||
appBar: AppBar(
|
||
backgroundColor: AppColors.guindaPrimary, foregroundColor: Colors.white,
|
||
title: Text(widget.editing != null ? 'Editar Domicilio' : 'Agregar Domicilio'),
|
||
bottom: PreferredSize(preferredSize: const Size.fromHeight(4),
|
||
child: Container(height: 4, color: AppColors.dorado)),
|
||
),
|
||
body: SingleChildScrollView(
|
||
padding: const EdgeInsets.all(16),
|
||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||
// Alias
|
||
TextField(
|
||
controller: _aliasCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Alias (ej. Casa, Trabajo, Familia)',
|
||
prefixIcon: Icon(Icons.label_outline, color: AppColors.guindaPrimary),
|
||
border: OutlineInputBorder(), filled: true, fillColor: Colors.white),
|
||
),
|
||
const SizedBox(height: 12),
|
||
// Calle
|
||
TextField(
|
||
controller: _calleCtrl,
|
||
decoration: const InputDecoration(
|
||
labelText: 'Calle y número',
|
||
prefixIcon: Icon(Icons.signpost_outlined, color: AppColors.guindaPrimary),
|
||
border: OutlineInputBorder(), filled: true, fillColor: Colors.white),
|
||
),
|
||
const SizedBox(height: 16),
|
||
const Text('Colonia', style: TextStyle(fontWeight: FontWeight.bold,
|
||
color: AppColors.guindaPrimary, fontSize: 15)),
|
||
const SizedBox(height: 8),
|
||
// Buscador de colonias
|
||
TextField(
|
||
onChanged: (v) => setState(() => _searchQuery = v),
|
||
decoration: const InputDecoration(
|
||
hintText: 'Buscar colonia...',
|
||
prefixIcon: Icon(Icons.search),
|
||
border: OutlineInputBorder(), filled: true, fillColor: Colors.white,
|
||
isDense: true,
|
||
),
|
||
),
|
||
const SizedBox(height: 8),
|
||
// Lista de colonias
|
||
Container(
|
||
height: 240,
|
||
decoration: BoxDecoration(
|
||
color: Colors.white, borderRadius: BorderRadius.circular(8),
|
||
border: Border.all(color: Colors.grey.shade300)),
|
||
child: ListView.builder(
|
||
itemCount: _filteredColonias.length,
|
||
itemBuilder: (_, i) {
|
||
final c = _filteredColonias[i];
|
||
final isSelected = c == _coloniaSeleccionada;
|
||
return ListTile(
|
||
dense: true,
|
||
title: Text(c, style: TextStyle(fontSize: 13,
|
||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||
color: isSelected ? AppColors.guindaPrimary : AppColors.negroTexto)),
|
||
trailing: isSelected
|
||
? const Icon(Icons.check_circle, color: AppColors.guindaPrimary, size: 18)
|
||
: null,
|
||
tileColor: isSelected ? AppColors.guindaPrimary.withOpacity(0.08) : null,
|
||
onTap: () {
|
||
setState(() {
|
||
_coloniaSeleccionada = c;
|
||
_coloniaData = getColonyByName(c);
|
||
});
|
||
},
|
||
);
|
||
},
|
||
),
|
||
),
|
||
if (_coloniaData != null) ...[
|
||
const SizedBox(height: 12),
|
||
Container(
|
||
padding: const EdgeInsets.all(12),
|
||
decoration: BoxDecoration(
|
||
color: AppColors.guindaPrimary.withOpacity(0.08),
|
||
borderRadius: BorderRadius.circular(8),
|
||
border: Border.all(color: AppColors.guindaPrimary.withOpacity(0.3))),
|
||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||
Text('Ruta asignada: ${_coloniaData!.routeId}',
|
||
style: const TextStyle(fontWeight: FontWeight.bold,
|
||
color: AppColors.guindaPrimary, fontSize: 13)),
|
||
Text('Horario: ${_coloniaData!.horarioEstimado}',
|
||
style: const TextStyle(color: AppColors.grisTexto, fontSize: 12)),
|
||
]),
|
||
),
|
||
],
|
||
const SizedBox(height: 24),
|
||
SizedBox(width: double.infinity, height: 50,
|
||
child: ElevatedButton.icon(
|
||
onPressed: _loading ? null : _guardar,
|
||
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.save),
|
||
label: Text(widget.editing != null ? 'ACTUALIZAR' : 'GUARDAR DOMICILIO',
|
||
style: const TextStyle(fontWeight: FontWeight.bold)))),
|
||
]),
|
||
),
|
||
);
|
||
}
|
||
|
||
@override void dispose() { _calleCtrl.dispose(); _aliasCtrl.dispose(); super.dispose(); }
|
||
}
|