feat(documents): rebuild hub — root view + entity-folder view

Three rendering modes for the main panel:
  - HubRootView (no folder selected): port-wide Signing + recent Files.
  - EntityFolderView (system-managed entity subfolder selected):
    AggregatedSection × 2 with owner-grouped subsections + per-row
    "view signing details" link on signed files (heuristic: filename
    starts with "signed-"; follow-up: surface signedFromDocumentId
    from the aggregated API).
  - FlatFolderListing (any other folder): existing search + chips + list.

Drops the signing-status tab strip (in_progress / awaiting_them / etc.)
— folders are the primary navigation now. hub-counts query removed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-11 12:39:03 +02:00
parent 7f85128dc2
commit 631b5d7ed5
3 changed files with 340 additions and 197 deletions

View File

@@ -0,0 +1,87 @@
'use client';
import Link from 'next/link';
import { FileText, ClipboardSignature } from 'lucide-react';
import { usePaginatedQuery } from '@/hooks/use-paginated-query';
interface HubRootDoc {
id: string;
title: string;
documentType: string;
status: string;
createdAt: string;
}
interface HubRootFile {
id: string;
filename: string;
createdAt: string;
}
interface Props {
portSlug: string;
}
export function HubRootView({ portSlug }: Props) {
const { data: workflows, isLoading: workflowsLoading } = usePaginatedQuery<HubRootDoc>({
queryKey: ['documents', 'hub-root', 'workflows'],
endpoint: '/api/v1/documents?tab=in_progress',
filterDefinitions: [],
});
const { data: filesData, isLoading: filesLoading } = usePaginatedQuery<HubRootFile>({
queryKey: ['files', 'hub-root'],
endpoint: '/api/v1/files?sort=createdAt&order=desc&limit=20',
filterDefinitions: [],
});
return (
<div className="space-y-4">
<section className="rounded-md border bg-white">
<h3 className="flex items-center gap-2 border-b px-3 py-2 text-sm font-semibold">
<ClipboardSignature className="h-4 w-4 text-muted-foreground" />
Signing in progress
</h3>
{workflowsLoading ? (
<div className="p-3 text-sm text-muted-foreground">Loading...</div>
) : workflows.length === 0 ? (
<div className="p-3 text-sm text-muted-foreground">No workflows in flight.</div>
) : (
<ul className="divide-y">
{workflows.map((w) => (
<li key={w.id} className="px-3 py-2 text-sm">
<Link href={`/${portSlug}/documents/${w.id}`} className="hover:underline">
{w.title}
</Link>
<span className="ml-2 text-xs text-muted-foreground">{w.status}</span>
</li>
))}
</ul>
)}
</section>
<section className="rounded-md border bg-white">
<h3 className="flex items-center gap-2 border-b px-3 py-2 text-sm font-semibold">
<FileText className="h-4 w-4 text-muted-foreground" />
Recent files
</h3>
{filesLoading ? (
<div className="p-3 text-sm text-muted-foreground">Loading...</div>
) : filesData.length === 0 ? (
<div className="p-3 text-sm text-muted-foreground">No files yet.</div>
) : (
<ul className="divide-y">
{filesData.map((f) => (
<li key={f.id} className="flex items-center justify-between px-3 py-2 text-sm">
<span className="truncate">{f.filename}</span>
<span className="text-xs text-muted-foreground tabular-nums">
{new Date(f.createdAt).toLocaleDateString('en-GB')}
</span>
</li>
))}
</ul>
)}
</section>
</div>
);
}