diff --git a/src/components/sidebar/Entity.tsx b/src/components/sidebar/Entity.tsx index 0cc5ba5..bf9310a 100644 --- a/src/components/sidebar/Entity.tsx +++ b/src/components/sidebar/Entity.tsx @@ -1,6 +1,8 @@ "use client"; -import { CollapsibleTrigger } from "@radix-ui/react-collapsible"; +import { useState } from "react"; +import { ChevronDown } from "lucide-react"; + import { SidebarGroup, SidebarGroupContent, @@ -9,27 +11,13 @@ import { SidebarMenuButton, SidebarMenuItem, } from "../ui/sidebar"; -import { Collapsible, CollapsibleContent } from "../ui/collapsible"; -import { ChevronDown, MoreHorizontal } from "lucide-react"; -import { Route, Workspace, LayoutNode } from "@/lib/types"; + import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuSeparator, - DropdownMenuTrigger, -} from "../ui/dropdown-menu"; -import { - Dialog, - DialogContent, - DialogHeader, - DialogTitle, - DialogDescription, - DialogFooter, -} from "@/components/ui/dialog"; -import { Input } from "@/components/ui/input"; -import { Button } from "@/components/ui/button"; -import { useState } from "react"; + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "../ui/collapsible"; + import { ContextMenu, ContextMenuContent, @@ -38,6 +26,22 @@ import { ContextMenuTrigger, } from "../ui/context-menu"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, + DialogFooter, +} from "../ui/dialog"; + +import { Input } from "../ui/input"; +import { Button } from "../ui/button"; + +import { Route, Workspace, LayoutNode } from "@/lib/types"; + +type DialogMode = "rename" | "add-item" | "add-group"; + type Props = { node: LayoutNode; workspace: Workspace; @@ -47,101 +51,151 @@ type Props = { parentGroupId: string | null, name?: string, ) => string | undefined; - addGroup: (name: string | undefined, parentGroupId: string | null) => string; + addGroup: (name: string, parentGroupId: string | null) => string; renameEntity: (entityId: string, newName: string) => void; deleteEntity: (entityId: string) => void; removeNode: (id: string) => void; renameGroup: (id: string, name: string) => void; }; -export default function EntitySwitch({ - node, - workspace, - setRoute, - addEntity, - addGroup, - renameEntity, - deleteEntity, - removeNode, - renameGroup, -}: Props) { - const [dialogOpen, setDialogOpen] = useState(false); +export default function EntitySwitch(props: Props) { + const { + node, + workspace, + setRoute, + addEntity, + addGroup, + renameEntity, + deleteEntity, + removeNode, + renameGroup, + } = props; + const [dialogValue, setDialogValue] = useState(""); - const [dialogMode, setDialogMode] = useState< - "rename-group" | "rename-item" | "add-item" | "add-group" - >("rename-item"); + const [dialogMode, setDialogMode] = useState(); - const openDialog = (mode: typeof dialogMode, initial = "") => { + const parentId = node.type === "group" ? node.id : null; + + const openDialog = (mode: DialogMode, initial = "") => { setDialogMode(mode); - // supply default for add-item - if (mode === "add-item") { - setDialogValue("New list"); - } else { - setDialogValue(initial); - } - setDialogOpen(true); + setDialogValue( + initial || + (mode === "add-item" + ? "New list" + : mode === "add-group" + ? "New group" + : ""), + ); }; - const handleDialogSubmit = () => { - if (dialogMode === "rename-group" && node.type === "group") { - renameGroup(node.id, dialogValue); - } else if (dialogMode === "rename-item" && node.type === "item") { - renameEntity(node.entityId, dialogValue); - } else if (dialogMode === "add-item") { - const parentId = node.type === "group" ? node.id : null; - addEntity("todo", parentId, dialogValue || "New list"); - } else if (dialogMode === "add-group") { - const parentId = node.type === "group" ? node.id : null; - addGroup(dialogValue || "New group", parentId); + const closeDialog = () => setDialogMode(undefined); + + const handleSubmit = () => { + const value = dialogValue.trim(); + if (!value) return; + + switch (dialogMode) { + case "rename": + if (node.type === "group") renameGroup(node.id, value); + else if (node.type === "item") renameEntity(node.entityId, value); + break; + + case "add-item": + addEntity("todo", parentId, value); + break; + + case "add-group": + addGroup(value, parentId); + break; } - setDialogOpen(false); + + closeDialog(); }; - // ---- GROUP ---- + const confirmDelete = (message: string, action: () => void) => { + if (window.confirm(message)) action(); + }; + + const dialogTitle = dialogMode?.startsWith("rename") + ? "Rename" + : dialogMode === "add-item" + ? "Add new list" + : "Add new group"; + + const dialog = ( + !o && closeDialog()}> + + + {dialogTitle} + + {(dialogMode === "add-item" || dialogMode === "add-group") && ( + Enter a name below. + )} + + + setDialogValue(e.target.value)} + /> + + + + + + + + ); + + /* ================= GROUP ================= */ + if (node.type === "group") { return ( <> -
- - - - - {node.name} - - + + + + + {node.name} + - - - openDialog("add-item")}> - Add list - - openDialog("add-group")}> - Add group - - - openDialog("rename-group", node.name)} - > - Rename - - { - if ( - window.confirm("Delete this group and its children?") - ) { - removeNode(node.id); - } - }} - > - Delete - - - -
+ + + + + openDialog("add-item")}> + Add list + + + openDialog("add-group")}> + Add group + + + + + openDialog("rename", node.name)} + > + Rename + + + + confirmDelete("Delete this group and its children?", () => + removeNode(node.id), + ) + } + > + Delete + + +
@@ -150,15 +204,8 @@ export default function EntitySwitch({ {node.children.map((child) => ( ))} @@ -166,52 +213,19 @@ export default function EntitySwitch({
- - {/* dialog for add/rename */} - - - - - {dialogMode.startsWith("rename") - ? "Rename" - : dialogMode === "add-item" - ? "Add new list" - : "Add new group"} - - - {dialogMode === "add-item" && - "A default todo list will be created."} - {dialogMode === "add-group" && - "Enter the name for the new group."} - - - setDialogValue(e.target.value)} - className="w-full" - /> - - - - - - + {dialog} ); } - // ---- ITEM ---- - const workspaceEntity = workspace.entities[node.entityId]; + /* ================= ITEM ================= */ - if (!workspaceEntity) { - return null; - } + const entity = workspace.entities[node.entityId]; + if (!entity) return null; return ( - -
+ <> + - {workspaceEntity.name} + {entity.name} + - openDialog("rename-item", workspaceEntity.name)} - > + openDialog("rename", entity.name)}> Rename + { - if (window.confirm("Delete this list?")) { - deleteEntity(node.entityId); - } - }} + onSelect={() => + confirmDelete("Delete this list?", () => + deleteEntity(node.entityId), + ) + } > Delete -
-
+ + {dialog} + ); }