Skip to content

Commit 7036fbd

Browse files
authored
Merge pull request #468 from Gopher-Industries/AbhishekGhimires225777323/fix/timesheet-shift-label
Timesheet shift label
2 parents ac647cf + 0b1b223 commit 7036fbd

2 files changed

Lines changed: 44 additions & 8 deletions

File tree

guard_app/src/screen/TimeSheetsScreen.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,10 @@ import {
1414
TouchableOpacity,
1515
} from 'react-native';
1616

17+
import { myShifts, type ShiftDto } from '../api/shifts';
1718
import { getAllMyTimesheets, type Timesheet } from '../api/timesheets';
1819
import { useAppTheme } from '../theme';
19-
import {
20-
formatHours,
21-
formatShiftDate,
22-
formatTimesheetDateTime,
23-
sumHours,
24-
} from '../utils/timesheet';
20+
import { fmtShiftLabel, formatHours, formatTimesheetDateTime, sumHours } from '../utils/timesheet';
2521

2622
import type { RootStackParamList } from '../navigation/AppNavigator';
2723
import type { AppColors } from '../theme/colors';
@@ -37,13 +33,18 @@ export default function TimesheetsScreen() {
3733
const [loading, setLoading] = useState(true);
3834
const [refreshing, setRefreshing] = useState(false);
3935
const [items, setItems] = useState<Timesheet[]>([]);
36+
const [shiftsById, setShiftsById] = useState<Record<string, ShiftDto>>({});
4037
const [error, setError] = useState<string | null>(null);
4138

4239
const load = async () => {
4340
try {
4441
setError(null);
45-
const rows = await getAllMyTimesheets();
42+
const [rows, shifts] = await Promise.all([
43+
getAllMyTimesheets(),
44+
myShifts().catch(() => [] as ShiftDto[]),
45+
]);
4646
setItems(rows);
47+
setShiftsById(Object.fromEntries(shifts.map((shift) => [shift._id, shift])));
4748
} catch (e: unknown) {
4849
let msg = t('timesheet.error');
4950

@@ -82,7 +83,7 @@ export default function TimesheetsScreen() {
8283
style={s.card}
8384
onPress={() => navigation.navigate('TimesheetDetails', { timesheetId: item.id })}
8485
>
85-
<Text style={s.title}>{formatShiftDate(item.shiftDate)}</Text>
86+
<Text style={s.title}>{fmtShiftLabel(shiftsById[item.shiftId], item.shiftId)}</Text>
8687

8788
<View style={s.row}>
8889
<Text style={s.label}>{t('timesheet.checkIn')}</Text>

guard_app/src/utils/timesheet.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type { ShiftDto } from '../api/shifts';
2+
13
export function formatTimesheetDateTime(value?: string | null) {
24
if (!value) return '—';
35
const dt = new Date(value);
@@ -16,6 +18,39 @@ export function formatShiftDate(value?: string | null) {
1618
});
1719
}
1820

21+
// same as formatShiftDate but with a weekday, for the "Title • Date • Time" row label
22+
function formatShiftLabelDate(value?: string | null) {
23+
if (!value) return '';
24+
const dt = new Date(value);
25+
if (Number.isNaN(dt.getTime())) return '';
26+
return dt.toLocaleDateString(undefined, {
27+
weekday: 'short',
28+
day: 'numeric',
29+
month: 'short',
30+
year: 'numeric',
31+
timeZone: 'UTC',
32+
});
33+
}
34+
35+
function formatShiftTimeRange(startTime?: string | null, endTime?: string | null) {
36+
if (startTime && endTime) return `${startTime}${endTime}`;
37+
return startTime || endTime || '';
38+
}
39+
40+
// builds "Title • Date • Time" from a shift, falling back to the raw id when the
41+
// shift can't be resolved (e.g. the guard's shift list hasn't loaded it)
42+
export function fmtShiftLabel(shift: ShiftDto | undefined, shiftId: string) {
43+
if (!shift) return `Shift ID: ${shiftId}`;
44+
45+
const parts = [
46+
shift.title?.trim(),
47+
formatShiftLabelDate(shift.date),
48+
formatShiftTimeRange(shift.startTime, shift.endTime),
49+
].filter((part): part is string => Boolean(part));
50+
51+
return parts.length > 0 ? parts.join(' • ') : `Shift ID: ${shiftId}`;
52+
}
53+
1954
export function formatHours(value?: number | null) {
2055
return typeof value === 'number' && Number.isFinite(value) ? String(value) : '—';
2156
}

0 commit comments

Comments
 (0)