fix(detail): handle non-Z timezone offsets in Last Seen

Backend sends ISO timestamps with +00:00 offset. Code blindly appended
'Z' when the string didn't end with 'Z', producing '...+00:00Z' which
parses to Invalid Date.

Detect any timezone marker (Z, z, or numeric offset like +00:00) and
only append 'Z' for naive datetimes.

Co-authored-by:
This commit is contained in:
Pouzor
2026-05-10 21:45:22 +02:00
parent ebdf6cb55b
commit 3f9866e8a1
2 changed files with 24 additions and 1 deletions
@@ -234,7 +234,7 @@ export function DetailPanel({ onEdit }: DetailPanelProps) {
{data.mac && <DetailRow label="MAC" value={data.mac} mono />}
{data.os && <DetailRow label="OS" value={data.os} />}
{data.check_method && <DetailRow label="Check" value={data.check_method} mono />}
{data.last_seen && <DetailRow label="Last Seen" value={new Date(data.last_seen.endsWith('Z') ? data.last_seen : data.last_seen + 'Z').toLocaleString()} />}
{data.last_seen && <DetailRow label="Last Seen" value={new Date(/[Zz]|[+-]\d{2}:?\d{2}$/.test(data.last_seen) ? data.last_seen : data.last_seen + 'Z').toLocaleString()} />}
</div>
{/* Properties section */}
@@ -487,4 +487,27 @@ describe('DetailPanel', () => {
expect(screen.getByText('health').tagName).not.toBe('A')
})
})
describe('Last Seen formatting', () => {
it('renders a valid date when last_seen has +00:00 offset (no Z)', () => {
setupStore({ last_seen: '2026-05-10T17:54:38.221403+00:00' })
render(<DetailPanel onEdit={vi.fn()} />)
const row = screen.getByText('Last Seen').parentElement
expect(row?.textContent).not.toMatch(/Invalid Date/)
})
it('renders a valid date when last_seen ends with Z', () => {
setupStore({ last_seen: '2026-05-10T17:54:38.221403Z' })
render(<DetailPanel onEdit={vi.fn()} />)
const row = screen.getByText('Last Seen').parentElement
expect(row?.textContent).not.toMatch(/Invalid Date/)
})
it('treats naive ISO strings as UTC', () => {
setupStore({ last_seen: '2026-05-10T17:54:38' })
render(<DetailPanel onEdit={vi.fn()} />)
const row = screen.getByText('Last Seen').parentElement
expect(row?.textContent).not.toMatch(/Invalid Date/)
})
})
})