Implement collaboration features with user access management and email invitation functionality

This commit is contained in:
2025-06-25 09:35:47 +05:30
parent 17ec72e283
commit 13a2648e83
8 changed files with 307 additions and 83 deletions

View File

@@ -1,72 +1,143 @@
import React, { useState } from "react";
import { getSearchUsers } from "../../../services/factoryBuilder/collab/getSearchUsers";
import { useParams } from "react-router-dom";
import { shareProject } from "../../../services/factoryBuilder/collab/shareProject";
import { getUserData } from "../../../functions/getUserData";
const MultiEmailInvite: React.FC = () => {
const [emails, setEmails] = useState<string[]>([]);
interface UserData {
_id: string;
Email: string;
userName: string;
}
interface MultiEmailProps {
searchedEmail: UserData[];
setSearchedEmail: React.Dispatch<React.SetStateAction<UserData[]>>
users: any,
getData: any,
}
const MultiEmailInvite: React.FC<MultiEmailProps> = ({ searchedEmail, setSearchedEmail, users, getData }) => {
console.log('users: ', users);
const [emails, setEmails] = useState<any>([]);
const [inputFocus, setInputFocus] = useState(false);
const [inputValue, setInputValue] = useState("");
const { projectId } = useParams();
const { userId } = getUserData();
const handleAddEmail = () => {
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);
// Validate email
if (!trimmedEmail || !validateEmail(trimmedEmail)) {
alert("Please enter a valid email address.");
return;
}
console.log('alreadyExistsInEmails: ', alreadyExistsInEmails);
console.log('alreadyExistsInUsers:', alreadyExistsInUsers);
// Check for duplicates
if (emails.includes(trimmedEmail)) {
alert("This email has already been added.");
return;
}
if (isNotCurrentUser && !alreadyExistsInEmails && !alreadyExistsInUsers) {
return [...prev, selectedUser];
}
// Add email to the list
setEmails([...emails, trimmedEmail]);
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 handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" || e.key === ",") {
e.preventDefault();
handleAddEmail();
if (trimmedEmail.length < 3) return;
try {
const searchedMail = await getSearchUsers(trimmedEmail);
console.log('searchedMail: ', searchedMail);
const filteredEmail = searchedMail.sharchMail?.filtered;
console.log('filteredEmail: ', filteredEmail);
if (filteredEmail) {
setSearchedEmail(filteredEmail)
}
} catch (error) {
console.error("Failed to search mail:", error);
}
};
const handleRemoveEmail = (emailToRemove: string) => {
setEmails(emails.filter((email) => email !== emailToRemove));
const handleKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter" || e.key === "," && searchedEmail.length > 0) {
e.preventDefault();
handleAddEmail(searchedEmail[0]);
}
};
const handleRemoveEmail = (idToRemove: string) => {
setEmails((prev: any) => prev.filter((email: any) => email._id !== idToRemove));
};
const validateEmail = (email: string) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const [inputFocus, setInputFocus] = useState(false);
const handleInvite = () => {
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([])
});
setTimeout(() => {
getData()
}, 1000);
} catch (error) {
console.error("General error:", error);
}
};
return (
<div className="multi-email-invite-input-container">
<div className={`multi-email-invite-input${inputFocus ? " active" : ""}`}>
{emails.map((email, index) => (
{emails.map((email: any, index: number) => (
<div key={index} className="entered-emails">
{email}
<span onClick={() => handleRemoveEmail(email)}>&times;</span>
{email.Email}
<span onClick={() => handleRemoveEmail(email._id)}>&times;</span>
</div>
))}
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onChange={(e) => handleSearchMail(e)}
onFocus={() => setInputFocus(true)}
onBlur={() => setInputFocus(false)}
// onBlur={() => setInputFocus(false)}
onKeyDown={handleKeyDown}
placeholder="Enter email and press Enter or comma to seperate"
/>
</div>
<div onClick={handleAddEmail} className="invite-button">
<div onClick={handleInvite} className="invite-button">
Invite
</div>
<div className="users-list-container">
{/* list available users */}
</div>
{inputFocus && inputValue.length > 0 && searchedEmail && searchedEmail.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}
</div>
))}
</div>
)}
</div>
);
};