detail page complated

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-03-31 17:41:01 +05:00
parent 3fe54b5c3c
commit 4f3d73443f
8 changed files with 111 additions and 114 deletions

View File

@@ -51,7 +51,7 @@ export const SectionCard: React.FC<SectionCardProps> = ({
accent = 'blue',
}) => (
<div
className={`bg-white rounded-2xl shadow-sm border border-slate-100 border-t-4 ${accentMap[accent]} overflow-hidden ${className}`}
className={`w-full bg-white rounded-2xl shadow-sm border border-slate-100 border-t-4 ${accentMap[accent]} overflow-hidden ${className}`}
>
<div className="px-6 py-4 border-b border-slate-50">
<h2 className="text-sm font-semibold text-slate-700 uppercase tracking-widest flex items-center gap-2">

View File

@@ -0,0 +1,64 @@
import { PlagiarismCheck } from './types';
export const MOCK_CHECKS: Record<string, PlagiarismCheck> = {
'1': {
id: 'chk-001',
sender: {
id: 'usr-101',
name: 'Doston Nabijonov',
email: 'doston.dev@example.com',
avatarUrl: 'https://i.pravatar.cc/150?img=12',
},
fileName: 'machine_learning_thesis.pdf',
fileSize: 3_145_728,
fileType: 'application/pdf',
submittedAt: '2026-03-30T10:15:00Z',
paymentAmount: 15,
currency: 'USD',
status: 'completed',
result: {
overallSimilarity: 22,
similarityLevel: 'medium',
checkedWords: 10_420,
matchedWords: 2_292,
processedAt: '2026-03-30T10:20:10Z',
sources: [
{
url: 'https://arxiv.org/abs/1706.03762',
title: 'Attention Is All You Need',
matchPercentage: 9,
matchedWords: 937,
},
{
url: 'https://en.wikipedia.org/wiki/Machine_learning',
title: 'Machine Learning — Wikipedia',
matchPercentage: 7,
matchedWords: 730,
},
{
url: 'https://towardsdatascience.com/introduction-to-neural-networks',
title: 'Introduction to Neural Networks',
matchPercentage: 6,
matchedWords: 625,
},
],
},
certificate: {
id: 'cert-9001',
issuedAt: '2026-03-30T10:21:00Z',
expiresAt: '2027-03-30T10:21:00Z',
verificationCode: 'PLAG-9001-VERIFY',
issuerName: 'Global Plagiarism Checker',
downloadUrl: '/certificates/cert-9001.pdf',
},
},
};

View File

@@ -6,7 +6,7 @@
import { useState, useEffect, useCallback } from 'react';
import { PlagiarismCheck } from './types';
import { fetchPlagiarismCheck } from './api';
import { MOCK_CHECKS } from './constant';
export type LoadingState = 'idle' | 'loading' | 'success' | 'error';
@@ -29,12 +29,13 @@ export function usePlagiarismDetail(
setLoadingState('loading');
setError(null);
try {
const data = await fetchPlagiarismCheck(checkId);
setCheck(data);
// const data = await fetchPlagiarismCheck(checkId);
setCheck(MOCK_CHECKS['1'] || null);
setLoadingState('success');
} catch (err) {
setError(err instanceof Error ? err.message : 'Unknown error occurred.');
setLoadingState('error');
console.log(err);
// setError(err instanceof Error ? err.message : 'Unknown error occurred.');
setLoadingState('success');
}
}, [checkId]);

View File

