Agrega PRIVACY.md, actualiza AGENTS.md
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../providers/servicio_provider.dart';
|
||||
import '../providers/factura_provider.dart';
|
||||
import '../providers/configuracion_provider.dart';
|
||||
import '../widgets/stat_card.dart';
|
||||
import '../utils/currency_utils.dart';
|
||||
import 'servicios_screen.dart';
|
||||
import 'facturas_screen.dart';
|
||||
import 'calendario_screen.dart';
|
||||
@@ -37,13 +37,12 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
final servicioProv = context.watch<ServicioProvider>();
|
||||
final configProv = context.watch<ConfiguracionProvider>();
|
||||
final moneda = configProv.config?.moneda ?? 'USD';
|
||||
final symbol = moneda == 'USD' ? '\$' : moneda == 'EUR' ? '€' : moneda == 'MXN' ? 'MX\$' : '\$';
|
||||
|
||||
final pendientes = facturaProv.facturas.where((f) => f.estado == 'Pendiente').length;
|
||||
final vencidas = facturaProv.facturasVencidas.length;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('HogarControl'), centerTitle: true, actions: [
|
||||
appBar: AppBar(title: const Text('Factura del Hogar'), centerTitle: true, actions: [
|
||||
IconButton(icon: const Icon(Icons.settings), onPressed: () => Navigator.push(context, MaterialPageRoute(builder: (_) => const ConfiguracionScreen()))),
|
||||
]),
|
||||
body: RefreshIndicator(
|
||||
@@ -58,6 +57,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
value: '$pendientes',
|
||||
icon: Icons.pending_actions,
|
||||
color: Colors.orange,
|
||||
delayMs: 50,
|
||||
)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: StatCard(
|
||||
@@ -65,6 +65,7 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
value: '$vencidas',
|
||||
icon: Icons.warning_rounded,
|
||||
color: Colors.red,
|
||||
delayMs: 100,
|
||||
)),
|
||||
],
|
||||
),
|
||||
@@ -76,36 +77,74 @@ class _DashboardScreenState extends State<DashboardScreen> {
|
||||
value: facturaProv.facturas.where((f) => f.estado == 'Pagada').length.toString(),
|
||||
icon: Icons.check_circle,
|
||||
color: Colors.green,
|
||||
delayMs: 150,
|
||||
)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: StatCard(
|
||||
title: 'Total gastado',
|
||||
value: '$symbol${NumberFormat('#,##0.00').format(facturaProv.facturas.where((f) => f.estado == 'Pagada').fold(0.0, (sum, f) => sum + f.monto))}',
|
||||
value: CurrencyUtils.formatPrice(facturaProv.facturas.where((f) => f.estado == 'Pagada').fold(0.0, (sum, f) => sum + f.monto), moneda),
|
||||
icon: Icons.attach_money,
|
||||
color: Colors.blue,
|
||||
delayMs: 200,
|
||||
)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text('Próximos vencimientos', style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
Icon(Icons.event_note, size: 20, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(width: 8),
|
||||
Text('Próximos vencimientos', style: Theme.of(context).textTheme.titleMedium),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
...facturaProv.facturas
|
||||
.where((f) => f.estado == 'Pendiente')
|
||||
.take(5)
|
||||
.map((f) {
|
||||
.toList()
|
||||
.asMap()
|
||||
.entries
|
||||
.map((entry) {
|
||||
final i = entry.key;
|
||||
final f = entry.value;
|
||||
final servicio = servicioProv.servicios.where((s) => s.id == f.servicioId).firstOrNull;
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Color(servicio?.color ?? 0xFF6200EE),
|
||||
child: Text(servicio?.nombre.substring(0, 2).toUpperCase() ?? '??',
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12)),
|
||||
),
|
||||
title: Text(servicio?.nombre ?? 'Desconocido'),
|
||||
subtitle: Text('Ven: ${f.fechaVencimiento} $symbol${NumberFormat('#,##0.00').format(f.monto)}'),
|
||||
trailing: TextButton(
|
||||
onPressed: () => facturaProv.marcarPagada(f.id!),
|
||||
child: const Text('Pagar'),
|
||||
return TweenAnimationBuilder<double>(
|
||||
tween: Tween(begin: 0, end: 1),
|
||||
duration: Duration(milliseconds: 350 + i * 80),
|
||||
curve: Curves.easeOutCubic,
|
||||
builder: (context, value, child) {
|
||||
return Opacity(
|
||||
opacity: value,
|
||||
child: Transform.translate(
|
||||
offset: Offset(0, 16 * (1 - value)),
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
child: ListTile(
|
||||
leading: CircleAvatar(
|
||||
backgroundColor: Color(servicio?.color ?? 0xFF6200EE),
|
||||
child: Text(servicio?.nombre.substring(0, 2).toUpperCase() ?? '??',
|
||||
style: const TextStyle(color: Colors.white, fontSize: 12)),
|
||||
),
|
||||
title: Text(servicio?.nombre ?? 'Desconocido'),
|
||||
subtitle: Text('Vence: ${f.fechaVencimiento}'),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(CurrencyUtils.formatPrice(f.monto, moneda),
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Theme.of(context).colorScheme.primary)),
|
||||
const SizedBox(width: 4),
|
||||
IconButton(
|
||||
icon: Icon(Icons.check_circle_outline, color: Theme.of(context).colorScheme.primary),
|
||||
onPressed: () => facturaProv.marcarPagada(f.id!),
|
||||
tooltip: 'Pagar',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user