Go to file
Yashas e90e4204ec console: redesign the UI — one card language, icons, filters, live trail
Visual and information-architecture pass across every screen. No API call,
payload, poll, permission rule or workflow mirror changes; forms still render
from the live schema and the timeline's merge/grouping is unchanged (only the
display order is reversible).

Design language
- Ground + white cards with one hairline and one radius; sentence-case
  headings; shared primitives in index.css (.card .pill .btn .avatar .live).
- One inline icon set (components/Icon.jsx); no more filled navy/red tiles.
- Read-side labels in api/display.js: roles and enum tokens humanized,
  customer initials/tones, money and date formatters. Nothing sent changes.

Shell
- 56px header with brand, global lead search (portfolio rows, "/" to focus)
  and identity chip with a human role label.
- Sidebar rows carry icons and a clear active bar; AI roster at the foot,
  each opening its remit card.

Login
- Operator copy instead of retail copy; centred sign-in card with show/hide
  password; demo persona picker that fills the EMAIL only.

Overview
- "Who holds the work" as four quiet cards that warm only when owed.
- Pipeline flow bar with every stage named beneath it; KPI strip in a card.
- Action rows with chevron / view-only eye; expiry bands filter the table.

Queues
- Filter bar (search, product, channel, expiry band, stalled, hide closed)
  and sortable columns, all client-side on the fetched page.
- Avatars, product/channel chips, stage chips for closed leads, tinted
  stalled rows, count inline with the title.

Lead
- Avatar + chips in the header; metrics card with the stage rail inside,
  and a branch node for Referred / Parked / Lost / Declined.
- Timeline newest-first by default (toggle), the worker's face as the node,
  one footer row per entry, AI markdown rendered as bold.
- "AI team on this lead" panel with per-agent step counts; PDF tags on docs.

Forms & dialogs
- Required marked with an asterisk + legend; "Select…" placeholder; dd Mon
  yyyy hint under date inputs; open activity form in a titled panel;
  one-line dialog footnotes.

Fixes: horizontal overflow at 1024px, boxed "in N days" figure, raw tokens
(sme_underwriter, verbal_call, Rsa), findings cut at "1.".

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 11:37:42 +05:30
public/brand Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30
src console: redesign the UI — one card language, icons, filters, live trail 2026-09-09 11:37:42 +05:30
.env.example Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30
.gitignore Updated to new frontend specifications 2026-09-04 13:26:20 +05:30
CLAUDE.md console: redesign the UI — one card language, icons, filters, live trail 2026-09-09 11:37:42 +05:30
eslint.config.js Empty vite-react project 2026-08-24 12:27:21 +05:30
index.html console: flat single-canvas design language, in the Zurich Kotak brand 2026-09-09 01:21:55 +05:30
package-lock.json Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30
package.json Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30
README.md Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30
vite.config.js Wire the console to the platform and make it deployable 2026-08-24 15:20:13 +05:30

Zurich Kotak — Lead Desk

Operator console for the Zurich Kotak "Lead to Policy" demo. Leads arrive through three channels — direct, bancassurance and agency — and run one state machine to policy issuance. The agents do the work; a person appears at one queue.

Workflow config is seeded from sm2/custom-apps/zurich-kotak/ (org 84, app 536, workflow zk_wf_lead). Design doc: sm2/app-designs/zurich-kotak/design.html. Workflow spec PDF: sm2/custom-apps/zurich-kotak/zurich-kotak-workflow.pdf.

Run it

npm install
npm run dev          # http://localhost:5175
npm run build        # → dist/

.env carries the API host for local dev only:

VITE_ZINO_API_URL=https://dev.getzino.in

Logins (all password ZurichKotak@2026, org 84):

Email Role Can do
sanjay.uw@zurichkotak.example SME Underwriter Clear / Decline Referral — the only human decision
meera.rm@zurichkotak.example Bancassurance RM Submit a Partner Bank Lead
arjun.posp@zurichkotak.example POSP / Broker Submit a Partner Agent Lead
kavya.csr@zurichkotak.example Direct / Call centre Submit a Self-Serve Lead
deepa.ops@zurichkotak.example Operations Cross-channel visibility

Sign in as Sanjay to land in Referred to Underwriting, which is where the demo happens.

How it talks to the platform

Everything goes through src/api/client.js:

  • POST /usr/login — auth. org_id must be a string; a number returns cannot unmarshal number into Go struct field LoginRequest.org_id.
  • POST /app/536/view/recordview — every queue is one record view (zk-rv-leads) filtered server-side on current_state_name.
  • POST /app/536/view/form-screens then POST /app/536/activity — forms are read from the live activity schema and submitted straight back.

Forms are not defined in this repo

Whatever /view/form-screens returns is what renders — labels, types, select options, which fields are mandatory. Add a field to an activity in Studio, redeploy, and it appears here with no frontend change. That is deliberate: the workflow is the source of truth, and a hardcoded form would quietly diverge from it.

Permissions are never enforced here

The console does not hide a button to stop someone using it. Every permission decision is the workflow's, made server-side on each submission — the platform refuses and this app reports what it said. Two refusals worth knowing: /activity answers 403, /start answers 400, and both carry permission denied.

The runtime-config contract

VITE_ZINO_API_URL is read at runtime from a config.js the server writes when it places the build — never compiled in. One artifact is promoted between environments unchanged, so a build-time URL would point every environment at whichever backend happened to build it. requireConfigValue throws if it is missing, so a production build with no config.js fails loudly rather than calling the wrong backend.

vite.config.js uses base: './' and the router takes its basename from the <base href> the server writes, so one build serves any mount path. Do not reintroduce a build-time base.

This is also why the fonts and logo live under src/assets/ and not public/. Vite rewrites bundled asset URLs to be relative; a public/ file referenced as /fonts/… stays absolute and 404s under the /zurich-kotak/ mount path. The favicon is the one exception — it stays in public/brand/ and is referenced relatively from index.html.

Deployment

Registered with frontgen by sm2/custom-apps/zurich-kotak/05_frontgen_project.sql (slug zurich-kotak, repo_name zurich_kotak, org 84). A push to main builds and serves at https://preview-dev.getzino.in/zurich-kotak/.

The webhook only fires on a new push — a push made before the frontgen project row existed matched no project and did nothing.

State of the build

Piece Status
Brand — Zurich Sans, palette, logo done (kept from the original scaffold)
Sign-in against the real gateway done
Runtime config, relative base, router done
Pipeline sidebar (mirrors tbl_wf_states) done
Queue lists waiting on the zk-rv-leads record view
Lead file, activity forms, attribution panel waiting on zk-dv-lead + form screens