Files
AkeshanandClaude Opus 4.8 d8b6772148 Interim-UI-Handover: 55 Vorschau-Screens fuer David (AD-28)
Uebergabe der Dev-Interim-Screens aus HiveGrid-Cloud an den Wireframes-Vault.
INDEX + 7 Domaenen-Seiten (CRM, Leads, HR, Files/Tasks, Audit/Notifications,
Integrations, Auth/RBAC) mit je Screen: D-*-Ziel, Archetyp, Route, VM,
benoetigte ~/ui-Elemente, Actions, States. Layout bleibt Davids freie Hand.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 17:35:12 +02:00

22 KiB

P17 · HR-Hub (AK-P17a/b → D-HR)

Interim-UI-Referenz (AD-28) für den HR-Hub. Alle Screens rein präsentational (VM als Prop, Route besitzt Loader/Fetcher/Actions). Layout = Davids freie Hand — unten nur ELEMENTE/DATEN/ACTIONS. ~/ui ist das gesetzte Baukasten-Inventar; data-ui-id-Marker existieren für Interim-Snapshots. Route-URLs: App-Host, Ordner routes/app.$tenant/ → /{tenant}/hr/….

HrHubPage · D-HR „HR-Hub-Start" (A1/A6)

  • Interim-Screen: apps/web/app/components/screens/hr/HrHubPage.tsx
  • Route(n): /{tenant}/hr (routes/app.$tenant/hr._index.tsx)
  • Daten (VM): kein @hivegrid-VM — lokale Props moduleActive: boolean, links: HrHubLink[] ({ labelKey, href }); Loader gated Connector+Permission und liefert die Quick-Link-Liste
  • Benötigte UI-Elemente (KEIN Layout): Card, EmptyState · Icons: FeatherArrowRight, FeatherLock
  • Interaktionen (Actions): keine Callbacks — Links sind <a href> (Navigations-Kacheln)
  • States: Locked (!moduleActive → EmptyState mit Lock) / Empty (leere Link-Liste rendert leere Grid) / Permission-Denied via Loader-Gate (404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen (Hub-Widgets Ankündigungen/Pflichten/Geburtstage kommen laut Header erst als Folge-Nachzug):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrDirectoryPage · D-HR „MA-Verzeichnis" (A2)

  • Interim-Screen: apps/web/app/components/screens/hr/HrDirectoryPage.tsx
  • Route(n): /{tenant}/hr/directory (routes/app.$tenant/hr.directory._index.tsx)
  • Daten (VM): HrDirectoryVM — packages/view-models/src/hr/hr-directory.vm.ts (nur nicht-sensible Anzeigefelder; Notfallkontakt NUR im Detail)
  • Benötigte UI-Elemente (KEIN Layout): Avatar, EmptyState, IconButton, Table · Icons: FeatherMail
  • Interaktionen (Actions): keine Action-Callbacks — Name-Link → Detail, mailto:-IconButton
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrDirectoryDetailPage · D-HR „MA-Detail" (A3)

  • Interim-Screen: apps/web/app/components/screens/hr/HrDirectoryDetailPage.tsx
  • Route(n): /{tenant}/hr/directory/{userId} (routes/app.$tenant/hr.directory.$userId.tsx)
  • Daten (VM): kein VM-Typ-Import — flache Props (name, email, position, team, isSelf, canRevealEmergency, canEditEmergency, hasEmergencyContact, revealedContact, revealing, saving, savingEmergency); Domain in hr-directory.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): Breadcrumbs, Button, Card, Dialog, TextInput · Icons: —
  • Interaktionen (Actions): onSaveProfile({position,team}), onRevealEmergency(), onSetEmergency({name,phone,relation})
  • States: Self-Edit vs. Read-only (isSelf) / Emergency: kein Kontakt / gespeichert-nicht-enthüllbar / enthüllt / Reveal-Button / Loading via revealing/saving/savingEmergency / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (On-Demand-Reveal Notfallkontakt, serverseitig auditiert):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrLeavePage · D-HR „Urlaub" (A2 + A4/A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrLeavePage.tsx
  • Route(n): /{tenant}/hr/leave (routes/app.$tenant/hr.leave._index.tsx), URL-Tabs ?tab=own|approvals|team
  • Daten (VM): HrLeaveOwnVM, HrLeaveApproverVM, HrVacationRequestKind — packages/view-models/src/hr/hr-leave.vm.ts; plus lokaler HrLeaveTeamAbsence
  • Benötigte UI-Elemente (KEIN Layout): Alert, BadgeFeedback, Button, Card, Dialog, EmptyState, Select, Tabs, TextArea, TextInput, DateField (tasks) · Icons: FeatherPlus
  • Interaktionen (Actions): onSubmit({requestKind,approverUserId,startDate,endDate,note}), onWithdraw(requestId), onReply(requestId,reply), onApprove(requestId), onReject(requestId), onClarify(requestId,question)
  • States: Empty je Tab (own/approvals/team → EmptyState) / Loading (status!=="ready" → null) / Konflikt-Warnung (Alert bei hasConflict) / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Overlap-Konflikt als Inline-Warnung):
    • Neue UI/UX-Entscheidungen (Approver-Auswahl aktuell freies TextInput = userId):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrSickPage · D-HR „Krank" (A2 + A4)

  • Interim-Screen: apps/web/app/components/screens/hr/HrSickPage.tsx
  • Route(n): /{tenant}/hr/sick (routes/app.$tenant/hr.sick._index.tsx), Tabs own|office
  • Daten (VM): HrSickLeaveOwnVM, HrSickLeaveOfficeVM, HrSickLeaveRow — packages/view-models/src/hr/hr-sickleave.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Dialog, EmptyState, Tabs, TextInput, DateField (tasks) · Icons: FeatherPlus
  • Interaktionen (Actions): onReport({startDate,expectedReturnDate}), onReportFor({employeeUserId,startDate}), onAttach(reportId,certificateFileId), onRevealCertificate(reportId), onClose(reportId,returnDate)
  • States: Empty je Tab (own/office → EmptyState) / AU-Zertifikat nie gerendert, nur Reveal-Action / Loading (Rows via ?? []) / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Zertifikat sensibel, reveal-on-demand):
    • Neue UI/UX-Entscheidungen (Attach = File-ID-TextInput; echte Datei-Auswahl offen):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrRequestsPage · D-HR „Anträge" (A2 + A4/A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrRequestsPage.tsx
  • Route(n): /{tenant}/hr/requests (routes/app.$tenant/hr.requests._index.tsx), Tabs own|approvals
  • Daten (VM): HrRequestOwnVM, HrRequestApproverVM, HrRequestKind — packages/view-models/src/hr/hr-request.vm.ts; plus lokaler HrRequestTemplateOption
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Dialog, EmptyState, Select, Tabs, TextArea, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onSubmit({templateId,requestKind,approverUserId,title,details}), onWithdraw(requestId), onApprove(requestId), onReject(requestId), onClarify(requestId,question)
  • States: Empty je Tab (own/approvals → EmptyState) / Loading (Rows via ?? []) / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (optionaler Vorlagen-Prefill):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrPayslipsPage · D-HR „Lohnabrechnungen" (A2)

  • Interim-Screen: apps/web/app/components/screens/hr/HrPayslipsPage.tsx
  • Route(n): /{tenant}/hr/payslips (routes/app.$tenant/hr.payslips._index.tsx)
  • Daten (VM): HrPayslipOwnVM — packages/view-models/src/hr/hr-payslip.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, EmptyState, Table · Icons: FeatherExternalLink
  • Interaktionen (Actions): onOpen(payslipId) (Öffnen serverseitig auditiert, Route öffnet File)
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Unread-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrMyDocumentsPage · D-HR „Eigene Dokumente" (A2)

  • Interim-Screen: apps/web/app/components/screens/hr/HrMyDocumentsPage.tsx
  • Route(n): /{tenant}/hr/my-documents (routes/app.$tenant/hr.my-documents.tsx)
  • Daten (VM): HrDocumentListVM, HrDocumentKind — packages/view-models/src/hr/hr-document.vm.ts; plus injizierter upload: HrDocumentUploadState (idle/uploading/done/error)
  • Benötigte UI-Elemente (KEIN Layout): Alert, BadgeFeedback, Button, Dialog, EmptyState, Select, Table, TextInput; native input[type=date] + input[type=file] (bewusste Ausnahme) · Icons: FeatherUpload
  • Interaktionen (Actions): onArchive(documentId), onUpload({file,title,documentKind,validUntilIso}), onResetUpload()
  • States: Empty (rows.length===0 → EmptyState) / No-Results (Kind-Filter leer → EmptyState no-results) / Loading (status!=="ready" → leeres Div) / Upload uploading/error (Alert) / Read-only-Badge (Office-Docs) / Expired-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Kind-Filter client-seitig, Office-Docs read-only):
    • Neue UI/UX-Entscheidungen (Upload-Progress-Darstellung):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAnnouncementsFeedPage · D-HR „Ankündigungen" (A2)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAnnouncementsFeedPage.tsx
  • Route(n): /{tenant}/hr/announcements (routes/app.$tenant/hr.announcements._index.tsx), Filter ?unread=1
  • Daten (VM): HrAnnouncementFeedVM — packages/view-models/src/hr/hr-announcement.vm.ts (pinned first)
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Card, EmptyState, LinkButton, Tabs · Icons: FeatherPin
  • Interaktionen (Actions): keine Callbacks — Zeilen-Link → Detail, „Verwalten"-Link (manageHref, bei canManage)
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Ack-Required-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (pinned zuerst, Unread-Filter):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAnnouncementDetailPage · D-HR „Ankündigung Detail" (A3)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAnnouncementDetailPage.tsx
  • Route(n): /{tenant}/hr/announcements/{id} (routes/app.$tenant/hr.announcements.$id.tsx)
  • Daten (VM): HrAnnouncementDetailVM — packages/view-models/src/hr/hr-announcement.vm.ts (Markdown-Body, Reaktionen, Kommentare 1 Ebene, Read-Receipts)
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Table, TextInput · Icons: — (Emoji-Reaktionen 👍❤️🎉👀 als Literale)
  • Interaktionen (Actions): onAck(), onReact(reaction), onComment(body)
  • States: Loading (status!=="ready" → leeres Div) / Kommentare-Empty (commentEmptyKey) / Ack-Zustand acknowledged vs. Button / Read-Receipt-Tabelle nur bei canManage / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Markdown wird aktuell whitespace-pre-wrap roh gerendert):
    • Neue UI/UX-Entscheidungen (Reaktions-Set fix vier Emojis):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrLocationsPage · D-HR „Standorte" (A2 + A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrLocationsPage.tsx
  • Route(n): /{tenant}/hr/locations (routes/app.$tenant/hr.locations._index.tsx)
  • Daten (VM): HrLocationListVM — packages/view-models/src/hr/hr-location.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Checkbox, Dialog, EmptyState, Table, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onCreate({name,city,isDefault}), onSetDefault(locationId), onArchive(locationId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Default-Badge / Aktionen nur bei canManage / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrPasswordSafeListPage · D-HR „Passwort-Safe" (A2 + A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrPasswordSafeListPage.tsx
  • Route(n): /{tenant}/hr/password-safe (routes/app.$tenant/hr.password-safe._index.tsx)
  • Daten (VM): VaultListVM — packages/view-models/src/hr/hr-password-safe.vm.ts (nur zugriffsberechtigte Vaults, keine Secrets)
  • Benötigte UI-Elemente (KEIN Layout): Button, Card, Dialog, EmptyState, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onCreateVault({name,description})
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Create nur bei canCreate / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrVaultDetailPage · D-HR „Passwort-Safe Detail" (A3 + reveal)

  • Interim-Screen: apps/web/app/components/screens/hr/HrVaultDetailPage.tsx
  • Route(n): /{tenant}/hr/password-safe/{vaultId} (routes/app.$tenant/hr.password-safe.$vaultId._index.tsx); Action-only: …$vaultId.reveal.tsx, …$vaultId.export.tsx
  • Daten (VM): VaultDetailVM, EntryRow — packages/view-models/src/hr/hr-password-safe.vm.ts (nur hasUsername/hasPassword/hasNotes-Flags, copyAutoClearMs)
  • Benötigte UI-Elemente (KEIN Layout): Breadcrumbs, Button, Card, CopyToClipboardButton, Dialog, EmptyState, LinkButton, Select, Tag_Label, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onReveal(entryId,field): Promise<string|null>, onCreateEntry({title,url,username,password,notes}), onArchiveEntry(entryId), onGrantAccess({targetUserId,permissionLevel})
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Secret pro Feld reveal-on-demand → copy → Clipboard-Wipe nach 30s (DoD #3) / Aktionen gated via canWrite/canManageAccess / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (SECURITY: Werte nur per audited reveal, Clipboard-Auto-Clear):
    • Neue UI/UX-Entscheidungen (Copy-Cleared-Hinweis, Zugriff via userId-TextInput):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrSurveysListPage · D-HR „Umfragen" (A2 + A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrSurveysListPage.tsx
  • Route(n): /{tenant}/hr/surveys (routes/app.$tenant/hr.surveys._index.tsx)
  • Daten (VM): HrSurveyListVM — packages/view-models/src/hr/hr-survey.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Checkbox, Dialog, EmptyState, LinkButton, Select, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onCreate({title,description,isAnonymous,resultVisibility}), onSetStatus(surveyId,"open"|"close"), onArchive(surveyId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (Rows via ?? []) / Status-/Anonymous-Badges / Teilnehmen/Ergebnisse/Edit gated (hasSubmitted,canViewResults,canManage) / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrSurveyParticipationPage · D-HR „Umfrage Teilnahme" (A3/A4)

  • Interim-Screen: apps/web/app/components/screens/hr/HrSurveyParticipationPage.tsx
  • Route(n): /{tenant}/hr/surveys/{id} (routes/app.$tenant/hr.surveys.$id.tsx)
  • Daten (VM): HrSurveyParticipationVM, HrSurveyItem, HrSurveyItemType — packages/view-models/src/hr/hr-survey.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): Alert, Button, Card, Checkbox, Dialog, Select, TextInput; native input[type=date] (sanktionierte Ausnahme) · Icons: FeatherPlus
  • Interaktionen (Actions): onSubmit(answers: Record<string,string>), onAddItem({itemType,prompt,options,required}), onRemoveItem(itemId)
  • States: Loading (status!=="ready" → leeres Div) / Anonymous-Hinweis (Alert) / bereits abgegeben (Alert success) / offen → Formular / geschlossen (Alert neutral) / Item-Editor nur bei canManage / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Item-Typen text/rating_5/nps/choice/boolean/date):
    • Neue UI/UX-Entscheidungen (Antwort-Feld-Rendering je Typ):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrSurveyResultsPage · D-HR „Umfrage Ergebnisse" (A3)

  • Interim-Screen: apps/web/app/components/screens/hr/HrSurveyResultsPage.tsx
  • Route(n): /{tenant}/hr/surveys/{id}/results (routes/app.$tenant/hr.surveys.$id.results.tsx)
  • Daten (VM): HrSurveyResultsVM — packages/view-models/src/hr/hr-survey.vm.ts (Verteilung + Durchschnitt + Freitext)
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Card, EmptyState, Progress · Icons: —
  • Interaktionen (Actions): keine (read-only)
  • States: Empty (submissionCount===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Anonymous-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Interim nutzt Progress-Balken; „richer charts" = expliziter Nachzug lt. Header):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAdminAnnouncementsPage · D-HR „Ankündigungen verwalten" (A2 + A4/A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAdminAnnouncementsPage.tsx
  • Route(n): /{tenant}/hr/admin/announcements (routes/app.$tenant/hr.admin.announcements._index.tsx)
  • Daten (VM): kein @hivegrid-VM — lokale Props rows: AdminAnnouncementRow[], audiences: string[]
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Checkbox, Dialog, EmptyState, Select, TextArea, TextInput, DateField (tasks) · Icons: FeatherPin, FeatherPlus
  • Interaktionen (Actions): onCreate({title,body,audienceKind,audienceRef,requiresAck,pinned,publishAt,expiresAt}), onArchive(announcementId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (—, Rows als Prop) / Ack-/Pin-/Audience-Badges / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Audience, Ack, Pin, Schedule/Expiry):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAdminPasswordSafePage · D-HR „Passwort-Safe-Verwaltung" (A2/A6)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAdminPasswordSafePage.tsx
  • Route(n): /{tenant}/hr/admin/password-safe (routes/app.$tenant/hr.admin.password-safe._index.tsx)
  • Daten (VM): AdminVaultListVM — packages/view-models/src/hr/hr-password-safe.vm.ts (alle Tenant-Vaults, Entry-/Access-Counts, NIE Inhalte)
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, EmptyState, Table · Icons: —
  • Interaktionen (Actions): onArchiveVault(vaultId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (status!=="ready" → leeres Div) / Active/Archived-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Oversight ohne Content-Zugriff):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAdminPayslipsPage · D-HR „Lohnabrechnungen verwalten" (A2 + A4)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAdminPayslipsPage.tsx
  • Route(n): /{tenant}/hr/admin/payslips (routes/app.$tenant/hr.admin.payslips._index.tsx)
  • Daten (VM): kein @hivegrid-VM — lokale Props rows: PayslipAdminRow[], preview: PayslipPreviewRow[] (confidence hard/soft/none), period: {year,month}
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, EmptyState, Table, TextArea, TextInput · Icons: —
  • Interaktionen (Actions): onMatch({periodYear,periodMonth,files}), onConfirm({fileId,employeeUserId,periodYear,periodMonth})
  • States: Empty (existing rows.length===0 → EmptyState) / Preview-Block nur bei preview.length>0 / Loading (Props) / Confidence-Badges / Read/Unread-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Bulk-Auto-Match-Preview + Per-Row-Confirm):
    • Neue UI/UX-Entscheidungen (Files-Input als Freitext-Hint, Assignee als userId-TextInput):
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAdminRequestTemplatesPage · D-HR „Antragsvorlagen" (A2 + A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAdminRequestTemplatesPage.tsx
  • Route(n): /{tenant}/hr/admin/request-templates (routes/app.$tenant/hr.admin.request-templates._index.tsx)
  • Daten (VM): HrRequestTemplateListVM, HrRequestKind — packages/view-models/src/hr/hr-request.vm.ts
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Dialog, EmptyState, Select, TextInput · Icons: FeatherPlus
  • Interaktionen (Actions): onCreate({requestKind,defaultApproverUserId,title,description}), onToggle(templateId,isActive), onArchive(templateId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (Rows via ?? []) / Inactive-Badge / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte:
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev:

HrAdminUploadRemindersPage · D-HR „Upload-Erinnerungen" (A2 + A5)

  • Interim-Screen: apps/web/app/components/screens/hr/HrAdminUploadRemindersPage.tsx
  • Route(n): /{tenant}/hr/admin/upload-reminders (routes/app.$tenant/hr.admin.upload-reminders._index.tsx)
  • Daten (VM): HrReminderListVM — packages/view-models/src/hr/hr-upload-reminder.vm.ts; HrReminderCadenceKind aus packages/view-models/src/hr/reminder-cadence.ts; plus Props documentKinds, audiences
  • Benötigte UI-Elemente (KEIN Layout): BadgeFeedback, Button, Card, Checkbox, Dialog, EmptyState, Select, TextInput, DateField (tasks) · Icons: FeatherPlus
  • Interaktionen (Actions): onCreate({title,documentKind,cadenceKind,intervalMonths,audienceKind,dueAt,mandatory,escalate}), onSetStatus(reminderId,"active"|"paused"), onArchive(reminderId)
  • States: Empty (rows.length===0 → EmptyState) / Loading (Rows via ?? []) / Status-Badge active/paused / Permission-Denied (Loader/404)
  • Davids Delta (offen):
    • Überschriebene/geänderte Spec-Punkte (Cadence once/yearly/every_n_months/on_expiry; Dispatch im Worker-Cron):
    • Neue UI/UX-Entscheidungen:
    • Subframe-Screen-Link(s):
    • Offene Fragen an Dev: