// TeamsTab.jsx — Takım Yönetimi // Takım CRUD + üye atama arayüzü (function () { const { useState, useEffect, useMemo, useCallback } = React; /* ── Team Modal ── */ function TeamModal({ team, agents, onClose, onSave }) { const isEdit = !!team; const [name, setName] = useState(team?.name || ''); const [leaderId, setLeaderId] = useState(team?.leader_id || ''); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); async function save() { setError(''); if (!name.trim()) { setError('Takım adı zorunludur.'); return; } setSaving(true); try { const url = isEdit ? `/api/teams/${team.id}` : '/api/teams'; const method = isEdit ? 'PUT' : 'POST'; const body = { name: name.trim() }; if (leaderId) body.leader_id = parseInt(leaderId); const r = await authFetch(url, { method, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body), }); if (!r.ok) { const err = await r.json(); throw new Error(err.detail || 'Hata olustu'); } onSave(); } catch (e) { setError(e.message); } finally { setSaving(false); } } return (
e.stopPropagation()} style={{ maxWidth: 480 }}>
{isEdit ? 'Takım Düzenle' : 'Yeni Takım'}
setName(e.target.value)} placeholder="Örn: Satış Ekibi A" />
{error &&
! {error}
}
); } /* ── Members Modal ── */ function MembersModal({ team, allAgents, onClose, onSave, toast }) { const [memberIds, setMemberIds] = useState(team.members ? team.members.map(m =>m.id) : []); const [search, setSearch] = useState(''); const [saving, setSaving] = useState(false); const available = useMemo(() => { const q = search.toLowerCase(); return allAgents.filter(a => { if (q && !a.name.toLowerCase().includes(q) && !a.extension.includes(q)) return false; return true; }); }, [allAgents, search]); function toggle(id) { setMemberIds(prev =>prev.includes(id) ? prev.filter(x =>x !== id) : [...prev, id]); } async function save() { setSaving(true); try { const r = await authFetch(`/api/teams/${team.id}/members`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(memberIds), }); if (!r.ok) { const err = await r.json(); throw new Error(err.detail || 'Hata'); } if (toast) toast('Takım üyeleri güncellendi', 'success'); onSave(); } catch (e) { if (toast) toast(e.message, 'error'); } finally { setSaving(false); } } return (
e.stopPropagation()} style={{ maxWidth: 600 }}>
"{team.name}" Üyeleri
setSearch(e.target.value)} style={{ width: '100%' }} />
{memberIds.length} üye seçili
{available.map(a => { const sel = memberIds.includes(a.id); const isLeader = team.leader_id === a.id; return ( ); })} {available.length === 0 && (
Temsilci bulunamadı
)}
); } /* ═══════════════════════════════════════════════════════════════════════════ MAIN: TeamsTab ═══════════════════════════════════════════════════════════════════════════ */ function TeamsTab({ toast }) { const [teams, setTeams] = useState([]); const [agents, setAgents] = useState([]); const [loading, setLoading] = useState(true); const [teamModal, setTeamModal] = useState(null); // null | 'new' | team obj const [membersModal, setMembersModal] = useState(null); // null | team obj const loadData = useCallback(async () => { try { const [tR, aR] = await Promise.all([ authFetch('/api/teams'), authFetch('/api/human-agents'), ]); const [tD, aD] = await Promise.all([ tR.ok ? tR.json() : [], aR.ok ? aR.json() : [], ]); setTeams(Array.isArray(tD) ? tD : []); setAgents(Array.isArray(aD) ? aD.filter(a =>a.is_active) : []); } catch (e) { console.error('Teams load error:', e); } finally { setLoading(false); } }, []); useEffect(() => { loadData(); }, [loadData]); async function deleteTeam(id, name) { if (!confirm(`"${name}" takımını silmek istediğinize emin misiniz?`)) return; try { const r = await authFetch(`/api/teams/${id}`, { method: 'DELETE' }); if (!r.ok && r.status !== 204) throw new Error('Silinemedi'); if (toast) toast('Takım silindi', 'success'); loadData(); } catch (e) { if (toast) toast(e.message, 'error'); } } async function toggleActive(team) { try { const r = await authFetch(`/api/teams/${team.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ is_active: !team.is_active }), }); if (!r.ok) throw new Error('Güncellenemedi'); loadData(); } catch (e) { if (toast) toast(e.message, 'error'); } } if (loading) { return (
Yükleniyor...
); } return (
{/* Header */}

Takım Yönetimi

{teams.length} takım tanımlı

{/* Teams Table */}
{teams.length === 0 && ( )} {teams.map(t => ( ))}
Takım Adı Lider Üye Sayısı Üyeler Durum İşlem
Henüz takım tanımlanmamış.
{t.name}
{t.leader_name ? ( {t.leader_name} ) : ( Atanmamış )} 0 ? 'rgba(88,166,255,.1)' : 'var(--surface2)', color: t.member_count > 0 ? 'var(--blue)' : 'var(--text-dim)', border: `1px solid ${t.member_count > 0 ? 'rgba(88,166,255,.2)' : 'var(--border)'}`, }}>{t.member_count}
{t.members && t.members.length > 0 ? t.members.slice(0, 5).map(m => ( {m.name}{t.leader_id === m.id ? ' ' : ''} )) : } {t.members && t.members.length > 5 && ( +{t.members.length - 5} )}
toggleActive(t)} title="Durumu değiştirmek için tıklayın"> {t.is_active ? 'Aktif' : 'Pasif'}
{/* Modals */} {teamModal && ( setTeamModal(null)} onSave={() => { if (toast) toast('Takım kaydedildi', 'success'); setTeamModal(null); loadData(); }} /> )} {membersModal && ( setMembersModal(null)} onSave={() => { setMembersModal(null); loadData(); }} toast={toast} /> )}
); } window.TeamsTab = TeamsTab; })();