Enhance DashboardCard component: add createdAt prop and implement relative time display; create ProjectSocketDev component for socket event handling.
This commit is contained in:
parent
44b6b4daab
commit
5ba7457276
|
@ -6,16 +6,13 @@ import { useProjectName, useSocketStore } from "../../store/builder/store";
|
||||||
import { viewProject } from "../../services/dashboard/viewProject";
|
import { viewProject } from "../../services/dashboard/viewProject";
|
||||||
import OuterClick from "../../utils/outerClick";
|
import OuterClick from "../../utils/outerClick";
|
||||||
import { KebabIcon } from "../icons/ExportCommonIcons";
|
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 { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||||
import { duplicateProject } from "../../services/dashboard/duplicateProject";
|
|
||||||
|
|
||||||
interface DashBoardCardProps {
|
interface DashBoardCardProps {
|
||||||
projectName: string;
|
projectName: string;
|
||||||
thumbnail: any;
|
thumbnail: any;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
createdAt?: string
|
||||||
handleDeleteProject?: (projectId: string) => Promise<void>;
|
handleDeleteProject?: (projectId: string) => Promise<void>;
|
||||||
handleTrashDeleteProject?: (projectId: string) => Promise<void>;
|
handleTrashDeleteProject?: (projectId: string) => Promise<void>;
|
||||||
handleRestoreProject?: (projectId: string) => Promise<void>;
|
handleRestoreProject?: (projectId: string) => Promise<void>;
|
||||||
|
@ -24,6 +21,8 @@ interface DashBoardCardProps {
|
||||||
active?: string;
|
active?: string;
|
||||||
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
}
|
}
|
||||||
|
type RelativeTimeFormatUnit = any
|
||||||
|
|
||||||
|
|
||||||
const DashboardCard: React.FC<DashBoardCardProps> = ({
|
const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
projectName,
|
projectName,
|
||||||
|
@ -33,9 +32,9 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
handleDeleteProject,
|
handleDeleteProject,
|
||||||
handleRestoreProject,
|
handleRestoreProject,
|
||||||
handleTrashDeleteProject,
|
handleTrashDeleteProject,
|
||||||
setIsSearchActive,
|
|
||||||
handleDuplicateWorkspaceProject,
|
handleDuplicateWorkspaceProject,
|
||||||
handleDuplicateRecentProject
|
handleDuplicateRecentProject,
|
||||||
|
createdAt
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { setProjectName } = useProjectName();
|
const { setProjectName } = useProjectName();
|
||||||
|
@ -44,10 +43,8 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
const [renameValue, setRenameValue] = useState(projectName);
|
const [renameValue, setRenameValue] = useState(projectName);
|
||||||
const [isRenaming, setIsRenaming] = useState(false);
|
const [isRenaming, setIsRenaming] = useState(false);
|
||||||
const { projectSocket } = useSocketStore();
|
const { projectSocket } = useSocketStore();
|
||||||
|
|
||||||
const kebabRef = useRef<HTMLDivElement>(null);
|
const kebabRef = useRef<HTMLDivElement>(null);
|
||||||
const savedTheme = localStorage.getItem("theme") ?? "light";
|
const savedTheme = localStorage.getItem("theme") ?? "light";
|
||||||
|
|
||||||
const navigateToProject = async (e: any) => {
|
const navigateToProject = async (e: any) => {
|
||||||
if (active && active == "trash") return
|
if (active && active == "trash") return
|
||||||
try {
|
try {
|
||||||
|
@ -68,9 +65,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
await handleDeleteProject(projectId);
|
await handleDeleteProject(projectId);
|
||||||
}
|
}
|
||||||
else if (handleTrashDeleteProject) {
|
else if (handleTrashDeleteProject) {
|
||||||
console.log('projectId:dashboard ', projectId);
|
await handleTrashDeleteProject(projectId);
|
||||||
// await handleTrashDeleteProject(projectId);
|
|
||||||
handleTrashDeleteProject(projectId);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case "restore":
|
case "restore":
|
||||||
|
@ -146,7 +141,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
setMenuVisible: () => setIsKebabOpen(false),
|
setMenuVisible: () => setIsKebabOpen(false),
|
||||||
});
|
});
|
||||||
const handleProjectName = async (projectName: string) => {
|
const handleProjectName = async (projectName: string) => {
|
||||||
setProjectName(projectName);
|
// setProjectName(projectName);
|
||||||
setRenameValue(projectName)
|
setRenameValue(projectName)
|
||||||
if (!projectId) return
|
if (!projectId) return
|
||||||
// localStorage.setItem("projectName", newName);
|
// 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 (
|
return (
|
||||||
<button
|
<button
|
||||||
className="dashboard-card-container"
|
className="dashboard-card-container"
|
||||||
|
@ -211,6 +234,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
<input
|
<input
|
||||||
value={renameValue}
|
value={renameValue}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
e.stopPropagation(); // Prevents click from bubbling up
|
||||||
handleProjectName(e.target.value);
|
handleProjectName(e.target.value);
|
||||||
}}
|
}}
|
||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
|
@ -228,8 +252,8 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||||
) : (
|
) : (
|
||||||
<span>{renameValue}</span>
|
<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>
|
||||||
<div className="users-list-container" ref={kebabRef}>
|
<div className="users-list-container" ref={kebabRef}>
|
||||||
<div className="user-profile">
|
<div className="user-profile">
|
||||||
|
|
|
@ -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;
|
|
@ -19,6 +19,7 @@ export const detectModifierKeys = (event: KeyboardEvent): string => {
|
||||||
// Handle special cases for keys with different representations
|
// Handle special cases for keys with different representations
|
||||||
const normalizedKey = mainKey === " " ? "Space" : mainKey;
|
const normalizedKey = mainKey === " " ? "Space" : mainKey;
|
||||||
|
|
||||||
|
|
||||||
// Build the combination string
|
// Build the combination string
|
||||||
if (modifiers.length > 0 && normalizedKey) {
|
if (modifiers.length > 0 && normalizedKey) {
|
||||||
return `${modifiers.join("+")}+${normalizedKey}`;
|
return `${modifiers.join("+")}+${normalizedKey}`;
|
||||||
|
|
Loading…
Reference in New Issue