Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 37x 37x 37x 13x 24x 24x 24x | /**
* Empty / unselected main pane for the Collections workspace.
*/
import { Database, Plus, Upload } from 'lucide-react';
import { useNavigate } from 'react-router';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import CollectionTemplatePicker from '@/components/collections/CollectionTemplatePicker';
import { BLANK_TEMPLATE_ID } from '@/lib/collectionTemplates';
import { useCollectionsWorkspace } from './CollectionsWorkspaceContext';
export default function CollectionEmptyState() {
const { collections, loading, isSuperadmin, setImportDialogOpen } =
useCollectionsWorkspace();
const navigate = useNavigate();
if (loading) {
return (
<div className="flex flex-1 items-center justify-center p-8 text-muted-foreground text-sm">
Loading collections…
</div>
);
}
const zeroCollections = collections.length === 0;
const goCreate = (templateId: string = BLANK_TEMPLATE_ID) => {
if (templateId === BLANK_TEMPLATE_ID) {
navigate('/admin/collections/new');
return;
}
navigate(`/admin/collections/new?template=${encodeURIComponent(templateId)}`);
};
return (
<div
className="flex flex-1 flex-col items-center justify-center p-8 text-center"
data-testid="collection-empty-state"
>
<div className="mx-auto max-w-lg space-y-4">
<Database className="mx-auto h-14 w-14 text-muted-foreground opacity-40" />
{zeroCollections ? (
<>
<div className="space-y-2">
<h2 className="text-xl font-semibold">No collections yet</h2>
<Badge variant="secondary" className="font-normal">
Global · multi-tenant
</Badge>
<p className="text-sm text-muted-foreground leading-relaxed">
Collections are global tables shared by all accounts. Each account's
rows are isolated by <code className="text-xs bg-muted px-1 rounded">account_id</code>
— not separate Postgres schemas.
</p>
</div>
{isSuperadmin && (
<div className="space-y-4 pt-2">
<div className="text-left space-y-2">
<p className="text-sm font-medium text-center">
Start from a template
</p>
<CollectionTemplatePicker
selectedId=""
onSelect={(id) => goCreate(id)}
variant="grid"
/>
</div>
<div className="flex flex-wrap items-center justify-center gap-2">
<Button
className="gap-1.5"
onClick={() => goCreate(BLANK_TEMPLATE_ID)}
>
<Plus className="h-4 w-4" />
Create blank collection
</Button>
<Button
variant="outline"
className="gap-1.5"
onClick={() => setImportDialogOpen(true)}
>
<Upload className="h-4 w-4" />
Import from JSON
</Button>
</div>
</div>
)}
</>
) : (
<>
<div className="space-y-2">
<h2 className="text-xl font-semibold">Select a collection</h2>
<p className="text-sm text-muted-foreground">
Choose a collection from the browser on the left to manage its schema,
data, rules, and analytics.
</p>
</div>
{isSuperadmin && (
<Button
className="gap-1.5"
onClick={() => goCreate(BLANK_TEMPLATE_ID)}
>
<Plus className="h-4 w-4" />
Create collection
</Button>
)}
</>
)}
</div>
</div>
);
}
|