| @@ -65,10 +65,18 @@ | ||
| 65 | 65 | * one day early. Building the Date from its parts pins it to the intended |
| 66 | 66 | * calendar day regardless of timezone. Datetime strings (with a time part) and |
| 67 | 67 | * Date objects are parsed/returned as before. |
| 68 | 68 | */ |
| 69 | -export function toDateValue(value: string | Date): Date { | |
| 70 | - if (typeof value !== "string") return value; | |
| 69 | +export function toDateValue(value: string | Date | null | undefined): Date { | |
| 70 | + // Never hand back a non-Date. This previously returned `value` unchanged for | |
| 71 | + // anything that wasn't a string, so a missing date came back as `undefined` | |
| 72 | + // and the caller's `.toLocaleDateString()` threw — taking the whole admin | |
| 73 | + // dashboard down with it via the error boundary. An Invalid Date keeps every | |
| 74 | + // caller's date maths working (comparisons are simply false) and lets the | |
| 75 | + // display helpers fall back to "-". | |
| 76 | + if (value === null || value === undefined) return new Date(NaN); | |
| 77 | + if (value instanceof Date) return value; | |
| 78 | + if (typeof value !== "string") return new Date(NaN); | |
| 71 | 79 | const dateOnly = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim()); |
| 72 | 80 | if (dateOnly) { |
| 73 | 81 | return new Date( |
| 74 | 82 | Number(dateOnly[1]), |