register , login model complated. plagiraism component complated(essential part of main page is complated )

This commit is contained in:
nabijonovdavronbek619@gmail.com
2026-03-30 20:25:30 +05:00
parent 8906cf6634
commit 8b93952a06
29 changed files with 1475 additions and 205 deletions

View File

@@ -0,0 +1,249 @@
'use client';
import React, { useCallback } from 'react';
import { useRegisterForm } from '../lib/useRegisterForm';
import { formatPhone, normalizeDigits } from '@/shared/lib/formatPhone';
import PhonePrefix from '@/shared/ui/phonePrefix';
function Field({
id,
label,
type = 'text',
placeholder,
value,
name,
onChange,
error,
}: {
id: string;
label: string;
type?: string;
placeholder?: string;
value: string;
name: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
error?: string;
}) {
return (
<div className="flex flex-col gap-1.5">
<label
htmlFor={id}
className="text-[0.7rem] font-medium tracking-widest uppercase text-stone-500"
>
{label}
</label>
<input
id={id}
name={name}
type={type}
placeholder={placeholder}
value={value}
onChange={onChange}
autoComplete="off"
className={`
w-full rounded-sm border bg-stone-50 px-3.5 py-2.5
font-sans text-[0.95rem] text-stone-900 outline-none
placeholder:text-stone-300
transition-all duration-150
focus:border-stone-400 focus:ring-2 focus:ring-stone-300/30
${
error
? 'border-red-400 ring-2 ring-red-200/40'
: 'border-stone-200 hover:border-stone-300'
}
`}
/>
{error && (
<span className="text-[0.7rem] text-red-500 tracking-tight">
{error}
</span>
)}
</div>
);
}
export function RegisterFormUI() {
const {
registerData,
errors,
loading,
success,
handleChange,
handleOferta,
handleSubmit,
} = useRegisterForm();
const [phone, setPhone] = React.useState(registerData.phone || '');
const [isFocused, setIsFocused] = React.useState(false);
const handlePhoneChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setPhone(normalizeDigits(e.target.value));
},
[setPhone],
);
// ── Success state ──────────────────────────────────────
if (success) {
return (
<div className="flex min-h-screen items-center justify-center bg-stone-100 p-8">
<div className="w-full max-w-sm rounded border border-stone-200 bg-white px-10 py-16 text-center shadow-sm">
<div className="mx-auto mb-5 flex h-14 w-14 items-center justify-center rounded-full bg-emerald-50 text-2xl text-emerald-600">
</div>
<h2 className="mb-1 font-serif text-2xl text-stone-900">
You&lsquo;re registered
</h2>
<p className="text-sm text-stone-400">
We&lsquo;ll be in touch shortly.
</p>
</div>
</div>
);
}
// ── Form ───────────────────────────────────────────────
return (
<div className="w-full">
{/* Header */}
<p className="mb-1 text-[0.65rem] font-semibold uppercase tracking-[0.16em] text-stone-400">
Create account
</p>
<h1 className="mb-1 font-serif text-3xl leading-tight text-stone-900">
Register
</h1>
<p className="mb-8 text-sm text-stone-400">
Fill in your details to get started.
</p>
<form onSubmit={handleSubmit} noValidate className="flex flex-col gap-5">
{/* Name + Surname row */}
<div className="grid grid-cols-2 gap-3">
<Field
id="name"
name="name"
label="Name"
placeholder="Ali"
value={registerData.name}
onChange={handleChange}
error={errors.name}
/>
<Field
id="surname"
name="surname"
label="Surname"
placeholder="Karimov"
value={registerData.surname}
onChange={handleChange}
error={errors.surname}
/>
</div>
{/* Phone */}
<div>
<label
htmlFor="phone"
className="text-[0.7rem] font-medium tracking-widest uppercase text-stone-500"
>
Telefon raqam
</label>
<div
className={`relative transition-transform duration-200 ${isFocused ? 'scale-[1.01]' : ''}`}
>
<PhonePrefix isFocused={isFocused} />
<input
id="phone"
type="tel"
placeholder="90 123 45 67"
value={formatPhone(phone)}
onChange={handlePhoneChange}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
className={`
w-full rounded-sm border bg-stone-50 py-2.5 pl-30 pr-3.5
text-[0.95rem] font-medium text-stone-900 outline-none
placeholder:text-stone-300 transition-all duration-150
${
isFocused
? 'border-stone-400 ring-2 ring-stone-300/30'
: 'border-stone-200 hover:border-stone-300'
}
`}
/>
</div>
{/* Digit counter / complete hint */}
<div className="flex items-center justify-between px-0.5">
<span className="text-[0.7rem] text-stone-400">
{phone.length > 0 && `${phone.length} ta raqam kiritildi`}
</span>
{phone.length === 9 && (
<span className="text-[0.7rem] font-medium text-emerald-600">
To&lsquo;liq
</span>
)}
</div>
</div>
{/* Terms checkbox */}
<div className="flex flex-col gap-1.5">
<div className="flex items-start gap-2.5">
<input
type="checkbox"
id="oferta"
checked={!!registerData.oferta}
onChange={handleOferta}
className="mt-0.5 h-4 w-4 shrink-0 cursor-pointer accent-stone-700"
/>
<label
htmlFor="oferta"
className="cursor-pointer text-[0.78rem] leading-relaxed text-stone-500"
>
I agree to the
<a
href="/terms"
target="_blank"
rel="noopener noreferrer"
className="text-stone-800 underline underline-offset-2 hover:text-stone-600"
>
Terms of Service
</a>
and
<a
href="/privacy"
target="_blank"
rel="noopener noreferrer"
className="text-stone-800 underline underline-offset-2 hover:text-stone-600"
>
Privacy Policy
</a>
</label>
</div>
{errors.oferta && (
<p className="text-[0.7rem] text-red-500">{errors.oferta}</p>
)}
</div>
{/* Submit */}
<button
type="submit"
disabled={loading}
className="
mt-1 w-full rounded-sm bg-stone-900 py-3
text-[0.82rem] font-semibold uppercase tracking-widest text-stone-100
transition-all duration-150
hover:bg-stone-800 active:scale-[0.99]
disabled:cursor-not-allowed disabled:opacity-40
"
>
{loading ? (
<span className="flex items-center justify-center gap-2">
<span className="h-3.5 w-3.5 rounded-full border-2 border-stone-500 border-t-stone-100 animate-spin" />
Submitting
</span>
) : (
'Create account'
)}
</button>
</form>
</div>
);
}