Avance de la aplicacion
This commit is contained in:
189
lib/screens/citizen/add_domicilio_screen.dart
Normal file
189
lib/screens/citizen/add_domicilio_screen.dart
Normal file
@@ -0,0 +1,189 @@
|
||||
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>();
|
||||
final routeData = getColonyByName(_coloniaSeleccionada!);
|
||||
final routeId = routeData?.routeId ?? 'RUTA-01';
|
||||
final horario = routeData?.horarioEstimado ?? 'Matutino (06:00-08:00)';
|
||||
|
||||
if (widget.editing != null) {
|
||||
// Editar existente — eliminar y volver a insertar
|
||||
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);
|
||||
}
|
||||
|
||||
@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(); }
|
||||
}
|
||||
Reference in New Issue
Block a user