history ready

This commit is contained in:
José Salazar
2026-02-02 07:26:07 +09:00
parent 761830b380
commit b7b7709386
10 changed files with 20296 additions and 19372 deletions

View File

@@ -101,7 +101,55 @@ class ShiftsRepositoryImpl implements ShiftsRepositoryInterface {
@override
Future<List<Shift>> getHistoryShifts() async {
return _fetchApplications(dc.ApplicationStatus.CHECKED_OUT);
try {
final staffId = await _getStaffId();
final response = await _dataConnect
.listCompletedApplicationsByStaffId(staffId: staffId)
.execute();
final List<Shift> shifts = [];
for (final app in response.data.applications) {
_shiftToAppIdMap[app.shift.id] = app.id;
_appToRoleIdMap[app.id] = app.shiftRole.id;
final String roleName = app.shiftRole.role.name;
final String orderName =
(app.shift.order.eventName ?? '').trim().isNotEmpty
? app.shift.order.eventName!
: app.shift.order.business.businessName;
final String title = '$roleName - $orderName';
final DateTime? shiftDate = _toDateTime(app.shift.date);
final DateTime? startDt = _toDateTime(app.shiftRole.startTime);
final DateTime? endDt = _toDateTime(app.shiftRole.endTime);
final DateTime? createdDt = _toDateTime(app.createdAt);
shifts.add(
Shift(
id: app.shift.id,
roleId: app.shiftRole.roleId,
title: title,
clientName: app.shift.order.business.businessName,
logoUrl: app.shift.order.business.companyLogoUrl,
hourlyRate: app.shiftRole.role.costPerHour,
location: app.shift.location ?? '',
locationAddress: app.shift.order.teamHub.hubName,
date: shiftDate?.toIso8601String() ?? '',
startTime: startDt != null ? DateFormat('HH:mm').format(startDt) : '',
endTime: endDt != null ? DateFormat('HH:mm').format(endDt) : '',
createdDate: createdDt?.toIso8601String() ?? '',
status: _mapStatus(dc.ApplicationStatus.CHECKED_OUT),
description: app.shift.description,
durationDays: app.shift.durationDays,
requiredSlots: app.shiftRole.count,
filledSlots: app.shiftRole.assigned ?? 0,
hasApplied: true,
),
);
}
return shifts;
} catch (e) {
return <Shift>[];
}
}
Future<List<Shift>> _fetchApplications(

View File

@@ -29,6 +29,7 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
required this.getHistoryShifts,
}) : super(ShiftsInitial()) {
on<LoadShiftsEvent>(_onLoadShifts);
on<LoadHistoryShiftsEvent>(_onLoadHistoryShifts);
on<LoadShiftsForRangeEvent>(_onLoadShiftsForRange);
on<FilterAvailableShiftsEvent>(_onFilterAvailableShifts);
}
@@ -51,7 +52,6 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
);
final pendingResult = await getPendingAssignments();
final cancelledResult = await getCancelledShifts();
final historyResult = await getHistoryShifts();
// Initial available with defaults
final availableResult = await getAvailableShifts(const GetAvailableShiftsArguments());
@@ -61,7 +61,9 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
pendingShifts: pendingResult,
cancelledShifts: cancelledResult,
availableShifts: _filterPastShifts(availableResult),
historyShifts: historyResult,
historyShifts: const [],
historyLoading: false,
historyLoaded: false,
searchQuery: '',
jobType: 'all',
));
@@ -70,6 +72,27 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
}
}
Future<void> _onLoadHistoryShifts(
LoadHistoryShiftsEvent event,
Emitter<ShiftsState> emit,
) async {
final currentState = state;
if (currentState is! ShiftsLoaded) return;
if (currentState.historyLoading || currentState.historyLoaded) return;
emit(currentState.copyWith(historyLoading: true));
try {
final historyResult = await getHistoryShifts();
emit(currentState.copyWith(
historyShifts: historyResult,
historyLoading: false,
historyLoaded: true,
));
} catch (_) {
emit(currentState.copyWith(historyLoading: false));
}
}
Future<void> _onLoadShiftsForRange(
LoadShiftsForRangeEvent event,
Emitter<ShiftsState> emit,
@@ -87,7 +110,6 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
final pendingResult = await getPendingAssignments();
final cancelledResult = await getCancelledShifts();
final historyResult = await getHistoryShifts();
final availableResult =
await getAvailableShifts(const GetAvailableShiftsArguments());
@@ -96,7 +118,9 @@ class ShiftsBloc extends Bloc<ShiftsEvent, ShiftsState> {
pendingShifts: pendingResult,
cancelledShifts: cancelledResult,
availableShifts: _filterPastShifts(availableResult),
historyShifts: historyResult,
historyShifts: const [],
historyLoading: false,
historyLoaded: false,
searchQuery: '',
jobType: 'all',
));

View File

