"use client" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" import Image from "next/image" import { useState, useCallback, useEffect, useMemo } from "react" import { set, z } from "zod" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, } from "@/components/ui/form" import { Input } from "@/components/ui/input" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select" import { useUser } from "@clerk/nextjs" import { createSandbox } from "@/lib/actions" import { useRouter } from "next/navigation" import { Loader2, ChevronRight, ChevronLeft, Search, SlashSquare, } from "lucide-react" import { Button } from "../ui/button" import { projectTemplates } from "@/lib/data" import useEmblaCarousel from "embla-carousel-react" import type { EmblaCarouselType } from "embla-carousel" import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures" import { cn } from "@/lib/utils" const formSchema = z.object({ name: z .string() .min(1) .max(16) .refine( (value) => /^[a-zA-Z0-9_]+$/.test(value), "Name must be alphanumeric and can contain underscores" ), visibility: z.enum(["public", "private"]), }) export default function NewProjectModal({ open, setOpen, }: { open: boolean setOpen: (open: boolean) => void }) { const router = useRouter() const user = useUser() const [selected, setSelected] = useState("reactjs") const [loading, setLoading] = useState(false) const [emblaRef, emblaApi] = useEmblaCarousel({ loop: false }, [ WheelGesturesPlugin(), ]) const { prevBtnDisabled, nextBtnDisabled, onPrevButtonClick, onNextButtonClick, } = usePrevNextButtons(emblaApi) const [search, setSearch] = useState("") const form = useForm>({ resolver: zodResolver(formSchema), defaultValues: { name: "", visibility: "public", }, }) const handleTemplateClick = useCallback( ({ id, index }: { id: string; index: number }) => { setSelected(id) emblaApi?.scrollTo(index) }, [emblaApi] ) const filteredTemplates = useMemo( () => projectTemplates.filter( (item) => item.name.toLowerCase().includes(search.toLowerCase()) || item.description.toLowerCase().includes(search.toLowerCase()) ), [search, projectTemplates] ) const emptyTemplates = useMemo( () => filteredTemplates.length === 0, [filteredTemplates] ) async function onSubmit(values: z.infer) { if (!user.isSignedIn) return const sandboxData = { type: selected, userId: user.user.id, ...values } setLoading(true) const id = await createSandbox(sandboxData) router.push(`/code/${id}`) } return ( { if (!loading) setOpen(open) }} > Create A Sandbox
{filteredTemplates.map((item, i) => ( ))} {emptyTemplates && (

No templates found

)}
( Name )} /> ( Visibility Note: All sandboxes cannot be seen by the public. Private sandboxes cannot be accessed by shared users that you add, while public sandboxes can. )} />
) } function SearchInput({ value, onValueChange, }: { value?: string onValueChange?: (value: string) => void }) { const onSubmit = useCallback((e: React.FormEvent) => { e.preventDefault() console.log("searching") }, []) return (
) } const usePrevNextButtons = (emblaApi: EmblaCarouselType | undefined) => { const [prevBtnDisabled, setPrevBtnDisabled] = useState(true) const [nextBtnDisabled, setNextBtnDisabled] = useState(true) const onPrevButtonClick = useCallback(() => { if (!emblaApi) return emblaApi.scrollPrev() }, [emblaApi]) const onNextButtonClick = useCallback(() => { if (!emblaApi) return emblaApi.scrollNext() }, [emblaApi]) const onSelect = useCallback((emblaApi: EmblaCarouselType) => { setPrevBtnDisabled(!emblaApi.canScrollPrev()) setNextBtnDisabled(!emblaApi.canScrollNext()) }, []) useEffect(() => { if (!emblaApi) return onSelect(emblaApi) emblaApi.on("reInit", onSelect).on("select", onSelect) }, [emblaApi, onSelect]) return { prevBtnDisabled, nextBtnDisabled, onPrevButtonClick, onNextButtonClick, } }