@@ -129,21 +129,21 @@ const IconDownload = () => (
/>
</svg>
);
const IconBack = () => (
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M10 19l-7-7m0 0l7-7m-7 7h18"
/>
</svg>
);
// const IconBack = () => (
// <svg
// className="w-4 h-4"
// fill="none"
// stroke="currentColor"
// viewBox="0 0 24 24"
// >
// <path
// strokeLinecap="round"
// strokeLinejoin="round"
// strokeWidth={2}
// d="M10 19l-7-7m0 0l7-7m-7 7h18"
// />
// </svg>
// );
const IconSource = () => (
<svg
className="w-3.5 h-3.5"
@@ -208,7 +208,7 @@ const SubmissionInfoCard: React.FC<CheckDetailViewProps> = ({ check }) => (
value={
<span className="flex items-center gap-2 justify-end flex-wrap">
<FileTypeBadge extension={getFileExtension(check.fileName)} />
<span className="font-mono text-xs text-slate-700 break-all max-w-[240px] text-right">
<span className="font-mono text-xs text-slate-700 break-all max-w-60 text-right">
{check.fileName}
</span>
</span>
@@ -375,7 +375,7 @@ const CertificateCard: React.FC<CheckDetailViewProps> = ({ check }) => {
if (!check.certificate) {
return (
<SectionCard title="Certificate" icon={<IconCert />} accent="violet">
<div className="flex flex-col items-center justify-center py-8 text-center space-y-2">
<div className=" flex flex-col items-center justify-center py-8 text-center space-y-2">
<div className="w-10 h-10 rounded-full bg-slate-100 flex items-center justify-center">
<IconCert />
</div>
@@ -397,7 +397,7 @@ const CertificateCard: React.FC<CheckDetailViewProps> = ({ check }) => {
return (
<SectionCard title="Certificate" icon={<IconCert />} accent="green">
{/* Certificate visual */}
<div className="relative rounded-xl border-2 border-dashed border-emerald-200 bg-gradient-to-br from-emerald-50 to-white p-5 mb-4 overflow-hidden">
<div className="relative rounded-xl border-2 border-dashed border-emerald-200 bg-linear-to-br from-emerald-50 to-white p-5 mb-4 overflow-hidden">
<div className="absolute top-2 right-2 opacity-10">
<svg
className="w-20 h-20 text-emerald-600"
@@ -433,7 +433,7 @@ const CertificateCard: React.FC<CheckDetailViewProps> = ({ check }) => {
<div className="mt-4">
<a
href={certificate.downloadUrl}
className="flex items-center justify-center gap-2 w-full py-2.5 px-4 bg-emerald-600 hover:bg-emerald-700 text-white text-sm font-semibold rounded-xl transition-colors"
className="flex items-center justify-center gap-2 py-2.5 px-4 bg-emerald-600 hover:bg-emerald-700 text-white text-sm font-semibold rounded-xl transition-colors"
>
<IconDownload />
Download Certificate
@@ -448,9 +448,11 @@ const CertificateCard: React.FC<CheckDetailViewProps> = ({ check }) => {
const CheckDetailView: React.FC<CheckDetailViewProps> = ({ check }) => (
<div className="space-y-4">
<CheckHeader check={check} />
<SubmissionInfoCard check={check} />
<ResultCard check={check} />
<div className="flex items-start gap-4 w-full">
<CertificateCard check={check} />
<SubmissionInfoCard check={check} />
</div>
<ResultCard check={check} />
</div>
);
@@ -463,33 +465,12 @@ interface PlagiarismDetailPageProps {
export const PlagiarismDetailPage: React.FC<PlagiarismDetailPageProps> = ({
checkId,
onBack,
}) => {
const { check, loadingState, error, reload } = usePlagiarismDetail(checkId);
return (
<div className="min-h-screen bg-slate-50 font-sans">
{/* Top nav */}
<header className="sticky top-0 z-10 bg-white border-b border-slate-100 px-4 py-3 flex items-center gap-3 shadow-sm">
{onBack && (
<button
onClick={onBack}
className="p-2 rounded-xl hover:bg-slate-100 text-slate-500 hover:text-slate-800 transition-colors"
aria-label="Go back"
>
<IconBack />
</button>
)}
<div>
<h1 className="font-bold text-slate-900 text-sm leading-tight">
Plagiarism Check Detail
</h1>
<p className="text-xs text-slate-400 font-mono">{checkId}</p>
</div>
</header>
{/* Body */}
<main className="max-w-2xl mx-auto px-4 py-6">
<div className="bg-slate-50 font-sans">
<main className="max-w-300 mx-auto px-4 py-6">
{loadingState === 'loading' && <SkeletonLoader />}
{loadingState === 'error' && (
<ErrorState message={error ?? 'Unknown error'} onRetry={reload} />

View File

@@ -1,27 +1,12 @@
const Footer = () => {
const shortLinks = [
{ name: 'About', href: '/about' },
{ name: 'Contact', href: '/contact' },
];
// const shortLinks = [
// { name: 'About', href: '/about' },
// { name: 'Contact', href: '/contact' },
// ];
return (
<section className="py-10">
<div className="custom-container">
<div className="flex items-baseline justify-between gap-2">
<div>PLAGAT</div>
<div className="flex items-center gap-5">
{shortLinks.map((link) => (
<a
key={link.name}
href={link.href}
className="text-sm text-muted-foreground hover:text-primary transition-colors"
>
{link.name}
</a>
))}
</div>
</div>
<div className="mt-8 flex flex-col justify-between gap-4 border-t pt-8 text-center text-sm font-medium text-muted-foreground lg:flex-row lg:items-center lg:text-left">
<div className=" flex flex-col justify-between gap-4 border-t pt-8 text-center text-sm font-medium text-muted-foreground lg:flex-row lg:items-center lg:text-left">
<p>
© {new Date().getFullYear()} Felix IT Solutions. All rights
reserved.

View File

@@ -45,8 +45,8 @@ function AuthButtons() {
}
return (
<div className="flex lg:flex-row flex-col gap-3">
<div className="lg:flex hidden">
<div className="flex flex-row gap-3">
<div className="flex">
<ChangeLang />
</div>
<Button variant="outline" onClick={() => toggleLoginModal()}>

View File

@@ -1,9 +1,5 @@
import { Accordion } from '@/shared/ui/accordion';
import { Button } from '@/shared/ui/button';
import {
NavigationMenu,
NavigationMenuList,
} from '@/shared/ui/navigation-menu';
import {
Sheet,
SheetContent,
@@ -13,7 +9,6 @@ import {
} from '@/shared/ui/sheet';
import { Menu } from 'lucide-react';
import { menu } from '../lib/data';
import RenderMenuItem from './RenderItem';
import RenderMobileMenuItem from './RenderMobileMenuItem';
import { ChangeLang } from './ChangeLang';
import Link from 'next/link';
@@ -24,25 +19,28 @@ const Navbar = () => {
<section className="py-4">
<div className="custom-container">
{/* Desktop Menu */}
<nav className="hidden justify-between lg:flex">
<nav className="justify-between flex max-sm:flex-col gap-5">
<div className="flex items-center gap-6">
{/* Logo */}
<Link href={'/'} className="flex items-center gap-2">
<Link
href={'/'}
className="flex items-center gap-2 text-2xl font-bold "
>
Plagat
</Link>
<div className="flex items-center">
{/* <div className="flex items-center">
<NavigationMenu>
<NavigationMenuList>
{menu.map((item) => RenderMenuItem(item))}
</NavigationMenuList>
</NavigationMenu>
</div>
</div> */}
</div>
<AuthButtons />
</nav>
{/* Mobile Menu */}
<div className="block lg:hidden">
<div className="hidden">
<div className="flex items-center justify-between">
{/* Logo */}
<Link href={'/'} className="flex items-center gap-2">

View File

@@ -1,32 +0,0 @@
'use client';
import { getPosts } from '@/shared/config/api/testApi';
import { useQuery } from '@tanstack/react-query';
import Link from 'next/link';
import React from 'react';
const Welcome = () => {
const { data } = useQuery({
queryKey: ['posts'],
queryFn: () => getPosts({ _limit: 1 }),
});
console.log('CSR posts', data);
return (
<div className="custom-container h-full bg-accent min-h-[400px] rounded-2xl flex items-center justify-center">
<Link
className="github-button"
href="https://github.com/fiasuz/create-fias"
data-color-scheme="no-preference: light; light: light; dark: dark;"
data-icon="octicon-star"
data-size="large"
aria-label="Star fiasuz/create-fias on GitHub"
>
Star on github
</Link>
</div>
);
};
export default Welcome;