feat: add benefit history feature with lazy loading and pagination

- 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.
This commit is contained in:
Achintha Isuru
2026-03-18 17:21:30 -04:00
parent 1552f60e5b
commit 9039aa63d6
22 changed files with 1047 additions and 19 deletions

View File

@@ -72,6 +72,7 @@ export 'src/entities/orders/recent_order.dart';
// Financial & Payroll
export 'src/entities/benefits/benefit.dart';
export 'src/entities/benefits/benefit_history.dart';
export 'src/entities/financial/invoice.dart';
export 'src/entities/financial/billing_account.dart';
export 'src/entities/financial/current_bill.dart';

View File

@@ -0,0 +1,100 @@
import 'package:equatable/equatable.dart';
import 'package:krow_domain/src/entities/enums/benefit_status.dart';
/// A historical record of a staff benefit accrual period.
///
/// Returned by `GET /staff/profile/benefits/history`.
class BenefitHistory extends Equatable {
/// Creates a [BenefitHistory] instance.
const BenefitHistory({
required this.historyId,
required this.benefitId,
required this.benefitType,
required this.title,
required this.status,
required this.effectiveAt,
required this.trackedHours,
required this.targetHours,
this.endedAt,
this.notes,
});
/// Deserialises a [BenefitHistory] from a V2 API JSON map.
factory BenefitHistory.fromJson(Map<String, dynamic> json) {
return BenefitHistory(
historyId: json['historyId'] as String,
benefitId: json['benefitId'] as String,
benefitType: json['benefitType'] as String,
title: json['title'] as String,
status: BenefitStatus.fromJson(json['status'] as String?),
effectiveAt: DateTime.parse(json['effectiveAt'] as String),
endedAt: json['endedAt'] != null
? DateTime.parse(json['endedAt'] as String)
: null,
trackedHours: (json['trackedHours'] as num).toInt(),
targetHours: (json['targetHours'] as num).toInt(),
notes: json['notes'] as String?,
);
}
/// Unique identifier for this history record.
final String historyId;
/// The benefit this record belongs to.
final String benefitId;
/// Type code (e.g. SICK_LEAVE, VACATION).
final String benefitType;
/// Human-readable title.
final String title;
/// Status of the benefit during this period.
final BenefitStatus status;
/// When this benefit period became effective.
final DateTime effectiveAt;
/// When this benefit period ended, or `null` if still active.
final DateTime? endedAt;
/// Hours tracked during this period.
final int trackedHours;
/// Target hours for this period.
final int targetHours;
/// Optional notes about the accrual.
final String? notes;
/// Serialises this [BenefitHistory] to a JSON map.
Map<String, dynamic> toJson() {
return <String, dynamic>{
'historyId': historyId,
'benefitId': benefitId,
'benefitType': benefitType,
'title': title,
'status': status.toJson(),
'effectiveAt': effectiveAt.toIso8601String(),
'endedAt': endedAt?.toIso8601String(),
'trackedHours': trackedHours,
'targetHours': targetHours,
'notes': notes,
};
}
@override
List<Object?> get props => <Object?>[
historyId,
benefitId,
benefitType,
title,
status,
effectiveAt,
endedAt,
trackedHours,
targetHours,
notes,
];
}