feat: 조직도 트리 dnd 작업
This commit is contained in:
@@ -4,4 +4,4 @@ export {
|
||||
type OrganizationTree,
|
||||
type OrganizationFormData,
|
||||
} from "./model/organization-interface";
|
||||
export { generateOrganizationTreeData } from "./lib/utils";
|
||||
export { generateOrganizationTreeData, handleDropNode } from "./lib/utils";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import type { DropOptions, NodeModel } from "@minoru/react-dnd-treeview";
|
||||
import type { OrganizationTree } from "../model/organization-interface";
|
||||
|
||||
export const generateOrganizationTreeData = (
|
||||
@@ -21,3 +21,57 @@ export const generateOrganizationTreeData = (
|
||||
return acc;
|
||||
}, []);
|
||||
};
|
||||
|
||||
export const generateNewOrganizationTreeData = (
|
||||
treeData: NodeModel<OrganizationTree>[],
|
||||
options: DropOptions<OrganizationTree>,
|
||||
): OrganizationTree | null => {
|
||||
const { dragSourceId, dragSource, dropTargetId } = options;
|
||||
|
||||
if (!dragSource?.data) return null;
|
||||
|
||||
const siblings = treeData.filter((node) => node.parent === dropTargetId);
|
||||
|
||||
const dragSourceIndex = siblings.findIndex(
|
||||
(node) => node.id === dragSourceId,
|
||||
);
|
||||
|
||||
const prevSibling = siblings[dragSourceIndex - 1];
|
||||
|
||||
const newSortSeq =
|
||||
dragSourceIndex === 0 ? 1 : (prevSibling?.data?.sortSeq ?? 0) + 1;
|
||||
|
||||
const childNodes = treeData.filter(
|
||||
(node) => node.parent === dragSourceId && node.data,
|
||||
);
|
||||
|
||||
const treeNode: OrganizationTree = {
|
||||
...dragSource.data,
|
||||
upOgnzSn: dropTargetId === 0 ? null : (dropTargetId as number),
|
||||
sortSeq: newSortSeq,
|
||||
};
|
||||
|
||||
const result: OrganizationTree = {
|
||||
...treeNode,
|
||||
children:
|
||||
childNodes?.map((child) => ({
|
||||
...child.data,
|
||||
ognzNm: child.data?.ognzNm ?? "",
|
||||
upOgnzSn: child.data?.upOgnzSn === 0 ? null : (dragSourceId as number),
|
||||
sortSeq: child.data?.sortSeq ?? 1,
|
||||
})) ?? [],
|
||||
};
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const handleDropNode =
|
||||
(callback: (newTree: OrganizationTree) => void) =>
|
||||
(
|
||||
newTree: NodeModel<OrganizationTree>[],
|
||||
options: DropOptions<OrganizationTree>,
|
||||
) => {
|
||||
const newTreeData = generateNewOrganizationTreeData(newTree, options);
|
||||
if (!newTreeData) return;
|
||||
callback(newTreeData);
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ export const organizationFormSchema = organizationSchema.omit({
|
||||
export type Organization = z.infer<typeof organizationSchema>;
|
||||
export type OrganizationFormData = z.infer<typeof organizationFormSchema>;
|
||||
export type OrganizationTree = Organization & {
|
||||
children: OrganizationTree[];
|
||||
children?: OrganizationTree[];
|
||||
};
|
||||
|
||||
export interface OrganizationService {
|
||||
|
||||
@@ -10,8 +10,9 @@ import { Button } from "@common/components/ui";
|
||||
import { DndTree, EditableNode } from "@/widgets/dnd-tree";
|
||||
import {
|
||||
OrganizationApi,
|
||||
generateOrganizationTreeData,
|
||||
organizationFormSchema,
|
||||
generateOrganizationTreeData,
|
||||
handleDropNode,
|
||||
type OrganizationFormData,
|
||||
type OrganizationTree,
|
||||
} from "@/entities/organization";
|
||||
@@ -198,7 +199,7 @@ function OrganizationPage() {
|
||||
/>
|
||||
)}
|
||||
handleSelectNode={handleNodeSelect}
|
||||
handleDropNode={() => {}}
|
||||
handleDropNode={handleDropNode(console.log)}
|
||||
updateNodeName={async (id, name) => {
|
||||
await updateOrganizationName({ ognzSn: id as number, name });
|
||||
}}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { cn } from "@common/components/lib";
|
||||
import { EditableNode } from "./editable-node";
|
||||
|
||||
interface TreeData extends Record<string, unknown> {
|
||||
children: unknown[];
|
||||
children?: unknown[];
|
||||
}
|
||||
|
||||
type CustomNodeProps<T extends TreeData> = {
|
||||
@@ -72,7 +72,7 @@ function CustomNode<T extends TreeData>({
|
||||
) : (
|
||||
<>
|
||||
<div className="flex items-center" onClick={handleSelect}>
|
||||
{data && data.children.length > 0 && (
|
||||
{data && data.children && data.children.length > 0 && (
|
||||
<i
|
||||
className={cn(
|
||||
"diveicon di-arrow-forward mr-2 text-base text-label",
|
||||
|
||||
@@ -15,7 +15,7 @@ import { cn } from "@common/components/lib";
|
||||
import { CustomNode } from "./custom-node";
|
||||
|
||||
interface TreeData extends Record<string, unknown> {
|
||||
children: unknown[];
|
||||
children?: unknown[];
|
||||
}
|
||||
|
||||
type EditableNodeProps = { depth: number };
|
||||
|
||||
Reference in New Issue
Block a user