рефакторинг структуры
This commit is contained in:
@@ -5,10 +5,12 @@ import { LoginPage, RegisterPage, ResetPasswordPage } from "@/pages/auth";
|
|||||||
import { HomePage } from "@/pages/home";
|
import { HomePage } from "@/pages/home";
|
||||||
import { MailingById, MailingsPage } from "@/pages/mailings";
|
import { MailingById, MailingsPage } from "@/pages/mailings";
|
||||||
import { SuppliersSearchPage } from "@/pages/suppliers-search";
|
import { SuppliersSearchPage } from "@/pages/suppliers-search";
|
||||||
|
import { SuppliersSearchProvider } from "@/pages/suppliers-search/model/SuppliersSearchContext";
|
||||||
import { ViewingRequestById, ViewingRequestsPage } from "@/pages/viewing-requests";
|
import { ViewingRequestById, ViewingRequestsPage } from "@/pages/viewing-requests";
|
||||||
import { AuthProvider, SuppliersSearchProvider, useAuth } from "@/shared/model";
|
|
||||||
import { UILoader } from "@/shared/ui";
|
import { UILoader } from "@/shared/ui";
|
||||||
|
|
||||||
|
import { AuthProvider, useAuth } from "./providers/AuthContext";
|
||||||
|
|
||||||
const AppContent = () => {
|
const AppContent = () => {
|
||||||
const { user, loading } = useAuth();
|
const { user, loading } = useAuth();
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import { Menu } from 'lucide-react';
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useDevices } from "@/shared/lib";
|
||||||
import { Sidebar } from '@/widgets/sidebar'
|
import { Sidebar } from '@/widgets/sidebar'
|
||||||
|
|
||||||
export const AppLayout = () => {
|
export const AppLayout = () => {
|
||||||
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
||||||
|
const { isMobile } = useDevices()
|
||||||
// Функция переключения состояния сайдбара
|
// Функция переключения состояния сайдбара
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = () => {
|
||||||
setIsSidebarOpen(!isSidebarOpen);
|
setIsSidebarOpen(!isSidebarOpen);
|
||||||
@@ -21,11 +22,13 @@ export const AppLayout = () => {
|
|||||||
<div className="min-h-screen bg-gray-50 flex">
|
<div className="min-h-screen bg-gray-50 flex">
|
||||||
<Sidebar isOpen={isSidebarOpen} onClose={closeSidebar} />
|
<Sidebar isOpen={isSidebarOpen} onClose={closeSidebar} />
|
||||||
|
|
||||||
<div className="flex-1 flex flex-col min-h-screen">
|
<div className="flex-1 flex flex-col">
|
||||||
{/* Кнопка в хедере только для мобильных */}
|
{/* Кнопка в хедере только для мобильных */}
|
||||||
<header className="lg:hidden bg-white border-b border-gray-200 p-4">
|
{isMobile && (
|
||||||
<Menu className="w-6 h-6 cursor-pointer hover:bg-gray-200" onClick={() => toggleSidebar()}/>
|
<header className="lg:hidden bg-white border-b border-gray-200 p-4">
|
||||||
</header>
|
<Menu className="w-6 h-6 cursor-pointer hover:bg-gray-200" onClick={() => toggleSidebar()}/>
|
||||||
|
</header>
|
||||||
|
)}
|
||||||
|
|
||||||
<main className="flex-1 p-6 lg:p-8">
|
<main className="flex-1 p-6 lg:p-8">
|
||||||
<Outlet />
|
<Outlet />
|
||||||
|
|||||||
1
src/entities/mailing/index.ts
Normal file
1
src/entities/mailing/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { MailingItem } from './ui/MailingItem'
|
||||||
@@ -9,7 +9,7 @@ interface IProps {
|
|||||||
onSelectItem: (id: string | number) => void
|
onSelectItem: (id: string | number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MailingsItem = (props: IProps) => {
|
export const MailingItem = (props: IProps) => {
|
||||||
const { item, onSelectItem } = props;
|
const { item, onSelectItem } = props;
|
||||||
|
|
||||||
const statusIcon = useMemo(() => {
|
const statusIcon = useMemo(() => {
|
||||||
1
src/entities/supplier/index.ts
Normal file
1
src/entities/supplier/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { SuppliersTable } from './ui/SuppliersTable'
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ArrowBigLeft } from "lucide-react";
|
import { ArrowBigLeft } from "lucide-react";
|
||||||
|
|
||||||
|
import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext";
|
||||||
import { ISupplier } from "@/shared/api";
|
import { ISupplier } from "@/shared/api";
|
||||||
import { useSuppliersSearch } from "@/shared/model";
|
|
||||||
import {
|
import {
|
||||||
ButtonSize,
|
ButtonSize,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
1
src/entities/viewing-requests/index.ts
Normal file
1
src/entities/viewing-requests/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { ViewingRequestItem } from './ui/ViewingRequestItem'
|
||||||
1
src/features/suppliers-search/request-input/index.ts
Normal file
1
src/features/suppliers-search/request-input/index.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export { RequestInputForm } from './ui/RequestInputForm'
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { Send } from 'lucide-react';
|
import { Send } from 'lucide-react';
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
|
import { useAuth } from "@/app/providers/AuthContext";
|
||||||
|
import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext";
|
||||||
import { suppliersSearchApi } from '@/shared/api';
|
import { suppliersSearchApi } from '@/shared/api';
|
||||||
import { useAuth, useSuppliersSearch } from "@/shared/model";
|
|
||||||
import {
|
import {
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
NotificationAppearance,
|
NotificationAppearance,
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { TechnicalSpecification } from './ui/TechnicalSpecification'
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { ArrowBigLeft, Search } from 'lucide-react';
|
import { ArrowBigLeft, Search } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { useAuth } from "@/app/providers/AuthContext";
|
||||||
|
import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext";
|
||||||
import { suppliersSearchApi } from '@/shared/api';
|
import { suppliersSearchApi } from '@/shared/api';
|
||||||
import { useAuth, useSuppliersSearch } from "@/shared/model";
|
|
||||||
import {
|
import {
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
NotificationAppearance,
|
NotificationAppearance,
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Link, useNavigate } from "react-router";
|
import { Link, useNavigate } from "react-router";
|
||||||
|
|
||||||
|
import { useAuth } from "@/app/providers/AuthContext";
|
||||||
import { authApi } from "@/shared/api/endpoints/auth/auth-api";
|
import { authApi } from "@/shared/api/endpoints/auth/auth-api";
|
||||||
import { ROUTES, useAuth } from "@/shared/model";
|
import { ROUTES } from "@/shared/model";
|
||||||
import { ButtonType, InputType, UIButton, UIInput } from "@/shared/ui";
|
import { ButtonType, InputType, UIButton, UIInput } from "@/shared/ui";
|
||||||
|
|
||||||
export const LoginPage = () => {
|
export const LoginPage = () => {
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import { useState } from 'react';
|
|||||||
import { Link } from "react-router";
|
import { Link } from "react-router";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { useAuth } from "@/app/providers/AuthContext";
|
||||||
import { authApi } from '@/shared/api';
|
import { authApi } from '@/shared/api';
|
||||||
import { ROUTES, useAuth } from "@/shared/model";
|
import { ROUTES } from "@/shared/model";
|
||||||
import { ButtonType, InputType, UIButton, UIInput, UIPhoneNumber } from '@/shared/ui';
|
import { ButtonType, InputType, UIButton, UIInput, UIPhoneNumber } from '@/shared/ui';
|
||||||
|
|
||||||
export const RegisterPage = () => {
|
export const RegisterPage = () => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { useParams } from "react-router";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api";
|
import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api";
|
||||||
import { ROUTES } from "@/shared/model/routes";
|
import { ROUTES } from "@/shared/model";
|
||||||
import {
|
import {
|
||||||
ButtonVariant, Column,
|
ButtonVariant, Column,
|
||||||
NotificationAppearance,
|
NotificationAppearance,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { MailingsItem } from "@/pages/mailings/ui/MailingsItem";
|
import { MailingItem } from "@/entities/mailing";
|
||||||
import { IMailingItem, mailingApi } from "@/shared/api";
|
import { IMailingItem, mailingApi } from "@/shared/api";
|
||||||
import { ROUTES } from "@/shared/model";
|
import { ROUTES } from "@/shared/model";
|
||||||
import {
|
import {
|
||||||
@@ -62,7 +62,7 @@ export const MailingsPage = () => {
|
|||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
{mailingList.length > 0 && (
|
{mailingList.length > 0 && (
|
||||||
mailingList.map((item) => (
|
mailingList.map((item) => (
|
||||||
<MailingsItem
|
<MailingItem
|
||||||
key={item.request_id}
|
key={item.request_id}
|
||||||
item={item}
|
item={item}
|
||||||
onSelectItem={() => navigate(`${ROUTES.MAILINGS}/${item.request_id}`)}
|
onSelectItem={() => navigate(`${ROUTES.MAILINGS}/${item.request_id}`)}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const SuppliersSearchContext = createContext<ISuppliersSearchContext>({
|
|||||||
export const useSuppliersSearch = () => {
|
export const useSuppliersSearch = () => {
|
||||||
const context = useContext(SuppliersSearchContext);
|
const context = useContext(SuppliersSearchContext);
|
||||||
if (!context) {
|
if (!context) {
|
||||||
throw new Error('useSuppliersSearch must be used within AuthProvider');
|
throw new Error('useSuppliersSearch must be used within AuthContext');
|
||||||
}
|
}
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
import { StagesEnum } from "@/pages/suppliers-search";
|
import { SuppliersTable } from "@/entities/supplier";
|
||||||
import { RequestInputForm } from "@/pages/suppliers-search/ui/RequestInputForm";
|
import { RequestInputForm } from "@/features/suppliers-search/request-input";
|
||||||
import { SuppliersTable } from "@/pages/suppliers-search/ui/SuppliersTable";
|
import { TechnicalSpecification } from "@/features/suppliers-search/technical-specification";
|
||||||
import { TechnicalSpecification } from "@/pages/suppliers-search/ui/TechnicalSpecification";
|
import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext";
|
||||||
import { useSuppliersSearch } from "@/shared/model";
|
|
||||||
import { UIStepper } from "@/shared/ui";
|
import { UIStepper } from "@/shared/ui";
|
||||||
|
|
||||||
|
import { StagesEnum } from "../model/types";
|
||||||
|
|
||||||
export const SuppliersSearchPage = () => {
|
export const SuppliersSearchPage = () => {
|
||||||
const [stage, setStage] = useState<StagesEnum>(StagesEnum.Input);
|
const [stage, setStage] = useState<StagesEnum>(StagesEnum.Input);
|
||||||
const { suppliers, updateSuppliersSearchContext } = useSuppliersSearch();
|
const { suppliers, updateSuppliersSearchContext } = useSuppliersSearch();
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
export { ViewingRequestsPage } from './ui/ViewingRequests'
|
export { ViewingRequestsPage } from './ui/ViewingRequests'
|
||||||
export { ViewingRequestById } from './ui/ViewingRequestById'
|
export { ViewingRequestById } from './ui/ViewingRequestById'
|
||||||
export { ViewingRequestItem } from './ui/ViewingRequestItem'
|
|
||||||
@@ -3,7 +3,6 @@ import { useEffect, useState } from "react";
|
|||||||
import { useParams } from "react-router";
|
import { useParams } from "react-router";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api";
|
import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api";
|
||||||
import {
|
import {
|
||||||
ButtonSize,
|
ButtonSize,
|
||||||
@@ -103,7 +102,6 @@ export const ViewingRequestById = () => {
|
|||||||
value={message}
|
value={message}
|
||||||
placeholder="Текст сообщения"
|
placeholder="Текст сообщения"
|
||||||
onChange={(val) => setMessage(val)}
|
onChange={(val) => setMessage(val)}
|
||||||
minCount={10}
|
|
||||||
minHeight={500}
|
minHeight={500}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { ViewingRequestItem } from "@/entities/viewing-requests";
|
||||||
import { IMailingItem, mailingApi } from "@/shared/api";
|
import { IMailingItem, mailingApi } from "@/shared/api";
|
||||||
import { ROUTES } from "@/shared/model/routes";
|
import { ROUTES } from "@/shared/model";
|
||||||
import {
|
import {
|
||||||
NotificationAppearance,
|
NotificationAppearance,
|
||||||
UILoader,
|
UILoader,
|
||||||
UINotification,
|
UINotification,
|
||||||
} from "@/shared/ui";
|
} from "@/shared/ui";
|
||||||
|
|
||||||
import { ViewingRequestItem } from "./ViewingRequestItem";
|
|
||||||
|
|
||||||
export const ViewingRequestsPage = () => {
|
export const ViewingRequestsPage = () => {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ export const useDevices = (): UseDevicesType => {
|
|||||||
const [ isDesktop, setIsDesktop ] = useState<boolean>(window.innerWidth > 880)
|
const [ isDesktop, setIsDesktop ] = useState<boolean>(window.innerWidth > 880)
|
||||||
|
|
||||||
const updateIsMobile = () => {
|
const updateIsMobile = () => {
|
||||||
setIsMobile(window.innerWidth < 880)
|
setIsMobile(window.innerWidth < 1024)
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateIsDesktop = () => {
|
const updateIsDesktop = () => {
|
||||||
setIsDesktop(window.innerWidth >= 880)
|
setIsDesktop(window.innerWidth >= 1024)
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
export const ROUTES = {
|
import { ROUTES, RouteNameEnum } from "@/shared/model";
|
||||||
LOGIN: '/login',
|
|
||||||
REGISTER: '/register',
|
|
||||||
RESET_PASSWORD: '/reset-password',
|
|
||||||
HOME: '/',
|
|
||||||
SUPPLIERS_SEARCH: '/suppliers-search',
|
|
||||||
MAILINGS: '/mailings',
|
|
||||||
VIEWING_REQUESTS: '/viewing-requests',
|
|
||||||
};
|
|
||||||
|
|
||||||
export type RouteName = keyof typeof ROUTES;
|
|
||||||
|
|
||||||
export const useNavigation = () => {
|
export const useNavigation = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const goTo = (route: RouteName | string) => {
|
const goTo = (route: RouteNameEnum | string) => {
|
||||||
if (route in ROUTES) {
|
if (route in ROUTES) {
|
||||||
navigate(ROUTES[route as RouteName]);
|
navigate(ROUTES[route as RouteNameEnum]);
|
||||||
} else {
|
} else {
|
||||||
navigate(route);
|
navigate(route);
|
||||||
}
|
}
|
||||||
@@ -27,9 +17,9 @@ export const useNavigation = () => {
|
|||||||
navigate(-1);
|
navigate(-1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const replace = (route: RouteName | string) => {
|
const replace = (route: RouteNameEnum | string) => {
|
||||||
if (route in ROUTES) {
|
if (route in ROUTES) {
|
||||||
navigate(ROUTES[route as RouteName], { replace: true });
|
navigate(ROUTES[route as RouteNameEnum], { replace: true });
|
||||||
} else {
|
} else {
|
||||||
navigate(route, { replace: true });
|
navigate(route, { replace: true });
|
||||||
}
|
}
|
||||||
@@ -38,7 +28,6 @@ export const useNavigation = () => {
|
|||||||
return {
|
return {
|
||||||
goTo,
|
goTo,
|
||||||
goBack,
|
goBack,
|
||||||
replace,
|
replace
|
||||||
ROUTES,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
// import { createClient } from '@supabase/supabase-js';
|
|
||||||
//
|
|
||||||
// import { VITE_SUPABASE_ANON_KEY, VITE_SUPABASE_URL } from "@/shared/api";
|
|
||||||
//
|
|
||||||
// if (!VITE_SUPABASE_URL || !VITE_SUPABASE_ANON_KEY) {
|
|
||||||
// throw new Error('Missing Supabase environment variables');
|
|
||||||
// }
|
|
||||||
|
|
||||||
// export const supabase = createClient(VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY);
|
|
||||||
@@ -1,4 +1 @@
|
|||||||
export { useSuppliersSearch, SuppliersSearchProvider } from './context/SuppliersSearchContext';
|
export { ROUTES, RouteNameEnum, type RouteType, type RouteName, getRoute, generatePath } from './routes/routes'
|
||||||
export { useAuth, AuthProvider } from './context/AuthContext';
|
|
||||||
|
|
||||||
export { ROUTES, type RouteType, type RouteName, getRoute, generatePath } from './routes'
|
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
export type RouteType = {
|
|
||||||
name: string;
|
|
||||||
path: string;
|
|
||||||
component: React.ComponentType<unknown>;
|
|
||||||
exact?: boolean;
|
|
||||||
isProtected?: boolean;
|
|
||||||
isAuthOnly?: boolean;
|
|
||||||
layout?: React.ComponentType<unknown>;
|
|
||||||
children?: RouteType[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ROUTES = {
|
|
||||||
HOME: '/',
|
|
||||||
LOGIN: '/login',
|
|
||||||
REGISTER: '/register',
|
|
||||||
RESET_PASSWORD: '/reset-password',
|
|
||||||
SUPPLIERS_SEARCH: '/suppliers-search',
|
|
||||||
MAILINGS: '/mailings',
|
|
||||||
SUPPLIERS: '/suppliers',
|
|
||||||
VIEWING_REQUESTS: '/viewing-requests',
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type RouteName = keyof typeof ROUTES;
|
|
||||||
|
|
||||||
// export const routesConfig: RouteType[] = [
|
|
||||||
// // Публичные роуты (не требуют аутентификации)
|
|
||||||
// {
|
|
||||||
// name: 'LOGIN',
|
|
||||||
// path: ROUTES.LOGIN,
|
|
||||||
// component: LoginPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'REGISTER',
|
|
||||||
// path: ROUTES.REGISTER,
|
|
||||||
// component: RegisterPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: false,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'RESET_PASSWORD',
|
|
||||||
// path: ROUTES.RESET_PASSWORD,
|
|
||||||
// component: ResetPasswordPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: false,
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// // Защищенные роуты (требуют аутентификации)
|
|
||||||
// {
|
|
||||||
// name: 'HOME',
|
|
||||||
// path: ROUTES.HOME,
|
|
||||||
// component: HomePage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'SUPPLIERS_SEARCH',
|
|
||||||
// path: ROUTES.SUPPLIERS_SEARCH,
|
|
||||||
// component: SuppliersSearchPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'MAILINGS',
|
|
||||||
// path: ROUTES.MAILINGS,
|
|
||||||
// component: MailingsPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: true,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: 'SUPPLIERS',
|
|
||||||
// path: ROUTES.SUPPLIERS,
|
|
||||||
// component: SuppliersPage,
|
|
||||||
// exact: true,
|
|
||||||
// isProtected: true,
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// Вспомогательные функции для работы с роутами
|
|
||||||
export const getRoute = (name: RouteName): string => ROUTES[name];
|
|
||||||
|
|
||||||
// export const getRouteConfig = (name: RouteName): RouteType | undefined =>
|
|
||||||
// routesConfig.find(route => route.name === name);
|
|
||||||
|
|
||||||
// Функция для генерации пути с параметрами
|
|
||||||
export const generatePath = (name: RouteName, params?: Record<string, string | number>): string => {
|
|
||||||
let path = getRoute(name);
|
|
||||||
if (params) {
|
|
||||||
Object.entries(params).forEach(([key, value]) => {
|
|
||||||
path = path.replace(`:${key}`, String(value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
};
|
|
||||||
52
src/shared/model/routes/routes.ts
Normal file
52
src/shared/model/routes/routes.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export type RouteType = {
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
component: React.ComponentType<unknown>;
|
||||||
|
exact?: boolean;
|
||||||
|
isProtected?: boolean;
|
||||||
|
isAuthOnly?: boolean;
|
||||||
|
layout?: React.ComponentType<unknown>;
|
||||||
|
children?: RouteType[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ROUTES = {
|
||||||
|
HOME: '/',
|
||||||
|
LOGIN: '/login',
|
||||||
|
REGISTER: '/register',
|
||||||
|
RESET_PASSWORD: '/reset-password',
|
||||||
|
SUPPLIERS_SEARCH: '/suppliers-search',
|
||||||
|
MAILINGS: '/mailings',
|
||||||
|
SUPPLIERS: '/suppliers',
|
||||||
|
VIEWING_REQUESTS: '/viewing-requests',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const enum RouteNameEnum {
|
||||||
|
HOME = 'HOME',
|
||||||
|
LOGIN = 'LOGIN',
|
||||||
|
REGISTER = 'REGISTER',
|
||||||
|
RESET_PASSWORD = 'RESET_PASSWORD',
|
||||||
|
SUPPLIERS_SEARCH = 'SUPPLIERS_SEARCH',
|
||||||
|
MAILINGS = 'MAILINGS',
|
||||||
|
SUPPLIERS = 'SUPPLIERS',
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RouteName = keyof typeof ROUTES;
|
||||||
|
|
||||||
|
// Вспомогательные функции для работы с роутами
|
||||||
|
export const getRoute = (name: RouteNameEnum): string => ROUTES[name];
|
||||||
|
|
||||||
|
// export const getRouteConfig = (name: RouteNameEnum): RouteType | undefined =>
|
||||||
|
// routesConfig.find(route => route.name === name);
|
||||||
|
|
||||||
|
// Функция для генерации пути с параметрами
|
||||||
|
export const generatePath = (name: RouteNameEnum, params?: Record<string, string | number>): string => {
|
||||||
|
let path = getRoute(name);
|
||||||
|
if (params) {
|
||||||
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
|
path = path.replace(`:${key}`, String(value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return path;
|
||||||
|
};
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { LogOut } from 'lucide-react';
|
import { LogOut } from 'lucide-react';
|
||||||
|
|
||||||
|
import { useAuth } from "@/app/providers/AuthContext";
|
||||||
import { authApi } from "@/shared/api";
|
import { authApi } from "@/shared/api";
|
||||||
import { useNavigation } from "@/shared/lib/hooks/useNavigation";
|
import { useNavigation } from "@/shared/lib/hooks/useNavigation";
|
||||||
import { ROUTES, useAuth } from "@/shared/model";
|
import { ROUTES } from "@/shared/model";
|
||||||
import { ButtonVariant, UIButton } from "@/shared/ui";
|
import { ButtonVariant, UIButton } from "@/shared/ui";
|
||||||
|
|
||||||
export const SidebarFooter = () => {
|
export const SidebarFooter = () => {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
|
||||||
import { useNavigation } from "@/shared/lib/hooks/useNavigation";
|
import { useNavigation } from "@/shared/lib/hooks/useNavigation";
|
||||||
import { RouteName, ROUTES } from "@/shared/model/routes";
|
import { RouteName, ROUTES } from "@/shared/model";
|
||||||
import { ButtonSize, ButtonVariant, UIButton } from "@/shared/ui";
|
import { ButtonSize, ButtonVariant, UIButton } from "@/shared/ui";
|
||||||
import { menuItems } from "@/widgets/sidebar/model/constants";
|
import { menuItems } from "@/widgets/sidebar/model/constants";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user