"use client"; import { FunctionSquareIcon, PlusIcon, SaveIcon } from "lucide-react"; import { useMemo, useState } from "react"; import { PublicBlockRenderer } from "@/components/public/block-renderer"; import { blockLabels } from "@/components/admin/block-canvas"; import { MediaUploader, type UploadedMedia, } from "@/components/admin/media-uploader"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldTitle, } from "@/components/ui/field"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, } from "@/components/ui/input-group"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Switch } from "@/components/ui/switch"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { evaluateDataSource } from "@/lib/content/data-source"; import type { DataSourceSnapshot, PageSnapshot } from "@/lib/content/types"; import type { EditorDraft } from "@/lib/editor/draft"; export function EditorInspector({ snapshot, draft, selectedId, dataSources, onDraftChange, onDataSourceChange, onSaveDataSource, sourceSaving, onMediaReady, }: { snapshot: PageSnapshot; draft: EditorDraft; selectedId: string | null; dataSources: Record; onDraftChange: (draft: EditorDraft) => void; onDataSourceChange: (source: DataSourceSnapshot) => void; onSaveDataSource: (source: DataSourceSnapshot) => void; sourceSaving: boolean; onMediaReady: (media: UploadedMedia) => void; }) { const selected = draft.blocks.find((block) => block.id === selectedId); const preview = { ...snapshot, page: { ...snapshot.page, title: draft.title, slug: draft.slug, visible: draft.visible, publicNote: draft.publicNote, }, blocks: draft.blocks, dataSources, }; const patchSelected = (patch: Partial<(typeof draft.blocks)[number]>) => { if (!selected) return; onDraftChange({ ...draft, blocks: draft.blocks.map((block) => block.id === selected.id ? { ...block, ...patch } : block, ), }); }; return (
Inspector Live Preview
{selected ? (
{blockLabels[selected.type] ?? selected.type}

{selected.id}

ความกว้าง
ซ่อนบนมือถือ เนื้อหานี้จะเริ่มแสดงตั้งแต่หน้าจอแท็บเล็ต
| undefined)?.hideOnMobile)} onCheckedChange={(hideOnMobile) => patchSelected({ responsiveLayout: { ...(selected.responsiveLayout as object ?? {}), hideOnMobile, }, }) } />
patchSelected({ config })} /> {Object.values(dataSources).map((source) => ( onSaveDataSource(source)} saving={sourceSaving} /> ))}
) : (
เลือกบล็อกบนแคนวาสเพื่อแก้ไขการจัดวางและข้อมูลขั้นสูง
)}
); } function AdvancedBlockSettings({ block, sources, onConfigChange, }: { block: EditorDraft["blocks"][number]; sources: Record; onConfigChange: (config: Record) => void; }) { const config = block.config as Record; if (!("dataSourceId" in config)) return null; return ( แหล่งข้อมูล ); } function DataSourceEditor({ source, onChange, onSave, saving, }: { source: DataSourceSnapshot; onChange: (source: DataSourceSnapshot) => void; onSave: () => void; saving: boolean; }) { const [rowId, setRowId] = useState(null); const evaluated = useMemo(() => { try { return evaluateDataSource(source); } catch { return null; } }, [source]); const selectedRow = source.rows.find((row) => row.id === rowId); const formulaFields = source.fields.filter((field) => field.formula); const previewRow = evaluated?.rows[0]; function updateField(key: string, formula: string) { onChange({ ...source, fields: source.fields.map((field) => field.key === key ? { ...field, formula: formula || null } : field, ), }); } return (
{source.name} แหล่งข้อมูลทั่วโลก · เวอร์ชัน {source.version}
{formulaFields.map((field) => { const cell = previewRow?.cells[field.key]; return ( {field.label} fx updateField(field.key, event.target.value)} /> {source.fields.filter((candidate) => candidate.key !== field.key).map((candidate) => )} {cell?.error ? สูตรนี้ยังคำนวณไม่ได้: ตรวจสอบชื่อฟิลด์และตัวหาร : ตัวอย่างผลลัพธ์: {cell?.display ?? "-"}} ); })}
{source.fields.slice(0, 3).map((field) => {field.label})}{source.rows.slice(0, 10).map((row) => {source.fields.slice(0, 3).map((field) => {row.values[field.key] ?? previewRow?.cells[field.key]?.display ?? "-"})})}
{ if (!open) setRowId(null); }}> แก้ไขแถวข้อมูล กรอกค่าต้นทาง ระบบจะคำนวณฟิลด์สูตรให้อัตโนมัติ {selectedRow ? ( {source.fields.map((field) => ( {field.label} onChange({ ...source, rows: source.rows.map((row) => row.id === selectedRow.id ? { ...row, values: { ...row.values, [field.key]: event.target.value || null } } : row), })} /> ))} ) : null}
); }