The scaffold had the brand right and nothing behind it: the login was a 600ms setTimeout with a TODO, and three pieces of the frontgen deploy contract were missing. - Sign in against POST /usr/login (org_id as a STRING — a number is rejected by the gateway) with the session in a provider; surface the gateway's own message rather than a generic "invalid credentials", because a wrong password and a user without access to this app look identical from here and are not. - Runtime config: the API URL is read from the config.js the server writes at placement, never compiled in, and requireConfigValue throws so a build with no config.js fails loudly instead of calling whichever backend built it. - base: './' plus a router basename taken from <base href>, so one build serves any mount path. - Move the fonts and logo from public/ into src/assets/ — Vite rewrites bundled asset URLs to be relative, while a public/ file referenced as "/fonts/..." stays absolute and 404s under the /zurich-kotak/ mount. - API client for recordview / detailview / form-screens / start / activity, and the pipeline shell whose sidebar is the state machine in the order a lead moves. Queue and lead-file data wait on the record and detail views. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
72 lines
2.4 KiB
JavaScript
72 lines
2.4 KiB
JavaScript
import { NavLink, Outlet } from 'react-router-dom'
|
|
import { useZino } from '../api/provider.jsx'
|
|
import { STAGES } from '../api/config.js'
|
|
import logo from '../assets/brand/zurich_logo.webp'
|
|
import './Shell.css'
|
|
|
|
/**
|
|
* The sidebar IS the pipeline, in the order a lead moves — so the shape of the
|
|
* process is legible before any record is opened. The one human queue is marked
|
|
* as such, because it is the only place the machine stops.
|
|
*/
|
|
export default function Shell() {
|
|
const { user, signOut } = useZino()
|
|
const work = STAGES.filter((s) => s.kind !== 'end')
|
|
const closed = STAGES.filter((s) => s.kind === 'end')
|
|
|
|
return (
|
|
<div className="shell">
|
|
<header className="shell__top">
|
|
<div className="shell__brand">
|
|
<img src={logo} alt="Zurich Kotak General Insurance" />
|
|
<div>
|
|
<strong>Lead Desk</strong>
|
|
<span>Lead to Policy</span>
|
|
</div>
|
|
</div>
|
|
<div className="shell__who">
|
|
<div className="shell__user">
|
|
<strong>{user?.name || user?.email || 'Signed in'}</strong>
|
|
<span>{user?.email}</span>
|
|
</div>
|
|
<button type="button" className="shell__signout" onClick={signOut}>
|
|
Sign out
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div className="shell__body">
|
|
<nav className="shell__nav" aria-label="Pipeline">
|
|
<p className="shell__navlabel">Pipeline</p>
|
|
{work.map((s) => (
|
|
<NavLink
|
|
key={s.uid}
|
|
to={`/stage/${s.uid}`}
|
|
className={({ isActive }) =>
|
|
'shell__stage' + (isActive ? ' is-active' : '') + (s.kind === 'human' ? ' is-human' : '')
|
|
}
|
|
>
|
|
<span className="shell__stagename">{s.name}</span>
|
|
{s.kind === 'human' ? <span className="shell__badge">you</span> : null}
|
|
</NavLink>
|
|
))}
|
|
<p className="shell__navlabel shell__navlabel--closed">Closed</p>
|
|
{closed.map((s) => (
|
|
<NavLink
|
|
key={s.uid}
|
|
to={`/stage/${s.uid}`}
|
|
className={({ isActive }) => 'shell__stage' + (isActive ? ' is-active' : '')}
|
|
>
|
|
<span className="shell__stagename">{s.name}</span>
|
|
</NavLink>
|
|
))}
|
|
</nav>
|
|
|
|
<main className="shell__main">
|
|
<Outlet />
|
|
</main>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|