From b4fd590edae14fcbf558fa3628c589f9c2bd151d Mon Sep 17 00:00:00 2001 From: "nabijonovdavronbek619@gmail.com" Date: Fri, 10 Apr 2026 16:53:29 +0500 Subject: [PATCH] fix base_api error --- .../sertificateModal/useSertificateModal.ts | 8 +- src/shared/request/apiRequest.ts | 2 +- src/shared/ui/navigation-menu.tsx | 2 +- src/shared/zustand/cabinetNav.ts | 12 ++ src/widgets/cabinet/lib/hooks/useCabinet.ts | 35 +++++- src/widgets/detail/pageDetail.tsx | 31 +++-- src/widgets/navbar/lib/model.ts | 1 + src/widgets/navbar/ui/SubMenuLink.tsx | 12 +- src/widgets/navbar/ui/authButtons.tsx | 106 +++++++++++------- 9 files changed, 151 insertions(+), 58 deletions(-) create mode 100644 src/shared/zustand/cabinetNav.ts diff --git a/src/features/modals/sertificateModal/useSertificateModal.ts b/src/features/modals/sertificateModal/useSertificateModal.ts index 751ee22..4d9cc3b 100644 --- a/src/features/modals/sertificateModal/useSertificateModal.ts +++ b/src/features/modals/sertificateModal/useSertificateModal.ts @@ -43,9 +43,9 @@ export function useCertificateModal({ const certificateMutation = useMutation({ mutationFn: (payload: CertificatePayload) => - apiRequest('POST', links.sertifikat(document_id), payload).then( - (res) => res.data as ArrayBuffer, - ), + apiRequest('POST', links.sertifikat(document_id), payload, { + responseType: 'arraybuffer', + }).then((res) => res.data), onSuccess: (data: ArrayBuffer) => { if (data) { const blob = new Blob([data], { type: 'application/pdf' }); @@ -54,7 +54,7 @@ export function useCertificateModal({ a.href = objectUrl; a.download = `certificate-${document_id}.pdf`; a.click(); - URL.revokeObjectURL(objectUrl); + setTimeout(() => URL.revokeObjectURL(objectUrl), 1000); } setSuccess(true); setTimeout(() => { diff --git a/src/shared/request/apiRequest.ts b/src/shared/request/apiRequest.ts index 7b29cff..8c06aa9 100644 --- a/src/shared/request/apiRequest.ts +++ b/src/shared/request/apiRequest.ts @@ -45,7 +45,7 @@ function extractErrorMessage(error: AxiosError): string { // ─── Constants ───────────────────────────────────────────────────────────────── // const baseUrl = process.env.NEXT_PUBLIC_API_BASE_URL; -const baseUrl = 'https://dev-api.anti-plagiat.uz/api/v1'; +const baseUrl = 'https://api.anti-plagiat.uz/api/v1'; const DEFAULT_LOCALE = 'uz'; // fallback locale for redirect // ─── Token helpers ───────────────────────────────────────────────────────────── diff --git a/src/shared/ui/navigation-menu.tsx b/src/shared/ui/navigation-menu.tsx index d242416..427bbdc 100644 --- a/src/shared/ui/navigation-menu.tsx +++ b/src/shared/ui/navigation-menu.tsx @@ -18,7 +18,7 @@ function NavigationMenu({ data-slot="navigation-menu" data-viewport={viewport} className={cn( - 'group/navigation-menu relative flex max-w-max flex-1 items-center justify-center', + ' relative flex max-w-max flex-1 items-center justify-center', className, )} {...props} diff --git a/src/shared/zustand/cabinetNav.ts b/src/shared/zustand/cabinetNav.ts new file mode 100644 index 0000000..2d35e71 --- /dev/null +++ b/src/shared/zustand/cabinetNav.ts @@ -0,0 +1,12 @@ +import { CabinetSection } from '@/widgets/cabinet/lib/types'; +import { create } from 'zustand'; + +type CabinetNavZustand = { + navItem: CabinetSection; + setNavItem: (item: string) => void; +}; + +export const useCabinetNav = create((set) => ({ + navItem: 'dashboard', + setNavItem: (item: string) => set({ navItem: item || 'dash' }), +})); diff --git a/src/widgets/cabinet/lib/hooks/useCabinet.ts b/src/widgets/cabinet/lib/hooks/useCabinet.ts index b928c0b..320dbac 100644 --- a/src/widgets/cabinet/lib/hooks/useCabinet.ts +++ b/src/widgets/cabinet/lib/hooks/useCabinet.ts @@ -1,14 +1,43 @@ 'use client'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; +import { useCabinetNav } from '@/shared/zustand/cabinetNav'; import type { CabinetSection } from '../types'; +const VALID_SECTIONS: CabinetSection[] = [ + 'dashboard', + 'plagiat', + 'si', + 'payments', + 'profile', +]; + export const useCabinet = () => { + const { navItem, setNavItem } = useCabinetNav(); + const navItemZustrand = useCabinetNav((state) => state.navItem); + const [isSidebarOpen, setIsSidebarOpen] = useState(false); const [activeSection, setActiveSection] = useState('dashboard'); - const [isSidebarOpen, setIsSidebarOpen] = useState(false); + + useEffect(() => { + if (navItemZustrand) { + const activeSection: CabinetSection = VALID_SECTIONS.includes( + navItemZustrand as CabinetSection, + ) + ? (navItemZustrand as CabinetSection) + : 'dashboard'; + setActiveSection(activeSection); + } else { + const activeSection: CabinetSection = VALID_SECTIONS.includes( + navItem as CabinetSection, + ) + ? (navItem as CabinetSection) + : 'dashboard'; + setActiveSection(activeSection); + } + }, [navItemZustrand]); const navigate = (section: CabinetSection) => { - setActiveSection(section); + setNavItem(section); setIsSidebarOpen(false); }; diff --git a/src/widgets/detail/pageDetail.tsx b/src/widgets/detail/pageDetail.tsx index 062b678..2d96f9d 100644 --- a/src/widgets/detail/pageDetail.tsx +++ b/src/widgets/detail/pageDetail.tsx @@ -10,7 +10,7 @@ import PaymentStatus from './paidStatus'; import Sertifikat from '@/features/modals/sertificateModal/sertifikat'; // ── Types ──────────────────────────────────────────────────────────────────── -const baseUrl = 'https://dev-api.anti-plagiat.uz/api/v1'; +const baseUrl = 'https://api.anti-plagiat.uz/api/v1'; interface AnalyzeText { [key: string]: number | string; } @@ -399,10 +399,25 @@ export default function DocumentDetailPage({ id }: { id: number }) { {doc.file && ( - { + const url = `${baseUrl}/shared/documents/${doc.id}/download`; + const res = await apiRequest( + 'GET', + url, + undefined, + { responseType: 'arraybuffer', baseURL: baseUrl }, + ); + const blob = new Blob([res.data], { + type: 'application/pdf', + }); + const objectUrl = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = objectUrl; + a.download = `document-${id}.pdf`; + a.click(); + setTimeout(() => URL.revokeObjectURL(objectUrl), 1000); + }} className="inline-flex items-center gap-2 px-4 py-2 rounded-lg bg-slate-900 text-white text-xs font-semibold hover:bg-slate-700 transition-colors" > {t('downloadPdf')} - + )} @@ -486,7 +501,7 @@ export default function DocumentDetailPage({ id }: { id: number }) {
@@ -502,7 +517,7 @@ export default function DocumentDetailPage({ id }: { id: number }) { color="#6366f1" /> diff --git a/src/widgets/navbar/lib/model.ts b/src/widgets/navbar/lib/model.ts index fa3c803..514a679 100644 --- a/src/widgets/navbar/lib/model.ts +++ b/src/widgets/navbar/lib/model.ts @@ -4,4 +4,5 @@ export interface MenuItem { description?: string; icon?: React.ComponentType<{ className?: string }>; items?: MenuItem[]; + key: string; } diff --git a/src/widgets/navbar/ui/SubMenuLink.tsx b/src/widgets/navbar/ui/SubMenuLink.tsx index dbff994..102efb7 100644 --- a/src/widgets/navbar/ui/SubMenuLink.tsx +++ b/src/widgets/navbar/ui/SubMenuLink.tsx @@ -1,3 +1,5 @@ +'use client'; +import { usePathname } from 'next/navigation'; import { MenuItem } from '../lib/model'; const SubMenuLink = ({ @@ -7,11 +9,17 @@ const SubMenuLink = ({ item: MenuItem; logOut?: () => void; }) => { + const pathname = usePathname(); + const isCabinet = pathname.includes('/cabinet'); + return ( { + href={isCabinet && item.url === '/cabinet' ? undefined : item.url} + onClick={(e) => { + if (isCabinet && item.url === '/cabinet') { + e.preventDefault(); + } if (logOut) { logOut(); } diff --git a/src/widgets/navbar/ui/authButtons.tsx b/src/widgets/navbar/ui/authButtons.tsx index 5cd7de9..82fef5d 100644 --- a/src/widgets/navbar/ui/authButtons.tsx +++ b/src/widgets/navbar/ui/authButtons.tsx @@ -2,37 +2,70 @@ import { Link } from '@/shared/config/i18n/navigation'; import { Button } from '@/shared/ui/button'; import { - NavigationMenu, - NavigationMenuContent, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, -} from '@/shared/ui/navigation-menu'; + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/shared/ui/dropdown-menu'; import SubMenuLink from './SubMenuLink'; import { ChangeLang } from './ChangeLang'; import { useLoginModal, useRegisterModal } from '@/shared/zustand/auth'; import { useTranslations } from 'next-intl'; import { useUserPlagiatStore } from '@/shared/zustand/user'; -import { LogOut, User } from 'lucide-react'; +import { + ChevronDown, + LogOut, + User, + LayoutDashboard, + FileSearch, + BrainCircuit, + CreditCard, +} from 'lucide-react'; import { useEffect, useState } from 'react'; +import { useCabinetNav } from '@/shared/zustand/cabinetNav'; function AuthButtons() { const t = useTranslations('Navbar'); + const t_cab = useTranslations('Cabinet'); + const setNavItem = useCabinetNav((state) => state.setNavItem); const [localUser, setLocalUser] = useState<{ id: number; name: string; surname: string; } | null>(null); - + const [open, setOpen] = useState(false); const auth = { login: { title: t('login'), url: '#' }, signup: { title: t('signup'), url: '#' }, }; const userItem = [ - { title: t('profile'), url: '/cabinet', icon: User }, - { title: t('logout'), url: '/', icon: LogOut }, + { title: t('profile'), url: '/cabinet', icon: User, key: 'profile' }, + { + url: '/cabinet', + title: t_cab('dashboard'), + icon: LayoutDashboard, + key: 'dashboard', + }, + { + url: '/cabinet', + title: t_cab('plagiat'), + icon: FileSearch, + key: 'plagiat', + }, + { + url: '/cabinet', + title: t_cab('siNav'), + icon: BrainCircuit, + key: 'si', + }, + { + url: '/cabinet', + title: t_cab('payments'), + icon: CreditCard, + key: 'payments', + }, + { title: t('logout'), url: '/', icon: LogOut, key: 'logout' }, ]; const toggleLoginModal = useLoginModal((state) => state.toggleLoginModal); @@ -51,7 +84,6 @@ function AuthButtons() { useEffect(() => { const data = localStorage.getItem('user'); - if (data) { setLocalUser(JSON.parse(data)); } else { @@ -65,33 +97,29 @@ function AuthButtons() {
- - - - - {localUser.name} - - - {userItem.map((subItem) => ( - - { - if (subItem.url !== '/cabinet') { - clearTokens(); - } - }} - item={subItem} - /> - - ))} - - - - + + + {localUser.name} + + + + {userItem.map((subItem) => ( + + { + setOpen(false); + if (subItem.url !== '/cabinet') { + clearTokens(); + } else { + setNavItem(subItem.key); + } + }} + item={subItem} + /> + + ))} + +
); }