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;