diff --git a/apps/editor/app/editor/[projectId]/page.tsx b/apps/editor/app/editor/[projectId]/page.tsx index 09102acc..2a013627 100644 --- a/apps/editor/app/editor/[projectId]/page.tsx +++ b/apps/editor/app/editor/[projectId]/page.tsx @@ -1,24 +1,33 @@ 'use client' import Editor from '@/components/editor' -import { useParams } from 'next/navigation' -import { useEffect, useLayoutEffect } from 'react' +import { useParams, useRouter } from 'next/navigation' +import { useLayoutEffect } from 'react' import { useProjectStore } from '@/features/community/lib/projects/store' import { useAuth } from '@/features/community/lib/auth/hooks' export default function EditorPage() { const params = useParams() const projectId = params.projectId as string - const { isAuthenticated } = useAuth() + const { isAuthenticated, isLoading } = useAuth() const setActiveProject = useProjectStore((state) => state.setActiveProject) + const router = useRouter() // Use layoutEffect to set active project BEFORE the editor renders and hooks run useLayoutEffect(() => { - // For authenticated users with cloud projects, set the active project from URL - if (isAuthenticated && projectId && !projectId.startsWith('local_')) { + if (isLoading) return + if (!isAuthenticated) { + router.replace('/') + return + } + if (projectId) { setActiveProject(projectId) } - }, [projectId, isAuthenticated, setActiveProject]) + }, [projectId, isAuthenticated, isLoading, setActiveProject, router]) + + if (isLoading || !isAuthenticated) { + return null + } return (
diff --git a/apps/editor/components/editor/index.tsx b/apps/editor/components/editor/index.tsx index 40edca0c..6509a582 100644 --- a/apps/editor/components/editor/index.tsx +++ b/apps/editor/components/editor/index.tsx @@ -2,8 +2,6 @@ import { initSpaceDetectionSync, initSpatialGridSync, useScene } from '@pascal-app/core' import { Viewer } from '@pascal-app/viewer' -import { useAuth } from '@/features/community/lib/auth/hooks' -import { useLocalProjectScene } from '@/features/community/lib/local-storage/hooks' import { useProjectScene } from '@/features/community/lib/models/hooks' import { useKeyboard } from '@/hooks/use-keyboard' import { initSFXBus } from '@/lib/sfx-bus' @@ -38,18 +36,7 @@ interface EditorProps { export default function Editor({ projectId }: EditorProps) { useKeyboard() - const { isAuthenticated } = useAuth() - - // Determine which mode to use - const isLocalProject = projectId?.startsWith('local_') - const shouldUseCloud = isAuthenticated && !isLocalProject - const shouldUseLocal = !shouldUseCloud && !!projectId - - // Call hooks unconditionally (hooks internally check if they should activate) - // Cloud hook activates when there's an activeProject in the store useProjectScene() - // Local hook activates when projectId is provided and starts with 'local_' - useLocalProjectScene(shouldUseLocal ? projectId : undefined) return (
diff --git a/apps/editor/components/ui/sidebar/panels/site-panel/references-dialog.tsx b/apps/editor/components/ui/sidebar/panels/site-panel/references-dialog.tsx index 7fd0b6b1..949c084f 100644 --- a/apps/editor/components/ui/sidebar/panels/site-panel/references-dialog.tsx +++ b/apps/editor/components/ui/sidebar/panels/site-panel/references-dialog.tsx @@ -53,8 +53,8 @@ export function ReferencesDialog({ levelId, open, onOpenChange }: ReferencesDial e.target.value = '' const projectId = activeProject?.id - if (!projectId || projectId.startsWith('local_')) { - setUploadError('Save your project to the cloud first to add references.') + if (!projectId) { + setUploadError('No active project. Please open a project first.') return } @@ -93,8 +93,8 @@ export function ReferencesDialog({ levelId, open, onOpenChange }: ReferencesDial e.target.value = '' const projectId = activeProject?.id - if (!projectId || projectId.startsWith('local_')) { - setUploadError('Save your project to the cloud first to add references.') + if (!projectId) { + setUploadError('No active project. Please open a project first.') return } @@ -142,7 +142,6 @@ export function ReferencesDialog({ levelId, open, onOpenChange }: ReferencesDial // Delete storage asset first (before removing from scene) if ( projectId && - !projectId.startsWith('local_') && refNode?.url && (refNode.url.startsWith('http://') || refNode.url.startsWith('https://')) ) { diff --git a/apps/editor/features/community/components/cloud-save-button.tsx b/apps/editor/features/community/components/cloud-save-button.tsx index 7a3d4f2c..750339ee 100644 --- a/apps/editor/features/community/components/cloud-save-button.tsx +++ b/apps/editor/features/community/components/cloud-save-button.tsx @@ -1,32 +1,23 @@ 'use client' -import { Cloud, Home } from 'lucide-react' -import { useEffect, useState } from 'react' +import { Home } from 'lucide-react' import { useRouter } from 'next/navigation' +import { useEffect } from 'react' import { useAuth } from '../lib/auth/hooks' import { useProjectStore } from '../lib/projects/store' import { ProfileDropdown } from './profile-dropdown' -import { SignInDialog } from './sign-in-dialog' - -interface CloudSaveButtonProps { - projectId?: string -} /** * CloudSaveButton - Shows authentication state and project management * - * Guest with local project: Shows "Save to cloud" button - * Guest without project: Shows "Home" button + * Guest: Shows "Home" button * Authenticated: Shows ProfileDropdown */ -export function CloudSaveButton({ projectId }: CloudSaveButtonProps) { +export function CloudSaveButton() { const { isAuthenticated, isLoading } = useAuth() - const [isSignInDialogOpen, setIsSignInDialogOpen] = useState(false) const initialize = useProjectStore(state => state.initialize) const router = useRouter() - const isLocalProject = projectId?.startsWith('local_') - // Initialize project store when authenticated useEffect(() => { if (isAuthenticated) { @@ -44,25 +35,6 @@ export function CloudSaveButton({ projectId }: CloudSaveButtonProps) { ) } - // Guest user with local project - if (!isAuthenticated && isLocalProject) { - return ( - <> -
- -
- - - ) - } - - // Guest user (no project context or browsing) if (!isAuthenticated) { return (
@@ -77,7 +49,6 @@ export function CloudSaveButton({ projectId }: CloudSaveButtonProps) { ) } - // Authenticated user return (
diff --git a/apps/editor/features/community/components/community-hub.tsx b/apps/editor/features/community/components/community-hub.tsx index 839fdc9b..4c2e235d 100644 --- a/apps/editor/features/community/components/community-hub.tsx +++ b/apps/editor/features/community/components/community-hub.tsx @@ -4,8 +4,6 @@ import Image from 'next/image' import { useRouter } from 'next/navigation' import { useEffect, useState } from 'react' import { useAuth } from '../lib/auth/hooks' -import type { LocalProject } from '../lib/local-storage/project-store' -import { createLocalProject, getLocalProjects } from '../lib/local-storage/project-store' import { getPublicProjects, getUserProjects } from '../lib/projects/actions' import type { Project } from '../lib/projects/types' import { CreateProjectButton } from './create-project-button' @@ -16,27 +14,23 @@ import { ProjectGrid } from './project-grid' import { SignInDialog } from './sign-in-dialog' export default function CommunityHub() { - const { isAuthenticated, isLoading: authLoading, user } = useAuth() + const { isAuthenticated, isLoading: authLoading } = useAuth() const router = useRouter() const [isSignInDialogOpen, setIsSignInDialogOpen] = useState(false) const [isNewProjectDialogOpen, setIsNewProjectDialogOpen] = useState(false) - const [localProjectToSave, setLocalProjectToSave] = useState(null) const [publicProjects, setPublicProjects] = useState([]) const [userProjects, setUserProjects] = useState([]) - const [localProjects, setLocalProjects] = useState([]) const [loading, setLoading] = useState(true) useEffect(() => { async function loadProjects() { setLoading(true) - // Load public projects (always) const publicResult = await getPublicProjects() if (publicResult.success) { setPublicProjects(publicResult.data || []) } - // Load user projects if authenticated if (isAuthenticated) { const userResult = await getUserProjects() if (userResult.success) { @@ -44,9 +38,6 @@ export default function CommunityHub() { } } - // Always load local projects - setLocalProjects(getLocalProjects()) - setLoading(false) } @@ -55,27 +46,7 @@ export default function CommunityHub() { } }, [isAuthenticated, authLoading]) - const handleCreateProject = async () => { - if (!isAuthenticated) { - // Create local project for guest - const project = createLocalProject('Untitled Project') - router.push(`/editor/${project.id}`) - } else { - // Open project creation dialog for authenticated users - setIsNewProjectDialogOpen(true) - } - } - const handleProjectCreated = async (projectId: string) => { - // If this was a local project being saved, delete it from localStorage - if (localProjectToSave) { - const { deleteLocalProject } = await import('../lib/local-storage/project-store') - deleteLocalProject(localProjectToSave.id) - setLocalProjects(getLocalProjects()) - setLocalProjectToSave(null) - } - - // Reload projects and navigate to the new project const result = await getUserProjects() if (result.success) { setUserProjects(result.data || []) @@ -83,11 +54,6 @@ export default function CommunityHub() { router.push(`/editor/${projectId}`) } - const handleSaveLocalToCloud = (localProject: LocalProject) => { - setLocalProjectToSave(localProject) - setIsNewProjectDialogOpen(true) - } - const handleProjectClick = (projectId: string) => { router.push(`/editor/${projectId}`) } @@ -153,18 +119,17 @@ export default function CommunityHub() {

My Projects

- + setIsNewProjectDialogOpen(true)} />
- {userProjects.length === 0 && localProjects.length === 0 ? ( + {userProjects.length === 0 ? (

You don't have any projects yet.

) : ( { @@ -181,30 +146,19 @@ export default function CommunityHub() {
)} - {/* Local Projects Section (Guest Users) */} - {!isAuthenticated && localProjects.length > 0 && ( -
-
-

My Local Projects

- -
- -
- )} - - {/* Create First Project CTA */} - {!isAuthenticated && localProjects.length === 0 && ( -
-

Get Started

-

- Create your first project to start designing + {/* Sign-in CTA for unauthenticated users */} + {!isAuthenticated && ( +

+

Build with Pascal

+

+ Create and share 3D architectural projects. Sign in to get started.

- +
)} @@ -230,15 +184,6 @@ export default function CommunityHub() { open={isNewProjectDialogOpen} onOpenChange={setIsNewProjectDialogOpen} onSuccess={handleProjectCreated} - localProjectData={ - localProjectToSave - ? { - id: localProjectToSave.id, - name: localProjectToSave.name, - sceneGraph: localProjectToSave.scene_graph, - } - : undefined - } />
) diff --git a/apps/editor/features/community/components/local-project-migration-dialog.tsx b/apps/editor/features/community/components/local-project-migration-dialog.tsx deleted file mode 100644 index 277b5670..00000000 --- a/apps/editor/features/community/components/local-project-migration-dialog.tsx +++ /dev/null @@ -1,83 +0,0 @@ -'use client' - -import { useState } from 'react' -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from '@/components/ui/primitives/dialog' -import type { LocalProject } from '../lib/local-storage/project-store' - -interface LocalProjectMigrationDialogProps { - localProjects: LocalProject[] - open: boolean - onMigrate: () => Promise - onSkip: () => void -} - -export function LocalProjectMigrationDialog({ - localProjects, - open, - onMigrate, - onSkip, -}: LocalProjectMigrationDialogProps) { - const [isMigrating, setIsMigrating] = useState(false) - - const handleMigrate = async () => { - setIsMigrating(true) - try { - await onMigrate() - } finally { - setIsMigrating(false) - } - } - - return ( - !open && !isMigrating && onSkip()}> - - - Save Local Projects to Cloud - - You have {localProjects.length} local {localProjects.length === 1 ? 'project' : 'projects'} that {localProjects.length === 1 ? 'hasn\'t' : 'haven\'t'} been saved to the cloud yet. - - - -
-

- Would you like to save {localProjects.length === 1 ? 'it' : 'them'} to your account? -

-
    - {localProjects.map((project) => ( -
  • - - {project.name} -
  • - ))} -
-
- - - - - -
-
- ) -} diff --git a/apps/editor/features/community/components/new-project-dialog.tsx b/apps/editor/features/community/components/new-project-dialog.tsx index 88e40637..5b5fcc63 100644 --- a/apps/editor/features/community/components/new-project-dialog.tsx +++ b/apps/editor/features/community/components/new-project-dialog.tsx @@ -2,26 +2,21 @@ import { X } from 'lucide-react' import { useState } from 'react' -import { createProject } from '../lib/projects/actions' import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/primitives/dialog' import { Switch } from '@/components/ui/primitives/switch' +import { createProject } from '../lib/projects/actions' interface NewProjectDialogProps { open: boolean onOpenChange: (open: boolean) => void onSuccess?: (projectId: string) => void - localProjectData?: { - id: string - name: string - sceneGraph: any - } } /** - * NewProjectDialog - Dialog for creating a new project with optional Google Maps address search + * NewProjectDialog - Dialog for creating a new project */ -export function NewProjectDialog({ open, onOpenChange, onSuccess, localProjectData }: NewProjectDialogProps) { - const [projectName, setProjectName] = useState(localProjectData?.name || '') +export function NewProjectDialog({ open, onOpenChange, onSuccess }: NewProjectDialogProps) { + const [projectName, setProjectName] = useState('') const [isPrivate, setIsPrivate] = useState(false) const [isCreating, setIsCreating] = useState(false) const [error, setError] = useState(null) @@ -32,19 +27,10 @@ export function NewProjectDialog({ open, onOpenChange, onSuccess, localProjectDa const name = projectName.trim() || 'Untitled Project' - if (!name) { - setError('Please enter a project name') - return - } - setIsCreating(true) try { - const result = await createProject({ - name, - isPrivate, - sceneGraph: localProjectData?.sceneGraph, - }) + const result = await createProject({ name, isPrivate }) if (result.success && result.data) { onOpenChange(false) @@ -73,7 +59,7 @@ export function NewProjectDialog({ open, onOpenChange, onSuccess, localProjectDa return ( e.preventDefault()} > @@ -120,17 +106,6 @@ export function NewProjectDialog({ open, onOpenChange, onSuccess, localProjectDa
- {localProjectData && ( -
-

- Saving local project: {localProjectData.name} -

-

- Your building data will be preserved -

-
- )} - {error && (
{error} diff --git a/apps/editor/features/community/components/project-grid.tsx b/apps/editor/features/community/components/project-grid.tsx index d4e785bc..9b594f73 100644 --- a/apps/editor/features/community/components/project-grid.tsx +++ b/apps/editor/features/community/components/project-grid.tsx @@ -3,34 +3,25 @@ import { Eye, Heart, Settings } from 'lucide-react' import Link from 'next/link' import { useEffect, useState } from 'react' -import type { Project } from '../lib/projects/types' -import type { LocalProject } from '../lib/local-storage/project-store' -import { ProjectSettingsDialog } from './project-settings-dialog' -import { getUserProjectLikes, toggleProjectLike } from '../lib/projects/actions' import { useAuth } from '../lib/auth/hooks' +import { getUserProjectLikes, toggleProjectLike } from '../lib/projects/actions' +import type { Project } from '../lib/projects/types' +import { ProjectSettingsDialog } from './project-settings-dialog' interface ProjectGridProps { - projects: (Project | LocalProject)[] + projects: Project[] onProjectClick: (id: string) => void onViewClick?: (id: string) => void - onSaveToCloud?: (project: LocalProject) => void showOwner: boolean - isLocal?: boolean canEdit?: boolean onUpdate?: () => void } -function isLocalProject(prop: Project | LocalProject): prop is LocalProject { - return 'is_local' in prop && prop.is_local === true -} - export function ProjectGrid({ projects, onProjectClick, onViewClick, - onSaveToCloud, showOwner, - isLocal = false, canEdit = false, onUpdate, }: ProjectGridProps) { @@ -39,28 +30,21 @@ export function ProjectGrid({ const [userLikes, setUserLikes] = useState>({}) const [likeCounts, setLikeCounts] = useState>({}) - // Initialize like counts from projects useEffect(() => { const counts: Record = {} projects.forEach((proj) => { - if (!isLocalProject(proj)) { - counts[proj.id] = proj.likes - } + counts[proj.id] = proj.likes }) setLikeCounts(counts) }, [projects]) - // Fetch which projects the user has liked useEffect(() => { if (!isAuthenticated) { setUserLikes({}) return } - const projectIds = projects - .filter((p) => !isLocalProject(p)) - .map((p) => p.id) - + const projectIds = projects.map((p) => p.id) if (projectIds.length === 0) return getUserProjectLikes(projectIds).then((result) => { @@ -70,11 +54,9 @@ export function ProjectGrid({ }) }, [projects, isAuthenticated]) - const handleSettingsClick = (e: React.MouseEvent, project: Project | LocalProject) => { + const handleSettingsClick = (e: React.MouseEvent, project: Project) => { e.stopPropagation() - if (!isLocalProject(project)) { - setSettingsProject(project) - } + setSettingsProject(project) } const handleViewClick = (e: React.MouseEvent, projectId: string) => { @@ -85,31 +67,24 @@ export function ProjectGrid({ const handleLikeClick = async (e: React.MouseEvent, projectId: string) => { e.stopPropagation() - if (!isAuthenticated) { - // Could show a sign-in prompt here - return - } + if (!isAuthenticated) return - // Optimistic update const wasLiked = userLikes[projectId] || false const currentCount = likeCounts[projectId] || 0 setUserLikes((prev) => ({ ...prev, [projectId]: !wasLiked })) setLikeCounts((prev) => ({ ...prev, - [projectId]: wasLiked ? currentCount - 1 : currentCount + 1 + [projectId]: wasLiked ? currentCount - 1 : currentCount + 1, })) - // Call server action const result = await toggleProjectLike(projectId) if (result.success && result.data) { - // Update with actual values from server const data = result.data setUserLikes((prev) => ({ ...prev, [projectId]: data.liked })) setLikeCounts((prev) => ({ ...prev, [projectId]: data.likes })) } else { - // Revert on error setUserLikes((prev) => ({ ...prev, [projectId]: wasLiked })) setLikeCounts((prev) => ({ ...prev, [projectId]: currentCount })) } @@ -119,7 +94,7 @@ export function ProjectGrid({ <>
{projects.map((project) => { - const owner = !isLocalProject(project) ? project.owner : null + const owner = project.owner return (
{/* Thumbnail card */}
- {!isLocalProject(project) && project.thumbnail_url ? ( + {project.thumbnail_url ? ( {project.name} )} - {isLocalProject(project) && ( -
- {isAuthenticated && onSaveToCloud ? ( - - ) : ( -
- Local -
- )} -
- )} - {canEdit && !isLocalProject(project) && ( + {canEdit && (
{onViewClick && ( )} - {isLocalProject(project) && ( - {new Date(project.updated_at).toLocaleDateString()} - )} +
+ + {project.views} +
+ · +
@@ -257,7 +201,6 @@ export function ProjectGrid({ })}
- {/* Settings Dialog */} {settingsProject && ( (undefined) - const currentProjectIdRef = useRef(null) - const lastProjectIdRef = useRef(null) - - // Load scene when project ID changes - useEffect(() => { - if (!projectId || !projectId.startsWith('local_')) { - return - } - - if (lastProjectIdRef.current === projectId) { - return - } - - lastProjectIdRef.current = projectId - currentProjectIdRef.current = projectId - - const project = getLocalProject(projectId) - - if (project?.scene_graph) { - const { nodes, rootNodeIds } = project.scene_graph - useScene.getState().setScene(nodes, rootNodeIds as AnyNodeId[]) - initSpatialGridSync() - } else { - useScene.getState().clearScene() - } - - useEditor.getState().setPhase('site') - useViewer.getState().setSelection({ - buildingId: null, - levelId: null, - selectedIds: [], - zoneId: null, - }) - }, [projectId]) - - // Auto-save to localStorage with debouncing - useEffect(() => { - if (!projectId || !projectId.startsWith('local_')) { - currentProjectIdRef.current = null - return - } - - currentProjectIdRef.current = projectId - let lastNodesSnapshot = JSON.stringify(useScene.getState().nodes) - - const unsubscribe = useScene.subscribe((state) => { - const currentNodesSnapshot = JSON.stringify(state.nodes) - - if (currentNodesSnapshot === lastNodesSnapshot) { - return - } - - lastNodesSnapshot = currentNodesSnapshot - const nodes = state.nodes - - if (saveTimeoutRef.current) { - clearTimeout(saveTimeoutRef.current) - } - - // Debounce save by 1 second (faster than cloud save) - saveTimeoutRef.current = setTimeout(() => { - const currentId = currentProjectIdRef.current - if (!currentId) return - - const rootNodeIds = useScene.getState().rootNodeIds - const sceneGraph = { nodes, rootNodeIds } - - updateLocalProjectScene(currentId, sceneGraph) - }, 1000) - }) - - return () => { - if (saveTimeoutRef.current) { - clearTimeout(saveTimeoutRef.current) - } - unsubscribe() - } - }, [projectId]) -} diff --git a/apps/editor/features/community/lib/local-storage/project-store.ts b/apps/editor/features/community/lib/local-storage/project-store.ts deleted file mode 100644 index 4560fb7d..00000000 --- a/apps/editor/features/community/lib/local-storage/project-store.ts +++ /dev/null @@ -1,114 +0,0 @@ -/** - * Local storage management for guest users - * Stores projects and scenes in browser localStorage - */ - -import { createId } from '../utils/id-generator' - -export interface SceneGraph { - nodes: Record - rootNodeIds: string[] -} - -export interface LocalProject { - id: string // Format: 'local_project_xyz' - name: string - created_at: string - updated_at: string - scene_graph: SceneGraph | null - is_local: true -} - -const LOCAL_PROJECTS_KEY = 'pascal_local_projects' -// Keep old key for migration -const LEGACY_LOCAL_PROPERTIES_KEY = 'pascal_local_properties' - -function migrateLegacyStorage(): void { - if (typeof window === 'undefined') return - - try { - const legacy = localStorage.getItem(LEGACY_LOCAL_PROPERTIES_KEY) - if (legacy && !localStorage.getItem(LOCAL_PROJECTS_KEY)) { - // Migrate old data to new key - const parsed = JSON.parse(legacy) - // Update IDs from local_property_* to local_project_* - const migrated = parsed.map((p: any) => ({ - ...p, - id: p.id.replace('local_property_', 'local_project_'), - })) - localStorage.setItem(LOCAL_PROJECTS_KEY, JSON.stringify(migrated)) - localStorage.removeItem(LEGACY_LOCAL_PROPERTIES_KEY) - } - } catch (error) { - console.error('Failed to migrate legacy local properties:', error) - } -} - -export function getLocalProjects(): LocalProject[] { - if (typeof window === 'undefined') return [] - - migrateLegacyStorage() - - try { - const stored = localStorage.getItem(LOCAL_PROJECTS_KEY) - return stored ? JSON.parse(stored) : [] - } catch (error) { - console.error('Failed to load local projects:', error) - return [] - } -} - -export function getLocalProject(id: string): LocalProject | null { - const projects = getLocalProjects() - return projects.find((p) => p.id === id) || null -} - -export function saveLocalProject(project: LocalProject): void { - const projects = getLocalProjects() - const index = projects.findIndex((p) => p.id === project.id) - - if (index >= 0) { - projects[index] = { ...project, updated_at: new Date().toISOString() } - } else { - projects.push(project) - } - - localStorage.setItem(LOCAL_PROJECTS_KEY, JSON.stringify(projects)) -} - -export function createLocalProject(name: string): LocalProject { - const project: LocalProject = { - id: createId('local_project'), - name, - created_at: new Date().toISOString(), - updated_at: new Date().toISOString(), - scene_graph: null, - is_local: true, - } - - saveLocalProject(project) - return project -} - -export function deleteLocalProject(id: string): void { - const projects = getLocalProjects().filter((p) => p.id !== id) - localStorage.setItem(LOCAL_PROJECTS_KEY, JSON.stringify(projects)) -} - -export function updateLocalProjectScene(id: string, sceneGraph: SceneGraph): void { - const project = getLocalProject(id) - if (project) { - project.scene_graph = sceneGraph - saveLocalProject(project) - } -} - -export function migrateLocalProjectsToCloud(userId: string): LocalProject[] { - // Return local projects that need to be migrated - // Actual migration handled by separate function - return getLocalProjects() -} - -export function clearLocalProjects(): void { - localStorage.removeItem(LOCAL_PROJECTS_KEY) -} diff --git a/apps/editor/features/community/lib/projects/actions.ts b/apps/editor/features/community/lib/projects/actions.ts index 0bc37057..a00efd9d 100644 --- a/apps/editor/features/community/lib/projects/actions.ts +++ b/apps/editor/features/community/lib/projects/actions.ts @@ -803,76 +803,6 @@ export async function updateProjectAddress( } } -/** - * Migrate a local project to the cloud - * Creates a new project with the local project's data - */ -export async function migrateLocalProject( - localProject: { - name: string - scene_graph: any - }, -): Promise> { - try { - const session = await getSession() - - if (!session?.user) { - return { - success: false, - error: 'Not authenticated', - } - } - - const supabase = await createServerSupabaseClient() - - // Create the project without an address (user can add one later via settings) - const projectId = createId('project') - const { error: projectError } = await (supabase.from('projects') as any).insert({ - id: projectId, - name: localProject.name, - owner_id: session.user.id, - address_id: null, - is_private: true, // Default to private - }) - - if (projectError) { - return { - success: false, - error: projectError.message, - } - } - - // Create the model with the scene graph - if (localProject.scene_graph) { - const modelId = createId('model') - const { error: modelError } = await (supabase.from('projects_models') as any).insert({ - id: modelId, - project_id: projectId, - version: 1, - scene_graph: localProject.scene_graph, - }) - - if (modelError) { - return { - success: false, - error: modelError.message, - } - } - } - - return { - success: true, - data: { id: projectId }, - message: 'Project migrated successfully', - } - } catch (error) { - return { - success: false, - error: error instanceof Error ? error.message : 'Failed to migrate project', - } - } -} - /** * Delete a project * Only the owner can delete their project