From 1717cd5e2b9a53aecb2a9170f94c2d928b696c5f Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Fri, 5 Dec 2025 10:53:36 +0530 Subject: [PATCH] added mytext --- .../dashbaord/collection_dashboard_card.dart | 374 +++++++++--------- .../dashbaord/purchase_invoice_dashboard.dart | 178 ++++----- 2 files changed, 248 insertions(+), 304 deletions(-) diff --git a/lib/helpers/widgets/dashbaord/collection_dashboard_card.dart b/lib/helpers/widgets/dashbaord/collection_dashboard_card.dart index 53fb95c..afc5556 100644 --- a/lib/helpers/widgets/dashbaord/collection_dashboard_card.dart +++ b/lib/helpers/widgets/dashbaord/collection_dashboard_card.dart @@ -1,6 +1,5 @@ -// collections_health_widget.dart - import 'package:flutter/material.dart'; +import 'package:on_field_work/helpers/widgets/my_text.dart'; // --- MAIN WIDGET FILE --- class CollectionsHealthWidget extends StatelessWidget { @@ -10,6 +9,7 @@ class CollectionsHealthWidget extends StatelessWidget { const double totalDue = 34190.0; const double totalCollected = 5000.0; const double totalValue = totalDue + totalCollected; + // Calculate Pending Percentage for Gauge final double pendingPercentage = totalValue > 0 ? totalDue / totalValue : 0.0; @@ -17,12 +17,10 @@ class CollectionsHealthWidget extends StatelessWidget { // 1. MAIN CARD CONTAINER (White Theme) return Container( decoration: BoxDecoration( - // Main card background color: WHITE color: Colors.white, borderRadius: BorderRadius.circular(5), boxShadow: [ BoxShadow( - // Lighter shadow for white background color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 5), @@ -60,7 +58,7 @@ class CollectionsHealthWidget extends StatelessWidget { ], ), const SizedBox(height: 20), - // 3. NEW: AGING ANALYSIS SECTION + // 3. AGING ANALYSIS SECTION _buildAgingAnalysis(), ], ), @@ -69,19 +67,24 @@ class CollectionsHealthWidget extends StatelessWidget { // --- HELPER METHOD 1: HEADER --- Widget _buildHeader() { - return Row( - children: const [ - Text( - 'Collections Health Overview', - style: TextStyle( - // Text color: Dark for contrast on white background - color: Colors.black87, - fontSize: 18, - fontWeight: FontWeight.bold, - ), + return Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + MyText.bodyMedium( + 'Collections Health Overview', + fontWeight: 700, + ), + const SizedBox(height: 2), + MyText.bodySmall( + 'View your collection health data.', + color: Colors.grey, + ), + ], ), - ], - ); + ), + ]); } // --- HELPER METHOD 2: LEFT SECTION (CHARTS) --- @@ -97,38 +100,33 @@ class CollectionsHealthWidget extends StatelessWidget { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - // Top: Gauge Chart and Due Amount + // Top: Gauge Chart Row( children: [ - // Use White-Theme Gauge Placeholder with calculated percentage _GaugeChartPlaceholder( - backgroundColor: Colors.white, - pendingPercentage: pendingPercentage), + backgroundColor: Colors.white, + pendingPercentage: pendingPercentage, + ), const SizedBox(width: 12), ], ), - const SizedBox(height: 20), + + // Total Due + Summary Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( + MyText.bodyLarge( '₹${totalDue.toStringAsFixed(0)} DUE', - style: const TextStyle( - // Text color: Dark for contrast - color: Colors.black87, - fontSize: 22, - fontWeight: FontWeight.bold, - ), + fontWeight: 700, ), const SizedBox(height: 4), - Text( + MyText.bodySmall( '• Pending ($pendingPercentStr%) • ₹${totalCollected.toStringAsFixed(0)} Collected', - // Sub-text color: Lighter dark color - style: const TextStyle(color: Colors.black54, fontSize: 12), + color: Colors.black54, ), ], ), @@ -136,6 +134,7 @@ class CollectionsHealthWidget extends StatelessWidget { ], ), const SizedBox(height: 20), + // Bottom: Timeline Charts (Trend Analysis) Row( children: [ @@ -144,34 +143,40 @@ class CollectionsHealthWidget extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text('Expected Collections Trend', - // Text color: Dark for contrast - style: TextStyle(color: Colors.black87, fontSize: 12)), + MyText.bodySmall( + 'Expected Collections Trend', + ), const SizedBox(height: 8), - _TimelineChartPlaceholder( - isBar: true, - barColor: const Color(0xFF2196F3)), // Blue Bar Chart - const Text('Week 16 Nov 2025', - style: TextStyle(color: Colors.black54, fontSize: 10)), + const _TimelineChartPlaceholder( + isBar: true, + barColor: Color(0xFF2196F3), + ), + MyText.bodySmall( + 'Week 16 Nov 2025', + color: Colors.black54, + ), ], ), ), const SizedBox(width: 10), - // Collection Rate Trend (Area Chart Placeholder for Analysis) + + // Collection Rate Trend (Area Chart Placeholder) Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text('Collection Rate Trend', - // Text color: Dark for contrast - style: TextStyle(color: Colors.black87, fontSize: 12)), + MyText.bodySmall( + 'Collection Rate Trend', + ), const SizedBox(height: 8), - _TimelineChartPlaceholder( - isBar: false, - areaColor: - const Color(0xFF4CAF50)), // Green Area Chart (Rate) - const Text('Week 14 Nov 2025', - style: TextStyle(color: Colors.black54, fontSize: 10)), + const _TimelineChartPlaceholder( + isBar: false, + areaColor: Color(0xFF4CAF50), + ), + MyText.bodySmall( + 'Week 14 Nov 2025', + color: Colors.black54, + ), ], ), ), @@ -188,7 +193,7 @@ class CollectionsHealthWidget extends StatelessWidget { return Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - // Metric Card 1: Top Client (From Invoice 1) + // Metric Card 1: Top Client _buildMetricCard( title: 'Top Client Balance', value: 'Peninsula Land Limited', @@ -197,7 +202,8 @@ class CollectionsHealthWidget extends StatelessWidget { isDetailed: true, ), const SizedBox(height: 10), - // Metric Card 2 (NEW): Total Collected (From Invoice 2) + + // Metric Card 2: Total Collected (YTD) _buildMetricCard( title: 'Total Collected (YTD)', value: '₹${totalCollected.toStringAsFixed(0)}', @@ -206,7 +212,8 @@ class CollectionsHealthWidget extends StatelessWidget { isDetailed: false, ), const SizedBox(height: 10), - // Metric Card 3: Days Sales Outstanding (DSO) (Analytical Placeholder) + + // Metric Card 3: DSO _buildMetricCard( title: 'Days Sales Outstanding (DSO)', value: '45 Days', @@ -215,7 +222,8 @@ class CollectionsHealthWidget extends StatelessWidget { isDetailed: false, ), const SizedBox(height: 10), - // Metric Card 4: Last Metric Card in the image (Repeating rate for layout) + + // Metric Card 4: Bad Debt Ratio _buildMetricCard( title: 'Bad Debt Ratio', value: '0.8%', @@ -227,7 +235,7 @@ class CollectionsHealthWidget extends StatelessWidget { ); } - // --- HELPER METHOD 4: METRIC CARD WIDGET (Unchanged) --- + // --- HELPER METHOD 4: METRIC CARD WIDGET --- Widget _buildMetricCard({ required String title, required String value, @@ -238,60 +246,39 @@ class CollectionsHealthWidget extends StatelessWidget { return Container( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), decoration: BoxDecoration( - // Light grey background for card separation on white theme color: const Color(0xFFF5F5F5), borderRadius: BorderRadius.circular(5), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( + MyText.bodySmall( title, - // Title text color: Soft dark grey - style: const TextStyle(color: Colors.black54, fontSize: 10), + color: Colors.black54, ), const SizedBox(height: 2), - // Conditional rendering for the detailed vs simple card structure if (isDetailed) ...[ - Text( - value, // Client Name - style: const TextStyle( - // Value text color: Dark - color: Colors.black87, - fontSize: 12, - fontWeight: FontWeight.w600, - ), + MyText.bodySmall( + value, + fontWeight: 600, ), - Text( - subValue, // Due Amount - style: TextStyle( - // Color remains dynamic (Red/Green/etc.) - color: valueColor, - fontSize: 16, - fontWeight: FontWeight.bold, - ), + MyText.bodyMedium( + subValue, + color: valueColor, + fontWeight: 700, ), ] else Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + MyText.bodySmall( value, - style: const TextStyle( - // Value text color: Dark - color: Colors.black87, - fontSize: 14, - fontWeight: FontWeight.w600, - ), + fontWeight: 600, ), - Text( + MyText.bodySmall( subValue, - style: TextStyle( - // Color remains dynamic (Red/Green/etc.) - color: valueColor, - fontSize: 14, - fontWeight: FontWeight.w600, - ), + color: valueColor, + fontWeight: 600, ), ], ), @@ -301,9 +288,8 @@ class CollectionsHealthWidget extends StatelessWidget { } // --- NEW HELPER METHOD: AGING ANALYSIS --- - // --- NEW HELPER METHOD: AGING ANALYSIS (MODIFIED) --- Widget _buildAgingAnalysis() { - // Hardcoded data based on the JSON analysis + // Hardcoded data const double due0to20Days = 0.0; const double due20to45Days = 34190.0; const double due45to90Days = 0.0; @@ -314,30 +300,38 @@ class CollectionsHealthWidget extends StatelessWidget { // Define buckets with their risk color final List buckets = [ - AgingBucketData('0-20 Days', due0to20Days, - const Color(0xFF4CAF50)), // Green (Low Risk) - AgingBucketData('20-45 Days', due20to45Days, - const Color(0xFFFF9800)), // Orange (Medium Risk) - AgingBucketData('45-90 Days', due45to90Days, - const Color(0xFFF44336).withOpacity(0.7)), // Light Red (High Risk) - AgingBucketData('> 90 Days', dueOver90Days, - const Color(0xFFF44336)), // Dark Red (Very High Risk) + AgingBucketData( + '0-20 Days', + due0to20Days, + const Color(0xFF4CAF50), // Green (Low Risk) + ), + AgingBucketData( + '20-45 Days', + due20to45Days, + const Color(0xFFFF9800), // Orange (Medium Risk) + ), + AgingBucketData( + '45-90 Days', + due45to90Days, + const Color(0xFFF44336).withOpacity(0.7), // Light Red + ), + AgingBucketData( + '> 90 Days', + dueOver90Days, + const Color(0xFFF44336), // Dark Red + ), ]; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( + MyText.bodyMedium( 'Outstanding Collections Aging Analysis', - style: TextStyle( - color: Colors.black87, - fontSize: 14, - fontWeight: FontWeight.bold, - ), + fontWeight: 700, ), const SizedBox(height: 10), - // NEW: STACKED BAR VISUALIZATION + // Stacked bar visualization _AgingStackedBar( buckets: buckets, totalOutstanding: totalOutstanding, @@ -345,21 +339,25 @@ class CollectionsHealthWidget extends StatelessWidget { const SizedBox(height: 15), - // NEW: LEGEND/BUCKET DETAILS (Replaces the old _buildAgingBucket layout) + // Legend / Bucket details Wrap( spacing: 12, runSpacing: 8, children: buckets - .map((bucket) => _buildAgingLegendItem( - bucket.title, bucket.amount, bucket.color)) + .map( + (bucket) => _buildAgingLegendItem( + bucket.title, + bucket.amount, + bucket.color, + ), + ) .toList(), ), ], ); } -// Keep the old _buildAgingBucket helper and rename it to a legend item -// This is more efficient than recreating the logic + // Legend item for aging buckets Widget _buildAgingLegendItem(String title, double amount, Color color) { return Row( mainAxisSize: MainAxisSize.min, @@ -373,24 +371,25 @@ class CollectionsHealthWidget extends StatelessWidget { ), ), const SizedBox(width: 6), - Text( - '${title}: ₹${amount.toStringAsFixed(0)}', - style: const TextStyle(color: Colors.black87, fontSize: 12), + MyText.bodySmall( + '$title: ₹${amount.toStringAsFixed(0)}', ), ], ); } } -// --- CUSTOM PAINTERS / PLACEHOLDERS (Modified to accept percentage) --- +// --- CUSTOM PAINTERS / PLACEHOLDERS --- // Placeholder for the Semi-Circle Gauge Chart class _GaugeChartPlaceholder extends StatelessWidget { final Color backgroundColor; final double pendingPercentage; - const _GaugeChartPlaceholder( - {required this.backgroundColor, required this.pendingPercentage}); + const _GaugeChartPlaceholder({ + required this.backgroundColor, + required this.pendingPercentage, + }); @override Widget build(BuildContext context) { @@ -402,37 +401,22 @@ class _GaugeChartPlaceholder extends StatelessWidget { // BACKGROUND GAUGE CustomPaint( size: const Size(120, 70), - // Pass the pending percentage to the painter painter: _SemiCirclePainter( - canvasColor: backgroundColor, - pendingPercentage: pendingPercentage), + canvasColor: backgroundColor, + pendingPercentage: pendingPercentage, + ), ), - // CENTER CIRCLE - Positioned( - bottom: 0, - left: 30, - child: Container( - height: 60, - width: 60, - decoration: BoxDecoration( - // Center circle background is the same as the main card background (white) - color: backgroundColor, - shape: BoxShape.circle, - border: Border.all(color: Colors.black.withOpacity(0.1)), - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - // Icon color: Dark - Icon(Icons.work, color: Colors.black87, size: 20), - SizedBox(height: 2), - Text( - 'RISK LEVEL', - // Text color: Soft dark grey - style: TextStyle(color: Colors.black54, fontSize: 8), - ), - ], + // CENTER TEXT + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: const EdgeInsets.only(bottom: 8), + child: FittedBox( + child: MyText.bodySmall( + 'RISK LEVEL', + fontWeight: 600, + ), ), ), ), @@ -442,75 +426,82 @@ class _GaugeChartPlaceholder extends StatelessWidget { } } -// Painter for the semi-circular gauge chart visualization (Simplified) +// Painter for the semi-circular gauge chart visualization class _SemiCirclePainter extends CustomPainter { final Color canvasColor; final double pendingPercentage; - _SemiCirclePainter( - {required this.canvasColor, required this.pendingPercentage}); + _SemiCirclePainter({ + required this.canvasColor, + required this.pendingPercentage, + }); @override void paint(Canvas canvas, Size size) { final rect = Rect.fromCircle( - center: Offset(size.width / 2, size.height), radius: size.width / 2); + center: Offset(size.width / 2, size.height), + radius: size.width / 2, + ); - // Radians for a semi-circle const double totalArc = 3.14159; - // Calculate the sweep angles final double pendingSweepAngle = totalArc * pendingPercentage; final double collectedSweepAngle = totalArc * (1.0 - pendingPercentage); - // Background Arc (Full semi-circle) + // Background Arc final backgroundPaint = Paint() - // Background arc is a soft grey on a white theme ..color = Colors.black.withOpacity(0.1) ..style = PaintingStyle.stroke ..strokeWidth = 10; - canvas.drawArc(rect, totalArc, totalArc, false, - backgroundPaint); // Start at 180 deg (Pi) + canvas.drawArc(rect, totalArc, totalArc, false, backgroundPaint); - // Pending Arc (Red/Orange segment) + // Pending Arc final pendingPaint = Paint() - ..color = const Color(0xFFF44336) // Red ..style = PaintingStyle.stroke ..strokeWidth = 10 - ..shader = const LinearGradient(colors: [ - Color(0xFFFF9800), // Orange - Color(0xFFF44336), // Red - ]).createShader(rect); - // Start angle: 3.14 (180 deg) + ..shader = const LinearGradient( + colors: [ + Color(0xFFFF9800), + Color(0xFFF44336), + ], + ).createShader(rect); canvas.drawArc(rect, totalArc, pendingSweepAngle, false, pendingPaint); - // Collected Arc (Green segment) + // Collected Arc final collectedPaint = Paint() - ..color = const Color(0xFF4CAF50) // Green + ..color = const Color(0xFF4CAF50) ..style = PaintingStyle.stroke ..strokeWidth = 10; - // Start angle: 3.14 + pendingSweepAngle - canvas.drawArc(rect, totalArc + pendingSweepAngle, collectedSweepAngle, - false, collectedPaint); + canvas.drawArc( + rect, + totalArc + pendingSweepAngle, + collectedSweepAngle, + false, + collectedPaint, + ); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } -// Placeholder for the Bar/Area Charts (Unchanged) +// Placeholder for the Bar/Area Charts class _TimelineChartPlaceholder extends StatelessWidget { final bool isBar; final Color? barColor; final Color? areaColor; - const _TimelineChartPlaceholder( - {required this.isBar, this.barColor, this.areaColor}); + const _TimelineChartPlaceholder({ + required this.isBar, + this.barColor, + this.areaColor, + }); @override Widget build(BuildContext context) { return Container( height: 50, width: double.infinity, - color: Colors.transparent, // Transparent container for visual space + color: Colors.transparent, child: isBar ? _BarChartVisual(barColor: barColor!) : _AreaChartVisual(areaColor: areaColor!), @@ -528,12 +519,12 @@ class _BarChartVisual extends StatelessWidget { return Row( crossAxisAlignment: CrossAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - _Bar(0.4, barColor), - _Bar(0.7, barColor), - _Bar(1.0, barColor), - _Bar(0.6, barColor), - _Bar(0.8, barColor), + children: const [ + _Bar(0.4), + _Bar(0.7), + _Bar(1.0), + _Bar(0.6), + _Bar(0.8), ], ); } @@ -541,17 +532,18 @@ class _BarChartVisual extends StatelessWidget { class _Bar extends StatelessWidget { final double heightFactor; - final Color color; - const _Bar(this.heightFactor, this.color); + const _Bar(this.heightFactor); @override Widget build(BuildContext context) { + // Bar color is taken from parent via DefaultTextStyle/Theme if needed; + // you can wrap with Theme if you want dynamic colors. return Container( width: 8, height: 50 * heightFactor, decoration: BoxDecoration( - color: color, + color: Colors.grey.shade400, borderRadius: BorderRadius.circular(5), ), ); @@ -587,7 +579,6 @@ class _AreaChartPainter extends CustomPainter { Offset(size.width, size.height * 0.4), ]; - // Path for the area final path = Path() ..moveTo(points.first.dx, size.height) ..lineTo(points.first.dx, points.first.dy); @@ -597,20 +588,18 @@ class _AreaChartPainter extends CustomPainter { path.lineTo(points.last.dx, size.height); path.close(); - // Paint for the gradient fill final areaPaint = Paint() ..shader = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ - areaColor.withOpacity(0.5), // Lighter opacity on white theme - areaColor.withOpacity(0.0), // Transparent + areaColor.withOpacity(0.5), + areaColor.withOpacity(0.0), ], ).createShader(Rect.fromLTWH(0, 0, size.width, size.height)) ..style = PaintingStyle.fill; canvas.drawPath(path, areaPaint); - // Paint for the line stroke final linePaint = Paint() ..color = areaColor ..strokeWidth = 2 @@ -622,7 +611,7 @@ class _AreaChartPainter extends CustomPainter { bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } -// --- NEW DATA MODEL --- +// --- DATA MODEL --- class AgingBucketData { final String title; final double amount; @@ -631,7 +620,7 @@ class AgingBucketData { AgingBucketData(this.title, this.amount, this.color); } -// --- NEW HELPER WIDGET: STACKED BAR VISUAL --- +// --- STACKED BAR VISUAL --- class _AgingStackedBar extends StatelessWidget { final List buckets; final double totalOutstanding; @@ -650,21 +639,20 @@ class _AgingStackedBar extends StatelessWidget { color: Colors.grey[200], borderRadius: BorderRadius.circular(8), ), - child: const Center( - child: Text( + child: Center( + child: MyText.bodySmall( 'No Outstanding Collections', - style: TextStyle(color: Colors.black54, fontSize: 10), + color: Colors.black54, ), ), ); } - // Build the segments for the Row final List segments = buckets.where((b) => b.amount > 0).map((bucket) { final double flexValue = bucket.amount / totalOutstanding; return Expanded( - flex: (flexValue * 100).toInt(), // Use a scaled integer for flex + flex: (flexValue * 100).toInt(), child: Container( height: 16, color: bucket.color, diff --git a/lib/helpers/widgets/dashbaord/purchase_invoice_dashboard.dart b/lib/helpers/widgets/dashbaord/purchase_invoice_dashboard.dart index 35eda5e..218a5d0 100644 --- a/lib/helpers/widgets/dashbaord/purchase_invoice_dashboard.dart +++ b/lib/helpers/widgets/dashbaord/purchase_invoice_dashboard.dart @@ -1,6 +1,8 @@ // lib/widgets/purchase_invoice_dashboard.dart import 'dart:convert'; import 'package:flutter/material.dart'; +import 'package:on_field_work/helpers/widgets/my_text.dart'; +import 'package:on_field_work/helpers/widgets/my_spacing.dart'; /// ======================= /// INTERNAL DUMMY DATA @@ -111,7 +113,7 @@ class CompactPurchaseInvoiceDashboard extends StatelessWidget { padding: const EdgeInsets.all(mainPadding), decoration: BoxDecoration( color: Colors.white, - borderRadius: BorderRadius.circular(10), // Slightly rounder corners + borderRadius: BorderRadius.circular(5), // Slightly rounder corners boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.08), // Softer, more subtle shadow @@ -420,14 +422,11 @@ class _SectionTitle extends StatelessWidget { @override Widget build(BuildContext context) { - return Text( + return MyText.bodySmall( title, - style: TextStyle( - color: Colors.grey.shade700, - fontSize: 14, - fontWeight: FontWeight.bold, - letterSpacing: 0.5, - ), + color: Colors.grey.shade700, + fontWeight: 700, + letterSpacing: 0.5, ); } } @@ -437,14 +436,21 @@ class _DashboardHeader extends StatelessWidget { @override Widget build(BuildContext context) { - return const Text( - 'Purchase Invoice Dashboard ', - style: TextStyle( - color: Colors.black, - fontSize: 20, - fontWeight: FontWeight.w700, - ), - ); + return Row(mainAxisAlignment: MainAxisAlignment.start, children: [ + Expanded( + child: + Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + MyText.bodyMedium( + 'Purchase Invoice ', + fontWeight: 700, + ), + SizedBox(height: 2), + MyText.bodySmall( + 'View your purchase invoice data.', + color: Colors.grey, + ), + ])) + ]); } } @@ -464,7 +470,7 @@ class _TotalValueCard extends StatelessWidget { padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 12), decoration: BoxDecoration( color: const Color(0xFFE3F2FD), // Lighter Blue - borderRadius: BorderRadius.circular(10), + borderRadius: BorderRadius.circular(5), border: Border.all(color: const Color(0xFFBBDEFB), width: 1), ), child: Column( @@ -473,14 +479,11 @@ class _TotalValueCard extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( + MyText.bodySmall( 'TOTAL PROFORMA VALUE (₹)', - style: TextStyle( - color: Colors.blue.shade800, - fontSize: 10, - fontWeight: FontWeight.w700, - letterSpacing: 1.0, - ), + color: Colors.blue.shade800, + fontWeight: 700, + letterSpacing: 1.0, ), Icon( Icons.account_balance_wallet_outlined, @@ -489,24 +492,15 @@ class _TotalValueCard extends StatelessWidget { ), ], ), - const SizedBox(height: 8), - Text( - // Format number with commas if needed for large values + MySpacing.height(8), + MyText.bodyMedium( totalProformaAmount.toStringAsFixed(0), - style: const TextStyle( - color: Colors.black, - fontSize: 32, - fontWeight: FontWeight.w900, - ), ), - const SizedBox(height: 4), - Text( + MySpacing.height(4), + MyText.bodySmall( 'Over $totalCount Total Invoices', - style: TextStyle( - color: Colors.blueGrey.shade600, - fontSize: 12, - fontWeight: FontWeight.w500, - ), + color: Colors.blueGrey.shade600, + fontWeight: 500, ), ], ), @@ -589,7 +583,7 @@ class _CondensedMetricCard extends StatelessWidget { padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12), decoration: BoxDecoration( color: color.withOpacity(0.05), - borderRadius: BorderRadius.circular(8), + borderRadius: BorderRadius.circular(5), border: Border.all(color: color.withOpacity(0.15), width: 1), ), child: Column( @@ -600,35 +594,25 @@ class _CondensedMetricCard extends StatelessWidget { Icon(icon, color: color, size: 16), const SizedBox(width: 4), Expanded( - child: Text( + child: MyText.bodySmall( title, overflow: TextOverflow.ellipsis, - style: TextStyle( - color: color, - fontSize: 10, - fontWeight: FontWeight.w700, - ), + color: color, + fontWeight: 700, ), ), ], ), - const SizedBox(height: 6), - Text( + MySpacing.height(6), + MyText.bodyMedium( value, overflow: TextOverflow.ellipsis, - style: const TextStyle( - color: Colors.black87, - fontSize: 16, - fontWeight: FontWeight.w800, - ), + fontWeight: 800, ), - Text( + MyText.bodySmall( caption, - style: TextStyle( - color: Colors.grey.shade500, - fontSize: 9, - fontWeight: FontWeight.w500, - ), + color: Colors.grey.shade500, + fontWeight: 500, ), ], ), @@ -656,9 +640,9 @@ class _StatusDonutChart extends StatelessWidget { if (activeBuckets.isEmpty) { return Padding( padding: const EdgeInsets.only(top: 8.0), - child: Text( + child: MyText.bodySmall( 'No active invoices to display status breakdown.', - style: TextStyle(fontSize: 12, color: Colors.grey.shade500), + color: Colors.grey.shade500, ), ); } @@ -667,10 +651,6 @@ class _StatusDonutChart extends StatelessWidget { final double mainPercentage = totalAmount > 0 ? activeBuckets.first.amount / totalAmount : 0.0; - // Placeholder for Donut Chart (requires external package like fl_chart for true pie/donut chart) - // We simulate the key visual hierarchy here: - // - return Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -688,21 +668,13 @@ class _StatusDonutChart extends StatelessWidget { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text( - '${activeBuckets.first.title}', // Top status name - style: TextStyle( - fontSize: 10, - color: activeBuckets.first.color, - fontWeight: FontWeight.bold, - ), + MyText.bodySmall( + activeBuckets.first.title, + color: activeBuckets.first.color, + fontWeight: 700, ), - Text( + MyText.bodyMedium( '${(mainPercentage * 100).toStringAsFixed(0)}%', - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.w900, - color: Colors.black87, - ), ), ], ), @@ -727,22 +699,16 @@ class _StatusDonutChart extends StatelessWidget { ), ), Expanded( - child: Text( + child: MyText.bodySmall( '${bucket.title} (${bucket.count})', - style: TextStyle( - fontSize: 12, - color: Colors.grey.shade800, - fontWeight: FontWeight.w500, - ), + color: Colors.grey.shade800, + fontWeight: 500, ), ), - Text( + MyText.bodySmall( '₹${bucket.amount.toStringAsFixed(0)}', - style: TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - color: bucket.color.withOpacity(0.9), - ), + fontWeight: 700, + color: bucket.color.withOpacity(0.9), ), ], ), @@ -772,9 +738,9 @@ class _ProjectBreakdown extends StatelessWidget { if (projects.isEmpty) { return Padding( padding: const EdgeInsets.only(top: 8.0), - child: Text( + child: MyText.bodySmall( 'No project data available.', - style: TextStyle(fontSize: 12, color: Colors.grey.shade500), + color: Colors.grey.shade500, ), ); } @@ -804,18 +770,14 @@ class _ProjectBreakdown extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( + MyText.bodyMedium( project.name, overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontSize: 13, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), + fontWeight: 600, ), const SizedBox(height: 2), ClipRRect( - borderRadius: BorderRadius.circular(4), + borderRadius: BorderRadius.circular(5), child: LinearProgressIndicator( value: percentage, backgroundColor: Colors.grey.shade200, @@ -830,21 +792,15 @@ class _ProjectBreakdown extends StatelessWidget { Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text( + MyText.bodyMedium( '₹${project.amount.toStringAsFixed(0)}', - style: TextStyle( - fontSize: 13, - fontWeight: FontWeight.w700, - color: color.withOpacity(0.9), - ), + fontWeight: 700, + color: color.withOpacity(0.9), ), - Text( + MyText.bodySmall( '$percentageText%', - style: TextStyle( - fontSize: 10, - fontWeight: FontWeight.w500, - color: Colors.grey.shade600, - ), + fontWeight: 500, + color: Colors.grey.shade600, ), ], ),