fix: dashboard types updated, tutorial started
This commit is contained in:
@@ -14,36 +14,21 @@ import { restoreTrashApi } from "../../services/dashboard/restoreTrashApi";
|
|||||||
import { generateUniqueId } from "../../functions/generateUniqueId";
|
import { generateUniqueId } from "../../functions/generateUniqueId";
|
||||||
import ProjectSocketRes from "./socket/projectSocketRes";
|
import ProjectSocketRes from "./socket/projectSocketRes";
|
||||||
|
|
||||||
interface Project {
|
|
||||||
_id: string;
|
|
||||||
projectName: string;
|
|
||||||
thumbnail: string;
|
|
||||||
createdBy: { _id: string; userName: string };
|
|
||||||
projectUuid?: string;
|
|
||||||
createdAt?: string;
|
|
||||||
DeletedAt?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProjectCollection {
|
|
||||||
[key: string]: Project[];
|
|
||||||
}
|
|
||||||
|
|
||||||
type Folder = "home" | "projects" | "shared" | "trash";
|
|
||||||
|
|
||||||
interface DashboardMainProps {
|
interface DashboardMainProps {
|
||||||
activeFolder: Folder;
|
activeFolder: Folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
||||||
const [activeSubFolder, setActiveSubFolder] = useState("myProjects");
|
const [activeSubFolder, setActiveSubFolder] = useState("myProjects");
|
||||||
const [projectsData, setProjectsData] = useState<ProjectCollection>({});
|
const [projectsData, setProjectsData] = useState<DashboardProjectCollection>({});
|
||||||
const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
|
const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
|
||||||
const [duplicateData, setDuplicateData] = useState<Object>({});
|
const [duplicateData, setDuplicateData] = useState<Object>({});
|
||||||
const [openKebabProjectId, setOpenKebabProjectId] = useState<string | null>(null);
|
const [openKebabProjectId, setOpenKebabProjectId] = useState<string | null>(null);
|
||||||
const [projectsCache, setProjectsCache] = useState<{ [key: string]: ProjectCollection }>({});
|
const [projectsCache, setProjectsCache] = useState<{ [key: string]: DashboardProjectCollection }>({});
|
||||||
|
|
||||||
const { userId, organization } = getUserData();
|
const { userId, organization } = getUserData();
|
||||||
const { projectSocket } = useSocketStore();
|
const { projectSocket } = useSocketStore();
|
||||||
|
console.log("duplicateData: ", duplicateData);
|
||||||
|
|
||||||
// #region API Fetchers
|
// #region API Fetchers
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
@@ -55,7 +40,7 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let projects: ProjectCollection = {}; // initialize as empty object
|
let projects: DashboardProjectCollection = {}; // initialize as empty object
|
||||||
|
|
||||||
switch (activeFolder) {
|
switch (activeFolder) {
|
||||||
case "home":
|
case "home":
|
||||||
@@ -71,6 +56,8 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
case "trash":
|
case "trash":
|
||||||
projects = await getTrashApi();
|
projects = await getTrashApi();
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only update cache if projects is not empty
|
// Only update cache if projects is not empty
|
||||||
@@ -129,7 +116,11 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
updateStateAfterRemove(projectId);
|
updateStateAfterRemove(projectId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDuplicate = async (projectId: string, projectName: string, thumbnail: string): Promise<void> => {
|
const handleDuplicate = async (
|
||||||
|
projectId: string,
|
||||||
|
projectName: string,
|
||||||
|
thumbnail: string
|
||||||
|
): Promise<void> => {
|
||||||
if (projectSocket) {
|
if (projectSocket) {
|
||||||
projectSocket.emit("v1:project:Duplicate", {
|
projectSocket.emit("v1:project:Duplicate", {
|
||||||
userId,
|
userId,
|
||||||
@@ -144,7 +135,7 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
|
|
||||||
// #region Project Map
|
// #region Project Map
|
||||||
const updateStateAfterRemove = (projectId: string) => {
|
const updateStateAfterRemove = (projectId: string) => {
|
||||||
setProjectsData((prev: ProjectCollection) => {
|
setProjectsData((prev: DashboardProjectCollection) => {
|
||||||
const key = Object.keys(prev)[0];
|
const key = Object.keys(prev)[0];
|
||||||
const updatedList = prev[key]?.filter((p) => p._id !== projectId) || [];
|
const updatedList = prev[key]?.filter((p) => p._id !== projectId) || [];
|
||||||
return { ...prev, [key]: updatedList };
|
return { ...prev, [key]: updatedList };
|
||||||
@@ -204,7 +195,12 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
<div className="dashboard-home-container">
|
<div className="dashboard-home-container">
|
||||||
<DashboardNavBar
|
<DashboardNavBar
|
||||||
page={activeFolder}
|
page={activeFolder}
|
||||||
{...(activeFolder === "trash" ? { handleTrashSearch: handleSearch } : { handleProjectsSearch: handleSearch, handleRecentProjectSearch: handleSearch })}
|
{...(activeFolder === "trash"
|
||||||
|
? { handleTrashSearch: handleSearch }
|
||||||
|
: {
|
||||||
|
handleProjectsSearch: handleSearch,
|
||||||
|
handleRecentProjectSearch: handleSearch,
|
||||||
|
})}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{activeFolder === "home" && <MarketPlaceBanner />}
|
{activeFolder === "home" && <MarketPlaceBanner />}
|
||||||
@@ -212,10 +208,16 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
|
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
|
||||||
{activeFolder === "projects" && (
|
{activeFolder === "projects" && (
|
||||||
<div className="header-wrapper" style={{ display: "flex", gap: "7px" }}>
|
<div className="header-wrapper" style={{ display: "flex", gap: "7px" }}>
|
||||||
<button className={`header ${activeSubFolder === "myProjects" && "active"}`} onClick={() => setActiveSubFolder("myProjects")}>
|
<button
|
||||||
|
className={`header ${activeSubFolder === "myProjects" && "active"}`}
|
||||||
|
onClick={() => setActiveSubFolder("myProjects")}
|
||||||
|
>
|
||||||
My Projects
|
My Projects
|
||||||
</button>
|
</button>
|
||||||
<button className={`header ${activeSubFolder === "shared" && "active"}`} onClick={() => setActiveSubFolder("shared")}>
|
<button
|
||||||
|
className={`header ${activeSubFolder === "shared" && "active"}`}
|
||||||
|
onClick={() => setActiveSubFolder("shared")}
|
||||||
|
>
|
||||||
Shared with me
|
Shared with me
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -223,7 +225,12 @@ const DashboardMain: React.FC<DashboardMainProps> = ({ activeFolder }) => {
|
|||||||
|
|
||||||
<div className="cards-container">{renderProjects()}</div>
|
<div className="cards-container">{renderProjects()}</div>
|
||||||
|
|
||||||
<ProjectSocketRes setIsSearchActive={setIsSearchActive} {...(activeFolder === "home" ? { setRecentProjects: setProjectsData } : { setWorkspaceProjects: setProjectsData })} />
|
<ProjectSocketRes
|
||||||
|
setIsSearchActive={setIsSearchActive}
|
||||||
|
{...(activeFolder === "home"
|
||||||
|
? { setRecentProjects: setProjectsData }
|
||||||
|
: { setWorkspaceProjects: setProjectsData })}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,61 +1,12 @@
|
|||||||
import { useEffect, useState } from "react";
|
|
||||||
import DashboardNavBar from "./DashboardNavBar";
|
import DashboardNavBar from "./DashboardNavBar";
|
||||||
import DashboardCard from "./DashboardCard";
|
|
||||||
import { projectTutorialApi } from "../../services/dashboard/projectTutorialApi";
|
import { projectTutorialApi } from "../../services/dashboard/projectTutorialApi";
|
||||||
|
|
||||||
interface Project {
|
|
||||||
_id: string;
|
|
||||||
projectName: string;
|
|
||||||
thumbnail: string;
|
|
||||||
createdBy: string;
|
|
||||||
projectUuid?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DiscardedProjects {
|
|
||||||
[key: string]: Project[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const DashboardTutorial = () => {
|
const DashboardTutorial = () => {
|
||||||
const [tutorialProject, setTutorialProject] = useState<DiscardedProjects>({});
|
|
||||||
|
|
||||||
const handleIcon = async () => {
|
|
||||||
try {
|
|
||||||
let tutorial = await projectTutorialApi();
|
|
||||||
setTutorialProject(tutorial);
|
|
||||||
} catch {}
|
|
||||||
};
|
|
||||||
|
|
||||||
const [openKebabProjectId, setOpenKebabProjectId] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
handleIcon();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const renderTrashProjects = () => {
|
|
||||||
const projectList = tutorialProject[Object.keys(tutorialProject)[0]];
|
|
||||||
|
|
||||||
if (!projectList?.length) {
|
|
||||||
return <div className="empty-state">No deleted projects found</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return projectList.map((tutorials: any) => (
|
|
||||||
<DashboardCard
|
|
||||||
key={tutorials._id}
|
|
||||||
projectName={tutorials.projectName}
|
|
||||||
thumbnail={tutorials.thumbnail}
|
|
||||||
projectId={tutorials._id}
|
|
||||||
openKebabProjectId={openKebabProjectId}
|
|
||||||
setOpenKebabProjectId={setOpenKebabProjectId}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-home-container">
|
<div className="dashboard-home-container">
|
||||||
<DashboardNavBar page="tutorial" />
|
<DashboardNavBar page="tutorial" />
|
||||||
|
|
||||||
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
|
<div className="dashboard-container" style={{ height: "calc(100% - 87px)" }}>
|
||||||
<div className="header" style={{ display: "flex", gap: "7px" }}></div>
|
<button className="add-tutorials-button">+</button>
|
||||||
<div className="cards-container">{renderTrashProjects()}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -115,9 +115,9 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
|
|||||||
<button
|
<button
|
||||||
className={activeTab === "Tutorials" ? "option-list active" : "option-list"}
|
className={activeTab === "Tutorials" ? "option-list active" : "option-list"}
|
||||||
title="coming soon"
|
title="coming soon"
|
||||||
disabled
|
// disabled
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// setActiveTab("Tutorials");
|
setActiveTab("Tutorials");
|
||||||
console.warn("Tutorials comming soon");
|
console.warn("Tutorials comming soon");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -127,9 +127,9 @@ const SidePannel: React.FC<SidePannelProps> = ({ setActiveTab, activeTab }) => {
|
|||||||
<button
|
<button
|
||||||
className={activeTab === "Documentation" ? "option-list active" : "option-list"}
|
className={activeTab === "Documentation" ? "option-list active" : "option-list"}
|
||||||
title="coming soon"
|
title="coming soon"
|
||||||
disabled
|
disabled // remove when added
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
// setActiveTab("Documentation");
|
setActiveTab("Documentation");
|
||||||
console.warn("Documentation comming soon");
|
console.warn("Documentation comming soon");
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,24 +5,14 @@ import { getAllProjectsApi } from "../../../services/dashboard/getAllProjectsApi
|
|||||||
import { recentlyViewedApi } from "../../../services/dashboard/recentlyViewedApi";
|
import { recentlyViewedApi } from "../../../services/dashboard/recentlyViewedApi";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
interface Project {
|
|
||||||
_id: string;
|
|
||||||
projectName: string;
|
|
||||||
thumbnail: string;
|
|
||||||
createdBy: { _id: string; userName: string };
|
|
||||||
projectUuid?: string;
|
|
||||||
createdAt?: string;
|
|
||||||
DeletedAt?: string;
|
|
||||||
isViewed?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProjectCollection {
|
interface DashboardProjectCollection {
|
||||||
[key: string]: Project[];
|
[key: string]: DashboardProject[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ProjectSocketResProps {
|
interface ProjectSocketResProps {
|
||||||
setRecentProjects?: React.Dispatch<React.SetStateAction<ProjectCollection>>;
|
setRecentProjects?: React.Dispatch<React.SetStateAction<DashboardProjectCollection>>;
|
||||||
setWorkspaceProjects?: React.Dispatch<React.SetStateAction<ProjectCollection>>;
|
setWorkspaceProjects?: React.Dispatch<React.SetStateAction<DashboardProjectCollection>>;
|
||||||
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,31 +6,27 @@ import DashboardTutorial from "../components/Dashboard/DashboardTutorial";
|
|||||||
import DashboardMain from "../components/Dashboard/DashboardMain";
|
import DashboardMain from "../components/Dashboard/DashboardMain";
|
||||||
|
|
||||||
const Dashboard: React.FC = () => {
|
const Dashboard: React.FC = () => {
|
||||||
const [activeTab, setActiveTab] = useState<string>("Home");
|
const [activeTab, setActiveTab] = useState<string>("Home");
|
||||||
const { socket } = useSocketStore();
|
const { socket } = useSocketStore();
|
||||||
const { organization, email } = getUserData();
|
const { organization, email } = getUserData();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const token = localStorage.getItem("token");
|
const token = localStorage.getItem("token");
|
||||||
const refreshToken = localStorage.getItem("refreshToken");
|
const refreshToken = localStorage.getItem("refreshToken");
|
||||||
if (token && refreshToken) {
|
if (token && refreshToken) {
|
||||||
useSocketStore
|
useSocketStore.getState().initializeSocket(email, organization, token, refreshToken);
|
||||||
.getState()
|
|
||||||
.initializeSocket(email, organization, token, refreshToken);
|
|
||||||
}
|
|
||||||
}, [socket, email, organization]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="dashboard-main">
|
|
||||||
<SidePannel setActiveTab={setActiveTab} activeTab={activeTab} />
|
|
||||||
<DashboardMain
|
|
||||||
activeFolder={
|
|
||||||
activeTab.toLowerCase() as "home" | "projects" | "shared" | "trash"
|
|
||||||
}
|
}
|
||||||
/>
|
}, [socket, email, organization]);
|
||||||
{activeTab === "Tutorials" && <DashboardTutorial />}
|
|
||||||
</div>
|
return (
|
||||||
);
|
<div className="dashboard-main">
|
||||||
|
<SidePannel setActiveTab={setActiveTab} activeTab={activeTab} />
|
||||||
|
{["Home", "Projects", "Shared", "Trash"].includes(activeTab) && (
|
||||||
|
<DashboardMain activeFolder={activeTab.toLowerCase() as Folder} />
|
||||||
|
)}
|
||||||
|
{activeTab === "Tutorials" && <DashboardTutorial />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Dashboard;
|
export default Dashboard;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ const ForgotPassword: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const emailResponse = await checkEmailApi(email);
|
const emailResponse = await checkEmailApi(email);
|
||||||
|
|
||||||
if (emailResponse.message == "OTP sent Successfully") {
|
if (emailResponse.message === "OTP sent Successfully") {
|
||||||
setCode(emailResponse.OTP);
|
setCode(emailResponse.OTP);
|
||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
@@ -41,7 +41,7 @@ const ForgotPassword: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const emailResponse = await checkEmailApi(email);
|
const emailResponse = await checkEmailApi(email);
|
||||||
|
|
||||||
if (emailResponse.message == "OTP sent Successfully") {
|
if (emailResponse.message === "OTP sent Successfully") {
|
||||||
setStep(2);
|
setStep(2);
|
||||||
setCode(emailResponse.OTP);
|
setCode(emailResponse.OTP);
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ const ForgotPassword: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
const otpResponse = await verifyOtpApi(email, Number(code));
|
const otpResponse = await verifyOtpApi(email, Number(code));
|
||||||
|
|
||||||
if (otpResponse.message == "OTP verified successfully") {
|
if (otpResponse.message === "OTP verified successfully") {
|
||||||
setResetToken(otpResponse.resetToken);
|
setResetToken(otpResponse.resetToken);
|
||||||
setStep(3);
|
setStep(3);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
import React, { useEffect } from 'react'
|
|
||||||
|
|
||||||
function sessionValidity() {
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default sessionValidity
|
|
||||||
16
app/src/types/dashboard.d.ts
vendored
Normal file
16
app/src/types/dashboard.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
interface DashboardProject {
|
||||||
|
_id: string;
|
||||||
|
projectName: string;
|
||||||
|
thumbnail: string;
|
||||||
|
createdBy: { _id: string; userName: string };
|
||||||
|
projectUuid?: string;
|
||||||
|
createdAt?: string;
|
||||||
|
DeletedAt?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DashboardProjectCollection {
|
||||||
|
[key: string]: DashboardProject[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type Folder = "home" | "projects" | "shared" | "trash";
|
||||||
Reference in New Issue
Block a user