refactor: onboarding form — drop Praxisgruppe, free-text role, add Dezernat (t-paliad-020)
- Drop the Praxisgruppe field from the onboarding form. Every Paliad user is in patent practice, so the field carried no signal. The DB column is retained for future use (set to NULL on insert). - Switch role from a 4-value enum (partner/associate/pa/admin) to free text with a <datalist> of suggestions (Partner, Associate, PA, Of Counsel, Referendar/in, Trainee, wiss. Mitarbeiter/in, Sekretariat). German firms have many roles beyond the original four. - Add an optional Dezernat field — the team led by a specific partner. Free text, no FK (the partner may not be registered yet). Backend: - Migration 015: drop the role enum CHECK, replace with non-empty CHECK; ADD COLUMN dezernat text. - UserService.Create: drop validRoles map, require non-empty role string, trim and persist Dezernat. Admin bootstrap gate unchanged. - models.User gains Dezernat *string; userColumns SELECT updated so /api/me returns it. Frontend: - onboarding.tsx: replace role <select> with <input list=...>; add dezernat input; remove practice_group. - onboarding.ts: send dezernat (if non-empty), require role. - i18n: add onboarding.role.placeholder, onboarding.dezernat[.placeholder], onboarding.error.role; remove the role.* enum and practice_group keys.
This commit is contained in:
@@ -671,16 +671,14 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"onboarding.office": "B\u00fcro",
|
||||
"onboarding.office.placeholder": "Bitte ausw\u00e4hlen",
|
||||
"onboarding.role": "Rolle",
|
||||
"onboarding.role.associate": "Associate",
|
||||
"onboarding.role.partner": "Partner",
|
||||
"onboarding.role.pa": "PA",
|
||||
"onboarding.role.admin": "Admin",
|
||||
"onboarding.practice_group": "Praxisgruppe",
|
||||
"onboarding.practice_group.placeholder": "z.B. Patent Litigation",
|
||||
"onboarding.role.placeholder": "z.B. Associate, Partner, PA",
|
||||
"onboarding.dezernat": "Dezernat / Partner",
|
||||
"onboarding.dezernat.placeholder": "z.B. Dr. M\u00fcller, Team Schmidt",
|
||||
"onboarding.optional": "(optional)",
|
||||
"onboarding.submit": "Profil anlegen",
|
||||
"onboarding.error.display_name": "Bitte Anzeigename eingeben.",
|
||||
"onboarding.error.office": "Bitte B\u00fcro ausw\u00e4hlen.",
|
||||
"onboarding.error.role": "Bitte Rolle eingeben.",
|
||||
"onboarding.error.generic": "Profil konnte nicht angelegt werden.",
|
||||
"onboarding.error.connection": "Verbindungsfehler. Bitte versuchen Sie es erneut.",
|
||||
|
||||
@@ -1471,16 +1469,14 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"onboarding.office": "Office",
|
||||
"onboarding.office.placeholder": "Please select",
|
||||
"onboarding.role": "Role",
|
||||
"onboarding.role.associate": "Associate",
|
||||
"onboarding.role.partner": "Partner",
|
||||
"onboarding.role.pa": "PA",
|
||||
"onboarding.role.admin": "Admin",
|
||||
"onboarding.practice_group": "Practice group",
|
||||
"onboarding.practice_group.placeholder": "e.g. Patent Litigation",
|
||||
"onboarding.role.placeholder": "e.g. Associate, Partner, PA",
|
||||
"onboarding.dezernat": "Department / Partner",
|
||||
"onboarding.dezernat.placeholder": "e.g. Dr. M\u00fcller, Team Schmidt",
|
||||
"onboarding.optional": "(optional)",
|
||||
"onboarding.submit": "Create profile",
|
||||
"onboarding.error.display_name": "Please enter a display name.",
|
||||
"onboarding.error.office": "Please select an office.",
|
||||
"onboarding.error.role": "Please enter a role.",
|
||||
"onboarding.error.generic": "Could not create profile.",
|
||||
"onboarding.error.connection": "Connection error. Please try again.",
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ async function submitForm(e: Event): Promise<void> {
|
||||
const displayName = (data.get("display_name") as string || "").trim();
|
||||
const office = (data.get("office") as string || "").trim();
|
||||
const role = (data.get("role") as string || "").trim();
|
||||
const practiceGroup = (data.get("practice_group") as string || "").trim();
|
||||
const dezernat = (data.get("dezernat") as string || "").trim();
|
||||
|
||||
if (!displayName) {
|
||||
showMessage(t("onboarding.error.display_name"), "login-error");
|
||||
@@ -96,13 +96,17 @@ async function submitForm(e: Event): Promise<void> {
|
||||
showMessage(t("onboarding.error.office"), "login-error");
|
||||
return;
|
||||
}
|
||||
if (!role) {
|
||||
showMessage(t("onboarding.error.role"), "login-error");
|
||||
return;
|
||||
}
|
||||
|
||||
const payload: Record<string, unknown> = {
|
||||
display_name: displayName,
|
||||
office,
|
||||
role,
|
||||
};
|
||||
if (practiceGroup) payload.practice_group = practiceGroup;
|
||||
if (dezernat) payload.dezernat = dezernat;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
try {
|
||||
|
||||
@@ -41,24 +41,39 @@ export function renderOnboarding(): string {
|
||||
</select>
|
||||
|
||||
<label htmlFor="onb-role" className="login-label" data-i18n="onboarding.role">Rolle</label>
|
||||
<select id="onb-role" name="role" required className="login-input">
|
||||
<option value="associate" data-i18n="onboarding.role.associate">Associate</option>
|
||||
<option value="partner" data-i18n="onboarding.role.partner">Partner</option>
|
||||
<option value="pa" data-i18n="onboarding.role.pa">PA</option>
|
||||
<option value="admin" data-i18n="onboarding.role.admin">Admin</option>
|
||||
</select>
|
||||
<input
|
||||
type="text"
|
||||
id="onb-role"
|
||||
name="role"
|
||||
list="onb-role-suggestions"
|
||||
required
|
||||
autocomplete="off"
|
||||
className="login-input"
|
||||
data-i18n-placeholder="onboarding.role.placeholder"
|
||||
placeholder="z.B. Associate, Partner, PA"
|
||||
/>
|
||||
<datalist id="onb-role-suggestions">
|
||||
<option value="Partner"></option>
|
||||
<option value="Associate"></option>
|
||||
<option value="PA"></option>
|
||||
<option value="Of Counsel"></option>
|
||||
<option value="Referendar/in"></option>
|
||||
<option value="Trainee"></option>
|
||||
<option value="wiss. Mitarbeiter/in"></option>
|
||||
<option value="Sekretariat"></option>
|
||||
</datalist>
|
||||
|
||||
<label htmlFor="onb-practice-group" className="login-label" data-i18n="onboarding.practice_group">
|
||||
Praxisgruppe <span className="login-label-optional" data-i18n="onboarding.optional">(optional)</span>
|
||||
<label htmlFor="onb-dezernat" className="login-label" data-i18n="onboarding.dezernat">
|
||||
Dezernat / Partner <span className="login-label-optional" data-i18n="onboarding.optional">(optional)</span>
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
id="onb-practice-group"
|
||||
name="practice_group"
|
||||
id="onb-dezernat"
|
||||
name="dezernat"
|
||||
autocomplete="off"
|
||||
className="login-input"
|
||||
data-i18n-placeholder="onboarding.practice_group.placeholder"
|
||||
placeholder="z.B. Patent Litigation"
|
||||
data-i18n-placeholder="onboarding.dezernat.placeholder"
|
||||
placeholder="z.B. Dr. Müller, Team Schmidt"
|
||||
/>
|
||||
|
||||
<button type="submit" className="login-button" data-i18n="onboarding.submit">Profil anlegen</button>
|
||||
|
||||
Reference in New Issue
Block a user