"use client"; import { useState } from "react"; import { Plus, Settings2, Trash2, Star } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/primitives"; import { cn } from "@/lib/utils"; import type { Database, View, ViewType } from "@/lib/databases/types"; import { VIEW_TYPES } from "@/lib/databases/types"; import { useViewMutations } from "./hooks"; import { VIEW_META, Sel, Field, inputCls } from "./meta"; export function ViewTabs({ db, view, onSelect }: { db: Database; view: View; onSelect: (id: string) => void }) { const m = useViewMutations(db, db.pageId); const [adding, setAdding] = useState(false); const [settings, setSettings] = useState(false); const [name, setName] = useState(""); const [type, setType] = useState("table"); const create = async () => { const v = await m.createView.mutateAsync({ name: name.trim() || VIEW_META[type].label, type, config: defaultConfig(db, type) }); setAdding(false); setName(""); onSelect(v.id); }; return (
{db.views.map((v) => { const active = v.id === view.id; const btn = ; return active ? {btn} setSettings(false)} onDeleted={() => { setSettings(false); onSelect(db.views.find((x) => x.id !== v.id)?.id ?? v.id); }} /> : btn; })}
New view
setName(e.target.value)} placeholder={VIEW_META[type].label} autoFocus className={inputCls} onKeyDown={(e) => { if (e.key === "Enter") create(); }} />
{VIEW_TYPES.map((t) => )}
); } function defaultConfig(db: Database, type: ViewType) { const first = (types: string[]) => db.properties.find((p) => types.includes(p.type))?.id ?? null; if (type === "board") return { groupBy: first(["status", "select"]) }; if (type === "calendar") return { dateProperty: first(["date", "created_time"]) }; if (type === "timeline") { const d = first(["date"]); return { startProperty: d, endProperty: d }; } if (type === "gallery") return { coverProperty: first(["file"]) }; return {}; } function ViewSettings({ db, view, onClose, onDeleted }: { db: Database; view: View; onClose: () => void; onDeleted: () => void }) { const m = useViewMutations(db, db.pageId); const [name, setName] = useState(view.name); const c = view.config; const patch = (config: Record) => m.patchView.mutate({ id: view.id, config }); const dates = db.properties.filter((p) => ["date", "created_time", "last_edited_time"].includes(p.type)); const groups = db.properties.filter((p) => ["select", "status", "checkbox"].includes(p.type)); const files = db.properties.filter((p) => p.type === "file"); const opt = (ps: typeof db.properties, none = "—") => <>{ps.map((p) => )}; return (
View settings
setName(e.target.value)} onBlur={() => name.trim() && name !== view.name && m.patchView.mutate({ id: view.id, name })} className={inputCls} onKeyDown={(e) => { if (e.key === "Enter") { (e.target as HTMLInputElement).blur(); onClose(); } }} /> m.patchView.mutate({ id: view.id, type: e.target.value, config: defaultConfig(db, e.target.value as ViewType) })} className="w-full">{VIEW_TYPES.map((t) => )} {view.type === "board" && patch({ groupBy: e.target.value || null })} className="w-full">{opt(groups, "Choose…")}} {view.type === "calendar" && patch({ dateProperty: e.target.value || null })} className="w-full">{opt(dates, "Choose…")}} {view.type === "timeline" && <> patch({ startProperty: e.target.value || null })} className="w-full">{opt(dates, "Choose…")} patch({ endProperty: e.target.value || null })} className="w-full">{opt(dates, "Same as start")}} {view.type === "gallery" && patch({ coverProperty: e.target.value || null })} className="w-full">{opt(files, "Page icon")}}
{!view.isDefault && } {db.views.length > 1 && }
); }