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 => (
))
)}
{/* 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 ? (
) : (
{displayedMembers.map(member => (
))}
)}
>
)}
{/* Teams (org chart) view */}
{viewMode === 'teams' && (
{teams.length === 0 && unassignedMembers.length === 0 ? (
) : (
<>
{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}
/>
)}
)
}