diff --git a/src/app/App.tsx b/src/app/App.tsx index 0c898c7..a418876 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -5,10 +5,12 @@ import { LoginPage, RegisterPage, ResetPasswordPage } from "@/pages/auth"; import { HomePage } from "@/pages/home"; import { MailingById, MailingsPage } from "@/pages/mailings"; import { SuppliersSearchPage } from "@/pages/suppliers-search"; +import { SuppliersSearchProvider } from "@/pages/suppliers-search/model/SuppliersSearchContext"; import { ViewingRequestById, ViewingRequestsPage } from "@/pages/viewing-requests"; -import { AuthProvider, SuppliersSearchProvider, useAuth } from "@/shared/model"; import { UILoader } from "@/shared/ui"; +import { AuthProvider, useAuth } from "./providers/AuthContext"; + const AppContent = () => { const { user, loading } = useAuth(); diff --git a/src/app/layout/ui/AppLayout.tsx b/src/app/layout/ui/AppLayout.tsx index 1f808b3..84273da 100644 --- a/src/app/layout/ui/AppLayout.tsx +++ b/src/app/layout/ui/AppLayout.tsx @@ -2,11 +2,12 @@ import { Menu } from 'lucide-react'; import { useState } from 'react'; import { Outlet } from 'react-router-dom'; +import { useDevices } from "@/shared/lib"; import { Sidebar } from '@/widgets/sidebar' export const AppLayout = () => { - const [isSidebarOpen, setIsSidebarOpen] = useState(true); - + const [isSidebarOpen, setIsSidebarOpen] = useState(false); + const { isMobile } = useDevices() // Функция переключения состояния сайдбара const toggleSidebar = () => { setIsSidebarOpen(!isSidebarOpen); @@ -21,11 +22,13 @@ export const AppLayout = () => {
-
+
{/* Кнопка в хедере только для мобильных */} -
- toggleSidebar()}/> -
+ {isMobile && ( +
+ toggleSidebar()}/> +
+ )}
diff --git a/src/shared/model/context/AuthContext.tsx b/src/app/providers/AuthContext.tsx similarity index 100% rename from src/shared/model/context/AuthContext.tsx rename to src/app/providers/AuthContext.tsx diff --git a/src/entities/mailing/index.ts b/src/entities/mailing/index.ts new file mode 100644 index 0000000..21a5cfb --- /dev/null +++ b/src/entities/mailing/index.ts @@ -0,0 +1 @@ +export { MailingItem } from './ui/MailingItem' \ No newline at end of file diff --git a/src/pages/mailings/ui/MailingsItem.tsx b/src/entities/mailing/ui/MailingItem.tsx similarity index 96% rename from src/pages/mailings/ui/MailingsItem.tsx rename to src/entities/mailing/ui/MailingItem.tsx index 7f824b1..3a801a4 100644 --- a/src/pages/mailings/ui/MailingsItem.tsx +++ b/src/entities/mailing/ui/MailingItem.tsx @@ -9,7 +9,7 @@ interface IProps { onSelectItem: (id: string | number) => void } -export const MailingsItem = (props: IProps) => { +export const MailingItem = (props: IProps) => { const { item, onSelectItem } = props; const statusIcon = useMemo(() => { diff --git a/src/entities/supplier/index.ts b/src/entities/supplier/index.ts new file mode 100644 index 0000000..96fa2c9 --- /dev/null +++ b/src/entities/supplier/index.ts @@ -0,0 +1 @@ +export { SuppliersTable } from './ui/SuppliersTable' diff --git a/src/pages/suppliers-search/ui/SuppliersTable.tsx b/src/entities/supplier/ui/SuppliersTable.tsx similarity index 95% rename from src/pages/suppliers-search/ui/SuppliersTable.tsx rename to src/entities/supplier/ui/SuppliersTable.tsx index 0b429f4..55a1c8d 100644 --- a/src/pages/suppliers-search/ui/SuppliersTable.tsx +++ b/src/entities/supplier/ui/SuppliersTable.tsx @@ -1,7 +1,7 @@ import { ArrowBigLeft } from "lucide-react"; +import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext"; import { ISupplier } from "@/shared/api"; -import { useSuppliersSearch } from "@/shared/model"; import { ButtonSize, ButtonVariant, diff --git a/src/entities/viewing-requests/index.ts b/src/entities/viewing-requests/index.ts new file mode 100644 index 0000000..48419a4 --- /dev/null +++ b/src/entities/viewing-requests/index.ts @@ -0,0 +1 @@ +export { ViewingRequestItem } from './ui/ViewingRequestItem' diff --git a/src/pages/viewing-requests/ui/ViewingRequestItem.tsx b/src/entities/viewing-requests/ui/ViewingRequestItem.tsx similarity index 100% rename from src/pages/viewing-requests/ui/ViewingRequestItem.tsx rename to src/entities/viewing-requests/ui/ViewingRequestItem.tsx diff --git a/src/features/suppliers-search/request-input/index.ts b/src/features/suppliers-search/request-input/index.ts new file mode 100644 index 0000000..c9c8155 --- /dev/null +++ b/src/features/suppliers-search/request-input/index.ts @@ -0,0 +1 @@ +export { RequestInputForm } from './ui/RequestInputForm' \ No newline at end of file diff --git a/src/pages/suppliers-search/ui/RequestInputForm.tsx b/src/features/suppliers-search/request-input/ui/RequestInputForm.tsx similarity index 94% rename from src/pages/suppliers-search/ui/RequestInputForm.tsx rename to src/features/suppliers-search/request-input/ui/RequestInputForm.tsx index c33b7df..b11bab5 100644 --- a/src/pages/suppliers-search/ui/RequestInputForm.tsx +++ b/src/features/suppliers-search/request-input/ui/RequestInputForm.tsx @@ -1,8 +1,9 @@ import { Send } from 'lucide-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 { useAuth, useSuppliersSearch } from "@/shared/model"; import { ButtonVariant, NotificationAppearance, diff --git a/src/features/suppliers-search/technical-specification/index.ts b/src/features/suppliers-search/technical-specification/index.ts new file mode 100644 index 0000000..fb4a951 --- /dev/null +++ b/src/features/suppliers-search/technical-specification/index.ts @@ -0,0 +1 @@ +export { TechnicalSpecification } from './ui/TechnicalSpecification' diff --git a/src/pages/suppliers-search/ui/TechnicalSpecification.tsx b/src/features/suppliers-search/technical-specification/ui/TechnicalSpecification.tsx similarity index 94% rename from src/pages/suppliers-search/ui/TechnicalSpecification.tsx rename to src/features/suppliers-search/technical-specification/ui/TechnicalSpecification.tsx index 4cc9686..b906438 100644 --- a/src/pages/suppliers-search/ui/TechnicalSpecification.tsx +++ b/src/features/suppliers-search/technical-specification/ui/TechnicalSpecification.tsx @@ -1,8 +1,9 @@ import { ArrowBigLeft, Search } from 'lucide-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 { useAuth, useSuppliersSearch } from "@/shared/model"; import { ButtonVariant, NotificationAppearance, diff --git a/src/pages/auth/login/ui/Login.tsx b/src/pages/auth/login/ui/Login.tsx index 0223759..85e5287 100644 --- a/src/pages/auth/login/ui/Login.tsx +++ b/src/pages/auth/login/ui/Login.tsx @@ -1,8 +1,9 @@ import { useState } from 'react'; import { Link, useNavigate } from "react-router"; +import { useAuth } from "@/app/providers/AuthContext"; 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"; export const LoginPage = () => { diff --git a/src/pages/auth/register/ui/Register.tsx b/src/pages/auth/register/ui/Register.tsx index a0b60c0..7a810de 100644 --- a/src/pages/auth/register/ui/Register.tsx +++ b/src/pages/auth/register/ui/Register.tsx @@ -2,8 +2,9 @@ import { useState } from 'react'; import { Link } from "react-router"; import { useNavigate } from "react-router-dom"; +import { useAuth } from "@/app/providers/AuthContext"; 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'; export const RegisterPage = () => { diff --git a/src/pages/mailings/ui/MailingById.tsx b/src/pages/mailings/ui/MailingById.tsx index b359f94..796fce9 100644 --- a/src/pages/mailings/ui/MailingById.tsx +++ b/src/pages/mailings/ui/MailingById.tsx @@ -3,7 +3,7 @@ import { useParams } from "react-router"; import { useNavigate } from "react-router-dom"; import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api"; -import { ROUTES } from "@/shared/model/routes"; +import { ROUTES } from "@/shared/model"; import { ButtonVariant, Column, NotificationAppearance, diff --git a/src/pages/mailings/ui/Mailings.tsx b/src/pages/mailings/ui/Mailings.tsx index a8b02eb..9181cca 100644 --- a/src/pages/mailings/ui/Mailings.tsx +++ b/src/pages/mailings/ui/Mailings.tsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; 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 { ROUTES } from "@/shared/model"; import { @@ -62,7 +62,7 @@ export const MailingsPage = () => {
{mailingList.length > 0 && ( mailingList.map((item) => ( - navigate(`${ROUTES.MAILINGS}/${item.request_id}`)} diff --git a/src/shared/model/context/SuppliersSearchContext.tsx b/src/pages/suppliers-search/model/SuppliersSearchContext.tsx similarity index 95% rename from src/shared/model/context/SuppliersSearchContext.tsx rename to src/pages/suppliers-search/model/SuppliersSearchContext.tsx index 16d0bb3..c58b2b0 100644 --- a/src/shared/model/context/SuppliersSearchContext.tsx +++ b/src/pages/suppliers-search/model/SuppliersSearchContext.tsx @@ -20,7 +20,7 @@ const SuppliersSearchContext = createContext({ export const useSuppliersSearch = () => { const context = useContext(SuppliersSearchContext); if (!context) { - throw new Error('useSuppliersSearch must be used within AuthProvider'); + throw new Error('useSuppliersSearch must be used within AuthContext'); } return context; }; diff --git a/src/pages/suppliers-search/ui/SuppliersSearchPage.tsx b/src/pages/suppliers-search/ui/SuppliersSearchPage.tsx index c075586..e8ffc4b 100644 --- a/src/pages/suppliers-search/ui/SuppliersSearchPage.tsx +++ b/src/pages/suppliers-search/ui/SuppliersSearchPage.tsx @@ -1,12 +1,13 @@ import { useCallback, useState } from 'react'; -import { StagesEnum } from "@/pages/suppliers-search"; -import { RequestInputForm } from "@/pages/suppliers-search/ui/RequestInputForm"; -import { SuppliersTable } from "@/pages/suppliers-search/ui/SuppliersTable"; -import { TechnicalSpecification } from "@/pages/suppliers-search/ui/TechnicalSpecification"; -import { useSuppliersSearch } from "@/shared/model"; +import { SuppliersTable } from "@/entities/supplier"; +import { RequestInputForm } from "@/features/suppliers-search/request-input"; +import { TechnicalSpecification } from "@/features/suppliers-search/technical-specification"; +import { useSuppliersSearch } from "@/pages/suppliers-search/model/SuppliersSearchContext"; import { UIStepper } from "@/shared/ui"; +import { StagesEnum } from "../model/types"; + export const SuppliersSearchPage = () => { const [stage, setStage] = useState(StagesEnum.Input); const { suppliers, updateSuppliersSearchContext } = useSuppliersSearch(); diff --git a/src/pages/viewing-requests/index.ts b/src/pages/viewing-requests/index.ts index 9586bf0..2a00e22 100644 --- a/src/pages/viewing-requests/index.ts +++ b/src/pages/viewing-requests/index.ts @@ -1,3 +1,2 @@ export { ViewingRequestsPage } from './ui/ViewingRequests' export { ViewingRequestById } from './ui/ViewingRequestById' -export { ViewingRequestItem } from './ui/ViewingRequestItem' \ No newline at end of file diff --git a/src/pages/viewing-requests/ui/ViewingRequestById.tsx b/src/pages/viewing-requests/ui/ViewingRequestById.tsx index ef9d8c3..f0827bc 100644 --- a/src/pages/viewing-requests/ui/ViewingRequestById.tsx +++ b/src/pages/viewing-requests/ui/ViewingRequestById.tsx @@ -3,7 +3,6 @@ import { useEffect, useState } from "react"; import { useParams } from "react-router"; import { useNavigate } from "react-router-dom"; - import { IMailingInfo, ISupplier, mailingApi } from "@/shared/api"; import { ButtonSize, @@ -103,7 +102,6 @@ export const ViewingRequestById = () => { value={message} placeholder="Текст сообщения" onChange={(val) => setMessage(val)} - minCount={10} minHeight={500} />
diff --git a/src/pages/viewing-requests/ui/ViewingRequests.tsx b/src/pages/viewing-requests/ui/ViewingRequests.tsx index 2607b53..f1d31fe 100644 --- a/src/pages/viewing-requests/ui/ViewingRequests.tsx +++ b/src/pages/viewing-requests/ui/ViewingRequests.tsx @@ -1,16 +1,15 @@ import { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; +import { ViewingRequestItem } from "@/entities/viewing-requests"; import { IMailingItem, mailingApi } from "@/shared/api"; -import { ROUTES } from "@/shared/model/routes"; +import { ROUTES } from "@/shared/model"; import { NotificationAppearance, UILoader, UINotification, } from "@/shared/ui"; -import { ViewingRequestItem } from "./ViewingRequestItem"; - export const ViewingRequestsPage = () => { const [loading, setLoading] = useState(false); const [error, setError] = useState(''); diff --git a/src/shared/lib/hooks/useDevices.ts b/src/shared/lib/hooks/useDevices.ts index 86ae882..cf9e3e5 100644 --- a/src/shared/lib/hooks/useDevices.ts +++ b/src/shared/lib/hooks/useDevices.ts @@ -10,11 +10,11 @@ export const useDevices = (): UseDevicesType => { const [ isDesktop, setIsDesktop ] = useState(window.innerWidth > 880) const updateIsMobile = () => { - setIsMobile(window.innerWidth < 880) + setIsMobile(window.innerWidth < 1024) }; const updateIsDesktop = () => { - setIsDesktop(window.innerWidth >= 880) + setIsDesktop(window.innerWidth >= 1024) }; useEffect(() => { diff --git a/src/shared/lib/hooks/useNavigation.ts b/src/shared/lib/hooks/useNavigation.ts index cf9b4d8..b5bafbf 100644 --- a/src/shared/lib/hooks/useNavigation.ts +++ b/src/shared/lib/hooks/useNavigation.ts @@ -1,23 +1,13 @@ import { useNavigate } from 'react-router-dom'; -export const ROUTES = { - 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; +import { ROUTES, RouteNameEnum } from "@/shared/model"; export const useNavigation = () => { const navigate = useNavigate(); - const goTo = (route: RouteName | string) => { + const goTo = (route: RouteNameEnum | string) => { if (route in ROUTES) { - navigate(ROUTES[route as RouteName]); + navigate(ROUTES[route as RouteNameEnum]); } else { navigate(route); } @@ -27,9 +17,9 @@ export const useNavigation = () => { navigate(-1); }; - const replace = (route: RouteName | string) => { + const replace = (route: RouteNameEnum | string) => { if (route in ROUTES) { - navigate(ROUTES[route as RouteName], { replace: true }); + navigate(ROUTES[route as RouteNameEnum], { replace: true }); } else { navigate(route, { replace: true }); } @@ -38,7 +28,6 @@ export const useNavigation = () => { return { goTo, goBack, - replace, - ROUTES, + replace }; }; \ No newline at end of file diff --git a/src/shared/lib/supabase/supabase.ts b/src/shared/lib/supabase/supabase.ts deleted file mode 100644 index b10b133..0000000 --- a/src/shared/lib/supabase/supabase.ts +++ /dev/null @@ -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); diff --git a/src/shared/model/index.ts b/src/shared/model/index.ts index fe07f33..1a80f7c 100644 --- a/src/shared/model/index.ts +++ b/src/shared/model/index.ts @@ -1,4 +1 @@ -export { useSuppliersSearch, SuppliersSearchProvider } from './context/SuppliersSearchContext'; -export { useAuth, AuthProvider } from './context/AuthContext'; - -export { ROUTES, type RouteType, type RouteName, getRoute, generatePath } from './routes' +export { ROUTES, RouteNameEnum, type RouteType, type RouteName, getRoute, generatePath } from './routes/routes' diff --git a/src/shared/model/routes/index.ts b/src/shared/model/routes/index.ts deleted file mode 100644 index 6eb6671..0000000 --- a/src/shared/model/routes/index.ts +++ /dev/null @@ -1,97 +0,0 @@ -import React from "react"; - -export type RouteType = { - name: string; - path: string; - component: React.ComponentType; - exact?: boolean; - isProtected?: boolean; - isAuthOnly?: boolean; - layout?: React.ComponentType; - 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 => { - let path = getRoute(name); - if (params) { - Object.entries(params).forEach(([key, value]) => { - path = path.replace(`:${key}`, String(value)); - }); - } - return path; -}; \ No newline at end of file diff --git a/src/shared/model/routes/routes.ts b/src/shared/model/routes/routes.ts new file mode 100644 index 0000000..02dfb64 --- /dev/null +++ b/src/shared/model/routes/routes.ts @@ -0,0 +1,52 @@ +import React from "react"; + +export type RouteType = { + name: string; + path: string; + component: React.ComponentType; + exact?: boolean; + isProtected?: boolean; + isAuthOnly?: boolean; + layout?: React.ComponentType; + 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 => { + let path = getRoute(name); + if (params) { + Object.entries(params).forEach(([key, value]) => { + path = path.replace(`:${key}`, String(value)); + }); + } + return path; +}; \ No newline at end of file diff --git a/src/widgets/sidebar/ui/SidebarFooter.tsx b/src/widgets/sidebar/ui/SidebarFooter.tsx index 978cb67..10f8cd8 100644 --- a/src/widgets/sidebar/ui/SidebarFooter.tsx +++ b/src/widgets/sidebar/ui/SidebarFooter.tsx @@ -1,8 +1,9 @@ import { LogOut } from 'lucide-react'; +import { useAuth } from "@/app/providers/AuthContext"; import { authApi } from "@/shared/api"; import { useNavigation } from "@/shared/lib/hooks/useNavigation"; -import { ROUTES, useAuth } from "@/shared/model"; +import { ROUTES } from "@/shared/model"; import { ButtonVariant, UIButton } from "@/shared/ui"; export const SidebarFooter = () => { diff --git a/src/widgets/sidebar/ui/SidebarNav.tsx b/src/widgets/sidebar/ui/SidebarNav.tsx index 4c14229..b245a84 100644 --- a/src/widgets/sidebar/ui/SidebarNav.tsx +++ b/src/widgets/sidebar/ui/SidebarNav.tsx @@ -1,7 +1,7 @@ import { FC } from 'react'; 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 { menuItems } from "@/widgets/sidebar/model/constants";