Wire the app to the shared Supabase catalog (public catalog read integration)

Moves port/cable/category/device-template data from per-diagram embedded
storage to the global public/private catalog backed by Supabase, per
organized-ideas.md's "live reference, not snapshot" decision.

- domain/types.ts, project.ts, compatibility.ts, bom.ts: lookup functions
  now take an explicit Catalog parameter instead of deriving data from
  Project — Project is reduced to just diagram-scoped fields.
- New CatalogRepository/SupabaseCatalogRepository (mirrors the
  DiagramRepository pattern) and catalogStore.ts, replacing the
  catalog-related actions that used to live in projectStore.
- device_templates gets a plain-text manufacturer column for now (the
  normalized manufacturer catalog from organized-ideas.md §3 is its own
  future pass, not blocking this one).
- domain/library.ts is no longer imported by the app — it's now only the
  source scripts/generate-seed.mjs reads to produce supabase/seed.sql.
- Swept every UI call site via tsc -b until clean; oxlint clean; 23/23
  pgTAP RLS tests still passing after a `supabase db reset`.
This commit is contained in:
2026-09-07 23:42:00 -05:00
parent 93cb4a9617
commit b97777444a
22 changed files with 656 additions and 323 deletions
+7 -7
View File
@@ -1,6 +1,6 @@
import { useMemo, useState } from 'react'
import { allDeviceCategories } from '../../domain/project'
import { useProjectStore } from '../../state/projectStore'
import { useCatalogStore } from '../../state/catalogStore'
const NEW_CATEGORY_VALUE = '__new__'
@@ -16,20 +16,20 @@ export default function CategorySelect({
onChange: (categoryId: string) => void
className?: string
}) {
const project = useProjectStore((s) => s.project)
const addCustomDeviceCategory = useProjectStore((s) => s.addCustomDeviceCategory)
const catalog = useCatalogStore((s) => s.catalog)
const addCustomDeviceCategory = useCatalogStore((s) => s.addCustomDeviceCategory)
const [creating, setCreating] = useState(false)
const [draftName, setDraftName] = useState('')
const categories = useMemo(
() => [...allDeviceCategories(project)].sort((a, b) => a.name.localeCompare(b.name)),
[project],
() => [...allDeviceCategories(catalog)].sort((a, b) => a.name.localeCompare(b.name)),
[catalog],
)
const commitNewCategory = () => {
const commitNewCategory = async () => {
const trimmed = draftName.trim()
if (trimmed) {
onChange(addCustomDeviceCategory(trimmed))
onChange(await addCustomDeviceCategory(trimmed))
}
setCreating(false)
setDraftName('')