diff --git a/public/index.html b/public/index.html index b67066c..18f5986 100644 --- a/public/index.html +++ b/public/index.html @@ -4,8 +4,14 @@ Hangman Lab +
+ + \ No newline at end of file diff --git a/src/components/Navigations/PathNode.css b/src/components/Navigations/PathNode.css index db8f2b3..d3bcc8e 100644 --- a/src/components/Navigations/PathNode.css +++ b/src/components/Navigations/PathNode.css @@ -35,3 +35,15 @@ font-size: 0.9rem; margin-left: 1rem; } +.actions { + display: flex; + justify-content: flex-end; + margin-left: auto; +} + +.path-node-header { + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; +} \ No newline at end of file diff --git a/src/components/Navigations/PathNode.js b/src/components/Navigations/PathNode.js index 37abad5..30e5806 100644 --- a/src/components/Navigations/PathNode.js +++ b/src/components/Navigations/PathNode.js @@ -3,18 +3,28 @@ import { Link } from "react-router-dom"; import PermissionGuard from "../PermissionGuard"; import config from "../../config"; import "./PathNode.css"; -import {fetch_} from "../../utils/requestUtils"; +import { fetch_ } from "../../utils/requestUtils"; -const PathNode = ({ path, isRoot = false }) => { +const PathNode = ({ path, isRoot = false, onDelete, onSave }) => { const [children, setChildren] = useState([]); const [markdowns, setMarkdowns] = useState([]); const [isExpanded, setIsExpanded] = useState(isRoot); // Root is always expanded const [loading, setLoading] = useState(false); - const [isEditing, setIsEditing] = useState(false); // Track if editing - const [editData, setEditData] = useState({ - name: path.name, - parent_id: path.parent_id, - }); + const [isEditing, setIsEditing] = useState(false); + const [newName, setNewName] = useState(path.name); + + const handleSave = () => { + if (onSave) { + onSave(path.id, newName); + setIsEditing(false); + } else { + console.error("onSave is not defined"); + } + }; + + const handleEdit = () => { + setIsEditing(true); + }; const toggleExpand = () => { if (isRoot || isExpanded) { @@ -28,7 +38,7 @@ const PathNode = ({ path, isRoot = false }) => { setLoading(true); fetch_(`${config.BACKEND_HOST}/api/path/parent/${path.id}`, {}, { use_cache: true, - use_token: false + use_token: false, }) .then((childPaths) => { setChildren(childPaths); @@ -42,180 +52,85 @@ const PathNode = ({ path, isRoot = false }) => { } }; - const handleDelete = () => { - if (window.confirm(`Are you sure you want to delete ${path.name}?`)) { - fetch_(`${config.BACKEND_HOST}/api/path/${path.id}`, { - method: "DELETE" - }, { - use_cache: false, - use_token: true - }) - .then((response) => { - if (response.ok) { - alert("Path deleted successfully!"); - setChildren([]); - setMarkdowns([]); - } else { - response.json().then((data) => { - alert(data.error || "Failed to delete path."); - }); - } - }) - .catch((error) => console.error(error)); - } - }; - - const handleEdit = () => { - setIsEditing(true); - }; - - const handleEditSubmit = (e) => { - e.preventDefault(); - fetch_(`${config.BACKEND_HOST}/api/path/${path.id}`, { - method: "PUT", - body: JSON.stringify(editData), - },{ - use_cache: false, - use_token: true - }) - .then((response) => { - if (response.ok) { - alert("Path updated successfully!"); - path.name = editData.name; - path.parent_id = editData.parent_id; - setIsEditing(false); - } else { - response.json().then((data) => { - alert(data.error || "Failed to update path."); - }); - } - }) - .catch((error) => console.error(error)); - }; - - const handleEditCancel = () => { - setEditData({ name: path.name, parent_id: path.parent_id }); - setIsEditing(false); - }; - return (
  • -
    - - {isExpanded && !isRoot ? "▼ " : isRoot ? "" : "▶ "} - {path.name} - +
    + {isEditing ? ( + +
    + setNewName(e.target.value)} + /> +
    + + ) : ( + {path.name} + )} - {/* Admin controls */} - - - - +
    + {isEditing ? ( +

    + +

    + ) : ( +

    + +

    + )} +

    + +

    +
    {isExpanded && ( )} - - {/* Edit Popup */} - {isEditing && ( -
    -
    -
    -

    Edit Path

    -
    - -
    - - setEditData({ - ...editData, - name: e.target.value, - }) - } - required - /> -
    -
    -
    - -
    - - setEditData({ - ...editData, - parent_id: Number( - e.target.value - ), - }) - } - required - /> -
    -
    -
    - - -
    -
    -
    -
    - )}
  • ); }; diff --git a/src/components/Navigations/SideNavigation.js b/src/components/Navigations/SideNavigation.js index f1b8080..4e4c2fe 100644 --- a/src/components/Navigations/SideNavigation.js +++ b/src/components/Navigations/SideNavigation.js @@ -3,14 +3,47 @@ import PermissionGuard from "../PermissionGuard"; import PathNode from "./PathNode"; import config from "../../config"; import "./SideNavigation.css"; -import {fetch_} from "../../utils/requestUtils"; +import { fetch_ } from "../../utils/requestUtils"; + const SideNavigation = () => { const [paths, setPaths] = useState([]); const [loading, setLoading] = useState(false); + const handleDelete = (id) => { + fetch_(`${config.BACKEND_HOST}/api/path/${id}`, { + method: "DELETE", + },{ + use_cache: false, + use_token: true, + }).then(() => { + setPaths((prevPaths) => prevPaths.filter((path) => path.id !== id)); + }) + .catch((error) => console.error(error)); + }; + + const handleSave = (id, newName) => { + fetch_(`${config.BACKEND_HOST}/api/path/${id}`, { + method: "PUT", + body: JSON.stringify({ name: newName, parent_id: 1 }), // Update with actual parent_id + }, { + use_cache: false, + use_token: true, + }).then(() => { + setPaths((prevPaths) => + prevPaths.map((path) => + path.id === id ? { ...path, name: newName } : path + ) + ); + }) + .catch((error) => console.error("Failed to update path", error)); + }; + useEffect(() => { setLoading(true); - fetch_(`${config.BACKEND_HOST}/api/path/`, {},{ use_cache: true, use_token:false }) + fetch_(`${config.BACKEND_HOST}/api/path/`, {},{ + use_cache: true, + use_token: false, + }) .then((data) => { setPaths(data); }) @@ -36,6 +69,8 @@ const SideNavigation = () => { key={path.id} path={path} isRoot={false} + onSave={handleSave} // Ensure this is passed + onDelete={handleDelete} /> ))}