@@ -10,6 +10,8 @@ sealed class ShiftsEvent extends Equatable {
class LoadShiftsEvent extends ShiftsEvent {}
class LoadHistoryShiftsEvent extends ShiftsEvent {}
class LoadShiftsForRangeEvent extends ShiftsEvent {
final DateTime start;
final DateTime end;

View File

@@ -18,6 +18,8 @@ class ShiftsLoaded extends ShiftsState {
final List<Shift> cancelledShifts;
final List<Shift> availableShifts;
final List<Shift> historyShifts;
final bool historyLoading;
final bool historyLoaded;
final String searchQuery;
final String jobType;
@@ -27,6 +29,8 @@ class ShiftsLoaded extends ShiftsState {
required this.cancelledShifts,
required this.availableShifts,
required this.historyShifts,
required this.historyLoading,
required this.historyLoaded,
required this.searchQuery,
required this.jobType,
});
@@ -37,6 +41,8 @@ class ShiftsLoaded extends ShiftsState {
List<Shift>? cancelledShifts,
List<Shift>? availableShifts,
List<Shift>? historyShifts,
bool? historyLoading,
bool? historyLoaded,
String? searchQuery,
String? jobType,
}) {
@@ -46,6 +52,8 @@ class ShiftsLoaded extends ShiftsState {
cancelledShifts: cancelledShifts ?? this.cancelledShifts,
availableShifts: availableShifts ?? this.availableShifts,
historyShifts: historyShifts ?? this.historyShifts,
historyLoading: historyLoading ?? this.historyLoading,
historyLoaded: historyLoaded ?? this.historyLoaded,
searchQuery: searchQuery ?? this.searchQuery,
jobType: jobType ?? this.jobType,
);
@@ -58,6 +66,8 @@ class ShiftsLoaded extends ShiftsState {
cancelledShifts,
availableShifts,
historyShifts,
historyLoading,
historyLoaded,
searchQuery,
jobType,
];

View File

@@ -29,6 +29,9 @@ class _ShiftsPageState extends State<ShiftsPage> {
_activeTab = widget.initialTab ?? 'myshifts';
_selectedDate = widget.selectedDate;
_bloc.add(LoadShiftsEvent());
if (_activeTab == 'history') {
_bloc.add(LoadHistoryShiftsEvent());
}
}
@override
@@ -67,6 +70,12 @@ class _ShiftsPageState extends State<ShiftsPage> {
final List<Shift> historyShifts = (state is ShiftsLoaded)
? state.historyShifts
: [];
final bool historyLoading = (state is ShiftsLoaded)
? state.historyLoading
: false;
final bool historyLoaded = (state is ShiftsLoaded)
? state.historyLoaded
: false;
// Note: "filteredJobs" logic moved to FindShiftsTab
// Note: Calendar logic moved to MyShiftsTab
@@ -120,6 +129,7 @@ class _ShiftsPageState extends State<ShiftsPage> {
"History",
UiIcons.clock,
historyShifts.length,
showCount: historyLoaded,
),
],
),
@@ -133,11 +143,12 @@ class _ShiftsPageState extends State<ShiftsPage> {
? const Center(child: CircularProgressIndicator())
: _buildTabContent(
myShifts,
pendingAssignments,
cancelledShifts,
availableJobs,
historyShifts,
),
pendingAssignments,
cancelledShifts,
availableJobs,
historyShifts,
historyLoading,
),
),
],
),
@@ -153,6 +164,7 @@ class _ShiftsPageState extends State<ShiftsPage> {
List<Shift> cancelledShifts,
List<Shift> availableJobs,
List<Shift> historyShifts,
bool historyLoading,
) {
switch (_activeTab) {
case 'myshifts':
@@ -165,17 +177,31 @@ class _ShiftsPageState extends State<ShiftsPage> {
case 'find':
return FindShiftsTab(availableJobs: availableJobs);
case 'history':
if (historyLoading) {
return const Center(child: CircularProgressIndicator());
}
return HistoryShiftsTab(historyShifts: historyShifts);
default:
return const SizedBox.shrink();
}
}
Widget _buildTab(String id, String label, IconData icon, int count) {
Widget _buildTab(
String id,
String label,
IconData icon,
int count, {
bool showCount = true,
}) {
final isActive = _activeTab == id;
return Expanded(
child: GestureDetector(
onTap: () => setState(() => _activeTab = id),
onTap: () {
setState(() => _activeTab = id);
if (id == 'history') {
_bloc.add(LoadHistoryShiftsEvent());
}
},
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 8),
decoration: BoxDecoration(
@@ -205,27 +231,32 @@ class _ShiftsPageState extends State<ShiftsPage> {
overflow: TextOverflow.ellipsis,
),
),
const SizedBox(width: 4),
Container(
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
constraints: const BoxConstraints(minWidth: 18),
decoration: BoxDecoration(
color: isActive
? AppColors.krowBlue.withAlpha((0.1 * 255).round())
: Colors.white.withAlpha((0.2 * 255).round()),
borderRadius: BorderRadius.circular(999),
),
child: Center(
child: Text(
"$count",
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: isActive ? AppColors.krowBlue : Colors.white,
if (showCount) ...[
const SizedBox(width: 4),
Container(
padding: const EdgeInsets.symmetric(
horizontal: 6,
vertical: 2,
),
constraints: const BoxConstraints(minWidth: 18),
decoration: BoxDecoration(
color: isActive
? AppColors.krowBlue.withAlpha((0.1 * 255).round())
: Colors.white.withAlpha((0.2 * 255).round()),
borderRadius: BorderRadius.circular(999),
),
child: Center(
child: Text(
"$count",
style: TextStyle(
fontSize: 10,
fontWeight: FontWeight.bold,
color: isActive ? AppColors.krowBlue : Colors.white,
),
),
),
),
),
],
],
),
),