import { useState, useEffect, useContext } from 'react' import { Plus, Users, ArrowLeft, User as UserIcon, Edit2, LayoutGrid, Network } from 'lucide-react' import { getInitials } from '../utils/api' import { AppContext } from '../App' import { useAuth } from '../contexts/AuthContext' import { useLanguage } from '../i18n/LanguageContext' import { api } from '../utils/api' import MemberCard from '../components/MemberCard' import StatusBadge from '../components/StatusBadge' import BrandBadge from '../components/BrandBadge' import TeamMemberPanel from '../components/TeamMemberPanel' import TeamPanel from '../components/TeamPanel' export default function Team() { const { t } = useLanguage() const { teamMembers, loadTeam, currentUser, teams, loadTeams, brands } = useContext(AppContext) const { user } = useAuth() const [panelMember, setPanelMember] = useState(null) const [panelIsEditingSelf, setPanelIsEditingSelf] = useState(false) const [selectedMember, setSelectedMember] = useState(null) const [memberTasks, setMemberTasks] = useState([]) const [memberPosts, setMemberPosts] = useState([]) const [loadingDetail, setLoadingDetail] = useState(false) const [panelTeam, setPanelTeam] = useState(null) const [teamFilter, setTeamFilter] = useState(null) const [viewMode, setViewMode] = useState('grid') // 'grid' | 'teams' const canManageTeam = user?.role === 'superadmin' || user?.role === 'manager' const openNew = () => { setPanelMember({ role: 'content_writer' }) setPanelIsEditingSelf(false) } const openEdit = (member) => { const isSelf = member._id === user?.id || member.id === user?.id setPanelMember(member) setPanelIsEditingSelf(isSelf) } const handlePanelSave = async (memberId, data, isEditingSelf) => { try { if (isEditingSelf) { await api.patch('/users/me/profile', { name: data.name, phone: data.phone, }) } else { const payload = { name: data.name, email: data.email, team_role: data.role, brands: data.brands, phone: data.phone, modules: data.modules, } if (data.password) payload.password = data.password if (memberId) { await api.patch(`/users/team/${memberId}`, payload) } else { const created = await api.post('/users/team', payload) memberId = created?.id || created?.Id } } // Sync team memberships if team_ids provided if (data.team_ids !== undefined && memberId && !isEditingSelf) { const member = teamMembers.find(m => (m.id || m._id) === memberId) const currentTeamIds = member?.teams ? member.teams.map(t => t.id) : [] const targetTeamIds = data.team_ids || [] const toAdd = targetTeamIds.filter(id => !currentTeamIds.includes(id)) const toRemove = currentTeamIds.filter(id => !targetTeamIds.includes(id)) for (const teamId of toAdd) { await api.post(`/teams/${teamId}/members`, { user_id: memberId }) } for (const teamId of toRemove) { await api.delete(`/teams/${teamId}/members/${memberId}`) } } await loadTeam() await loadTeams() } catch (err) { console.error('Save failed:', err) alert(err.message || 'Failed to save') } } const handleTeamSave = async (teamId, data) => { try { if (teamId) { await api.patch(`/teams/${teamId}`, data) } else { await api.post('/teams', data) } await loadTeams() await loadTeam() } catch (err) { console.error('Team save failed:', err) alert(err.message || 'Failed to save team') } } const handleTeamDelete = async (teamId) => { try { await api.delete(`/teams/${teamId}`) setPanelTeam(null) if (teamFilter === teamId) setTeamFilter(null) await loadTeams() await loadTeam() } catch (err) { console.error('Team delete failed:', err) } } const handlePanelDelete = async (memberId) => { await api.delete(`/users/team/${memberId}`) if (selectedMember?._id === memberId) { setSelectedMember(null) } setPanelMember(null) await loadTeam() } const openMemberDetail = async (member) => { setSelectedMember(member) setLoadingDetail(true) try { const [tasksRes, postsRes] = await Promise.allSettled([ api.get(`/tasks?assignedTo=${member._id}`), api.get(`/posts?assignedTo=${member._id}`), ]) setMemberTasks(tasksRes.status === 'fulfilled' ? (tasksRes.value.data || tasksRes.value || []) : []) setMemberPosts(postsRes.status === 'fulfilled' ? (postsRes.value.data || postsRes.value || []) : []) } catch { setMemberTasks([]) setMemberPosts([]) } finally { setLoadingDetail(false) } } // Member detail view if (selectedMember) { 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 return (
{/* Member profile */}
{selectedMember.name?.split(' ').map(w => w[0]).join('').slice(0, 2).toUpperCase()}

{selectedMember.name}

{(selectedMember.team_role || selectedMember.role)?.replace('_', ' ')}

{selectedMember.email && (

{selectedMember.email}

)} {selectedMember.brands && selectedMember.brands.length > 0 && (
{selectedMember.brands.map(b => )}
)}
{/* Workload stats */}

{memberTasks.length}

{t('team.totalTasks')}

{todoCount}

{t('team.toDo')}

{inProgressCount}

{t('team.inProgress')}

{doneCount}

{t('tasks.done')}

{/* Tasks & Posts */}
{/* Tasks */}

{t('tasks.title')} ({memberTasks.length})

{loadingDetail ? (
{t('common.loading')}
) : memberTasks.length === 0 ? (
{t('team.noTasks')}
) : ( memberTasks.map(task => (

{task.title}

)) )}
{/* Posts */}

{t('nav.posts')} ({memberPosts.length})

{loadingDetail ? (
{t('common.loading')}
) : memberPosts.length === 0 ? (
{t('posts.noPosts')}
) : ( memberPosts.map(post => (

{post.title}

{post.brand && }
)) )}
{/* Team Member Panel */} {panelMember && ( setPanelMember(null)} onSave={handlePanelSave} onDelete={canManageTeam ? handlePanelDelete : null} canManageTeam={canManageTeam} userRole={user?.role} teams={teams} brands={brands} /> )}
) } const displayedMembers = teamFilter ? teamMembers.filter(m => m.teams?.some(t => t.id === teamFilter)) : teamMembers // Members not in any team const unassignedMembers = teamMembers.filter(m => !m.teams || m.teams.length === 0) const avatarColors = [ 'from-indigo-400 to-purple-500', 'from-pink-400 to-rose-500', 'from-emerald-400 to-teal-500', 'from-amber-400 to-orange-500', 'from-cyan-400 to-blue-500', ] // Team grid return (
{/* Toolbar */}

