"use client"
import { $fetch } from "@repo/lib/api"
import { DEFAULT_PROJECT_ID } from "@repo/lib/constants"
import { Button } from "@repo/ui/components/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@repo/ui/components/dialog"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@repo/ui/components/dropdown-menu"
import { Label } from "@repo/ui/components/label"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@repo/ui/components/select"
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import {
ChevronDown,
FolderIcon,
Loader2,
MoreHorizontal,
Plus,
Trash2,
} from "lucide-react"
import { AnimatePresence, motion } from "motion/react"
import { useState } from "react"
import { toast } from "sonner"
import { useProjectMutations } from "@/hooks/use-project-mutations"
import { useProjectName } from "@/hooks/use-project-name"
import { useProject } from "@/stores"
import { CreateProjectDialog } from "./create-project-dialog"
interface Project {
id: string
name: string
containerTag: string
createdAt: string
updatedAt: string
isExperimental?: boolean
}
export function ProjectSelector() {
const queryClient = useQueryClient()
const [isOpen, setIsOpen] = useState(false)
const [showCreateDialog, setShowCreateDialog] = useState(false)
const { selectedProject } = useProject()
const projectName = useProjectName()
const { switchProject, deleteProjectMutation } = useProjectMutations()
const [deleteDialog, setDeleteDialog] = useState<{
open: boolean
project: null | { id: string; name: string; containerTag: string }
action: "move" | "delete"
targetProjectId: string
}>({
open: false,
project: null,
action: "move",
targetProjectId: DEFAULT_PROJECT_ID,
})
const [expDialog, setExpDialog] = useState<{
open: boolean
projectId: string
}>({
open: false,
projectId: "",
})
const { data: projects = [], isLoading } = useQuery({
queryKey: ["projects"],
queryFn: async () => {
const response = await $fetch("@get/projects")
if (response.error) {
throw new Error(response.error?.message || "Failed to load projects")
}
return response.data?.projects || []
},
staleTime: 30 * 1000,
})
const enableExperimentalMutation = useMutation({
mutationFn: async (projectId: string) => {
const response = await $fetch(
`@post/projects/${projectId}/enable-experimental`,
)
if (response.error) {
throw new Error(
response.error?.message || "Failed to enable experimental mode",
)
}
return response.data
},
onSuccess: () => {
toast.success("Experimental mode enabled for project")
queryClient.invalidateQueries({ queryKey: ["projects"] })
setExpDialog({ open: false, projectId: "" })
},
onError: (error) => {
toast.error("Failed to enable experimental mode", {
description: error instanceof Error ? error.message : "Unknown error",
})
},
})
const handleProjectSelect = (containerTag: string) => {
switchProject(containerTag)
setIsOpen(false)
}
const handleCreateNewProject = () => {
setIsOpen(false)
setShowCreateDialog(true)
}
return (
{isOpen && (
<>
setIsOpen(false)}
/>
{/* User Projects */}
{projects
.filter((p: Project) => p.containerTag !== DEFAULT_PROJECT_ID)
.map((project: Project, index: number) => (
e.stopPropagation()}
whileHover={{ scale: 1.1 }}
whileTap={{ scale: 0.9 }}
>
{/* Show experimental toggle only if NOT experimental and NOT default project */}
{!project.isExperimental &&
project.containerTag !== DEFAULT_PROJECT_ID && (
{
e.stopPropagation()
setExpDialog({
open: true,
projectId: project.id,
})
setIsOpen(false)
}}
>
Enable Experimental Mode
)}
{project.isExperimental && (
Experimental Mode Active
)}
{
e.stopPropagation()
setDeleteDialog({
open: true,
project: {
id: project.id,
name: project.name,
containerTag: project.containerTag,
},
action: "move",
targetProjectId: "",
})
setIsOpen(false)
}}
>
Delete Project
))}
New Project
>
)}
{/* Delete Project Dialog */}
{deleteDialog.open && deleteDialog.project && (
)}
{/* Experimental Mode Confirmation Dialog */}
{expDialog.open && (
)}
)
}