Merge branch 'dev' into feature/centralized-data-error-handling and resolve conflicts
This commit is contained in:
@@ -65,7 +65,7 @@ class CertificatesPage extends StatelessWidget {
|
||||
Transform.translate(
|
||||
offset: const Offset(0, -48),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
padding: const EdgeInsets.symmetric(horizontal: UiConstants.space5),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
...documents.map((StaffDocument doc) => CertificateCard(
|
||||
@@ -82,11 +82,11 @@ class CertificatesPage extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
)),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
AddCertificateCard(
|
||||
onTap: () => _showUploadModal(context, null),
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -12,37 +12,36 @@ class AddCertificateCard extends StatelessWidget {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: const EdgeInsets.all(UiConstants.space5),
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: <Color>[Colors.grey[50]!, Colors.grey[100]!], // Keep prototype style
|
||||
colors: <Color>[
|
||||
UiColors.bgSecondary.withValues(alpha: 0.5),
|
||||
UiColors.bgSecondary,
|
||||
],
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(
|
||||
color: Colors.grey[300]!,
|
||||
color: UiColors.border,
|
||||
style: BorderStyle.solid,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.add, color: UiColors.primary, size: 24),
|
||||
const SizedBox(width: 16),
|
||||
const SizedBox(width: UiConstants.space4),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_certificates.add_more.title,
|
||||
style: UiTypography.body1b.copyWith( // 16px Bold
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1b.textPrimary,
|
||||
),
|
||||
Text(
|
||||
t.staff_certificates.add_more.subtitle,
|
||||
style: UiTypography.body3r.copyWith( // 12px Regular
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
|
||||
class CertificateCard extends StatelessWidget {
|
||||
final StaffDocument document;
|
||||
@@ -39,13 +39,13 @@ class CertificateCard extends StatelessWidget {
|
||||
final _CertificateUiProps uiProps = _getUiProps(document.documentId);
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white,
|
||||
borderRadius: BorderRadius.circular(UiConstants.space4),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: UiColors.black.withOpacity(0.05),
|
||||
color: UiColors.black.withValues(alpha: 0.05),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
@@ -57,11 +57,14 @@ class CertificateCard extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
if (isExpiring || isExpired)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF9E547).withOpacity(0.2), // Yellow tint
|
||||
border: const Border(
|
||||
bottom: BorderSide(color: Color(0x66F9E547)),
|
||||
color: UiColors.accent.withValues(alpha: 0.2), // Yellow tint
|
||||
border: Border(
|
||||
bottom: BorderSide(color: UiColors.accent.withValues(alpha: 0.4)),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
@@ -76,16 +79,14 @@ class CertificateCard extends StatelessWidget {
|
||||
isExpired
|
||||
? t.staff_certificates.card.expired
|
||||
: t.staff_certificates.card.expires_in_days(days: _daysUntilExpiry(document.expiryDate)),
|
||||
style: UiTypography.body3m.copyWith( // 12px Medium
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body3m.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: const EdgeInsets.all(UiConstants.space5),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@@ -96,8 +97,8 @@ class CertificateCard extends StatelessWidget {
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: uiProps.color.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
color: uiProps.color.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Center(
|
||||
child: Icon(
|
||||
@@ -137,7 +138,7 @@ class CertificateCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
const SizedBox(width: UiConstants.space4),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -151,16 +152,12 @@ class CertificateCard extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
document.name,
|
||||
style: UiTypography.body1m.copyWith( // 16px Medium
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
document.description ?? '', // Optional description
|
||||
style: UiTypography.body3r.copyWith( // 12px Regular
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -172,7 +169,7 @@ class CertificateCard extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
|
||||
if (showComplete) _buildCompleteStatus(document.expiryDate),
|
||||
|
||||
@@ -186,9 +183,11 @@ class CertificateCard extends StatelessWidget {
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space3,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
elevation: 0,
|
||||
),
|
||||
child: Row(
|
||||
@@ -202,9 +201,7 @@ class CertificateCard extends StatelessWidget {
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
t.staff_certificates.card.upload_button,
|
||||
style: UiTypography.body2m.copyWith( // 14px Medium
|
||||
color: UiColors.white,
|
||||
),
|
||||
style: UiTypography.body2m.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -212,7 +209,7 @@ class CertificateCard extends StatelessWidget {
|
||||
),
|
||||
|
||||
if (showComplete || isExpiring || isExpired) ...<Widget>[
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
@@ -223,13 +220,15 @@ class CertificateCard extends StatelessWidget {
|
||||
foregroundColor: UiColors.textPrimary,
|
||||
side: const BorderSide(color: UiColors.border),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space3,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: TextButton.icon(
|
||||
@@ -238,9 +237,11 @@ class CertificateCard extends StatelessWidget {
|
||||
label: Text(t.staff_certificates.card.remove),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: UiColors.destructive,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space3,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -274,16 +275,14 @@ class CertificateCard extends StatelessWidget {
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
t.staff_certificates.card.verified,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
if (expiryDate != null)
|
||||
Text(
|
||||
t.staff_certificates.card.exp(date: DateFormat('MMM d, yyyy').format(expiryDate)),
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -6,7 +6,8 @@ import 'package:flutter/material.dart';
|
||||
class CertificateUploadModal extends StatelessWidget {
|
||||
/// The document being edited, or null for a new upload.
|
||||
// ignore: unused_field
|
||||
final dynamic document; // Using dynamic for now as we don't import domain here to avoid direct coupling if possible, but actually we should import domain.
|
||||
final dynamic
|
||||
document; // Using dynamic for now as we don't import domain here to avoid direct coupling if possible, but actually we should import domain.
|
||||
// Ideally, widgets should be dumb. Let's import domain.
|
||||
|
||||
final VoidCallback onSave;
|
||||
@@ -24,13 +25,13 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height * 0.75,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.only(
|
||||
topLeft: Radius.circular(24),
|
||||
topRight: Radius.circular(24),
|
||||
topLeft: Radius.circular(UiConstants.radiusBase),
|
||||
topRight: Radius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.all(24),
|
||||
padding: const EdgeInsets.all(UiConstants.space6),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@@ -39,7 +40,7 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.title,
|
||||
style: UiTypography.headline3m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.headline3m.textPrimary,
|
||||
),
|
||||
IconButton(
|
||||
onPressed: onCancel,
|
||||
@@ -47,35 +48,42 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.expiry_label,
|
||||
style: UiTypography.body1m,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space3,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: UiColors.border),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.calendar, size: 20, color: UiColors.textSecondary),
|
||||
const SizedBox(width: 12),
|
||||
const Icon(
|
||||
UiIcons.calendar,
|
||||
size: 20,
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.select_date,
|
||||
style: UiTypography.body1m.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body1m.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.upload_file,
|
||||
style: UiTypography.body1m,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Expanded(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
@@ -84,16 +92,16 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
color: UiColors.border,
|
||||
style: BorderStyle.solid,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
color: UiColors.background,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFEFF6FF), // Light blue
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.tagActive,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
@@ -102,7 +110,7 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
color: UiColors.primary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.drag_drop,
|
||||
style: UiTypography.body1m,
|
||||
@@ -110,43 +118,51 @@ class CertificateUploadModal extends StatelessWidget {
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
t.staff_certificates.upload_modal.supported_formats,
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: OutlinedButton(
|
||||
onPressed: onCancel,
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
side: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
child: Text(t.staff_certificates.upload_modal.cancel,
|
||||
style: UiTypography.body1m.copyWith(color: UiColors.textPrimary)),
|
||||
child: Text(
|
||||
t.staff_certificates.upload_modal.cancel,
|
||||
style: UiTypography.body1m.textPrimary,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
const SizedBox(width: UiConstants.space4),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: onSave,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
child: Text(t.staff_certificates.upload_modal.save,
|
||||
style: UiTypography.body1m.copyWith(color: Colors.white)),
|
||||
child: Text(
|
||||
t.staff_certificates.upload_modal.save,
|
||||
style: UiTypography.body1m.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -20,13 +20,21 @@ class CertificatesHeader extends StatelessWidget {
|
||||
final int progressPercent = totalCount == 0 ? 0 : (progressValue * 100).round();
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 60, 20, 80),
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
UiConstants.space5,
|
||||
60,
|
||||
UiConstants.space5,
|
||||
80,
|
||||
),
|
||||
// Keeping gradient as per prototype layout requirement
|
||||
decoration: const BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: <Color>[UiColors.primary, Color(0xFF1E40AF)], // Using Primary and a darker shade
|
||||
colors: <Color>[
|
||||
UiColors.primary,
|
||||
Color(0xFF1E40AF),
|
||||
], // Using Primary and a darker shade
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
@@ -39,7 +47,7 @@ class CertificatesHeader extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.white.withOpacity(0.1),
|
||||
color: UiColors.white.withValues(alpha: 0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
@@ -49,16 +57,14 @@ class CertificatesHeader extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Text(
|
||||
t.staff_certificates.title,
|
||||
style: UiTypography.headline3m.copyWith( // 18px Bold
|
||||
color: UiColors.white,
|
||||
),
|
||||
style: UiTypography.headline3m.white,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
const SizedBox(height: UiConstants.space8),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
SizedBox(
|
||||
@@ -70,53 +76,48 @@ class CertificatesHeader extends StatelessWidget {
|
||||
CircularProgressIndicator(
|
||||
value: progressValue,
|
||||
strokeWidth: 8,
|
||||
backgroundColor: UiColors.white.withOpacity(0.2),
|
||||
backgroundColor: UiColors.white.withValues(alpha: 0.2),
|
||||
valueColor: const AlwaysStoppedAnimation<Color>(
|
||||
Color(0xFFF9E547), // Yellow from prototype
|
||||
UiColors.accent, // Yellow from prototype
|
||||
),
|
||||
),
|
||||
Center(
|
||||
child: Text(
|
||||
'$progressPercent%',
|
||||
style: UiTypography.display1b.copyWith( // 26px Bold
|
||||
color: UiColors.white,
|
||||
),
|
||||
style: UiTypography.display1b.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 24),
|
||||
const SizedBox(width: UiConstants.space6),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_certificates.progress.title,
|
||||
style: UiTypography.body1b.copyWith( // 16px Bold
|
||||
color: UiColors.white,
|
||||
),
|
||||
style: UiTypography.body1b.white,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
t.staff_certificates.progress.verified_count(completed: completedCount, total: totalCount),
|
||||
style: UiTypography.body3r.copyWith( // 12px Regular
|
||||
color: UiColors.white.withOpacity(0.7),
|
||||
t.staff_certificates.progress.verified_count(
|
||||
completed: completedCount, total: totalCount),
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.white.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
const Icon(
|
||||
UiIcons.shield,
|
||||
color: Color(0xFFF9E547),
|
||||
color: UiColors.accent,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
t.staff_certificates.progress.active,
|
||||
style: UiTypography.body3m.copyWith( // 12px Medium
|
||||
color: const Color(0xFFF9E547),
|
||||
),
|
||||
style: UiTypography.body3m.accent,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
|
||||
@@ -18,11 +17,11 @@ class DocumentCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
padding: const EdgeInsets.all(16),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space3),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Row(
|
||||
@@ -32,7 +31,7 @@ class DocumentCard extends StatelessWidget {
|
||||
width: 40,
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: const Center(
|
||||
@@ -43,7 +42,7 @@ class DocumentCard extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -53,9 +52,7 @@ class DocumentCard extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
document.name,
|
||||
style: UiTypography.body1m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1m.textPrimary,
|
||||
),
|
||||
_getStatusIcon(document.status),
|
||||
],
|
||||
@@ -64,15 +61,13 @@ class DocumentCard extends StatelessWidget {
|
||||
if (document.description != null)
|
||||
Text(
|
||||
document.description!,
|
||||
style: UiTypography.body2r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
Row(
|
||||
children: <Widget>[
|
||||
_buildStatusBadge(document.status),
|
||||
const SizedBox(width: 8),
|
||||
const SizedBox(width: UiConstants.space2),
|
||||
_buildActionButton(document.status),
|
||||
],
|
||||
),
|
||||
@@ -114,27 +109,27 @@ class DocumentCard extends StatelessWidget {
|
||||
|
||||
switch (status) {
|
||||
case DocumentStatus.verified:
|
||||
bg = UiColors.textSuccess.withOpacity(0.2);
|
||||
bg = UiColors.tagSuccess;
|
||||
text = UiColors.textSuccess;
|
||||
label = t.staff_documents.card.verified;
|
||||
break;
|
||||
case DocumentStatus.pending:
|
||||
bg = UiColors.textWarning.withOpacity(0.2);
|
||||
bg = UiColors.tagPending;
|
||||
text = UiColors.textWarning;
|
||||
label = t.staff_documents.card.pending;
|
||||
break;
|
||||
case DocumentStatus.missing:
|
||||
bg = UiColors.textError.withOpacity(0.2);
|
||||
bg = UiColors.textError.withValues(alpha: 0.1);
|
||||
text = UiColors.textError;
|
||||
label = t.staff_documents.card.missing;
|
||||
break;
|
||||
case DocumentStatus.rejected:
|
||||
bg = UiColors.textError.withOpacity(0.2);
|
||||
bg = UiColors.textError.withValues(alpha: 0.1);
|
||||
text = UiColors.textError;
|
||||
label = t.staff_documents.card.rejected;
|
||||
break;
|
||||
case DocumentStatus.expired:
|
||||
bg = UiColors.textError.withOpacity(0.2);
|
||||
bg = UiColors.textError.withValues(alpha: 0.1);
|
||||
text = UiColors.textError;
|
||||
label = t.staff_documents.card.rejected; // Or define "Expired" string
|
||||
break;
|
||||
@@ -165,7 +160,7 @@ class DocumentCard extends StatelessWidget {
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
isVerified ? UiIcons.eye : LucideIcons.upload,
|
||||
isVerified ? UiIcons.eye : UiIcons.upload,
|
||||
size: 16,
|
||||
color: UiColors.primary,
|
||||
),
|
||||
@@ -174,9 +169,7 @@ class DocumentCard extends StatelessWidget {
|
||||
isVerified
|
||||
? t.staff_documents.card.view
|
||||
: t.staff_documents.card.upload,
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.body3m.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -24,10 +24,10 @@ class DocumentsProgressCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Column(
|
||||
@@ -37,16 +37,14 @@ class DocumentsProgressCard extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_documents.verification_card.title,
|
||||
style: UiTypography.body1m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
t.staff_documents.verification_card.progress(
|
||||
completed: completedCount,
|
||||
total: totalCount,
|
||||
),
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.primary),
|
||||
style: UiTypography.body2r.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -83,10 +83,13 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
if (state.status == FormI9Status.success) {
|
||||
// Success view is handled by state check in build or we can navigate
|
||||
} else if (state.status == FormI9Status.failure) {
|
||||
final ScaffoldMessengerState messenger = ScaffoldMessenger.of(context);
|
||||
final ScaffoldMessengerState messenger =
|
||||
ScaffoldMessenger.of(context);
|
||||
messenger.hideCurrentSnackBar();
|
||||
messenger.showSnackBar(
|
||||
SnackBar(content: Text(state.errorMessage ?? 'An error occurred')),
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage ?? 'An error occurred'),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
@@ -100,7 +103,10 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
_buildHeader(context, state),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space5,
|
||||
vertical: UiConstants.space6,
|
||||
),
|
||||
child: _buildCurrentStep(context, state),
|
||||
),
|
||||
),
|
||||
@@ -118,9 +124,9 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
backgroundColor: UiColors.background,
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
padding: const EdgeInsets.all(UiConstants.space6),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(32),
|
||||
padding: const EdgeInsets.all(UiConstants.space8),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
@@ -132,40 +138,40 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFDCFCE7),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.tagSuccess,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
UiIcons.success,
|
||||
color: Color(0xFF16A34A),
|
||||
color: UiColors.textSuccess,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
'Form I-9 Submitted!',
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline4m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Text(
|
||||
'Your employment eligibility verification has been submitted.',
|
||||
textAlign: TextAlign.center,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Modular.to.pop(true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
foregroundColor: UiColors.bgPopup,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
foregroundColor: UiColors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
@@ -183,7 +189,12 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
Widget _buildHeader(BuildContext context, FormI9State state) {
|
||||
return Container(
|
||||
color: UiColors.primary,
|
||||
padding: const EdgeInsets.only(top: 60, bottom: 24, left: 20, right: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 60,
|
||||
bottom: UiConstants.space6,
|
||||
left: UiConstants.space5,
|
||||
right: UiConstants.space5,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@@ -193,31 +204,34 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
onTap: () => Modular.to.pop(),
|
||||
child: const Icon(
|
||||
UiIcons.arrowLeft,
|
||||
color: UiColors.bgPopup,
|
||||
color: UiColors.white,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Form I-9',
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.bgPopup,
|
||||
),
|
||||
style: UiTypography.headline4m.white,
|
||||
),
|
||||
Text(
|
||||
'Employment Eligibility Verification',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.bgPopup.withOpacity(0.7)),
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.white.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Row(
|
||||
children: _steps.asMap().entries.map((MapEntry<int, Map<String, String>> entry) {
|
||||
children: _steps
|
||||
.asMap()
|
||||
.entries
|
||||
.map((MapEntry<int, Map<String, String>> entry) {
|
||||
final int idx = entry.key;
|
||||
final bool isLast = idx == _steps.length - 1;
|
||||
return Expanded(
|
||||
@@ -228,8 +242,8 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: idx <= state.currentStep
|
||||
? UiColors.bgPopup
|
||||
: UiColors.bgPopup.withOpacity(0.3),
|
||||
? UiColors.white
|
||||
: UiColors.white.withValues(alpha: 0.3),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
@@ -240,20 +254,21 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Step ${state.currentStep + 1} of ${_steps.length}',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.bgPopup.withOpacity(0.7)),
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.white.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
_steps[state.currentStep]['title']!,
|
||||
textAlign: TextAlign.end,
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.bgPopup,
|
||||
style: UiTypography.body3m.white.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
@@ -292,8 +307,7 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
style: UiTypography.body3m.textSecondary.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
@@ -305,26 +319,26 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
),
|
||||
onChanged: onChanged,
|
||||
keyboardType: keyboardType,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
decoration: InputDecoration(
|
||||
hintText: placeholder,
|
||||
hintStyle: TextStyle(color: Colors.grey[400]),
|
||||
hintStyle: const TextStyle(color: UiColors.textPlaceholder),
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 16,
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.primary),
|
||||
),
|
||||
),
|
||||
@@ -455,15 +469,15 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'State *',
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
style: UiTypography.body3m.textSecondary.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
DropdownButtonFormField<String>(
|
||||
value: state.state.isEmpty ? null : state.state,
|
||||
onChanged: (String? val) => context.read<FormI9Cubit>().stateChanged(val ?? ''),
|
||||
onChanged: (String? val) =>
|
||||
context.read<FormI9Cubit>().stateChanged(val ?? ''),
|
||||
items: _usStates.map((String stateAbbr) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: stateAbbr,
|
||||
@@ -473,13 +487,15 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
),
|
||||
@@ -507,9 +523,9 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'I attest, under penalty of perjury, that I am (check one of the following boxes):',
|
||||
style: UiTypography.body2m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
_buildRadioOption(
|
||||
context,
|
||||
state,
|
||||
@@ -578,15 +594,21 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRadioOption(BuildContext context, FormI9State state, String value, String label, {Widget? child}) {
|
||||
Widget _buildRadioOption(
|
||||
BuildContext context,
|
||||
FormI9State state,
|
||||
String value,
|
||||
String label, {
|
||||
Widget? child,
|
||||
}) {
|
||||
final bool isSelected = state.citizenshipStatus == value;
|
||||
return GestureDetector(
|
||||
onTap: () => context.read<FormI9Cubit>().citizenshipStatusChanged(value),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(
|
||||
color: isSelected ? UiColors.primary : UiColors.border,
|
||||
width: isSelected ? 2 : 1,
|
||||
@@ -602,18 +624,16 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: isSelected ? UiColors.primary : Colors.grey,
|
||||
color: isSelected ? UiColors.primary : UiColors.border,
|
||||
width: isSelected ? 6 : 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Text(
|
||||
label,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -630,10 +650,10 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Column(
|
||||
@@ -643,15 +663,21 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
'Summary',
|
||||
style: UiTypography.headline4m.copyWith(fontSize: 14),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
_buildSummaryRow('Name', '${state.firstName} ${state.lastName}'),
|
||||
_buildSummaryRow('Address', '${state.address}, ${state.city}'),
|
||||
_buildSummaryRow('SSN', '***-**-${state.ssn.length >= 4 ? state.ssn.substring(state.ssn.length - 4) : '****'}'),
|
||||
_buildSummaryRow('Citizenship', _getReadableCitizenship(state.citizenshipStatus)),
|
||||
_buildSummaryRow(
|
||||
'SSN',
|
||||
'***-**-${state.ssn.length >= 4 ? state.ssn.substring(state.ssn.length - 4) : '****'}',
|
||||
),
|
||||
_buildSummaryRow(
|
||||
'Citizenship',
|
||||
_getReadableCitizenship(state.citizenshipStatus),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
CheckboxListTile(
|
||||
value: state.preparerUsed,
|
||||
onChanged: (bool? val) {
|
||||
@@ -660,29 +686,27 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
contentPadding: EdgeInsets.zero,
|
||||
title: Text(
|
||||
'I used a preparer or translator',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
controlAffinity: ListTileControlAffinity.leading,
|
||||
activeColor: UiColors.primary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.amber[50],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.accent.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'I am aware that federal law provides for imprisonment and/or fines for false statements or use of false documents in connection with the completion of this form.',
|
||||
style: TextStyle(fontSize: 12, color: Color(0xFFB45309)),
|
||||
style: UiTypography.body3r.textWarning.copyWith(fontSize: 12),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Text(
|
||||
'Signature (type your full name) *',
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3m.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
TextField(
|
||||
@@ -690,44 +714,46 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
..selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: state.signature.length),
|
||||
),
|
||||
onChanged: (String val) => context.read<FormI9Cubit>().signatureChanged(val),
|
||||
onChanged: (String val) =>
|
||||
context.read<FormI9Cubit>().signatureChanged(val),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Type your full name',
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 16,
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.primary),
|
||||
),
|
||||
),
|
||||
style: const TextStyle(fontFamily: 'Cursive', fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
'Date',
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3m.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF3F4F6),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.bgSecondary,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Text(
|
||||
@@ -747,15 +773,13 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
value,
|
||||
textAlign: TextAlign.end,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -780,7 +804,7 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
|
||||
Widget _buildFooter(BuildContext context, FormI9State state) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
border: Border(top: BorderSide(color: UiColors.border)),
|
||||
@@ -791,24 +815,30 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
if (state.currentStep > 0)
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
padding: const EdgeInsets.only(right: UiConstants.space3),
|
||||
child: OutlinedButton(
|
||||
onPressed: () => _handleBack(context),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
side: const BorderSide(color: UiColors.border),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.arrowLeft, size: 16, color: UiColors.textPrimary),
|
||||
const Icon(
|
||||
UiIcons.arrowLeft,
|
||||
size: 16,
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'Back',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -818,16 +848,20 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: ElevatedButton(
|
||||
onPressed: (_canProceed(state) && state.status != FormI9Status.submitting)
|
||||
onPressed: (
|
||||
_canProceed(state) &&
|
||||
state.status != FormI9Status.submitting)
|
||||
? () => _handleNext(context, state.currentStep)
|
||||
: null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
disabledBackgroundColor: Colors.grey[300],
|
||||
foregroundColor: UiColors.bgPopup,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
disabledBackgroundColor: UiColors.bgSecondary,
|
||||
foregroundColor: UiColors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
@@ -836,7 +870,7 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
color: UiColors.bgPopup,
|
||||
color: UiColors.white,
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
@@ -850,7 +884,7 @@ class _FormI9PageState extends State<FormI9Page> {
|
||||
),
|
||||
if (state.currentStep < _steps.length - 1) ...<Widget>[
|
||||
const SizedBox(width: 8),
|
||||
const Icon(UiIcons.arrowRight, size: 16, color: UiColors.bgPopup),
|
||||
const Icon(UiIcons.arrowRight, size: 16, color: UiColors.white),
|
||||
],
|
||||
],
|
||||
),
|
||||
|
||||
@@ -146,7 +146,10 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
_buildHeader(context, state),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 24),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space5,
|
||||
vertical: UiConstants.space6,
|
||||
),
|
||||
child: _buildCurrentStep(context, state),
|
||||
),
|
||||
),
|
||||
@@ -164,9 +167,9 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
backgroundColor: UiColors.background,
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
padding: const EdgeInsets.all(UiConstants.space6),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(32),
|
||||
padding: const EdgeInsets.all(UiConstants.space8),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(24),
|
||||
@@ -178,40 +181,40 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
Container(
|
||||
width: 64,
|
||||
height: 64,
|
||||
decoration: const BoxDecoration(
|
||||
color: Color(0xFFDCFCE7),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.tagSuccess,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
UiIcons.success,
|
||||
color: Color(0xFF16A34A),
|
||||
color: UiColors.textSuccess,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
'Form W-4 Submitted!',
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline4m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Text(
|
||||
'Your withholding certificate has been submitted to your employer.',
|
||||
textAlign: TextAlign.center,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Modular.to.pop(true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
foregroundColor: UiColors.bgPopup,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
foregroundColor: UiColors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
@@ -229,7 +232,12 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
Widget _buildHeader(BuildContext context, FormW4State state) {
|
||||
return Container(
|
||||
color: UiColors.primary,
|
||||
padding: const EdgeInsets.only(top: 60, bottom: 24, left: 20, right: 20),
|
||||
padding: const EdgeInsets.only(
|
||||
top: 60,
|
||||
bottom: UiConstants.space6,
|
||||
left: UiConstants.space5,
|
||||
right: UiConstants.space5,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
@@ -239,31 +247,34 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
onTap: () => Modular.to.pop(),
|
||||
child: const Icon(
|
||||
UiIcons.arrowLeft,
|
||||
color: UiColors.bgPopup,
|
||||
color: UiColors.white,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Form W-4',
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.bgPopup,
|
||||
),
|
||||
style: UiTypography.headline4m.white,
|
||||
),
|
||||
Text(
|
||||
'Employee\'s Withholding Certificate',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.bgPopup.withOpacity(0.7)),
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.white.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Row(
|
||||
children: _steps.asMap().entries.map((MapEntry<int, Map<String, String>> entry) {
|
||||
children: _steps
|
||||
.asMap()
|
||||
.entries
|
||||
.map((MapEntry<int, Map<String, String>> entry) {
|
||||
final int idx = entry.key;
|
||||
final bool isLast = idx == _steps.length - 1;
|
||||
return Expanded(
|
||||
@@ -274,8 +285,8 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: idx <= state.currentStep
|
||||
? UiColors.bgPopup
|
||||
: UiColors.bgPopup.withOpacity(0.3),
|
||||
? UiColors.white
|
||||
: UiColors.white.withValues(alpha: 0.3),
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
@@ -286,18 +297,19 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Step ${state.currentStep + 1} of ${_steps.length}',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.bgPopup.withOpacity(0.7)),
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.white.withValues(alpha: 0.7),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
_steps[state.currentStep]['title']!,
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.bgPopup,
|
||||
style: UiTypography.body3m.white.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
@@ -339,8 +351,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
style: UiTypography.body3m.textSecondary.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
@@ -352,26 +363,26 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
),
|
||||
onChanged: onChanged,
|
||||
keyboardType: keyboardType,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
decoration: InputDecoration(
|
||||
hintText: placeholder,
|
||||
hintStyle: TextStyle(color: Colors.grey[400]),
|
||||
hintStyle: const TextStyle(color: UiColors.textPlaceholder),
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 16,
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.primary),
|
||||
),
|
||||
),
|
||||
@@ -438,25 +449,25 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[50],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.tagActive,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
children: const <Widget>[
|
||||
Icon(UiIcons.info, color: Color(0xFF2563EB), size: 20),
|
||||
SizedBox(width: 12),
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.info, color: UiColors.primary, size: 20),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Your filing status determines your standard deduction and tax rates.',
|
||||
style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
_buildRadioOption(
|
||||
context,
|
||||
state,
|
||||
@@ -484,15 +495,21 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRadioOption(BuildContext context, FormW4State state, String value, String label, String? subLabel) {
|
||||
Widget _buildRadioOption(
|
||||
BuildContext context,
|
||||
FormW4State state,
|
||||
String value,
|
||||
String label,
|
||||
String? subLabel,
|
||||
) {
|
||||
final bool isSelected = state.filingStatus == value;
|
||||
return GestureDetector(
|
||||
onTap: () => context.read<FormW4Cubit>().filingStatusChanged(value),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(
|
||||
color: isSelected ? UiColors.primary : UiColors.border,
|
||||
width: isSelected ? 2 : 1,
|
||||
@@ -508,29 +525,25 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: isSelected ? UiColors.primary : Colors.grey,
|
||||
color: isSelected ? UiColors.primary : UiColors.border,
|
||||
width: isSelected ? 6 : 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
if (subLabel != null) ...<Widget>[
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
subLabel,
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
],
|
||||
@@ -546,36 +559,32 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.amber[50],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.accent.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Icon(
|
||||
const Icon(
|
||||
UiIcons.help,
|
||||
color: Color(0xFFD97706),
|
||||
color: UiColors.accent,
|
||||
size: 20,
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'When to complete this step?',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFF92400E),
|
||||
fontSize: 14,
|
||||
),
|
||||
style: UiTypography.body2m.accent,
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Complete this step only if you hold more than one job at a time, or are married filing jointly and your spouse also works.',
|
||||
style: TextStyle(fontSize: 12, color: Color(0xFFB45309)),
|
||||
style: UiTypography.body3r.accent,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -583,18 +592,17 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
GestureDetector(
|
||||
onTap: () => context.read<FormW4Cubit>().multipleJobsChanged(!state.multipleJobs),
|
||||
onTap: () =>
|
||||
context.read<FormW4Cubit>().multipleJobsChanged(!state.multipleJobs),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(
|
||||
color: state.multipleJobs
|
||||
? UiColors.primary
|
||||
: UiColors.border,
|
||||
color: state.multipleJobs ? UiColors.primary : UiColors.border,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
@@ -604,20 +612,16 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: state.multipleJobs
|
||||
? UiColors.primary
|
||||
: UiColors.bgPopup,
|
||||
color: state.multipleJobs ? UiColors.primary : UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(
|
||||
color: state.multipleJobs
|
||||
? UiColors.primary
|
||||
: Colors.grey,
|
||||
color: state.multipleJobs ? UiColors.primary : UiColors.border,
|
||||
),
|
||||
),
|
||||
child: state.multipleJobs
|
||||
? const Icon(
|
||||
UiIcons.check,
|
||||
color: UiColors.bgPopup,
|
||||
color: UiColors.white,
|
||||
size: 16,
|
||||
)
|
||||
: null,
|
||||
@@ -629,16 +633,12 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'I have multiple jobs or my spouse works',
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Check this box if there are only two jobs total',
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -651,7 +651,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
Text(
|
||||
'If this does not apply, you can continue to the next step',
|
||||
textAlign: TextAlign.center,
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -661,30 +661,30 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[50], // Same note about blue migration
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.tagActive,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: const Row(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Icon(UiIcons.info, color: Color(0xFF2563EB), size: 20),
|
||||
SizedBox(width: 12),
|
||||
const Icon(UiIcons.info, color: UiColors.primary, size: 20),
|
||||
const SizedBox(width: UiConstants.space3),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'If your total income will be \$200,000 or less (\$400,000 if married filing jointly), you may claim credits for dependents.',
|
||||
style: TextStyle(fontSize: 14, color: Color(0xFF1D4ED8)),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Column(
|
||||
@@ -715,10 +715,10 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
if (_totalCredits(state) > 0) ...<Widget>[
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFDCFCE7),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -770,16 +770,12 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFDCFCE7),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.tagSuccess,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Text(
|
||||
badge,
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
color: Color(0xFF15803D),
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
style: UiTypography.footnote2b.textSuccess,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -834,7 +830,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'These adjustments are optional. You can skip them if they don\'t apply.',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_buildTextField(
|
||||
@@ -848,7 +844,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 16),
|
||||
child: Text(
|
||||
'Include interest, dividends, retirement income',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -863,7 +859,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 16),
|
||||
child: Text(
|
||||
'If you expect to claim deductions other than the standard deduction',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -878,7 +874,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
padding: const EdgeInsets.only(top: 4, bottom: 16),
|
||||
child: Text(
|
||||
'Any additional tax you want withheld each pay period',
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -890,10 +886,10 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Column(
|
||||
@@ -927,22 +923,20 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.amber[50],
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.accent.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'Under penalties of perjury, I declare that this certificate, to the best of my knowledge and belief, is true, correct, and complete.',
|
||||
style: TextStyle(fontSize: 12, color: Color(0xFFB45309)),
|
||||
style: UiTypography.body3r.textWarning.copyWith(fontSize: 12),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
Text(
|
||||
'Signature (type your full name) *',
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3m.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
TextField(
|
||||
@@ -950,44 +944,46 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
..selection = TextSelection.fromPosition(
|
||||
TextPosition(offset: state.signature.length),
|
||||
),
|
||||
onChanged: (String val) => context.read<FormW4Cubit>().signatureChanged(val),
|
||||
onChanged: (String val) =>
|
||||
context.read<FormW4Cubit>().signatureChanged(val),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Type your full name',
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 16,
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.border),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: const BorderSide(color: UiColors.primary),
|
||||
),
|
||||
),
|
||||
style: const TextStyle(fontFamily: 'Cursive', fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
Text(
|
||||
'Date',
|
||||
style: UiTypography.body3m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3m.textSecondary,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF3F4F6),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: UiColors.bgSecondary,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
border: Border.all(color: UiColors.border),
|
||||
),
|
||||
child: Text(
|
||||
@@ -1007,7 +1003,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
label,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
@@ -1035,7 +1031,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
|
||||
Widget _buildFooter(BuildContext context, FormW4State state) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
border: Border(top: BorderSide(color: UiColors.border)),
|
||||
@@ -1046,24 +1042,30 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
if (state.currentStep > 0)
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 12),
|
||||
padding: const EdgeInsets.only(right: UiConstants.space3),
|
||||
child: OutlinedButton(
|
||||
onPressed: () => _handleBack(context),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
side: const BorderSide(color: UiColors.border),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
const Icon(UiIcons.arrowLeft, size: 16, color: UiColors.textPrimary),
|
||||
const Icon(
|
||||
UiIcons.arrowLeft,
|
||||
size: 16,
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'Back',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -1073,16 +1075,20 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: ElevatedButton(
|
||||
onPressed: (_canProceed(state) && state.status != FormW4Status.submitting)
|
||||
onPressed: (
|
||||
_canProceed(state) &&
|
||||
state.status != FormW4Status.submitting)
|
||||
? () => _handleNext(context, state.currentStep)
|
||||
: null,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: UiColors.primary,
|
||||
disabledBackgroundColor: Colors.grey[300],
|
||||
foregroundColor: UiColors.bgPopup,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
disabledBackgroundColor: UiColors.bgSecondary,
|
||||
foregroundColor: UiColors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
@@ -1091,7 +1097,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
color: UiColors.bgPopup,
|
||||
color: UiColors.white,
|
||||
strokeWidth: 2,
|
||||
),
|
||||
)
|
||||
@@ -1105,7 +1111,7 @@ class _FormW4PageState extends State<FormW4Page> {
|
||||
),
|
||||
if (state.currentStep < _steps.length - 1) ...<Widget>[
|
||||
const SizedBox(width: 8),
|
||||
const Icon(UiIcons.arrowRight, size: 16, color: UiColors.bgPopup),
|
||||
const Icon(UiIcons.arrowRight, size: 16, color: UiColors.white),
|
||||
],
|
||||
],
|
||||
),
|
||||
|
||||
@@ -22,7 +22,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
),
|
||||
title: Text(
|
||||
'Tax Documents',
|
||||
style: UiTypography.headline3m.copyWith(color: UiColors.bgPopup),
|
||||
style: UiTypography.headline3m.textSecondary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(24),
|
||||
@@ -38,7 +38,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
child: Text(
|
||||
'Complete required forms to start working',
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.bgPopup.withOpacity(0.8),
|
||||
color: UiColors.primaryForeground.withValues(alpha: 0.8),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -120,15 +120,11 @@ class TaxFormsPage extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Document Progress',
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
'$completedCount/$totalCount',
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -180,7 +176,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Center(child: Text(icon, style: UiTypography.headline1m)),
|
||||
@@ -195,9 +191,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
form.title,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline4m.textPrimary,
|
||||
),
|
||||
_buildStatusBadge(form.status),
|
||||
],
|
||||
@@ -205,17 +199,14 @@ class TaxFormsPage extends StatelessWidget {
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
form.subtitle ?? '',
|
||||
style: UiTypography.body2m.copyWith(
|
||||
style: UiTypography.body2m.textSecondary.copyWith(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
form.description ?? '',
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -256,9 +247,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text(
|
||||
'Completed',
|
||||
style: UiTypography.footnote2b.copyWith(
|
||||
color: UiColors.textSuccess,
|
||||
),
|
||||
style: UiTypography.footnote2b.textSuccess,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -280,9 +269,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text(
|
||||
'In Progress',
|
||||
style: UiTypography.footnote2b.copyWith(
|
||||
color: UiColors.textWarning,
|
||||
),
|
||||
style: UiTypography.footnote2b.textWarning,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -299,9 +286,7 @@ class TaxFormsPage extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
'Not Started',
|
||||
style: UiTypography.footnote2b.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.footnote2b.textSecondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -325,16 +310,12 @@ class TaxFormsPage extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'Why are these needed?',
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline4m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space1),
|
||||
Text(
|
||||
'I-9 and W-4 forms are required by federal law to verify your employment eligibility and set up correct tax withholding.',
|
||||
style: UiTypography.body3r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -37,7 +37,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
),
|
||||
title: Text(
|
||||
strings.title,
|
||||
style: UiTypography.headline3m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.headline3m.textPrimary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
@@ -165,7 +165,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.08),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
child: Row(
|
||||
@@ -179,15 +179,12 @@ class BankAccountPage extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
strings.secure_title,
|
||||
style: UiTypography.body2r.copyWith( // Was body2
|
||||
fontWeight: FontWeight.w500,
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
strings.secure_subtitle,
|
||||
style: UiTypography.body3r.copyWith(color: UiColors.textSecondary), // Was bodySmall
|
||||
style: UiTypography.body3r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -221,7 +218,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withOpacity(0.1),
|
||||
color: primaryColor.withValues(alpha: 0.1),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
),
|
||||
child: const Center(
|
||||
@@ -238,10 +235,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
account.bankName,
|
||||
style: UiTypography.body2r.copyWith( // Was body2
|
||||
fontWeight: FontWeight.w500,
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
strings.account_ending(
|
||||
@@ -249,9 +243,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
? account.last4!
|
||||
: '----',
|
||||
),
|
||||
style: UiTypography.body2r.copyWith( // Was body2
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -261,7 +253,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withOpacity(0.15),
|
||||
color: primaryColor.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
@@ -270,10 +262,7 @@ class BankAccountPage extends StatelessWidget {
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
strings.primary,
|
||||
style: UiTypography.body3r.copyWith( // Was bodySmall
|
||||
fontWeight: FontWeight.w500,
|
||||
color: primaryColor,
|
||||
),
|
||||
style: UiTypography.body3m.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -43,7 +43,7 @@ class _AddAccountFormState extends State<AddAccountForm> {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
widget.strings.add_new_account,
|
||||
style: UiTypography.headline4m.copyWith(color: UiColors.textPrimary), // Was header4
|
||||
style: UiTypography.headline4m.textPrimary, // Was header4
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
UiTextField(
|
||||
@@ -71,8 +71,7 @@ class _AddAccountFormState extends State<AddAccountForm> {
|
||||
padding: const EdgeInsets.only(bottom: UiConstants.space2),
|
||||
child: Text(
|
||||
widget.strings.account_type,
|
||||
style: UiTypography.body2r.copyWith( // Was body2
|
||||
color: UiColors.textSecondary, fontWeight: FontWeight.w500),
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
@@ -122,7 +121,7 @@ class _AddAccountFormState extends State<AddAccountForm> {
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? UiColors.primary.withOpacity(0.05)
|
||||
? UiColors.primary.withValues(alpha: 0.05)
|
||||
: UiColors.bgPopup, // Was surface
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
border: Border.all(
|
||||
@@ -133,8 +132,7 @@ class _AddAccountFormState extends State<AddAccountForm> {
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: UiTypography.body2r.copyWith( // Was body2
|
||||
fontWeight: FontWeight.w600,
|
||||
style: UiTypography.body2b.copyWith(
|
||||
color: isSelected ? UiColors.primary : UiColors.textSecondary,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -41,9 +41,7 @@ class _TimeCardPageState extends State<TimeCardPage> {
|
||||
),
|
||||
title: Text(
|
||||
t.staff_time_card.title,
|
||||
style: UiTypography.headline4m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline4m.textPrimary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
|
||||
@@ -19,22 +19,22 @@ class TimesheetCard extends StatelessWidget {
|
||||
|
||||
switch (status) {
|
||||
case TimeCardStatus.approved:
|
||||
statusBg = UiColors.textSuccess.withOpacity(0.12);
|
||||
statusBg = UiColors.tagSuccess;
|
||||
statusColor = UiColors.textSuccess;
|
||||
statusText = t.staff_time_card.status.approved;
|
||||
break;
|
||||
case TimeCardStatus.disputed:
|
||||
statusBg = UiColors.destructive.withOpacity(0.12);
|
||||
statusBg = UiColors.destructive.withValues(alpha: 0.12);
|
||||
statusColor = UiColors.destructive;
|
||||
statusText = t.staff_time_card.status.disputed;
|
||||
break;
|
||||
case TimeCardStatus.paid:
|
||||
statusBg = UiColors.primary.withOpacity(0.12);
|
||||
statusBg = UiColors.primary.withValues(alpha: 0.12);
|
||||
statusColor = UiColors.primary;
|
||||
statusText = t.staff_time_card.status.paid;
|
||||
break;
|
||||
case TimeCardStatus.pending:
|
||||
statusBg = UiColors.textWarning.withOpacity(0.12);
|
||||
statusBg = UiColors.tagPending;
|
||||
statusColor = UiColors.textWarning;
|
||||
statusText = t.staff_time_card.status.pending;
|
||||
break;
|
||||
@@ -61,15 +61,11 @@ class TimesheetCard extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
timesheet.shiftTitle,
|
||||
style: UiTypography.body1m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1m.textPrimary,
|
||||
),
|
||||
Text(
|
||||
timesheet.clientName,
|
||||
style: UiTypography.body2r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -116,13 +112,11 @@ class TimesheetCard extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
'${timesheet.totalHours.toStringAsFixed(1)} ${t.staff_time_card.hours} @ \$${timesheet.hourlyRate.toStringAsFixed(2)}${t.staff_time_card.per_hr}',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
Text(
|
||||
'\$${timesheet.totalPay.toStringAsFixed(2)}',
|
||||
style: UiTypography.title2b.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.title2b.primary,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -163,7 +157,7 @@ class _IconText extends StatelessWidget {
|
||||
const SizedBox(width: UiConstants.space1),
|
||||
Text(
|
||||
text,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -32,9 +32,7 @@ class AttirePage extends StatelessWidget {
|
||||
),
|
||||
title: Text(
|
||||
t.staff_profile_attire.title,
|
||||
style: UiTypography.headline3m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.headline3m.textPrimary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
|
||||
@@ -11,8 +11,8 @@ class AttireInfoCard extends StatelessWidget {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.primary.withOpacity(0.08),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.primary.withValues(alpha: 0.08),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -26,16 +26,12 @@ class AttireInfoCard extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Text(
|
||||
t.staff_profile_attire.info_card.title,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
t.staff_profile_attire.info_card.description,
|
||||
style: UiTypography.body2r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -24,12 +24,12 @@ class EmergencyContactScreen extends StatelessWidget {
|
||||
appBar: AppBar(
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: Icon(UiIcons.chevronLeft, color: UiColors.textSecondary),
|
||||
icon: const Icon(UiIcons.chevronLeft, color: UiColors.textSecondary),
|
||||
onPressed: () => Modular.to.pop(),
|
||||
),
|
||||
title: Text(
|
||||
'Emergency Contact',
|
||||
style: UiTypography.title1m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.title1m.textPrimary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
@@ -62,11 +62,11 @@ class EmergencyContactScreen extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(UiConstants.space6),
|
||||
padding: const EdgeInsets.all(UiConstants.space6),
|
||||
child: Column(
|
||||
children: [
|
||||
const EmergencyContactInfoBanner(),
|
||||
SizedBox(height: UiConstants.space6),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
...state.contacts.asMap().entries.map(
|
||||
(entry) => EmergencyContactFormItem(
|
||||
index: entry.key,
|
||||
@@ -75,7 +75,7 @@ class EmergencyContactScreen extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const EmergencyContactAddButton(),
|
||||
SizedBox(height: UiConstants.space16),
|
||||
const SizedBox(height: UiConstants.space16),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -12,20 +12,20 @@ class EmergencyContactAddButton extends StatelessWidget {
|
||||
child: TextButton.icon(
|
||||
onPressed: () =>
|
||||
context.read<EmergencyContactBloc>().add(EmergencyContactAdded()),
|
||||
icon: Icon(UiIcons.add, size: 20.0),
|
||||
icon: const Icon(UiIcons.add, size: 20.0),
|
||||
label: Text(
|
||||
'Add Another Contact',
|
||||
style: UiTypography.title2b,
|
||||
),
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: UiColors.primary,
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space6,
|
||||
vertical: UiConstants.space3,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: UiConstants.radiusFull,
|
||||
side: BorderSide(color: UiColors.primary),
|
||||
side: const BorderSide(color: UiColors.primary),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -19,8 +19,8 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
margin: EdgeInsets.only(bottom: UiConstants.space4),
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
margin: const EdgeInsets.only(bottom: UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
@@ -30,33 +30,27 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(context),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildLabel('Full Name'),
|
||||
_buildTextField(
|
||||
initialValue: contact.name,
|
||||
hint: 'Contact name',
|
||||
icon: UiIcons.user,
|
||||
onChanged: (val) => context.read<EmergencyContactBloc>().add(
|
||||
EmergencyContactUpdated(
|
||||
index,
|
||||
contact.copyWith(name: val),
|
||||
),
|
||||
),
|
||||
EmergencyContactUpdated(index, contact.copyWith(name: val)),
|
||||
),
|
||||
),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildLabel('Phone Number'),
|
||||
_buildTextField(
|
||||
initialValue: contact.phone,
|
||||
hint: '+1 (555) 000-0000',
|
||||
icon: UiIcons.phone,
|
||||
onChanged: (val) => context.read<EmergencyContactBloc>().add(
|
||||
EmergencyContactUpdated(
|
||||
index,
|
||||
contact.copyWith(phone: val),
|
||||
),
|
||||
),
|
||||
EmergencyContactUpdated(index, contact.copyWith(phone: val)),
|
||||
),
|
||||
),
|
||||
SizedBox(height: UiConstants.space4),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildLabel('Relationship'),
|
||||
_buildDropdown(
|
||||
context,
|
||||
@@ -65,11 +59,11 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
onChanged: (val) {
|
||||
if (val != null) {
|
||||
context.read<EmergencyContactBloc>().add(
|
||||
EmergencyContactUpdated(
|
||||
index,
|
||||
contact.copyWith(relationship: val),
|
||||
),
|
||||
);
|
||||
EmergencyContactUpdated(
|
||||
index,
|
||||
contact.copyWith(relationship: val),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
@@ -85,7 +79,7 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
required ValueChanged<RelationshipType?> onChanged,
|
||||
}) {
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space4,
|
||||
vertical: UiConstants.space2,
|
||||
),
|
||||
@@ -99,13 +93,13 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
value: value,
|
||||
isExpanded: true,
|
||||
dropdownColor: UiColors.bgPopup,
|
||||
icon: Icon(UiIcons.chevronDown, color: UiColors.iconSecondary),
|
||||
icon: const Icon(UiIcons.chevronDown, color: UiColors.iconSecondary),
|
||||
items: items.map((type) {
|
||||
return DropdownMenuItem<RelationshipType>(
|
||||
value: type,
|
||||
child: Text(
|
||||
_formatRelationship(type),
|
||||
style: UiTypography.body1r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body1r.textPrimary,
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
@@ -116,11 +110,15 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
}
|
||||
|
||||
String _formatRelationship(RelationshipType type) {
|
||||
switch(type) {
|
||||
case RelationshipType.family: return 'Family';
|
||||
case RelationshipType.spouse: return 'Spouse';
|
||||
case RelationshipType.friend: return 'Friend';
|
||||
case RelationshipType.other: return 'Other';
|
||||
switch (type) {
|
||||
case RelationshipType.family:
|
||||
return 'Family';
|
||||
case RelationshipType.spouse:
|
||||
return 'Spouse';
|
||||
case RelationshipType.friend:
|
||||
return 'Friend';
|
||||
case RelationshipType.other:
|
||||
return 'Other';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,22 +126,17 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Contact ${index + 1}',
|
||||
style: UiTypography.title2m.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
),
|
||||
Text('Contact ${index + 1}', style: UiTypography.title2m.textPrimary),
|
||||
if (totalContacts > 1)
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
icon: const Icon(
|
||||
UiIcons.delete,
|
||||
color: UiColors.textError,
|
||||
size: 20.0,
|
||||
),
|
||||
onPressed: () => context
|
||||
.read<EmergencyContactBloc>()
|
||||
.add(EmergencyContactRemoved(index)),
|
||||
onPressed: () => context.read<EmergencyContactBloc>().add(
|
||||
EmergencyContactRemoved(index),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -151,13 +144,8 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
|
||||
Widget _buildLabel(String label) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(bottom: UiConstants.space2),
|
||||
child: Text(
|
||||
label,
|
||||
style: UiTypography.body2m.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.only(bottom: UiConstants.space2),
|
||||
child: Text(label, style: UiTypography.body2m.textSecondary),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -169,16 +157,16 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
}) {
|
||||
return TextFormField(
|
||||
initialValue: initialValue,
|
||||
style: UiTypography.body1r.copyWith(
|
||||
color: UiColors.textPrimary,
|
||||
),
|
||||
style: UiTypography.body1r.textPrimary,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: TextStyle(color: UiColors.textPlaceholder),
|
||||
hintStyle: const TextStyle(color: UiColors.textPlaceholder),
|
||||
prefixIcon: Icon(icon, color: UiColors.textSecondary, size: 20.0),
|
||||
filled: true,
|
||||
fillColor: UiColors.bgPopup,
|
||||
contentPadding: EdgeInsets.symmetric(vertical: UiConstants.space4),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: UiConstants.space4,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
borderSide: BorderSide(color: UiColors.border),
|
||||
@@ -196,4 +184,3 @@ class EmergencyContactFormItem extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@ class EmergencyContactInfoBanner extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
color: UiColors.accent.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||
color: UiColors.accent.withValues(alpha: 0.2),
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: Text(
|
||||
'Please provide at least one emergency contact. This information will only be used in case of an emergency during your shifts.',
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -30,19 +30,18 @@ class EmergencyContactSaveButton extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
final isLoading = state.status == EmergencyContactStatus.saving;
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
border: Border(top: BorderSide(color: UiColors.border)),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: UiButton.primary(
|
||||
fullWidth: true,
|
||||
onPressed: state.isValid && !isLoading
|
||||
? () => _onSave(context)
|
||||
: null,
|
||||
onPressed:
|
||||
state.isValid && !isLoading ? () => _onSave(context) : null,
|
||||
child: isLoading
|
||||
? SizedBox(
|
||||
? const SizedBox(
|
||||
height: 20.0,
|
||||
width: 20.0,
|
||||
child: CircularProgressIndicator(
|
||||
|
||||
@@ -80,16 +80,16 @@ class ExperiencePage extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(UiConstants.space5),
|
||||
padding: const EdgeInsets.all(UiConstants.space5),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
ExperienceSectionTitle(title: i18n.industries_title),
|
||||
Text(
|
||||
i18n.industries_subtitle,
|
||||
style: UiTypography.body2m.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
),
|
||||
SizedBox(height: UiConstants.space3),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
@@ -97,23 +97,26 @@ class ExperiencePage extends StatelessWidget {
|
||||
.map(
|
||||
(i) => UiChip(
|
||||
label: _getIndustryLabel(i18n.industries, i),
|
||||
isSelected: state.selectedIndustries.contains(i),
|
||||
onTap: () => BlocProvider.of<ExperienceBloc>(context)
|
||||
.add(ExperienceIndustryToggled(i)),
|
||||
variant: state.selectedIndustries.contains(i)
|
||||
? UiChipVariant.primary
|
||||
: UiChipVariant.secondary,
|
||||
isSelected:
|
||||
state.selectedIndustries.contains(i),
|
||||
onTap: () =>
|
||||
BlocProvider.of<ExperienceBloc>(context)
|
||||
.add(ExperienceIndustryToggled(i)),
|
||||
variant:
|
||||
state.selectedIndustries.contains(i)
|
||||
? UiChipVariant.primary
|
||||
: UiChipVariant.secondary,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
SizedBox(height: UiConstants.space6),
|
||||
const SizedBox(height: UiConstants.space6),
|
||||
ExperienceSectionTitle(title: i18n.skills_title),
|
||||
Text(
|
||||
i18n.skills_subtitle,
|
||||
style: UiTypography.body2m.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
),
|
||||
SizedBox(height: UiConstants.space3),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
@@ -121,19 +124,22 @@ class ExperiencePage extends StatelessWidget {
|
||||
.map(
|
||||
(s) => UiChip(
|
||||
label: _getSkillLabel(i18n.skills, s),
|
||||
isSelected: state.selectedSkills.contains(s.value),
|
||||
onTap: () => BlocProvider.of<ExperienceBloc>(context)
|
||||
.add(ExperienceSkillToggled(s.value)),
|
||||
variant: state.selectedSkills.contains(s.value)
|
||||
? UiChipVariant.primary
|
||||
: UiChipVariant.secondary,
|
||||
isSelected:
|
||||
state.selectedSkills.contains(s.value),
|
||||
onTap: () =>
|
||||
BlocProvider.of<ExperienceBloc>(context)
|
||||
.add(ExperienceSkillToggled(s.value)),
|
||||
variant:
|
||||
state.selectedSkills.contains(s.value)
|
||||
? UiChipVariant.primary
|
||||
: UiChipVariant.secondary,
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
_buildSaveButton(context, state, i18n),
|
||||
],
|
||||
@@ -155,9 +161,9 @@ class ExperiencePage extends StatelessWidget {
|
||||
children: [
|
||||
Text(
|
||||
i18n.custom_skills_title,
|
||||
style: UiTypography.body2m.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2m.textSecondary,
|
||||
),
|
||||
SizedBox(height: UiConstants.space2),
|
||||
const SizedBox(height: UiConstants.space2),
|
||||
Wrap(
|
||||
spacing: UiConstants.space2,
|
||||
runSpacing: UiConstants.space2,
|
||||
@@ -172,10 +178,14 @@ class ExperiencePage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSaveButton(BuildContext context, ExperienceState state, dynamic i18n) {
|
||||
Widget _buildSaveButton(
|
||||
BuildContext context,
|
||||
ExperienceState state,
|
||||
dynamic i18n,
|
||||
) {
|
||||
return Container(
|
||||
padding: EdgeInsets.all(UiConstants.space4),
|
||||
decoration: BoxDecoration(
|
||||
padding: const EdgeInsets.all(UiConstants.space4),
|
||||
decoration: const BoxDecoration(
|
||||
color: UiColors.bgPopup,
|
||||
border: Border(top: BorderSide(color: UiColors.border)),
|
||||
),
|
||||
@@ -183,16 +193,21 @@ class ExperiencePage extends StatelessWidget {
|
||||
child: UiButton.primary(
|
||||
onPressed: state.status == ExperienceStatus.loading
|
||||
? null
|
||||
: () => BlocProvider.of<ExperienceBloc>(context).add(ExperienceSubmitted()),
|
||||
: () => BlocProvider.of<ExperienceBloc>(context)
|
||||
.add(ExperienceSubmitted()),
|
||||
fullWidth: true,
|
||||
text: state.status == ExperienceStatus.loading ? null : i18n.save_button,
|
||||
text: state.status == ExperienceStatus.loading
|
||||
? null
|
||||
: i18n.save_button,
|
||||
child: state.status == ExperienceStatus.loading
|
||||
? SizedBox(
|
||||
? const SizedBox(
|
||||
height: 20.0,
|
||||
width: 20.0,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(UiColors.white), // UiColors.primaryForeground is white mostly
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
UiColors.white,
|
||||
), // UiColors.primaryForeground is white mostly
|
||||
),
|
||||
)
|
||||
: null,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import 'package:core_localization/core_localization.dart';
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -56,13 +55,16 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
backgroundColor: UiColors.bgPopup,
|
||||
elevation: 0,
|
||||
leading: IconButton(
|
||||
icon: const Icon(UiIcons.chevronLeft, color: UiColors.textSecondary),
|
||||
icon: const Icon(
|
||||
UiIcons.chevronLeft,
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
onPressed: () => Modular.to.pop(),
|
||||
tooltip: MaterialLocalizations.of(context).backButtonTooltip,
|
||||
),
|
||||
title: Text(
|
||||
i18n.title,
|
||||
style: UiTypography.title1m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.title1m.textPrimary,
|
||||
),
|
||||
bottom: PreferredSize(
|
||||
preferredSize: const Size.fromHeight(1.0),
|
||||
@@ -86,9 +88,7 @@ class PersonalInfoPage extends StatelessWidget {
|
||||
return Center(
|
||||
child: Text(
|
||||
'Failed to load personal information',
|
||||
style: UiTypography.body1r.copyWith(
|
||||
color: UiColors.textSecondary,
|
||||
),
|
||||
style: UiTypography.body1r.textSecondary,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ class _FieldLabel extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return Text(
|
||||
text,
|
||||
style: UiTypography.body2m.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2m.textPrimary,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,6 @@ class _FieldLabel extends StatelessWidget {
|
||||
/// A read-only field widget for displaying non-editable information.
|
||||
/// A read-only field widget for displaying non-editable information.
|
||||
class _ReadOnlyField extends StatelessWidget {
|
||||
|
||||
const _ReadOnlyField({required this.value});
|
||||
final String value;
|
||||
|
||||
@@ -120,7 +119,7 @@ class _ReadOnlyField extends StatelessWidget {
|
||||
),
|
||||
child: Text(
|
||||
value,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -129,7 +128,6 @@ class _ReadOnlyField extends StatelessWidget {
|
||||
/// An editable text field widget.
|
||||
/// An editable text field widget.
|
||||
class _EditableField extends StatelessWidget {
|
||||
|
||||
const _EditableField({
|
||||
required this.controller,
|
||||
required this.hint,
|
||||
@@ -150,10 +148,10 @@ class _EditableField extends StatelessWidget {
|
||||
enabled: enabled,
|
||||
keyboardType: keyboardType,
|
||||
autofillHints: autofillHints,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textPrimary),
|
||||
style: UiTypography.body2r.textPrimary,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
hintStyle: UiTypography.body2r.textSecondary,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: UiConstants.space3,
|
||||
vertical: UiConstants.space3,
|
||||
|
||||
@@ -28,7 +28,8 @@ class ProfilePhotoWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n = t.staff.onboarding.personal_info;
|
||||
final TranslationsStaffOnboardingPersonalInfoEn i18n =
|
||||
t.staff.onboarding.personal_info;
|
||||
|
||||
return Column(
|
||||
children: <Widget>[
|
||||
@@ -41,7 +42,7 @@ class ProfilePhotoWidget extends StatelessWidget {
|
||||
height: 96,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: UiColors.primary.withOpacity(0.1),
|
||||
color: UiColors.primary.withValues(alpha: 0.1),
|
||||
),
|
||||
child: photoUrl != null
|
||||
? ClipOval(
|
||||
@@ -53,9 +54,7 @@ class ProfilePhotoWidget extends StatelessWidget {
|
||||
: Center(
|
||||
child: Text(
|
||||
fullName.isNotEmpty ? fullName[0].toUpperCase() : '?',
|
||||
style: UiTypography.displayL.copyWith(
|
||||
color: UiColors.primary,
|
||||
),
|
||||
style: UiTypography.displayL.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -71,7 +70,7 @@ class ProfilePhotoWidget extends StatelessWidget {
|
||||
border: Border.all(color: UiColors.border),
|
||||
boxShadow: <BoxShadow>[
|
||||
BoxShadow(
|
||||
color: UiColors.textPrimary.withOpacity(0.1),
|
||||
color: UiColors.textPrimary.withValues(alpha: 0.1),
|
||||
blurRadius: UiConstants.space1,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
@@ -92,7 +91,7 @@ class ProfilePhotoWidget extends StatelessWidget {
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
Text(
|
||||
i18n.change_photo_hint,
|
||||
style: UiTypography.body2r.copyWith(color: UiColors.textSecondary),
|
||||
style: UiTypography.body2r.textSecondary,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user