diff --git a/public/lanka.jpg b/public/lanka.jpg new file mode 100644 index 0000000..6de218f Binary files /dev/null and b/public/lanka.jpg differ diff --git a/src/app/[locale]/dashboard/page.tsx b/src/app/[locale]/dashboard/page.tsx new file mode 100644 index 0000000..40f7edc --- /dev/null +++ b/src/app/[locale]/dashboard/page.tsx @@ -0,0 +1,26 @@ +'use client'; +import { useEffect, useState } from 'react'; +import { Dashboard } from '@/widgets/cabinet/ui/dashboard'; +import { MOCK_USER } from '@/widgets/cabinet/lib/mock'; + +export default function Page() { + const [userName, setUserName] = useState(MOCK_USER.first_name); + + useEffect(() => { + const data = localStorage.getItem('user'); + if (data) { + try { + const user = JSON.parse(data); + setUserName(user.name || MOCK_USER.first_name); + } catch { + // ignore + } + } + }, []); + + return ( +
+ +
+ ); +} diff --git a/src/app/[locale]/payments/page.tsx b/src/app/[locale]/payments/page.tsx new file mode 100644 index 0000000..9ff75fd --- /dev/null +++ b/src/app/[locale]/payments/page.tsx @@ -0,0 +1,9 @@ +import { PaymentsTable } from '@/widgets/cabinet/ui/tables/PaymentsTable'; + +export default function Page() { + return ( +
+ +
+ ); +} diff --git a/src/app/[locale]/profile/page.tsx b/src/app/[locale]/profile/page.tsx new file mode 100644 index 0000000..097c5b3 --- /dev/null +++ b/src/app/[locale]/profile/page.tsx @@ -0,0 +1,10 @@ +import { ProfileSection } from '@/widgets/cabinet/ui/profile'; +import { MOCK_STATS } from '@/widgets/cabinet/lib/mock'; + +export default function Page() { + return ( +
+ +
+ ); +} diff --git a/src/app/[locale]/si/page.tsx b/src/app/[locale]/si/page.tsx new file mode 100644 index 0000000..6745a07 --- /dev/null +++ b/src/app/[locale]/si/page.tsx @@ -0,0 +1,12 @@ +import { SiTable } from '@/widgets/cabinet/ui/tables/SiTable'; +import { SiUploadSection } from '@/features/modals/siModal/ui/SiUploadSection'; +import React from 'react'; + +export default function Page() { + return ( +
+ + +
+ ); +} diff --git a/src/features/auth/login/lib/useLoginForm.ts b/src/features/auth/login/lib/useLoginForm.ts index 0f30c53..07bc1df 100644 --- a/src/features/auth/login/lib/useLoginForm.ts +++ b/src/features/auth/login/lib/useLoginForm.ts @@ -52,7 +52,7 @@ export function useLoginForm() { console.log('Login successful:', data); toggleLoginModal(); toast.success('Kirish muvaffaqiyatli!'); - route.push('/plagiat'); + route.push('/dashboard'); }, onError: (err) => { console.log('Login failed:', err); diff --git a/src/features/modals/siModal/page.tsx b/src/features/modals/siModal/page.tsx index 9e8b8af..8047885 100644 --- a/src/features/modals/siModal/page.tsx +++ b/src/features/modals/siModal/page.tsx @@ -1,54 +1,30 @@ 'use client'; -import { useState } from 'react'; -import { ArrowRight, BrainCircuit, Plus } from 'lucide-react'; -import { FileUploadModal } from './ui/fileUploadModal'; +import { ArrowRight, BrainCircuit } from 'lucide-react'; import { useTranslations } from 'next-intl'; +import Link from 'next/link'; export function SiCTACard() { - const [isOpen, setIsOpen] = useState(false); const t = useTranslations('Cabinet'); return ( - <> - - setIsOpen(false)} /> - - ); -} - -export function SiButton() { - const [isOpen, setIsOpen] = useState(false); - const t = useTranslations('Cabinet'); - return ( - <> - - setIsOpen(false)} /> - + +
+ +
+ +

+ {t('siDetector')} +

+

+ {t('siDesc')} +

+ + {t('submit')} + + ); } diff --git a/src/features/modals/siModal/ui/SiUploadSection.tsx b/src/features/modals/siModal/ui/SiUploadSection.tsx new file mode 100644 index 0000000..7750a54 --- /dev/null +++ b/src/features/modals/siModal/ui/SiUploadSection.tsx @@ -0,0 +1,117 @@ +'use client'; + +import { DEFAULT_PRICING, formatPrice } from '../utils/pricing'; +import { PricingConfig } from '../utils/tyeps'; +import { useFileUpload } from '../utils/useFileUpload'; +import { SUPPORTED_EXTENSIONS } from '../utils/wordCount'; +import { ErrorBanner, FileChip, PricingInfo, Spinner } from './modalParts'; +import { DropZone } from './dropZone'; +import { useTranslations } from 'next-intl'; + +interface SiUploadSectionProps { + pricing?: PricingConfig; +} + +export function SiUploadSection({ + pricing = DEFAULT_PRICING, +}: SiUploadSectionProps) { + const t = useTranslations('Cabinet'); + const { + documentName, + setDocumentName, + uploadedFile, + isDragging, + isProcessing, + error, + fileInputRef, + handleFileSelect, + handleDrop, + handleDragOver, + handleDragLeave, + handleRemoveFile, + openFilePicker, + canSubmit, + handleSubmit, + } = useFileUpload(); + + const wordCount = uploadedFile?.word_count ?? 0; + const totalPrice = uploadedFile?.total_price ?? 0; + + return ( +
+
+

+ {t('siDetector')} +

+

{t('siDesc')}

+
+ +
+ + setDocumentName(e.target.value)} + placeholder="Enter document name…" + className="w-full rounded-xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-800 placeholder:text-slate-400 outline-none transition-all duration-150 focus:border-blue-400 focus:ring-4 focus:ring-blue-400/10" + /> +
+ + { + const file = e.target.files?.[0]; + if (file) handleFileSelect(file); + }} + /> + + {uploadedFile ? ( +
+ +
+ ) : ( + + )} + + {error && } + + {uploadedFile?.status === 'done' && wordCount > 0 && ( + + )} + +
+ +
+
+ ); +} diff --git a/src/shared/config/i18n/messages/en.json b/src/shared/config/i18n/messages/en.json index a9322da..27a3b05 100644 --- a/src/shared/config/i18n/messages/en.json +++ b/src/shared/config/i18n/messages/en.json @@ -10,7 +10,9 @@ "login": "Login", "signup": "Sign up", "profile": "Profile", - "logout": "Logout" + "logout": "Logout", + "aboutPlagiat": "About Plagiarism", + "howItWorks": "How It Works" }, "Footer": { "product": "Product", diff --git a/src/shared/config/i18n/messages/ru.json b/src/shared/config/i18n/messages/ru.json index efe75fb..6370e67 100644 --- a/src/shared/config/i18n/messages/ru.json +++ b/src/shared/config/i18n/messages/ru.json @@ -10,7 +10,9 @@ "login": "Войти", "signup": "Регистрация", "profile": "Профиль", - "logout": "Выйти" + "logout": "Выйти", + "aboutPlagiat": "О плагиате", + "howItWorks": "Как это работает" }, "Footer": { "product": "Продукт", diff --git a/src/shared/config/i18n/messages/uz.d.json.ts b/src/shared/config/i18n/messages/uz.d.json.ts index cab81e5..5e7418e 100644 --- a/src/shared/config/i18n/messages/uz.d.json.ts +++ b/src/shared/config/i18n/messages/uz.d.json.ts @@ -14,6 +14,8 @@ declare const messages: { signup: "Ro'yxatdan o'tish"; profile: 'Profil'; logout: 'Chiqish'; + aboutPlagiat: 'Plagiat haqida'; + howItWorks: 'Bu qanday ishlaydi'; }; Footer: { product: 'Mahsulot'; diff --git a/src/shared/config/i18n/messages/uz.json b/src/shared/config/i18n/messages/uz.json index f3c1d5a..2144c0e 100644 --- a/src/shared/config/i18n/messages/uz.json +++ b/src/shared/config/i18n/messages/uz.json @@ -10,7 +10,9 @@ "login": "Kirish", "signup": "Ro'yxatdan o'tish", "profile": "Profil", - "logout": "Chiqish" + "logout": "Chiqish", + "aboutPlagiat": "Plagiat haqida", + "howItWorks": "Bu qanday ishlaydi" }, "Footer": { "product": "Mahsulot", diff --git a/src/widgets/cabinet/ui/index.tsx b/src/widgets/cabinet/ui/index.tsx index 6465886..9876802 100644 --- a/src/widgets/cabinet/ui/index.tsx +++ b/src/widgets/cabinet/ui/index.tsx @@ -2,8 +2,6 @@ import React from 'react'; import dynamic from 'next/dynamic'; import { AnimatePresence, motion } from 'framer-motion'; -import { Sidebar } from './Sidebar'; -import { CabinetNav } from './CabinetNav'; import { Dashboard } from './dashboard'; import { useCabinet } from '../lib/hooks/useCabinet'; import { MOCK_USER, MOCK_STATS } from '../lib/mock'; @@ -69,31 +67,15 @@ const FADE = { // ─── CabinetLayout ──────────────────────────────────────────────────────────── export const CabinetLayout: React.FC = () => { - const { activeSection, navigate, isSidebarOpen, toggleSidebar } = - useCabinet(); - const fullName = `${MOCK_USER.first_name} ${MOCK_USER.last_name}`; + const { activeSection } = useCabinet(); return ( -
- - -
- - -
- - - - - -
-
-
+
+ + + + + +
); }; diff --git a/src/widgets/cabinet/ui/tables/SiTable.tsx b/src/widgets/cabinet/ui/tables/SiTable.tsx index 1d8af46..6aef4d3 100644 --- a/src/widgets/cabinet/ui/tables/SiTable.tsx +++ b/src/widgets/cabinet/ui/tables/SiTable.tsx @@ -9,7 +9,6 @@ import { apiRequest } from '@/shared/request/apiRequest'; import { links } from '@/shared/request/links'; import { toast } from 'react-toastify'; import type { SiDocument } from '../../lib/types'; -import { SiButton } from '@/features/modals/siModal/page'; import { useRouter, useParams } from 'next/navigation'; // ─── State badge ─────────────────────────────────────────────────────────────── @@ -194,7 +193,6 @@ export const SiTable: React.FC = () => { {isLoading ? '...' : t('checksCount', { count: items.length })}

-
diff --git a/src/widgets/home/components/InfoSection.tsx b/src/widgets/home/components/InfoSection.tsx index eaffb4a..a93e84f 100644 --- a/src/widgets/home/components/InfoSection.tsx +++ b/src/widgets/home/components/InfoSection.tsx @@ -37,7 +37,7 @@ const InfoSection: FC = () => { }; return ( -
+
{/* Heading */} { return (
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, 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); const toggleRegisterModal = useRegisterModal( @@ -74,13 +29,13 @@ function AuthButtons() { ); const user = useUserPlagiatStore((state) => state.user); const clearUser = useUserPlagiatStore((state) => state.clearUser); + const clearTokens = () => { localStorage.removeItem('access'); localStorage.removeItem('refresh'); localStorage.removeItem('user'); clearUser(); }; - console.log('Current user:', user); useEffect(() => { const data = localStorage.getItem('user'); @@ -93,7 +48,7 @@ function AuthButtons() { if (localUser) { return ( -
+
@@ -102,24 +57,21 @@ function AuthButtons() { {localUser.name} - - {userItem.map((subItem) => ( - - { - setOpen(false); - if (subItem.url !== '/cabinet') { - clearTokens(); - } else { - setNavItem( - subItem.key as import('@/widgets/cabinet/lib/types').CabinetSection, - ); - } - }} - item={subItem} - /> - - ))} + + { + clearTokens(); + setOpen(false); + }} + > + + + {t('logout')} + +
@@ -127,16 +79,14 @@ function AuthButtons() { } return ( -
+
- +
); } diff --git a/src/widgets/navbar/ui/index.tsx b/src/widgets/navbar/ui/index.tsx index a24da44..342c43f 100644 --- a/src/widgets/navbar/ui/index.tsx +++ b/src/widgets/navbar/ui/index.tsx @@ -1,3 +1,4 @@ +'use client'; import { Button } from '@/shared/ui/button'; import { Sheet, @@ -13,16 +14,47 @@ import { AuthButtons } from './authButtons'; import { useTranslations } from 'next-intl'; import { Logo_image } from '@/image'; import Image from 'next/image'; +import { useEffect, useState } from 'react'; +import { useUserPlagiatStore } from '@/shared/zustand/user'; const Navbar = () => { const t = useTranslations('Navbar'); + const t_cab = useTranslations('Cabinet'); + const [localUser, setLocalUser] = useState<{ + id: number; + name: string; + surname: string; + } | null>(null); + const user = useUserPlagiatStore((state) => state.user); + + const scrollTo = (id: string) => { + const el = document.getElementById(id); + if (el) el.scrollIntoView({ behavior: 'smooth' }); + }; + + useEffect(() => { + const data = localStorage.getItem('user'); + if (data) { + setLocalUser(JSON.parse(data)); + } else { + setLocalUser(null); + } + }, [user]); + + const navItems = [ + { title: t_cab('dashboard'), href: '/dashboard' as const }, + { title: t_cab('plagiat'), href: '/plagiat' as const }, + { title: t_cab('siNav'), href: '/si' as const }, + { title: t_cab('payments'), href: '/payments' as const }, + { title: t('profile'), href: '/profile' as const }, + ]; return (
{/* Desktop Menu */}