From a7b34e40c815aa10c757b1f4538e71ad3da65573 Mon Sep 17 00:00:00 2001 From: Suriya Date: Tue, 24 Feb 2026 16:25:24 +0530 Subject: [PATCH] chore: add localization to benefits overview page (en & es) --- .../lib/src/l10n/en.i18n.json | 15 + .../lib/src/l10n/es.i18n.json | 15 + .../pages/benefits_overview_page.dart | 312 +++++++++--------- 3 files changed, 188 insertions(+), 154 deletions(-) diff --git a/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json b/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json index b560e5f8..3d6c2c54 100644 --- a/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json +++ b/apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json @@ -536,6 +536,21 @@ "sick_days": "Sick Days", "vacation": "Vacation", "holidays": "Holidays" + }, + "overview": { + "title": "Your Benefits Overview", + "subtitle": "Manage and track your earned benefits here", + "request_payment": "Request Payment for $benefit", + "request_submitted": "Request submitted for $benefit", + "sick_leave_subtitle": "You need at least 8 hours to request sick leave", + "vacation_subtitle": "You need 40 hours to claim vacation pay", + "holidays_subtitle": "Pay holidays: Thanksgiving, Christmas, New Year", + "sick_leave_history": "SICK LEAVE HISTORY", + "compliance_banner": "Listed certificates are mandatory for employees. If the employee does not have the complete certificates, they can't proceed with their registration.", + "status": { + "pending": "Pending", + "submitted": "Submitted" + } } }, "auto_match": { diff --git a/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json b/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json index 938d4154..46d6d9dd 100644 --- a/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json +++ b/apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json @@ -536,6 +536,21 @@ "sick_days": "D\u00edas de Enfermedad", "vacation": "Vacaciones", "holidays": "Festivos" + }, + "overview": { + "title": "Resumen de tus Beneficios", + "subtitle": "Gestiona y sigue tus beneficios ganados aqu\u00ed", + "request_payment": "Solicitar pago por $benefit", + "request_submitted": "Solicitud enviada para $benefit", + "sick_leave_subtitle": "Necesitas al menos 8 horas para solicitar d\u00edas de enfermedad", + "vacation_subtitle": "Necesitas 40 horas para reclamar el pago de vacaciones", + "holidays_subtitle": "D\u00edas festivos pagados: Acci\u00f3n de Gracias, Navidad, A\u00f1o Nuevo", + "sick_leave_history": "HISTORIAL DE D\u00cdAS DE ENFERMEDAD", + "compliance_banner": "Los certificados listados son obligatorios para los empleados. Si el empleado no tiene los certificados completos, no puede proceder con su registro.", + "status": { + "pending": "Pendiente", + "submitted": "Enviado" + } } }, "auto_match": { diff --git a/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/benefits_overview_page.dart b/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/benefits_overview_page.dart index 12dd93bf..c8454d76 100644 --- a/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/benefits_overview_page.dart +++ b/apps/mobile/packages/features/staff/home/lib/src/presentation/pages/benefits_overview_page.dart @@ -4,6 +4,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:krow_core/core.dart'; import 'package:krow_domain/krow_domain.dart'; +import 'package:core_localization/core_localization.dart'; import 'package:staff_home/src/presentation/blocs/home_cubit.dart'; import 'dart:math' as math; @@ -58,186 +59,189 @@ class BenefitsOverviewPage extends StatelessWidget { centerTitle: true, title: Column( children: [ - Text( - 'Your Benefits Overview', - style: UiTypography.title2b.textPrimary, + Text( + t.staff.home.benefits.overview.title, + style: UiTypography.title2b.textPrimary, + ), + const SizedBox(height: 2), + Text( + t.staff.home.benefits.overview.subtitle, + style: UiTypography.footnote2r.textSecondary, + ), + ], ), - const SizedBox(height: 2), - Text( - 'Manage and track your earned benefits here', - style: UiTypography.footnote2r.textSecondary, + bottom: PreferredSize( + preferredSize: const Size.fromHeight(1), + child: Container(color: UiColors.border.withOpacity(0.5), height: 1), ), - ], - ), - bottom: PreferredSize( - preferredSize: const Size.fromHeight(1), - child: Container(color: UiColors.border.withOpacity(0.5), height: 1), - ), - ); - } -} + ); + } + } -class _BenefitCard extends StatelessWidget { - final Benefit benefit; + class _BenefitCard extends StatelessWidget { + final Benefit benefit; - const _BenefitCard({required this.benefit}); + const _BenefitCard({required this.benefit}); - @override - Widget build(BuildContext context) { - final bool isSickLeave = benefit.title.toLowerCase().contains('sick'); - final bool isVacation = benefit.title.toLowerCase().contains('vacation'); - final bool isHolidays = benefit.title.toLowerCase().contains('holiday'); + @override + Widget build(BuildContext context) { + final bool isSickLeave = benefit.title.toLowerCase().contains('sick'); + final bool isVacation = benefit.title.toLowerCase().contains('vacation'); + final bool isHolidays = benefit.title.toLowerCase().contains('holiday'); + + final i18n = t.staff.home.benefits.overview; - return Container( - padding: const EdgeInsets.all(UiConstants.space6), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: UiConstants.radiusLg, - border: Border.all(color: UiColors.border.withOpacity(0.5)), - boxShadow: [ - BoxShadow( - color: UiColors.black.withOpacity(0.02), - blurRadius: 10, - offset: const Offset(0, 4), + return Container( + padding: const EdgeInsets.all(UiConstants.space6), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: UiConstants.radiusLg, + border: Border.all(color: UiColors.border.withOpacity(0.5)), + boxShadow: [ + BoxShadow( + color: UiColors.black.withOpacity(0.02), + blurRadius: 10, + offset: const Offset(0, 4), + ), + ], ), - ], - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildProgressCircle(), - const SizedBox(width: UiConstants.space4), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, + Row( + children: [ + _buildProgressCircle(), + const SizedBox(width: UiConstants.space4), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - benefit.title, - style: UiTypography.body1b.textPrimary, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + benefit.title, + style: UiTypography.body1b.textPrimary, + ), + const Icon(UiIcons.info, size: 18, color: Color(0xFFE2E8F0)), + ], + ), + const SizedBox(height: 4), + Text( + _getSubtitle(benefit.title), + style: UiTypography.footnote2r.textSecondary, ), - const Icon(UiIcons.info, size: 18, color: Color(0xFFE2E8F0)), ], ), - const SizedBox(height: 4), - Text( - _getSubtitle(benefit.title), - style: UiTypography.footnote2r.textSecondary, + ), + ], + ), + const SizedBox(height: UiConstants.space6), + if (isSickLeave) ...[ + _AccordionHistory(label: i18n.sick_leave_history), + const SizedBox(height: UiConstants.space6), + ], + if (isVacation || isHolidays) ...[ + _buildComplianceBanner(i18n.compliance_banner), + const SizedBox(height: UiConstants.space6), + ], + SizedBox( + width: double.infinity, + child: UiButton.primary( + text: i18n.request_payment(benefit: benefit.title), + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF0038A8), + padding: const EdgeInsets.symmetric(vertical: 16), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), ), - ], + ), + onPressed: () { + // TODO: Implement payment request + UiSnackbar.show(context, message: i18n.request_submitted(benefit: benefit.title), type: UiSnackbarType.success); + }, ), ), ], ), - const SizedBox(height: UiConstants.space6), - if (isSickLeave) ...[ - const _AccordionHistory(label: 'SICK LEAVE HISTORY'), - const SizedBox(height: UiConstants.space6), - ], - if (isVacation || isHolidays) ...[ - _buildComplianceBanner(), - const SizedBox(height: UiConstants.space6), - ], - SizedBox( - width: double.infinity, - child: UiButton.primary( - text: 'Request Payment for ${benefit.title}', - style: ElevatedButton.styleFrom( - backgroundColor: const Color(0xFF0038A8), - padding: const EdgeInsets.symmetric(vertical: 16), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), + ); + } + + Widget _buildProgressCircle() { + final double progress = benefit.entitlementHours > 0 + ? (benefit.remainingHours / benefit.entitlementHours) + : 0.0; + + final bool isSickLeave = benefit.title.toLowerCase().contains('sick'); + final Color circleColor = isSickLeave ? const Color(0xFF2563EB) : const Color(0xFF10B981); + + return SizedBox( + width: 72, + height: 72, + child: CustomPaint( + painter: _CircularProgressPainter( + progress: progress, + color: circleColor, + backgroundColor: const Color(0xFFE2E8F0), + strokeWidth: 6, + ), + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + '${benefit.remainingHours.toInt()}/${benefit.entitlementHours.toInt()}', + style: UiTypography.body2b.textPrimary.copyWith(fontSize: 14), + ), + Text( + t.client_billing.hours_suffix, + style: UiTypography.footnote2r.textTertiary.copyWith(fontSize: 9), + ), + ], ), - onPressed: () { - // TODO: Implement payment request - UiSnackbar.show(context, message: 'Request submitted for ${benefit.title}', type: UiSnackbarType.success); - }, ), ), - ], - ), - ); - } + ); + } - Widget _buildProgressCircle() { - final double progress = benefit.entitlementHours > 0 - ? (benefit.remainingHours / benefit.entitlementHours) - : 0.0; - - final bool isSickLeave = benefit.title.toLowerCase().contains('sick'); - final Color circleColor = isSickLeave ? const Color(0xFF2563EB) : const Color(0xFF10B981); - - return SizedBox( - width: 72, - height: 72, - child: CustomPaint( - painter: _CircularProgressPainter( - progress: progress, - color: circleColor, - backgroundColor: const Color(0xFFE2E8F0), - strokeWidth: 6, - ), - child: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, + String _getSubtitle(String title) { + final i18n = t.staff.home.benefits.overview; + if (title.toLowerCase().contains('sick')) { + return i18n.sick_leave_subtitle; + } else if (title.toLowerCase().contains('vacation')) { + return i18n.vacation_subtitle; + } else if (title.toLowerCase().contains('holiday')) { + return i18n.holidays_subtitle; + } + return ''; + } + + Widget _buildComplianceBanner(String text) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: const Color(0xFFECFDF5), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - '${benefit.remainingHours.toInt()}/${benefit.entitlementHours.toInt()}', - style: UiTypography.body2b.textPrimary.copyWith(fontSize: 14), - ), - Text( - 'hours', - style: UiTypography.footnote2r.textTertiary.copyWith(fontSize: 9), + const Icon(UiIcons.checkCircle, size: 16, color: Color(0xFF10B981)), + const SizedBox(width: 8), + Expanded( + child: Text( + text, + style: UiTypography.footnote1r.copyWith( + color: const Color(0xFF065F46), + fontSize: 11, + ), + ), ), ], ), - ), - ), - ); - } - - String _getSubtitle(String title) { - if (title.toLowerCase().contains('sick')) { - return 'You need at least 8 hours to request sick leave'; - } else if (title.toLowerCase().contains('vacation')) { - return 'You need 40 hours to claim vacation pay'; - } else if (title.toLowerCase().contains('holiday')) { - return 'Pay holidays: Thanksgiving, Christmas, New Year'; + ); + } } - return ''; - } - - Widget _buildComplianceBanner() { - return Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - color: const Color(0xFFECFDF5), - borderRadius: BorderRadius.circular(8), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(UiIcons.checkCircle, size: 16, color: Color(0xFF10B981)), - const SizedBox(width: 8), - Expanded( - child: Text( - 'Listed certificates are mandatory for employees. If the employee does not have the complete certificates, they can\'t proceed with their registration.', - style: UiTypography.footnote1r.copyWith( - color: const Color(0xFF065F46), - fontSize: 11, - ), - ), - ), - ], - ), - ); - } -} class _CircularProgressPainter extends CustomPainter { final double progress;