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

88 lines
9.1 KiB
Markdown

# P04 · Files & Tasks (AK-P4a/b → D-P4)
> Interim-UI-Referenz (AD-28) für zwei Domänen (Dev-DoD 100 %, `🎨 design-nachzug: offen`). Alle Screens aus
> `~/ui` komponiert, VM als Prop, Backend/Loader/Action stabil. **Layout = Davids freie Hand.** Routen liegen
> unter `apps/web/app/routes/app.$tenant/`, laufen real unter `/:tenant/<route>` (Kurzform wie in D-P4).
## Files
### FilesBrowserPage · Files-Browser [`/files`] (A2)
- **Interim-Screen:** `apps/web/app/components/screens/files/FilesBrowserPage.tsx`
- **Route(n):** `/files` (`routes/app.$tenant/files._index.tsx`)
- **Daten (VM):** `FileBrowserVM` — `packages/view-models/src/files/file-browser.vm.ts`
- **Benötigte UI-Elemente (KEIN Layout):** ToggleGroup (Table/Grid-Umschalter), Button, Select (MIME/Entität/Tag/Verantwortlicher-Filter), Checkbox (Archiv-Toggle + Row-/Select-All), Table (+ HeaderRow/HeaderCell/Row/Cell), Card (Grid-Kacheln mit Thumbnail), BadgeFeedback (Preview-/Scan-Status), Tag_Label (Tags), plus native `<form>`-Bulk-ZIP-Leiste · Icons: FeatherList, FeatherGrid, FeatherUpload, FeatherDownload, FeatherFile
- **Interaktionen (Actions):** `onApply(query: FilesBrowserQuery)` (server-side Navigation: mimeGroup/entityType/tag/assignedToUserId/includeArchived/viewMode), `onToggleSelect(id)`, `onToggleSelectAll(ids, selectAll)`; zusätzlich Upload-CTA-Link (`uploadHref`), Cursor-Pagination-Link (`nextHref`), Bulk-ZIP-POST (`bulkZipAction`, `selectedIds`), Row-Detail-Links
- **States:** Empty (`emptyHeadlineKey`/`emptyBodyKey` + optional Upload-CTA) · Loading/not-ready (leerer Marker `ui.files.browser`) · Permission-Denied = 404 (Loader/Guard, kein UI-State); Upload-CTA nur bei `canWrite`
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev:
### FileUploadPage · Upload-View + Datei-Dropzone [`/files/upload`] (A4)
- **Interim-Screen:** `apps/web/app/components/screens/files/FileUploadPage.tsx`
- **Route(n):** `/files/upload` (`routes/app.$tenant/files.upload.tsx`; Resource-Routes: `files.upload.init.tsx`, `files.upload.$uploadId.chunk.$index.tsx`, `files.upload.$uploadId.complete.tsx`)
- **Daten (VM):** `FileUploadVM` — `packages/view-models/src/files/file-upload.vm.ts` (liefert `dropzoneHeadlineKey`/`dropzoneBodyKey`/`heicNoticeKey`); Queue-State separat als `items: FileUploadDisplayItem[]` (Route-injiziert)
- **Benötigte UI-Elemente (KEIN Layout):** Custom Drag&Drop-Dropzone (kein i18n-fähiges `~/ui`-Dropzone vorhanden — bewusst handgebaut), Button, Progress (Per-Datei-Fortschritt, State uploading/success/error), Alert (HEIC→JPG-Hinweis), Queue-Liste mit Per-Datei-Status · Icons: FeatherUpload
- **Interaktionen (Actions):** `onFiles(files: FileList | null)` (via Klick-Input + Drop); Client-Chunked-Pipeline (init/chunk/complete) lebt in der Route
- **States:** Empty (`files.upload.queue.empty`) · Per-Item queued/uploading/processing/done/error (mit `errorKey`, Retry-Text) · Loading/not-ready (leerer Marker `ui.files.upload`) · Permission-Denied = 404 (`files.write`-Gate im Loader)
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev:
### FileDetailPage · File-Detail [`/files/:id`] (A3)
- **Interim-Screen:** `apps/web/app/components/screens/files/FileDetailPage.tsx`
- **Route(n):** `/files/:id` (`routes/app.$tenant/files.$id.tsx`); Medien via `media.$fileId.$variant.tsx` (Auth-Proxy)
- **Daten (VM):** `FileDetailData` (entpackt aus `FileDetailVM`) — `packages/view-models/src/files/file-detail.vm.ts`
- **Benötigte UI-Elemente (KEIN Layout):** Breadcrumbs, Button, IconButton, Card (Stammdaten/Metadaten-Grid), Alert (Scan-Notice fail-closed + Preview-Fallback-Klartext), Tag_Label (Tags) + TextInput-Tag-Editor, Select (Entity-Type im Add-Link), TextInput (entityId/linkRole), Dialog (Add-Link S 560 + Delete XS 420), Bild-/PDF-Preview-Container · Icons: FeatherDownload, FeatherRefreshCw, FeatherArchive, FeatherTrash2, FeatherLink, FeatherX
- **Interaktionen (Actions):** Server-`<form method=post>`+`intent` — `regeneratePreview`, `archive`, `delete`, `updateMeta` (Tags), `link` (entityType/entityId/linkRole), `unlink` (entityType/entityId); Download-Link (`downloadUrl`); lokaler State nur für Dialog-Öffnen (addLinkOpen/deleteOpen)
- **States:** Scan-Notice (infected=error / pending=warning) · Preview vorhanden / `previewFallbackKey`-Klartext + Download · Linked-Entities Empty (`files.detail.links.empty`) · Tags-Editor/Aktionen nur bei `canWrite`/`canDelete`/`canRegeneratePreview` · Permission-Denied = 404 (Guard)
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev:
## Tasks
### TasksListPage · Task-Liste [`/tasks`] (A2 — wiederverwendbare Komponente)
- **Interim-Screen:** `apps/web/app/components/screens/tasks/TasksListPage.tsx`
- **Route(n):** `/tasks` (`routes/app.$tenant/tasks._index.tsx`) — Host der embeddable Liste; Entity-Detail-Views betten sie ein (R-P6 ff.)
- **Daten (VM):** `TaskListVM` — `packages/view-models/src/tasks/task-list.vm.ts`
- **Benötigte UI-Elemente (KEIN Layout):** ToggleGroup (Presets Meine/Erstellt/Alle), Select (Status- + Prioritäts-Filter), Checkbox (Archiv- + Demo-Daten-Toggle), Button (Neu-CTA + Pagination), Table (Titel/Status/Priorität/Assignee/Deadline), BadgeFeedback (Status), Tag_Label (Priorität), EmptyState · Icons: FeatherPlus
- **Interaktionen (Actions):** `onApply(query: TaskListQuery)` (server-side Navigation: preset/status/priority/includeArchived/includeDemoData); Neu-CTA-Link (`createHref`), Cursor-Pagination-Link (`nextHref`), Row-Detail-Links; `data-overdue`-Marker auf Deadline
- **States:** Empty (`emptyHeadlineKey`/`emptyBodyKey` via `EmptyState`) · Loading/not-ready (leerer Marker `ui.tasks.list`) · Neu-CTA nur bei `canWrite` · Permission-Denied = 404 (Preset „Alle" nur mit `tasks.read_all`)
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev:
### TaskDetailPage · Task-Detail [`/tasks/:id`] (A3 + A5)
- **Interim-Screen:** `apps/web/app/components/screens/tasks/TaskDetailPage.tsx`
- **Route(n):** `/tasks/:id` (`routes/app.$tenant/tasks.$id.tsx`)
- **Daten (VM):** `TaskDetailData` (entpackt aus `TaskDetailVM`) — `packages/view-models/src/tasks/task-detail.vm.ts`
- **Benötigte UI-Elemente (KEIN Layout):** Breadcrumbs, BadgeFeedback (Status) + Tag_Label (Priorität) + Quelle-Marker, Card (Overview-Metadaten + Edit-Formular), TextInput/TextArea (Titel/Beschreibung), Select (Status/Priorität/Assignee-Typ/Assignee/Watcher), DateField (native Date-Input-Helfer, kein `~/ui`-Äquivalent), Button/IconButton, Watcher-Liste, Dialog (Delete XS 420) · Icons: FeatherCheck, FeatherArchive, FeatherTrash2
- **Interaktionen (Actions):** Server-`<form method=post>`+`intent` — `complete`, `archive`, `delete`, `update` (title/description/status/priority/deadline), `reassign` (assigneeType user↔group + assigneeId), `addWatcher` (userId), `removeWatcher` (userId); lokaler State nur für Delete-Dialog
- **States:** Overdue-Marker (`data-overdue`, `isOverdue`) · linkedEntity optional · Watchers Empty (`tasks.detail.watchers.empty`) · Edit-/Reassign-/Watcher-/Complete-/Archive-Blöcke nur bei `canWrite`, Delete nur bei `canDelete`; „Erledigen" ausgeblendet wenn Status=done · Unassigned-Fallback-Text · Permission-Denied = 404 (fremde Task)
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev:
### TaskNewPage · Task-Anlage [`/tasks/new`] (A5 — Anlage-Modal/Form)
- **Interim-Screen:** `apps/web/app/components/screens/tasks/TaskNewPage.tsx`
- **Route(n):** `/tasks/new` (`routes/app.$tenant/tasks.new.tsx`)
- **Daten (VM):** kein VM-Wrapper — Loader-injizierte Props `assignableUsers`/`assignableGroups`/`prefill`/`cancelHref` (`TaskPickerOption`, `TaskNewPrefill`); Typ `TaskPriority` aus `@hivegrid/view-models` (`packages/view-models/src/tasks/task-list.vm.ts`)
- **Benötigte UI-Elemente (KEIN Layout):** Breadcrumbs, Card, TextInput (Titel), TextArea (Beschreibung), Select (Priorität/Assignee-Typ user↔group/Assignee mit Creator-Default-Sentinel `__creator__`), DateField (Deadline), Button (Anlegen + Cancel-Link), optionaler Prefill-Marker · Icons: FeatherPlus
- **Interaktionen (Actions):** Server-`<form method=post>` → Route-Action `createTask` (title/description/priority/deadline/assigneeType/assigneeId; optional hidden entityType/entityId aus `prefill`); Cancel-Link (`cancelHref`); Assignee-Default `__creator__` mappt server-seitig auf „kein expliziter Assignee"
- **States:** Prefill-Hinweiszeile nur wenn `prefill` gesetzt (Anlage aus Entity-Detail-CTA); Permission-Denied = 404 (`tasks.write`-Gate); reines Form, kein Empty/Loading
- **Davids Delta (offen):**
- [ ] Überschriebene/geänderte Spec-Punkte:
- [ ] Neue UI/UX-Entscheidungen:
- [ ] Subframe-Screen-Link(s):
- [ ] Offene Fragen an Dev: