diff --git a/app/.env b/app/.env index c50d174..9116020 100644 --- a/app/.env +++ b/app/.env @@ -2,10 +2,13 @@ PORT=8200 # Base URL for the server socket API, used for real-time communication (e.g., WebSockets). -REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000 +REACT_APP_SERVER_SOCKET_API_BASE_URL=192.168.0.110:8000 +# REACT_APP_SERVER_SOCKET_API_BASE_URL=185.100.212.76:8000 # Base URL for the server REST API, used for HTTP requests to the backend server. -REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 +REACT_APP_SERVER_REST_API_BASE_URL=192.168.0.110:5000 +# REACT_APP_SERVER_REST_API_BASE_URL=192.168.0.102:5000 +# REACT_APP_SERVER_REST_API_BASE_URL=185.100.212.76:5000 # Base URL for the server marketplace, used for market place model blob. REACT_APP_SERVER_MARKETPLACE_URL=185.100.212.76:50011 diff --git a/app/src/app.tsx b/app/src/app.tsx index 0b6fd3e..2158dad 100644 --- a/app/src/app.tsx +++ b/app/src/app.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import Dashboard from "./pages/Dashboard"; import Project from "./pages/Project"; @@ -7,13 +7,24 @@ import "./styles/main.scss"; import { LoggerProvider } from "./components/ui/log/LoggerContext"; const App: React.FC = () => { + useEffect(() => { + const handlePopState = () => { + window.location.reload(); + }; + + window.addEventListener("popstate", handlePopState); + + return () => { + window.removeEventListener("popstate", handlePopState); + }; + }, []); return ( } /> } /> - } /> + } /> diff --git a/app/src/assets/image/darkThemeProject.png b/app/src/assets/image/darkThemeProject.png new file mode 100644 index 0000000..3189860 Binary files /dev/null and b/app/src/assets/image/darkThemeProject.png differ diff --git a/app/src/assets/image/lightThemeProject.png b/app/src/assets/image/lightThemeProject.png new file mode 100644 index 0000000..a5096ab Binary files /dev/null and b/app/src/assets/image/lightThemeProject.png differ diff --git a/app/src/components/layout/Dashboard/DashboardCard.tsx b/app/src/components/layout/Dashboard/DashboardCard.tsx index d58bfb6..b6e818c 100644 --- a/app/src/components/layout/Dashboard/DashboardCard.tsx +++ b/app/src/components/layout/Dashboard/DashboardCard.tsx @@ -1,25 +1,78 @@ import React from "react"; import { KebabIcon } from "../../icons/ExportCommonIcons"; -import img from "../../../assets/image/image.png" +import img from "../../../assets/image/image.png"; +import { useNavigate } from "react-router-dom"; +import { useProjectName } from "../../../store/builder/store"; +import { viewProject } from "../../../services/dashboard/viewProject"; +import { getUserData } from "./functions/getUserData"; + +interface DashBoardCardProps { + projectName: string; + thumbnail: any; + projectId: string; + handleDeleteProject?: (projectId: string) => Promise; + handleRestoreProject?: (projectId: string) => Promise; +} + +const DashboardCard: React.FC = ({ + projectName, + handleDeleteProject, + thumbnail, + projectId, + handleRestoreProject, +}) => { + let navigate = useNavigate(); + const { setProjectName } = useProjectName(); + const { userId, organization, userName } = getUserData(); + + const handleKebabIconClick = async () => { + try { + if (handleRestoreProject) { + await handleRestoreProject(projectId); + } else if (handleDeleteProject) { + await handleDeleteProject(projectId); + } + } catch { } + }; + + const navigateToProject = async () => { + try { + const viewedProject = await viewProject(organization, projectId, userId); + console.log("Saved viewwdProject:", viewedProject); + } catch (error) { + console.error("Error deleting project:", error); + } + + setProjectName(projectName); + navigate(`/${projectId}`); + }; -const DashboardCard:React.FC = () => { return ( -
+
- + {thumbnail ? : }
-
Untitled
+
{projectName}
24-12-2025
-
V
- +
+ {userName ? userName.charAt(0).toUpperCase() : "Anonymous"} +
+
{ + e.stopPropagation(); + handleKebabIconClick(); + }} + > + +
); }; -export default DashboardCard; +export default DashboardCard; \ No newline at end of file diff --git a/app/src/components/layout/Dashboard/DashboardHome.tsx b/app/src/components/layout/Dashboard/DashboardHome.tsx index 38e7bad..98b8a5c 100644 --- a/app/src/components/layout/Dashboard/DashboardHome.tsx +++ b/app/src/components/layout/Dashboard/DashboardHome.tsx @@ -1,21 +1,137 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import DashboardCard from "./DashboardCard"; import DashboardNavBar from "./DashboardNavBar"; import MarketPlaceBanner from "./MarketPlaceBanner"; +import { recentlyViewed } from "../../../services/dashboard/recentlyViewed"; +import { getUserData } from "./functions/getUserData"; +import { searchProject } from "../../../services/dashboard/searchProjects"; +import { deleteProject } from "../../../services/dashboard/deleteProject"; +import { useSocketStore } from "../../../store/builder/store"; + +interface Project { + _id: string; + projectName: string; + thumbnail: string; + createdBy: string; + projectUuid?: string; +} + +interface RecentProjectsData { + [key: string]: Project[]; +} const DashboardHome: React.FC = () => { + const [recentProjects, setRecentProjects] = useState({}); + const [isSearchActive, setIsSearchActive] = useState(false); + const { userId, organization } = getUserData(); + const { dashBoardSocket } = useSocketStore(); + + const fetchRecentProjects = async () => { + try { + const projects = await recentlyViewed(organization, userId); + + if (JSON.stringify(projects) !== JSON.stringify(recentProjects)) { + setRecentProjects(projects); + } + } catch (error) { + console.error("Error fetching recent projects:", error); + } + }; + + const handleRecentProjectSearch = async (inputValue: string) => { + if (!inputValue.trim()) { + setIsSearchActive(false); + return; + } + const filterRecentProcess = await searchProject(organization, userId, inputValue); + setIsSearchActive(true); + setRecentProjects(filterRecentProcess.message ? {} : filterRecentProcess); + }; + + const handleDeleteProject = async (projectId: any) => { + try { + //API for delete project + + // const deletedProject = await deleteProject( + // projectId, + // userId, + // Organization + // ); + + //socket for delete Project + const deleteProject = { + projectId, + organization, + userId, + }; + + if (dashBoardSocket) { + const handleResponse = (data: any) => { + console.log("Project add response:", data); + dashBoardSocket.off("v1-project:response:delete", handleResponse); + }; + + dashBoardSocket.on("v1-project:response:delete", handleResponse); + dashBoardSocket.emit("v1:project:delete", deleteProject); + } + + setRecentProjects((prevDiscardedProjects: RecentProjectsData) => { + if (!Array.isArray(prevDiscardedProjects?.RecentlyViewed)) { + return prevDiscardedProjects; + } + const updatedProjectDatas = prevDiscardedProjects.RecentlyViewed.filter( + (project) => project._id !== projectId + ); + return { + ...prevDiscardedProjects, + RecentlyViewed: updatedProjectDatas, + }; + }); + setIsSearchActive(false); + } catch (error) { + console.error("Error deleting project:", error); + } + }; + + const renderProjects = () => { + const projectList = recentProjects[Object.keys(recentProjects)[0]]; + + if (!projectList?.length) { + return
No recent projects found
; + } + + return projectList.map((project) => ( + + )); + }; + + useEffect(() => { + if (!isSearchActive) { + fetchRecentProjects(); + } + }, [isSearchActive]); + return (
- + + +
-
Recents
-
- -
+

Recent Projects

+
{renderProjects()}
); }; -export default DashboardHome; +export default DashboardHome; \ No newline at end of file diff --git a/app/src/components/layout/Dashboard/DashboardNavBar.tsx b/app/src/components/layout/Dashboard/DashboardNavBar.tsx index 3da1a61..ab1590f 100644 --- a/app/src/components/layout/Dashboard/DashboardNavBar.tsx +++ b/app/src/components/layout/Dashboard/DashboardNavBar.tsx @@ -4,18 +4,40 @@ import Search from "../../ui/inputs/Search"; interface DashboardNavBarProps { page: React.ReactNode; + handleProjectsSearch?: (inputValue: string) => Promise; + handleTrashSearch?: (inputValue: string) => Promise; + handleRecentProjectSearch?: (inputValue: string) => Promise; } -const DashboardNavBar: React.FC = ({ page }) => { +const DashboardNavBar: React.FC = ({ + page, + handleProjectsSearch, + handleTrashSearch, + handleRecentProjectSearch, +}) => { + const handleSearch = async (inputValue: string) => { + try { + if (handleProjectsSearch) { + await handleProjectsSearch(inputValue); + } else if (handleTrashSearch) { + await handleTrashSearch(inputValue); + } else if (handleRecentProjectSearch) { + await handleRecentProjectSearch(inputValue); + } + } catch (error) { + console.error("Search failed:", error); + } + }; + return (
{page}
Market Place
- {}} /> +
); }; -export default DashboardNavBar; +export default DashboardNavBar; \ No newline at end of file diff --git a/app/src/components/layout/Dashboard/DashboardProjects.tsx b/app/src/components/layout/Dashboard/DashboardProjects.tsx new file mode 100644 index 0000000..8df8216 --- /dev/null +++ b/app/src/components/layout/Dashboard/DashboardProjects.tsx @@ -0,0 +1,155 @@ +import React, { useEffect, useState } from 'react'; +import DashboardNavBar from './DashboardNavBar'; +import DashboardCard from './DashboardCard'; +import { getAllProjects } from '../../../services/dashboard/getAllProjects'; +import { getUserData } from './functions/getUserData'; +import { searchProject } from '../../../services/dashboard/searchProjects'; +import { deleteProject } from '../../../services/dashboard/deleteProject'; +import { useSocketStore } from '../../../store/builder/store'; + +interface Project { + _id: string; + projectName: string; + thumbnail: string; + createdBy: string; + projectUuid?: string; +} + +interface WorkspaceProjects { + [key: string]: Project[]; +} + +const DashboardProjects: React.FC = () => { + const [workspaceProjects, setWorkspaceProjects] = useState({}); + const [isSearchActive, setIsSearchActive] = useState(false); + const [activeFolder, setActiveFolder] = useState("myProjects"); + const { dashBoardSocket } = useSocketStore(); + const { userId, organization } = getUserData(); + + const fetchAllProjects = async () => { + try { + const projects = await getAllProjects(userId, organization); + + if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) { + setWorkspaceProjects(projects); + } + } catch (error) { + console.error("Error fetching projects:", error); + } + }; + const handleProjectsSearch = async ( + inputValue: string + ) => { + if (!inputValue.trim()) { + setIsSearchActive(false); + return; + } + if (!setWorkspaceProjects || !setIsSearchActive) return; + + const searchedProject = await searchProject(organization, userId, inputValue); + setIsSearchActive(true); + setWorkspaceProjects(searchedProject.message ? {} : searchedProject); + }; + const handleDeleteProject = async (projectId: any) => { + try { + + const Organization = organization + // const deletedProject = await deleteProject( + // projectId, + // userId, + // Organization + // ); + const deleteProject = { + projectId, + organization: organization, + userId + } + if (dashBoardSocket) { + const handleResponse = (data: any) => { + console.log('Project add response:', data); + dashBoardSocket.off("v1-project:response:delete", handleResponse); // Clean up + }; + + dashBoardSocket.on("v1-project:response:delete", handleResponse); + + dashBoardSocket.emit("v1:project:delete", deleteProject); + } else { + console.error("Socket is not connected."); + } + setWorkspaceProjects((prevDiscardedProjects: WorkspaceProjects) => { + if (!Array.isArray(prevDiscardedProjects?.Projects)) { + return prevDiscardedProjects; + } + const updatedProjectDatas = prevDiscardedProjects.Projects.filter( + (project) => project._id !== projectId + ); + return { + ...prevDiscardedProjects, + Projects: updatedProjectDatas + }; + }); + setIsSearchActive(false) + + } catch (error) { + console.error('Error deleting project:', error); + } + }; + + + const renderProjects = () => { + if (activeFolder !== "myProjects") return null; + + const projectList = workspaceProjects[Object.keys(workspaceProjects)[0]]; + + if (!projectList?.length) { + return
No projects found
; + } + + return projectList.map((project) => ( + + )); + }; + + useEffect(() => { + if (!isSearchActive) { + fetchAllProjects(); + } + }, [isSearchActive]); + + return ( +
+ + +
+
+
setActiveFolder("myProjects")} + > + My Projects +
+
setActiveFolder("shared")} + > + Shared with me +
+
+
+ {renderProjects()} +
+
+
+ ); +}; + +export default DashboardProjects; \ No newline at end of file diff --git a/app/src/components/layout/Dashboard/DashboardTrash.tsx b/app/src/components/layout/Dashboard/DashboardTrash.tsx new file mode 100644 index 0000000..b66a05c --- /dev/null +++ b/app/src/components/layout/Dashboard/DashboardTrash.tsx @@ -0,0 +1,122 @@ +import React, { useEffect, useState } from 'react'; +import { getTrash } from '../../../services/dashboard/getTrash'; +import DashboardCard from './DashboardCard'; +import DashboardNavBar from './DashboardNavBar'; +import { getUserData } from './functions/getUserData'; +import { trashSearchProject } from '../../../services/dashboard/trashSearchProject'; +import { restoreTrash } from '../../../services/dashboard/restoreTrash'; + +interface Project { + _id: string; + projectName: string; + thumbnail: string; + createdBy: string; + projectUuid?: string; +} + +interface DiscardedProjects { + [key: string]: Project[]; +} + +const DashboardTrash: React.FC = () => { + const [discardedProjects, setDiscardedProjects] = useState({}); + console.log('discardedProjects: ', discardedProjects); + const [isSearchActive, setIsSearchActive] = useState(false); + const { userId, organization } = getUserData(); + + const fetchTrashProjects = async () => { + try { + const projects = await getTrash(organization); + console.log('organization: ', organization); + console.log('trashedprojects: ', projects); + + if (JSON.stringify(projects) !== JSON.stringify(discardedProjects)) { + setDiscardedProjects(projects); + } + } catch (error) { + console.error('Error fetching trash projects:', error); + } + }; + const handleTrashSearch = async ( + inputValue: string + ) => { + if (!inputValue.trim()) { + setIsSearchActive(false); + return; + } + if (!setDiscardedProjects || !setIsSearchActive) return; + + const filterTrashedProcess = await trashSearchProject(organization, userId, inputValue); + setIsSearchActive(true); + setDiscardedProjects(filterTrashedProcess.message ? {} : filterTrashedProcess); + }; + const handleRestoreProject = async (projectId: any) => { + try { + const Organization = organization; + const restoreProject = await restoreTrash( + Organization, + projectId + ); + + setDiscardedProjects((prevDiscardedProjects: DiscardedProjects) => { + // Check if TrashDatas exists and is an array + if (!Array.isArray(prevDiscardedProjects?.TrashDatas)) { + console.error('TrashDatas is not an array', prevDiscardedProjects); + return prevDiscardedProjects; + } + const updatedTrashDatas = prevDiscardedProjects.TrashDatas.filter( + (project) => project._id !== projectId + ); + return { + ...prevDiscardedProjects, + TrashDatas: updatedTrashDatas + }; + }); + setIsSearchActive(false) + } catch (error) { + console.error('Error deleting project:', error); + } + }; + const renderTrashProjects = () => { + const projectList = discardedProjects[Object.keys(discardedProjects)[0]]; + + if (!projectList?.length) { + return
No deleted projects found
; + } + + return projectList.map((project) => ( + + )); + }; + + useEffect(() => { + console.log('isSearchActive:trash ', isSearchActive); + if (!isSearchActive) { + fetchTrashProjects(); + } + }, [isSearchActive]); + + return ( +
+ + +
+
+
+ {renderTrashProjects()} +
+
+
+ ); +}; + +export default DashboardTrash; \ No newline at end of file diff --git a/app/src/components/layout/Dashboard/DashboardTutorial.tsx b/app/src/components/layout/Dashboard/DashboardTutorial.tsx new file mode 100644 index 0000000..5e11ab8 --- /dev/null +++ b/app/src/components/layout/Dashboard/DashboardTutorial.tsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from 'react'; +import { projectTutorial } from '../../../services/dashboard/projectTutorial'; +import DashboardNavBar from './DashboardNavBar'; +import DashboardCard from './DashboardCard'; +interface Project { + _id: string; + projectName: string; + thumbnail: string; + createdBy: string; + projectUuid?: string; +} + +interface DiscardedProjects { + [key: string]: Project[]; +} + +const DashboardTutorial = () => { + const [tutorialProject, setTutorialProject] = useState({}) + const handleIcon = async () => { + try { + let tutorial = await projectTutorial() + setTutorialProject(tutorial) + } catch { + + } + } + useEffect(() => { + handleIcon() + }, []) + const renderTrashProjects = () => { + const projectList = tutorialProject[Object.keys(tutorialProject)[0]]; + + if (!projectList?.length) { + return
No deleted projects found
; + } + + return projectList.map((tutorials: any) => ( + + )); + }; + return ( +
+ + +
+
+
+ {renderTrashProjects()} +
+
+
+ ); +} + +export default DashboardTutorial; diff --git a/app/src/components/layout/Dashboard/SidePannel.tsx b/app/src/components/layout/Dashboard/SidePannel.tsx index 5d69ffc..4298380 100644 --- a/app/src/components/layout/Dashboard/SidePannel.tsx +++ b/app/src/components/layout/Dashboard/SidePannel.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect, useState } from "react"; import { DocumentationIcon, HelpIcon, @@ -9,40 +9,98 @@ import { TutorialsIcon, } from "../../icons/DashboardIcon"; import { SettingsIcon, TrashIcon } from "../../icons/ExportCommonIcons"; +import { useNavigate } from "react-router-dom"; +import img from "../../../assets/image/image.png" +import darkThemeImage from "../../../assets/image/darkThemeProject.png" +import lightThemeImage from "../../../assets/image/lightThemeProject.png" +import { createProject } from "../../../services/dashboard/createProject"; +import { getUserData } from "./functions/getUserData"; +import { useSocketStore } from "../../../store/builder/store"; +interface SidePannelProps { + setActiveTab: React.Dispatch>; + activeTab: string +} + +const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { + const { userName, userId, organization } = getUserData(); + const navigate = useNavigate(); + const { dashBoardSocket } = useSocketStore(); + const savedTheme = localStorage.getItem("theme") ?? "light"; + function generateProjectId() { + const randomBytes = new Uint8Array(12); + crypto.getRandomValues(randomBytes); + return Array.from(randomBytes, (byte) => + byte.toString(16).padStart(2, "0")).join(""); + } + + + const handleCreateNewProject = async () => { + try { + const projectId = generateProjectId(); + navigate(`/${projectId}`); + //API for creating new Project + // const project = await createProject( + // projectId, + // userId, + // img, + // organization + // ); + // console.log('Created project: ', project); + const addProject = { + userId, + thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage, + organization: organization, + projectUuid: projectId, + }; + + if (dashBoardSocket) { + // console.log('addProject: ', addProject); + const handleResponse = (data: any) => { + console.log('Project add response:', data); + dashBoardSocket.off("v1-project:response:add", handleResponse); // Clean up + }; + dashBoardSocket.on("v1-project:response:add", handleResponse); + + dashBoardSocket.emit("v1:project:add", addProject); + } else { + console.error("Socket is not connected."); + } + } catch (error) { + console.error("Error creating project:", error); + } + }; -const SidePannel: React.FC = () => { - const userName = localStorage.getItem("userName") ?? "Anonymous"; return (
-
{userName[0]}
-
{userName}
+
{userName?.charAt(0).toUpperCase()}
+
{userName ? userName.charAt(0).toUpperCase() + userName.slice(1).toLowerCase() : "Anonymous"}
-
+ New project
+
+ New project
-
+
setActiveTab("Home")}> Home
-
+
setActiveTab("Projects")}> Projects
-
+
setActiveTab("Trash")}> Trash
-
+
setActiveTab("Tutorials")}> Tutorials
-
+
setActiveTab("Documentation")}> Documentation
@@ -52,7 +110,7 @@ const SidePannel: React.FC = () => { Settings
-
+
Log out
diff --git a/app/src/components/layout/Dashboard/functions/getUserData.ts b/app/src/components/layout/Dashboard/functions/getUserData.ts new file mode 100644 index 0000000..132dcc2 --- /dev/null +++ b/app/src/components/layout/Dashboard/functions/getUserData.ts @@ -0,0 +1,31 @@ +interface UserData { + email: string; + userId: string; + userName?: string; // Optional + organization: string; +} + +export const getUserData = (): UserData => { + const email = localStorage.getItem("email"); + const userId = localStorage.getItem("userId"); + const userName = localStorage.getItem("userName"); + + if (!email || !userId) { + throw new Error("User data not found in localStorage"); + } + + const [_, emailDomain] = email.split("@"); + + if (!emailDomain) { + throw new Error("Invalid email format"); + } + + const [organization] = emailDomain.split("."); + + return { + email: email, + userId: userId, + userName: userName ?? undefined, + organization, + }; +}; diff --git a/app/src/components/templates/LoadingPage.tsx b/app/src/components/templates/LoadingPage.tsx index a5fef18..8a5a450 100644 --- a/app/src/components/templates/LoadingPage.tsx +++ b/app/src/components/templates/LoadingPage.tsx @@ -1,6 +1,9 @@ -import React from "react"; +import React, { useEffect } from "react"; import RenderOverlay from "./Overlay"; import { LogoIconLarge } from "../icons/Logo"; +import { useProjectName } from "../../store/builder/store"; +import { useParams } from "react-router-dom"; +import { getAllProjects } from "../../services/dashboard/getAllProjects"; interface LoadingPageProps { progress: number; // Expect progress as a percentage (0-100) @@ -8,12 +11,46 @@ interface LoadingPageProps { const LoadingPage: React.FC = ({ progress }) => { const validatedProgress = Math.min(100, Math.max(0, progress)); + const { projectName, setProjectName } = useProjectName(); + const { projectId } = useParams(); + const generateThumbnail = async () => { + const email = localStorage.getItem("email"); + const userId = localStorage.getItem("userId"); + try { + if (!email || !userId) { + console.error("User data not found in localStorage"); + return; + } + const emailParts = email.split("@"); + if (emailParts.length < 2) { + console.error("Invalid email format"); + return; + } + + const domainParts = emailParts[1].split("."); + const Organization = domainParts[0]; + const projects = await getAllProjects( + userId, Organization + ); + const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id + === projectId) + + setProjectName(filterProject.projectName) + + } + catch { + + } + } + useEffect(() => { + generateThumbnail(); + }, []); return (
-
Untitled
+
{projectName}
diff --git a/app/src/components/ui/FileMenu.tsx b/app/src/components/ui/FileMenu.tsx index 4ad40c5..33c9e4c 100644 --- a/app/src/components/ui/FileMenu.tsx +++ b/app/src/components/ui/FileMenu.tsx @@ -3,10 +3,17 @@ import RenameInput from "./inputs/RenameInput"; import { ArrowIcon } from "../icons/ExportCommonIcons"; import MenuBar from "./menu/menu"; import { ProjectIcon } from "../icons/HeaderIcons"; +import { useProjectName, useSocketStore } from "../../store/builder/store"; +import { useParams } from "react-router-dom"; +import { updateProject } from "../../services/dashboard/updateProject"; +import { getAllProjects } from "../../services/dashboard/getAllProjects"; const FileMenu: React.FC = () => { const [openMenu, setOpenMenu] = useState(false); + const { projectName, setProjectName } = useProjectName(); + const { dashBoardSocket } = useSocketStore(); const containerRef = useRef(null); + const { projectId } = useParams(); let clickTimeout: NodeJS.Timeout | null = null; const handleClick = () => { @@ -31,20 +38,65 @@ const FileMenu: React.FC = () => { return () => document.removeEventListener("mousedown", handleClickOutside); }, []); - // project - const [projectName, setProjectName] = useState("Demo Project"); - // Load project name from localStorage on mount - useEffect(() => { - const savedName = localStorage.getItem("projectName"); - if (savedName) { - setProjectName(savedName); + const handleProjectRename = async (projectName: string) => { + setProjectName(projectName); + if (!projectId) return + // localStorage.setItem("projectName", newName); + try { + const email = localStorage.getItem("email"); + const userId = localStorage.getItem("userId"); + + if (!email || !userId) { + + return; + } + + const emailParts = email.split("@"); + if (emailParts.length < 2) { + + return; + } + + const domainParts = emailParts[1].split("."); + const Organization = domainParts[0]; + const projects = await getAllProjects( + userId, Organization + ); + console.log('projects: ', projects); + let projectUuid = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id + === projectId) + const updateProject = { + projectId: projectUuid, + organization: Organization, + userId, + projectName, + thumbnail: undefined + } + + if (dashBoardSocket) { + const handleResponse = (data: any) => { + console.log('Project update response:', data); + dashBoardSocket.off("v1-project:response:update", handleResponse); // Clean up + }; + + dashBoardSocket.on("v1-project:response:update", handleResponse); + + dashBoardSocket.emit("v1:project:update", updateProject); + } + + //API for projects rename + // const updatedProjectName = await updateProject( + // projectId, + // userId, + // Organization, + // undefined, + // projectName + // ); + // + } catch (error) { + } - }, []); - - const handleProjectRename = (newName: string) => { - setProjectName(newName); - localStorage.setItem("projectName", newName); }; return ( diff --git a/app/src/components/ui/inputs/Search.tsx b/app/src/components/ui/inputs/Search.tsx index fa9d28c..bc8b282 100644 --- a/app/src/components/ui/inputs/Search.tsx +++ b/app/src/components/ui/inputs/Search.tsx @@ -38,9 +38,8 @@ const Search: React.FC = ({ return (
diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 0e81cf6..f11d260 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -7,6 +7,7 @@ import Visualization from "../visualization/visualization"; import Setup from "./setup/setup"; import Simulation from "../simulation/simulation"; import Collaboration from "../collaboration/collaboration"; +import { useSocketStore } from "../../store/builder/store"; export default function Scene() { const map = useMemo( @@ -19,11 +20,13 @@ export default function Scene() { [] ); + return ( { e.preventDefault(); }} diff --git a/app/src/pages/Dashboard.tsx b/app/src/pages/Dashboard.tsx index 02ce030..39afd94 100644 --- a/app/src/pages/Dashboard.tsx +++ b/app/src/pages/Dashboard.tsx @@ -1,14 +1,36 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import SidePannel from '../components/layout/Dashboard/SidePannel'; import DashboardHome from '../components/layout/Dashboard/DashboardHome'; +import DashboardProjects from '../components/layout/Dashboard/DashboardProjects'; +import DashboardTrash from '../components/layout/Dashboard/DashboardTrash'; +import { useOrganization, useSocketStore, useUserName, useZones } from '../store/builder/store'; +import { getUserData } from '../components/layout/Dashboard/functions/getUserData'; +import DashboardTutorial from '../components/layout/Dashboard/DashboardTutorial'; + const Dashboard: React.FC = () => { + const [activeTab, setActiveTab] = useState('Home'); + const { setUserName } = useUserName(); + const { setOrganization } = useOrganization(); + const { userId, organization, email, userName } = getUserData(); + useEffect(() => { + if (email) { + useSocketStore.getState().initializeSocket(email, organization, userId); + if (organization && userName) { + setOrganization(organization); + setUserName(userName); + } + } + }, []) return (
- - + + {activeTab == 'Home' && } + {activeTab == 'Projects' && } + {activeTab == 'Trash' && } + {activeTab == 'Tutorials' && }
); }; -export default Dashboard; +export default Dashboard; \ No newline at end of file diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 6857a5c..a308e10 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useState } from "react"; import ModuleToggle from "../components/ui/ModuleToggle"; import SideBarLeft from "../components/layout/sidebarLeft/SideBarLeft"; import SideBarRight from "../components/layout/sidebarRight/SideBarRight"; @@ -14,8 +14,10 @@ import { useZones, useLoadingProgress, useWidgetSubOption, + useProjectName, + useStartSimulation, } from "../store/builder/store"; -import { useNavigate } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import { usePlayButtonStore } from "../store/usePlayButtonStore"; import MarketPlace from "../modules/market/MarketPlace"; import LoadingPage from "../components/templates/LoadingPage"; @@ -32,19 +34,59 @@ import RenderOverlay from "../components/templates/Overlay"; import LogList from "../components/ui/log/LogList"; import Footer from "../components/footer/Footer"; import SelectFloorPlan from "../components/temporary/SelectFloorPlan"; +import { getAllProjects } from "../services/dashboard/getAllProjects"; +import { viewProject } from "../services/dashboard/viewProject"; const Project: React.FC = () => { let navigate = useNavigate(); const echo = useLogger(); - const { activeModule, setActiveModule } = useModuleStore(); - const { loadingProgress } = useLoadingProgress(); + const { loadingProgress, setLoadingProgress } = useLoadingProgress(); const { setUserName } = useUserName(); const { setOrganization } = useOrganization(); const { setFloorItems } = useFloorItems(); const { setWallItems } = useWallItems(); const { setZones } = useZones(); + const { projectId } = useParams(); + const { setProjectName } = useProjectName(); + const generateThumbnail = async () => { + const email = localStorage.getItem("email"); + const userId = localStorage.getItem("userId"); + try { + if (!email || !userId) { + console.error("User data not found in localStorage"); + return; + } + + const emailParts = email.split("@"); + if (emailParts.length < 2) { + console.error("Invalid email format"); + return; + } + + const domainParts = emailParts[1].split("."); + const Organization = domainParts[0]; + const projects = await getAllProjects( + userId, Organization + ); + const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id + === projectId) + const viewedProject = await viewProject( + Organization, + filterProject._id, + userId, + ); + setProjectName(filterProject.projectName) + + } + catch { + + } + } + useEffect(() => { + generateThumbnail(); + }, []); useEffect(() => { setFloorItems([]); setWallItems([]); @@ -53,7 +95,7 @@ const Project: React.FC = () => { const email = localStorage.getItem("email"); if (email) { const Organization = email.split("@")[1].split(".")[0]; - useSocketStore.getState().initializeSocket(email, Organization); + // useSocketStore.getState().initializeSocket(email, Organization); const name = localStorage.getItem("userName"); if (Organization && name) { setOrganization(Organization); @@ -82,6 +124,7 @@ const Project: React.FC = () => { const { selectedZone } = useSelectedZoneStore(); const { setFloatingWidget } = useFloatingWidget(); + return (
{!selectedUser && ( diff --git a/app/src/pages/UserAuth.tsx b/app/src/pages/UserAuth.tsx index 8b162c6..90b8e2c 100644 --- a/app/src/pages/UserAuth.tsx +++ b/app/src/pages/UserAuth.tsx @@ -26,19 +26,23 @@ const UserAuth: React.FC = () => { e.preventDefault(); const organization = email.split("@")[1].split(".")[0]; + console.log('email, password, organization: ', email, password, organization); try { const res = await signInApi(email, password, organization); + if (res.message === "login successfull") { setError(""); setOrganization(organization); setUserName(res.name); + console.log(' res.userId: ', res.userId); localStorage.setItem("userId", res.userId); localStorage.setItem("email", res.email); localStorage.setItem("userName", res.name); if (res.isShare) { setLoadingProgress(1); - navigate("/Project"); + // navigate("/Project"); + navigate("/Dashboard"); } } else if (res.message === "User Not Found!!! Kindly signup...") { setError("Account not found"); diff --git a/app/src/services/dashboard/addedProject.ts b/app/src/services/dashboard/addedProject.ts new file mode 100644 index 0000000..e69de29 diff --git a/app/src/services/dashboard/createProject.ts b/app/src/services/dashboard/createProject.ts new file mode 100644 index 0000000..8d6fb98 --- /dev/null +++ b/app/src/services/dashboard/createProject.ts @@ -0,0 +1,38 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// let url_Backend_dwinzo = `http://192.168.0.102:5000`; +// let url_Backend_dwinzo = `http://192.168.0.110:5000`; + +export const createProject = async ( + projectUuid: string, + userId: string, + thumbnail: string, + organization: string +) => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/upsertProject`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + projectUuid, + userId, + thumbnail, + organization, + }), + }); + + if (!response.ok) { + throw new Error("Failed to add project"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/deleteProject.ts b/app/src/services/dashboard/deleteProject.ts new file mode 100644 index 0000000..b5449d9 --- /dev/null +++ b/app/src/services/dashboard/deleteProject.ts @@ -0,0 +1,35 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// let url_Backend_dwinzo = `http://192.168.0.102:5000`; + +export const deleteProject = async ( + projectId: string, + userId: string, + organization: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1//Project/archive/${projectId}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ userId, organization }), + } + ); + + if (!response.ok) { + throw new Error("Failed to clearPanel in the zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + echo.error("Failed to clean pannel"); + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/getAllProjects.ts b/app/src/services/dashboard/getAllProjects.ts new file mode 100644 index 0000000..a43aecd --- /dev/null +++ b/app/src/services/dashboard/getAllProjects.ts @@ -0,0 +1,24 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getAllProjects = async (userId: string, organization: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/Projects/${userId}/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch assets"); + } + + return await response.json(); + } catch (error: any) { + echo.error("Failed to get asset image"); + throw new Error(error.message); + } +}; diff --git a/app/src/services/dashboard/getTrash.ts b/app/src/services/dashboard/getTrash.ts new file mode 100644 index 0000000..76cd989 --- /dev/null +++ b/app/src/services/dashboard/getTrash.ts @@ -0,0 +1,28 @@ +const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// const url_Backend_dwinzo = `http://192.168.0.102:5000`; + +export const getTrash = async (organization: string) => { + console.log("Organization:", organization); + + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/Trash/Lists?organization=${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch trash data"); + } + + const data = await response.json(); + return data; + } catch (error: any) { + console.error("Failed to fetch trash data:", error); + throw new Error(error.message || "Unknown error"); + } +}; diff --git a/app/src/services/dashboard/projectTutorial.ts b/app/src/services/dashboard/projectTutorial.ts new file mode 100644 index 0000000..e27f907 --- /dev/null +++ b/app/src/services/dashboard/projectTutorial.ts @@ -0,0 +1,27 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const projectTutorial = async () => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/v1/tutorials`, { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }); + + console.log("response: ", response); + + if (!response.ok) { + throw new Error("Failed to add project"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/recentlyViewed.ts b/app/src/services/dashboard/recentlyViewed.ts new file mode 100644 index 0000000..cfefa70 --- /dev/null +++ b/app/src/services/dashboard/recentlyViewed.ts @@ -0,0 +1,24 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const recentlyViewed = async (organization: string, userId: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/RecentlyViewed/${userId}/${organization}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch project"); + } + + return await response.json(); + } catch (error: any) { + console.error("Failed to get project"); + throw new Error(error.message); + } +}; diff --git a/app/src/services/dashboard/restoreTrash.ts b/app/src/services/dashboard/restoreTrash.ts new file mode 100644 index 0000000..3e5adb2 --- /dev/null +++ b/app/src/services/dashboard/restoreTrash.ts @@ -0,0 +1,26 @@ +const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// const url_Backend_dwinzo = `http://192.168.0.102:5000`; + +export const restoreTrash = async (organization: string, projectId: string) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/restore?organization=${organization}&projectId=${projectId}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch trash data"); + } + + const data = await response.json(); + return data; + } catch (error: any) { + console.error("Failed to fetch trash data:", error); + throw new Error(error.message || "Unknown error"); + } +}; diff --git a/app/src/services/dashboard/searchProjects.ts b/app/src/services/dashboard/searchProjects.ts new file mode 100644 index 0000000..2740432 --- /dev/null +++ b/app/src/services/dashboard/searchProjects.ts @@ -0,0 +1,35 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const searchProject = async ( + organization: string, + userId: string, + searchName: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/searchProjects?organization=${organization}&userId=${userId}&searchName=${searchName}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to Search project"); + } + + console.log("response: ", response); + const result = await response.json(); + console.log("result: ", result); + + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/trashSearchProject.ts b/app/src/services/dashboard/trashSearchProject.ts new file mode 100644 index 0000000..85732b2 --- /dev/null +++ b/app/src/services/dashboard/trashSearchProject.ts @@ -0,0 +1,32 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const trashSearchProject = async ( + organization: string, + userId: string, + searchName: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/searchTrashProjects?organization=${organization}&userId=${userId}&searchName=${searchName}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to add project"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/updateProject.ts b/app/src/services/dashboard/updateProject.ts new file mode 100644 index 0000000..8a1682c --- /dev/null +++ b/app/src/services/dashboard/updateProject.ts @@ -0,0 +1,45 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; +// let url_Backend_dwinzo = `http://192.168.0.102:5000`; + +export const updateProject = async ( + projectId: string, + userId: string, + organization: string, + thumbnail?: string, + projectName?: string +) => { + const body: any = { + projectId, + userId, + organization, + }; + + if (projectName) body.projectName = projectName; + if (thumbnail) body.thumbnail = thumbnail; + + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/Project/modify`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(body), + } + ); + + if (!response.ok) { + throw new Error("Failed to clearPanel in the zone"); + } + + const result = await response.json(); + return result; + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } else { + throw new Error("An unknown error occurred"); + } + } +}; diff --git a/app/src/services/dashboard/viewProject.ts b/app/src/services/dashboard/viewProject.ts new file mode 100644 index 0000000..d2dff52 --- /dev/null +++ b/app/src/services/dashboard/viewProject.ts @@ -0,0 +1,28 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const viewProject = async ( + organization: string, + projectId: string, + userId: string +) => { + try { + const response = await fetch( + `${url_Backend_dwinzo}/api/v1/Project/view?organization=${organization}&projectId=${projectId}&userId=${userId}`, + { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + } + ); + + if (!response.ok) { + throw new Error("Failed to fetch"); + } + + return await response.json(); + } catch (error: any) { + console.error("Failed to get asset image:", error); + throw new Error(error.message); + } +}; diff --git a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts index aa9c63b..29939fb 100644 --- a/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts +++ b/app/src/services/factoryBuilder/signInSignUp/signUpApi.ts @@ -20,6 +20,7 @@ export const signUpApi = async ( } const result = await response.json(); + console.log("result: ", result); return result; } catch (error) { echo.error("Failed to sign-up"); diff --git a/app/src/store/builder/store.ts b/app/src/store/builder/store.ts index 06c7bfc..527ee4d 100644 --- a/app/src/store/builder/store.ts +++ b/app/src/store/builder/store.ts @@ -1,454 +1,497 @@ import * as THREE from "three"; import { create } from "zustand"; import { io } from "socket.io-client"; -import * as CONSTANTS from '../../types/world/worldConstants'; +import * as CONSTANTS from "../../types/world/worldConstants"; export const useSocketStore = create((set: any, get: any) => ({ - socket: null, - initializeSocket: (email: string, organization: string) => { - const existingSocket = get().socket; - if (existingSocket) { - return; - } + socket: null, + initializeSocket: (email: string, organization: string, userId?: string) => { + const existingSocket = get().socket; + if (existingSocket) { + return; + } - const socket = io( - `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`, - { - reconnection: true, - auth: { email, organization }, - } - ); + const socket = io( + `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Builder`, + { + reconnection: true, + auth: { email, organization }, + } + ); - const visualizationSocket = io( - `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`, - { - reconnection: true, - auth: { email, organization }, - } - ); + const visualizationSocket = io( + `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/Visualization`, + { + reconnection: true, + auth: { email, organization }, + } + ); - set({ socket, visualizationSocket }); - }, - disconnectSocket: () => { - set((state: any) => { - state.socket?.disconnect(); - state.visualizationSocket?.disconnect(); - return { socket: null }; - }); - }, + const dashBoardSocket = io( + `http://${process.env.REACT_APP_SERVER_SOCKET_API_BASE_URL}/project`, + { + reconnection: true, + auth: { email, organization, userId }, + } + ); + + set({ socket, visualizationSocket, dashBoardSocket }); + }, + disconnectSocket: () => { + set((state: any) => { + state.socket?.disconnect(); + state.visualizationSocket?.disconnect(); + state.dashBoardSocket?.disconnect(); + return { socket: null }; + }); + }, })); export const useLoadingProgress = create<{ - loadingProgress: number; - setLoadingProgress: (x: number) => void; + loadingProgress: number; + setLoadingProgress: (x: number) => void; }>((set) => ({ - loadingProgress: 1, - setLoadingProgress: (x: number) => set({ loadingProgress: x }), + loadingProgress: 1, + setLoadingProgress: (x: number) => set({ loadingProgress: x }), })); export const useOrganization = create((set: any) => ({ - organization: "", - setOrganization: (x: any) => set(() => ({ organization: x })), + organization: "", + setOrganization: (x: any) => set(() => ({ organization: x })), })); export const useToggleView = create((set: any) => ({ - toggleView: false, - setToggleView: (x: any) => set(() => ({ toggleView: x })), + toggleView: false, + setToggleView: (x: any) => set(() => ({ toggleView: x })), })); export const useUpdateScene = create((set: any) => ({ - updateScene: false, - setUpdateScene: (x: any) => set(() => ({ updateScene: x })), + updateScene: false, + setUpdateScene: (x: any) => set(() => ({ updateScene: x })), })); export const useWalls = create((set: any) => ({ - walls: [], - setWalls: (x: any) => set(() => ({ walls: x })), + walls: [], + setWalls: (x: any) => set(() => ({ walls: x })), })); export const useRoomsState = create((set: any) => ({ - roomsState: [], - setRoomsState: (x: any) => set(() => ({ roomsState: x })), + roomsState: [], + setRoomsState: (x: any) => set(() => ({ roomsState: x })), })); export const useZones = create((set: any) => ({ - zones: [], - setZones: (callback: any) => - set((state: any) => ({ - zones: typeof callback === "function" ? callback(state.zones) : callback, - })), + zones: [], + setZones: (callback: any) => + set((state: any) => ({ + zones: typeof callback === "function" ? callback(state.zones) : callback, + })), })); interface ZonePointsState { - zonePoints: THREE.Vector3[]; - setZonePoints: (points: THREE.Vector3[]) => void; + zonePoints: THREE.Vector3[]; + setZonePoints: (points: THREE.Vector3[]) => void; } export const useZonePoints = create((set) => ({ - zonePoints: [], - setZonePoints: (points) => set({ zonePoints: points }), + zonePoints: [], + setZonePoints: (points) => set({ zonePoints: points }), })); export const useSelectedItem = create((set: any) => ({ - selectedItem: { name: "", id: "", type: undefined, category: '', subCatergory: '' }, - setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), + selectedItem: { + name: "", + id: "", + type: undefined, + category: "", + subCatergory: "", + }, + setSelectedItem: (x: any) => set(() => ({ selectedItem: x })), })); export const useNavMesh = create((set: any) => ({ - navMesh: null, - setNavMesh: (x: any) => set({ navMesh: x }), + navMesh: null, + setNavMesh: (x: any) => set({ navMesh: x }), })); export const useSelectedAssets = create((set: any) => ({ - selectedAssets: [], - setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), + selectedAssets: [], + setSelectedAssets: (x: any) => set(() => ({ selectedAssets: x })), })); export const useLayers = create((set: any) => ({ - Layers: 1, - setLayers: (x: any) => set(() => ({ Layers: x })), + Layers: 1, + setLayers: (x: any) => set(() => ({ Layers: x })), })); export const useCamPosition = create((set: any) => ({ - camPosition: { x: undefined, y: undefined, z: undefined }, - setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), + camPosition: { x: undefined, y: undefined, z: undefined }, + setCamPosition: (newCamPosition: any) => set({ camPosition: newCamPosition }), })); export const useMenuVisible = create((set: any) => ({ - menuVisible: false, - setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), + menuVisible: false, + setMenuVisible: (x: any) => set(() => ({ menuVisible: x })), })); export const useDeleteTool = create((set: any) => ({ - deleteTool: false, - setDeleteTool: (x: any) => set(() => ({ deleteTool: x })), + deleteTool: false, + setDeleteTool: (x: any) => set(() => ({ deleteTool: x })), })); export const useToolMode = create((set: any) => ({ - toolMode: null, - setToolMode: (x: any) => set(() => ({ toolMode: x })), + toolMode: null, + setToolMode: (x: any) => set(() => ({ toolMode: x })), })); export const useNewLines = create((set: any) => ({ - newLines: [], - setNewLines: (x: any) => set(() => ({ newLines: x })), + newLines: [], + setNewLines: (x: any) => set(() => ({ newLines: x })), })); export const useDeletedLines = create((set: any) => ({ - deletedLines: [], - setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), + deletedLines: [], + setDeletedLines: (x: any) => set(() => ({ deletedLines: x })), })); export const useMovePoint = create((set: any) => ({ - movePoint: false, - setMovePoint: (x: any) => set(() => ({ movePoint: x })), + movePoint: false, + setMovePoint: (x: any) => set(() => ({ movePoint: x })), })); export const useDeletePointOrLine = create((set: any) => ({ - deletePointOrLine: false, - setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), + deletePointOrLine: false, + setDeletePointOrLine: (x: any) => set(() => ({ deletePointOrLine: x })), })); export const useFloorItems = create((set: any) => ({ - floorItems: null, - setFloorItems: (callback: any) => - set((state: any) => ({ - floorItems: - typeof callback === "function" ? callback(state.floorItems) : callback, - })), + floorItems: null, + setFloorItems: (callback: any) => + set((state: any) => ({ + floorItems: + typeof callback === "function" ? callback(state.floorItems) : callback, + })), })); export const useWallItems = create((set: any) => ({ - wallItems: [], - setWallItems: (callback: any) => - set((state: any) => ({ - wallItems: - typeof callback === "function" ? callback(state.wallItems) : callback, - })), + wallItems: [], + setWallItems: (callback: any) => + set((state: any) => ({ + wallItems: + typeof callback === "function" ? callback(state.wallItems) : callback, + })), })); export const useSelectedWallItem = create((set: any) => ({ - selectedWallItem: null, - setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), + selectedWallItem: null, + setSelectedWallItem: (x: any) => set(() => ({ selectedWallItem: x })), })); export const useSelectedFloorItem = create((set: any) => ({ - selectedFloorItem: null, - setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), + selectedFloorItem: null, + setSelectedFloorItem: (x: any) => set(() => ({ selectedFloorItem: x })), })); export const useDeletableFloorItem = create((set: any) => ({ - deletableFloorItem: null, - setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), + deletableFloorItem: null, + setDeletableFloorItem: (x: any) => set(() => ({ deletableFloorItem: x })), })); export const useSetScale = create((set: any) => ({ - scale: null, - setScale: (x: any) => set(() => ({ scale: x })), + scale: null, + setScale: (x: any) => set(() => ({ scale: x })), })); export const useRoofVisibility = create((set: any) => ({ - roofVisibility: false, - setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), + roofVisibility: false, + setRoofVisibility: (x: any) => set(() => ({ roofVisibility: x })), })); export const useWallVisibility = create((set: any) => ({ - wallVisibility: false, - setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), + wallVisibility: false, + setWallVisibility: (x: any) => set(() => ({ wallVisibility: x })), })); export const useShadows = create((set: any) => ({ - shadows: false, - setShadows: (x: any) => set(() => ({ shadows: x })), + shadows: false, + setShadows: (x: any) => set(() => ({ shadows: x })), })); export const useSunPosition = create((set: any) => ({ - sunPosition: { x: undefined, y: undefined, z: undefined }, - setSunPosition: (newSuntPosition: any) => - set({ sunPosition: newSuntPosition }), + sunPosition: { x: undefined, y: undefined, z: undefined }, + setSunPosition: (newSuntPosition: any) => + set({ sunPosition: newSuntPosition }), })); export const useRemoveLayer = create((set: any) => ({ - removeLayer: false, - setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), + removeLayer: false, + setRemoveLayer: (x: any) => set(() => ({ removeLayer: x })), })); export const useRemovedLayer = create((set: any) => ({ - removedLayer: null, - setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), + removedLayer: null, + setRemovedLayer: (x: any) => set(() => ({ removedLayer: x })), })); export const useActiveLayer = create((set: any) => ({ - activeLayer: 1, - setActiveLayer: (x: any) => set({ activeLayer: x }), + activeLayer: 1, + setActiveLayer: (x: any) => set({ activeLayer: x }), })); interface RefTextUpdateState { - refTextupdate: number; - setRefTextUpdate: ( - callback: (currentValue: number) => number | number - ) => void; + refTextupdate: number; + setRefTextUpdate: ( + callback: (currentValue: number) => number | number + ) => void; } export const useRefTextUpdate = create((set) => ({ - refTextupdate: -1000, - setRefTextUpdate: (callback) => - set((state) => ({ - refTextupdate: - typeof callback === "function" - ? callback(state.refTextupdate) - : callback, - })), + refTextupdate: -1000, + setRefTextUpdate: (callback) => + set((state) => ({ + refTextupdate: + typeof callback === "function" + ? callback(state.refTextupdate) + : callback, + })), })); export const useResetCamera = create((set: any) => ({ - resetCamera: false, - setResetCamera: (x: any) => set({ resetCamera: x }), + resetCamera: false, + setResetCamera: (x: any) => set({ resetCamera: x }), })); export const useAddAction = create((set: any) => ({ - addAction: null, - setAddAction: (x: any) => set({ addAction: x }), + addAction: null, + setAddAction: (x: any) => set({ addAction: x }), })); export const useActiveTool = create((set: any) => ({ - activeTool: "cursor", - setActiveTool: (x: any) => set({ activeTool: x }), + activeTool: "cursor", + setActiveTool: (x: any) => set({ activeTool: x }), })); export const useActiveSubTool = create((set: any) => ({ - activeSubTool: "cursor", - setActiveSubTool: (x: any) => set({ activeSubTool: x }), + activeSubTool: "cursor", + setActiveSubTool: (x: any) => set({ activeSubTool: x }), })); export const use2DUndoRedo = create((set: any) => ({ - is2DUndoRedo: null, - set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), + is2DUndoRedo: null, + set2DUndoRedo: (x: any) => set({ is2DUndoRedo: x }), })); export const useElevation = create((set: any) => ({ - elevation: 45, - setElevation: (x: any) => set({ elevation: x }), + elevation: 45, + setElevation: (x: any) => set({ elevation: x }), })); export const useAzimuth = create((set: any) => ({ - azimuth: -160, - setAzimuth: (x: any) => set({ azimuth: x }), + azimuth: -160, + setAzimuth: (x: any) => set({ azimuth: x }), })); export const useRenderDistance = create((set: any) => ({ - renderDistance: 40, - setRenderDistance: (x: any) => set({ renderDistance: x }), + renderDistance: 40, + setRenderDistance: (x: any) => set({ renderDistance: x }), })); export const useCamMode = create((set: any) => ({ - camMode: "ThirdPerson", - setCamMode: (x: any) => set({ camMode: x }), + camMode: "ThirdPerson", + setCamMode: (x: any) => set({ camMode: x }), })); export const useUserName = create((set: any) => ({ - userName: "", - setUserName: (x: any) => set({ userName: x }), + userName: "", + setUserName: (x: any) => set({ userName: x }), })); export const useObjectPosition = create((set: any) => ({ - objectPosition: { x: undefined, y: undefined, z: undefined }, - setObjectPosition: (newObjectPosition: any) => - set({ objectPosition: newObjectPosition }), + objectPosition: { x: undefined, y: undefined, z: undefined }, + setObjectPosition: (newObjectPosition: any) => + set({ objectPosition: newObjectPosition }), })); export const useObjectRotation = create((set: any) => ({ - objectRotation: { x: undefined, y: undefined, z: undefined }, - setObjectRotation: (newObjectRotation: any) => - set({ objectRotation: newObjectRotation }), + objectRotation: { x: undefined, y: undefined, z: undefined }, + setObjectRotation: (newObjectRotation: any) => + set({ objectRotation: newObjectRotation }), })); export const useDrieTemp = create((set: any) => ({ - drieTemp: undefined, - setDrieTemp: (x: any) => set({ drieTemp: x }), + drieTemp: undefined, + setDrieTemp: (x: any) => set({ drieTemp: x }), })); export const useActiveUsers = create((set: any) => ({ - activeUsers: [], - setActiveUsers: (callback: (prev: any[]) => any[] | any[]) => - set((state: { activeUsers: any[] }) => ({ - activeUsers: - typeof callback === "function" ? callback(state.activeUsers) : callback, - })), + activeUsers: [], + setActiveUsers: (callback: (prev: any[]) => any[] | any[]) => + set((state: { activeUsers: any[] }) => ({ + activeUsers: + typeof callback === "function" ? callback(state.activeUsers) : callback, + })), })); export const useDrieUIValue = create((set: any) => ({ - drieUIValue: { touch: null, temperature: null, humidity: null }, + drieUIValue: { touch: null, temperature: null, humidity: null }, - setDrieUIValue: (x: any) => - set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), + setDrieUIValue: (x: any) => + set((state: any) => ({ drieUIValue: { ...state.drieUIValue, ...x } })), - setTouch: (value: any) => - set((state: any) => ({ - drieUIValue: { ...state.drieUIValue, touch: value }, - })), - setTemperature: (value: any) => - set((state: any) => ({ - drieUIValue: { ...state.drieUIValue, temperature: value }, - })), - setHumidity: (value: any) => - set((state: any) => ({ - drieUIValue: { ...state.drieUIValue, humidity: value }, - })), + setTouch: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, touch: value }, + })), + setTemperature: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, temperature: value }, + })), + setHumidity: (value: any) => + set((state: any) => ({ + drieUIValue: { ...state.drieUIValue, humidity: value }, + })), })); export const useStartSimulation = create((set: any) => ({ - startSimulation: false, - setStartSimulation: (x: any) => set({ startSimulation: x }), + startSimulation: false, + setStartSimulation: (x: any) => set({ startSimulation: x }), })); export const useEyeDropMode = create((set: any) => ({ - eyeDropMode: false, - setEyeDropMode: (x: any) => set({ eyeDropMode: x }), + eyeDropMode: false, + setEyeDropMode: (x: any) => set({ eyeDropMode: x }), })); export const useEditingPoint = create((set: any) => ({ - editingPoint: false, - setEditingPoint: (x: any) => set({ editingPoint: x }), + editingPoint: false, + setEditingPoint: (x: any) => set({ editingPoint: x }), })); export const usezoneTarget = create((set: any) => ({ - zoneTarget: [], - setZoneTarget: (x: any) => set({ zoneTarget: x }), + zoneTarget: [], + setZoneTarget: (x: any) => set({ zoneTarget: x }), })); export const usezonePosition = create((set: any) => ({ - zonePosition: [], - setZonePosition: (x: any) => set({ zonePosition: x }), + zonePosition: [], + setZonePosition: (x: any) => set({ zonePosition: x }), })); interface EditPositionState { - Edit: boolean; - setEdit: (value: boolean) => void; + Edit: boolean; + setEdit: (value: boolean) => void; } export const useEditPosition = create((set) => ({ - Edit: false, - setEdit: (value) => set({ Edit: value }), + Edit: false, + setEdit: (value) => set({ Edit: value }), })); export const useAsset3dWidget = create((set: any) => ({ - widgetSelect: "", - setWidgetSelect: (x: any) => set({ widgetSelect: x }), + widgetSelect: "", + setWidgetSelect: (x: any) => set({ widgetSelect: x }), })); export const useWidgetSubOption = create((set: any) => ({ - widgetSubOption: "2D", - setWidgetSubOption: (x: any) => set({ widgetSubOption: x }), + widgetSubOption: "2D", + setWidgetSubOption: (x: any) => set({ widgetSubOption: x }), })); export const useLimitDistance = create((set: any) => ({ - limitDistance: true, - setLimitDistance: (x: any) => set({ limitDistance: x }), + limitDistance: true, + setLimitDistance: (x: any) => set({ limitDistance: x }), +})); +export const useProjectName = create((set: any) => ({ + projectName: "Creating Your Project", + setProjectName: (x: any) => set({ projectName: x }), })); +// // export const useProjectCount = create((set: any) => ({ +// // projectCount: 1, // Initial state for projectCount +// // // Function to update projectCount +// // setProjectCount: (x: number) => +// // set((state: any) => ({ +// // projectCount: state.projectCount + x, +// // })), +// // })); +// export const useProjectCount = create((set: any) => ({ +// projectCount: Number(localStorage.getItem("projectCount")) || 1, // Load from localStorage or default to 1 +// setProjectCount: (x: number) => +// set((state: any) => { +// const newCount = state.projectCount + x; +// localStorage.setItem("projectCount", newCount.toString()); // Sync with localStorage +// return { projectCount: newCount }; +// }), +// })); + export const useTileDistance = create((set: any) => ({ - gridValue: { size: CONSTANTS.gridConfig.size, divisions: CONSTANTS.gridConfig.divisions }, - planeValue: { height: CONSTANTS.planeConfig.height, width: CONSTANTS.planeConfig.width }, + gridValue: { + size: CONSTANTS.gridConfig.size, + divisions: CONSTANTS.gridConfig.divisions, + }, + planeValue: { + height: CONSTANTS.planeConfig.height, + width: CONSTANTS.planeConfig.width, + }, - setGridValue: (value: any) => - set((state: any) => ({ - gridValue: { ...state.gridValue, ...value }, - })), + setGridValue: (value: any) => + set((state: any) => ({ + gridValue: { ...state.gridValue, ...value }, + })), - setPlaneValue: (value: any) => - set((state: any) => ({ - planeValue: { ...state.planeValue, ...value }, - })), + setPlaneValue: (value: any) => + set((state: any) => ({ + planeValue: { ...state.planeValue, ...value }, + })), })); export const usePlayAgv = create((set, get) => ({ - PlayAgv: [], - setPlayAgv: (updateFn: (prev: any[]) => any[]) => - set({ PlayAgv: updateFn(get().PlayAgv) }), + PlayAgv: [], + setPlayAgv: (updateFn: (prev: any[]) => any[]) => + set({ PlayAgv: updateFn(get().PlayAgv) }), })); // Define the Asset type type Asset = { - id: string; - name: string; - position?: [number, number, number]; // Optional: 3D position - rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation + id: string; + name: string; + position?: [number, number, number]; // Optional: 3D position + rotation?: { x: number; y: number; z: number }; // Optional: Euler rotation }; // Zustand store type type ZoneAssetState = { - zoneAssetId: Asset | null; - setZoneAssetId: (asset: Asset | null) => void; + zoneAssetId: Asset | null; + setZoneAssetId: (asset: Asset | null) => void; }; // Zustand store export const useZoneAssetId = create((set) => ({ - zoneAssetId: null, - setZoneAssetId: (asset) => set({ zoneAssetId: asset }), + zoneAssetId: null, + setZoneAssetId: (asset) => set({ zoneAssetId: asset }), })); // version visible hidden interface VersionHistoryState { - viewVersionHistory: boolean; - setVersionHistory: (value: boolean) => void; + viewVersionHistory: boolean; + setVersionHistory: (value: boolean) => void; } const useVersionHistoryStore = create((set) => ({ - viewVersionHistory: false, - setVersionHistory: (value) => set({ viewVersionHistory: value }), + viewVersionHistory: false, + setVersionHistory: (value) => set({ viewVersionHistory: value }), })); export default useVersionHistoryStore; interface ShortcutStore { - showShortcuts: boolean; - setShowShortcuts: (value: boolean) => void; - toggleShortcuts: () => void; + showShortcuts: boolean; + setShowShortcuts: (value: boolean) => void; + toggleShortcuts: () => void; } export const useShortcutStore = create((set) => ({ - showShortcuts: false, - setShowShortcuts: (value) => set({ showShortcuts: value }), - toggleShortcuts: () => - set((state) => ({ showShortcuts: !state.showShortcuts })), -})); \ No newline at end of file + showShortcuts: false, + setShowShortcuts: (value) => set({ showShortcuts: value }), + toggleShortcuts: () => + set((state) => ({ showShortcuts: !state.showShortcuts })), +}));