112 lines
4.7 KiB
TypeScript
112 lines
4.7 KiB
TypeScript
import { useState } from 'react';
|
||
import { useNavigate } from 'react-router';
|
||
import { ArrowRight } from 'lucide-react';
|
||
import { setAuthStatus } from '../data/session';
|
||
|
||
export function AuthPhone() {
|
||
const navigate = useNavigate();
|
||
const [phone, setPhone] = useState('');
|
||
|
||
function formatPhone(raw: string) {
|
||
const digits = raw.replace(/\D/g, '').slice(0, 11);
|
||
if (digits.length === 0) return '';
|
||
let result = '+7';
|
||
if (digits.length > 1) result += ' (' + digits.slice(1, 4);
|
||
if (digits.length >= 4) result += ') ' + digits.slice(4, 7);
|
||
if (digits.length >= 7) result += ' ' + digits.slice(7, 9);
|
||
if (digits.length >= 9) result += ' ' + digits.slice(9, 11);
|
||
return result;
|
||
}
|
||
|
||
function handleInput(e: React.ChangeEvent<HTMLInputElement>) {
|
||
const raw = e.target.value.replace(/\D/g, '');
|
||
// Если начинается с 8, заменяем на 7
|
||
const normalized = raw.startsWith('8') ? '7' + raw.slice(1) : raw.startsWith('7') ? raw : '7' + raw;
|
||
setPhone(formatPhone(normalized));
|
||
}
|
||
|
||
const isValid = phone.replace(/\D/g, '').length === 11;
|
||
|
||
function handleSubmit(e: React.FormEvent) {
|
||
e.preventDefault();
|
||
if (isValid) navigate('/auth/otp', { state: { phone } });
|
||
}
|
||
|
||
return (
|
||
<div className="flex flex-col h-full bg-background">
|
||
<div className="flex-1 flex flex-col justify-between px-6 pt-16 pb-8">
|
||
{/* Верхняя часть */}
|
||
<div className="flex-1 flex flex-col">
|
||
{/* Логотип */}
|
||
<div className="mb-12">
|
||
<div className="flex items-end gap-1 mb-3">
|
||
<span className="text-4xl font-bold tracking-tight text-foreground">HAN</span>
|
||
<span className="w-2 h-2 rounded-full bg-primary mb-2" />
|
||
</div>
|
||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||
Персональный консультант мигранта
|
||
</p>
|
||
</div>
|
||
|
||
{/* Заголовок */}
|
||
<div className="mb-8">
|
||
<h1 className="text-2xl font-semibold text-foreground mb-2">
|
||
Добро пожаловать
|
||
</h1>
|
||
<p className="text-muted-foreground text-sm leading-relaxed">
|
||
Введите номер телефона — отправим код подтверждения
|
||
</p>
|
||
</div>
|
||
|
||
{/* Форма */}
|
||
<form onSubmit={handleSubmit} className="space-y-4">
|
||
<div className="space-y-1.5">
|
||
<label className="text-sm font-medium text-foreground">Номер телефона</label>
|
||
<div className="relative">
|
||
<input
|
||
type="tel"
|
||
inputMode="numeric"
|
||
value={phone}
|
||
onChange={handleInput}
|
||
placeholder="+7 (___) ___ __ __"
|
||
className="w-full h-14 px-4 rounded-xl border border-border bg-input-background text-foreground text-base placeholder:text-muted-foreground/60 focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary/50 transition-all"
|
||
autoComplete="tel"
|
||
/>
|
||
</div>
|
||
<p className="text-xs text-muted-foreground px-1">
|
||
Россия · Код страны +7
|
||
</p>
|
||
</div>
|
||
|
||
<button
|
||
type="submit"
|
||
disabled={!isValid}
|
||
className="w-full h-14 bg-primary text-primary-foreground rounded-xl font-medium flex items-center justify-center gap-2.5 transition-all disabled:opacity-40 disabled:cursor-not-allowed hover:bg-primary/90 active:scale-[0.98]"
|
||
>
|
||
Получить код
|
||
<ArrowRight className="w-4 h-4" />
|
||
</button>
|
||
</form>
|
||
</div>
|
||
|
||
{/* Низ страницы */}
|
||
<div className="space-y-4 text-center">
|
||
<button
|
||
type="button"
|
||
onClick={() => { setAuthStatus('guest'); navigate('/'); }}
|
||
className="w-full text-sm text-muted-foreground hover:text-foreground transition-colors py-1"
|
||
>
|
||
Войти как гость
|
||
</button>
|
||
<p className="text-xs text-muted-foreground leading-relaxed">
|
||
Нажимая «Получить код», вы соглашаетесь с{' '}
|
||
<span className="text-foreground/70 underline underline-offset-2">условиями использования</span>
|
||
{' '}и{' '}
|
||
<span className="text-foreground/70 underline underline-offset-2">политикой конфиденциальности</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|