{displayedMembers.length} {displayedMembers.length !== 1 ? t('team.membersPlural') : t('team.member')}

{/* View toggle */}
{/* Edit own profile button */} {/* Create Team button (managers and superadmins only) */} {canManageTeam && ( )} {/* Add member button (managers and superadmins only) */} {canManageTeam && ( )}
{/* Grid view: team filter pills + member cards */} {viewMode === 'grid' && ( <> {/* Team filter pills */} {teams.length > 0 && (
{t('teams.teams')}: {teams.map(team => { const tid = team.id || team._id const active = teamFilter === tid return (
{canManageTeam && ( )}
) })}
)} {/* Member grid */} {displayedMembers.length === 0 ? (

{t('team.noMembers')}

) : (
{displayedMembers.map(member => ( ))}
)} )} {/* Teams (org chart) view */} {viewMode === 'teams' && (
{teams.length === 0 && unassignedMembers.length === 0 ? (

{t('team.noMembers')}

) : ( <> {teams.map(team => { const tid = team.id || team._id const members = teamMembers.filter(m => m.teams?.some(t => t.id === tid)) return (
{/* Team header */}

{team.name}

{members.length} {members.length !== 1 ? t('team.membersPlural') : t('team.member')} {team.description && ` ยท ${team.description}`}

{canManageTeam && ( )}
{/* Team members */} {members.length === 0 ? (
{t('team.noMembers')}
) : (
{members.map(member => { const colorIndex = (member.name?.charCodeAt(0) || 0) % avatarColors.length return (
openMemberDetail(member)} className="flex items-center gap-4 px-5 py-3 hover:bg-surface-secondary transition-colors cursor-pointer" >
{getInitials(member.name)}

{member.name}

{(member.team_role || member.role)?.replace('_', ' ')}

{member.brands && member.brands.length > 0 && (
{member.brands.slice(0, 3).map(b => )}
)}
) })}
)}
) })} {/* Unassigned members */} {unassignedMembers.length > 0 && (

{t('team.unassigned')}

{unassignedMembers.length} {unassignedMembers.length !== 1 ? t('team.membersPlural') : t('team.member')}

{unassignedMembers.map(member => { const colorIndex = (member.name?.charCodeAt(0) || 0) % avatarColors.length return (
openMemberDetail(member)} className="flex items-center gap-4 px-5 py-3 hover:bg-surface-secondary transition-colors cursor-pointer" >
{getInitials(member.name)}

{member.name}

{(member.team_role || member.role)?.replace('_', ' ')}

{member.brands && member.brands.length > 0 && (
{member.brands.slice(0, 3).map(b => )}
)}
) })}
)} )}
)} {/* Team Member Panel */} {panelMember && ( setPanelMember(null)} onSave={handlePanelSave} onDelete={canManageTeam ? handlePanelDelete : null} canManageTeam={canManageTeam} userRole={user?.role} teams={teams} brands={brands} /> )} {/* Team Panel */} {panelTeam && ( setPanelTeam(null)} onSave={handleTeamSave} onDelete={canManageTeam ? handleTeamDelete : null} teamMembers={teamMembers} /> )}
) }