import { useState } from 'react' import { NavLink, Outlet, useNavigate } from 'react-router-dom' import { ASK_DESK_ROLES, NAV_GROUPS, STAGES } from '../api/config.js' import { rolesOf, visibleStages } from '../api/permissions.js' import { useStageCounts } from '../api/portfolio.jsx' import { useZino } from '../api/provider.jsx' import AskDesk from '../components/AskDesk.jsx' import logo from '../assets/brand/zurich_logo.webp' /** * The frame: a navy bar that stays put, and a drawer behind the hamburger. * * On a phone the queues cannot live beside the content, and stacked above it * they cost a screenful before the first lead. So they go in a drawer, and the * bar carries the only two things worth permanent space: where you are, and * who you are. */ /** Two letters for the avatar: a name if we have one, else the local part. */ function initials(user) { const from = user?.name || user?.email || '' const parts = from.replace(/@.*$/, '').split(/[\s._-]+/).filter(Boolean) if (!parts.length) return '?' return (parts[0][0] + (parts[1]?.[0] || '')).toUpperCase() } /** The badge colour is the colour of whoever is being waited on. */ function tone(stage) { if (stage.kind === 'needs') return 'red' if (stage.kind === 'customer') return 'amber' return 'grey' } /** A queue's icon, chosen for what it is waiting on rather than decoration. */ function NavIcon({ kind }) { if (kind === 'needs') { return } if (kind === 'customer') { return } if (kind === 'waiting') { return } return } export default function Shell() { const { user, signOut } = useZino() const navigate = useNavigate() const roles = rolesOf(user) const stages = visibleStages(roles) const { counts, ready } = useStageCounts() const [open, setOpen] = useState(false) const [me, setMe] = useState(false) // The support desk reads the WHOLE book — every partner, every premium — so // it is an ops tool rather than something a partner agent may open. The // platform enforces that too (the desk is assigned per user); this only // decides whether the entry is drawn. const [desk, setDesk] = useState(false) const canAskDesk = ASK_DESK_ROLES.some((r) => roles.includes(r)) const count = (s) => counts[s.uid] || { total: 0, waiting: 0, working: 0, urgent: 0 } const openTotal = STAGES.filter((s) => s.kind !== 'end').reduce((t, s) => t + count(s).total, 0) const row = (s) => { const c = count(s) const n = s.kind === 'end' ? c.total : c.waiting const t = tone(s) return ( setOpen(false)} className={({ isActive }) => 'nav nav--' + (s.kind === 'customer' ? 'teal' : s.kind === 'needs' ? 'red' : 'blue') + (isActive ? ' is-on' : '')} > {s.need ?? s.name} {ready ? {n} : null} ) } return (
{/* The real mark rather than type set to look like it — see the console's masthead. Bundled from src/assets, so the URL is rewritten relative and resolves under the sub-path mount. */} Zurich Kotak General Insurance
{open ? ( <>
setOpen(false)} /> ) : null} {me ? ( <>
setMe(false)} />
) : null} {desk ? setDesk(false)} /> : null}
) }