125 lines
5.9 KiB
TypeScript
125 lines
5.9 KiB
TypeScript
import { useState } from "react";
|
|
import { useSceneContext } from "../../../../modules/scene/sceneContext";
|
|
import { getRelativeTime } from "../../../ui/collaboration/function/getRelativeTime";
|
|
import { KebabIcon } from "../../../icons/ExportCommonIcons";
|
|
import { getAvatarColorUsingUserID } from "../../../../modules/collaboration/functions/getAvatarColor";
|
|
import { deleteThreadApi } from "../../../../services/builder/collab/comments/deleteThreadApi";
|
|
import { useParams } from "react-router-dom";
|
|
import { useSocketStore } from "../../../../store/socket/useSocketStore";
|
|
import { getUserData } from "../../../../functions/getUserData";
|
|
import useThreadResponseHandler from "../../../../modules/collaboration/responseHandler/useThreadResponseHandler";
|
|
|
|
const ThreadProperties = () => {
|
|
const { threadStore, versionStore } = useSceneContext();
|
|
const { threads, setSelectedThread } = threadStore();
|
|
const { userId, organization } = getUserData();
|
|
const { selectedVersion } = versionStore();
|
|
const { projectId } = useParams();
|
|
const { threadSocket } = useSocketStore();
|
|
const [selectedChart, setSelectedChart] = useState<ThreadSchema | null>(null);
|
|
const [isKebabActive, setIsKebabActive] = useState<boolean>(false);
|
|
const { removeThreadFromScene } = useThreadResponseHandler();
|
|
const handleDeleteThread = (val: ThreadSchema) => {
|
|
if (!projectId) return;
|
|
|
|
const threadIdToDelete = val?.threadId;
|
|
|
|
if (!threadSocket?.connected) {
|
|
// API fallback
|
|
deleteThreadApi(projectId, threadIdToDelete, selectedVersion?.versionId || "").then(
|
|
(res) => {
|
|
if (res.message === "Thread deleted Successfully") {
|
|
removeThreadFromScene(res.data._id);
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
// SOCKET path
|
|
const deleteThreadPayload = {
|
|
projectId,
|
|
userId,
|
|
organization,
|
|
threadId: threadIdToDelete,
|
|
versionId: selectedVersion?.versionId || "",
|
|
};
|
|
|
|
threadSocket.emit("v1:thread:delete", deleteThreadPayload);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="global-properties-container">
|
|
{threads &&
|
|
threads.map((val) => {
|
|
const isMenuVisible =
|
|
selectedChart?.createdAt === val.createdAt && isKebabActive;
|
|
|
|
return (
|
|
<section key={val?.threadId} className="thread-section">
|
|
<div className="thread-card">
|
|
{/* Avatar */}
|
|
<div
|
|
className="thread-avatar"
|
|
style={{
|
|
backgroundColor: getAvatarColorUsingUserID(val.creatorId),
|
|
}}
|
|
>
|
|
{val?.creatorName?.charAt(0).toUpperCase()}
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="thread-content">
|
|
{/* Title + username */}
|
|
<div>
|
|
<div className="thread-title">{val.threadTitle}</div>
|
|
<div className="thread-username">{val.creatorName}</div>
|
|
</div>
|
|
|
|
{/* Last updated + kebab */}
|
|
<div className="thread-footer">
|
|
<div className="thread-time">
|
|
{getRelativeTime(val.createdAt)}
|
|
</div>
|
|
<button
|
|
className="thread-kebab-button"
|
|
onClick={() => {
|
|
// Toggle menu visibility per-thread
|
|
if (
|
|
selectedChart?.createdAt === val.createdAt &&
|
|
isKebabActive
|
|
) {
|
|
setIsKebabActive(false);
|
|
setSelectedChart(null);
|
|
} else {
|
|
setSelectedChart(val);
|
|
setIsKebabActive(true);
|
|
}
|
|
}}
|
|
>
|
|
<KebabIcon />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Kebab menu shown only for selected thread */}
|
|
{isMenuVisible && (
|
|
<div className="thread-menu">
|
|
<button onClick={() => setSelectedThread(val)}>Visible</button>
|
|
<button>Show in Scene</button>
|
|
{val.creatorId === userId && (
|
|
<button onClick={() => handleDeleteThread(val)}>
|
|
Delete
|
|
</button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</section>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ThreadProperties;
|