import { useState, useEffect, useCallback } from 'react'; import { PageContainer } from '../../StyledForPage'; import { HeaderSwitch } from '../../../components/HeaderMenu/HeaderSwitch'; import { SwitchUserSsp } from '../../../components/AdminPanel/SwitchUserSsp'; import { ROLES_NAME_ID } from '../../../constants'; import { useAuth } from '../../../app/context/AuthProvider'; import { Box, TextField, Autocomplete, FormLabel, Button, FormControlLabel, Switch, } from '@mui/material'; import SearchComponent from '../../../components/common/SearchComponent'; import { toast } from 'react-toastify'; import { SspApi } from '../../../api/ssp'; import { UsersApi } from '../../../api/users'; import SspTable from './SspTable'; import { ModalAddSsp } from './ModalAddSsp'; import { ModalChangeUsersInSsp } from './ModalChangeUsersInSsp'; import { ModalEditSsp } from './ModalEditSsp'; import { PrimaryButton } from '../../../components/common/Buttons/Buttons'; import { WhitePlus } from '../../../components/common/icons/icons'; const SspsPage = () => { const { user } = useAuth(); const [ssps, setSsps] = useState([]); const [loading, setLoading] = useState(false); const [sspForChangeUsers, setSspForChangeUsers] = useState(null); const [needUpdateCountUsers, setNeedUpdateCountUsers] = useState(false); const [filterString, setFilterString] = useState(''); const [filterType, setFilterType] = useState(null); const [filterStatus, setFilterStatus] = useState(0); const [openModalUsersinSspChange, setOpenModalUsersinSspChange] = useState(false); const [openModalEdit, setOpenModalEdit] = useState(false); const [sspForEdit, setSspForEdit] = useState(null); const [openModalAdd, setOpenModalAdd] = useState(false); useEffect(() => { const loadSsps = async () => { setLoading(true); try { const data = await SspApi.getAll({ load_users_count: true }); if (!data.success) { toast.error( 'Ошибка получения ССП/Региональные филиалы ' + data.message, ); return; } setSsps(data.result.sort((a, b) => a.id - b.id)); } catch { toast.error('Ошибка получения ССП/Региональные филиалы '); } finally { setLoading(false); } }; loadSsps(); }, []); useEffect(() => { if (openModalUsersinSspChange && openModalAdd) return; setTimeout(() => { setNeedUpdateCountUsers(true); }, 500); }, [openModalUsersinSspChange, openModalAdd]); const handleOpenModalUsersInSspChange = useCallback( (sspId) => { setOpenModalUsersinSspChange(true); setSspForChangeUsers(ssps.find((ssp) => ssp.id == sspId)); }, [ssps], ); const handleCloseModalUsersInSspChange = () => { setOpenModalUsersinSspChange(false); setSspForChangeUsers(null); }; const handleChangeStatus = (ssp) => SspApi.deleteSsp(ssp.id) .then((data) => { if (!data.success) { toast.error( 'Не удалось отправить в архив ' + (data.message || ''), ); throw new Error(data.message || 'archive_failed'); } toast.success('ССП/РФ перенесены в архив'); setSsps((prev) => prev .map((s) => s.id === ssp.id ? { ...s, is_active: false } : s, ) .sort((a, b) => a.id - b.id), ); }) .catch((error) => { if (error?.response) { const msg = error.response.data?.message || error.response.data?.detail; toast.error(msg || 'Не удалось отправить в архив'); } throw error; }); const updateUser = (user) => { UsersApi.update(user.id, user) .then((data) => { if (!data.success) { toast.error('Ошибка обновления пользователя ' + data.message); } }) .catch(() => { toast.error('Ошибка обновления пользователя '); }); }; const adjustSspUsersCount = (sspId, delta) => { if (!delta) return; setSsps((prev) => prev.map((s) => s.id === sspId ? { ...s, users_count: (s.users_count ?? 0) + delta } : s, ), ); }; const updateUserManySsp = (user, sspIds) => SspApi.putManySsps(user.id, sspIds) .then((data) => { if (!data.success) { toast.error(data?.message || 'Ошибка добавления пользователя'); return false; } return true; }) .catch((error) => { const msg = error?.response?.data?.message || error?.response?.data?.detail; toast.error(msg || 'Ошибка добавления пользователя'); return false; }); const deleteUserManySsp = (user, sspIds) => SspApi.deleteManySsps(user.id, sspIds) .then((data) => { if (!data.success) { toast.error('Ошибка обновления пользователя ' + data.message); return false; } return true; }) .catch(() => { toast.error('Ошибка обновления пользователя '); return false; }); const handleUpdateUsers = async (ssp, usersDataForUpdate) => { let added = 0; let removed = 0; for (const user of usersDataForUpdate.update) { if (await updateUserManySsp(user, { ssp_ids: [ssp.id] })) { added += 1; } } for (const user of usersDataForUpdate.delete) { if (await deleteUserManySsp(user, { ssp_ids: [ssp.id] })) { removed += 1; } } adjustSspUsersCount(ssp.id, added - removed); }; const handleEditSsp = (ssp) => { setOpenModalEdit(true); setSspForEdit(ssp); }; const handleUpdateSsp = (ssp) => { SspApi.updateSsp(ssp.id, ssp) .then((data) => { if (!data.success) { toast.error('Не удалось обновить данные ' + data.message); return; } setSsps((prev) => { const newSsps = [...prev.filter((s) => s.id !== ssp.id), ssp].sort( (a, b) => a.id - b.id, ); return newSsps; }); }) .catch(() => { toast.error('Не удалось обновить данные '); }); }; const handleCloseModalEdit = () => { setOpenModalEdit(false); setSspForEdit(null); }; const handleAddSsp = () => { setOpenModalAdd(true); }; const handleCloseAddSsp = () => { setOpenModalAdd(false); }; const handleSaveNewSsp = (ssp, usersData) => { SspApi.createSsp(ssp) .then((data) => { if (!data.success) { toast.error('Не удалось создать ССП/Рег. филиал ' + data.message); return; } const newSsp = { ...data.result, users_count: data.result.users_count ?? 0 }; setSsps((prev) => [...prev, newSsp].sort((a, b) => a.id - b.id)); handleUpdateUsers(newSsp, usersData); }) .catch(() => { toast.error('Не удалось создать ССП/Рег. филиал '); }); }; if (!user || user.role_id != ROLES_NAME_ID.admin) return; return ( <> }> Добавить Тип option.text} value={filterType} onChange={(event, newValue) => { setFilterType(newValue); }} sx={{ height: '2rem', minWidth: '20.25rem' }} renderInput={(params) => ( )} /> setFilterStatus(e.target.checked)} size="small" sx={{ height: 'max-content', width: 'max-content', '& .MuiSwitch-switchBase': { padding: '0.375rem', '&.Mui-checked': { transform: 'translateX(.65rem)', color: 'white', '& + .MuiSwitch-track': { backgroundColor: '#258141', opacity: 1, }, '& .MuiSwitch-thumb': { width: '0.75rem', height: '0.75rem', }, }, '& .MuiSwitch-thumb': { width: '0.75rem', height: '0.75rem', boxShadow: 'none', }, }, '& .MuiSwitch-track': { backgroundColor: '#ccc', opacity: 1, borderRadius: '0.75rem', height: '1rem', width: '1.75rem', }, padding: '0.225rem', }} /> } sx={{ margin: 0 }} /> Показать архивные ); }; export default SspsPage;