Files
frontend/apps/cs/src/pages/site/ui/menu-node.tsx
T

129 lines
3.4 KiB
TypeScript

import { useState } from "react";
import type { NodeModel } from "@minoru/react-dnd-treeview";
import type { UseFieldArrayReturn } from "react-hook-form";
import { Button, Checkbox, cn } from "@common/components";
import { type TreeMenu } from "@/entities/tree-menu";
import type { SiteMapFormData, SiteMapPayloadData } from "@/entities/menu";
import { EditableNode } from "./editable-node";
type MenuNodeProps = {
node: NodeModel<TreeMenu>;
depth: number;
isOpen: boolean;
fieldArray: UseFieldArrayReturn<SiteMapFormData>;
onToggle: (id: NodeModel["id"]) => void;
};
function MenuNode({
node,
depth,
isOpen,
fieldArray,
onToggle,
}: MenuNodeProps) {
const { id, text, data } = node;
const indent = depth * 10 + 5;
const [editMode, setEditMode] = useState(false);
const [nodeName, setNodeName] = useState(text);
const [otptYn, setOtptYn] = useState(data?.otptYn ?? "N");
const updateField = (id: number, newField: SiteMapPayloadData) => {
const existingFieldIndex = fieldArray.fields.findIndex(
(field) => field.menuCd === id,
);
if (existingFieldIndex !== -1) {
fieldArray.update(existingFieldIndex, newField);
} else {
fieldArray.append(newField);
}
};
const handleToggle = () => onToggle(id);
const handleSave = async () => {
const newField = {
menuCd: id as number,
menuSubKornNm: nodeName,
otptYn,
};
updateField(id as number, newField);
setEditMode(false);
};
const handleCancel = () => {
setEditMode(false);
setNodeName(text);
};
const handleOtptYnChange = (checked: boolean) => {
const newField = {
menuCd: id as number,
menuSubKornNm: nodeName,
otptYn: checked ? "Y" : "N",
};
updateField(id as number, newField);
setOtptYn(checked ? "Y" : "N");
};
return (
<div
style={{ paddingInlineStart: indent }}
className={cn(
"group flex cursor-pointer items-center gap-2 rounded-sm p-2 hover:bg-accent",
editMode && "p-0 pr-2 hover:bg-transparent",
)}
onClick={(e) => {
e.stopPropagation();
handleToggle();
}}
>
{editMode ? (
<EditableNode
value={nodeName}
onChange={(e) => setNodeName(e.target.value)}
onSave={handleSave}
onCancel={handleCancel}
/>
) : (
<div className="flex w-full items-center justify-between">
<div className="flex items-center">
{data?.children?.length && (
<i
className={cn(
"diveicon di-arrow-forward mr-2 text-base text-label",
isOpen && "rotate-90",
)}
/>
)}
<span className="text-[1.4rem] font-medium text-label">
{nodeName}
</span>
</div>
<Button
variant="ghost"
size="icon"
className="invisible !bg-transparent group-hover:visible"
onClick={(e) => {
e.stopPropagation();
setEditMode(true);
}}
>
<i className="diveicon di-pencil" />
</Button>
</div>
)}
<Checkbox
className="ml-auto"
checked={otptYn === "Y"}
onClick={(e) => {
e.stopPropagation();
}}
onCheckedChange={handleOtptYnChange}
/>
</div>
);
}
export { MenuNode };