diff --git a/src/app/[locale]/si/[id]/page.tsx b/src/app/[locale]/si/[id]/page.tsx
new file mode 100644
index 0000000..7ec954b
--- /dev/null
+++ b/src/app/[locale]/si/[id]/page.tsx
@@ -0,0 +1,10 @@
+import SiDetailPage from '@/widgets/detail/SiDetailPage';
+
+interface Props {
+ params: Promise<{ id: string }>;
+}
+
+export default async function SiDetail({ params }: Props) {
+ const { id } = await params;
+ return ;
+}
diff --git a/src/widgets/cabinet/ui/tables/SiTable.tsx b/src/widgets/cabinet/ui/tables/SiTable.tsx
index b9be12a..1504db1 100644
--- a/src/widgets/cabinet/ui/tables/SiTable.tsx
+++ b/src/widgets/cabinet/ui/tables/SiTable.tsx
@@ -1,6 +1,6 @@
'use client';
import React from 'react';
-import { Download, CreditCard } from 'lucide-react';
+import { Download, CreditCard, Eye } from 'lucide-react';
import { useMutation } from '@tanstack/react-query';
import { useSiHistory } from '../../lib/hooks/useSiHistory';
import { formatDate } from '@/widgets/history/lib/utils';
@@ -9,6 +9,7 @@ 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 ───────────────────────────────────────────────────────────────
@@ -89,6 +90,9 @@ const SiRow: React.FC<{ item: SiDocument; index: number }> = ({
item,
index,
}) => {
+ const router = useRouter();
+ const { locale } = useParams() as { locale: string };
+
const pay = useMutation({
mutationKey: ['si-payment', item.id],
mutationFn: () =>
@@ -168,7 +172,13 @@ const SiRow: React.FC<{ item: SiDocument; index: number }> = ({
{pay.isPending ? '...' : "To'lash"}
) : (
- —
+ router.push(`/${locale}/si/${item.id}`)}
+ className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium text-blue-600 bg-blue-50 hover:bg-blue-100 active:scale-95 transition-all duration-150"
+ >
+
+ Ko'rish
+
)}
diff --git a/src/widgets/detail/SiDetailPage.tsx b/src/widgets/detail/SiDetailPage.tsx
new file mode 100644
index 0000000..12b83cb
--- /dev/null
+++ b/src/widgets/detail/SiDetailPage.tsx
@@ -0,0 +1,356 @@
+'use client';
+
+import React, { useEffect } from 'react';
+import { useQuery } from '@tanstack/react-query';
+import { useParams } from 'next/navigation';
+import { apiRequest } from '@/shared/request/apiRequest';
+import { links } from '@/shared/request/links';
+import { Download, CloudDownload } from 'lucide-react';
+
+// ── Types ────────────────────────────────────────────────────────────────────
+
+type SiResult = {
+ original: number;
+ ai_possible: number;
+ ai: number;
+};
+
+type SiDetail = {
+ id: number;
+ title: string;
+ file: string;
+ created_at: string;
+ updated_at: string;
+ state: 'paid' | 'unpaid';
+ total_words: number;
+ si_percantage: number | null;
+ result: SiResult | null;
+ file_size?: number;
+ file_extension?: string;
+ total_price?: number | string;
+ user?: { name: string; surname: string };
+};
+
+// ── Helpers ───────────────────────────────────────────────────────────────────
+
+function formatDate(iso: string): string {
+ return new Date(iso).toLocaleString('uz-UZ', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute: '2-digit',
+ second: '2-digit',
+ });
+}
+
+function fileExtension(url: string): string {
+ const name = url.split('/').pop() ?? '';
+ const ext = name.split('.').pop();
+ return ext ? `.${ext}` : '—';
+}
+
+function fileName(url: string): string {
+ return url.split('/').pop() ?? '—';
+}
+
+function fileSizeMb(bytes?: number): string {
+ if (!bytes) return '—';
+ return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
+}
+
+// ── Sub-components ────────────────────────────────────────────────────────────
+
+function InfoRow({ label, value }: { label: string; value: React.ReactNode }) {
+ return (
+
+ {label}
+
+ {value}
+
+
+ );
+}
+
+function SiBar({
+ label,
+ value,
+ color,
+}: {
+ label: string;
+ value: number;
+ color: string;
+}) {
+ return (
+
+
+ {label}
+ {value}%
+
+
+
+ );
+}
+
+// ── Skeleton ──────────────────────────────────────────────────────────────────
+
+function Skeleton({ className }: { className?: string }) {
+ return (
+
+ );
+}
+
+function LoadingSkeleton() {
+ return (
+
+
+
+
+
+ {Array.from({ length: 8 }).map((_, i) => (
+
+
+
+
+ ))}
+
+
+ {Array.from({ length: 3 }).map((_, i) => (
+
+ ))}
+
+
+
+ );
+}
+
+// ── Main Page ─────────────────────────────────────────────────────────────────
+
+export default function SiDetailPage({ id }: { id: number }) {
+ const { locale } = useParams() as { locale: string };
+ useEffect(() => {
+ console.log(locale);
+ }, []);
+
+ const {
+ data: doc,
+ isLoading,
+ isError,
+ } = useQuery({
+ queryKey: ['si-detail', id],
+ queryFn: (): Promise =>
+ apiRequest('GET', links.si_id(id)).then((res) => res.data as SiDetail),
+ enabled: !!id,
+ staleTime: 1000 * 60 * 5,
+ });
+
+ if (isLoading) return ;
+
+ if (isError || !doc) {
+ return (
+
+
+
+ Ma'lumot topilmadi
+
+
window.history.back()}
+ className="text-sm text-blue-600 hover:underline"
+ >
+ Ortga qaytish
+
+
+
+ );
+ }
+
+ // Derive SI percentages
+ const original = doc.result?.original ?? 100 - (doc.si_percantage ?? 0);
+ const aiPossible = doc.result?.ai_possible ?? 0;
+ const ai = doc.result?.ai ?? doc.si_percantage ?? 0;
+
+ return (
+
+ {/* ── Header ── */}
+
+
+
window.history.back()}
+ className="w-8 h-8 rounded-lg border border-slate-200 flex items-center justify-center hover:bg-slate-50 transition-colors shrink-0"
+ >
+
+
+
+
+
+ {doc.title || 'SI tekshiruv'}
+
+
+
+
+
+ {/* ── Section 1: Asosiy ma'lumotlar ── */}
+
+ {/* Section header */}
+
+
+ Asosiy ma'lumotlar
+
+
+
+
+
+ {/* Sub-header */}
+
+ Hujjat haqida ma'lumotlar
+
+
+
+ {doc.user && (
+
+ )}
+
+
+
0
+ ? doc.total_words.toLocaleString('uz-UZ')
+ : '—'
+ }
+ />
+
+ {doc.file_size !== undefined && (
+
+ )}
+ {doc.total_price !== undefined && (
+
+ )}
+
+ {/* Download button */}
+ {doc.file && (
+
+ )}
+
+
+
+ {/* ── Section 2: SI detektor natijalari ── */}
+
+ {/* Header row */}
+
+
+ {/* PDF icon */}
+
+
+
+ Hujjatning SI detektori natijalari
+
+
+ Ushbu oynada foydalanuvchi tomonidan yuklangan matn
+ sun'iy intellekt (SI) yordamida yozilgan bo'lish
+ ehtimoli bo'yicha tahlil natijalari aks etirilgan.
+ Detektor matnning stilistik, grammatik va semantik
+ xususiyatlarini baholab, uning qanchalik darajada sun'iy
+ intellekt tomonidan generatsiya qilingan bo'lishi
+ mumkinligini foizlik ko'rinishida ko'rsatadi.
+
+
+
+
+ {doc.file && (
+
+
+ Yuklab olish
+
+ )}
+
+
+ {/* Bars */}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/widgets/fileUpload/lib/usePlagiraism.ts b/src/widgets/fileUpload/lib/usePlagiraism.ts
index 02c8152..d520bbd 100644
--- a/src/widgets/fileUpload/lib/usePlagiraism.ts
+++ b/src/widgets/fileUpload/lib/usePlagiraism.ts
@@ -140,6 +140,7 @@ export function usePlagiarismForm() {
fd.append('file', form.file!); // File object — multipart/form-data
fd.append('certificate', String(form.certificate));
fd.append('total_price', '41200');
+ fd.append('document_type', form.document_type);
checkdocumentRequest.mutate(fd);
},
[form],
diff --git a/src/widgets/fileUpload/ui/Plagiraismcheckform.tsx b/src/widgets/fileUpload/ui/Plagiraismcheckform.tsx
index 21de95b..7e202b8 100644
--- a/src/widgets/fileUpload/ui/Plagiraismcheckform.tsx
+++ b/src/widgets/fileUpload/ui/Plagiraismcheckform.tsx
@@ -11,10 +11,10 @@ import {
} from './Plagiraismui';
import { usePlagiarismForm } from '../lib/usePlagiraism';
import { useTranslations } from 'next-intl';
-import { DOCUMENT_TYPES } from '@/features/modals/sertificateModal/types';
import { PaymentModal } from '@/features/modals/paymentModal/ui/Paymentmodal';
+import DocumentsTypes from './documentsType';
-const inputCls = `
+export const inputCls = `
w-full px-3.5 py-3.5 text-[14px] text-slate-800
bg-blue-50 border border-blue-200 rounded-xl
placeholder:text-blue-400
@@ -177,26 +177,11 @@ export function PlagiarismCheckForm() {
{/* Document type */}
-
-
- setOption(e.target.value as typeof form.document_type)
- }
- disabled={isLoading || submission.status === 'success'}
- className={`${inputCls} cursor-pointer`}
- >
-
- Hujjat turini tanlang...
-
- {DOCUMENT_TYPES.map((type) => (
-
- {type.label}
-
- ))}
-
-
+
{/* Submit */}
void;
+ disabled?: boolean;
+}
+
+export default function DocumentsTypes({
+ value,
+ onChange,
+ disabled,
+}: DocumentsTypesProps) {
+ const { data, isLoading } = useQuery({
+ queryKey: ['document_types'],
+ queryFn: (): Promise =>
+ apiRequest('GET', links.document_types).then(
+ (res) => res.data as DocumentType[],
+ ),
+ });
+
+ return (
+
+ onChange(e.target.value)}
+ disabled={isLoading || disabled}
+ className={`${inputCls} cursor-pointer`}
+ >
+
+ {isLoading ? 'Yuklanmoqda...' : 'Hujjat turini tanlang...'}
+
+ {data?.map((type) => (
+
+ {type.name}
+
+ ))}
+
+
+ );
+}