fix: home
This commit is contained in:
@@ -8,7 +8,7 @@ interface ProtectedRouteProps {
|
|||||||
|
|
||||||
export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
|
export const ProtectedRoute: React.FC<ProtectedRouteProps> = ({
|
||||||
children,
|
children,
|
||||||
fallbackPath = "/",
|
fallbackPath = "/auth",
|
||||||
}) => {
|
}) => {
|
||||||
const isAuthenticated = authService.isAuthenticated();
|
const isAuthenticated = authService.isAuthenticated();
|
||||||
|
|
||||||
|
|||||||
@@ -17,16 +17,13 @@ export const Routing = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<ReactRoutes>
|
<ReactRoutes>
|
||||||
<Route path="/" element={<AuthPage />} />
|
<Route path="/" element={<HomePage />} />
|
||||||
|
<Route path="/auth" element={<AuthPage />} />
|
||||||
<Route
|
<Route
|
||||||
path="/create-organization"
|
path="/create-organization"
|
||||||
element={<CreateOrganizationPage />}
|
|
||||||
/>
|
|
||||||
<Route
|
|
||||||
path="/home"
|
|
||||||
element={
|
element={
|
||||||
<ProtectedRoute>
|
<ProtectedRoute>
|
||||||
<HomePage />
|
<CreateOrganizationPage />
|
||||||
</ProtectedRoute>
|
</ProtectedRoute>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import type {
|
|||||||
LoginCredentials,
|
LoginCredentials,
|
||||||
RegisterData,
|
RegisterData,
|
||||||
OrganizationCreateData,
|
OrganizationCreateData,
|
||||||
OrganizationMember,
|
|
||||||
} from "../types/auth.types";
|
} from "../types/auth.types";
|
||||||
|
|
||||||
export const useAuth = () => {
|
export const useAuth = () => {
|
||||||
@@ -24,7 +23,7 @@ export const useAuth = () => {
|
|||||||
const orgs = await request(() => authService.getOrganizations());
|
const orgs = await request(() => authService.getOrganizations());
|
||||||
if (orgs && orgs.length > 0) {
|
if (orgs && orgs.length > 0) {
|
||||||
authService.saveOrganization(orgs[0]);
|
authService.saveOrganization(orgs[0]);
|
||||||
navigate("/home");
|
navigate("/");
|
||||||
} else {
|
} else {
|
||||||
navigate("/create-organization");
|
navigate("/create-organization");
|
||||||
}
|
}
|
||||||
@@ -58,7 +57,7 @@ export const useAuth = () => {
|
|||||||
|
|
||||||
if (result) {
|
if (result) {
|
||||||
authService.saveOrganization(result);
|
authService.saveOrganization(result);
|
||||||
navigate("/home");
|
navigate("/");
|
||||||
} else if (error) {
|
} else if (error) {
|
||||||
setAuthError(error);
|
setAuthError(error);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-2
@@ -1,17 +1,30 @@
|
|||||||
import { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import { ThemeToggle } from "@/modules/theme-changer/ui/Theme.toggle";
|
import { ThemeToggle } from "@/modules/theme-changer/ui/Theme.toggle";
|
||||||
import { LoginForm } from "@/modules/auth/components/LoginForm";
|
import { LoginForm } from "@/modules/auth/components/LoginForm";
|
||||||
import { RegisterForm } from "@/modules/auth/components/RegisterForm";
|
import { RegisterForm } from "@/modules/auth/components/RegisterForm";
|
||||||
|
|
||||||
export const AuthPage = () => {
|
export const AuthPage = () => {
|
||||||
const [isLogin, setIsLogin] = useState(true);
|
const [isLogin, setIsLogin] = useState(true);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="min-h-screen flex items-center justify-center p-4 transition-theme"
|
className="min-h-screen flex items-center justify-center p-4 transition-theme"
|
||||||
style={{ backgroundColor: "var(--bg-primary)" }}
|
style={{ backgroundColor: "var(--bg-primary)" }}
|
||||||
>
|
>
|
||||||
<div className="absolute top-4 right-4">
|
<div className="absolute top-4 right-4 flex gap-4">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate("/")}
|
||||||
|
className="px-4 py-2 rounded-lg font-medium transition-all hover:scale-105"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--bg-secondary)",
|
||||||
|
color: "var(--text-primary)",
|
||||||
|
border: `1px solid var(--border)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
На главную
|
||||||
|
</button>
|
||||||
<ThemeToggle />
|
<ThemeToggle />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+197
-12
@@ -6,7 +6,6 @@ import {
|
|||||||
Shield,
|
Shield,
|
||||||
Users,
|
Users,
|
||||||
Bot,
|
Bot,
|
||||||
Settings,
|
|
||||||
Activity,
|
Activity,
|
||||||
LogOut,
|
LogOut,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
@@ -20,11 +19,14 @@ import {
|
|||||||
AlertCircle,
|
AlertCircle,
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
Clock,
|
Clock,
|
||||||
|
LogIn,
|
||||||
|
UserPlus,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
||||||
export const HomePage = () => {
|
export const HomePage = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { logout } = useAuth();
|
const { logout } = useAuth();
|
||||||
|
const isAuthenticated = authService.isAuthenticated();
|
||||||
const organization = authService.getCurrentOrganization();
|
const organization = authService.getCurrentOrganization();
|
||||||
const authStorage = localStorage.getItem("auth-storage");
|
const authStorage = localStorage.getItem("auth-storage");
|
||||||
const user = authStorage ? JSON.parse(authStorage).state?.user : null;
|
const user = authStorage ? JSON.parse(authStorage).state?.user : null;
|
||||||
@@ -72,7 +74,35 @@ export const HomePage = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const quickActions = [
|
const features = [
|
||||||
|
{
|
||||||
|
title: "Централизованное управление",
|
||||||
|
description: "Управляйте всеми IPS агентами из единого интерфейса",
|
||||||
|
icon: Server,
|
||||||
|
color: "#6366f1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "AI Аналитика",
|
||||||
|
description: "Искусственный интеллект помогает находить сложные атаки",
|
||||||
|
icon: Bot,
|
||||||
|
color: "#8b5cf6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Мгновенная блокировка",
|
||||||
|
description: "Автоматическая блокировка IP при обнаружении угроз",
|
||||||
|
icon: Zap,
|
||||||
|
color: "#f59e0b",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Безопасность данных",
|
||||||
|
description: "LLM не получает доступ к чувствительным логам",
|
||||||
|
icon: Lock,
|
||||||
|
color: "#22c55e",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const quickActions = isAuthenticated
|
||||||
|
? [
|
||||||
{
|
{
|
||||||
name: "IPS Агенты",
|
name: "IPS Агенты",
|
||||||
icon: Server,
|
icon: Server,
|
||||||
@@ -101,7 +131,8 @@ export const HomePage = () => {
|
|||||||
description: "Управление доступом",
|
description: "Управление доступом",
|
||||||
color: "#f59e0b",
|
color: "#f59e0b",
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
: [];
|
||||||
|
|
||||||
const getSeverityStyles = (severity: string) => {
|
const getSeverityStyles = (severity: string) => {
|
||||||
switch (severity) {
|
switch (severity) {
|
||||||
@@ -169,6 +200,8 @@ export const HomePage = () => {
|
|||||||
|
|
||||||
{/* Right section */}
|
{/* Right section */}
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
|
{isAuthenticated ? (
|
||||||
|
<>
|
||||||
<button
|
<button
|
||||||
className="relative p-2 rounded-lg transition-all hover:scale-105"
|
className="relative p-2 rounded-lg transition-all hover:scale-105"
|
||||||
style={{ backgroundColor: "var(--bg-secondary)" }}
|
style={{ backgroundColor: "var(--bg-secondary)" }}
|
||||||
@@ -198,7 +231,10 @@ export const HomePage = () => {
|
|||||||
>
|
>
|
||||||
{user?.first_name} {user?.last_name}
|
{user?.first_name} {user?.last_name}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs" style={{ color: "var(--text-muted)" }}>
|
<p
|
||||||
|
className="text-xs"
|
||||||
|
style={{ color: "var(--text-muted)" }}
|
||||||
|
>
|
||||||
Администратор
|
Администратор
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -210,13 +246,42 @@ export const HomePage = () => {
|
|||||||
>
|
>
|
||||||
<LogOut className="w-5 h-5 text-white" />
|
<LogOut className="w-5 h-5 text-white" />
|
||||||
</button>
|
</button>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<ThemeToggle />
|
||||||
|
<button
|
||||||
|
onClick={() => navigate("/auth")}
|
||||||
|
className="px-4 py-2 rounded-lg font-medium transition-all flex items-center gap-2 hover:scale-105"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--bg-secondary)",
|
||||||
|
color: "var(--text-primary)",
|
||||||
|
border: `1px solid var(--border)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<LogIn className="w-4 h-4" />
|
||||||
|
Войти
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => navigate("/auth")}
|
||||||
|
className="px-4 py-2 rounded-lg font-medium transition-all flex items-center gap-2 hover:scale-105"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--accent)",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<UserPlus className="w-4 h-4" />
|
||||||
|
Регистрация
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container mx-auto px-6 py-8">
|
<main className="container mx-auto px-6 py-8">
|
||||||
{/* Welcome Section */}
|
{/* Hero Section */}
|
||||||
<div
|
<div
|
||||||
className="rounded-2xl p-8 mb-8 text-white relative overflow-hidden"
|
className="rounded-2xl p-8 mb-8 text-white relative overflow-hidden"
|
||||||
style={{
|
style={{
|
||||||
@@ -227,17 +292,36 @@ export const HomePage = () => {
|
|||||||
<div className="flex justify-between items-start">
|
<div className="flex justify-between items-start">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-3xl font-bold mb-2">
|
<h2 className="text-3xl font-bold mb-2">
|
||||||
Добро пожаловать, {user?.first_name || "Администратор"}!
|
{isAuthenticated
|
||||||
|
? `Добро пожаловать, ${user?.first_name || "Администратор"}!`
|
||||||
|
: "Добро пожаловать в IPS Manager"}
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-white/80 text-lg">
|
<p className="text-white/80 text-lg">
|
||||||
Система IPS мониторинга и защиты
|
{isAuthenticated
|
||||||
|
? "Система IPS мониторинга и защиты"
|
||||||
|
: "Современная платформа для централизованного управления IPS агентами"}
|
||||||
</p>
|
</p>
|
||||||
|
{!isAuthenticated && (
|
||||||
|
<div className="flex gap-4 mt-6">
|
||||||
|
<button
|
||||||
|
onClick={() => navigate("/auth")}
|
||||||
|
className="px-6 py-2 rounded-lg font-medium bg-white text-indigo-600 transition-all hover:scale-105 hover:shadow-lg"
|
||||||
|
>
|
||||||
|
Начать работу
|
||||||
|
</button>
|
||||||
|
<button className="px-6 py-2 rounded-lg font-medium border border-white/30 transition-all hover:bg-white/10">
|
||||||
|
Узнать больше
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{isAuthenticated && (
|
||||||
<div className="flex items-center gap-2 mt-4">
|
<div className="flex items-center gap-2 mt-4">
|
||||||
<Zap className="w-5 h-5" />
|
<Zap className="w-5 h-5" />
|
||||||
<span className="text-white/90">
|
<span className="text-white/90">
|
||||||
Все системы работают стабильно
|
Все системы работают стабильно
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="hidden lg:block opacity-20">
|
<div className="hidden lg:block opacity-20">
|
||||||
<Cloud className="w-32 h-32" />
|
<Cloud className="w-32 h-32" />
|
||||||
@@ -246,7 +330,8 @@ export const HomePage = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Stats Grid */}
|
{/* Stats Grid - только для авторизованных */}
|
||||||
|
{isAuthenticated && (
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||||
{stats.map((stat, index) => {
|
{stats.map((stat, index) => {
|
||||||
const Icon = stat.icon;
|
const Icon = stat.icon;
|
||||||
@@ -303,7 +388,62 @@ export const HomePage = () => {
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Features Section - для всех */}
|
||||||
|
<div className="mb-8">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<h2
|
||||||
|
className="text-2xl font-bold mb-2"
|
||||||
|
style={{ color: "var(--text-primary)" }}
|
||||||
|
>
|
||||||
|
Ключевые возможности
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm" style={{ color: "var(--text-secondary)" }}>
|
||||||
|
Всё необходимое для защиты вашей инфраструктуры
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||||
|
{features.map((feature, index) => {
|
||||||
|
const Icon = feature.icon;
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="rounded-2xl p-6 transition-all hover:scale-105 hover:shadow-xl text-center"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--card-bg)",
|
||||||
|
boxShadow: `0 4px 6px -1px var(--shadow-color)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="w-14 h-14 rounded-xl flex items-center justify-center mx-auto mb-4"
|
||||||
|
style={{ backgroundColor: `${feature.color}20` }}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
className="w-7 h-7"
|
||||||
|
style={{ color: feature.color }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<h3
|
||||||
|
className="font-bold mb-2"
|
||||||
|
style={{ color: "var(--text-primary)" }}
|
||||||
|
>
|
||||||
|
{feature.title}
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="text-sm"
|
||||||
|
style={{ color: "var(--text-secondary)" }}
|
||||||
|
>
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isAuthenticated ? (
|
||||||
|
<>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
{/* Quick Actions */}
|
{/* Quick Actions */}
|
||||||
<div className="lg:col-span-2">
|
<div className="lg:col-span-2">
|
||||||
@@ -497,8 +637,12 @@ export const HomePage = () => {
|
|||||||
>
|
>
|
||||||
🔍 Обнаружена аномалия
|
🔍 Обнаружена аномалия
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs" style={{ color: "var(--text-secondary)" }}>
|
<p
|
||||||
Повышенная активность с IP-адресов из диапазона 185.xxx.xx.xx
|
className="text-xs"
|
||||||
|
style={{ color: "var(--text-secondary)" }}
|
||||||
|
>
|
||||||
|
Повышенная активность с IP-адресов из диапазона
|
||||||
|
185.xxx.xx.xx
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
@@ -511,7 +655,10 @@ export const HomePage = () => {
|
|||||||
>
|
>
|
||||||
💡 Предложено правил
|
💡 Предложено правил
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs" style={{ color: "var(--text-secondary)" }}>
|
<p
|
||||||
|
className="text-xs"
|
||||||
|
style={{ color: "var(--text-secondary)" }}
|
||||||
|
>
|
||||||
AI предлагает 3 новых правила для блокировки бот-сканеров
|
AI предлагает 3 новых правила для блокировки бот-сканеров
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -525,13 +672,51 @@ export const HomePage = () => {
|
|||||||
>
|
>
|
||||||
⚡ Оптимизация
|
⚡ Оптимизация
|
||||||
</p>
|
</p>
|
||||||
<p className="text-xs" style={{ color: "var(--text-secondary)" }}>
|
<p
|
||||||
|
className="text-xs"
|
||||||
|
style={{ color: "var(--text-secondary)" }}
|
||||||
|
>
|
||||||
Рекомендуется обновить 5 существующих правил для повышения
|
Рекомендуется обновить 5 существующих правил для повышения
|
||||||
эффективности
|
эффективности
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
/* CTA Section для неавторизованных */
|
||||||
|
<div
|
||||||
|
className="rounded-2xl p-8 text-center"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--card-bg)",
|
||||||
|
boxShadow: `0 4px 6px -1px var(--shadow-color)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<h3
|
||||||
|
className="text-2xl font-bold mb-2"
|
||||||
|
style={{ color: "var(--text-primary)" }}
|
||||||
|
>
|
||||||
|
Готовы начать?
|
||||||
|
</h3>
|
||||||
|
<p
|
||||||
|
className="text-sm mb-6"
|
||||||
|
style={{ color: "var(--text-secondary)" }}
|
||||||
|
>
|
||||||
|
Присоединяйтесь к IPS Manager и получите полный контроль над
|
||||||
|
безопасностью
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => navigate("/auth")}
|
||||||
|
className="px-6 py-2 rounded-lg font-medium transition-all hover:scale-105"
|
||||||
|
style={{
|
||||||
|
backgroundColor: "var(--accent)",
|
||||||
|
color: "white",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Начать работу
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user