Files
paliad/frontend/src/onboarding.tsx
m 2af4bf1f88 feat(t-paliad-148) commit 5/6: frontend — team-add dropdown + 3-col team table + admin-team profession + onboarding
projects-detail.tsx (the bug surface):
- Team-add dropdown switches from 7 mixed values (lead/associate/pa/of_counsel/local_counsel/expert/observer) to 4 responsibility-only values (lead/member/observer/external). Default 'member'. Closes m's bug — staffing a person no longer pretends to define their firm tier.
- Team table gains a Profession column (between Name and Responsibility), so the firm-tier badge is glanceable at staffing time.
- form.team-profession-hint surfaces the picked person's profession or warns when none is set ("kann keine 4-Augen-Genehmigungen erteilen").

projects-detail.ts:
- ProjectTeamMember type gains responsibility + user_profession. Legacy .role field kept readable for the deprecation window but UI no longer uses it.
- renderTeam renders 3-column tabular layout. Profession pill is read-only (.projekt-team-profession[--none]); responsibility is visible inline (inline-edit deferred to follow-up).
- canManagePartnerUnits switches from m.role==="lead" to m.responsibility==="lead".
- Team-add submit posts {responsibility} instead of {role}.

admin-team.tsx + client/admin-team.ts:
- New Profession column with inline-edit dropdown (6 values + "(extern)" NULL option). User type extends with profession?: string|null.
- Read-only cell uses .projekt-team-profession pill with "(extern)" placeholder for NULL.

onboarding.tsx + client/onboarding.ts:
- New required profession <select> with default 'associate'. Six values match the new enum. Hint copy explains the difference from job_title.
- POST /api/onboarding payload gains profession field.

i18n.ts: ~30 new keys DE+EN — projects.team.profession.* / .responsibility.* / projects.detail.team.col.profession / .responsibility / .form.responsibility / .form.profession.* / admin.team.col.profession.* / onboarding.profession.* / projects.team.profession.none + .hint variants.

CSS:
- .projekt-team-profession pill (firm-tier, read-only).
- .projekt-team-profession--none italic-dashed for NULL professions.
- .projekt-team-responsibility pill (per-project).
- .form-hint--warning for the team-add no-profession warning.

Build: bun build.ts clean (1723 i18n keys, all referenced). go build + go vet + go test (pure-Go) clean.
2026-05-07 21:56:18 +02:00

116 lines
5.3 KiB
TypeScript

import { h } from "./jsx";
import { Header } from "./components/Header";
import { Footer } from "./components/Footer";
import { PWAHead } from "./components/PWAHead";
export function renderOnboarding(): string {
return "<!DOCTYPE html>" + (
<html lang="de">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="theme-color" content="#BFF355" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<PWAHead />
<title data-i18n="onboarding.title">Willkommen &mdash; Paliad</title>
<link rel="stylesheet" href="/assets/global.css" />
</head>
<body>
<Header />
<main className="login-main">
<div className="login-card onboarding-card">
<h1 className="onboarding-heading" data-i18n="onboarding.heading">Willkommen bei Paliad</h1>
<p className="onboarding-lede" data-i18n="onboarding.lede">
Bitte vervollst&auml;ndigen Sie Ihr Profil, damit Ihnen Akten, Fristen und Termine angezeigt werden k&ouml;nnen.
</p>
<form className="login-form" id="onboarding-form" autocomplete="off">
<label htmlFor="onb-display-name" className="login-label" data-i18n="onboarding.display_name">Anzeigename</label>
<input
type="text"
id="onb-display-name"
name="display_name"
required
autofocus
autocomplete="name"
className="login-input"
data-i18n-placeholder="onboarding.display_name.placeholder"
placeholder="Vor- und Nachname"
/>
<label htmlFor="onb-office" className="login-label" data-i18n="onboarding.office">B&uuml;ro</label>
<select id="onb-office" name="office" required className="login-input">
{/* Options populated from /api/offices at init. */}
</select>
<label htmlFor="onb-job-title" className="login-label" data-i18n="onboarding.job_title">Berufsbezeichnung</label>
<input
type="text"
id="onb-job-title"
name="job_title"
list="onb-job-title-suggestions"
required
autocomplete="off"
className="login-input"
data-i18n-placeholder="onboarding.job_title.placeholder"
placeholder="z.B. Associate, Partner, Patentanwalt"
/>
<datalist id="onb-job-title-suggestions">
<option value="Partner"></option>
<option value="Associate"></option>
<option value="PA"></option>
<option value="Of Counsel"></option>
<option value="Counsel"></option>
<option value="Counsel Knowledge Lawyer"></option>
<option value="Knowledge Lawyer"></option>
<option value="Referendar/in"></option>
<option value="Trainee"></option>
<option value="wiss. Mitarbeiter/in"></option>
<option value="Sekretariat"></option>
</datalist>
<label htmlFor="onb-profession" className="login-label" data-i18n="onboarding.profession">Profession</label>
<select
id="onb-profession"
name="profession"
required
className="login-input"
>
<option value="associate" selected data-i18n="projects.team.profession.associate">Associate</option>
<option value="partner" data-i18n="projects.team.profession.partner">Partner</option>
<option value="of_counsel" data-i18n="projects.team.profession.of_counsel">Of Counsel</option>
<option value="senior_pa" data-i18n="projects.team.profession.senior_pa">Senior PA</option>
<option value="pa" data-i18n="projects.team.profession.pa">PA</option>
<option value="paralegal" data-i18n="projects.team.profession.paralegal">Paralegal</option>
</select>
<p className="login-hint" data-i18n="onboarding.profession.hint">
Strukturiertes Tier steuert die 4-Augen-Genehmigung. Distinkt von der Berufsbezeichnung.
</p>
<label htmlFor="onb-partner-unit" className="login-label" data-i18n="onboarding.partner_unit">
Partner Unit <span className="login-label-optional" data-i18n="onboarding.optional">(optional)</span>
</label>
<select
id="onb-partner-unit"
name="partner_unit_id"
className="login-input"
>
{/* Options populated from /api/partner-units at init. */}
<option value="" data-i18n="onboarding.partner_unit.unassigned">(noch keine Zuordnung)</option>
</select>
<button type="submit" className="login-button" data-i18n="onboarding.submit">Profil anlegen</button>
</form>
</div>
</main>
<Footer />
<script src="/assets/onboarding.js"></script>
</body>
</html>
);
}