import { emitter, useScene } from "@pascal-app/core"; import { useViewer } from "@pascal-app/viewer"; import { Camera, Download, Save, Trash2, Upload } from "lucide-react"; import { useRef, useState } from "react"; import { Button } from "@/components/ui/primitives/button"; import { Switch } from "@/components/ui/primitives/switch"; import useEditor from "@/store/use-editor"; import { AudioSettingsDialog } from "./audio-settings-dialog"; import { useProjectStore } from "@/features/community/lib/projects/store"; import { updateProjectVisibility } from "@/features/community/lib/projects/actions"; export function SettingsPanel() { const fileInputRef = useRef(null); const nodes = useScene((state) => state.nodes); const rootNodeIds = useScene((state) => state.rootNodeIds); const setScene = useScene((state) => state.setScene); const clearScene = useScene((state) => state.clearScene); const resetSelection = useViewer((state) => state.resetSelection); const exportScene = useViewer((state) => state.exportScene); const setPhase = useEditor((state) => state.setPhase); const activeProject = useProjectStore((state) => state.activeProject); const [isGeneratingThumbnail, setIsGeneratingThumbnail] = useState(false); const projectId = activeProject?.id; const isLocalProject = false; // Store only contains cloud projects const handleExport = async () => { if (exportScene) { await exportScene(); } }; const handleSaveBuild = () => { const sceneData = { nodes, rootNodeIds }; const json = JSON.stringify(sceneData, null, 2); const blob = new Blob([json], { type: "application/json" }); const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; const date = new Date().toISOString().split("T")[0]; link.download = `layout_${date}.json`; link.click(); URL.revokeObjectURL(url); }; const handleFileLoad = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { try { const data = JSON.parse(event.target?.result as string); if (data.nodes && data.rootNodeIds) { setScene(data.nodes, data.rootNodeIds); resetSelection(); setPhase("site"); } } catch (err) { console.error("Failed to load build:", err); } }; reader.readAsText(file); // Reset input so the same file can be loaded again e.target.value = ""; }; const handleResetToDefault = () => { clearScene(); resetSelection(); setPhase("site"); }; const handleGenerateThumbnail = () => { if (!projectId) return; setIsGeneratingThumbnail(true); emitter.emit('camera-controls:generate-thumbnail', { projectId }); setTimeout(() => setIsGeneratingThumbnail(false), 3000); }; const handleVisibilityChange = async ( field: 'isPrivate' | 'showScansPublic' | 'showGuidesPublic', value: boolean, ) => { if (!projectId) return; // Optimistic update useProjectStore.setState((state) => ({ activeProject: state.activeProject ? { ...state.activeProject, ...(field === 'isPrivate' && { is_private: value }), ...(field === 'showScansPublic' && { show_scans_public: value }), ...(field === 'showGuidesPublic' && { show_guides_public: value }), } : null, })); await updateProjectVisibility(projectId, { [field]: value }); }; return (
{/* Visibility Section (only for cloud projects) */} {projectId && !isLocalProject && (
Public
{activeProject?.is_private ? 'Only you' : 'Anyone'} can view
handleVisibilityChange('isPrivate', !checked)} />
Show 3D Scans
Visible to public viewers
handleVisibilityChange('showScansPublic', checked)} />
Show Floorplans
Visible to public viewers
handleVisibilityChange('showGuidesPublic', checked)} />
)} {/* Export Section */}
{/* Thumbnail Section (only for cloud projects) */} {projectId && !isLocalProject && (
{activeProject?.thumbnail_url && (
{/* eslint-disable-next-line @next/next/no-img-element */} Project thumbnail
)}
)} {/* Save/Load Section */}
{/* Audio Section */}
{/* Danger Zone */}
); }