import { useState, useCallback, useEffect } from 'react' import { sectorApi, type Sector, type Team } from '../services/chatApiService' // ─── State shape ────────────────────────────────────────────────────────────── interface SectorWithTeams extends Sector { teams: Team[] teamsLoaded: boolean teamsLoading: boolean expanded: boolean } // ─── Hook ───────────────────────────────────────────────────────────────────── export function useSectorsLogic() { const [sectors, setSectors] = useState([]) const [loading, setLoading] = useState(false) const [toast, setToast] = useState<{ message: string; type: 'success' | 'error' } | null>(null) // ── Modal state ─────────────────────────────────────────────────────────── const [newSectorName, setNewSectorName] = useState('') const [newSectorOpen, setNewSectorOpen] = useState(false) const [savingSector, setSavingSector] = useState(false) const [newTeamSectorId, setNewTeamSectorId] = useState(null) const [newTeamName, setNewTeamName] = useState('') const [savingTeam, setSavingTeam] = useState(false) const [editingSector, setEditingSector] = useState(null) const [editSectorName, setEditSectorName] = useState('') const [savingEditSector, setSavingEditSector] = useState(false) const [editingTeam, setEditingTeam] = useState<{ team: Team; sectorId: string } | null>(null) const [editTeamName, setEditTeamName] = useState('') const [savingEditTeam, setSavingEditTeam] = useState(false) const showToast = useCallback((message: string, type: 'success' | 'error') => { setToast({ message, type }) setTimeout(() => setToast(null), 3000) }, []) // ── Load sectors ────────────────────────────────────────────────────────── const load = useCallback(async () => { setLoading(true) try { const data = await sectorApi.list() setSectors((prev) => data.map((s) => { const existing = prev.find((p) => p.id === s.id) return { ...s, teams: existing?.teams ?? [], teamsLoaded: existing?.teamsLoaded ?? false, teamsLoading: false, expanded: existing?.expanded ?? false, } }) ) } catch { showToast('Erro ao carregar setores.', 'error') } finally { setLoading(false) } }, [showToast]) useEffect(() => { load() }, []) // ── Toggle expand + load teams lazily ──────────────────────────────────── const toggleExpand = useCallback(async (sectorId: string) => { setSectors((prev) => prev.map((s) => s.id === sectorId ? { ...s, expanded: !s.expanded } : s ) ) // load teams if not yet loaded const sector = sectors.find((s) => s.id === sectorId) if (sector && !sector.teamsLoaded && !sector.teamsLoading) { setSectors((prev) => prev.map((s) => s.id === sectorId ? { ...s, teamsLoading: true } : s)) try { const teams = await sectorApi.listTeams(sectorId) setSectors((prev) => prev.map((s) => s.id === sectorId ? { ...s, teams, teamsLoaded: true, teamsLoading: false } : s ) ) } catch { setSectors((prev) => prev.map((s) => s.id === sectorId ? { ...s, teamsLoading: false } : s)) } } }, [sectors]) // ── Create sector ───────────────────────────────────────────────────────── const createSector = useCallback(async () => { if (!newSectorName.trim()) return setSavingSector(true) try { const sector = await sectorApi.create(newSectorName.trim()) setSectors((prev) => [...prev, { ...sector, teams: [], teamsLoaded: false, teamsLoading: false, expanded: false }]) setNewSectorName('') setNewSectorOpen(false) showToast('Setor criado.', 'success') } catch (err: any) { showToast(err?.response?.data?.error ?? 'Erro ao criar setor.', 'error') } finally { setSavingSector(false) } }, [newSectorName, showToast]) // ── Edit sector ─────────────────────────────────────────────────────────── const openEditSector = useCallback((sector: Sector) => { setEditingSector(sector) setEditSectorName(sector.name) }, []) const saveEditSector = useCallback(async () => { if (!editingSector) return setSavingEditSector(true) try { const updated = await sectorApi.update(editingSector.id, { name: editSectorName.trim() }) setSectors((prev) => prev.map((s) => s.id === updated.id ? { ...s, ...updated } : s)) setEditingSector(null) showToast('Setor atualizado.', 'success') } catch (err: any) { showToast(err?.response?.data?.error ?? 'Erro ao atualizar setor.', 'error') } finally { setSavingEditSector(false) } }, [editingSector, editSectorName, showToast]) const toggleSectorActive = useCallback(async (sector: Sector) => { try { const updated = await sectorApi.update(sector.id, { isActive: !sector.isActive }) setSectors((prev) => prev.map((s) => s.id === updated.id ? { ...s, ...updated } : s)) } catch { showToast('Erro ao alterar status.', 'error') } }, [showToast]) const deleteSector = useCallback(async (sectorId: string) => { try { await sectorApi.delete(sectorId) setSectors((prev) => prev.filter((s) => s.id !== sectorId)) showToast('Setor removido.', 'success') } catch { showToast('Erro ao remover setor.', 'error') } }, [showToast]) // ── Create team ─────────────────────────────────────────────────────────── const openNewTeam = useCallback((sectorId: string) => { setNewTeamSectorId(sectorId) setNewTeamName('') }, []) const createTeam = useCallback(async () => { if (!newTeamSectorId || !newTeamName.trim()) return setSavingTeam(true) try { const team = await sectorApi.createTeam(newTeamSectorId, newTeamName.trim()) setSectors((prev) => prev.map((s) => s.id === newTeamSectorId ? { ...s, teams: [...s.teams, team], teamsLoaded: true } : s ) ) setNewTeamSectorId(null) setNewTeamName('') showToast('Equipe criada.', 'success') } catch (err: any) { showToast(err?.response?.data?.error ?? 'Erro ao criar equipe.', 'error') } finally { setSavingTeam(false) } }, [newTeamSectorId, newTeamName, showToast]) // ── Edit team ───────────────────────────────────────────────────────────── const openEditTeam = useCallback((team: Team, sectorId: string) => { setEditingTeam({ team, sectorId }) setEditTeamName(team.name) }, []) const saveEditTeam = useCallback(async () => { if (!editingTeam) return setSavingEditTeam(true) try { const updated = await sectorApi.updateTeam(editingTeam.sectorId, editingTeam.team.id, { name: editTeamName.trim() }) setSectors((prev) => prev.map((s) => s.id === editingTeam.sectorId ? { ...s, teams: s.teams.map((t) => t.id === updated.id ? updated : t) } : s ) ) setEditingTeam(null) showToast('Equipe atualizada.', 'success') } catch (err: any) { showToast(err?.response?.data?.error ?? 'Erro ao atualizar equipe.', 'error') } finally { setSavingEditTeam(false) } }, [editingTeam, editTeamName, showToast]) const deleteTeam = useCallback(async (sectorId: string, teamId: string) => { try { await sectorApi.deleteTeam(sectorId, teamId) setSectors((prev) => prev.map((s) => s.id === sectorId ? { ...s, teams: s.teams.filter((t) => t.id !== teamId) } : s ) ) showToast('Equipe removida.', 'success') } catch { showToast('Erro ao remover equipe.', 'error') } }, [showToast]) return { sectors, loading, load, // sector create newSectorName, setNewSectorName, newSectorOpen, setNewSectorOpen, savingSector, createSector, // sector edit editingSector, editSectorName, setEditSectorName, savingEditSector, openEditSector, saveEditSector, setEditingSector, // sector actions toggleSectorActive, deleteSector, toggleExpand, // team create newTeamSectorId, newTeamName, setNewTeamName, savingTeam, openNewTeam, createTeam, setNewTeamSectorId, // team edit editingTeam, editTeamName, setEditTeamName, savingEditTeam, openEditTeam, saveEditTeam, setEditingTeam, // team actions deleteTeam, toast, } }