- 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.
88 lines
3.3 KiB
Markdown
88 lines
3.3 KiB
Markdown
---
|
|
name: KROW Staff App Component Patterns
|
|
description: Established UI patterns, widget conventions, and design decisions confirmed in the KROW staff app codebase
|
|
type: project
|
|
---
|
|
|
|
## Card Pattern (standard surface)
|
|
|
|
Cards use:
|
|
- `UiColors.cardViewBackground` (white) background
|
|
- `Border.all(color: UiColors.border)` outline
|
|
- `BorderRadius.circular(UiConstants.radiusBase)` = 12dp
|
|
- `EdgeInsets.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.textSecondary` for ALL-CAPS labels
|
|
- Trailing: `UiIcons.chevronDown` animated 180° via `AnimatedRotation`, 200ms
|
|
- Ripple: `InkWell` with `borderRadius: UiConstants.radiusMd` and splash `UiColors.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.radiusFull`
|
|
- `padding: EdgeInsets.symmetric(horizontal: space2, vertical: 2)`
|
|
- Label style: `UiTypography.footnote2b`
|
|
- Do NOT use the interactive `UiChip` widget 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.error` at `iconMd` (20dp), color: `UiColors.destructive`
|
|
- Title: `body2m.textError`
|
|
- Retry link: `body3r.primary` with `TextDecoration.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.textSecondary` label
|
|
- `EdgeInsets.symmetric(vertical: space6)` padding
|
|
|
|
## AnimatedSize for Expand/Collapse
|
|
|
|
```dart
|
|
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.
|