Dwinzo_dev/app/src/components/ui/menu/menu.tsx

276 lines
7.6 KiB
TypeScript

import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { ArrowIcon } from "../../icons/ExportCommonIcons";
import { toggleTheme } from "../../../utils/theme";
import useVersionHistoryStore, {
useShortcutStore,
useVersionStore,
} from "../../../store/builder/store";
import { useSubModuleStore } from "../../../store/useModuleStore";
import { generateUniqueId } from "../../../functions/generateUniqueId";
interface MenuBarProps {
setOpenMenu: (isOpen: boolean) => void;
}
interface MenuItem {
label: string;
onClick?: string;
shortcut?: string;
submenu?: MenuItem[];
action?: () => void;
}
const MenuBar: React.FC<MenuBarProps> = ({ setOpenMenu }) => {
const userName = localStorage.getItem("userName") ?? "Anonymous";
const navigate = useNavigate();
const [activeMenu, setActiveMenu] = useState<string | null>(null);
const [activeSubMenu, setActiveSubMenu] = useState<string | null>(null);
const [selectedItems, setSelectedItems] = useState<Record<string, boolean>>(
{}
);
const { setVersionHistory } = useVersionHistoryStore();
const { setSubModule } = useSubModuleStore();
const { showShortcuts, setShowShortcuts } = useShortcutStore();
const savedTheme = localStorage.getItem("theme") ?? "light";
const toggleSelection = (itemName: string) => {
setSelectedItems((prev) => ({
...prev,
[itemName]: !prev[itemName],
}));
};
// functions
const handleThemeChange = () => {
toggleTheme();
window.location.reload();
};
const handleLogout = () => {
localStorage.clear();
navigate("/");
};
function handleShotcutsHelper() {
setShowShortcuts(!showShortcuts);
}
const menus: Record<string, MenuItem[]> = {
File: [
{ label: "New File", shortcut: "Ctrl + N" },
{ label: "Open Local File", shortcut: "Ctrl + O" },
{
label: "Save Version",
action: () => {
const versionStore = useVersionStore.getState();
const versionCount = versionStore.versions.length;
const newVersion = {
id: generateUniqueId(),
versionLabel: `v${versionCount + 1}.0`,
timestamp: `${new Date().toLocaleTimeString("en-US", {
hour: "numeric",
minute: "2-digit",
hour12: true,
})} ${new Date().toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "2-digit",
})}`,
savedBy: userName,
};
console.log("newVersion: ", newVersion);
versionStore.addVersion(newVersion);
},
},
{ label: "Make a Copy" },
{ label: "Share" },
{ label: "Rename" },
{ label: "Import" },
{ label: "Close File" },
],
Edit: [
{ label: "Undo", shortcut: "Ctrl + Z" },
{ label: "Redo", shortcut: "Ctrl + Shift + Z" },
{ label: "Undo History" },
{ label: "Redo History" },
{ label: "Find", shortcut: "Ctrl + F" },
{ label: "Delete" },
{ label: "Select by..." },
{ label: "Keymap" },
],
View: [
{ label: "Grid" },
{
label: "Gizmo",
submenu: [
{ label: "Visibility" },
{ label: "Cube view" },
{ label: "Sphere view" },
],
},
{ label: "Zoom" },
{ label: "Full Screen", shortcut: "F11" },
],
Help: [
{
label: "Shortcuts",
shortcut: "Ctrl + Shift + ?",
action: handleShotcutsHelper,
},
{ label: "Manual" },
{ label: "Video Tutorials" },
{ label: "Report a bug" },
],
};
// render menu item and sub menu item component
const renderMenuItem = ({ label, shortcut, action }: MenuItem) => (
<button
id={label}
className="menu-item-container"
key={label}
onClick={() => {
toggleSelection(label);
action && action();
}}
>
<div className="menu-item">
<span>
{selectedItems[label] ? "✓ " : ""}
{label}
</span>
{shortcut && (
<div className="menu-item-right">
<span className="shortcut">{shortcut}</span>
</div>
)}
</div>
</button>
);
const renderSubMenu = (submenu: MenuItem[], parentLabel: string) => (
<div className="submenu">
{submenu.map((item) => (
<button
id={item.label}
key={item.label}
className="submenu-item"
onClick={() => {
console.log("hi", item.onClick);
toggleSelection(item.label);
}}
>
<span>
{selectedItems[item.label] ? "✓ " : ""}
{item.label}
</span>
</button>
))}
</div>
);
return (
<div className="menu-bar" onPointerLeave={() => setOpenMenu(false)}>
<div className="menu-buttons">
{Object.entries(menus).map(([menu, items]) => (
<button
id={menu}
key={menu}
className="menu-button-container"
onMouseEnter={() => setActiveMenu(menu)}
onMouseLeave={() => {
setActiveMenu(null);
setActiveSubMenu(null);
}}
>
<div className="menu-button">
{menu}
<span className="dropdown-icon">
<ArrowIcon />
</span>
</div>
{activeMenu === menu && (
<div className="dropdown-menu">
{items.map((item) =>
item.submenu ? (
<button
id={item.label}
key={item.label}
className="menu-item-container"
onMouseEnter={() => setActiveSubMenu(item.label)}
onMouseLeave={() => setActiveSubMenu(null)}
>
<div className="menu-item">
<span>{item.label}</span>
<span className="dropdown-icon">
<ArrowIcon />
</span>
</div>
{activeSubMenu === item.label &&
renderSubMenu(item.submenu, item.label)}
</button>
) : (
renderMenuItem(item)
)
)}
</div>
)}
</button>
))}
{/* Version History */}
<button
id="version-history"
className="menu-button-container"
onMouseEnter={() => setActiveMenu("Version history")}
onMouseLeave={() => {
setActiveMenu(null);
setActiveSubMenu(null);
}}
onClick={() => {
setVersionHistory(true);
setSubModule("properties");
}}
>
<div className="menu-button">Version history</div>
</button>
{/* Theme */}
<button
id="theme-btn"
className="menu-button-container"
onMouseEnter={() => setActiveMenu("Theme")}
onMouseLeave={() => {
setActiveMenu(null);
setActiveSubMenu(null);
}}
onClick={handleThemeChange}
>
<div className="menu-button">
Theme <div className="value">{savedTheme}</div>
</div>
</button>
{/* Log out */}
<button
id="logout"
className="menu-button-container"
onClick={handleLogout}
>
<div className="menu-button">Log out</div>
</button>
</div>
</div>
);
};
export default MenuBar;