diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 9aabd04..c056933 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -108,12 +108,18 @@ const App = () => { } }; - const handleLogout = () => { + const handleLogout = (message = '') => { setToken(''); setUsername(''); localStorage.removeItem('token'); localStorage.removeItem('username'); - setActiveView('directory'); + if (message) { + setLoginError(message); + setActiveView('login'); + } else { + setLoginError(''); + setActiveView('directory'); + } }; // Client-side search and filtering @@ -199,7 +205,7 @@ const App = () => { Справочник ) : ( - ) @@ -290,6 +296,7 @@ const App = () => { departments={departments} companies={companies} onRefreshData={fetchData} + onLogout={handleLogout} /> )} diff --git a/frontend/src/components/AdminPanel.jsx b/frontend/src/components/AdminPanel.jsx index c0d4be6..6cf1545 100644 --- a/frontend/src/components/AdminPanel.jsx +++ b/frontend/src/components/AdminPanel.jsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { PlusIcon, EditIcon, DeleteIcon, CloseIcon, PhoneIcon, EmailIcon } from '../utils/svgs'; import ImportExport from './ImportExport'; -const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) => { +const AdminPanel = ({ token, employees, departments, companies, onRefreshData, onLogout }) => { const [activeTab, setActiveTab] = useState('employees'); // 'employees', 'departments', 'companies', 'import-export' const [showEmpModal, setShowEmpModal] = useState(false); const [editingEmp, setEditingEmp] = useState(null); @@ -57,6 +57,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) }, body: JSON.stringify({ name: editingCompanyName.trim() }) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } const data = await res.json(); if (res.ok) { @@ -84,6 +88,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) }, body: JSON.stringify({ name: editingDeptName.trim() }) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } const data = await res.json(); if (res.ok) { @@ -115,6 +123,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) }, body: JSON.stringify({ name: newDeptName.trim() }) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } const data = await res.json(); if (res.ok) { @@ -139,7 +151,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); - + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } if (res.ok) { onRefreshData(); showAlert('success', 'Подразделение удалено!'); @@ -167,6 +182,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) }, body: JSON.stringify({ name: newCompanyName.trim() }) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } const data = await res.json(); if (res.ok) { @@ -191,7 +210,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); - + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } if (res.ok) { onRefreshData(); showAlert('success', 'Компания удалена!'); @@ -268,6 +290,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) }, body: JSON.stringify(employeePayload) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } const data = await res.json(); if (res.ok) { @@ -292,6 +318,10 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) method: 'DELETE', headers: { 'Authorization': `Bearer ${token}` } }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } if (res.ok) { onRefreshData(); @@ -705,7 +735,7 @@ const AdminPanel = ({ token, employees, departments, companies, onRefreshData }) {/* Tab: Import/Export */} {/* ---------------------------------------------------- */} {activeTab === 'import-export' && ( - + )} {/* ---------------------------------------------------- */} diff --git a/frontend/src/components/ImportExport.jsx b/frontend/src/components/ImportExport.jsx index f0d790f..59a7a27 100644 --- a/frontend/src/components/ImportExport.jsx +++ b/frontend/src/components/ImportExport.jsx @@ -1,7 +1,7 @@ import React, { useState, useRef } from 'react'; import { DownloadIcon, UploadIcon } from '../utils/svgs'; -const ImportExport = ({ token, onRefreshData }) => { +const ImportExport = ({ token, onRefreshData, onLogout }) => { const [dragActive, setDragActive] = useState(false); const [status, setStatus] = useState({ type: '', message: '' }); const fileInputRef = useRef(null); @@ -130,6 +130,11 @@ const ImportExport = ({ token, onRefreshData }) => { body: JSON.stringify(payload) }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } + const data = await res.json(); if (res.ok) { setStatus({ type: 'success', message: `Импорт завершен! Загружено компаний: ${payload.companies.length}, отделов: ${payload.departments.length}, сотрудников: ${payload.employees.length}` }); @@ -151,6 +156,10 @@ const ImportExport = ({ token, onRefreshData }) => { const res = await fetch('/api/admin/export', { headers: { 'Authorization': `Bearer ${token}` } }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } if (!res.ok) throw new Error('Ошибка экспорта данных с сервера'); const data = await res.json(); @@ -173,6 +182,10 @@ const ImportExport = ({ token, onRefreshData }) => { const res = await fetch('/api/admin/export', { headers: { 'Authorization': `Bearer ${token}` } }); + if (res.status === 401 || res.status === 403) { + onLogout('Сессия истекла, войдите заново'); + return; + } if (!res.ok) throw new Error('Ошибка экспорта данных с сервера'); const data = await res.json();