Files
plagiat/src/widgets/plagiatCheck/ui/Plagiraismcheckform.tsx
nabijonovdavronbek619@gmail.com 73158a1972 vulneribilty fixed
2026-04-09 12:00:06 +05:00

216 lines
7.4 KiB
TypeScript

'use client';
import React from 'react';
import {
FieldWrapper,
TextInput,
ReadonlyField,
FileUploadField,
CertificateCheckbox,
SubmitButton,
StatusBanner,
} from './Plagiraismui';
import { usePlagiarismForm } from '../lib/usePlagiraism';
import { useTranslations } from 'next-intl';
import { PaymentModal } from '@/features/modals/paymentModal/ui/Paymentmodal';
import DocumentsTypes from './documentsType';
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
focus:outline-none focus:ring-2 focus:ring-blue-400/40 focus:border-blue-400
hover:border-blue-300
transition-all duration-150
disabled:opacity-60 disabled:cursor-not-allowed
`.trim();
// ─── UserIcon (inline) ───────────────────────────────────────────────────────
function UserIcon() {
return (
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={1.5}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15.75 6a3.75 3.75 0 11-7.5 0 3.75 3.75 0 017.5 0zM4.501 20.118a7.5 7.5 0 0114.998 0A17.933 17.933 0 0112 21.75c-2.676 0-5.216-.584-7.499-1.632z"
/>
</svg>
);
}
// ─── Component ───────────────────────────────────────────────────────────────
export function PlagiarismCheckForm() {
const t = useTranslations('PlagiarismCheck');
const {
form,
errors,
submission,
senderFullName,
isLoading,
setTopic,
setFile,
toggleCertificate,
handleSubmit,
resetSubmission,
handleSubmitWithModal,
isPaymentOpen,
setOption,
setIsPaymentOpen,
prices,
} = usePlagiarismForm();
return (
<>
<div className=" flex items-center justify-center p-4 font-['DM_Sans',sans-serif]">
<div className="w-full max-w-4xl">
{/* ── Header ────────────────────────────────────────────────────── */}
<div className="mb-8">
<div className="inline-flex items-center gap-2 bg-blue-100 text-blue-700 text-xs font-bold uppercase tracking-widest px-3 py-1.5 rounded-full mb-4">
<span className="w-1.5 h-1.5 rounded-full bg-blue-500" />
{t('badge')}
</div>
<h1 className="text-3xl font-black text-stone-900 leading-tight">
{t('title')}
</h1>
<p className="text-stone-500 mt-2 text-sm leading-relaxed">
{t('description')}
</p>
</div>
{/* ── Card ──────────────────────────────────────────────────────── */}
<div className="bg-white rounded-3xl shadow-xl shadow-stone-200/80 border border-stone-100 overflow-hidden">
{/* Progress bar accent */}
<div className="h-1 w-full bg-linear-to-r from-blue-400 via-blue-500 to-indigo-400" />
<form
onSubmit={handleSubmitWithModal}
noValidate
className="p-7 flex md:flex-row flex-col gap-6"
>
{/* Status banners */}
{submission.status === 'success' && (
<StatusBanner
status="success"
message={t('submissionSuccess')}
onDismiss={resetSubmission}
dismissText={t('dismiss')}
/>
)}
{submission.status === 'error' && submission.error && (
<StatusBanner
status="error"
message={submission.error}
onDismiss={resetSubmission}
dismissText={t('dismiss')}
/>
)}
{/* left part */}
<div className="flex flex-col gap-9 md:max-w-[50%] w-full">
{/* Topic */}
<FieldWrapper
label={t('documentTopic')}
htmlFor="title"
error={errors.title}
required
>
<TextInput
id="title"
type="text"
placeholder={t('topicPlaceholder')}
value={form.title}
onChange={(e) => setTopic(e.target.value)}
hasError={!!errors.title}
maxLength={200}
disabled={isLoading}
/>
</FieldWrapper>
{/* Sender Full Name (read-only) */}
<FieldWrapper label={t('senderFullName')}>
<ReadonlyField
value={senderFullName || t('notLoggedIn')}
icon={<UserIcon />}
autoFilledText={t('autoFilled')}
/>
</FieldWrapper>
{/* Certificate Option */}
<div>
<p className="text-sm font-semibold tracking-wide text-stone-700 uppercase mb-2">
{t('certificateOption')}
</p>
<CertificateCheckbox
checked={form.certificate}
onChange={toggleCertificate}
title={t('certificateTitle')}
description={t('certificateDescription')}
/>
</div>
</div>
{/* right part */}
<div className="flex flex-col gap-4 md:max-w-[50%] w-full">
{/* File Upload */}
<FieldWrapper
label={t('documentFile')}
error={errors.file}
required
>
<FileUploadField
file={form.file}
onFileChange={setFile}
hasError={!!errors.file}
clickToUploadText={t('clickToUpload')}
fileTypesText={t('fileTypes')}
removeFileAriaLabel={t('removeFile')}
/>
</FieldWrapper>
{/* Divider */}
<div className="border-t border-stone-100" />
{/* Document type */}
<DocumentsTypes
value={form.type}
onChange={setOption}
disabled={submission.status === 'success'}
hasError={!!errors.type}
error={errors.type}
/>
{/* Submit */}
<SubmitButton
isLoading={isLoading}
submittingText={t('submitting')}
submitText={t('submitButton')}
/>
</div>
</form>
</div>
{/* Footer note */}
<p className="text-center text-xs text-stone-400 mt-5">
{t('secureNote')}
</p>
</div>
</div>
<PaymentModal
isOpen={isPaymentOpen}
onClose={() => setIsPaymentOpen(false)}
price={prices}
onConfirmPayment={handleSubmit}
isLoading={isLoading}
/>
</>
);
}