diff --git a/components/workspace/file-explorer-top-menu.tsx b/components/workspace/file-explorer-top-menu.tsx new file mode 100644 index 0000000..00c832e --- /dev/null +++ b/components/workspace/file-explorer-top-menu.tsx @@ -0,0 +1,9 @@ +import NewFile from "./new-file"; + +export function FileExplorerTopMenu() { + return ( +
+ +
+ ); +} diff --git a/components/workspace/file-explorer.tsx b/components/workspace/file-explorer.tsx index 89377bc..9ce5ef0 100644 --- a/components/workspace/file-explorer.tsx +++ b/components/workspace/file-explorer.tsx @@ -12,6 +12,7 @@ import Link from "next/link"; import { usePathname, useSearchParams } from "next/navigation"; import useSWR, { mutate } from "swr"; import { FileIcon } from "./file-icon"; +import { FileExplorerTopMenu } from "./file-explorer-top-menu"; type TOCProps = { toc: TreeViewElement[]; @@ -116,7 +117,12 @@ const FileExplorer = () => { if (!toc) return

Loading...

; - return ; + return ( + <> + + + + ); }; /** diff --git a/components/workspace/new-file-form.tsx b/components/workspace/new-file-form.tsx new file mode 100644 index 0000000..e21e911 --- /dev/null +++ b/components/workspace/new-file-form.tsx @@ -0,0 +1,91 @@ +"use client"; + +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { z } from "zod"; + +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { usePathname } from "next/navigation"; +import { db } from "@/data/db"; +import { Loader2 } from "lucide-react"; +import { useRefreshFileExplorer } from "./file-explorer"; + +const FormSchema = z.object({ + path: z.string(), +}); + +export function NewFileForm({ + onSubmit, +}: { + onSubmit?: (path: string) => void; +}) { + const pathname = usePathname(); + const refreshFileExplorer = useRefreshFileExplorer(); + + const form = useForm>({ + resolver: zodResolver(FormSchema), + defaultValues: { + path: "", + }, + }); + + async function _onSubmit(data: z.infer) { + form.clearErrors(); + try { + await db.files.add({ + path: `${pathname}/${encodeURIComponent(data.path)}`, + contents: "", + }); + await refreshFileExplorer(); + onSubmit?.(data.path); + } catch (err) { + form.setError("path", { message: String(err) }); + } + } + + return ( +
+ + ( + + Path + + + + + This is the path of your new file. + + + + )} + /> + + + + ); +} diff --git a/components/workspace/new-file.tsx b/components/workspace/new-file.tsx new file mode 100644 index 0000000..5d87578 --- /dev/null +++ b/components/workspace/new-file.tsx @@ -0,0 +1,37 @@ +"use client"; + +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; + +import { useState } from "react"; +import { FilePlus } from "lucide-react"; +import { NewFileForm } from "./new-file-form"; + +export default function NewFile() { + const [isOpen, setIsOpen] = useState(false); + + return ( + setIsOpen(open)}> + + + + + + New File + + setIsOpen(false)} /> + + + + + ); +}