M29: polish recruiter engineering story
MobilityOps acceptance / backend (push) Canceled after 0s
MobilityOps acceptance / frontend (push) Canceled after 0s

This commit is contained in:
NuklearRabbit
2026-08-10 18:13:18 +02:00
parent 6365586e82
commit 29325b6c27
57 changed files with 717 additions and 349 deletions
+52 -113
View File
@@ -1,25 +1,20 @@
import { Link } from "react-router-dom";
import { Trans, useTranslation } from "react-i18next";
import { useAuth } from "../context/AuthContext";
import { useDemoGuide } from "../context/DemoGuideContext";
import { useDemoManifest } from "../context/DemoManifestContext";
import { useLocaleFormat } from "../i18n/format";
import { Icon } from "../components/Icons";
import { Icon, type IconName } from "../components/Icons";
import { IntegrationMark, LoadingState, PageHeader, SectionHeading } from "../components/PageChrome";
import { PRODUCT_NAME } from "../product";
const INTEGRATION_ICON: Record<string, "n8n" | "rag" | "mcp"> = {
n8n: "n8n",
ragcore: "rag",
mcp_hub: "mcp",
};
const N8N_STATUS_LABEL_KEY: Record<string, string> = {
disabled: "notConnected",
unavailable: "deliveryFailed",
degraded: "retryAvailable",
operational: "operational",
no_evidence: "prepared",
};
const INTEGRATION_ICON: Record<string, "n8n" | "rag" | "mcp"> = { n8n: "n8n", ragcore: "rag", mcp_hub: "mcp" };
const N8N_STATUS_LABEL_KEY: Record<string, string> = { disabled: "notConnected", unavailable: "deliveryFailed", degraded: "retryAvailable", operational: "operational", no_evidence: "prepared" };
const PROOFS: Array<{ id: "Rules" | "Reliability" | "Ai"; icon: IconName }> = [
{ id: "Rules", icon: "shield" },
{ id: "Reliability", icon: "integrations" },
{ id: "Ai", icon: "knowledge" },
];
export function AboutDemo() {
const { t } = useTranslation(["demo", "integrations"]);
@@ -27,112 +22,56 @@ export function AboutDemo() {
const { manifest, loading } = useDemoManifest();
const { user } = useAuth();
const { openGuide } = useDemoGuide();
function statusLabelKey(key: string, statusCode: string): string {
if (key === "n8n") return N8N_STATUS_LABEL_KEY[statusCode] ?? statusCode;
return statusCode;
}
const statusLabelKey = (key: string, statusCode: string) => key === "n8n" ? N8N_STATUS_LABEL_KEY[statusCode] ?? statusCode : statusCode;
return (
<div className="page">
<PageHeader
eyebrow={t("about.eyebrow")}
title={t("about.title", { productName: PRODUCT_NAME })}
description={manifest ? t("about.description", { orgName: manifest.organization_name }) : undefined}
/>
<div className="page engineering-story">
<PageHeader eyebrow={t("about.eyebrow")} title={t("about.title", { productName: PRODUCT_NAME })} description={manifest ? t("about.description", { orgName: manifest.organization_name }) : undefined} />
{loading && <LoadingState label={t("about.loading")} />}
{manifest && (
<>
{user?.role === "operations_manager" && (
<section className="record-surface about-card about-cta">
<div>
<strong>{t("about.ctaTitle")}</strong>
<p>{t("about.ctaBody")}</p>
</div>
<button type="button" className="button button-primary" onClick={openGuide}>
<Icon name="spark" /> {t("about.ctaButton")}
</button>
</section>
)}
<section className="record-surface about-card">
<h2>{t("about.problemTitle")}</h2>
<p>{t("about.problemBody", { orgName: manifest.organization_name, productName: PRODUCT_NAME })}</p>
</section>
<section className="record-surface about-card">
<h2>{t("about.scopeTitle")}</h2>
<p>{t("about.scopeBody", { productName: PRODUCT_NAME })}</p>
</section>
<div className="about-grid">
<div className="record-surface about-card">
<h2>{t("about.realTitle")}</h2>
<p>{t("about.realBody")}</p>
</div>
<div className="record-surface about-card">
<h2>{t("about.syntheticTitle")}</h2>
<p>{t("about.syntheticBody", { testDomain: ".test" })}</p>
</div>
<details className="record-surface about-card about-details">
<summary>{t("about.architectureTitle")}</summary>
<p>{t("about.architectureBody")}</p>
</details>
<details className="record-surface about-card about-details">
<summary>{t("about.securityTitle")}</summary>
<p>{t("about.securityBody")}</p>
</details>
<details className="record-surface about-card about-details">
<summary>{t("about.testingTitle")}</summary>
<p>{t("about.testingBody")}</p>
</details>
{manifest && <>
<section className="panel engineering-hero">
<div>
<p className="page-eyebrow">{t("about.proofEyebrow")}</p>
<h2>{t("about.proofTitle")}</h2>
<p>{t("about.proofDescription")}</p>
</div>
<div className="engineering-hero-actions">
<Link className="button button-primary" to="/highlights"><Icon name="spark" /> {t("about.quickTourButton")}</Link>
{user?.role === "operations_manager" && <button type="button" className="button button-secondary" onClick={openGuide}>{t("about.ctaButton")}</button>}
<Link className="button button-secondary" to="/scenarios">{t("about.scenarioButton")}</Link>
</div>
</section>
<section aria-label={t("about.integrationsTitle")} className="record-surface">
<SectionHeading title={t("about.integrationsTitle")} description={t("about.integrationsDescription")} />
<div className="integration-cards">
{manifest.integrations.map((integration) => (
<article key={integration.key}>
<IntegrationMark kind={INTEGRATION_ICON[integration.key]} />
<div>
<span className="integration-kicker">
{t(`integrations:statusLabels.${statusLabelKey(integration.key, integration.status_code)}`)}
</span>
<h2>{t(`integrationSummary.titles.${integration.key}`, { ns: "demo" })}</h2>
<p>{t(`integrationSummary.${integration.detail_code}`, { ns: "demo", ...integration.detail_params })}</p>
</div>
</article>
))}
</div>
</section>
<section aria-label={t("about.proofTitle")}>
<div className="proof-grid">
{PROOFS.map((proof) => <article className="panel proof-card" key={proof.id}><span><Icon name={proof.icon} /></span><h3>{t(`about.proof${proof.id}Title`)}</h3><p>{t(`about.proof${proof.id}Body`)}</p></article>)}
</div>
</section>
<section className="record-surface about-card">
<h2>{t("about.resetTitle")}</h2>
<p>
<Trans
i18nKey={user?.role === "operations_manager" ? "about.resetBodyManager" : "about.resetBodyEmployee"}
t={t}
values={{ when: manifest.last_reset_at ? formatDateTime(manifest.last_reset_at) : t("about.unknown") }}
components={{ strong: <strong /> }}
/>
</p>
</section>
<section className="panel architecture-story" aria-labelledby="architecture-heading">
<SectionHeading title={t("about.architectureFlowTitle")} description={t("about.architectureFlowDescription")} />
<div className="architecture-flow" id="architecture-heading">
{["Frontend", "Api", "Database", "Outbox", "External"].map((step, index) => <div className="architecture-step" key={step}><span>{index + 1}</span><strong>{t(`about.architecture${step}`)}</strong>{index < 4 && <Icon name="chevron" />}</div>)}
</div>
</section>
<section className="access-note record-surface" aria-label={t("about.limitationsTitle")}>
<Icon name="shield" />
<p>
<strong>{t("about.limitationsTitle")}</strong>
<span>{t("about.limitationsBody")}</span>
</p>
</section>
</>
)}
<div className="about-grid">
<div className="record-surface about-card"><h2>{t("about.problemTitle")}</h2><p>{t("about.problemBody", { orgName: manifest.organization_name, productName: PRODUCT_NAME })}</p></div>
<div className="record-surface about-card"><h2>{t("about.scopeTitle")}</h2><p>{t("about.scopeBody", { productName: PRODUCT_NAME })}</p></div>
<div className="record-surface about-card"><h2>{t("about.realTitle")}</h2><p>{t("about.realBody")}</p></div>
<div className="record-surface about-card"><h2>{t("about.syntheticTitle")}</h2><p>{t("about.syntheticBody", { testDomain: ".test" })}</p></div>
<div className="record-surface about-card"><h2>{t("about.verificationTitle")}</h2><p>{t("about.verificationBody")}</p></div>
<div className="record-surface about-card"><h2>{t("about.securityTitle")}</h2><p>{t("about.securityBody")}</p></div>
</div>
<section aria-label={t("about.integrationsTitle")} className="record-surface">
<SectionHeading title={t("about.integrationsTitle")} description={t("about.integrationsDescription")} />
<div className="integration-cards">{manifest.integrations.map((integration) => <article key={integration.key}><IntegrationMark kind={INTEGRATION_ICON[integration.key]} /><div><span className="integration-kicker">{t(`integrations:statusLabels.${statusLabelKey(integration.key, integration.status_code)}`)}</span><h2>{t(`integrationSummary.titles.${integration.key}`, { ns: "demo" })}</h2><p>{t(`integrationSummary.${integration.detail_code}`, { ns: "demo", ...integration.detail_params })}</p></div></article>)}</div>
</section>
<section className="record-surface about-card"><h2>{t("about.resetTitle")}</h2><p><Trans i18nKey={user?.role === "operations_manager" ? "about.resetBodyManager" : "about.resetBodyEmployee"} t={t} values={{ when: manifest.last_reset_at ? formatDateTime(manifest.last_reset_at) : t("about.unknown") }} components={{ strong: <strong /> }} /></p></section>
<section className="access-note record-surface" aria-label={t("about.limitationsTitle")}><Icon name="shield" /><p><strong>{t("about.limitationsTitle")}</strong><span>{t("about.limitationsBody")}</span></p></section>
</>}
</div>
);
}
+18
View File
@@ -7,6 +7,7 @@ import { useAuth } from "../context/AuthContext";
import { useLocaleFormat } from "../i18n/format";
import { EmptyState, ErrorState, LoadingState, PageHeader } from "../components/PageChrome";
import { Pagination } from "../components/Pagination";
import { Icon } from "../components/Icons";
function humanizeField(field: string): string {
const spaced = field.replace(/_/g, " ");
@@ -39,6 +40,22 @@ function ChangeDiff({ before, after, t }: { before: Record<string, unknown> | nu
interface EventGroup { correlationId: string; primary: AuditEvent; related: AuditEvent[]; }
function OperationTrace({ events, t }: { events: AuditEvent[]; t: (key: string, options?: Record<string, unknown>) => string }) {
const actions = new Set(events.map((event) => event.action));
const isReturn = actions.has("return_registered");
if (!isReturn) return null;
const steps = [
{ key: "return", complete: isReturn },
{ key: "vehicle", complete: actions.has("vehicle_status_changed") },
{ key: "outbox", complete: isReturn },
{ key: "delivery", complete: actions.has("n8n_return_followup_recorded") },
];
return <section className="panel operation-trace" aria-labelledby="operation-trace-title">
<div><p className="page-eyebrow">{t("trace.eyebrow")}</p><h2 id="operation-trace-title">{t("trace.title")}</h2><p>{t("trace.description")}</p></div>
<ol>{steps.map((step, index) => <li className={step.complete ? "is-complete" : "is-pending"} key={step.key}><span>{step.complete ? <Icon name="check" /> : index + 1}</span><div><strong>{t(`trace.steps.${step.key}.title`)}</strong><small>{t(`trace.steps.${step.key}.${step.complete ? "complete" : "pending"}`)}</small></div></li>)}</ol>
</section>;
}
export function Audit() {
const { t } = useTranslation("audit");
const { formatDateTime } = useLocaleFormat();
@@ -95,6 +112,7 @@ export function Audit() {
<label>{t("fromFilterLabel")}<input type="date" value={from} onChange={(e) => updateParams({ from: e.target.value, page: 1 })} /></label>
<label>{t("toFilterLabel")}<input type="date" value={to} onChange={(e) => updateParams({ to: e.target.value, page: 1 })} /></label>
</form>
{correlationId && events && <OperationTrace events={events.items} t={t} />}
{correlationId && <p className="quiet-empty" role="status">{t("relatedFilterActive", { count: events?.total ?? 0 })} <button type="button" className="link-button" onClick={() => updateParams({ correlation_id: null, page: 1 })}>{t("clearFilter")}</button></p>}
{error && <ErrorState message={error} />}
{!error && !events && <LoadingState label={t("loading")} />}
@@ -774,7 +774,7 @@ export function DataQualityIssueDetail() {
return (
<div className="page">
<Link className="back-link" to="/data-quality"><Icon name="arrow-left" /> {t("detail.backLink")}</Link>
<PageHeader eyebrow={t("detail.eyebrow", { rule: t(`ruleTypes.${issue.rule_type}`, { defaultValue: issue.rule_type.replace(/_/g, " ") }) })} title={issue.public_ref} description={t("detail.title")} actions={<div className="status-stack"><SeverityBadge severity={issue.severity} /><StatusBadge status={issue.status} label={t(`list.status${issue.status.charAt(0).toUpperCase()}${issue.status.slice(1)}`, { defaultValue: issue.status })} /></div>} />
<PageHeader eyebrow={issue.public_ref} title={t(`ruleTypes.${issue.rule_type}`, { defaultValue: issue.rule_type.replace(/_/g, " ") })} description={t("detail.title")} actions={<div className="status-stack"><SeverityBadge severity={issue.severity} /><StatusBadge status={issue.status} label={t(`list.status${issue.status.charAt(0).toUpperCase()}${issue.status.slice(1)}`, { defaultValue: issue.status })} /></div>} />
<section className="record-surface" aria-label={t("detail.summary.rule")}><dl className="detail-grid">
<div><dt>{t("detail.summary.rule")}</dt><dd>{t(`ruleTypes.${issue.rule_type}`, { defaultValue: issue.rule_type.replace(/_/g, " ") })}</dd></div>
<div><dt>{t("detail.summary.entity")}</dt><dd>{issue.entity_type === "vehicle" ? <Link to={`/vehicles/${issue.entity_ref}`}>{issue.entity_ref}</Link> : issue.entity_ref}</dd></div>
+60
View File
@@ -0,0 +1,60 @@
import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { Icon, type IconName } from "../components/Icons";
import { PageHeader } from "../components/PageChrome";
import { useDemoGuide } from "../context/DemoGuideContext";
import { PRODUCT_NAME } from "../product";
const HIGHLIGHTS: Array<{ id: "return" | "quality" | "knowledge"; to: string; icon: IconName }> = [
{ id: "return", to: "/bookings/BK-DEMO-RETURN", icon: "bookings" },
{ id: "quality", to: "/data-quality/DQ-DEMO-DUPLICATE", icon: "quality" },
{ id: "knowledge", to: "/knowledge", icon: "knowledge" },
];
export function Highlights() {
const { t } = useTranslation("demo");
const { openGuide } = useDemoGuide();
return (
<div className="page recruiter-highlights">
<PageHeader
eyebrow={t("highlights.eyebrow")}
title={t("highlights.title")}
description={t("highlights.description", { productName: PRODUCT_NAME })}
/>
<ol className="highlight-grid">
{HIGHLIGHTS.map((highlight, index) => (
<li key={highlight.id} className="panel highlight-card">
<div className="highlight-card-top">
<span className="highlight-number">0{index + 1}</span>
<span className="highlight-duration"><Icon name="clock" /> {t("highlights.duration")}</span>
</div>
<span className="highlight-icon"><Icon name={highlight.icon} /></span>
<h2>{t(`highlights.${highlight.id}.title`)}</h2>
<p>{t(`highlights.${highlight.id}.body`)}</p>
<div className="highlight-proof">
<strong>{t("highlights.proofLabel")}</strong>
<span>{t(`highlights.${highlight.id}.proof`)}</span>
</div>
<Link className="button button-primary" to={highlight.to}>
{t("highlights.open")} <Icon name="chevron" />
</Link>
</li>
))}
</ol>
<section className="panel highlights-next">
<div>
<p className="page-eyebrow">{t("highlights.proofLabel")}</p>
<h2>{t("highlights.storyTitle")}</h2>
<p>{t("highlights.storyBody")}</p>
</div>
<div className="highlights-next-actions">
<Link className="button button-primary" to="/about">{t("highlights.storyButton")} <Icon name="chevron" /></Link>
<button type="button" className="button button-secondary" onClick={openGuide}><Icon name="spark" /> {t("highlights.fullTourButton")}</button>
</div>
</section>
</div>
);
}
+18 -3
View File
@@ -20,6 +20,12 @@ function isOpaqueVersion(value: string): boolean {
return /^[0-9a-f]{8}-[0-9a-f-]{27,}$/i.test(value);
}
function sourceDisplayTitle(title: string, t: (key: string, options?: Record<string, unknown>) => string): string {
const base = title.replace(/\.md$/i, "");
const fallback = base.split(/[-_]/).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
return t(`sourceTitles.${base}`, { defaultValue: fallback });
}
export function Knowledge() {
const { t, i18n } = useTranslation(["knowledge", "errors"]);
const { formatDateTime } = useLocaleFormat();
@@ -27,6 +33,7 @@ export function Knowledge() {
const [statusSettled, setStatusSettled] = useState(false);
const [question, setQuestion] = useState("");
const [submitting, setSubmitting] = useState(false);
const [loadingStage, setLoadingStage] = useState(0);
const [error, setError] = useState<ApiErrorInfo | null>(null);
const [exchanges, setExchanges] = useState<Exchange[]>([]);
@@ -44,6 +51,9 @@ export function Knowledge() {
async function ask(questionText: string) {
setError(null);
setSubmitting(true);
setLoadingStage(0);
const sourceTimer = window.setTimeout(() => setLoadingStage(1), 900);
const evidenceTimer = window.setTimeout(() => setLoadingStage(2), 2600);
const startedAt = performance.now();
try {
const answer = await api.post<GroundedAnswer>("/api/v1/knowledge/questions", {
@@ -61,6 +71,8 @@ export function Knowledge() {
} catch (err) {
setError(describeApiError(t, err, "askFailed"));
} finally {
window.clearTimeout(sourceTimer);
window.clearTimeout(evidenceTimer);
setSubmitting(false);
}
}
@@ -124,11 +136,11 @@ export function Knowledge() {
<span>
{status.available ? t("statusAvailable") : t("statusUnavailable")} ·{" "}
{status.document_count === null
? t("proceduresIndexUnknown")
? t("proceduresAvailable", { count: status.source_document_count })
: t("proceduresIndexed", { count: status.document_count })}
</span>
</div>
<small>{status.collection}</small>
<details className="knowledge-diagnostics"><summary>{t("technicalDetails")}</summary><small>{status.collection} · {status.detail}</small></details>
</div>
)}
{statusSettled && !status && (
@@ -181,6 +193,9 @@ export function Knowledge() {
</button>
</div>
<ApiErrorNotice error={error} />
{submitting && <div className="knowledge-progress" role="status" aria-live="polite">
{["retrieving", "checking", "composing"].map((stage, index) => <span className={index <= loadingStage ? "is-active" : ""} key={stage}>{index < loadingStage ? <Icon name="check" /> : <i />}{t(`progress.${stage}`)}</span>)}
</div>}
<div className="knowledge-suggestions">
<span>{t("suggestedLabel")}</span>
{suggestedQuestions.map((suggestion) => (
@@ -230,7 +245,7 @@ export function Knowledge() {
<details open={sourceIndex === 0}>
<summary>
<span className="source-number">{sourceIndex + 1}</span>
<span className="source-title">{source.title}</span>
<span className="source-title">{sourceDisplayTitle(source.title, t)}</span>
{source.section && <span className="source-section">{source.section}</span>}
</summary>
<p className="source-excerpt">{source.excerpt}</p>
+7 -3
View File
@@ -17,11 +17,11 @@ export function Login() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
async function handleLogin(role: Role, guided = false) {
async function handleLogin(role: Role, destination = "/dashboard") {
setError(null);
try {
await loginAs(role);
navigate(guided ? "/dashboard?guide=start" : "/dashboard");
navigate(destination);
} catch {
setError(t("loginFailed"));
}
@@ -78,9 +78,13 @@ export function Login() {
type="button"
className="button button-primary login-guide-cta"
disabled={loading}
onClick={() => handleLogin("operations_manager", true)}
onClick={() => handleLogin("operations_manager", "/highlights")}
>
<Icon name="spark" />
{t("startRecruiterTour")}
</button>
<button type="button" className="button button-secondary login-full-demo" disabled={loading} onClick={() => handleLogin("operations_manager", "/dashboard?guide=start")}>
{t("startGuidedDemo")}
</button>