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:
87
src/components/documents/hub-root-view.tsx
Normal file
87
src/components/documents/hub-root-view.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user