Refactor: Update project handling and sharing functionalities; integrate shared projects retrieval; enhance user data structure and loading mechanisms; improve input handling in MultiEmailInvite component; adjust wall generation callbacks in DXF processing.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useRef, useEffect } from "react";
|
||||
import React, { useState, useRef, useEffect, act } from "react";
|
||||
import img from "../../assets/image/image.png";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { getUserData } from "../../functions/getUserData";
|
||||
@@ -14,13 +14,15 @@ interface DashBoardCardProps {
|
||||
projectId: string;
|
||||
createdAt?: string;
|
||||
isViewed?: string;
|
||||
createdBy?: { _id: string, userName: string };
|
||||
handleDeleteProject?: (projectId: string) => Promise<void>;
|
||||
handleTrashDeleteProject?: (projectId: string) => Promise<void>;
|
||||
handleRestoreProject?: (projectId: string) => Promise<void>;
|
||||
handleDuplicateWorkspaceProject?: (
|
||||
projectId: string,
|
||||
projectName: string,
|
||||
thumbnail: string
|
||||
thumbnail: string,
|
||||
userId?: string
|
||||
) => Promise<void>;
|
||||
handleDuplicateRecentProject?: (
|
||||
projectId: string,
|
||||
@@ -31,6 +33,7 @@ interface DashBoardCardProps {
|
||||
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
setRecentDuplicateData?: React.Dispatch<React.SetStateAction<Object>>;
|
||||
setProjectDuplicateData?: React.Dispatch<React.SetStateAction<Object>>;
|
||||
setActiveFolder?: React.Dispatch<React.SetStateAction<string>>;
|
||||
}
|
||||
type RelativeTimeFormatUnit = any;
|
||||
|
||||
@@ -45,8 +48,10 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
handleDuplicateWorkspaceProject,
|
||||
handleDuplicateRecentProject,
|
||||
createdAt,
|
||||
createdBy,
|
||||
setRecentDuplicateData,
|
||||
setProjectDuplicateData,
|
||||
setActiveFolder
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const { setProjectName } = useProjectName();
|
||||
@@ -59,10 +64,18 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
const kebabRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const navigateToProject = async (e: any) => {
|
||||
console.log('active: ', active);
|
||||
if (active && active == "trash") return;
|
||||
setLoadingProgress(1)
|
||||
setProjectName(projectName);
|
||||
navigate(`/${projectId}`);
|
||||
try {
|
||||
const viewProjects = await viewProject(organization, projectId, userId)
|
||||
console.log('viewProjects: ', viewProjects);
|
||||
console.log('projectName: ', projectName);
|
||||
setLoadingProgress(1)
|
||||
setProjectName(projectName);
|
||||
navigate(`/${projectId}`);
|
||||
} catch {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
const handleOptionClick = async (option: string) => {
|
||||
@@ -81,11 +94,18 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
break;
|
||||
case "open in new tab":
|
||||
try {
|
||||
await viewProject(organization, projectId, userId);
|
||||
setProjectName(projectName);
|
||||
setIsKebabOpen(false);
|
||||
if (active === "shared" && createdBy) {
|
||||
console.log("ihreq");
|
||||
const newTab = await viewProject(organization, projectId, createdBy?._id);
|
||||
console.log('newTab: ', newTab);
|
||||
} else {
|
||||
const newTab = await viewProject(organization, projectId, userId);
|
||||
console.log('newTab: ', newTab);
|
||||
setProjectName(projectName);
|
||||
setIsKebabOpen(false);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error opening project in new tab:", error);
|
||||
|
||||
}
|
||||
window.open(`/${projectId}`, "_blank");
|
||||
break;
|
||||
@@ -100,13 +120,17 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
projectName,
|
||||
thumbnail,
|
||||
});
|
||||
await handleDuplicateWorkspaceProject(projectId, projectName, thumbnail);
|
||||
await handleDuplicateWorkspaceProject(projectId, projectName, thumbnail, userId);
|
||||
if (active === "shared" && setActiveFolder) {
|
||||
setActiveFolder("myProjects")
|
||||
}
|
||||
} else if (handleDuplicateRecentProject) {
|
||||
setRecentDuplicateData &&
|
||||
setRecentDuplicateData({
|
||||
projectId,
|
||||
projectName,
|
||||
thumbnail,
|
||||
userId
|
||||
});
|
||||
await handleDuplicateRecentProject(projectId, projectName, thumbnail);
|
||||
}
|
||||
@@ -128,7 +152,6 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
try {
|
||||
const projects = await getAllProjects(userId, organization);
|
||||
if (!projects || !projects.Projects) return;
|
||||
// console.log("projects: ", projects);
|
||||
let projectUuid = projects.Projects.find(
|
||||
(val: any) => val.projectUuid === projectId || val._id === projectId
|
||||
);
|
||||
@@ -173,6 +196,19 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
return "just now";
|
||||
}
|
||||
|
||||
const kebabOptionsMap: Record<string, string[]> = {
|
||||
default: ["rename", "delete", "duplicate", "open in new tab"],
|
||||
trash: ["restore", "delete"],
|
||||
shared: ["duplicate", "open in new tab"],
|
||||
};
|
||||
|
||||
const getOptions = () => {
|
||||
if (active === "trash") return kebabOptionsMap.trash;
|
||||
if (active === "shared") return kebabOptionsMap.shared;
|
||||
if (createdBy && createdBy?._id !== userId) return kebabOptionsMap.shared;
|
||||
return kebabOptionsMap.default;
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
className="dashboard-card-container"
|
||||
@@ -212,13 +248,12 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
<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">
|
||||
{userName ? userName.charAt(0).toUpperCase() : "A"}
|
||||
{(!createdBy) ? userName ? userName?.charAt(0).toUpperCase() : "A" : createdBy?.userName?.charAt(0).toUpperCase()}
|
||||
</div>
|
||||
<button
|
||||
className="kebab-wrapper"
|
||||
@@ -232,29 +267,9 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{isKebabOpen && active !== "trash" && (
|
||||
{isKebabOpen && (
|
||||
<div className="kebab-options-wrapper">
|
||||
{["rename", "delete", "duplicate", "open in new tab"].map(
|
||||
(option) => (
|
||||
<button
|
||||
key={option}
|
||||
className="option"
|
||||
title={""}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleOptionClick(option);
|
||||
}}
|
||||
>
|
||||
{option}
|
||||
</button>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{isKebabOpen && active && active == "trash" && (
|
||||
<div className="kebab-options-wrapper">
|
||||
{["restore", "delete"].map((option) => (
|
||||
{getOptions().map((option) => (
|
||||
<button
|
||||
key={option}
|
||||
className="option"
|
||||
|
||||
@@ -13,7 +13,7 @@ interface Project {
|
||||
_id: string;
|
||||
projectName: string;
|
||||
thumbnail: string;
|
||||
createdBy: string;
|
||||
createdBy: { _id: string, userName: string };
|
||||
projectUuid?: string;
|
||||
createdAt: string;
|
||||
isViewed?: string
|
||||
@@ -34,7 +34,8 @@ const DashboardHome: React.FC = () => {
|
||||
const fetchRecentProjects = async () => {
|
||||
try {
|
||||
const projects = await recentlyViewed(organization, userId);
|
||||
|
||||
console.log('projects: ', projects);
|
||||
|
||||
if (JSON.stringify(projects) !== JSON.stringify(recentProjects)) {
|
||||
setRecentProjects(projects);
|
||||
}
|
||||
@@ -126,7 +127,8 @@ const DashboardHome: React.FC = () => {
|
||||
projectName={project.projectName}
|
||||
thumbnail={project.thumbnail}
|
||||
projectId={project._id}
|
||||
createdAt={project.isViewed}
|
||||
createdBy={project.createdBy}
|
||||
createdAt={project.createdAt}
|
||||
handleDeleteProject={handleDeleteProject}
|
||||
handleDuplicateRecentProject={handleDuplicateRecentProject}
|
||||
setRecentDuplicateData={setRecentDuplicateData}
|
||||
|
||||
@@ -7,6 +7,8 @@ import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||
import { searchProject } from "../../services/dashboard/searchProjects";
|
||||
import { deleteProject } from "../../services/dashboard/deleteProject";
|
||||
import ProjectSocketRes from "./socket/projectSocketRes.dev";
|
||||
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
|
||||
import { duplicateProject } from "../../services/dashboard/duplicateProject";
|
||||
|
||||
interface Project {
|
||||
_id: string;
|
||||
@@ -25,12 +27,25 @@ const DashboardProjects: React.FC = () => {
|
||||
const [workspaceProjects, setWorkspaceProjects] = useState<WorkspaceProjects>(
|
||||
{}
|
||||
);
|
||||
const [sharedwithMeProject, setSharedWithMeProjects] = useState<any>([])
|
||||
const [projectDuplicateData, setProjectDuplicateData] = useState<Object>({});
|
||||
const [isSearchActive, setIsSearchActive] = useState<boolean>(false);
|
||||
const [activeFolder, setActiveFolder] = useState<string>("myProjects");
|
||||
const { projectSocket } = useSocketStore();
|
||||
const { userId, organization } = getUserData();
|
||||
|
||||
const handleProjectsSearch = async (inputValue: string) => {
|
||||
if (!inputValue.trim()) {
|
||||
setIsSearchActive(false);
|
||||
return;
|
||||
}
|
||||
if (!setWorkspaceProjects || !setIsSearchActive) return;
|
||||
|
||||
const searchedProject = await searchProject(organization, userId, inputValue);
|
||||
setIsSearchActive(true);
|
||||
setWorkspaceProjects(searchedProject.message ? {} : searchedProject);
|
||||
};
|
||||
|
||||
const fetchAllProjects = async () => {
|
||||
try {
|
||||
const projects = await getAllProjects(userId, organization);
|
||||
@@ -44,18 +59,6 @@ const DashboardProjects: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleProjectsSearch = async (inputValue: string) => {
|
||||
if (!inputValue.trim()) {
|
||||
setIsSearchActive(false);
|
||||
return;
|
||||
}
|
||||
if (!setWorkspaceProjects || !setIsSearchActive) return;
|
||||
|
||||
const searchedProject = await searchProject(organization, userId, inputValue);
|
||||
setIsSearchActive(true);
|
||||
setWorkspaceProjects(searchedProject.message ? {} : searchedProject);
|
||||
};
|
||||
|
||||
const handleDeleteProject = async (projectId: any) => {
|
||||
try {
|
||||
// const deletedProject = await deleteProject(
|
||||
@@ -97,18 +100,9 @@ const DashboardProjects: React.FC = () => {
|
||||
const handleDuplicateWorkspaceProject = async (
|
||||
projectId: string,
|
||||
projectName: string,
|
||||
thumbnail: string
|
||||
thumbnail: string,
|
||||
) => {
|
||||
// await handleDuplicateProjects({
|
||||
// userId,
|
||||
// organization,
|
||||
// projectId,
|
||||
// projectName,
|
||||
// projectSocket,
|
||||
// thumbnail,
|
||||
// setWorkspaceProjects,
|
||||
// setIsSearchActive
|
||||
// });
|
||||
|
||||
const duplicateProjectData = {
|
||||
userId,
|
||||
thumbnail,
|
||||
@@ -121,9 +115,7 @@ const DashboardProjects: React.FC = () => {
|
||||
|
||||
const renderProjects = () => {
|
||||
if (activeFolder !== "myProjects") return null;
|
||||
|
||||
const projectList = workspaceProjects[Object.keys(workspaceProjects)[0]];
|
||||
|
||||
if (!projectList?.length) {
|
||||
return <div className="empty-state">No projects found</div>;
|
||||
}
|
||||
@@ -143,12 +135,49 @@ const DashboardProjects: React.FC = () => {
|
||||
));
|
||||
};
|
||||
|
||||
const renderSharedProjects = () => {
|
||||
return sharedwithMeProject?.map((project: any) => (
|
||||
<DashboardCard
|
||||
key={project._id}
|
||||
projectName={project.projectName}
|
||||
thumbnail={project.thumbnail}
|
||||
projectId={project._id}
|
||||
createdAt={project.createdAt}
|
||||
setIsSearchActive={setIsSearchActive}
|
||||
active="shared"
|
||||
createdBy={project.createdBy}
|
||||
setProjectDuplicateData={setProjectDuplicateData}
|
||||
handleDuplicateWorkspaceProject={handleDuplicateWorkspaceProject}
|
||||
setActiveFolder={setActiveFolder}
|
||||
/>
|
||||
));
|
||||
};
|
||||
|
||||
|
||||
const sharedProject = async () => {
|
||||
try {
|
||||
const sharedWithMe = await sharedWithMeProjects();
|
||||
console.log('sharedWithMe: ', sharedWithMe);
|
||||
setSharedWithMeProjects(sharedWithMe)
|
||||
} catch {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSearchActive) {
|
||||
fetchAllProjects();
|
||||
}
|
||||
}, [isSearchActive]);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeFolder === "shared") {
|
||||
sharedProject()
|
||||
}
|
||||
}, [activeFolder])
|
||||
|
||||
|
||||
return (
|
||||
<div className="dashboard-home-container">
|
||||
<DashboardNavBar
|
||||
@@ -171,7 +200,8 @@ const DashboardProjects: React.FC = () => {
|
||||
Shared with me
|
||||
</button>
|
||||
</div>
|
||||
<div className="cards-container">{renderProjects()}</div>
|
||||
<div className="cards-container">{activeFolder == "myProjects" ? renderProjects() : renderSharedProjects()}</div>
|
||||
|
||||
{projectDuplicateData && Object.keys(projectDuplicateData).length > 0 && (
|
||||
<ProjectSocketRes
|
||||
setIsSearchActive={setIsSearchActive}
|
||||
@@ -183,4 +213,6 @@ const DashboardProjects: React.FC = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DashboardProjects;
|
||||
export default DashboardProjects;
|
||||
|
||||
|
||||
|
||||
@@ -14,12 +14,24 @@ interface Project {
|
||||
createdAt: string;
|
||||
isViewed?: string
|
||||
}
|
||||
interface RecentProject {
|
||||
_id: string;
|
||||
projectName: string;
|
||||
thumbnail: string;
|
||||
createdBy: { _id: string, userName: string };
|
||||
projectUuid?: string;
|
||||
createdAt: string;
|
||||
isViewed?: string
|
||||
}
|
||||
|
||||
interface RecentProjectData {
|
||||
[key: string]: RecentProject[];
|
||||
}
|
||||
interface ProjectsData {
|
||||
[key: string]: Project[];
|
||||
}
|
||||
interface ProjectSocketResProps {
|
||||
setRecentProjects?: React.Dispatch<React.SetStateAction<ProjectsData>>;
|
||||
setRecentProjects?: React.Dispatch<React.SetStateAction<RecentProjectData>>;
|
||||
setWorkspaceProjects?: React.Dispatch<React.SetStateAction<ProjectsData>>;
|
||||
setIsSearchActive?: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}
|
||||
@@ -52,7 +64,7 @@ const ProjectSocketRes = ({
|
||||
};
|
||||
|
||||
const handleDuplicate = async (data: any) => {
|
||||
// console.log("Project duplicate response:", data);
|
||||
console.log("Project duplicate response:", data);
|
||||
if (data?.message === "Project Duplicated successfully") {
|
||||
if (setWorkspaceProjects) {
|
||||
const allProjects = await getAllProjects(userId, organization);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useProjectName } from "../../store/builder/store";
|
||||
import { getAllProjects } from "../../services/dashboard/getAllProjects";
|
||||
import { useComparisonProduct } from "../../store/simulation/useSimulationStore";
|
||||
import { getUserData } from "../../functions/getUserData";
|
||||
import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject";
|
||||
|
||||
interface LoadingPageProps {
|
||||
progress: number; // Expect progress as a percentage (0-100)
|
||||
@@ -18,19 +19,35 @@ const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
|
||||
const { userId, organization } = getUserData();
|
||||
|
||||
const validatedProgress = Math.min(100, Math.max(0, progress));
|
||||
|
||||
useEffect(() => {
|
||||
if (!userId) return;
|
||||
if (!userId) {
|
||||
console.error("User data not found in localStorage");
|
||||
return;
|
||||
}
|
||||
|
||||
getAllProjects(userId, organization).then((projects) => {
|
||||
if (!projects || !projects.Projects) return;
|
||||
const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
|
||||
if (filterProject) {
|
||||
setProjectName(filterProject.projectName);
|
||||
const fetchProjects = async () => {
|
||||
try {
|
||||
const projects = await getAllProjects(userId, organization);
|
||||
const shared = await sharedWithMeProjects();
|
||||
|
||||
const allProjects = [...(projects?.Projects || []), ...(shared || [])];
|
||||
|
||||
const matchedProject = allProjects.find(
|
||||
(val: any) => val.projectUuid === projectId || val._id === projectId
|
||||
);
|
||||
|
||||
if (matchedProject) {
|
||||
setProjectName(matchedProject.projectName);
|
||||
|
||||
} else {
|
||||
console.warn("Project not found with given ID:", projectId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching projects:", error);
|
||||
}
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
};
|
||||
|
||||
fetchProjects();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -12,7 +12,7 @@ const SelectFloorPlan: React.FC = () => {
|
||||
// Access layout state and state setters
|
||||
const { currentLayout, setLayout } = useLayoutStore();
|
||||
// Access DXF-related states and setters
|
||||
const { setDfxUploaded, setDfxGenerate, setObjValue, objValue } =
|
||||
const { setDfxUploaded, setDxfWallGenerate, setObjValue, objValue } =
|
||||
useDfxUpload();
|
||||
const { activeLayer } = useActiveLayer();
|
||||
const { wallThickness, wallHeight, insideMaterial, outsideMaterial } = useBuilderStore();
|
||||
@@ -63,7 +63,7 @@ const SelectFloorPlan: React.FC = () => {
|
||||
if (parsedFile !== undefined) {
|
||||
getWallPointsFromBlueprint({
|
||||
parsedData: parsedFile,
|
||||
setDfxGenerate,
|
||||
setDxfWallGenerate,
|
||||
objValue,
|
||||
wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState } from "react";
|
||||
import { getSearchUsers } from "../../../services/factoryBuilder/collab/getSearchUsers";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { getSearchUsers } from "../../../services/factoryBuilder/collab/getSearchUsers";
|
||||
import { shareProject } from "../../../services/factoryBuilder/collab/shareProject";
|
||||
import { getUserData } from "../../../functions/getUserData";
|
||||
|
||||
@@ -11,121 +12,120 @@ interface UserData {
|
||||
}
|
||||
|
||||
interface MultiEmailProps {
|
||||
users: any,
|
||||
getData: any,
|
||||
users: Array<any>;
|
||||
getData: () => void;
|
||||
}
|
||||
|
||||
const MultiEmailInvite: React.FC<MultiEmailProps> = ({ users, getData }) => {
|
||||
const [emails, setEmails] = useState<any>([]);
|
||||
const [searchedEmail, setSearchedEmail] = useState<UserData[]>([]);
|
||||
const [inputFocus, setInputFocus] = useState(false);
|
||||
const [selectedUsers, setSelectedUsers] = useState<UserData[]>([]);
|
||||
const [searchResults, setSearchResults] = useState<UserData[]>([]);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
|
||||
const { projectId } = useParams();
|
||||
const { userId } = getUserData();
|
||||
|
||||
const handleAddEmail = async (selectedUser: UserData) => {
|
||||
if (!projectId || !selectedUser) return
|
||||
const trimmedEmail = inputValue.trim();
|
||||
setEmails((prev: any[]) => {
|
||||
if (!selectedUser) return prev;
|
||||
const isNotCurrentUser = selectedUser._id !== userId;
|
||||
const alreadyExistsInEmails = prev.some(email => email._id === selectedUser._id);
|
||||
const alreadyExistsInUsers = users.some((val: any) => val.userId === selectedUser._id);
|
||||
if (isNotCurrentUser && !alreadyExistsInEmails && !alreadyExistsInUsers) {
|
||||
return [...prev, selectedUser];
|
||||
}
|
||||
|
||||
return prev;
|
||||
});
|
||||
setInputValue(""); // Clear the input field after adding
|
||||
};
|
||||
const handleSearchMail = async (e: any) => {
|
||||
setInputValue(e.target.value);
|
||||
const trimmedEmail = e.target.value.trim();
|
||||
const handleSearchInput = async (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = e.target.value.trim();
|
||||
setInputValue(value);
|
||||
|
||||
if (value.length < 3) return;
|
||||
|
||||
if (trimmedEmail.length < 3) return;
|
||||
try {
|
||||
const searchedMail = await getSearchUsers(trimmedEmail);
|
||||
const filteredEmail = searchedMail.sharchMail?.filtered;
|
||||
if (filteredEmail) {
|
||||
setSearchedEmail(filteredEmail)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to search mail:", error);
|
||||
const result = await getSearchUsers(value);
|
||||
const filtered = result?.sharchMail?.filtered || [];
|
||||
setSearchResults(filtered);
|
||||
} catch (err) {
|
||||
console.error("Search failed:", err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAddUser = (user: UserData) => {
|
||||
if (!user || user._id === userId) return;
|
||||
|
||||
const handleKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter" || e.key === "," && searchedEmail.length > 0) {
|
||||
const isAlreadySelected = selectedUsers.some(u => u._id === user._id);
|
||||
const isAlreadyShared = users.some(u => u.userId === user._id);
|
||||
|
||||
if (!isAlreadySelected && !isAlreadyShared) {
|
||||
setSelectedUsers(prev => [...prev, user]);
|
||||
}
|
||||
|
||||
setInputValue("");
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if ((e.key === "Enter" || e.key === ",") && searchResults.length > 0) {
|
||||
e.preventDefault();
|
||||
handleAddEmail(searchedEmail[0]);
|
||||
handleAddUser(searchResults[0]);
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveEmail = (idToRemove: string) => {
|
||||
setEmails((prev: any) => prev.filter((email: any) => email._id !== idToRemove));
|
||||
const handleRemoveUser = (userIdToRemove: string) => {
|
||||
setSelectedUsers(prev => prev.filter(user => user._id !== userIdToRemove));
|
||||
};
|
||||
|
||||
|
||||
const validateEmail = (email: string) => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
||||
const handleInvite = () => {
|
||||
const handleAddEmail = async () => {
|
||||
if (!projectId) return;
|
||||
try {
|
||||
emails.forEach((user: any) => {
|
||||
shareProject(user._id, projectId)
|
||||
.then((res) => {
|
||||
console.log("sharedProject:", res);
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error sharing project:", err);
|
||||
});
|
||||
setEmails([])
|
||||
setInputValue("")
|
||||
});
|
||||
setTimeout(() => {
|
||||
getData()
|
||||
}, 1000);
|
||||
try {
|
||||
await Promise.all(
|
||||
selectedUsers.map(user =>
|
||||
shareProject(user._id, projectId)
|
||||
.then(res => console.log("Shared:", res))
|
||||
.catch(err => console.error("Share error:", err))
|
||||
)
|
||||
);
|
||||
|
||||
setSelectedUsers([]);
|
||||
setInputValue("");
|
||||
setTimeout(getData, 1000);
|
||||
} catch (error) {
|
||||
console.error("General error:", error);
|
||||
console.error("Invite error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="multi-email-invite-input-container">
|
||||
<div className={`multi-email-invite-input${inputFocus ? " active" : ""}`}>
|
||||
{emails.map((email: any, index: number) => (
|
||||
<div key={index} className="entered-emails">
|
||||
{email.Email}
|
||||
<span onClick={() => handleRemoveEmail(email._id)}>×</span>
|
||||
<div className={`multi-email-invite-input${isFocused ? " active" : ""}`}>
|
||||
{selectedUsers.map(user => (
|
||||
<div key={user._id} className="entered-emails">
|
||||
{user.Email}
|
||||
<span onClick={() => handleRemoveUser(user._id)}>×</span>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => handleSearchMail(e)}
|
||||
onFocus={() => setInputFocus(true)}
|
||||
// onBlur={() => setInputFocus(false)}
|
||||
onChange={handleSearchInput}
|
||||
onFocus={() => setIsFocused(true)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Enter email and press Enter or comma to seperate"
|
||||
placeholder="Enter email and press Enter or comma"
|
||||
/>
|
||||
</div>
|
||||
<div onClick={handleInvite} className="invite-button">
|
||||
|
||||
<div onClick={handleAddEmail} className="invite-button">
|
||||
Add
|
||||
</div>
|
||||
{inputFocus && inputValue.length > 2 && searchedEmail && searchedEmail.length > 0 && (
|
||||
|
||||
{isFocused && inputValue.length > 2 && searchResults.length > 0 && (
|
||||
<div className="users-list-container">
|
||||
{/* list available users here */}
|
||||
{searchedEmail.map((val: any, i: any) => (
|
||||
<div onClick={(e) => {
|
||||
handleAddEmail(val)
|
||||
setInputFocus(false)
|
||||
}} key={i} >
|
||||
{val?.Email}
|
||||
{searchResults.map(user => (
|
||||
<div
|
||||
key={user._id}
|
||||
onClick={() => {
|
||||
handleAddUser(user);
|
||||
setIsFocused(false);
|
||||
}}
|
||||
>
|
||||
{user.Email}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user