Files
home-control/lib/screens/configuracion_screen.dart
Super User bbd20f66da Facturas recurrentes, edición, padding, y política de privacidad
- Servicio: nuevo campo esRecurrente + migración DB v2
- Al marcar pagada una factura recurrente se genera la siguiente
- Editar facturas existentes desde CrearFacturaScreen
- Nuevo método actualizarFactura en FacturaProvider
- padding inferior en listas de facturas y servicios (último item visible)
- Nota de factura visible en subtítulo
- Filtro Vencidas corregido
- Monto pendiente total visible en dashboard
- Botón undo para revertir factura pagada
- Configuración de release signing (keystore)
- Pantalla de política de privacidad en la app + PRIVACY_POLICY.md
2026-06-15 21:45:59 -04:00

104 lines
3.8 KiB
Dart

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models/configuracion.dart';
import '../providers/configuracion_provider.dart';
import '../utils/currency_utils.dart';
import 'privacy_policy_screen.dart';
class ConfiguracionScreen extends StatefulWidget {
const ConfiguracionScreen({super.key});
@override
State<ConfiguracionScreen> createState() => _ConfiguracionScreenState();
}
class _ConfiguracionScreenState extends State<ConfiguracionScreen> {
late List<bool> _diasSeleccionados;
late String _moneda;
final List<Map<String, dynamic>> _opcionesDias = [
{'label': '7 días antes', 'value': 7},
{'label': '3 días antes', 'value': 3},
{'label': '1 día antes', 'value': 1},
{'label': 'Día de vencimiento', 'value': 0},
];
final List<CurrencyInfo> _monedas = CurrencyUtils.allCurrencies;
@override
void initState() {
super.initState();
final config = context.read<ConfiguracionProvider>().config;
final dias = config?.diasRecordatorio ?? '7,3,1,0';
final lista = dias.split(',').map((e) => int.tryParse(e.trim()) ?? 0).toList();
_diasSeleccionados = _opcionesDias.map((o) => lista.contains(o['value'])).toList();
_moneda = config?.moneda ?? 'USD';
}
@override
Widget build(BuildContext context) {
final provider = context.read<ConfiguracionProvider>();
return Scaffold(
appBar: AppBar(title: const Text('Configuración')),
body: ListView(
padding: const EdgeInsets.all(16),
children: [
Text('Recordatorios', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
...List.generate(_opcionesDias.length, (i) {
return CheckboxListTile(
title: Text(_opcionesDias[i]['label'] as String),
value: _diasSeleccionados[i],
onChanged: (v) {
setState(() => _diasSeleccionados[i] = v ?? false);
},
);
}),
const SizedBox(height: 20),
Text('Moneda', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
DropdownButtonFormField<String>(
value: _moneda,
decoration: const InputDecoration(border: OutlineInputBorder()),
items: _monedas.map((m) => DropdownMenuItem(value: m.code, child: Text(CurrencyUtils.getDisplayName(m.code)))).toList(),
onChanged: (v) => setState(() => _moneda = v!),
),
const SizedBox(height: 32),
const SizedBox(height: 16),
ListTile(
leading: const Icon(Icons.privacy_tip_outlined),
title: const Text('Política de privacidad'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const PrivacyPolicyScreen())),
),
const SizedBox(height: 16),
FilledButton(
onPressed: () async {
final diasStr = _opcionesDias
.asMap()
.entries
.where((e) => _diasSeleccionados[e.key])
.map((e) => e.value['value'].toString())
.join(',');
final config = Configuracion(
id: provider.config?.id,
diasRecordatorio: diasStr.isEmpty ? '0' : diasStr,
tema: provider.config?.tema ?? 'claro',
moneda: _moneda,
);
await provider.guardarConfiguracion(config);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Configuración guardada')),
);
}
},
child: const Text('Guardar configuración'),
),
],
),
);
}
}