Update: 2026-08-03 11:32:12

This commit is contained in:
Hamza-Ayed
2026-08-03 11:32:12 +03:00
parent 2b9f696372
commit 0334f9881f
40 changed files with 86899 additions and 84841 deletions
@@ -60,6 +60,9 @@ class FinancialV2Page extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildMainFinancialStats(ctrl.stats, cs),
const SizedBox(height: 32),
_buildSectionTitle('محفظة سيرو', cs),
_buildSiroWalletSection(ctrl.walletSummary, cs),
const SizedBox(height: 24),
_buildSectionTitle('طرق الدفع', cs),
_buildPaymentMethodBreakdown(ctrl.stats, cs),
@@ -78,6 +81,116 @@ class FinancialV2Page extends StatelessWidget {
);
}
/// تنسيق مبلغ بفواصل آلاف وخانتين عشريتين.
/// بلا رمز عملة عمداً: هذا النشر أردني بينما بطاقات هذه الشاشة الأخرى
/// ما زالت تكتب "ج.م" ثابتة — راجع صحّتها قبل توحيد الرمز.
String _money(double v) {
final neg = v < 0;
final parts = v.abs().toStringAsFixed(2).split('.');
final digits = parts[0];
final buf = StringBuffer();
for (int i = 0; i < digits.length; i++) {
if (i > 0 && (digits.length - i) % 3 == 0) buf.write(',');
buf.write(digits[i]);
}
return '${neg ? '-' : ''}$buf.${parts[1]}';
}
/// محفظة سيرو من خادم المدفوعات: الشهر الجاري مقابل الشهر السابق،
/// والإجمالي التراكمي، مع فصل الإيداع عن الصرف.
Widget _buildSiroWalletSection(
Map<String, dynamic> summary, ColorScheme cs) {
if (summary.isEmpty) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: cs.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16),
border: Border.all(color: cs.outline),
),
child: Row(
children: [
Icon(Icons.account_balance_wallet_outlined,
color: cs.onSurfaceVariant, size: 18),
const SizedBox(width: 10),
Expanded(
child: Text(
'تعذّر جلب ملخّص المحفظة من خادم المدفوعات',
style: TextStyle(color: cs.onSurfaceVariant, fontSize: 13),
),
),
],
),
);
}
final mtd = (summary['month_to_date'] as Map?) ?? {};
final allTime = (summary['all_time'] as Map?) ?? {};
final growth = summary['growth_percent'];
double n(dynamic v) => double.tryParse('${v ?? 0}') ?? 0;
return Column(
children: [
Row(
children: [
Expanded(
child: _buildFinancialCard(
'صافي هذا الشهر',
_money(n(mtd['net'])),
Icons.calendar_month_rounded,
cs.primary,
cs,
// المؤشّر يظهر فقط عند وجود شهر سابق يُقارن به
subtitle: growth == null
? null
: '${n(growth) >= 0 ? '▲' : '▼'} ${n(growth).abs().toStringAsFixed(1)}% عن الشهر السابق',
subtitleColor: growth == null
? null
: (n(growth) >= 0 ? cs.success : cs.danger),
),
),
const SizedBox(width: 12),
Expanded(
child: _buildFinancialCard(
'الإجمالي التراكمي',
_money(n(allTime['net'])),
Icons.savings_rounded,
cs.tertiary,
cs,
),
),
],
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: _buildFinancialCard(
'إيداع هذا الشهر',
_money(n(mtd['credits'])),
Icons.south_west_rounded,
cs.success,
cs,
subtitle: '${mtd['tx_count'] ?? 0} حركة',
),
),
const SizedBox(width: 12),
Expanded(
child: _buildFinancialCard(
'صرف هذا الشهر',
_money(n(mtd['debits'])),
Icons.north_east_rounded,
cs.warning,
cs,
),
),
],
),
],
);
}
Widget _buildSectionTitle(String title, ColorScheme cs) {
return Padding(
padding: const EdgeInsets.only(bottom: 16),
@@ -134,7 +247,7 @@ class FinancialV2Page extends StatelessWidget {
Widget _buildFinancialCard(
String title, String value, IconData icon, Color color, ColorScheme cs,
{bool isSmall = false}) {
{bool isSmall = false, String? subtitle, Color? subtitleColor}) {
return Container(
padding: EdgeInsets.all(isSmall ? 16 : 24),
decoration: BoxDecoration(
@@ -170,6 +283,14 @@ class FinancialV2Page extends StatelessWidget {
color: cs.onSurface,
fontSize: isSmall ? 18 : 24,
fontWeight: FontWeight.bold)),
if (subtitle != null) ...[
const SizedBox(height: 4),
Text(subtitle,
style: TextStyle(
color: subtitleColor ?? cs.onSurfaceVariant,
fontSize: 11,
fontWeight: FontWeight.w600)),
],
],
),
),