import React, { useState, useEffect } from 'react'; import { ProjectMember, User, UserRole } from '../types'; import { UserPlus, Shield, Trash2, Search, CheckCircle2, XCircle, User as UserIcon, Crown } from 'lucide-react'; import { useLocalCollection } from '../hooks/useLocalCollection'; interface MemberManagerProps { projectId: string; ownerUid: string; currentUserUid: string; } const MemberManager: React.FC = ({ projectId, ownerUid, currentUserUid }) => { const { data: members, add, update, remove } = useLocalCollection(`members_${projectId}`); const [searchEmail, setSearchEmail] = useState(''); const [searchResult, setSearchResult] = useState(null); const [searchError, setSearchError] = useState(null); const [allUsers, setAllUsers] = useState([]); const isOwner = currentUserUid === ownerUid; useEffect(() => { // Fetch all users for search (ideally this is a backend search API, but we'll fetch entire mock users collection for now) fetch('/api/collections/users') .then(res => res.json()) .then(result => setAllUsers(result || [])) .catch(console.error); }, []); const handleSearch = async (e: React.FormEvent) => { e.preventDefault(); if (!searchEmail.trim()) return; setSearchError(null); setSearchResult(null); // Mock search against users collection if (searchEmail === 'mock@example.com') { setSearchResult({ uid: 'mock-1', name: 'Mock User', role: 'ENGINEER', avatar: '', email: 'mock@example.com' }); return; } const found = allUsers.find(u => u.email === searchEmail || u.name?.toLowerCase() === searchEmail.toLowerCase()); if (found) { if (members.some(m => m.uid === found.uid)) { setSearchError('This user is already a member of the project.'); } else { setSearchResult(found); } } else { setSearchError('User not found. For offline simulation, type "mock@example.com"'); } }; const handleAddMember = async (user: User) => { if (!user.uid) return; // We append the standard useLocalCollection ID to map it uniquely const memberData: ProjectMember & { id: string } = { id: user.uid, // Map uid to the collection's string ID uid: user.uid, name: user.name, role: user.role, avatar: user.avatar || null, joinedAt: new Date().toISOString() }; add(memberData); setSearchResult(null); setSearchEmail(''); }; const handleUpdateRole = async (memberUid: string, newRole: UserRole) => { // Map using memberUid as id update(memberUid, { role: newRole }); }; const handleRemoveMember = async (memberUid: string) => { if (memberUid === ownerUid) return; // Cannot remove owner if (!window.confirm('Are you sure you want to remove this member from the project?')) return; remove(memberUid); }; return (
{/* Add Member Section */} {isOwner && (

Add Team Member

setSearchEmail(e.target.value)} className="w-full pl-10 pr-4 py-2.5 bg-slate-50 border border-slate-200 rounded-xl focus:ring-2 focus:ring-blue-500 outline-none text-sm transition-all" />
{searchError && (
{searchError}
)} {searchResult && (
{searchResult.avatar ? ( ) : (
{searchResult.name.charAt(0)}
)}

{searchResult.name}

{searchResult.email}

)}
)} {/* Members List */}

Project Team

{members.length} Members
{members.map((member) => (
{member.avatar ? ( ) : (
{member.name.charAt(0)}
)} {member.uid === ownerUid && (
)}

{member.name}

{member.uid === currentUserUid && ( You )}

Joined {new Date(member.joinedAt).toLocaleDateString()}

{isOwner && member.uid !== ownerUid ? ( ) : ( {member.role} )}
{isOwner && member.uid !== ownerUid && ( )}
))}
); }; export default MemberManager;