fix: dashboard types updated, tutorial started

This commit is contained in:
2025-09-10 14:14:14 +05:30
parent f3f4087255
commit 9b21966210
8 changed files with 79 additions and 134 deletions

View File

@@ -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>
); );

View File

@@ -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>
); );

View File

@@ -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");
}} }}
> >

View File

@@ -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>>;
} }

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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
View 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";