Enhance DashboardCard component: add createdAt prop and implement relative time display; create ProjectSocketDev component for socket event handling.

This commit is contained in:
Poovizhi99 2025-06-04 09:11:11 +05:30
parent 44b6b4daab
commit 5ba7457276
3 changed files with 141 additions and 14 deletions

View File

@ -6,16 +6,13 @@ import { useProjectName, useSocketStore } from "../../store/builder/store";
import { viewProject } from "../../services/dashboard/viewProject";
import OuterClick from "../../utils/outerClick";
import { KebabIcon } from "../icons/ExportCommonIcons";
import darkThemeImage from "../../assets/image/darkThemeProject.png";
import lightThemeImage from "../../assets/image/lightThemeProject.png";
import { updateProject } from "../../services/dashboard/updateProject";
import { getAllProjects } from "../../services/dashboard/getAllProjects";
import { duplicateProject } from "../../services/dashboard/duplicateProject";
interface DashBoardCardProps {
projectName: string;
thumbnail: any;
projectId: string;
createdAt?: string
handleDeleteProject?: (projectId: string) => Promise<void>;
handleTrashDeleteProject?: (projectId: string) => Promise<void>;
handleRestoreProject?: (projectId: string) => Promise<void>;
@ -24,6 +21,8 @@ interface DashBoardCardProps {
active?: string;
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
}
type RelativeTimeFormatUnit = any
const DashboardCard: React.FC<DashBoardCardProps> = ({
projectName,
@ -33,9 +32,9 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
handleDeleteProject,
handleRestoreProject,
handleTrashDeleteProject,
setIsSearchActive,
handleDuplicateWorkspaceProject,
handleDuplicateRecentProject
handleDuplicateRecentProject,
createdAt
}) => {
const navigate = useNavigate();
const { setProjectName } = useProjectName();
@ -44,10 +43,8 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
const [renameValue, setRenameValue] = useState(projectName);
const [isRenaming, setIsRenaming] = useState(false);
const { projectSocket } = useSocketStore();
const kebabRef = useRef<HTMLDivElement>(null);
const savedTheme = localStorage.getItem("theme") ?? "light";
const navigateToProject = async (e: any) => {
if (active && active == "trash") return
try {
@ -68,9 +65,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
await handleDeleteProject(projectId);
}
else if (handleTrashDeleteProject) {
console.log('projectId:dashboard ', projectId);
// await handleTrashDeleteProject(projectId);
handleTrashDeleteProject(projectId);
await handleTrashDeleteProject(projectId);
}
break;
case "restore":
@ -146,7 +141,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
setMenuVisible: () => setIsKebabOpen(false),
});
const handleProjectName = async (projectName: string) => {
setProjectName(projectName);
// setProjectName(projectName);
setRenameValue(projectName)
if (!projectId) return
// localStorage.setItem("projectName", newName);
@ -190,6 +185,34 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
}
};
function getRelativeTime(dateString: string): string {
const date = new Date(dateString);
const now = new Date();
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
const intervals: Record<RelativeTimeFormatUnit, number> = {
year: 31536000,
month: 2592000,
week: 604800,
day: 86400,
hour: 3600,
minute: 60,
second: 1,
};
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
for (const key in intervals) {
const unit = key as RelativeTimeFormatUnit;
const diff = Math.floor(diffInSeconds / intervals[unit]);
if (diff >= 1) {
return rtf.format(-diff, unit);
}
}
return 'just now';
}
return (
<button
className="dashboard-card-container"
@ -211,6 +234,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
<input
value={renameValue}
onChange={(e) => {
e.stopPropagation(); // Prevents click from bubbling up
handleProjectName(e.target.value);
}}
onBlur={() => {
@ -228,8 +252,8 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
) : (
<span>{renameValue}</span>
)}
{/* <div className="project-name">{projectName}</div> */}
<div className="project-data">24-12-2025</div>
{createdAt && <div className="project-data">{active && active == "trash" ? `Trashed by you` : `Edited `} {getRelativeTime(createdAt)}</div>}
</div>
<div className="users-list-container" ref={kebabRef}>
<div className="user-profile">

View File

@ -0,0 +1,102 @@
import React, { useEffect } from 'react';
import { useSocketStore } from '../../../store/builder/store';
import { getAllProjects } from '../../../services/dashboard/getAllProjects';
import { recentlyViewed } from '../../../services/dashboard/recentlyViewed';
import { data } from 'react-router-dom';
interface HandleDuplicateProjectsParams {
userId: string;
organization: string;
projectId: string;
projectName: string;
projectSocket: any;
thumbnail: string;
setWorkspaceProjects?: React.Dispatch<React.SetStateAction<any>>;
setRecentProjects?: React.Dispatch<React.SetStateAction<any>>;
setIsSearchActive: React.Dispatch<React.SetStateAction<boolean>>;
}
const ProjectSocketDev = () => {
const { projectSocket } = useSocketStore();
useEffect(() => {
if (projectSocket) {
projectSocket.on("v1-project:response:add", (data: any) => {
// console.log('data: ', data);
})
projectSocket.on("v1-project:response:delete", (data: any) => {
// console.log('data: ', data)
})
projectSocket.on("v1-project:response:update", (data: any) => {
// console.log('data: ', data);
});
projectSocket.on("v1-project:response:Duplicate", (data: any) => {
// console.log('data: ', data);
})
projectSocket.on("v1:trash:response:delete", (data: any) => {
// console.log('data: ', data);
})
}
return (() => {
projectSocket.off("v1-project:response:add");
projectSocket.off("v1-project:response:delete");
projectSocket.off("v1-project:response:update");
projectSocket.off("v1-project:response:Duplicate");
projectSocket.off("v1:trash:response:delete");
})
}, [projectSocket])
// const handleDuplicateProjects = async ({
// userId,
// organization,
// projectId,
// projectName,
// projectSocket,
// thumbnail,
// setWorkspaceProjects,
// setRecentProjects,
// setIsSearchActive,
// }: HandleDuplicateProjectsParams): Promise<void> => {
// const duplicateProjectData = {
// userId,
// thumbnail,
// organization,
// projectUuid: projectId,
// projectName,
// };
// if (projectSocket) {
// const handleResponse = async (data: any) => {
// console.log("Project add response:", data);
// if (data?.message === "Project Duplicated successfully") {
// if (setWorkspaceProjects) {
// const allProjects = await getAllProjects(userId, organization);
// console.log("allProjects: ", allProjects);
// setWorkspaceProjects(allProjects);
// } else if (setRecentProjects) {
// const recentProjects = await recentlyViewed(organization, userId);
// console.log("recentProjects: ", recentProjects);
// setRecentProjects(recentProjects);
// }
// setIsSearchActive(false);
// } else {
// console.warn("Duplication failed or unexpected response.");
// }
// projectSocket.off("v1-project:response:Duplicate", handleResponse); // Clean up
// };
// projectSocket.on("v1-project:response:Duplicate", handleResponse);
// console.log("Emitting duplicate:", duplicateProjectData);
// }
// };
return <></>
}
export default ProjectSocketDev;

View File

@ -19,6 +19,7 @@ export const detectModifierKeys = (event: KeyboardEvent): string => {
// Handle special cases for keys with different representations
const normalizedKey = mainKey === " " ? "Space" : mainKey;
// Build the combination string
if (modifiers.length > 0 && normalizedKey) {
return `${modifiers.join("+")}+${normalizedKey}`;