Add sync error logging, extend error flash, fix unload saves

- Log workforce sync errors to backend stdout so they appear in docker logs
- Extend error flash from 5s to 15s so errors are readable
- Replace sendBeacon (POST-only) with keepalive fetch (PUT) on unload —
  sendBeacon was hitting 404s on all three unload saves

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-22 14:19:38 +00:00
parent c7066521ff
commit 18e24efbeb
14485 changed files with 1836116 additions and 33 deletions

View file

@ -2,20 +2,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { NavLink } from 'react-router-dom';
import { CalendarClock, Settings, LogOut } from 'lucide-react';
import { can } from '../types';
import { useFrameViewport } from '../hooks/useFrameViewport';
export function Layout({ user, children }) {
useFrameViewport('desktop');
async function logout() {
await fetch('/api/auth/logout', { method: 'POST', credentials: 'include' });
window.location.href = '/';
await fetch('/hk-planner/api/auth/logout', { method: 'POST', credentials: 'include' });
window.location.reload();
}
return (_jsxs("div", { style: { display: 'flex', height: '100dvh', overflow: 'hidden' }, children: [_jsxs("nav", { style: {
width: '200px', flexShrink: 0, background: 'var(--navy)',
display: 'flex', flexDirection: 'column', padding: '1rem 0',
borderRight: '1px solid var(--surface-2)',
}, children: [_jsxs("div", { style: { padding: '0 1rem 1rem', borderBottom: '1px solid var(--surface-2)' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [_jsx(CalendarClock, { size: 20, strokeWidth: 1.75, color: "#74c69d" }), _jsx("span", { style: { color: '#74c69d', fontWeight: 700, fontSize: '0.95rem' }, children: "HK Planner" })] }), _jsx("p", { style: { color: 'var(--text-muted)', fontSize: '0.72rem', marginTop: '0.2rem' }, children: user.name })] }), _jsxs("div", { className: "nav-scroll", style: { flex: 1, padding: '0.5rem 0', overflowY: 'auto' }, children: [_jsx(NavItem, { to: "/planner", icon: CalendarClock, label: "Planner" }), can(user, 'settings') && _jsx(NavItem, { to: "/settings", icon: Settings, label: "Settings" })] }), _jsx("div", { style: { padding: '0.75rem 1rem', borderTop: '1px solid var(--surface-2)' }, children: _jsxs("button", { onClick: logout, style: {
display: 'flex', alignItems: 'center', gap: '0.5rem',
background: 'none', border: 'none', color: 'var(--text-muted)',
fontSize: '0.875rem', padding: '0.375rem 0', width: '100%', cursor: 'pointer',
}, children: [_jsx(LogOut, { size: 14, strokeWidth: 1.75 }), "Sign out"] }) })] }), _jsx("main", { style: { flex: 1, overflow: 'auto', background: 'var(--body-bg)' }, children: children })] }));
}, children: [_jsx("div", { style: { padding: '0 1rem 1rem', borderBottom: '1px solid var(--surface-2)' }, children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem' }, children: [_jsx(CalendarClock, { size: 20, strokeWidth: 1.75, color: "#74c69d" }), _jsx("span", { style: { color: '#74c69d', fontWeight: 700, fontSize: '0.95rem' }, children: "HK Planner" })] }) }), _jsxs("div", { className: "nav-scroll", style: { flex: 1, padding: '0.5rem 0', overflowY: 'auto' }, children: [_jsx(NavItem, { to: "/planner", icon: CalendarClock, label: "Planner" }), can(user, 'settings') && _jsx(NavItem, { to: "/settings", icon: Settings, label: "Settings" })] }), _jsxs("div", { style: { padding: '0.75rem 1rem', borderTop: '1px solid var(--surface-2)' }, children: [_jsxs("div", { style: { marginBottom: '0.5rem' }, children: [_jsx("div", { style: { color: 'var(--text)', fontSize: '0.8rem', fontWeight: 600 }, children: user.name }), _jsx("div", { style: { color: 'var(--text-muted)', fontSize: '0.72rem' }, children: user.email })] }), _jsxs("button", { onClick: logout, style: {
display: 'flex', alignItems: 'center', gap: '0.5rem',
background: 'none', border: 'none', color: 'var(--text-muted)',
fontSize: '0.8rem', padding: '0.375rem 0', width: '100%', cursor: 'pointer',
}, children: [_jsx(LogOut, { size: 14, strokeWidth: 1.75 }), "Sign out"] })] })] }), _jsx("main", { style: { flex: 1, overflow: 'auto', background: 'var(--body-bg)' }, children: children })] }));
}
function NavItem({ to, icon: Icon, label }) {
return (_jsxs(NavLink, { to: to, style: ({ isActive }) => ({