diff --git a/app/src/components/Dashboard/DasboardUseCases.tsx b/app/src/components/Dashboard/DasboardUseCases.tsx index fc3bd64..0493851 100644 --- a/app/src/components/Dashboard/DasboardUseCases.tsx +++ b/app/src/components/Dashboard/DasboardUseCases.tsx @@ -1,42 +1,34 @@ +import { MathUtils } from "three"; import React, { useEffect, useState } from "react"; -import DashboardNavBar from "./DashboardNavBar"; -import { projectTutorialApi } from "../../services/dashboard/projectTutorialApi"; +import { useNavigate } from "react-router-dom"; import { TutorialCard } from "./TutorialCard"; +import { useSocketStore } from "../../store/socket/useSocketStore"; import { getUserData } from "../../functions/getUserData"; import { ALPHA_ORG } from "../../pages/Dashboard"; +import { useLoadingProgress, useProjectName } from "../../store/builder/store"; +import DashboardNavBar from "./DashboardNavBar"; -const DUMMY_DATA = [ - //remove later - { - _id: "1", - name: "Robotic Arm Control", - thumbnail: "https://signfix.com.au/wp-content/uploads/2017/09/placeholder-600x400.png", - updatedAt: new Date().toISOString(), - }, - { - _id: "2", - name: "Simulation Basics", - thumbnail: "https://signfix.com.au/wp-content/uploads/2017/09/placeholder-600x400.png", - updatedAt: new Date().toISOString(), - }, - { - _id: "3", - name: "3D Visualization", - thumbnail: "https://signfix.com.au/wp-content/uploads/2017/09/placeholder-600x400.png", - updatedAt: new Date().toISOString(), - }, -]; +import darkThemeImage from "../../assets/image/darkThemeProject.png"; +import lightThemeImage from "../../assets/image/lightThemeProject.png"; + +import { createProjectApi } from "../../services/dashboard/createProjectApi"; +import { getUseCaseProjectsApi } from "../../services/dashboard/getuseCaseProjectsApi"; const DashboardUseCases: React.FC = () => { - const [useCases, setUseCases] = useState(DUMMY_DATA || []); // default [] - const { organization } = getUserData(); + const navigate = useNavigate(); + const { setLoadingProgress } = useLoadingProgress(); + const { setProjectName } = useProjectName(); + const [useCases, setUseCases] = useState([]); + const { projectSocket, initializeProjectSocket } = useSocketStore(); + const { organization, userId } = getUserData(); + const savedTheme = localStorage.getItem("theme") ?? "light"; useEffect(() => { const fetchTutorials = async () => { try { - const res = await projectTutorialApi(); - if (res && Array.isArray(res) && res.length > 0) { - setUseCases(res); + const res = await getUseCaseProjectsApi(); + if (res.Projects.length > 0) { + setUseCases(res.Projects); } } catch (error) { console.error("Error fetching useCases:", error); @@ -46,6 +38,47 @@ const DashboardUseCases: React.FC = () => { fetchTutorials(); }, []); + const handleCreateNewUseCase = async () => { + const token = localStorage.getItem("token"); + const refreshToken = localStorage.getItem("refreshToken"); + if (!token || !refreshToken) { + console.error("token expired"); + return; + } + + const projectId = MathUtils.generateUUID(); + initializeProjectSocket(token, refreshToken); + + if (projectSocket?.connected) { + // SOCKET + + const addProject = { + userId, + thumbnail: savedTheme === "dark" ? darkThemeImage : lightThemeImage, + organization: organization, + projectUuid: projectId, + projectType: "useCase", + }; + + projectSocket.emit("v1:project:add", addProject); + } else { + // API + + createProjectApi(projectId, userId, savedTheme === "dark" ? darkThemeImage : lightThemeImage, organization, "useCase").then((data) => { + if (data.message === "Project created Successfully") { + setLoadingProgress(1); + navigate(`/projects/${data.data.projectId}`); + } + }); + } + }; + + const handleNavigateToUseCase = (useCase: Tutorial) => { + setLoadingProgress(1); + setProjectName(useCase.projectName); + navigate(`/projects/${useCase._id}`); + }; + return (
@@ -54,18 +87,21 @@ const DashboardUseCases: React.FC = () => { {organization === ALPHA_ORG && (
-
)} {useCases.length > 0 ? ( - useCases.map((tut) => ) + useCases.map((tut) => ) ) : ( -
- No Use Cases available click on '+' button to add -
+
No Use Cases available click on '+' button to add
)}
diff --git a/app/src/components/Dashboard/DashboardMain.tsx b/app/src/components/Dashboard/DashboardMain.tsx index ae180bf..b42f932 100644 --- a/app/src/components/Dashboard/DashboardMain.tsx +++ b/app/src/components/Dashboard/DashboardMain.tsx @@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react"; import { getUserData } from "../../functions/getUserData"; import { useSocketStore } from "../../store/socket/useSocketStore"; -import ProjectSocketRes from "./socket/projectSocketRes"; import DashboardNavBar from "./DashboardNavBar"; import DashboardCard from "./DashboardCard"; import MarketPlaceBanner from "./MarketPlaceBanner"; @@ -18,13 +17,16 @@ import { generateUniqueId } from "../../functions/generateUniqueId"; interface DashboardMainProps { activeFolder: Folder; + projectsData: DashboardProjectCollection; + projectsCache: Record; + isSearchActive: boolean; + setProjectsData: React.Dispatch>; + setProjectsCache: React.Dispatch>>; + setIsSearchActive: React.Dispatch>; } -const DashboardMain: React.FC = ({ activeFolder }) => { +const DashboardMain: React.FC = ({ activeFolder, projectsData, projectsCache, isSearchActive, setProjectsData, setProjectsCache, setIsSearchActive }) => { const [activeSubFolder, setActiveSubFolder] = useState("myProjects"); - const [projectsData, setProjectsData] = useState({}); - const [projectsCache, setProjectsCache] = useState>({}); - const [isSearchActive, setIsSearchActive] = useState(false); const [openKebabProjectId, setOpenKebabProjectId] = useState(null); const { userId, organization } = getUserData(); @@ -173,7 +175,7 @@ const DashboardMain: React.FC = ({ activeFolder }) => { const key = Object.keys(projectsData)[0]; const projectList = projectsData[key]; - if (!projectList?.length) { + if (!projectList || projectList.length === 0) { return
No projects found
; } @@ -237,8 +239,6 @@ const DashboardMain: React.FC = ({ activeFolder }) => { )}
{renderProjects()}
- - ); diff --git a/app/src/components/Dashboard/DashboardTutorial.tsx b/app/src/components/Dashboard/DashboardTutorial.tsx index 6859c26..4ee7d5c 100644 --- a/app/src/components/Dashboard/DashboardTutorial.tsx +++ b/app/src/components/Dashboard/DashboardTutorial.tsx @@ -22,6 +22,8 @@ const DashboardTutorial: React.FC = () => { fetchTutorials(); }, []); + const handleNavigateToTutorial = () => {}; + return (
@@ -36,7 +38,7 @@ const DashboardTutorial: React.FC = () => {
{tutorials.length > 0 ? ( - tutorials.map((tut) => ) + tutorials.map((tut) => ) ) : (
No tutorials available
)} diff --git a/app/src/components/Dashboard/SidePannel.tsx b/app/src/components/Dashboard/SidePannel.tsx index 95d9376..8eb519a 100644 --- a/app/src/components/Dashboard/SidePannel.tsx +++ b/app/src/components/Dashboard/SidePannel.tsx @@ -1,13 +1,15 @@ import React from "react"; -import { DocumentationIcon, HelpIcon, HomeIcon, LogoutIcon, NotificationIcon, ProjectsIcon, TrashIcon, TutorialsIcon } from "../icons/DashboardIcon"; import { useNavigate } from "react-router-dom"; -import darkThemeImage from "../../assets/image/darkThemeProject.png"; -import lightThemeImage from "../../assets/image/lightThemeProject.png"; +import { DocumentationIcon, HelpIcon, HomeIcon, LogoutIcon, NotificationIcon, ProjectsIcon, TrashIcon, TutorialsIcon } from "../icons/DashboardIcon"; import { SettingsIcon } from "../icons/ExportCommonIcons"; import { getUserData } from "../../functions/getUserData"; import { useSocketStore } from "../../store/socket/useSocketStore"; +import { useLoadingProgress } from "../../store/builder/store"; -// import { createProject } from "../../services/dashboard/createProject"; +import { createProjectApi } from "../../services/dashboard/createProjectApi"; + +import darkThemeImage from "../../assets/image/darkThemeProject.png"; +import lightThemeImage from "../../assets/image/lightThemeProject.png"; interface SidePannelProps { setActiveTab: React.Dispatch>; @@ -15,8 +17,9 @@ interface SidePannelProps { } const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { - const { userName, userId, organization } = getUserData(); const navigate = useNavigate(); + const { setLoadingProgress } = useLoadingProgress(); + const { userName, userId, organization } = getUserData(); const { projectSocket, initializeProjectSocket } = useSocketStore(); const savedTheme = localStorage.getItem("theme") ?? "light"; @@ -49,12 +52,12 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { projectSocket.emit("v1:project:add", addProject); } else { // API - // const project = await createProject( - // projectId, - // userId, - // savedTheme === "dark" ? darkThemeImage : lightThemeImage, - // organization - // ); + createProjectApi(projectId, userId, savedTheme === "dark" ? darkThemeImage : lightThemeImage, organization).then((data) => { + if (data.message === "Project created Successfully") { + setLoadingProgress(1); + navigate(`/projects/${data.data.projectId}`); + } + }); } }; @@ -92,7 +95,6 @@ const SidePannel: React.FC = ({ setActiveTab, activeTab }) => { // disabled onClick={() => { setActiveTab("Use Cases"); - console.warn("Use Cases comming soon"); }} > diff --git a/app/src/components/Dashboard/TutorialCard.tsx b/app/src/components/Dashboard/TutorialCard.tsx index a0ae4bf..1d30ca6 100644 --- a/app/src/components/Dashboard/TutorialCard.tsx +++ b/app/src/components/Dashboard/TutorialCard.tsx @@ -2,24 +2,20 @@ import { getUserData } from "../../functions/getUserData"; import { ALPHA_ORG } from "../../pages/Dashboard"; import { DeleteIcon } from "../icons/ContextMenuIcons"; -export const TutorialCard: React.FC<{ tutorial: Tutorial }> = ({ tutorial }) => { +export const TutorialCard: React.FC<{ tutorial: Tutorial; onClick: (tutorial: Tutorial) => void }> = ({ tutorial, onClick }) => { const { organization } = getUserData(); return ( -
+
onClick(tutorial)}>
-
{tutorial.name}
-
- {new Date(tutorial.updatedAt).toLocaleDateString()} -
+
{tutorial.projectName}
+
{new Date(tutorial.createdAt).toLocaleDateString()}
{organization === ALPHA_ORG && (
diff --git a/app/src/pages/Dashboard.tsx b/app/src/pages/Dashboard.tsx index deda19c..dba0700 100644 --- a/app/src/pages/Dashboard.tsx +++ b/app/src/pages/Dashboard.tsx @@ -5,14 +5,23 @@ import SidePannel from "../components/Dashboard/SidePannel"; import DashboardTutorial from "../components/Dashboard/DashboardTutorial"; import DashboardMain from "../components/Dashboard/DashboardMain"; import DashboardUseCases from "../components/Dashboard/DasboardUseCases"; +import ProjectSocketRes from "../components/Dashboard/socket/projectSocketRes"; +import { useNavigate } from "react-router-dom"; export const ALPHA_ORG = "hexrfactory"; const Dashboard: React.FC = () => { + const navigate = useNavigate(); const [activeTab, setActiveTab] = useState("Home"); + const [projectsData, setProjectsData] = useState({}); + const [projectsCache, setProjectsCache] = useState>({}); + const [isSearchActive, setIsSearchActive] = useState(false); const { organization, email } = getUserData(); useEffect(() => { + if (email === "" || organization === "") { + navigate("/"); + } const token = localStorage.getItem("token"); const refreshToken = localStorage.getItem("refreshToken"); if (token && refreshToken) { @@ -20,12 +29,31 @@ const Dashboard: React.FC = () => { } }, [email, organization]); + if (email === "" || organization === "") { + return null; + } + return (
- {["Home", "Projects", "Shared", "Trash"].includes(activeTab) && } + {["Home", "Projects", "Shared", "Trash"].includes(activeTab) && ( + + )} {activeTab === "Tutorials" && } {activeTab === "Use Cases" && } + +
); }; diff --git a/app/src/services/dashboard/createProjectApi.ts b/app/src/services/dashboard/createProjectApi.ts index 82d60b6..7555833 100644 --- a/app/src/services/dashboard/createProjectApi.ts +++ b/app/src/services/dashboard/createProjectApi.ts @@ -1,6 +1,6 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; -export const createProjectApi = async (projectUuid: string, userId: string, thumbnail: string, organization: string) => { +export const createProjectApi = async (projectUuid: string, userId: string, thumbnail: string, organization: string, projectType?: string) => { try { const response = await fetch(`${url_Backend_dwinzo}/api/V1/NewProject`, { method: "POST", @@ -10,7 +10,7 @@ export const createProjectApi = async (projectUuid: string, userId: string, thum token: localStorage.getItem("token") || "", refresh_token: localStorage.getItem("refreshToken") || "", }, - body: JSON.stringify({ projectUuid, userId, thumbnail, organization }), + body: JSON.stringify({ projectUuid, userId, thumbnail, organization, projectType }), }); const newAccessToken = response.headers.get("x-access-token"); if (newAccessToken) { diff --git a/app/src/services/dashboard/getuseCaseProjectsApi.ts b/app/src/services/dashboard/getuseCaseProjectsApi.ts new file mode 100644 index 0000000..a1d198b --- /dev/null +++ b/app/src/services/dashboard/getuseCaseProjectsApi.ts @@ -0,0 +1,28 @@ +let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; + +export const getUseCaseProjectsApi = async () => { + try { + const response = await fetch(`${url_Backend_dwinzo}/api/V1/useCases/projects`, { + method: "GET", + headers: { + Authorization: "Bearer ", + "Content-Type": "application/json", + token: localStorage.getItem("token") || "", + refresh_token: localStorage.getItem("refreshToken") || "", + }, + }); + const newAccessToken = response.headers.get("x-access-token"); + if (newAccessToken) { + localStorage.setItem("token", newAccessToken); + } + + if (!response.ok) { + console.error("Failed to get usecase Projects"); + } + + const result = await response.json(); + return result; + } catch { + console.log("Failed to get usecase Projects"); + } +}; diff --git a/app/src/types/uiTypes.d.ts b/app/src/types/uiTypes.d.ts index 7bb590b..20506b0 100644 --- a/app/src/types/uiTypes.d.ts +++ b/app/src/types/uiTypes.d.ts @@ -73,7 +73,7 @@ interface ListProps { interface Tutorial { _id: string; - name: string; + projectName: string; thumbnail?: string; - updatedAt: string; + createdAt: string; }