import { useState, useEffect, useRef } from 'react' import { X, Trash2, ChevronDown, Check } from 'lucide-react' import { useLanguage } from '../i18n/LanguageContext' import { api } from '../utils/api' import Modal from './Modal' import SlidePanel from './SlidePanel' import CollapsibleSection from './CollapsibleSection' import StatusBadge from './StatusBadge' const ROLES = [ { value: 'manager', label: 'Manager' }, { value: 'approver', label: 'Approver' }, { value: 'publisher', label: 'Publisher' }, { value: 'content_creator', label: 'Content Creator' }, { value: 'producer', label: 'Producer' }, { value: 'designer', label: 'Designer' }, { value: 'content_writer', label: 'Content Writer' }, { value: 'social_media_manager', label: 'Social Media Manager' }, { value: 'photographer', label: 'Photographer' }, { value: 'videographer', label: 'Videographer' }, { value: 'strategist', label: 'Strategist' }, ] const ALL_MODULES = ['marketing', 'projects', 'finance'] const MODULE_LABELS = { marketing: 'Marketing', projects: 'Projects', finance: 'Finance' } const MODULE_COLORS = { marketing: { on: 'bg-emerald-100 text-emerald-700 border-emerald-300', off: 'bg-gray-100 text-gray-400 border-gray-200' }, projects: { on: 'bg-blue-100 text-blue-700 border-blue-300', off: 'bg-gray-100 text-gray-400 border-gray-200' }, finance: { on: 'bg-amber-100 text-amber-700 border-amber-300', off: 'bg-gray-100 text-gray-400 border-gray-200' }, } export default function TeamMemberPanel({ member, isEditingSelf, onClose, onSave, onDelete, canManageTeam, userRole, teams, brands: brandsList }) { const { t, lang } = useLanguage() const [form, setForm] = useState({}) const [dirty, setDirty] = useState(false) const [saving, setSaving] = useState(false) const [showDeleteConfirm, setShowDeleteConfirm] = useState(false) const [showBrandsDropdown, setShowBrandsDropdown] = useState(false) const brandsDropdownRef = useRef(null) // Workload state (loaded internally) const [memberTasks, setMemberTasks] = useState([]) const [memberPosts, setMemberPosts] = useState([]) const [loadingWorkload, setLoadingWorkload] = useState(false) const memberId = member?._id || member?.id const isCreateMode = !memberId useEffect(() => { if (member) { setForm({ name: member.name || '', email: member.email || '', password: '', role: member.team_role || member.role || 'content_writer', brands: Array.isArray(member.brands) ? member.brands : [], phone: member.phone || '', modules: Array.isArray(member.modules) ? member.modules : ALL_MODULES, team_ids: Array.isArray(member.teams) ? member.teams.map(t => t.id) : [], }) setDirty(isCreateMode) if (!isCreateMode) loadWorkload() } }, [member]) const loadWorkload = async () => { if (!memberId) return setLoadingWorkload(true) try { const [tasksRes, postsRes] = await Promise.allSettled([ api.get(`/tasks?assignedTo=${memberId}`), api.get(`/posts?assignedTo=${memberId}`), ]) setMemberTasks(tasksRes.status === 'fulfilled' ? (tasksRes.value.data || tasksRes.value || []) : []) setMemberPosts(postsRes.status === 'fulfilled' ? (postsRes.value.data || postsRes.value || []) : []) } catch { setMemberTasks([]) setMemberPosts([]) } finally { setLoadingWorkload(false) } } if (!member) return null const update = (field, value) => { setForm(f => ({ ...f, [field]: value })) setDirty(true) } // Close brands dropdown on outside click useEffect(() => { const handleClickOutside = (e) => { if (brandsDropdownRef.current && !brandsDropdownRef.current.contains(e.target)) { setShowBrandsDropdown(false) } } if (showBrandsDropdown) document.addEventListener('mousedown', handleClickOutside) return () => document.removeEventListener('mousedown', handleClickOutside) }, [showBrandsDropdown]) const toggleBrand = (brandName) => { const current = form.brands || [] update('brands', current.includes(brandName) ? current.filter(b => b !== brandName) : [...current, brandName] ) } const handleSave = async () => { setSaving(true) try { await onSave(isCreateMode ? null : memberId, { name: form.name, email: form.email, password: form.password, role: form.role, brands: form.brands || [], phone: form.phone, modules: form.modules, team_ids: form.team_ids, }, isEditingSelf) setDirty(false) if (isCreateMode) onClose() } finally { setSaving(false) } } const confirmDelete = async () => { setShowDeleteConfirm(false) await onDelete(memberId) onClose() } const initials = member.name?.split(' ').map(w => w[0]).join('').slice(0, 2).toUpperCase() || '?' const roleName = (form.role || '').replace(/_/g, ' ') const todoCount = memberTasks.filter(t => t.status === 'todo').length const inProgressCount = memberTasks.filter(t => t.status === 'in_progress').length const doneCount = memberTasks.filter(t => t.status === 'done').length const header = (
{initials}
update('name', e.target.value)} className="w-full text-lg font-semibold text-text-primary bg-transparent border-0 p-0 focus:outline-none focus:ring-0" placeholder={t('team.fullName')} /> {roleName}
) return ( <> {/* Details Section */}
{!isEditingSelf && ( <>
update('email', e.target.value)} className="w-full px-3 py-2 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary" placeholder="email@example.com" disabled={!isCreateMode} />
{isCreateMode && (
update('password', e.target.value)} className="w-full px-3 py-2 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary" placeholder="••••••••" /> {!form.password && (

{t('team.defaultPassword')}

)}
)} )}
{userRole === 'manager' && isCreateMode && !isEditingSelf ? ( <>

{t('team.fixedRole')}

) : ( )}
update('phone', e.target.value)} className="w-full px-3 py-2 text-sm border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-primary/20 focus:border-brand-primary" placeholder="+966 ..." />
{/* Selected brand chips */} {(form.brands || []).length > 0 && (
{(form.brands || []).map(b => ( {b} ))}
)} {/* Dropdown */} {showBrandsDropdown && (
{brandsList && brandsList.length > 0 ? ( brandsList.map(brand => { const name = lang === 'ar' && brand.name_ar ? brand.name_ar : brand.name const checked = (form.brands || []).includes(name) return ( ) }) ) : (

{t('brands.noBrands')}

)}
)}
{/* Modules toggle */} {!isEditingSelf && canManageTeam && (
{ALL_MODULES.map(mod => { const active = (form.modules || []).includes(mod) const colors = MODULE_COLORS[mod] return ( ) })}
)} {/* Teams multi-select */} {teams && teams.length > 0 && (
{teams.map(team => { const active = (form.team_ids || []).includes(team.id || team._id) const teamId = team.id || team._id return ( ) })}
)}
{dirty && ( )} {!isCreateMode && !isEditingSelf && canManageTeam && onDelete && ( )}
{/* Workload Section (hidden in create mode) */} {!isCreateMode && (
{/* Stats */}

{memberTasks.length}

{t('team.totalTasks')}

{todoCount}

{t('team.toDo')}

{inProgressCount}

{t('team.inProgress')}

{doneCount}

{t('tasks.done')}

{/* Recent tasks */} {memberTasks.length > 0 && (

{t('team.recentTasks')}

{memberTasks.slice(0, 8).map(task => (
{task.title}
))}
)} {/* Recent posts */} {memberPosts.length > 0 && (

{t('team.recentPosts')}

{memberPosts.slice(0, 8).map(post => (
{post.title}
))}
)} {loadingWorkload && (

{t('common.loading')}

)}
)}
setShowDeleteConfirm(false)} title={t('team.removeMember')} isConfirm danger confirmText={t('team.remove')} onConfirm={confirmDelete} > {t('team.removeConfirm', { name: member?.name })} ) }