copied the code from the working repo

This commit is contained in:
2024-11-30 16:00:48 +03:00
parent f22b92869b
commit 15ac0cb9b8
148 changed files with 23342 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
'use client';
import React, { createContext, useContext, useState, useEffect } from 'react';
interface AuthContextType {
isAuthenticated: boolean;
loading: boolean;
login: (token: string, expiresAt: number) => void;
logout: () => void;
}
const AuthContext = createContext<AuthContextType | undefined>(undefined);
export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
useEffect(() => {
const token = localStorage.getItem('token');
const expiresAt = localStorage.getItem('expiresAt');
if (token && expiresAt && new Date().getTime() < Number(expiresAt)) {
setIsAuthenticated(true);
} else {
setIsAuthenticated(false);
}
setLoading(false); // завершение проверки
}, []);
const login = (token: string, expiresInSeconds: number) => {
const expiresAt = new Date().getTime() + expiresInSeconds * 1000;
localStorage.setItem('expiresAt', expiresAt.toString());
setIsAuthenticated(true);
};
const logout = () => {
localStorage.removeItem('token');
localStorage.removeItem('expiresAt');
setIsAuthenticated(false);
};
return (
<AuthContext.Provider value={{ isAuthenticated, loading, login, logout }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = (): AuthContextType => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};

View File

@@ -0,0 +1,30 @@
'use client';
import { useRouter, usePathname } from 'next/navigation';
import { useEffect } from 'react';
import { useAuth } from '@/fsd/app/provider/AuthContext';
const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { isAuthenticated, loading } = useAuth();
const router = useRouter();
const pathname = usePathname();
useEffect(() => {
if (!loading) {
if (!isAuthenticated && pathname !== '/login') {
router.replace('/login');
}
}
}, [loading, isAuthenticated, pathname, router]);
if (loading) {
return <div>Loading...</div>; // Показываем загрузку
}
if (!isAuthenticated && pathname !== '/login') {
return null; // Не рендерим контент до завершения редиректа
}
return <>{children}</>;
};
export default AuthGuard;

View File

@@ -0,0 +1,14 @@
'use client';
import { PropsWithChildren } from 'react';
import { QueryClient, QueryClientProvider } from 'react-query';
export const queryClient = new QueryClient();
const ClientProvider = ({ children }: PropsWithChildren) => {
return (
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
);
};
export default ClientProvider;

View File

@@ -0,0 +1,25 @@
'use client';
import React, { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/fsd/app/provider/AuthContext';
const AuthGuard: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const { isAuthenticated } = useAuth();
const router = useRouter();
useEffect(() => {
if (!isAuthenticated) {
router.replace('/login');
}
}, [isAuthenticated, router]);
if (!isAuthenticated) {
return null; // Или можно отобразить загрузочный экран
}
return <>{children}</>;
};
export default AuthGuard;

View File

@@ -0,0 +1,182 @@
body {
background-image: url('../../../public/backgorund.png');
font-family: 'Montserrat', sans-serif;
}
/* Reset and base styles */
* {
padding: 0px;
margin: 0px;
border: none;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
/* Links */
a,
a:link,
a:visited {
text-decoration: none;
}
a:hover {
text-decoration: none;
}
/* Common */
aside,
nav,
footer,
header,
section,
main {
display: block;
}
h1,
h2,
h3,
h4,
h5,
h6,
p {
font-size: inherit;
font-weight: inherit;
}
ul,
ul li {
list-style: none;
}
img {
vertical-align: top;
}
img,
svg {
max-width: 100%;
height: auto;
}
address {
font-style: normal;
}
/* Form */
input,
textarea,
button,
select {
font-family: inherit;
font-size: inherit;
color: inherit;
background-color: transparent;
}
input::-ms-clear {
display: none;
}
button,
input[type='submit'] {
display: inline-block;
box-shadow: none;
background-color: transparent;
background: none;
cursor: pointer;
}
input:focus,
input:active,
button:focus,
button:active {
outline: none;
}
button::-moz-focus-inner {
padding: 0;
border: 0;
}
label {
cursor: pointer;
}
legend {
display: block;
}
.ant-menu-item-selected {
background-color: #372579 !important;
}
.ant-input-outlined {
&:focus {
border-color: #372579;
outline: none;
box-shadow: 0 0 0 2px rgba(55, 37, 121, 0.1);
}
&:hover {
border-color: #372579;
}
}
.ant-select .ant-select-selector {
&:hover {
border-color: #372579 !important;
}
&:focus-within {
border-color: #372579 !important;
outline: none !important;
box-shadow: 0 0 0 2px rgba(55, 37, 121, 0.1) !important;
}
}
.ant-input-number-outlined {
&:hover {
border-color: #372579 !important;
}
&:focus-within {
border-color: #372579 !important;
outline: none !important;
box-shadow: 0 0 0 2px rgba(55, 37, 121, 0.1) !important;
}
}
.ant-checkbox-inner {
background-color: #ffffff;
border: 2px solid #d9d9d9;
transition: all 0.3s;
}
.ant-checkbox-checked .ant-checkbox-inner{
background-color: #372579 !important;
border-color: #372579 !important;
outline: none !important;
box-shadow: 0 0 0 2px rgba(55, 37, 121, 0.1) !important;
&:hover {
border-color: #372579 !important;
background: #47309c !important;
}
}
:where(.css-dev-only-do-not-override-1uq9j6g).ant-checkbox-wrapper:not(.ant-checkbox-wrapper-disabled):hover .ant-checkbox-inner, :where(.css-dev-only-do-not-override-1uq9j6g).ant-checkbox:not(.ant-checkbox-disabled):hover .ant-checkbox-inner{
border-color: #372579;
}
.ant-checkbox:hover .ant-checkbox-inner,
.ant-checkbox-inner:focus {
border-color: #372579; /* цвет бордюра при ховере */
border-color: #372579 !important;
background-color: #f0f0f0; /* цвет фона при ховере */
outline: none; /* убираем outline при фокусе */
box-shadow: 0 0 0 2px rgba(55, 37, 121, 0.1);
}