From f254597b1aeeaa1a463ec861718ac083a97a4f2f Mon Sep 17 00:00:00 2001 From: Georgiy Syralev Date: Thu, 18 Sep 2025 17:49:06 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B0=D1=82=D0=B0=20=D0=BB?= =?UTF-8?q?=D0=BE=D0=B3=D0=B8=D0=BA=D0=B0=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D1=8F=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/src/checkProxmoxConnection.ts | 6 + ospabhost/backend/src/index.ts | 19 +- .../backend/src/modules/server/proxmoxApi.ts | 60 +++++++ .../src/modules/server/server.routes.ts | 81 +++++++-- .../checks/1758206338893-666161055-logo.jpg | Bin 0 -> 213793 bytes .../frontend/src/pages/dashboard/checkout.tsx | 30 +++- .../frontend/src/pages/dashboard/mainpage.tsx | 154 ++++++---------- .../src/pages/dashboard/servermanagement.tsx | 96 ---------- .../src/pages/dashboard/serverpanel.tsx | 169 ++++++++++++++++++ .../frontend/src/pages/dashboard/servers.tsx | 32 +++- ospabhost/frontend/src/pages/login.tsx | 27 +-- 11 files changed, 440 insertions(+), 234 deletions(-) create mode 100644 ospabhost/backend/src/checkProxmoxConnection.ts create mode 100644 ospabhost/backend/src/modules/server/proxmoxApi.ts create mode 100644 ospabhost/backend/uploads/checks/1758206338893-666161055-logo.jpg delete mode 100644 ospabhost/frontend/src/pages/dashboard/servermanagement.tsx create mode 100644 ospabhost/frontend/src/pages/dashboard/serverpanel.tsx diff --git a/ospabhost/backend/src/checkProxmoxConnection.ts b/ospabhost/backend/src/checkProxmoxConnection.ts new file mode 100644 index 0000000..da730e2 --- /dev/null +++ b/ospabhost/backend/src/checkProxmoxConnection.ts @@ -0,0 +1,6 @@ +import { checkProxmoxConnection } from './modules/server/proxmoxApi'; + +(async () => { + const result = await checkProxmoxConnection(); + console.log('Проверка соединения с Proxmox:', result); +})(); diff --git a/ospabhost/backend/src/index.ts b/ospabhost/backend/src/index.ts index db3cc97..06262c8 100644 --- a/ospabhost/backend/src/index.ts +++ b/ospabhost/backend/src/index.ts @@ -29,10 +29,23 @@ app.use((req, res, next) => { next(); }); -app.get('/', (req, res) => { - res.json({ +import { checkProxmoxConnection } from './modules/server/proxmoxApi'; + +app.get('/', async (req, res) => { + // Проверка соединения с Proxmox + let proxmoxStatus; + try { + proxmoxStatus = await checkProxmoxConnection(); + } catch (err) { + proxmoxStatus = { status: 'fail', message: 'Ошибка проверки Proxmox', error: err }; + } + + res.json({ message: 'Сервер ospab.host запущен!', - timestamp: new Date().toISOString() + timestamp: new Date().toISOString(), + port: PORT, + database: process.env.DATABASE_URL ? 'подключена' : 'НЕ НАСТРОЕНА', + proxmox: proxmoxStatus }); }); diff --git a/ospabhost/backend/src/modules/server/proxmoxApi.ts b/ospabhost/backend/src/modules/server/proxmoxApi.ts new file mode 100644 index 0000000..5c0539d --- /dev/null +++ b/ospabhost/backend/src/modules/server/proxmoxApi.ts @@ -0,0 +1,60 @@ +import axios from 'axios'; +import dotenv from 'dotenv'; +dotenv.config(); + +const PROXMOX_API_URL = process.env.PROXMOX_API_URL; +const PROXMOX_TOKEN_ID = process.env.PROXMOX_TOKEN_ID; +const PROXMOX_TOKEN_SECRET = process.env.PROXMOX_TOKEN_SECRET; + +export async function createProxmoxContainer({ os, tariff, user }: any) { + try { + const node = process.env.PROXMOX_NODE; + const diskTemplate = process.env.PROXMOX_DISK_TEMPLATE; + if (!node || !diskTemplate) { + return { status: 'fail', message: 'Не указаны PROXMOX_NODE или PROXMOX_DISK_TEMPLATE в .env' }; + } + const vmId = Math.floor(10000 + Math.random() * 89999); + const res = await axios.post( + `${PROXMOX_API_URL}/nodes/${node}/qemu`, + { + vmid: vmId, + name: `user${user.id}-vm${vmId}`, + ostype: os.code || 'l26', + cores: tariff.cores || 2, + memory: tariff.memory || 2048, + storage: diskTemplate, + }, + { + headers: { + 'Authorization': `PVEAPIToken=${PROXMOX_TOKEN_ID}=${PROXMOX_TOKEN_SECRET}`, + 'Content-Type': 'application/json' + } + } + ); + if (res.data && res.data.data) { + return { status: 'ok', proxmoxId: vmId, message: 'Сервер создан на Proxmox', proxmox: res.data.data }; + } + return { status: 'fail', message: 'Не удалось создать сервер на Proxmox', details: res.data }; + } catch (err) { + return { status: 'fail', message: 'Ошибка создания сервера на Proxmox', error: err }; + } +} + +export async function checkProxmoxConnection() { + try { + const res = await axios.get( + `${PROXMOX_API_URL}/version`, + { + headers: { + 'Authorization': `PVEAPIToken=${PROXMOX_TOKEN_ID}=${PROXMOX_TOKEN_SECRET}` + } + } + ); + if (res.data && res.data.data) { + return { status: 'ok', message: 'Соединение с Proxmox установлено', version: res.data.data.version }; + } + return { status: 'fail', message: 'Не удалось получить версию Proxmox' }; + } catch (err) { + return { status: 'fail', message: 'Ошибка соединения с Proxmox', error: err }; + } +} diff --git a/ospabhost/backend/src/modules/server/server.routes.ts b/ospabhost/backend/src/modules/server/server.routes.ts index e132e5b..6420a2b 100644 --- a/ospabhost/backend/src/modules/server/server.routes.ts +++ b/ospabhost/backend/src/modules/server/server.routes.ts @@ -1,16 +1,23 @@ import { Router } from 'express'; import { PrismaClient } from '@prisma/client'; -// import { createProxmoxContainer } from '../../proxmox/proxmoxApi'; // если есть интеграция +import { authMiddleware } from '../auth/auth.middleware'; +import { checkProxmoxConnection, createProxmoxContainer } from './proxmoxApi'; const router = Router(); const prisma = new PrismaClient(); -// POST /api/server/create — создать сервер (контейнер) +router.use(authMiddleware); + +router.get('/proxmox-status', async (req, res) => { + const status = await checkProxmoxConnection(); + res.json(status); +}); router.post('/create', async (req, res) => { try { const { tariffId, osId } = req.body; - // TODO: получить userId из авторизации (req.user) - const userId = 1; // временно, заменить на реального пользователя + // Получаем userId из авторизации + const userId = req.user?.id; + if (!userId) return res.status(401).json({ error: 'Нет авторизации' }); // Получаем тариф и ОС const tariff = await prisma.tariff.findUnique({ where: { id: tariffId } }); @@ -19,30 +26,52 @@ router.post('/create', async (req, res) => { return res.status(400).json({ error: 'Тариф или ОС не найдены' }); } - // TODO: интеграция с Proxmox для создания контейнера - // Если интеграция с Proxmox есть, то только при успешном создании контейнера создавать запись в БД - // Например: - // let proxmoxResult; - // try { - // proxmoxResult = await createProxmoxContainer({ ... }); - // } catch (proxmoxErr) { - // console.error('Ошибка Proxmox:', proxmoxErr); - // return res.status(500).json({ error: 'Ошибка создания контейнера на Proxmox' }); - // } + // Проверяем баланс пользователя + const user = await prisma.user.findUnique({ where: { id: userId } }); + if (!user) return res.status(404).json({ error: 'Пользователь не найден' }); + if (user.balance < tariff.price) { + return res.status(400).json({ error: 'Недостаточно средств на балансе' }); + } - // Если всё успешно — создаём запись сервера в БД + // 1. Создаём сервер на Proxmox + let proxmoxResult; + try { + proxmoxResult = await createProxmoxContainer({ os, tariff, user }); + } catch (proxmoxErr) { + console.error('Ошибка Proxmox:', proxmoxErr); + return res.status(500).json({ error: 'Ошибка создания сервера на Proxmox', details: proxmoxErr }); + } + if (!proxmoxResult || proxmoxResult.status !== 'ok') { + return res.status(500).json({ error: 'Сервер не создан на Proxmox', details: proxmoxResult }); + } + + // 2. Списываем средства + await prisma.user.update({ + where: { id: userId }, + data: { + balance: { + decrement: tariff.price + } + } + }); + + // 3. Создаём запись о сервере в БД + const node = process.env.PROXMOX_NODE; + const diskTemplate = process.env.PROXMOX_DISK_TEMPLATE; const server = await prisma.server.create({ data: { userId, tariffId, osId, - status: 'creating', + status: 'active', + node, + diskTemplate, + proxmoxId: proxmoxResult.proxmoxId || null, }, }); res.json({ success: true, server }); } catch (err) { console.error('Ошибка создания сервера:', err); - // Не создавать сервер, если есть ошибка return res.status(500).json({ error: 'Ошибка создания сервера' }); } }); @@ -67,4 +96,22 @@ router.get('/', async (req, res) => { } }); +// GET /api/server/:id — получить один сервер пользователя по id +router.get('/:id', async (req, res) => { + try { + // TODO: получить userId из авторизации (req.user) + const userId = 1; // временно + const serverId = Number(req.params.id); + const server = await prisma.server.findFirst({ + where: { id: serverId, userId }, + include: { os: true, tariff: true }, + }); + if (!server) return res.status(404).json({ error: 'Сервер не найден' }); + res.json(server); + } catch (err) { + console.error('Ошибка получения сервера:', err); + res.status(500).json({ error: 'Ошибка получения сервера' }); + } +}); + export default router; diff --git a/ospabhost/backend/uploads/checks/1758206338893-666161055-logo.jpg b/ospabhost/backend/uploads/checks/1758206338893-666161055-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..30fd29ccd8641f13b40cee9010413cff86fd2680 GIT binary patch literal 213793 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 qZS^=@D_PiNqIyM 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 KF@XHq^Zx = ({ onSuccess }) => { setLoading(true); setError(''); try { + const token = localStorage.getItem('access_token') || localStorage.getItem('token'); console.log('Покупка сервера:', { tariffId: selectedTariff, osId: selectedOs }); const res = await axios.post('http://localhost:5000/api/server/create', { tariffId: selectedTariff, osId: selectedOs, + }, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + withCredentials: true, }); - console.log('Ответ сервера:', res.data); + if (res.data && res.data.error === 'Недостаточно средств на балансе') { + setError('Недостаточно средств на балансе. Пополните баланс и попробуйте снова.'); + setLoading(false); + return; + } + // После успешной покупки обновляем userData + try { + const userRes = await axios.get('http://localhost:5000/api/auth/me', { headers: token ? { Authorization: `Bearer ${token}` } : {} }); + window.dispatchEvent(new CustomEvent('userDataUpdate', { + detail: { + user: userRes.data.user, + balance: userRes.data.user.balance ?? 0, + servers: userRes.data.user.servers ?? [], + tickets: userRes.data.user.tickets ?? [], + } + })); + } catch (err) { + console.error('Ошибка обновления userData после покупки:', err); + } onSuccess(); } catch (err) { + if (axios.isAxiosError(err) && err.response?.data?.error === 'Недостаточно средств на балансе') { + setError('Недостаточно средств на балансе. Пополните баланс и попробуйте снова.'); + } else { + setError('Ошибка покупки сервера'); + } console.error('Ошибка покупки сервера:', err); - setError('Ошибка покупки сервера'); } setLoading(false); }; diff --git a/ospabhost/frontend/src/pages/dashboard/mainpage.tsx b/ospabhost/frontend/src/pages/dashboard/mainpage.tsx index e16b758..fd22051 100644 --- a/ospabhost/frontend/src/pages/dashboard/mainpage.tsx +++ b/ospabhost/frontend/src/pages/dashboard/mainpage.tsx @@ -7,7 +7,8 @@ import { useContext } from 'react'; // Импортируем компоненты для вкладок import Summary from './summary'; -import ServerManagementPage from './servermanagement'; +import Servers from './servers'; +import ServerPanel from './serverpanel'; import TicketsPage from './tickets'; import Billing from './billing'; import Settings from './settings'; @@ -109,11 +110,23 @@ const Dashboard = () => { ); } + // Вкладки для сайдбара + const tabs = [ + { key: 'summary', label: 'Сводка', to: '/dashboard' }, + { key: 'servers', label: 'Серверы', to: '/dashboard/servers' }, + { key: 'tickets', label: 'Тикеты', to: '/dashboard/tickets' }, + { key: 'billing', label: 'Баланс', to: '/dashboard/billing' }, + { key: 'settings', label: 'Настройки', to: '/dashboard/settings' }, + ]; + const adminTabs = [ + { key: 'checkverification', label: 'Проверка чеков', to: '/dashboard/checkverification' }, + { key: 'ticketresponse', label: 'Ответы на тикеты', to: '/dashboard/ticketresponse' }, + ]; + return (

- {/* Sidebar - фиксированный слева */} + {/* Sidebar */}
- {/* Заголовок сайдбара */}

Привет, {userData?.user?.username || 'Гость'}! @@ -127,122 +140,68 @@ const Dashboard = () => { Баланс: ₽{userData?.balance ?? 0}

- - {/* Навигация */} - - {/* Футер сайдбара */} -
-
-

© 2024 ospab.host

-

Версия 1.0.0

-
+
+

© 2025 ospab.host

+

Версия 1.0.0

- {/* Main Content - занимает оставшееся место */} + {/* Main Content */}
- {/* Хлебные крошки/заголовок */}
-
-
-

- {activeTab === 'summary' ? 'Сводка' : - activeTab === 'servers' ? 'Серверы' : - activeTab === 'tickets' ? 'Тикеты поддержки' : - activeTab === 'billing' ? 'Пополнение баланса' : - activeTab === 'settings' ? 'Настройки аккаунта' : - activeTab === 'checkverification' ? 'Проверка чеков' : - activeTab === 'ticketresponse' ? 'Ответы на тикеты' : - 'Панель управления'} -

-

- {new Date().toLocaleDateString('ru-RU', { - weekday: 'long', - year: 'numeric', - month: 'long', - day: 'numeric' - })} -

-
-
+

+ {tabs.concat(adminTabs).find(t => t.key === activeTab)?.label || 'Панель управления'} +

+

+ {new Date().toLocaleDateString('ru-RU', { + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric', + })} +

- - {/* Контент страницы */}
} /> - } /> - window.location.reload()} />} /> + } /> + } /> + navigate('/dashboard/servers')} />} /> } /> {userData && ( } /> @@ -251,7 +210,6 @@ const Dashboard = () => { } /> )} } /> - {isOperator && ( <> } /> diff --git a/ospabhost/frontend/src/pages/dashboard/servermanagement.tsx b/ospabhost/frontend/src/pages/dashboard/servermanagement.tsx deleted file mode 100644 index c6b3fbb..0000000 --- a/ospabhost/frontend/src/pages/dashboard/servermanagement.tsx +++ /dev/null @@ -1,96 +0,0 @@ -import { useEffect, useState } from 'react'; -import axios from 'axios'; -import { useNavigate } from 'react-router-dom'; -import useAuth from '../../context/useAuth'; - -interface Server { - id: number; - status: string; - createdAt: string; - updatedAt: string; - tariff: { name: string; price: number }; - os: { name: string; type: string }; -} - -const ServerManagementPage = () => { - const [servers, setServers] = useState([]); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(''); - const { isLoggedIn } = useAuth(); - const navigate = useNavigate(); - - useEffect(() => { - if (!isLoggedIn) { - navigate('/login'); - return; - } - const fetchServers = async () => { - try { - const token = localStorage.getItem('access_token'); - const res = await axios.get('http://localhost:5000/api/server', { - headers: { Authorization: `Bearer ${token}` }, - }); - setServers(res.data); - } catch { - setError('Ошибка загрузки серверов'); - setServers([]); - } - setLoading(false); - }; - fetchServers(); - }, [isLoggedIn, navigate]); - - // TODO: добавить управление сервером (включить, выключить, перезагрузить, переустановить ОС) - - try { - return ( -
-
-

Управление серверами

- {loading ? ( -

Загрузка...

- ) : error ? ( -
-

{error}

- -
- ) : servers.length === 0 ? ( -

У вас нет серверов.

- ) : ( -
- {servers.map(server => ( -
-
-

{server.tariff.name}

-

ОС: {server.os.name} ({server.os.type})

-

Статус: {server.status}

-

Создан: {new Date(server.createdAt).toLocaleString()}

-
- {/* TODO: Кнопки управления сервером */} -
- - - - -
-
- ))} -
- )} -
-
- ); - } catch { - return ( -
-
-

Ошибка отображения страницы

-

Произошла критическая ошибка. Попробуйте перезагрузить страницу.

- -
-
- ); - } -}; - -export default ServerManagementPage; diff --git a/ospabhost/frontend/src/pages/dashboard/serverpanel.tsx b/ospabhost/frontend/src/pages/dashboard/serverpanel.tsx new file mode 100644 index 0000000..c029d97 --- /dev/null +++ b/ospabhost/frontend/src/pages/dashboard/serverpanel.tsx @@ -0,0 +1,169 @@ + +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import axios, { AxiosError } from 'axios'; + +interface Server { + id: number; + status: string; + createdAt: string; + updatedAt: string; + os: { name: string; type: string }; + tariff: { name: string; price: number }; + ip?: string; + rootPassword?: string; +} + +const TABS = [ + { key: 'overview', label: 'Обзор' }, + { key: 'console', label: 'Консоль' }, + { key: 'stats', label: 'Статистика' }, + { key: 'manage', label: 'Управление' }, + { key: 'security', label: 'Безопасность' }, +]; + +const generatePassword = () => { + return Math.random().toString(36).slice(-10) + Math.random().toString(36).slice(-6); +}; + +const ServerPanel: React.FC = () => { + const { id } = useParams(); + const [server, setServer] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(''); + const [activeTab, setActiveTab] = useState('overview'); + const [newRoot, setNewRoot] = useState(null); + const [showRoot, setShowRoot] = useState(false); + + useEffect(() => { + const fetchServer = async () => { + try { + const token = localStorage.getItem('access_token'); + const headers = token ? { Authorization: `Bearer ${token}` } : {}; + const res = await axios.get(`http://localhost:5000/api/server/${id}`, { headers }); + setServer(res.data); + } catch (err) { + const error = err as AxiosError; + if (error?.response?.status === 404) { + setError('Сервер не найден или был удалён.'); + } else { + setError('Ошибка загрузки данных сервера'); + } + console.error('Ошибка загрузки данных сервера:', err); + } finally { + setLoading(false); + } + }; + fetchServer(); + }, [id]); + + // Генерация root-пароля (только для копирования) + const handleGenerateRoot = () => { + try { + const password = generatePassword(); + setNewRoot(password); + setShowRoot(true); + // TODO: отправить новый пароль на backend для смены + } catch (err) { + console.error('Ошибка генерации root-пароля:', err); + } + }; + + // Базовые действия (заглушки) + const handleAction = async (action: 'start' | 'stop' | 'restart') => { + alert(`Выполнено действие: ${action} (реализовать вызов к backend)`); + // TODO: реализовать вызов к backend + }; + + if (loading) { + return
Загрузка...
; + } + if (error) { + return ( +
+
+ {error} + +
+
+ ); + } + if (!server) { + return
Сервер не найден
; + } + + return ( +
+
+

Панель управления сервером #{server.id}

+
+ {TABS.map(tab => ( + + ))} +
+ + {activeTab === 'overview' && ( +
+
Статус: {server.status}
+
Тариф: {server.tariff.name} ({server.tariff.price}₽)
+
ОС: {server.os.name} ({server.os.type})
+
IP: {server.ip || '—'}
+
Создан: {new Date(server.createdAt).toLocaleString()}
+
Обновлён: {new Date(server.updatedAt).toLocaleString()}
+
+ )} + + {activeTab === 'console' && ( +
+
Консоль сервера (заглушка)
+
root@{server.ip || 'server'}:~# _
+
+ )} + + {activeTab === 'stats' && ( +
+
Графики нагрузки (заглушка)
+
+
CPU
+
RAM
+
+
+ )} + + {activeTab === 'manage' && ( +
+ + + +
+ )} + + {activeTab === 'security' && ( +
+ + {showRoot && newRoot && ( +
+
Ваш новый root-пароль:
+
{newRoot}
+
Скопируйте пароль — он будет показан только один раз!
+
+ )} +
+ )} +
+
+ ); +}; + +export default ServerPanel; diff --git a/ospabhost/frontend/src/pages/dashboard/servers.tsx b/ospabhost/frontend/src/pages/dashboard/servers.tsx index 97a3d95..fa1084c 100644 --- a/ospabhost/frontend/src/pages/dashboard/servers.tsx +++ b/ospabhost/frontend/src/pages/dashboard/servers.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from 'react'; import axios from 'axios'; +import { Link } from 'react-router-dom'; interface Server { id: number; @@ -18,7 +19,9 @@ const Servers: React.FC = () => { useEffect(() => { const fetchServers = async () => { try { - const res = await axios.get('http://localhost:5000/api/server'); + const token = localStorage.getItem('access_token'); + const headers = token ? { Authorization: `Bearer ${token}` } : {}; + const res = await axios.get('http://localhost:5000/api/server', { headers }); console.log('Ответ API серверов:', res.data); // Защита от получения HTML вместо JSON if (typeof res.data === 'string' && res.data.startsWith(' { return (
-

Серверы

- {/* Кнопка 'Купить сервер' только если серверов нет */} +

Мои серверы

{servers.length === 0 && !loading && !error && ( Купить сервер )} @@ -62,10 +64,28 @@ const Servers: React.FC = () => { Посмотреть тарифы
) : ( -
- Перейти к управлению серверами +
+ {servers.map(server => ( +
+
+

{server.tariff.name}

+

ОС: {server.os.name} ({server.os.type})

+

Статус: {server.status}

+

Создан: {new Date(server.createdAt).toLocaleString()}

+

Обновлён: {new Date(server.updatedAt).toLocaleString()}

+
+
+ + Перейти в панель управления + +
+
+ ))}
- )} + )}
); }; diff --git a/ospabhost/frontend/src/pages/login.tsx b/ospabhost/frontend/src/pages/login.tsx index bcdea45..3039f23 100644 --- a/ospabhost/frontend/src/pages/login.tsx +++ b/ospabhost/frontend/src/pages/login.tsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useEffect } from 'react'; import { Link, useNavigate, useLocation } from 'react-router-dom'; import axios from 'axios'; import useAuth from '../context/useAuth'; @@ -10,27 +10,30 @@ const LoginPage = () => { const [isLoading, setIsLoading] = useState(false); const navigate = useNavigate(); const location = useLocation(); - const { login } = useAuth(); + const { login, isLoggedIn } = useAuth(); + + // Если уже авторизован — редирект на dashboard + useEffect(() => { + if (isLoggedIn) { + navigate('/dashboard', { replace: true }); + } + }, [isLoggedIn, navigate]); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setError(''); setIsLoading(true); - try { const response = await axios.post('http://localhost:5000/api/auth/login', { email: email, password: password, }); - - localStorage.setItem('token', response.data.token); - login(response.data.token); - // Возврат на исходную страницу, если был редирект - type LocationState = { from?: { pathname?: string } }; - const state = location.state as LocationState | null; - const from = state?.from?.pathname || '/dashboard'; - navigate(from); - + login(response.data.token); + // Возврат на исходную страницу, если был редирект + type LocationState = { from?: { pathname?: string } }; + const state = location.state as LocationState | null; + const from = state?.from?.pathname || '/dashboard'; + navigate(from); } catch (err) { if (axios.isAxiosError(err) && err.response) { setError(err.response.data.message || 'Неизвестная ошибка входа.');