From e06c244ade26c9c85f5b02414d907f8903705dff Mon Sep 17 00:00:00 2001 From: Fing0r Date: Tue, 17 Mar 2026 21:11:45 +0700 Subject: [PATCH 1/5] =?UTF-8?q?feat(web):=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20prefetchQuery=20=D0=BF=D1=80=D0=BE=D1=84=D0=B8?= =?UTF-8?q?=D0=BB=D1=8F=20=D0=B2=20dashboard=20layout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/(dashboard)/layout.tsx | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx index 1f689d7b..7cd10b2b 100644 --- a/apps/web/app/(dashboard)/layout.tsx +++ b/apps/web/app/(dashboard)/layout.tsx @@ -1,15 +1,37 @@ +import { authKeys } from '@/hooks/api/use-auth' +import { authService } from '@/lib/api/auth-service' +import { isApiError } from '@/lib/api/utils' +import { getQueryClient } from '@/lib/query-client' +import { ROUTES } from '@/shared/config/routes' import { MainLayout } from '@/widgets/main-layout' +import { dehydrate, HydrationBoundary } from '@tanstack/react-query' +import { redirect } from 'next/navigation' interface Props { children: React.ReactNode modal: React.ReactNode } -export default function DashboardLayout({ children, modal }: Props) { +export default async function DashboardLayout({ children, modal }: Props) { + const queryClient = getQueryClient() + + try { + await queryClient.prefetchQuery({ + queryKey: authKeys.getMe, + queryFn: authService.getMe, + }) + } catch (error) { + if (isApiError(error) && error.statusCode === 401) { + redirect(ROUTES.login) + } + + throw error + } + return ( - <> + {children} {modal} - + ) } From 25b72c1c3b79f4a15cc71ff6bd594589335eb286 Mon Sep 17 00:00:00 2001 From: Fing0r Date: Tue, 17 Mar 2026 21:12:49 +0700 Subject: [PATCH 2/5] =?UTF-8?q?feat(web):=20=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2?= =?UTF-8?q?=D0=B8=D0=BB=20logout=20=D0=B2=20profile-menu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main-layout/ui/header/profile-menu.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx index e2bc0f2c..72b511f9 100644 --- a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx +++ b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx @@ -1,8 +1,7 @@ 'use client' -import { useLogout } from '@/hooks/api/use-auth' -import { ROUTES } from '@/shared/config/routes' -import { useRouter } from 'next/navigation' +import { useLogout, useMe } from '@/hooks/api/use-auth' +import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config/routes' import React from 'react' import { @@ -23,15 +22,17 @@ const currentUser = { } const ProfileMenu = () => { - const router = useRouter() const logoutMutation = useLogout() - const handleLogout = async () => { - await logoutMutation.mutateAsync() - - router.push(ROUTES.login) + const handleLogout = () => { + logoutMutation.mutateAsync() + const url = new URL(ROUTES.login, window.location.origin) + url.searchParams.set(ROUTE_QUERY_PARAMS.clearAuth, '1') + window.location.assign(url) } + const profileQuery = useMe() + return ( @@ -48,7 +49,7 @@ const ProfileMenu = () => { {currentUser.avatar} - {currentUser.name} + {profileQuery.data?.name} From 1b0b5381107bec38cecbfea161cfe8517bc31152 Mon Sep 17 00:00:00 2001 From: Fing0r Date: Tue, 17 Mar 2026 21:33:27 +0700 Subject: [PATCH 3/5] =?UTF-8?q?refactor(web):=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=20=D1=84=D0=B0=D0=B9=D0=BB=D1=8B=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=BD=D0=BE=20fsd?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/(auth)/layout.tsx | 3 +- apps/web/app/(auth)/login/page.tsx | 65 +----------------- apps/web/app/(auth)/register/page.tsx | 65 +----------------- apps/web/app/(dashboard)/layout.tsx | 10 +-- apps/web/app/(dashboard)/sprints/page.tsx | 2 +- apps/web/app/(dashboard)/tasks/page.tsx | 2 +- .../teams/[id]/projects/[projectId]/page.tsx | 2 +- .../(dashboard)/teams/[id]/projects/page.tsx | 2 +- .../(dashboard)/teams/[id]/settings/page.tsx | 2 +- apps/web/app/error.tsx | 2 +- apps/web/app/not-found.tsx | 2 +- apps/web/app/providers.tsx | 3 +- apps/web/features/theme/ui/theme-sync.tsx | 2 +- apps/web/features/theme/ui/theme-toggle.tsx | 3 +- apps/web/proxy.ts | 11 ++- apps/web/{hooks => shared}/api/use-auth.ts | 2 +- apps/web/{hooks => shared}/api/use-example.ts | 7 +- apps/web/{hooks => shared}/api/use-teams.ts | 4 +- .../config/feature-flags.ts} | 0 apps/web/shared/config/index.ts | 2 + apps/web/{ => shared}/lib/api/auth-cookies.ts | 0 apps/web/{ => shared}/lib/api/auth-service.ts | 0 apps/web/{ => shared}/lib/api/axios-config.ts | 0 apps/web/{ => shared}/lib/api/client.ts | 4 +- .../{ => shared}/lib/api/example-service.ts | 0 .../web/{ => shared}/lib/api/public-client.ts | 0 .../lib/api/refresh-auth-session.ts | 0 .../lib/api/request-auth-refresh.ts | 0 .../web/{ => shared}/lib/api/teams-service.ts | 0 apps/web/{ => shared}/lib/api/types.ts | 0 apps/web/{ => shared}/lib/api/utils.ts | 0 apps/web/{ => shared}/lib/projects/catalog.ts | 2 +- apps/web/shared/lib/projects/index.ts | 2 + .../{ => shared}/lib/projects/project-code.ts | 0 apps/web/{ => shared}/lib/query-client.ts | 0 apps/web/{ => shared}/lib/session/index.ts | 0 apps/web/{ => shared}/lib/session/utils.ts | 0 apps/web/views/auth/index.ts | 2 + .../auth/model}/use-login-form.ts | 0 .../auth/model}/use-register-form.ts | 0 .../auth/ui}/auth-form-layout.tsx | 0 .../login => views/auth/ui}/login-form.tsx | 2 +- apps/web/views/auth/ui/login-page-view.tsx | 68 +++++++++++++++++++ .../auth/ui}/register-form.tsx | 2 +- apps/web/views/auth/ui/register-page-view.tsx | 68 +++++++++++++++++++ apps/web/views/home/model/content.ts | 2 +- apps/web/views/home/ui/home-header.tsx | 2 +- .../projects/ui/create-project-dialog.tsx | 2 +- apps/web/views/projects/ui/project-card.tsx | 2 +- .../projects/ui/project-detail-page-view.tsx | 6 +- .../views/projects/ui/projects-page-view.tsx | 4 +- .../web/views/teams/ui/create-team-dialog.tsx | 6 +- .../teams/ui/team-settings-page-view.tsx | 2 +- apps/web/views/teams/ui/teams-page-view.tsx | 4 +- .../main-layout/model/sidebar/navigation.ts | 5 +- .../main-layout/model/sidebar/types.ts | 2 +- .../main-layout/ui/header/profile-menu.tsx | 4 +- .../main-layout/ui/sidebar/sidebar.tsx | 6 +- 58 files changed, 202 insertions(+), 186 deletions(-) rename apps/web/{hooks => shared}/api/use-auth.ts (91%) rename apps/web/{hooks => shared}/api/use-example.ts (95%) rename apps/web/{hooks => shared}/api/use-teams.ts (95%) rename apps/web/{hooks/use-feature-flag.ts => shared/config/feature-flags.ts} (100%) create mode 100644 apps/web/shared/config/index.ts rename apps/web/{ => shared}/lib/api/auth-cookies.ts (100%) rename apps/web/{ => shared}/lib/api/auth-service.ts (100%) rename apps/web/{ => shared}/lib/api/axios-config.ts (100%) rename apps/web/{ => shared}/lib/api/client.ts (92%) rename apps/web/{ => shared}/lib/api/example-service.ts (100%) rename apps/web/{ => shared}/lib/api/public-client.ts (100%) rename apps/web/{ => shared}/lib/api/refresh-auth-session.ts (100%) rename apps/web/{ => shared}/lib/api/request-auth-refresh.ts (100%) rename apps/web/{ => shared}/lib/api/teams-service.ts (100%) rename apps/web/{ => shared}/lib/api/types.ts (100%) rename apps/web/{ => shared}/lib/api/utils.ts (100%) rename apps/web/{ => shared}/lib/projects/catalog.ts (98%) create mode 100644 apps/web/shared/lib/projects/index.ts rename apps/web/{ => shared}/lib/projects/project-code.ts (100%) rename apps/web/{ => shared}/lib/query-client.ts (100%) rename apps/web/{ => shared}/lib/session/index.ts (100%) rename apps/web/{ => shared}/lib/session/utils.ts (100%) create mode 100644 apps/web/views/auth/index.ts rename apps/web/{app/(auth)/login => views/auth/model}/use-login-form.ts (100%) rename apps/web/{app/(auth)/register => views/auth/model}/use-register-form.ts (100%) rename apps/web/{app/(auth) => views/auth/ui}/auth-form-layout.tsx (100%) rename apps/web/{app/(auth)/login => views/auth/ui}/login-form.tsx (93%) create mode 100644 apps/web/views/auth/ui/login-page-view.tsx rename apps/web/{app/(auth)/register => views/auth/ui}/register-form.tsx (95%) create mode 100644 apps/web/views/auth/ui/register-page-view.tsx diff --git a/apps/web/app/(auth)/layout.tsx b/apps/web/app/(auth)/layout.tsx index f0832d70..02a1a56c 100644 --- a/apps/web/app/(auth)/layout.tsx +++ b/apps/web/app/(auth)/layout.tsx @@ -1,5 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' -import { ROUTES } from '@/shared/config/routes' +import { FEATURES, ROUTES } from '@/shared/config' import Link from 'next/link' import { notFound } from 'next/navigation' diff --git a/apps/web/app/(auth)/login/page.tsx b/apps/web/app/(auth)/login/page.tsx index 1b8930d9..d75d88cd 100644 --- a/apps/web/app/(auth)/login/page.tsx +++ b/apps/web/app/(auth)/login/page.tsx @@ -1,66 +1,5 @@ -'use client' - -import { useLogin } from '@/hooks/api/use-auth' -import { isApiError } from '@/lib/api/utils' -import { ROUTES } from '@/shared/config/routes' -import Link from 'next/link' -import { useRouter } from 'next/navigation' - -import { Button, Form, toast } from '@repo/ui' - -import { AuthFormLayout } from '../auth-form-layout' -import { LoginForm } from './login-form' -import { LoginFormValues, useLoginForm } from './use-login-form' +import { LoginPageView } from '@/views/auth' export default function LoginPage() { - const form = useLoginForm() - - const loginMutation = useLogin() - const router = useRouter() - - const onSubmit = async (data: LoginFormValues) => { - try { - await loginMutation.mutateAsync(data) - router.push(ROUTES.teams) - } catch (error) { - if (isApiError(error)) { - toast.error(error.message) - } else { - throw error - } - } - } - - return ( -
- - - Войти - - } - > -
- -

- Еще нет аккаунта?{' '} - - Зарегистрироваться - -

-
-
-
- - ) + return } diff --git a/apps/web/app/(auth)/register/page.tsx b/apps/web/app/(auth)/register/page.tsx index c883890a..16b13f29 100644 --- a/apps/web/app/(auth)/register/page.tsx +++ b/apps/web/app/(auth)/register/page.tsx @@ -1,66 +1,5 @@ -'use client' - -import { useRegister } from '@/hooks/api/use-auth' -import { isApiError } from '@/lib/api/utils' -import { ROUTES } from '@/shared/config/routes' -import Link from 'next/link' -import { useRouter } from 'next/navigation' - -import { Button, Form, toast } from '@repo/ui' - -import { AuthFormLayout } from '../auth-form-layout' -import { RegisterForm } from './register-form' -import { RegisterFormValues, useRegisterForm } from './use-register-form' +import { RegisterPageView } from '@/views/auth' export default function RegisterPage() { - const form = useRegisterForm() - - const registerMutation = useRegister() - const router = useRouter() - - const onSubmit = async (data: RegisterFormValues) => { - try { - await registerMutation.mutateAsync(data) - router.push(ROUTES.teams) - } catch (error) { - if (isApiError(error)) { - toast.error(error.message) - } else { - throw error - } - } - } - - return ( -
- - - Зарегистрироваться - - } - > -
- -

- Уже есть аккаунт?{' '} - - Войти - -

-
-
-
- - ) + return } diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx index 7cd10b2b..7556f9d8 100644 --- a/apps/web/app/(dashboard)/layout.tsx +++ b/apps/web/app/(dashboard)/layout.tsx @@ -1,8 +1,8 @@ -import { authKeys } from '@/hooks/api/use-auth' -import { authService } from '@/lib/api/auth-service' -import { isApiError } from '@/lib/api/utils' -import { getQueryClient } from '@/lib/query-client' -import { ROUTES } from '@/shared/config/routes' +import { authKeys } from '@/shared/api/use-auth' +import { ROUTES } from '@/shared/config' +import { authService } from '@/shared/lib/api/auth-service' +import { isApiError } from '@/shared/lib/api/utils' +import { getQueryClient } from '@/shared/lib/query-client' import { MainLayout } from '@/widgets/main-layout' import { dehydrate, HydrationBoundary } from '@tanstack/react-query' import { redirect } from 'next/navigation' diff --git a/apps/web/app/(dashboard)/sprints/page.tsx b/apps/web/app/(dashboard)/sprints/page.tsx index 5a35bf11..c37a00cd 100644 --- a/apps/web/app/(dashboard)/sprints/page.tsx +++ b/apps/web/app/(dashboard)/sprints/page.tsx @@ -1,4 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' +import { FEATURES } from '@/shared/config' import { notFound } from 'next/navigation' import { Card, CardContent } from '@repo/ui' diff --git a/apps/web/app/(dashboard)/tasks/page.tsx b/apps/web/app/(dashboard)/tasks/page.tsx index 6cf7dfa7..8c7212b3 100644 --- a/apps/web/app/(dashboard)/tasks/page.tsx +++ b/apps/web/app/(dashboard)/tasks/page.tsx @@ -1,4 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' +import { FEATURES } from '@/shared/config' import { notFound } from 'next/navigation' import { Button } from '@repo/ui' diff --git a/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx b/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx index b1f80ff8..16fcb7a4 100644 --- a/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx @@ -1,4 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' +import { FEATURES } from '@/shared/config' import { ProjectDetailPageView } from '@/views/projects' import { notFound } from 'next/navigation' diff --git a/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx b/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx index 3df15731..8ac5b2e6 100644 --- a/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx @@ -1,4 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' +import { FEATURES } from '@/shared/config' import { ProjectsPageView } from '@/views/projects' import { notFound } from 'next/navigation' diff --git a/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx b/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx index 867d6fb2..a90a7a13 100644 --- a/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx @@ -1,4 +1,4 @@ -import { FEATURES } from '@/hooks/use-feature-flag' +import { FEATURES } from '@/shared/config' import { TeamSettingsPageView } from '@/views/teams' import { notFound } from 'next/navigation' diff --git a/apps/web/app/error.tsx b/apps/web/app/error.tsx index 09e16aa5..b540ffa5 100644 --- a/apps/web/app/error.tsx +++ b/apps/web/app/error.tsx @@ -1,6 +1,6 @@ 'use client' -import { ROUTES } from '@/shared/config/routes' +import { ROUTES } from '@/shared/config' import Link from 'next/link' import { useEffect } from 'react' diff --git a/apps/web/app/not-found.tsx b/apps/web/app/not-found.tsx index f0afa265..2a09f457 100644 --- a/apps/web/app/not-found.tsx +++ b/apps/web/app/not-found.tsx @@ -1,4 +1,4 @@ -import { ROUTES } from '@/shared/config/routes' +import { ROUTES } from '@/shared/config' import Link from 'next/link' import { Button, EmptyState } from '@repo/ui' diff --git a/apps/web/app/providers.tsx b/apps/web/app/providers.tsx index 7e2dc72d..80a787eb 100644 --- a/apps/web/app/providers.tsx +++ b/apps/web/app/providers.tsx @@ -1,11 +1,10 @@ 'use client' import { ThemeSync } from '@/features/theme' +import { getQueryClient } from '@/shared/lib/query-client' import { QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' -import { getQueryClient } from '../lib/query-client' - interface Props { children: React.ReactNode } diff --git a/apps/web/features/theme/ui/theme-sync.tsx b/apps/web/features/theme/ui/theme-sync.tsx index 7a81c2a8..38e04363 100644 --- a/apps/web/features/theme/ui/theme-sync.tsx +++ b/apps/web/features/theme/ui/theme-sync.tsx @@ -1,8 +1,8 @@ 'use client' +import { useHydratedStore } from '@/shared/hooks' import { useEffect } from 'react' -import { useHydratedStore } from '../../../shared/hooks' import { useThemeStore } from '../model/store' function ThemeSync() { diff --git a/apps/web/features/theme/ui/theme-toggle.tsx b/apps/web/features/theme/ui/theme-toggle.tsx index 5846eeca..62f87a79 100644 --- a/apps/web/features/theme/ui/theme-toggle.tsx +++ b/apps/web/features/theme/ui/theme-toggle.tsx @@ -1,8 +1,9 @@ 'use client' +import { useHydratedStore } from '@/shared/hooks' + import { Button, cn, MoonIcon, SunIcon } from '@repo/ui' -import { useHydratedStore } from '../../../shared/hooks' import { useThemeStore } from '../model/store' interface ThemeToggleProps { diff --git a/apps/web/proxy.ts b/apps/web/proxy.ts index f6ad920a..efdef2fb 100644 --- a/apps/web/proxy.ts +++ b/apps/web/proxy.ts @@ -3,15 +3,14 @@ import { isProtectedRoute, ROUTE_QUERY_PARAMS, ROUTES, -} from '@/shared/config/routes' -import { NextResponse, type NextRequest, type ProxyConfig } from 'next/server' - -import { appendSetCookieHeaders, clearAuthCookies } from './lib/api/auth-cookies' +} from '@/shared/config' +import { appendSetCookieHeaders, clearAuthCookies } from '@/shared/lib/api/auth-cookies' import { refreshAuthSession, type AuthRefreshResult, -} from './lib/api/refresh-auth-session' -import { isTokenExpiredSoon } from './lib/session' +} from '@/shared/lib/api/refresh-auth-session' +import { isTokenExpiredSoon } from '@/shared/lib/session' +import { NextResponse, type NextRequest, type ProxyConfig } from 'next/server' const createLoginRedirect = (request: NextRequest) => { const { pathname, search } = request.nextUrl diff --git a/apps/web/hooks/api/use-auth.ts b/apps/web/shared/api/use-auth.ts similarity index 91% rename from apps/web/hooks/api/use-auth.ts rename to apps/web/shared/api/use-auth.ts index c9bbaac0..6cc4251d 100644 --- a/apps/web/hooks/api/use-auth.ts +++ b/apps/web/shared/api/use-auth.ts @@ -1,4 +1,4 @@ -import { authService } from '@/lib/api/auth-service' +import { authService } from '@/shared/lib/api/auth-service' import { useMutation, useQuery } from '@tanstack/react-query' export const authKeys = { diff --git a/apps/web/hooks/api/use-example.ts b/apps/web/shared/api/use-example.ts similarity index 95% rename from apps/web/hooks/api/use-example.ts rename to apps/web/shared/api/use-example.ts index 712eec29..856529c2 100644 --- a/apps/web/hooks/api/use-example.ts +++ b/apps/web/shared/api/use-example.ts @@ -3,15 +3,14 @@ * Скопируйте его и адаптируйте для своей сущности. */ -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' - import { CreateExampleDto, Example, exampleService, UpdateExampleDto, -} from '../../lib/api/example-service' -import { ApiError, PaginationParams } from '../../lib/api/types' +} from '@/shared/lib/api/example-service' +import { ApiError, PaginationParams } from '@/shared/lib/api/types' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' // Query keys для кэширования export const exampleKeys = { diff --git a/apps/web/hooks/api/use-teams.ts b/apps/web/shared/api/use-teams.ts similarity index 95% rename from apps/web/hooks/api/use-teams.ts rename to apps/web/shared/api/use-teams.ts index aedd8ad2..a2aca699 100644 --- a/apps/web/hooks/api/use-teams.ts +++ b/apps/web/shared/api/use-teams.ts @@ -4,8 +4,8 @@ import { type DeleteTeamResponse, type Team, type UpdateTeam, -} from '@/lib/api/teams-service' -import type { ApiError } from '@/lib/api/types' +} from '@/shared/lib/api/teams-service' +import type { ApiError } from '@/shared/lib/api/types' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' export const teamsKeys = { diff --git a/apps/web/hooks/use-feature-flag.ts b/apps/web/shared/config/feature-flags.ts similarity index 100% rename from apps/web/hooks/use-feature-flag.ts rename to apps/web/shared/config/feature-flags.ts diff --git a/apps/web/shared/config/index.ts b/apps/web/shared/config/index.ts new file mode 100644 index 00000000..0bcf4b99 --- /dev/null +++ b/apps/web/shared/config/index.ts @@ -0,0 +1,2 @@ +export * from './feature-flags' +export * from './routes' diff --git a/apps/web/lib/api/auth-cookies.ts b/apps/web/shared/lib/api/auth-cookies.ts similarity index 100% rename from apps/web/lib/api/auth-cookies.ts rename to apps/web/shared/lib/api/auth-cookies.ts diff --git a/apps/web/lib/api/auth-service.ts b/apps/web/shared/lib/api/auth-service.ts similarity index 100% rename from apps/web/lib/api/auth-service.ts rename to apps/web/shared/lib/api/auth-service.ts diff --git a/apps/web/lib/api/axios-config.ts b/apps/web/shared/lib/api/axios-config.ts similarity index 100% rename from apps/web/lib/api/axios-config.ts rename to apps/web/shared/lib/api/axios-config.ts diff --git a/apps/web/lib/api/client.ts b/apps/web/shared/lib/api/client.ts similarity index 92% rename from apps/web/lib/api/client.ts rename to apps/web/shared/lib/api/client.ts index e90b32a9..329fccf8 100644 --- a/apps/web/lib/api/client.ts +++ b/apps/web/shared/lib/api/client.ts @@ -1,10 +1,10 @@ -import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config/routes' +import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios' import { isClientSide, setCookieHeader } from './auth-cookies' import { axiosConfig } from './axios-config' import { refreshAuthSession } from './refresh-auth-session' -import { ApiError } from './types' +import type { ApiError } from './types' import { toApiError } from './utils' type RetryableConfig = InternalAxiosRequestConfig & { diff --git a/apps/web/lib/api/example-service.ts b/apps/web/shared/lib/api/example-service.ts similarity index 100% rename from apps/web/lib/api/example-service.ts rename to apps/web/shared/lib/api/example-service.ts diff --git a/apps/web/lib/api/public-client.ts b/apps/web/shared/lib/api/public-client.ts similarity index 100% rename from apps/web/lib/api/public-client.ts rename to apps/web/shared/lib/api/public-client.ts diff --git a/apps/web/lib/api/refresh-auth-session.ts b/apps/web/shared/lib/api/refresh-auth-session.ts similarity index 100% rename from apps/web/lib/api/refresh-auth-session.ts rename to apps/web/shared/lib/api/refresh-auth-session.ts diff --git a/apps/web/lib/api/request-auth-refresh.ts b/apps/web/shared/lib/api/request-auth-refresh.ts similarity index 100% rename from apps/web/lib/api/request-auth-refresh.ts rename to apps/web/shared/lib/api/request-auth-refresh.ts diff --git a/apps/web/lib/api/teams-service.ts b/apps/web/shared/lib/api/teams-service.ts similarity index 100% rename from apps/web/lib/api/teams-service.ts rename to apps/web/shared/lib/api/teams-service.ts diff --git a/apps/web/lib/api/types.ts b/apps/web/shared/lib/api/types.ts similarity index 100% rename from apps/web/lib/api/types.ts rename to apps/web/shared/lib/api/types.ts diff --git a/apps/web/lib/api/utils.ts b/apps/web/shared/lib/api/utils.ts similarity index 100% rename from apps/web/lib/api/utils.ts rename to apps/web/shared/lib/api/utils.ts diff --git a/apps/web/lib/projects/catalog.ts b/apps/web/shared/lib/projects/catalog.ts similarity index 98% rename from apps/web/lib/projects/catalog.ts rename to apps/web/shared/lib/projects/catalog.ts index f08c59f1..29381501 100644 --- a/apps/web/lib/projects/catalog.ts +++ b/apps/web/shared/lib/projects/catalog.ts @@ -1,4 +1,4 @@ -import { teamRoutes } from '@/shared/config/routes' +import { teamRoutes } from '@/shared/config' export type ProjectCatalogItem = { id: string diff --git a/apps/web/shared/lib/projects/index.ts b/apps/web/shared/lib/projects/index.ts new file mode 100644 index 00000000..6f5c1d90 --- /dev/null +++ b/apps/web/shared/lib/projects/index.ts @@ -0,0 +1,2 @@ +export * from './catalog' +export * from './project-code' diff --git a/apps/web/lib/projects/project-code.ts b/apps/web/shared/lib/projects/project-code.ts similarity index 100% rename from apps/web/lib/projects/project-code.ts rename to apps/web/shared/lib/projects/project-code.ts diff --git a/apps/web/lib/query-client.ts b/apps/web/shared/lib/query-client.ts similarity index 100% rename from apps/web/lib/query-client.ts rename to apps/web/shared/lib/query-client.ts diff --git a/apps/web/lib/session/index.ts b/apps/web/shared/lib/session/index.ts similarity index 100% rename from apps/web/lib/session/index.ts rename to apps/web/shared/lib/session/index.ts diff --git a/apps/web/lib/session/utils.ts b/apps/web/shared/lib/session/utils.ts similarity index 100% rename from apps/web/lib/session/utils.ts rename to apps/web/shared/lib/session/utils.ts diff --git a/apps/web/views/auth/index.ts b/apps/web/views/auth/index.ts new file mode 100644 index 00000000..e1d9e759 --- /dev/null +++ b/apps/web/views/auth/index.ts @@ -0,0 +1,2 @@ +export { LoginPageView } from './ui/login-page-view' +export { RegisterPageView } from './ui/register-page-view' diff --git a/apps/web/app/(auth)/login/use-login-form.ts b/apps/web/views/auth/model/use-login-form.ts similarity index 100% rename from apps/web/app/(auth)/login/use-login-form.ts rename to apps/web/views/auth/model/use-login-form.ts diff --git a/apps/web/app/(auth)/register/use-register-form.ts b/apps/web/views/auth/model/use-register-form.ts similarity index 100% rename from apps/web/app/(auth)/register/use-register-form.ts rename to apps/web/views/auth/model/use-register-form.ts diff --git a/apps/web/app/(auth)/auth-form-layout.tsx b/apps/web/views/auth/ui/auth-form-layout.tsx similarity index 100% rename from apps/web/app/(auth)/auth-form-layout.tsx rename to apps/web/views/auth/ui/auth-form-layout.tsx diff --git a/apps/web/app/(auth)/login/login-form.tsx b/apps/web/views/auth/ui/login-form.tsx similarity index 93% rename from apps/web/app/(auth)/login/login-form.tsx rename to apps/web/views/auth/ui/login-form.tsx index ce59e409..8f5d093e 100644 --- a/apps/web/app/(auth)/login/login-form.tsx +++ b/apps/web/views/auth/ui/login-form.tsx @@ -12,7 +12,7 @@ import { VStack, } from '@repo/ui' -import { LoginFormValues } from './use-login-form' +import type { LoginFormValues } from '../model/use-login-form' const LoginForm = () => { const { control } = useFormContext() diff --git a/apps/web/views/auth/ui/login-page-view.tsx b/apps/web/views/auth/ui/login-page-view.tsx new file mode 100644 index 00000000..ec65f149 --- /dev/null +++ b/apps/web/views/auth/ui/login-page-view.tsx @@ -0,0 +1,68 @@ +'use client' + +import { useLogin } from '@/shared/api/use-auth' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' +import Link from 'next/link' +import { useRouter } from 'next/navigation' + +import { Button, Form, toast } from '@repo/ui' + +import { useLoginForm, type LoginFormValues } from '../model/use-login-form' +import { AuthFormLayout } from './auth-form-layout' +import { LoginForm } from './login-form' + +function LoginPageView() { + const form = useLoginForm() + + const loginMutation = useLogin() + const router = useRouter() + + const onSubmit = async (data: LoginFormValues) => { + try { + await loginMutation.mutateAsync(data) + router.push(ROUTES.teams) + } catch (error) { + if (isApiError(error)) { + toast.error(error.message) + } else { + throw error + } + } + } + + return ( +
+ + + Войти + + } + > +
+ +

+ Еще нет аккаунта?{' '} + + Зарегистрироваться + +

+
+
+
+ + ) +} + +export { LoginPageView } diff --git a/apps/web/app/(auth)/register/register-form.tsx b/apps/web/views/auth/ui/register-form.tsx similarity index 95% rename from apps/web/app/(auth)/register/register-form.tsx rename to apps/web/views/auth/ui/register-form.tsx index 3716b06a..a620ca94 100644 --- a/apps/web/app/(auth)/register/register-form.tsx +++ b/apps/web/views/auth/ui/register-form.tsx @@ -12,7 +12,7 @@ import { VStack, } from '@repo/ui' -import { RegisterFormValues } from './use-register-form' +import type { RegisterFormValues } from '../model/use-register-form' const RegisterForm = () => { const { control } = useFormContext() diff --git a/apps/web/views/auth/ui/register-page-view.tsx b/apps/web/views/auth/ui/register-page-view.tsx new file mode 100644 index 00000000..d1513143 --- /dev/null +++ b/apps/web/views/auth/ui/register-page-view.tsx @@ -0,0 +1,68 @@ +'use client' + +import { useRegister } from '@/shared/api/use-auth' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' +import Link from 'next/link' +import { useRouter } from 'next/navigation' + +import { Button, Form, toast } from '@repo/ui' + +import { useRegisterForm, type RegisterFormValues } from '../model/use-register-form' +import { AuthFormLayout } from './auth-form-layout' +import { RegisterForm } from './register-form' + +function RegisterPageView() { + const form = useRegisterForm() + + const registerMutation = useRegister() + const router = useRouter() + + const onSubmit = async (data: RegisterFormValues) => { + try { + await registerMutation.mutateAsync(data) + router.push(ROUTES.teams) + } catch (error) { + if (isApiError(error)) { + toast.error(error.message) + } else { + throw error + } + } + } + + return ( +
+ + + Зарегистрироваться + + } + > +
+ +

+ Уже есть аккаунт?{' '} + + Войти + +

+
+
+
+ + ) +} + +export { RegisterPageView } diff --git a/apps/web/views/home/model/content.ts b/apps/web/views/home/model/content.ts index cac770d5..649b782f 100644 --- a/apps/web/views/home/model/content.ts +++ b/apps/web/views/home/model/content.ts @@ -1,4 +1,4 @@ -import { ROUTES } from '@/shared/config/routes' +import { ROUTES } from '@/shared/config' import type { ComponentType, SVGProps } from 'react' import { diff --git a/apps/web/views/home/ui/home-header.tsx b/apps/web/views/home/ui/home-header.tsx index 0dabc700..f67a356c 100644 --- a/apps/web/views/home/ui/home-header.tsx +++ b/apps/web/views/home/ui/home-header.tsx @@ -1,4 +1,4 @@ -import { ROUTES } from '@/shared/config/routes' +import { ROUTES } from '@/shared/config' import Link from 'next/link' import { Button } from '@repo/ui' diff --git a/apps/web/views/projects/ui/create-project-dialog.tsx b/apps/web/views/projects/ui/create-project-dialog.tsx index aebf46e8..0fb1f71f 100644 --- a/apps/web/views/projects/ui/create-project-dialog.tsx +++ b/apps/web/views/projects/ui/create-project-dialog.tsx @@ -5,7 +5,7 @@ import { normalizeProjectCodeInput, PROJECT_CODE_MAX_LENGTH, PROJECT_CODE_MIN_LENGTH, -} from '@/lib/projects/project-code' +} from '@/shared/lib/projects' import { useEffect, useState } from 'react' import { diff --git a/apps/web/views/projects/ui/project-card.tsx b/apps/web/views/projects/ui/project-card.tsx index 7523909e..2c4242ae 100644 --- a/apps/web/views/projects/ui/project-card.tsx +++ b/apps/web/views/projects/ui/project-card.tsx @@ -1,6 +1,6 @@ 'use client' -import type { ProjectCatalogItem } from '@/lib/projects/catalog' +import type { ProjectCatalogItem } from '@/shared/lib/projects' import { cn } from '@repo/ui' import { ArrowRight, KanbanSquare, ListTodo } from '@repo/ui/icons' diff --git a/apps/web/views/projects/ui/project-detail-page-view.tsx b/apps/web/views/projects/ui/project-detail-page-view.tsx index 56fe3f77..49be4d80 100644 --- a/apps/web/views/projects/ui/project-detail-page-view.tsx +++ b/apps/web/views/projects/ui/project-detail-page-view.tsx @@ -1,8 +1,8 @@ 'use client' -import { useTeamDetail } from '@/hooks/api/use-teams' -import { formatProjectNameFromId, getProjectById } from '@/lib/projects/catalog' -import { teamRoutes } from '@/shared/config/routes' +import { useTeamDetail } from '@/shared/api/use-teams' +import { teamRoutes } from '@/shared/config' +import { formatProjectNameFromId, getProjectById } from '@/shared/lib/projects' import Link from 'next/link' import { useParams } from 'next/navigation' diff --git a/apps/web/views/projects/ui/projects-page-view.tsx b/apps/web/views/projects/ui/projects-page-view.tsx index 3ac10e88..b130e9bc 100644 --- a/apps/web/views/projects/ui/projects-page-view.tsx +++ b/apps/web/views/projects/ui/projects-page-view.tsx @@ -1,12 +1,12 @@ 'use client' -import { useTeamDetail } from '@/hooks/api/use-teams' +import { useTeamDetail } from '@/shared/api/use-teams' import { buildTeamProjectHref, createProjectId, projectCatalog, type ProjectCatalogItem, -} from '@/lib/projects/catalog' +} from '@/shared/lib/projects' import { useParams, useRouter } from 'next/navigation' import { useState } from 'react' diff --git a/apps/web/views/teams/ui/create-team-dialog.tsx b/apps/web/views/teams/ui/create-team-dialog.tsx index 548128c8..cb01e5de 100644 --- a/apps/web/views/teams/ui/create-team-dialog.tsx +++ b/apps/web/views/teams/ui/create-team-dialog.tsx @@ -1,8 +1,8 @@ 'use client' -import { useCreateTeam } from '@/hooks/api/use-teams' -import { isApiError } from '@/lib/api/utils' -import { ROUTES } from '@/shared/config/routes' +import { useCreateTeam } from '@/shared/api/use-teams' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' import { useRouter } from 'next/navigation' import { useState } from 'react' diff --git a/apps/web/views/teams/ui/team-settings-page-view.tsx b/apps/web/views/teams/ui/team-settings-page-view.tsx index c60a23fd..3e66fa49 100644 --- a/apps/web/views/teams/ui/team-settings-page-view.tsx +++ b/apps/web/views/teams/ui/team-settings-page-view.tsx @@ -1,6 +1,6 @@ 'use client' -import { useTeamDetail } from '@/hooks/api/use-teams' +import { useTeamDetail } from '@/shared/api/use-teams' import { useParams } from 'next/navigation' import { useEffect, useState } from 'react' diff --git a/apps/web/views/teams/ui/teams-page-view.tsx b/apps/web/views/teams/ui/teams-page-view.tsx index 1a21c422..e412537c 100644 --- a/apps/web/views/teams/ui/teams-page-view.tsx +++ b/apps/web/views/teams/ui/teams-page-view.tsx @@ -1,7 +1,7 @@ 'use client' -import { useTeamsList } from '@/hooks/api/use-teams' -import { ROUTES, teamRoutes } from '@/shared/config/routes' +import { useTeamsList } from '@/shared/api/use-teams' +import { ROUTES, teamRoutes } from '@/shared/config' import { useRouter } from 'next/navigation' import { useMemo } from 'react' diff --git a/apps/web/widgets/main-layout/model/sidebar/navigation.ts b/apps/web/widgets/main-layout/model/sidebar/navigation.ts index 9c314d1b..e022cdbe 100644 --- a/apps/web/widgets/main-layout/model/sidebar/navigation.ts +++ b/apps/web/widgets/main-layout/model/sidebar/navigation.ts @@ -1,6 +1,5 @@ -import { FEATURES } from '@/hooks/use-feature-flag' -import { projectCatalog } from '@/lib/projects/catalog' -import { ROUTES, SIDEBAR_ROUTE_IDS, teamRoutes } from '@/shared/config/routes' +import { FEATURES, ROUTES, SIDEBAR_ROUTE_IDS, teamRoutes } from '@/shared/config' +import { projectCatalog } from '@/shared/lib/projects' import { Bell, diff --git a/apps/web/widgets/main-layout/model/sidebar/types.ts b/apps/web/widgets/main-layout/model/sidebar/types.ts index 9d842974..8aeaa8cb 100644 --- a/apps/web/widgets/main-layout/model/sidebar/types.ts +++ b/apps/web/widgets/main-layout/model/sidebar/types.ts @@ -1,4 +1,4 @@ -import type { SidebarRouteId } from '@/shared/config/routes' +import type { SidebarRouteId } from '@/shared/config' import type { LucideIcon } from '@repo/ui/icons' diff --git a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx index 72b511f9..ffc2d2ff 100644 --- a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx +++ b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx @@ -1,7 +1,7 @@ 'use client' -import { useLogout, useMe } from '@/hooks/api/use-auth' -import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config/routes' +import { useLogout, useMe } from '@/shared/api/use-auth' +import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' import React from 'react' import { diff --git a/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx b/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx index d6da24aa..47899ed2 100644 --- a/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx +++ b/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx @@ -1,9 +1,9 @@ 'use client' import { ThemeToggle } from '@/features/theme' -import { useTeamsList } from '@/hooks/api/use-teams' -import { buildTeamProjectHref } from '@/lib/projects/catalog' -import { getSidebarRouteId, ROUTES, type SidebarRouteId } from '@/shared/config/routes' +import { useTeamsList } from '@/shared/api/use-teams' +import { getSidebarRouteId, ROUTES, type SidebarRouteId } from '@/shared/config' +import { buildTeamProjectHref } from '@/shared/lib/projects' import Link from 'next/link' import { useParams, usePathname } from 'next/navigation' import React from 'react' From b8df9889f4eae364a3d9539c657ecf5377ddafd4 Mon Sep 17 00:00:00 2001 From: Fing0r Date: Tue, 17 Mar 2026 21:37:22 +0700 Subject: [PATCH 4/5] =?UTF-8?q?feat(repo):=20=D0=BE=D0=B1=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=D0=BE=D0=B2=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B4=20=D0=B2=20fsd=20=D0=B2=20prettierrc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .prettierrc.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.prettierrc.mjs b/.prettierrc.mjs index c09cbcef..23666d92 100644 --- a/.prettierrc.mjs +++ b/.prettierrc.mjs @@ -9,6 +9,12 @@ const config = { '', '^@repo(.*)$', '', + '^@/views(.*)$', + '^@/widgets(.*)$', + '^@/features(.*)$', + '^@/entities(.*)$', + '^@/shared(.*)$', + '', '^[../]', '^[./]', ], From 4a2c02cf7bf11059ce003404e3ae3b4982026fde Mon Sep 17 00:00:00 2001 From: Fing0r Date: Tue, 17 Mar 2026 21:39:35 +0700 Subject: [PATCH 5/5] =?UTF-8?q?refactor(web):=20=D0=BF=D1=80=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=BB=20=D0=BF=D1=80=D0=B5=D1=82=D1=82=D0=B8?= =?UTF-8?q?=D0=B5=D1=80=20=D0=B4=D0=BB=D1=8F=20=D0=B8=D0=BC=D0=BF=D0=BE?= =?UTF-8?q?=D1=80=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/app/(auth)/layout.tsx | 3 ++- apps/web/app/(dashboard)/layout.tsx | 7 ++++--- apps/web/app/(dashboard)/sprints/page.tsx | 3 ++- apps/web/app/(dashboard)/tasks/page.tsx | 3 ++- .../teams/[id]/projects/[projectId]/page.tsx | 5 +++-- .../app/(dashboard)/teams/[id]/projects/page.tsx | 5 +++-- .../app/(dashboard)/teams/[id]/settings/page.tsx | 5 +++-- apps/web/app/error.tsx | 3 ++- apps/web/app/not-found.tsx | 3 ++- apps/web/app/providers.tsx | 5 +++-- apps/web/features/theme/ui/theme-sync.tsx | 3 ++- apps/web/features/theme/ui/theme-toggle.tsx | 4 ++-- apps/web/proxy.ts | 3 ++- apps/web/shared/api/use-auth.ts | 3 ++- apps/web/shared/api/use-example.ts | 3 ++- apps/web/shared/api/use-teams.ts | 3 ++- apps/web/shared/lib/api/client.ts | 3 ++- apps/web/views/auth/ui/login-page-view.tsx | 7 ++++--- apps/web/views/auth/ui/register-page-view.tsx | 7 ++++--- apps/web/views/home/model/content.ts | 3 ++- apps/web/views/home/ui/home-header.tsx | 3 ++- .../web/views/projects/ui/create-project-dialog.tsx | 13 +++++++------ apps/web/views/projects/ui/project-card.tsx | 4 ++-- .../views/projects/ui/project-detail-page-view.tsx | 7 ++++--- apps/web/views/projects/ui/projects-page-view.tsx | 11 ++++++----- apps/web/views/teams/ui/create-team-dialog.tsx | 7 ++++--- apps/web/views/teams/ui/team-settings-page-view.tsx | 3 ++- apps/web/views/teams/ui/teams-page-view.tsx | 5 +++-- .../widgets/main-layout/model/sidebar/navigation.ts | 6 +++--- apps/web/widgets/main-layout/model/sidebar/types.ts | 4 ++-- .../widgets/main-layout/ui/header/profile-menu.tsx | 5 +++-- apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx | 9 +++++---- 32 files changed, 93 insertions(+), 65 deletions(-) diff --git a/apps/web/app/(auth)/layout.tsx b/apps/web/app/(auth)/layout.tsx index 02a1a56c..8051227c 100644 --- a/apps/web/app/(auth)/layout.tsx +++ b/apps/web/app/(auth)/layout.tsx @@ -1,7 +1,8 @@ -import { FEATURES, ROUTES } from '@/shared/config' import Link from 'next/link' import { notFound } from 'next/navigation' +import { FEATURES, ROUTES } from '@/shared/config' + interface Props { children: React.ReactNode } diff --git a/apps/web/app/(dashboard)/layout.tsx b/apps/web/app/(dashboard)/layout.tsx index 7556f9d8..80d614ff 100644 --- a/apps/web/app/(dashboard)/layout.tsx +++ b/apps/web/app/(dashboard)/layout.tsx @@ -1,11 +1,12 @@ +import { dehydrate, HydrationBoundary } from '@tanstack/react-query' +import { redirect } from 'next/navigation' + +import { MainLayout } from '@/widgets/main-layout' import { authKeys } from '@/shared/api/use-auth' import { ROUTES } from '@/shared/config' import { authService } from '@/shared/lib/api/auth-service' import { isApiError } from '@/shared/lib/api/utils' import { getQueryClient } from '@/shared/lib/query-client' -import { MainLayout } from '@/widgets/main-layout' -import { dehydrate, HydrationBoundary } from '@tanstack/react-query' -import { redirect } from 'next/navigation' interface Props { children: React.ReactNode diff --git a/apps/web/app/(dashboard)/sprints/page.tsx b/apps/web/app/(dashboard)/sprints/page.tsx index c37a00cd..34b78e60 100644 --- a/apps/web/app/(dashboard)/sprints/page.tsx +++ b/apps/web/app/(dashboard)/sprints/page.tsx @@ -1,8 +1,9 @@ -import { FEATURES } from '@/shared/config' import { notFound } from 'next/navigation' import { Card, CardContent } from '@repo/ui' +import { FEATURES } from '@/shared/config' + type SprintTask = { id: string title: string diff --git a/apps/web/app/(dashboard)/tasks/page.tsx b/apps/web/app/(dashboard)/tasks/page.tsx index 8c7212b3..dd00b9ca 100644 --- a/apps/web/app/(dashboard)/tasks/page.tsx +++ b/apps/web/app/(dashboard)/tasks/page.tsx @@ -1,8 +1,9 @@ -import { FEATURES } from '@/shared/config' import { notFound } from 'next/navigation' import { Button } from '@repo/ui' +import { FEATURES } from '@/shared/config' + const mockTasks = [ { id: 'TT-1', diff --git a/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx b/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx index 16fcb7a4..9dfc63db 100644 --- a/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/projects/[projectId]/page.tsx @@ -1,7 +1,8 @@ -import { FEATURES } from '@/shared/config' -import { ProjectDetailPageView } from '@/views/projects' import { notFound } from 'next/navigation' +import { ProjectDetailPageView } from '@/views/projects' +import { FEATURES } from '@/shared/config' + export default function ProjectDetailPage() { if (!FEATURES.PROJECTS) { notFound() diff --git a/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx b/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx index 8ac5b2e6..ecb9f9d3 100644 --- a/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/projects/page.tsx @@ -1,7 +1,8 @@ -import { FEATURES } from '@/shared/config' -import { ProjectsPageView } from '@/views/projects' import { notFound } from 'next/navigation' +import { ProjectsPageView } from '@/views/projects' +import { FEATURES } from '@/shared/config' + export default function ProjectsPage() { if (!FEATURES.PROJECTS) { notFound() diff --git a/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx b/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx index a90a7a13..37cc59ec 100644 --- a/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx +++ b/apps/web/app/(dashboard)/teams/[id]/settings/page.tsx @@ -1,7 +1,8 @@ -import { FEATURES } from '@/shared/config' -import { TeamSettingsPageView } from '@/views/teams' import { notFound } from 'next/navigation' +import { TeamSettingsPageView } from '@/views/teams' +import { FEATURES } from '@/shared/config' + export default function TeamSettingsPage() { if (!FEATURES.TEAM_SETTINGS) { notFound() diff --git a/apps/web/app/error.tsx b/apps/web/app/error.tsx index b540ffa5..15821203 100644 --- a/apps/web/app/error.tsx +++ b/apps/web/app/error.tsx @@ -1,11 +1,12 @@ 'use client' -import { ROUTES } from '@/shared/config' import Link from 'next/link' import { useEffect } from 'react' import { Button, EmptyState } from '@repo/ui' +import { ROUTES } from '@/shared/config' + type GlobalErrorProps = { error: Error & { digest?: string } reset: () => void diff --git a/apps/web/app/not-found.tsx b/apps/web/app/not-found.tsx index 2a09f457..f937f9d9 100644 --- a/apps/web/app/not-found.tsx +++ b/apps/web/app/not-found.tsx @@ -1,8 +1,9 @@ -import { ROUTES } from '@/shared/config' import Link from 'next/link' import { Button, EmptyState } from '@repo/ui' +import { ROUTES } from '@/shared/config' + export default function GlobalNotFound() { return (
diff --git a/apps/web/app/providers.tsx b/apps/web/app/providers.tsx index 80a787eb..ab1d12b0 100644 --- a/apps/web/app/providers.tsx +++ b/apps/web/app/providers.tsx @@ -1,10 +1,11 @@ 'use client' -import { ThemeSync } from '@/features/theme' -import { getQueryClient } from '@/shared/lib/query-client' import { QueryClientProvider } from '@tanstack/react-query' import { ReactQueryDevtools } from '@tanstack/react-query-devtools' +import { ThemeSync } from '@/features/theme' +import { getQueryClient } from '@/shared/lib/query-client' + interface Props { children: React.ReactNode } diff --git a/apps/web/features/theme/ui/theme-sync.tsx b/apps/web/features/theme/ui/theme-sync.tsx index 38e04363..44f30a89 100644 --- a/apps/web/features/theme/ui/theme-sync.tsx +++ b/apps/web/features/theme/ui/theme-sync.tsx @@ -1,8 +1,9 @@ 'use client' -import { useHydratedStore } from '@/shared/hooks' import { useEffect } from 'react' +import { useHydratedStore } from '@/shared/hooks' + import { useThemeStore } from '../model/store' function ThemeSync() { diff --git a/apps/web/features/theme/ui/theme-toggle.tsx b/apps/web/features/theme/ui/theme-toggle.tsx index 62f87a79..fbba1207 100644 --- a/apps/web/features/theme/ui/theme-toggle.tsx +++ b/apps/web/features/theme/ui/theme-toggle.tsx @@ -1,9 +1,9 @@ 'use client' -import { useHydratedStore } from '@/shared/hooks' - import { Button, cn, MoonIcon, SunIcon } from '@repo/ui' +import { useHydratedStore } from '@/shared/hooks' + import { useThemeStore } from '../model/store' interface ThemeToggleProps { diff --git a/apps/web/proxy.ts b/apps/web/proxy.ts index efdef2fb..1dbb0042 100644 --- a/apps/web/proxy.ts +++ b/apps/web/proxy.ts @@ -1,3 +1,5 @@ +import { NextResponse, type NextRequest, type ProxyConfig } from 'next/server' + import { isAuthRoute, isProtectedRoute, @@ -10,7 +12,6 @@ import { type AuthRefreshResult, } from '@/shared/lib/api/refresh-auth-session' import { isTokenExpiredSoon } from '@/shared/lib/session' -import { NextResponse, type NextRequest, type ProxyConfig } from 'next/server' const createLoginRedirect = (request: NextRequest) => { const { pathname, search } = request.nextUrl diff --git a/apps/web/shared/api/use-auth.ts b/apps/web/shared/api/use-auth.ts index 6cc4251d..51dfc037 100644 --- a/apps/web/shared/api/use-auth.ts +++ b/apps/web/shared/api/use-auth.ts @@ -1,6 +1,7 @@ -import { authService } from '@/shared/lib/api/auth-service' import { useMutation, useQuery } from '@tanstack/react-query' +import { authService } from '@/shared/lib/api/auth-service' + export const authKeys = { register: ['register'], login: ['login'], diff --git a/apps/web/shared/api/use-example.ts b/apps/web/shared/api/use-example.ts index 856529c2..3486246c 100644 --- a/apps/web/shared/api/use-example.ts +++ b/apps/web/shared/api/use-example.ts @@ -3,6 +3,8 @@ * Скопируйте его и адаптируйте для своей сущности. */ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' + import { CreateExampleDto, Example, @@ -10,7 +12,6 @@ import { UpdateExampleDto, } from '@/shared/lib/api/example-service' import { ApiError, PaginationParams } from '@/shared/lib/api/types' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' // Query keys для кэширования export const exampleKeys = { diff --git a/apps/web/shared/api/use-teams.ts b/apps/web/shared/api/use-teams.ts index a2aca699..e81c052e 100644 --- a/apps/web/shared/api/use-teams.ts +++ b/apps/web/shared/api/use-teams.ts @@ -1,3 +1,5 @@ +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' + import { teamsService, type CreateTeam, @@ -6,7 +8,6 @@ import { type UpdateTeam, } from '@/shared/lib/api/teams-service' import type { ApiError } from '@/shared/lib/api/types' -import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' export const teamsKeys = { all: ['teams'] as const, diff --git a/apps/web/shared/lib/api/client.ts b/apps/web/shared/lib/api/client.ts index 329fccf8..ba1d4ddf 100644 --- a/apps/web/shared/lib/api/client.ts +++ b/apps/web/shared/lib/api/client.ts @@ -1,6 +1,7 @@ -import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' import axios, { AxiosError, InternalAxiosRequestConfig } from 'axios' +import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' + import { isClientSide, setCookieHeader } from './auth-cookies' import { axiosConfig } from './axios-config' import { refreshAuthSession } from './refresh-auth-session' diff --git a/apps/web/views/auth/ui/login-page-view.tsx b/apps/web/views/auth/ui/login-page-view.tsx index ec65f149..1d6af186 100644 --- a/apps/web/views/auth/ui/login-page-view.tsx +++ b/apps/web/views/auth/ui/login-page-view.tsx @@ -1,13 +1,14 @@ 'use client' -import { useLogin } from '@/shared/api/use-auth' -import { ROUTES } from '@/shared/config' -import { isApiError } from '@/shared/lib/api/utils' import Link from 'next/link' import { useRouter } from 'next/navigation' import { Button, Form, toast } from '@repo/ui' +import { useLogin } from '@/shared/api/use-auth' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' + import { useLoginForm, type LoginFormValues } from '../model/use-login-form' import { AuthFormLayout } from './auth-form-layout' import { LoginForm } from './login-form' diff --git a/apps/web/views/auth/ui/register-page-view.tsx b/apps/web/views/auth/ui/register-page-view.tsx index d1513143..180f21ac 100644 --- a/apps/web/views/auth/ui/register-page-view.tsx +++ b/apps/web/views/auth/ui/register-page-view.tsx @@ -1,13 +1,14 @@ 'use client' -import { useRegister } from '@/shared/api/use-auth' -import { ROUTES } from '@/shared/config' -import { isApiError } from '@/shared/lib/api/utils' import Link from 'next/link' import { useRouter } from 'next/navigation' import { Button, Form, toast } from '@repo/ui' +import { useRegister } from '@/shared/api/use-auth' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' + import { useRegisterForm, type RegisterFormValues } from '../model/use-register-form' import { AuthFormLayout } from './auth-form-layout' import { RegisterForm } from './register-form' diff --git a/apps/web/views/home/model/content.ts b/apps/web/views/home/model/content.ts index 649b782f..feda8d2d 100644 --- a/apps/web/views/home/model/content.ts +++ b/apps/web/views/home/model/content.ts @@ -1,4 +1,3 @@ -import { ROUTES } from '@/shared/config' import type { ComponentType, SVGProps } from 'react' import { @@ -14,6 +13,8 @@ import { Zap, } from '@repo/ui/icons' +import { ROUTES } from '@/shared/config' + type IconType = ComponentType> export const navigationItems = [ diff --git a/apps/web/views/home/ui/home-header.tsx b/apps/web/views/home/ui/home-header.tsx index f67a356c..24164504 100644 --- a/apps/web/views/home/ui/home-header.tsx +++ b/apps/web/views/home/ui/home-header.tsx @@ -1,9 +1,10 @@ -import { ROUTES } from '@/shared/config' import Link from 'next/link' import { Button } from '@repo/ui' import { Github, KanbanSquare } from '@repo/ui/icons' +import { ROUTES } from '@/shared/config' + import { navigationItems } from '../model/content' function HomeHeader() { diff --git a/apps/web/views/projects/ui/create-project-dialog.tsx b/apps/web/views/projects/ui/create-project-dialog.tsx index 0fb1f71f..72748bf9 100644 --- a/apps/web/views/projects/ui/create-project-dialog.tsx +++ b/apps/web/views/projects/ui/create-project-dialog.tsx @@ -1,11 +1,5 @@ 'use client' -import { - isValidProjectCode, - normalizeProjectCodeInput, - PROJECT_CODE_MAX_LENGTH, - PROJECT_CODE_MIN_LENGTH, -} from '@/shared/lib/projects' import { useEffect, useState } from 'react' import { @@ -19,6 +13,13 @@ import { Label, } from '@repo/ui' +import { + isValidProjectCode, + normalizeProjectCodeInput, + PROJECT_CODE_MAX_LENGTH, + PROJECT_CODE_MIN_LENGTH, +} from '@/shared/lib/projects' + import { projectDialogContentClassName, projectDialogFooterClassName, diff --git a/apps/web/views/projects/ui/project-card.tsx b/apps/web/views/projects/ui/project-card.tsx index 2c4242ae..09cc9895 100644 --- a/apps/web/views/projects/ui/project-card.tsx +++ b/apps/web/views/projects/ui/project-card.tsx @@ -1,10 +1,10 @@ 'use client' -import type { ProjectCatalogItem } from '@/shared/lib/projects' - import { cn } from '@repo/ui' import { ArrowRight, KanbanSquare, ListTodo } from '@repo/ui/icons' +import type { ProjectCatalogItem } from '@/shared/lib/projects' + interface Props { project: ProjectCatalogItem onOpen: (project: ProjectCatalogItem) => void diff --git a/apps/web/views/projects/ui/project-detail-page-view.tsx b/apps/web/views/projects/ui/project-detail-page-view.tsx index 49be4d80..26d5a81b 100644 --- a/apps/web/views/projects/ui/project-detail-page-view.tsx +++ b/apps/web/views/projects/ui/project-detail-page-view.tsx @@ -1,8 +1,5 @@ 'use client' -import { useTeamDetail } from '@/shared/api/use-teams' -import { teamRoutes } from '@/shared/config' -import { formatProjectNameFromId, getProjectById } from '@/shared/lib/projects' import Link from 'next/link' import { useParams } from 'next/navigation' @@ -16,6 +13,10 @@ import { SquareKanban, } from '@repo/ui/icons' +import { useTeamDetail } from '@/shared/api/use-teams' +import { teamRoutes } from '@/shared/config' +import { formatProjectNameFromId, getProjectById } from '@/shared/lib/projects' + import { projectPageSubtitleClassName, projectPageTitleClassName } from '../lib/styles' const actionCards = [ diff --git a/apps/web/views/projects/ui/projects-page-view.tsx b/apps/web/views/projects/ui/projects-page-view.tsx index b130e9bc..fbc14187 100644 --- a/apps/web/views/projects/ui/projects-page-view.tsx +++ b/apps/web/views/projects/ui/projects-page-view.tsx @@ -1,5 +1,11 @@ 'use client' +import { useParams, useRouter } from 'next/navigation' +import { useState } from 'react' + +import { Button, EmptyState, Input } from '@repo/ui' +import { FolderKanban, Plus, Search } from '@repo/ui/icons' + import { useTeamDetail } from '@/shared/api/use-teams' import { buildTeamProjectHref, @@ -7,11 +13,6 @@ import { projectCatalog, type ProjectCatalogItem, } from '@/shared/lib/projects' -import { useParams, useRouter } from 'next/navigation' -import { useState } from 'react' - -import { Button, EmptyState, Input } from '@repo/ui' -import { FolderKanban, Plus, Search } from '@repo/ui/icons' import { projectPageHeaderClassName, diff --git a/apps/web/views/teams/ui/create-team-dialog.tsx b/apps/web/views/teams/ui/create-team-dialog.tsx index cb01e5de..fd901b9e 100644 --- a/apps/web/views/teams/ui/create-team-dialog.tsx +++ b/apps/web/views/teams/ui/create-team-dialog.tsx @@ -1,8 +1,5 @@ 'use client' -import { useCreateTeam } from '@/shared/api/use-teams' -import { ROUTES } from '@/shared/config' -import { isApiError } from '@/shared/lib/api/utils' import { useRouter } from 'next/navigation' import { useState } from 'react' @@ -19,6 +16,10 @@ import { toast, } from '@repo/ui' +import { useCreateTeam } from '@/shared/api/use-teams' +import { ROUTES } from '@/shared/config' +import { isApiError } from '@/shared/lib/api/utils' + import { teamDialogContentClassName, teamDialogFooterClassName, diff --git a/apps/web/views/teams/ui/team-settings-page-view.tsx b/apps/web/views/teams/ui/team-settings-page-view.tsx index 3e66fa49..eb1c7af6 100644 --- a/apps/web/views/teams/ui/team-settings-page-view.tsx +++ b/apps/web/views/teams/ui/team-settings-page-view.tsx @@ -1,6 +1,5 @@ 'use client' -import { useTeamDetail } from '@/shared/api/use-teams' import { useParams } from 'next/navigation' import { useEffect, useState } from 'react' @@ -28,6 +27,8 @@ import { } from '@repo/ui' import { Crown, Mail, Settings2, Shield, Trash2, UserPlus, Users } from '@repo/ui/icons' +import { useTeamDetail } from '@/shared/api/use-teams' + import { teamDialogContentClassName, teamDialogFooterClassName, diff --git a/apps/web/views/teams/ui/teams-page-view.tsx b/apps/web/views/teams/ui/teams-page-view.tsx index e412537c..49b6881e 100644 --- a/apps/web/views/teams/ui/teams-page-view.tsx +++ b/apps/web/views/teams/ui/teams-page-view.tsx @@ -1,13 +1,14 @@ 'use client' -import { useTeamsList } from '@/shared/api/use-teams' -import { ROUTES, teamRoutes } from '@/shared/config' import { useRouter } from 'next/navigation' import { useMemo } from 'react' import { Button, EmptyState } from '@repo/ui' import { Plus, Users } from '@repo/ui/icons' +import { useTeamsList } from '@/shared/api/use-teams' +import { ROUTES, teamRoutes } from '@/shared/config' + import { mapTeamListItemToTeamCardModel } from '../lib/mappers' import { teamPageHeaderClassName, diff --git a/apps/web/widgets/main-layout/model/sidebar/navigation.ts b/apps/web/widgets/main-layout/model/sidebar/navigation.ts index e022cdbe..a279c17d 100644 --- a/apps/web/widgets/main-layout/model/sidebar/navigation.ts +++ b/apps/web/widgets/main-layout/model/sidebar/navigation.ts @@ -1,6 +1,3 @@ -import { FEATURES, ROUTES, SIDEBAR_ROUTE_IDS, teamRoutes } from '@/shared/config' -import { projectCatalog } from '@/shared/lib/projects' - import { Bell, FolderKanban, @@ -12,6 +9,9 @@ import { Users, } from '@repo/ui/icons' +import { FEATURES, ROUTES, SIDEBAR_ROUTE_IDS, teamRoutes } from '@/shared/config' +import { projectCatalog } from '@/shared/lib/projects' + import type { SidebarNavSection, SidebarProjectItem, diff --git a/apps/web/widgets/main-layout/model/sidebar/types.ts b/apps/web/widgets/main-layout/model/sidebar/types.ts index 8aeaa8cb..fd365861 100644 --- a/apps/web/widgets/main-layout/model/sidebar/types.ts +++ b/apps/web/widgets/main-layout/model/sidebar/types.ts @@ -1,7 +1,7 @@ -import type { SidebarRouteId } from '@/shared/config' - import type { LucideIcon } from '@repo/ui/icons' +import type { SidebarRouteId } from '@/shared/config' + type SideBarStoreState = { isOpen: boolean } diff --git a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx index ffc2d2ff..d8faaa31 100644 --- a/apps/web/widgets/main-layout/ui/header/profile-menu.tsx +++ b/apps/web/widgets/main-layout/ui/header/profile-menu.tsx @@ -1,7 +1,5 @@ 'use client' -import { useLogout, useMe } from '@/shared/api/use-auth' -import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' import React from 'react' import { @@ -16,6 +14,9 @@ import { DropdownMenuTrigger, } from '@repo/ui' +import { useLogout, useMe } from '@/shared/api/use-auth' +import { ROUTE_QUERY_PARAMS, ROUTES } from '@/shared/config' + const currentUser = { name: 'Имя', avatar: 'AL', diff --git a/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx b/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx index 47899ed2..26a478c5 100644 --- a/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx +++ b/apps/web/widgets/main-layout/ui/sidebar/sidebar.tsx @@ -1,9 +1,5 @@ 'use client' -import { ThemeToggle } from '@/features/theme' -import { useTeamsList } from '@/shared/api/use-teams' -import { getSidebarRouteId, ROUTES, type SidebarRouteId } from '@/shared/config' -import { buildTeamProjectHref } from '@/shared/lib/projects' import Link from 'next/link' import { useParams, usePathname } from 'next/navigation' import React from 'react' @@ -11,6 +7,11 @@ import React from 'react' import { Avatar, AvatarFallback, cn } from '@repo/ui' import { KanbanSquare } from '@repo/ui/icons' +import { ThemeToggle } from '@/features/theme' +import { useTeamsList } from '@/shared/api/use-teams' +import { getSidebarRouteId, ROUTES, type SidebarRouteId } from '@/shared/config' +import { buildTeamProjectHref } from '@/shared/lib/projects' + import { getSidebarSections, sidebarCurrentUser,