"use client"; /** * GalleryView — card grid for GALLERY views. * * Cover = first FILES/image property (or record cover/icon), title, up to 2 * secondary properties. Masonry-ish via CSS grid auto rows. Card click → * record panel. */ import { useMemo } from "react"; import { LayoutGrid, Plus } from "lucide-react"; import { cn } from "@/lib/utils"; import { DatabaseProperty, DatabaseView, RecordDto, UseDatabaseRecordsResult, useCreateRecord, valueToText } from "@/hooks/use-database"; import { cellToText } from "@/components/database/cell-renderer"; export interface GalleryProps { databaseId: string; view: DatabaseView; properties: DatabaseProperty[]; records: UseDatabaseRecordsResult; onOpenRecord: (record: RecordDto) => void; readOnly?: boolean; } function coverOf(record: RecordDto, properties: DatabaseProperty[]): string | null { if (record.coverUrl) return record.coverUrl; const fileProp = properties.find( (p) => p.type === "files" && (record.properties[p.id]?.fileIds?.length ?? 0) > 0 ); if (fileProp) { const id = record.properties[fileProp.id]?.fileIds?.[0]; if (id) return `/api/preview/file/${id}`; } return null; } export function GalleryView({ databaseId, view, properties, records, onOpenRecord, readOnly }: GalleryProps) { const { data, isLoading } = records; const createRecord = useCreateRecord(databaseId); const titleProp = properties.find((p) => p.isTitle); const perRow = view.config.cardsPerRow ?? 4; const chips = useMemo( () => properties.filter((p) => p !== titleProp && p.type !== "files" && p.type !== "relation").slice(0, 2), [properties, titleProp] ); const addCard = () => { createRecord.mutate({ properties: titleProp ? { [titleProp.id]: { text: "New card", marks: [] } } : {} }); }; if (isLoading) { return (
No cards in this view yet.
{!readOnly && ( )}