- Implemented `getBenefitsHistory` method in `HomeRepository` to retrieve paginated benefit history. - Enhanced `BenefitsOverviewCubit` to manage loading and displaying benefit history. - Created `BenefitHistoryPage` for full-screen display of benefit history with infinite scroll support. - Added `BenefitHistoryPreview` widget for expandable history preview in benefit cards. - Introduced `BenefitHistoryRow` to display individual history records. - Updated `BenefitsOverviewState` to include history management fields. - Added new entities and use cases for handling benefit history. - Created design system documentation for UI patterns and known gaps.
3.3 KiB
name, description, type
| name | description | type |
|---|---|---|
| KROW Staff App Component Patterns | Established UI patterns, widget conventions, and design decisions confirmed in the KROW staff app codebase | project |
Card Pattern (standard surface)
Cards use:
UiColors.cardViewBackground(white) backgroundBorder.all(color: UiColors.border)outlineBorderRadius.circular(UiConstants.radiusBase)= 12dpEdgeInsets.all(UiConstants.space4)= 16dp padding
Do NOT use UiColors.bgSecondary as card background — that is for toggles/headers inside cards.
Section Toggle / Expand-Collapse Header
Used for collapsible sections inside cards:
- Background:
UiColors.bgSecondary - Radius:
UiConstants.radiusMd(6dp) - Height: minimum 48dp (touch target)
- Label:
UiTypography.titleUppercase3m.textSecondaryfor ALL-CAPS labels - Trailing:
UiIcons.chevronDownanimated 180° viaAnimatedRotation, 200ms - Ripple:
InkWellwithborderRadius: UiConstants.radiusMdand splashUiColors.primary.withValues(alpha: 0.06)
Shimmer Loading Pattern
Use UiShimmer wrapper + UiShimmerLine / UiShimmerBox / UiShimmerCircle primitives.
- Base color:
UiColors.muted - Highlight:
UiColors.background - For list content: 3 shimmer rows by default
- Do NOT use fixed height containers for shimmer — let content flow
Status Badge (read-only, non-interactive)
Custom Container with pill shape:
borderRadius: UiConstants.radiusFullpadding: EdgeInsets.symmetric(horizontal: space2, vertical: 2)- Label style:
UiTypography.footnote2b - Do NOT use the interactive
UiChipwidget for read-only display
Status color mapping:
- ACTIVE: bg=
tagActive, fg=textSuccess - PENDING: bg=
tagPending, fg=textWarning - INACTIVE/ENDED: bg=
tagFreeze, fg=textSecondary - ERROR: bg=
tagError, fg=textError
Inline Error Banner (inside card)
NOT a full-page error — a compact container inside the widget:
- bg:
UiColors.tagError - radius:
UiConstants.radiusMd - Icon:
UiIcons.erroraticonMd(20dp), color:UiColors.destructive - Title:
body2m.textError - Retry link:
body3r.primarywithTextDecoration.underline
Inline Empty State (inside card)
NOT UiEmptyState widget (that is full-page). Use compact inline version:
Icon(UiIcons.clock, size: iconXl=32, color: UiColors.iconDisabled)body2r.textSecondarylabelEdgeInsets.symmetric(vertical: space6)padding
AnimatedSize for Expand/Collapse
AnimatedSize(
duration: const Duration(milliseconds: 250),
curve: Curves.easeInOut,
child: isExpanded ? content : const SizedBox.shrink(),
)
Benefits Feature Structure
Legacy benefits: apps/mobile/legacy/legacy-staff-app/lib/features/profile/benefits/
V2 domain entity: apps/mobile/packages/domain/lib/src/entities/benefits/benefit.dart
V2 history entity: needs creation at packages/domain/lib/src/entities/benefits/benefit_history.dart
Benefit history is lazy-loaded per card (not with the initial overview fetch).
History state is cached in BLoC as Map<String, AsyncValue<List<BenefitHistory>>> keyed by benefitId.
Screen Page Pattern (overview pages)
Uses CustomScrollView with SliverList for header + SliverPadding wrapping SliverList.separated for content.
Bottom padding on content sliver: EdgeInsets.fromLTRB(16, 16, 16, 120) to clear bottom nav bar.