correction of change view for recurring and permant - show permanet and recurring in find shift

This commit is contained in:
José Salazar
2026-02-18 19:23:15 -05:00
parent 83457a0a9b
commit 8b6061cb30
6 changed files with 323 additions and 13 deletions

View File

@@ -227,6 +227,8 @@ class ShiftsRepositoryImpl
filledSlots: sr.assigned ?? 0,
latitude: sr.shift.latitude,
longitude: sr.shift.longitude,
orderId: sr.shift.order.id,
orderType: sr.shift.order.orderType?.stringValue,
breakInfo: BreakAdapter.fromData(
isPaid: sr.isBreakPaid ?? false,
breakTime: sr.breakType?.stringValue,

View File

@@ -77,6 +77,13 @@ class _MyShiftCardState extends State<MyShiftCard> {
String _getShiftType() {
// Handling potential localization key availability
try {
final String orderType = (widget.shift.orderType ?? '').toUpperCase();
if (orderType == 'PERMANENT') {
return t.staff_shifts.filter.long_term;
}
if (orderType == 'RECURRING') {
return t.staff_shifts.filter.multi_day;
}
if (widget.shift.durationDays != null && widget.shift.durationDays! > 30) {
return t.staff_shifts.filter.long_term;
}
@@ -133,6 +140,24 @@ class _MyShiftCardState extends State<MyShiftCard> {
statusText = status?.toUpperCase() ?? "";
}
final schedules = widget.shift.schedules ?? <ShiftSchedule>[];
final hasSchedules = schedules.isNotEmpty;
final List<ShiftSchedule> visibleSchedules = schedules.length <= 5
? schedules
: schedules.take(3).toList();
final int remainingSchedules =
schedules.length <= 5 ? 0 : schedules.length - 3;
final String scheduleRange = hasSchedules
? () {
final first = schedules.first.date;
final last = schedules.last.date;
if (first == last) {
return _formatDate(first);
}
return '${_formatDate(first)} ${_formatDate(last)}';
}()
: '';
return GestureDetector(
onTap: () {
Modular.to.pushNamed(
@@ -299,7 +324,55 @@ class _MyShiftCardState extends State<MyShiftCard> {
const SizedBox(height: UiConstants.space2),
// Date & Time
if (widget.shift.durationDays != null &&
if (hasSchedules) ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
const Icon(
UiIcons.clock,
size: UiConstants.iconXs,
color: UiColors.primary,
),
const SizedBox(width: UiConstants.space1),
Text(
'${schedules.length} schedules',
style: UiTypography.footnote2m.copyWith(
color: UiColors.primary,
),
),
],
),
const SizedBox(height: UiConstants.space1),
Padding(
padding: const EdgeInsets.only(bottom: 2),
child: Text(
scheduleRange,
style: UiTypography.footnote2r.copyWith(color: UiColors.primary),
),
),
...visibleSchedules.map(
(schedule) => Padding(
padding: const EdgeInsets.only(bottom: 2),
child: Text(
'${_formatDate(schedule.date)}, ${_formatTime(schedule.startTime)} ${_formatTime(schedule.endTime)}',
style: UiTypography.footnote2r.copyWith(
color: UiColors.primary,
),
),
),
),
if (remainingSchedules > 0)
Text(
'+$remainingSchedules more schedules',
style: UiTypography.footnote2r.copyWith(
color: UiColors.primary.withOpacity(0.7),
),
),
],
),
] else if (widget.shift.durationDays != null &&
widget.shift.durationDays! > 1) ...[
Column(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -324,17 +397,22 @@ class _MyShiftCardState extends State<MyShiftCard> {
),
const SizedBox(height: UiConstants.space1),
Padding(
padding: const EdgeInsets.only(bottom: 2),
child: Text(
'${_formatDate(widget.shift.date)}, ${_formatTime(widget.shift.startTime)} ${_formatTime(widget.shift.endTime)}',
style: UiTypography.footnote2r.copyWith(color: UiColors.primary),
padding: const EdgeInsets.only(bottom: 2),
child: Text(
'${_formatDate(widget.shift.date)}, ${_formatTime(widget.shift.startTime)} ${_formatTime(widget.shift.endTime)}',
style: UiTypography.footnote2r.copyWith(
color: UiColors.primary,
),
),
),
if (widget.shift.durationDays! > 1)
Text(
'... +${widget.shift.durationDays! - 1} more days',
style: UiTypography.footnote2r.copyWith(color: UiColors.primary.withOpacity(0.7)),
)
Text(
'... +${widget.shift.durationDays! - 1} more days',
style: UiTypography.footnote2r.copyWith(
color:
UiColors.primary.withOpacity(0.7),
),
)
],
),
] else ...[

View File

@@ -20,6 +20,119 @@ class _FindShiftsTabState extends State<FindShiftsTab> {
String _searchQuery = '';
String _jobType = 'all';
bool _isRecurring(Shift shift) =>
(shift.orderType ?? '').toUpperCase() == 'RECURRING';
bool _isPermanent(Shift shift) =>
(shift.orderType ?? '').toUpperCase() == 'PERMANENT';
DateTime? _parseShiftDate(String date) {
if (date.isEmpty) return null;
try {
return DateTime.parse(date);
} catch (_) {
return null;
}
}
List<Shift> _groupMultiDayShifts(List<Shift> shifts) {
final Map<String, List<Shift>> grouped = <String, List<Shift>>{};
for (final shift in shifts) {
if (!_isRecurring(shift) && !_isPermanent(shift)) {
continue;
}
final orderId = shift.orderId;
final roleId = shift.roleId;
if (orderId == null || roleId == null) {
continue;
}
final key = '$orderId::$roleId';
grouped.putIfAbsent(key, () => <Shift>[]).add(shift);
}
final Set<String> addedGroups = <String>{};
final List<Shift> result = <Shift>[];
for (final shift in shifts) {
if (!_isRecurring(shift) && !_isPermanent(shift)) {
result.add(shift);
continue;
}
final orderId = shift.orderId;
final roleId = shift.roleId;
if (orderId == null || roleId == null) {
result.add(shift);
continue;
}
final key = '$orderId::$roleId';
if (addedGroups.contains(key)) {
continue;
}
addedGroups.add(key);
final List<Shift> group = grouped[key] ?? <Shift>[];
if (group.isEmpty) {
result.add(shift);
continue;
}
group.sort((a, b) {
final ad = _parseShiftDate(a.date);
final bd = _parseShiftDate(b.date);
if (ad == null && bd == null) return 0;
if (ad == null) return 1;
if (bd == null) return -1;
return ad.compareTo(bd);
});
final Shift first = group.first;
final List<ShiftSchedule> schedules = group
.map((s) => ShiftSchedule(
date: s.date,
startTime: s.startTime,
endTime: s.endTime,
))
.toList();
result.add(
Shift(
id: first.id,
roleId: first.roleId,
title: first.title,
clientName: first.clientName,
logoUrl: first.logoUrl,
hourlyRate: first.hourlyRate,
location: first.location,
locationAddress: first.locationAddress,
date: first.date,
startTime: first.startTime,
endTime: first.endTime,
createdDate: first.createdDate,
tipsAvailable: first.tipsAvailable,
travelTime: first.travelTime,
mealProvided: first.mealProvided,
parkingAvailable: first.parkingAvailable,
gasCompensation: first.gasCompensation,
description: first.description,
instructions: first.instructions,
managers: first.managers,
latitude: first.latitude,
longitude: first.longitude,
status: first.status,
durationDays: schedules.length,
requiredSlots: first.requiredSlots,
filledSlots: first.filledSlots,
hasApplied: first.hasApplied,
totalValue: first.totalValue,
breakInfo: first.breakInfo,
orderId: first.orderId,
orderType: first.orderType,
schedules: schedules,
),
);
}
return result;
}
Widget _buildFilterTab(String id, String label) {
final isSelected = _jobType == id;
return GestureDetector(
@@ -49,8 +162,10 @@ class _FindShiftsTabState extends State<FindShiftsTab> {
@override
Widget build(BuildContext context) {
final groupedJobs = _groupMultiDayShifts(widget.availableJobs);
// Filter logic
final filteredJobs = widget.availableJobs.where((s) {
final filteredJobs = groupedJobs.where((s) {
final matchesSearch =
s.title.toLowerCase().contains(_searchQuery.toLowerCase()) ||
s.location.toLowerCase().contains(_searchQuery.toLowerCase()) ||
@@ -60,10 +175,15 @@ class _FindShiftsTabState extends State<FindShiftsTab> {
if (_jobType == 'all') return true;
if (_jobType == 'one-day') {
if (_isRecurring(s) || _isPermanent(s)) return false;
return s.durationDays == null || s.durationDays! <= 1;
}
if (_jobType == 'multi-day') {
return s.durationDays != null && s.durationDays! > 1;
return _isRecurring(s) ||
(s.durationDays != null && s.durationDays! > 1);
}
if (_jobType == 'long-term') {
return _isPermanent(s);
}
return true;
}).toList();