Agrega PRIVACY.md, actualiza AGENTS.md

This commit is contained in:
Super User
2026-06-14 15:34:53 -04:00
parent 9ac9e9e953
commit 0df1bf90cf
20 changed files with 685 additions and 166 deletions

View File

@@ -1,9 +1,9 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
import 'package:fl_chart/fl_chart.dart';
import '../providers/factura_provider.dart';
import '../providers/configuracion_provider.dart';
import '../utils/currency_utils.dart';
class EstadisticasScreen extends StatefulWidget {
const EstadisticasScreen({super.key});
@@ -26,7 +26,6 @@ class _EstadisticasScreenState extends State<EstadisticasScreen> {
final facturaProv = context.watch<FacturaProvider>();
final configProv = context.watch<ConfiguracionProvider>();
final moneda = configProv.config?.moneda ?? 'USD';
final symbol = moneda == 'USD' ? '\$' : moneda == 'EUR' ? '' : moneda == 'MXN' ? 'MX\$' : '\$';
return Scaffold(
appBar: AppBar(title: const Text('Estadísticas')),
@@ -48,19 +47,33 @@ class _EstadisticasScreenState extends State<EstadisticasScreen> {
children: [
Text('Resumen $_year', style: Theme.of(context).textTheme.titleLarge),
const SizedBox(height: 8),
Card(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Gasto mensual actual', style: Theme.of(context).textTheme.titleSmall),
Text('$symbol${NumberFormat('#,##0.00').format(totalMes)}',
style: Theme.of(context).textTheme.headlineMedium),
],
Card(
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(12),
),
child: Icon(Icons.attach_money, color: Theme.of(context).colorScheme.primary, size: 28),
),
const SizedBox(width: 16),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Gasto mensual actual', style: Theme.of(context).textTheme.titleSmall),
const SizedBox(height: 4),
Text(CurrencyUtils.formatPrice(totalMes, moneda),
style: Theme.of(context).textTheme.headlineMedium),
],
),
],
),
),
),
),
),
const SizedBox(height: 20),
Text('Gasto mensual ($_year)', style: Theme.of(context).textTheme.titleMedium),
const SizedBox(height: 8),
@@ -86,7 +99,7 @@ class _EstadisticasScreenState extends State<EstadisticasScreen> {
);
}),
titlesData: FlTitlesData(
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, reservedSize: 40, getTitlesWidget: (v, _) => Text('$symbol${v.toInt()}', style: const TextStyle(fontSize: 10)))),
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, reservedSize: 40, getTitlesWidget: (v, _) => Text('${CurrencyUtils.getSymbol(moneda)}${v.toInt()}', style: const TextStyle(fontSize: 10)))),
bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, getTitlesWidget: (v, _) {
const meses = ['E', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D'];
return Text(meses[v.toInt()], style: const TextStyle(fontSize: 10));
@@ -109,27 +122,43 @@ class _EstadisticasScreenState extends State<EstadisticasScreen> {
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: gastoPorServicio.entries.map((e) {
children: gastoPorServicio.entries.toList().asMap().entries.map((entry) {
final i = entry.key;
final e = entry.value;
final total = gastoPorServicio.values.fold(0.0, (a, b) => a + b);
final pct = total > 0 ? e.value / total * 100 : 0.0;
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
SizedBox(width: 100, child: Text(e.key, style: const TextStyle(fontSize: 13))),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: pct / 100,
backgroundColor: Colors.grey[200],
minHeight: 12,
return TweenAnimationBuilder<double>(
tween: Tween(begin: 0, end: 1),
duration: Duration(milliseconds: 300 + i * 80),
curve: Curves.easeOutCubic,
builder: (context, value, child) {
return Opacity(
opacity: value,
child: Transform.translate(
offset: Offset(0, 12 * (1 - value)),
child: child,
),
);
},
child: Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
SizedBox(width: 100, child: Text(e.key, style: const TextStyle(fontSize: 13))),
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(4),
child: LinearProgressIndicator(
value: pct / 100,
backgroundColor: Colors.grey[200],
minHeight: 12,
),
),
),
),
const SizedBox(width: 8),
SizedBox(width: 70, child: Text('$symbol${NumberFormat('#,##0.00').format(e.value)}', style: const TextStyle(fontSize: 12), textAlign: TextAlign.right)),
],
const SizedBox(width: 8),
SizedBox(width: 70, child: Text(CurrencyUtils.formatPrice(e.value, moneda), style: const TextStyle(fontSize: 12), textAlign: TextAlign.right)),
],
),
),
);
}).toList(),