Integration: Stubs von L2/L3/L4/L5 gegen echte Services getauscht
- Aufträge: createWorkOrder/transitionWorkOrder/getCompletionBlockers aus L2 - Dokumente: storeFile aus L1; neu services/documents/read.ts (readStoredBytes, readDocumentBytes mit Prüfsummenprüfung); L2-Upload nutzt zentrale Ablage - Dubletten aus L1 (findDuplicateCustomers(ctx)); Objekt-Kandidaten als imports/site-candidates.ts; Dateityp-Erkennung mobil als field/mime.ts - Objekt-Historie mobil als Adapter auf L1 getSiteHistory, PDF über /api/v1/reports/:id/pdf - L4-Upload-Idempotenz: fester Upload-Lineage nach storeFile, Race → Soft-Delete + Replay - PDF-Worker-Kontext: document:write zum Ablegen des Berichts-PDF - Import: doppeltes Work-Order-Audit entfernt; bestätigte Aufträge starten planned - Dateilinks in Auftragsdetail auf /files/[documentId] - proxy: /api/v1 ohne Session → 401 JSON statt Login-Redirect - ARCHITEKTUR §2: Objekt-Historie für Feldrollen (freigegebene Einsätze aller Teams) Gate: tsc, lint, build, 42/42 Tests grün. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -339,9 +339,9 @@ export async function PhotosTab({ ctx, wo, locale, tz }: TabProps) {
|
||||
<ul className="grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4">
|
||||
{photos.map((p) => (
|
||||
<li key={p.id} className="shadow-card overflow-hidden rounded-xl border bg-card">
|
||||
<a href={`/files/${p.document.storageKey}`} className="block aspect-[4/3] bg-muted">
|
||||
<a href={`/files/${p.document.id}`} className="block aspect-[4/3] bg-muted">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element -- tenant file route, no next/image optimisation for private files */}
|
||||
<img src={`/files/${p.document.previewKey ?? p.document.storageKey}`} alt={p.comment ?? p.photoRequirement?.label ?? p.document.fileName} className="size-full object-cover" loading="lazy" />
|
||||
<img src={`/files/${p.document.id}`} alt={p.comment ?? p.photoRequirement?.label ?? p.document.fileName} className="size-full object-cover" loading="lazy" />
|
||||
</a>
|
||||
<div className="p-2 text-xs">
|
||||
<p className="flex items-center gap-1 font-semibold">
|
||||
@@ -452,7 +452,7 @@ export async function DocumentsTab({ ctx, wo, locale, tz, uploadError, uploaded
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<a href={`/files/${d.storageKey}`} className={buttonCls("outline")}>
|
||||
<a href={`/files/${d.id}`} className={buttonCls("outline")}>
|
||||
<Download className="size-4" aria-hidden />
|
||||
{t("documents.download")}
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user