complated si check request
This commit is contained in:
@@ -74,7 +74,6 @@ export function useLoginForm() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loginReqest.mutate({ phone: `998${phone}`, password: password });
|
loginReqest.mutate({ phone: `998${phone}`, password: password });
|
||||||
sessionStorage.setItem('prev_page', 'login');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,28 +1,11 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { ArrowRight, BrainCircuit } from 'lucide-react';
|
import { ArrowRight, BrainCircuit, Plus } from 'lucide-react';
|
||||||
import { FileUploadModal } from './ui/fileUploadModal';
|
import { FileUploadModal } from './ui/fileUploadModal';
|
||||||
|
|
||||||
export default function SiCTACard() {
|
export function SiCTACard() {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [lastSubmission, setLastSubmission] = useState<{
|
|
||||||
name: string;
|
|
||||||
words: number;
|
|
||||||
} | null>(null);
|
|
||||||
|
|
||||||
const handleSubmit = (
|
|
||||||
documentName: string,
|
|
||||||
_file: File,
|
|
||||||
wordCount: number,
|
|
||||||
) => {
|
|
||||||
// Here you would send the file to your backend for plagiarism check.
|
|
||||||
// The word count is already computed client-side for instant pricing display.
|
|
||||||
console.log(lastSubmission);
|
|
||||||
console.log('Submitting:', { documentName, wordCount });
|
|
||||||
setLastSubmission({ name: documentName, words: wordCount });
|
|
||||||
setIsOpen(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -42,11 +25,23 @@ export default function SiCTACard() {
|
|||||||
Yuborish <ArrowRight size={12} />
|
Yuborish <ArrowRight size={12} />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<FileUploadModal
|
<FileUploadModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
||||||
isOpen={isOpen}
|
</>
|
||||||
onClose={() => setIsOpen(false)}
|
);
|
||||||
onSubmit={handleSubmit}
|
}
|
||||||
/>
|
|
||||||
|
export function SiButton() {
|
||||||
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
onClick={() => setIsOpen(true)}
|
||||||
|
className="flex items-center gap-2 py-1 px-2 group relative overflow-hidden rounded-sm bg-linear-to-br from-violet-500 to-violet-600 text-left shadow-md hover:shadow-xl transition-all duration-200 hover:-translate-y-0.5 active:translate-y-0 active:shadow-md"
|
||||||
|
>
|
||||||
|
<Plus size={15} className="text-white" />
|
||||||
|
<h3 className="text-white font-semibold text-base">SI detektor</h3>
|
||||||
|
</button>
|
||||||
|
<FileUploadModal isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { DropZone } from './dropZone';
|
|||||||
export function FileUploadModal({
|
export function FileUploadModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
onSubmit,
|
|
||||||
pricing = DEFAULT_PRICING,
|
pricing = DEFAULT_PRICING,
|
||||||
}: FileUploadModalProps) {
|
}: FileUploadModalProps) {
|
||||||
const {
|
const {
|
||||||
@@ -59,7 +58,6 @@ export function FileUploadModal({
|
|||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
if (!canSubmit || !uploadedFile) return;
|
if (!canSubmit || !uploadedFile) return;
|
||||||
onSubmit(documentName.trim(), uploadedFile.file, wordCount);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export interface PricingConfig {
|
|||||||
export interface FileUploadModalProps {
|
export interface FileUploadModalProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
onSubmit: (documentName: string, file: File, wordCount: number) => void;
|
|
||||||
pricing?: PricingConfig;
|
pricing?: PricingConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
import { useState, useCallback, useRef } from 'react';
|
import { useState, useCallback, useRef } from 'react';
|
||||||
import { UploadedFile } from './tyeps';
|
import { UploadedFile } from './tyeps';
|
||||||
import { countWordsFromFile, SUPPORTED_EXTENSIONS } from './wordCount';
|
import { countWordsFromFile, SUPPORTED_EXTENSIONS } from './wordCount';
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { apiRequest } from '@/shared/request/apiRequest';
|
||||||
|
import { links } from '@/shared/request/links';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
interface UseFileUploadReturn {
|
interface UseFileUploadReturn {
|
||||||
documentName: string;
|
documentName: string;
|
||||||
@@ -28,6 +32,17 @@ export function useFileUpload(): UseFileUploadReturn {
|
|||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
|
const wordCount = useMutation({
|
||||||
|
mutationFn: (data: FormData) => apiRequest('POST', links.si_create, data),
|
||||||
|
onSuccess: (res) => {
|
||||||
|
console.log(res);
|
||||||
|
},
|
||||||
|
onError: (err) => {
|
||||||
|
console.log(err instanceof Error ? err.message : 'Unknown error');
|
||||||
|
toast.error(err instanceof Error ? err.message : 'Unknown error');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const validateFile = (file: File): string | null => {
|
const validateFile = (file: File): string | null => {
|
||||||
const ext = '.' + file.name.split('.').pop()?.toLowerCase();
|
const ext = '.' + file.name.split('.').pop()?.toLowerCase();
|
||||||
if (!SUPPORTED_EXTENSIONS.includes(ext)) {
|
if (!SUPPORTED_EXTENSIONS.includes(ext)) {
|
||||||
@@ -77,7 +92,14 @@ export function useFileUpload(): UseFileUploadReturn {
|
|||||||
wordCount: result.count,
|
wordCount: result.count,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
console.log('running');
|
||||||
|
if (!file) return;
|
||||||
|
console.log('running inner');
|
||||||
|
const fd = new FormData();
|
||||||
|
fd.append('title', file.name.replace(/\.[^/.]+$/, ''));
|
||||||
|
fd.append('file', file);
|
||||||
|
wordCount.mutate(fd);
|
||||||
|
console.log('stop');
|
||||||
setIsProcessing(false);
|
setIsProcessing(false);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@@ -11,4 +11,6 @@ export const links = {
|
|||||||
si_id: (si_id: number) => `/shared/ai_document/list/${si_id}/`,
|
si_id: (si_id: number) => `/shared/ai_document/list/${si_id}/`,
|
||||||
si_payment: (document_id: number) => `/shared/ai_document/pay/${document_id}`,
|
si_payment: (document_id: number) => `/shared/ai_document/pay/${document_id}`,
|
||||||
si_create: '/shared/ai_document/create/',
|
si_create: '/shared/ai_document/create/',
|
||||||
|
document_types: '/shared/document_types/',
|
||||||
|
pay_history: '/shared/orders/all/',
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FileSearch, ArrowRight } from 'lucide-react';
|
import { FileSearch, ArrowRight } from 'lucide-react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import SiCTACard from '@/features/modals/siModal/page';
|
import { SiCTACard } from '@/features/modals/siModal/page';
|
||||||
|
|
||||||
export const CtaCards = () => (
|
export const CtaCards = () => (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { apiRequest } from '@/shared/request/apiRequest';
|
|||||||
import { links } from '@/shared/request/links';
|
import { links } from '@/shared/request/links';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
import type { SiDocument } from '../../lib/types';
|
import type { SiDocument } from '../../lib/types';
|
||||||
|
import { SiButton } from '@/features/modals/siModal/page';
|
||||||
|
|
||||||
// ─── State badge ───────────────────────────────────────────────────────────────
|
// ─── State badge ───────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -181,13 +182,14 @@ export const SiTable: React.FC = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-xl font-bold text-slate-900">SI detektor</h2>
|
<h2 className="text-xl font-bold text-slate-900">SI detektor</h2>
|
||||||
<p className="text-sm text-slate-500 mt-0.5">
|
<p className="text-sm text-slate-500 mt-0.5">
|
||||||
{isLoading ? '...' : `${items.length} ta tekshiruv`}
|
{isLoading ? '...' : `${items.length} ta tekshiruv`}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<SiButton />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm overflow-hidden">
|
<div className="bg-white rounded-2xl border border-slate-100 shadow-sm overflow-hidden">
|
||||||
|
|||||||
Reference in New Issue
Block a user