frontend: defensive coercion in Bookings table

`b.totalHoursBooked.toFixed(1)` would crash if Airtable ever returned
null/undefined for the rollup field; coerce through Number() with 0
fallback. Also coerce nullable department/resourceName in the client-
side filter check to ''.

Flagged by the previous frontend audit as a follow-up risk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
DJP 2026-05-17 20:56:35 -04:00
parent e1db93ad4a
commit 9e9daa3ec0

View file

@ -54,8 +54,8 @@ export default function Bookings() {
const filtered = useMemo(() => {
return bookings.filter((b) => {
if (filters.departments.length && !filters.departments.includes(b.department)) return false;
if (filters.names.length && !filters.names.includes(b.resourceName)) return false;
if (filters.departments.length && !filters.departments.includes(b.department ?? '')) return false;
if (filters.names.length && !filters.names.includes(b.resourceName ?? '')) return false;
return true;
});
}, [bookings, filters.departments, filters.names]);
@ -155,7 +155,7 @@ export default function Bookings() {
<div className="truncate" title={b.projectName}>{b.projectName}</div>
<div className="truncate" title={b.task}>{b.task}</div>
<div className="truncate text-slate-500">{b.startDate} {b.endDate}</div>
<div className="text-right tabular-nums">{b.totalHoursBooked.toFixed(1)}</div>
<div className="text-right tabular-nums">{(Number(b.totalHoursBooked) || 0).toFixed(1)}</div>
<div className="truncate text-slate-500">{b.bookingStatus}</div>
</div>
))}