Skip to content

Instantly share code, notes, and snippets.

@zourdyzou
Created May 25, 2023 09:48
Show Gist options
  • Select an option

  • Save zourdyzou/af59918fb9afb408272bcdf0a6193dcb to your computer and use it in GitHub Desktop.

Select an option

Save zourdyzou/af59918fb9afb408272bcdf0a6193dcb to your computer and use it in GitHub Desktop.
import { useState } from 'react';
export type WBSProjectCRUD = {
id?: string | null;
name: string;
reference: string;
parentReference?: string | null;
parentWbsId?: string | null;
projectId?: string | null;
wbsLevel: number;
wbsOrder: number;
expand: boolean;
editMode: boolean;
tempId: string;
allChildren: WBSProjectCRUD[];
};
export type UseWBSProject = {
projects: WBSProjectCRUD[];
addProject: (level: number) => void;
updateProject: (
id: string | null,
tempId: string | null,
name: string,
reference: string,
) => void;
deleteProject: (id: string, tempId: string) => void;
toggleExpand: (id: string, tempId: string) => void;
};
export function findNodeById<
A extends { id: string; tempId: string | any; allChildren: A[] },
>(node: A, id: string | null, tempId: string | null): A | null {
if ((node.id && node.id === id) || (node.tempId && node.tempId === tempId)) {
return node;
}
const foundNode = node.allChildren?.find((child) =>
findNodeById(child, id, tempId),
);
return foundNode || null;
}
export const useWBSProject = (
initialProjects: WBSProjectCRUD[] = [],
): UseWBSProject => {
const [projects, setProjects] = useState<WBSProjectCRUD[]>(initialProjects);
const addProject = (level: number) => {
const newProject: WBSProjectCRUD = {
wbsOrder: 0,
id: null,
tempId: Date.now().toString(), // temporary ID
name: ``,
reference: ``,
wbsLevel: level,
expand: false,
editMode: true,
allChildren: [],
};
if (level === 0) {
setProjects([...projects, newProject]);
} else {
const addNode = (node: WBSProjectCRUD, level: number): WBSProjectCRUD => {
if (node.wbsLevel === level - 1) {
return { ...node, allChildren: [...node.allChildren, newProject] };
} else {
node.allChildren = node.allChildren.map((child) =>
addNode(child, level),
);
return node;
}
};
setProjects(projects.map((project) => addNode(project, level)));
}
};
const updateProject = (
id: string | null,
tempId: string | null,
name: string,
reference: string,
) => {
const updateNode = (node: WBSProjectCRUD): WBSProjectCRUD => {
if (node.id === id || node.tempId === tempId) {
return { ...node, name, reference, editMode: false };
} else {
node.allChildren = node.allChildren.map((child) => updateNode(child));
return node;
}
};
setProjects(projects.map((project) => updateNode(project)));
};
const deleteProject = (id: string, tempId: string) => {
const deleteNode = (node: WBSProjectCRUD): WBSProjectCRUD | null => {
if (
(node.id && node.id === id) ||
(node.tempId && node.tempId === tempId)
) {
return null;
} else {
node.allChildren = node.allChildren
.map((child) => deleteNode(child))
.filter(Boolean) as WBSProjectCRUD[];
return node;
}
};
setProjects(
projects
.map((project) => deleteNode(project))
.filter(Boolean) as WBSProjectCRUD[],
);
};
const toggleExpand = (id: string, tempId: string) => {
const toggleNode = (node: WBSProjectCRUD): WBSProjectCRUD => {
if (
(node.id && node.id === id) ||
(node.tempId && node.tempId === tempId)
) {
return { ...node, expand: !node.expand };
} else {
node.allChildren = node.allChildren.map((child) => toggleNode(child));
return node;
}
};
setProjects(projects.map((project) => toggleNode(project)));
};
return {
projects,
addProject,
updateProject,
deleteProject,
toggleExpand,
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment