localization reports page

This commit is contained in:
2026-02-19 13:09:44 +05:30
parent c4610003b4
commit 3b7715a382
7 changed files with 96 additions and 111 deletions

View File

@@ -1254,6 +1254,7 @@
} }
}, },
"all_shifts_title": "ALL SHIFTS", "all_shifts_title": "ALL SHIFTS",
"no_shifts_today": "No shifts scheduled for today",
"shift_item": { "shift_item": {
"time": "Time", "time": "Time",
"workers": "Workers", "workers": "Workers",
@@ -1289,6 +1290,7 @@
"sun": "Sun" "sun": "Sun"
}, },
"spend_by_industry": "Spend by Industry", "spend_by_industry": "Spend by Industry",
"no_industry_data": "No industry data available",
"industries": { "industries": {
"hospitality": "Hospitality", "hospitality": "Hospitality",
"events": "Events", "events": "Events",
@@ -1319,41 +1321,16 @@
}, },
"forecast_report": { "forecast_report": {
"title": "Forecast Report", "title": "Forecast Report",
"subtitle": "Next 4 weeks projection", "subtitle": "Projected spend & staffing",
"summary": { "metrics": {
"four_week": "4-Week Forecast", "projected_spend": "Projected Spend",
"avg_weekly": "Avg Weekly", "workers_needed": "Workers Needed"
"total_shifts": "Total Shifts",
"total_hours": "Total Hours",
"total_projected": "Total projected",
"per_week": "Per week",
"scheduled": "Scheduled",
"worker_hours": "Worker hours"
}, },
"spending_forecast": "Spending Forecast", "chart_title": "Spending Forecast",
"weekly_breakdown": "WEEKLY BREAKDOWN", "daily_projections": "DAILY PROJECTIONS",
"breakdown_headings": { "empty_state": "No projections available",
"shifts": "Shifts", "shift_item": {
"hours": "Hours", "workers_needed": "$count workers needed"
"avg_shift": "Avg/Shift"
},
"insights": {
"title": "Forecast Insights",
"insight_1": {
"prefix": "Demand is expected to spike by ",
"highlight": "25%",
"suffix": " in week 3"
},
"insight_2": {
"prefix": "Projected spend for next month is ",
"highlight": "USD 68.4k",
"suffix": ""
},
"insight_3": {
"prefix": "Consider increasing budget for ",
"highlight": "Holiday Season",
"suffix": " coverage"
}
}, },
"placeholders": { "placeholders": {
"export_message": "Exporting Forecast Report (Placeholder)" "export_message": "Exporting Forecast Report (Placeholder)"
@@ -1364,7 +1341,9 @@
"subtitle": "Key metrics & benchmarks", "subtitle": "Key metrics & benchmarks",
"overall_score": { "overall_score": {
"title": "Overall Performance Score", "title": "Overall Performance Score",
"label": "Excellent" "excellent": "Excellent",
"good": "Good",
"needs_work": "Needs Work"
}, },
"kpis_title": "KEY PERFORMANCE INDICATORS", "kpis_title": "KEY PERFORMANCE INDICATORS",
"kpis": { "kpis": {
@@ -1373,8 +1352,11 @@
"on_time_rate": "On-Time Rate", "on_time_rate": "On-Time Rate",
"avg_fill_time": "Avg Fill Time", "avg_fill_time": "Avg Fill Time",
"target_prefix": "Target: ", "target_prefix": "Target: ",
"target_hours": "$hours hrs",
"target_percent": "$percent%",
"met": "✓ Met", "met": "✓ Met",
"close": " Close" "close": " Close",
"miss": "✗ Miss"
}, },
"additional_metrics_title": "ADDITIONAL METRICS", "additional_metrics_title": "ADDITIONAL METRICS",
"additional_metrics": { "additional_metrics": {
@@ -1425,13 +1407,13 @@
"title": "Reliability Insights", "title": "Reliability Insights",
"insight_1": { "insight_1": {
"prefix": "Your no-show rate of ", "prefix": "Your no-show rate of ",
"highlight": "1.2%", "highlight": "$rate%",
"suffix": " is below industry average" "suffix": " is $comparison industry average"
}, },
"insight_2": { "insight_2": {
"prefix": "", "prefix": "",
"highlight": "1 worker", "highlight": "$count worker(s)",
"suffix": " has multiple incidents this month" "suffix": " have multiple incidents this month"
}, },
"insight_3": { "insight_3": {
"prefix": "Consider implementing ", "prefix": "Consider implementing ",
@@ -1439,6 +1421,7 @@
"suffix": " 24hrs before shifts" "suffix": " 24hrs before shifts"
} }
}, },
"empty_state": "No workers flagged for no-shows",
"placeholders": { "placeholders": {
"export_message": "Exporting No-Show Report (Placeholder)" "export_message": "Exporting No-Show Report (Placeholder)"
} }
@@ -1452,9 +1435,11 @@
"needs_help": "Needs Help" "needs_help": "Needs Help"
}, },
"next_7_days": "NEXT 7 DAYS", "next_7_days": "NEXT 7 DAYS",
"empty_state": "No shifts scheduled",
"shift_item": { "shift_item": {
"confirmed_workers": "$confirmed/$needed workers confirmed", "confirmed_workers": "$confirmed/$needed workers confirmed",
"spots_remaining": "$count spots remaining", "spots_remaining": "$count spots remaining",
"one_spot_remaining": "1 spot remaining",
"fully_staffed": "Fully staffed" "fully_staffed": "Fully staffed"
}, },
"insights": { "insights": {

View File

@@ -175,21 +175,21 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
children: [ children: [
_CoverageStatCard( _CoverageStatCard(
icon: UiIcons.trendingUp, icon: UiIcons.trendingUp,
label: 'Avg Coverage', label: context.t.client_reports.coverage_report.metrics.avg_coverage,
value: '${report.overallCoverage.toStringAsFixed(0)}%', value: '${report.overallCoverage.toStringAsFixed(0)}%',
iconColor: UiColors.primary, iconColor: UiColors.primary,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_CoverageStatCard( _CoverageStatCard(
icon: UiIcons.checkCircle, icon: UiIcons.checkCircle,
label: 'Full', label: context.t.client_reports.coverage_report.metrics.full,
value: fullDays.toString(), value: fullDays.toString(),
iconColor: UiColors.success, iconColor: UiColors.success,
), ),
const SizedBox(width: 12), const SizedBox(width: 12),
_CoverageStatCard( _CoverageStatCard(
icon: UiIcons.warning, icon: UiIcons.warning,
label: 'Needs Help', label: context.t.client_reports.coverage_report.metrics.needs_help,
value: needsHelpDays.toString(), value: needsHelpDays.toString(),
iconColor: UiColors.error, iconColor: UiColors.error,
), ),
@@ -209,8 +209,8 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
const SizedBox(height: 32), const SizedBox(height: 32),
// Section label // Section label
const Text( Text(
'NEXT 7 DAYS', context.t.client_reports.coverage_report.next_7_days,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -224,9 +224,9 @@ class _CoverageReportPageState extends State<CoverageReportPage> {
Container( Container(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
alignment: Alignment.center, alignment: Alignment.center,
child: const Text( child: Text(
'No shifts scheduled', context.t.client_reports.coverage_report.empty_state,
style: TextStyle( style: const TextStyle(
color: UiColors.textSecondary, color: UiColors.textSecondary,
), ),
), ),
@@ -398,7 +398,7 @@ class _DayCoverageCard extends StatelessWidget {
), ),
const SizedBox(height: 2), const SizedBox(height: 2),
Text( Text(
'$filled/$needed workers confirmed', context.t.client_reports.coverage_report.shift_item.confirmed_workers(confirmed: filled.toString(), needed: needed.toString()),
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: UiColors.textSecondary, color: UiColors.textSecondary,
@@ -442,8 +442,10 @@ class _DayCoverageCard extends StatelessWidget {
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: Text( child: Text(
isFullyStaffed isFullyStaffed
? 'Fully staffed' ? context.t.client_reports.coverage_report.shift_item.fully_staffed
: '$spotsRemaining spot${spotsRemaining != 1 ? 's' : ''} remaining', : spotsRemaining == 1
? context.t.client_reports.coverage_report.shift_item.one_spot_remaining
: context.t.client_reports.coverage_report.shift_item.spots_remaining(count: spotsRemaining.toString()),
style: TextStyle( style: TextStyle(
fontSize: 11, fontSize: 11,
color: isFullyStaffed color: isFullyStaffed

View File

@@ -335,7 +335,7 @@ class _DailyOpsReportPageState extends State<DailyOpsReportPage> {
const Padding( const Padding(
padding: EdgeInsets.symmetric(vertical: 40), padding: EdgeInsets.symmetric(vertical: 40),
child: Center( child: Center(
child: Text('No shifts scheduled for today'), child: Text(context.t.client_reports.daily_ops_report.no_shifts_today),
), ),
) )
else else
@@ -579,7 +579,7 @@ class _ShiftListItem extends StatelessWidget {
_infoItem( _infoItem(
context, context,
UiIcons.trendingUp, UiIcons.trendingUp,
'Rate', context.t.client_reports.daily_ops_report.shift_item.rate,
rate), rate),
], ],
), ),

View File

@@ -120,7 +120,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
children: [ children: [
Expanded( Expanded(
child: _ForecastSummaryCard( child: _ForecastSummaryCard(
label: 'Projected Spend', label: context.t.client_reports.forecast_report.metrics.projected_spend,
value: NumberFormat.currency(symbol: r'$') value: NumberFormat.currency(symbol: r'$')
.format(report.projectedSpend), .format(report.projectedSpend),
icon: UiIcons.dollar, icon: UiIcons.dollar,
@@ -130,7 +130,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
const SizedBox(width: 12), const SizedBox(width: 12),
Expanded( Expanded(
child: _ForecastSummaryCard( child: _ForecastSummaryCard(
label: 'Workers Needed', label: context.t.client_reports.forecast_report.metrics.workers_needed,
value: report.projectedWorkers.toString(), value: report.projectedWorkers.toString(),
icon: UiIcons.users, icon: UiIcons.users,
color: UiColors.primary, color: UiColors.primary,
@@ -158,7 +158,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
'Spending Forecast', context.t.client_reports.forecast_report.chart_title,
style: const TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -178,7 +178,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
// Daily List // Daily List
Text( Text(
'DAILY PROJECTIONS', context.t.client_reports.forecast_report.daily_projections,
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -188,7 +188,7 @@ class _ForecastReportPageState extends State<ForecastReportPage> {
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
if (report.chartData.isEmpty) if (report.chartData.isEmpty)
const Center(child: Text('No projections available')) Center(child: Text(context.t.client_reports.forecast_report.empty_state))
else else
...report.chartData.map((point) => _ForecastListItem( ...report.chartData.map((point) => _ForecastListItem(
date: DateFormat('EEE, MMM dd').format(point.date), date: DateFormat('EEE, MMM dd').format(point.date),
@@ -348,7 +348,7 @@ class _ForecastListItem extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(date, style: const TextStyle(fontWeight: FontWeight.bold)), Text(date, style: const TextStyle(fontWeight: FontWeight.bold)),
Text('$workers workers needed', style: const TextStyle(fontSize: 11, color: UiColors.textSecondary)), Text(context.t.client_reports.forecast_report.shift_item.workers_needed(count: workers), style: const TextStyle(fontSize: 11, color: UiColors.textSecondary)),
], ],
), ),
Text(cost, style: const TextStyle(fontWeight: FontWeight.bold, color: UiColors.primary)), Text(cost, style: const TextStyle(fontWeight: FontWeight.bold, color: UiColors.primary)),

View File

@@ -158,7 +158,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
child: _SummaryChip( child: _SummaryChip(
icon: UiIcons.warning, icon: UiIcons.warning,
iconColor: UiColors.error, iconColor: UiColors.error,
label: 'No-Shows', label: context.t.client_reports.no_show_report.metrics.no_shows,
value: report.totalNoShows.toString(), value: report.totalNoShows.toString(),
), ),
), ),
@@ -167,7 +167,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
child: _SummaryChip( child: _SummaryChip(
icon: UiIcons.trendingUp, icon: UiIcons.trendingUp,
iconColor: UiColors.textWarning, iconColor: UiColors.textWarning,
label: 'Rate', label: context.t.client_reports.no_show_report.metrics.rate,
value: value:
'${report.noShowRate.toStringAsFixed(1)}%', '${report.noShowRate.toStringAsFixed(1)}%',
), ),
@@ -177,7 +177,7 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
child: _SummaryChip( child: _SummaryChip(
icon: UiIcons.user, icon: UiIcons.user,
iconColor: UiColors.primary, iconColor: UiColors.primary,
label: 'Workers', label: context.t.client_reports.no_show_report.metrics.workers,
value: uniqueWorkers.toString(), value: uniqueWorkers.toString(),
), ),
), ),
@@ -204,9 +204,9 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
Container( Container(
padding: const EdgeInsets.all(40), padding: const EdgeInsets.all(40),
alignment: Alignment.center, alignment: Alignment.center,
child: const Text( child: Text(
'No workers flagged for no-shows', context.t.client_reports.no_show_report.empty_state,
style: TextStyle( style: const TextStyle(
color: UiColors.textSecondary, color: UiColors.textSecondary,
), ),
), ),
@@ -232,9 +232,9 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'💡 Reliability Insights', '💡 ${context.t.client_reports.no_show_report.insights.title}',
style: TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: UiColors.textPrimary, color: UiColors.textPrimary,
@@ -243,21 +243,19 @@ class _NoShowReportPageState extends State<NoShowReportPage> {
const SizedBox(height: 12), const SizedBox(height: 12),
_InsightLine( _InsightLine(
text: text:
'· Your no-show rate of ${report.noShowRate.toStringAsFixed(1)}% is ' '· ${context.t.client_reports.no_show_report.insights.insight_1.prefix}${context.t.client_reports.no_show_report.insights.insight_1.highlight(rate: report.noShowRate.toStringAsFixed(1))}${context.t.client_reports.no_show_report.insights.insight_1.suffix(comparison: report.noShowRate < 5 ? 'below' : 'above')}',
'${report.noShowRate < 5 ? 'below' : 'above'} industry average',
), ),
if (report.flaggedWorkers.any( if (report.flaggedWorkers.any(
(w) => w.noShowCount > 1, (w) => w.noShowCount > 1,
)) ))
_InsightLine( _InsightLine(
text: text:
'· ${report.flaggedWorkers.where((w) => w.noShowCount > 1).length} ' '· ${context.t.client_reports.no_show_report.insights.insight_2.highlight(count: report.flaggedWorkers.where((w) => w.noShowCount > 1).length.toString())} ${context.t.client_reports.no_show_report.insights.insight_2.suffix}',
'worker(s) have multiple incidents this month',
bold: true, bold: true,
), ),
const _InsightLine( _InsightLine(
text: text:
'· Consider implementing confirmation reminders 24hrs before shifts', '· ${context.t.client_reports.no_show_report.insights.insight_3.prefix}${context.t.client_reports.no_show_report.insights.insight_3.highlight}${context.t.client_reports.no_show_report.insights.insight_3.suffix}',
bold: true, bold: true,
), ),
], ],
@@ -352,9 +350,9 @@ class _WorkerCard extends StatelessWidget {
const _WorkerCard({required this.worker}); const _WorkerCard({required this.worker});
String _riskLabel(int count) { String _riskLabel(int count) {
if (count >= 3) return 'High Risk'; if (count >= 3) return context.t.client_reports.no_show_report.risks.high;
if (count == 2) return 'Medium Risk'; if (count == 2) return context.t.client_reports.no_show_report.risks.medium;
return 'Low Risk'; return context.t.client_reports.no_show_report.risks.low;
} }
Color _riskColor(int count) { Color _riskColor(int count) {
@@ -421,7 +419,7 @@ class _WorkerCard extends StatelessWidget {
), ),
), ),
Text( Text(
'${worker.noShowCount} no-show${worker.noShowCount > 1 ? 's' : ''}', context.t.client_reports.no_show_report.no_show_count(count: worker.noShowCount.toString()),
style: const TextStyle( style: const TextStyle(
fontSize: 12, fontSize: 12,
color: UiColors.textSecondary, color: UiColors.textSecondary,
@@ -458,9 +456,9 @@ class _WorkerCard extends StatelessWidget {
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const Text( Text(
'Latest incident', context.t.client_reports.no_show_report.latest_incident,
style: TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 11,
color: UiColors.textSecondary, color: UiColors.textSecondary,
), ),

View File

@@ -50,10 +50,10 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
.clamp(0.0, 100.0); .clamp(0.0, 100.0);
final scoreLabel = overallScore >= 90 final scoreLabel = overallScore >= 90
? 'Excellent' ? context.t.client_reports.performance_report.overall_score.excellent
: overallScore >= 75 : overallScore >= 75
? 'Good' ? context.t.client_reports.performance_report.overall_score.good
: 'Needs Work'; : context.t.client_reports.performance_report.overall_score.needs_work;
final scoreLabelColor = overallScore >= 90 final scoreLabelColor = overallScore >= 90
? UiColors.success ? UiColors.success
: overallScore >= 75 : overallScore >= 75
@@ -70,8 +70,8 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
_KpiData( _KpiData(
icon: UiIcons.users, icon: UiIcons.users,
iconColor: UiColors.primary, iconColor: UiColors.primary,
label: 'Fill Rate', label: context.t.client_reports.performance_report.kpis.fill_rate,
target: 'Target: 95%', target: context.t.client_reports.performance_report.kpis.target_percent(percent: '95'),
value: report.fillRate, value: report.fillRate,
displayValue: '${report.fillRate.toStringAsFixed(0)}%', displayValue: '${report.fillRate.toStringAsFixed(0)}%',
barColor: UiColors.primary, barColor: UiColors.primary,
@@ -81,8 +81,8 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
_KpiData( _KpiData(
icon: UiIcons.checkCircle, icon: UiIcons.checkCircle,
iconColor: UiColors.success, iconColor: UiColors.success,
label: 'Completion Rate', label: context.t.client_reports.performance_report.kpis.completion_rate,
target: 'Target: 98%', target: context.t.client_reports.performance_report.kpis.target_percent(percent: '98'),
value: report.completionRate, value: report.completionRate,
displayValue: '${report.completionRate.toStringAsFixed(0)}%', displayValue: '${report.completionRate.toStringAsFixed(0)}%',
barColor: UiColors.success, barColor: UiColors.success,
@@ -92,8 +92,8 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
_KpiData( _KpiData(
icon: UiIcons.clock, icon: UiIcons.clock,
iconColor: const Color(0xFF9B59B6), iconColor: const Color(0xFF9B59B6),
label: 'On-Time Rate', label: context.t.client_reports.performance_report.kpis.on_time_rate,
target: 'Target: 97%', target: context.t.client_reports.performance_report.kpis.target_percent(percent: '97'),
value: report.onTimeRate, value: report.onTimeRate,
displayValue: '${report.onTimeRate.toStringAsFixed(0)}%', displayValue: '${report.onTimeRate.toStringAsFixed(0)}%',
barColor: const Color(0xFF9B59B6), barColor: const Color(0xFF9B59B6),
@@ -103,8 +103,8 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
_KpiData( _KpiData(
icon: UiIcons.trendingUp, icon: UiIcons.trendingUp,
iconColor: const Color(0xFFF39C12), iconColor: const Color(0xFFF39C12),
label: 'Avg Fill Time', label: context.t.client_reports.performance_report.kpis.avg_fill_time,
target: 'Target: 3 hrs', target: context.t.client_reports.performance_report.kpis.target_hours(hours: '3'),
// invert: lower is better — show as % of target met // invert: lower is better — show as % of target met
value: report.avgFillTimeHours == 0 value: report.avgFillTimeHours == 0
? 100 ? 100
@@ -256,8 +256,8 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
color: UiColors.primary, color: UiColors.primary,
), ),
const SizedBox(height: 12), const SizedBox(height: 12),
const Text( Text(
'Overall Performance Score', context.t.client_reports.performance_report.overall_score.title,
style: TextStyle( style: TextStyle(
fontSize: 13, fontSize: 13,
color: UiColors.textSecondary, color: UiColors.textSecondary,
@@ -313,9 +313,9 @@ class _PerformanceReportPageState extends State<PerformanceReportPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'KEY PERFORMANCE INDICATORS', context.t.client_reports.performance_report.kpis_title,
style: TextStyle( style: const TextStyle(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: UiColors.textSecondary, color: UiColors.textSecondary,
@@ -381,10 +381,10 @@ class _KpiRow extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final badgeText = kpi.met final badgeText = kpi.met
? '✓ Met' ? context.t.client_reports.performance_report.kpis.met
: kpi.close : kpi.close
? '→ Close' ? context.t.client_reports.performance_report.kpis.close
: '✗ Miss'; : context.t.client_reports.performance_report.kpis.miss;
final badgeColor = kpi.met final badgeColor = kpi.met
? UiColors.success ? UiColors.success
: kpi.close : kpi.close

View File

@@ -220,9 +220,9 @@ class _SpendReportPageState extends State<SpendReportPage> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Daily Spend Trend', context.t.client_reports.spend_report.chart_title,
style: TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: UiColors.textPrimary, color: UiColors.textPrimary,
@@ -475,9 +475,9 @@ class _SpendByIndustryCard extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text( Text(
'Spend by Industry', context.t.client_reports.spend_report.spend_by_industry,
style: TextStyle( style: const TextStyle(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: UiColors.textPrimary, color: UiColors.textPrimary,
@@ -485,12 +485,12 @@ class _SpendByIndustryCard extends StatelessWidget {
), ),
const SizedBox(height: 24), const SizedBox(height: 24),
if (industries.isEmpty) if (industries.isEmpty)
const Center( Center(
child: Padding( child: Padding(
padding: EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Text( child: Text(
'No industry data available', context.t.client_reports.spend_report.no_industry_data,
style: TextStyle(color: UiColors.textSecondary), style: const TextStyle(color: UiColors.textSecondary),
), ),
), ),
) )
@@ -533,7 +533,7 @@ class _SpendByIndustryCard extends StatelessWidget {
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
Text( Text(
'${ind.percentage.toStringAsFixed(1)}% of total', context.t.client_reports.spend_report.percent_total(percent: ind.percentage.toStringAsFixed(1)),
style: const TextStyle( style: const TextStyle(
fontSize: 10, fontSize: 10,
color: UiColors.textDescription, color: UiColors.textDescription,