// Guest PF Order Form — same as OrderFormPage but no balance, + phone field, direct YooKassa payment const { useState: useGOFState, useEffect: useGOFEffect } = React; // parseAvitoUrls is defined locally (not exported from OrderForm.jsx) function parseGuestAvitoUrls(text) { if (!text) return []; const normalized = text.replace(/(?<=\S)[\r\n]+(?=\S)/g, ''); const raw = normalized.match(/https?:\/\/(?:www\.)?avito\.ru\/\S+/g) || []; const seen = new Set(); return raw .map(u => u.replace(/["')\].,;]+$/, '').split('?')[0]) .filter(u => { if (seen.has(u)) return false; seen.add(u); return true; }); } function GuestOrderForm({ onNavigate }) { const [inputText, setInputText] = useGOFState(''); const [links, setLinks] = useGOFState([]); const [views, setViews] = useGOFState(30); const [days, setDays] = useGOFState(7); const [contacts, setContacts] = useGOFState(false); const [startDate, setStartDate] = useGOFState(() => { const d = new Date(); d.setDate(d.getDate() + 1); return d.toISOString().split('T')[0]; }); const [phone, setPhone] = useGOFState(''); const [pricePerUnit, setPricePerUnit] = useGOFState(6); const [paymentAvailable, setPaymentAvailable] = useGOFState(true); const [loading, setLoading] = useGOFState(false); const [error, setError] = useGOFState(''); // Legal consent is implicit-via-button-click on this form (same pattern as // Cabinet refill). The fineprint under the CTA explains it. Server still // validates agreed_* fields, so we always send true on submit. useGOFEffect(() => { api.get('/api/orders/pf/price').then(d => { if (!d.__unauthorized) setPricePerUnit(d.price_per_unit || 6); }).catch(() => {}); api.get('/api/guest-orders/payment-available').then(d => { if (!d.__unauthorized) setPaymentAvailable(d.available !== false); }).catch(() => {}); }, []); const urlCount = links.length; const totalPrice = urlCount > 0 ? views * days * urlCount * pricePerUnit : 0; const handleInputChange = e => { const val = e.target.value; const parsed = parseGuestAvitoUrls(val); const toAdd = parsed.filter(u => !links.includes(u)); if (toAdd.length) setLinks(prev => [...prev, ...toAdd]); setInputText(val); }; const removeLink = url => setLinks(prev => prev.filter(u => u !== url)); const handleSubmit = async () => { if (urlCount === 0) return setError('Вставьте хотя бы одну ссылку на объявление'); if (!phone.trim()) return setError('Укажите номер телефона'); if (!paymentAvailable) return setError('Онлайн-оплата временно недоступна'); setError(''); setLoading(true); try { const data = await api.post('/api/guest-orders/pf', { links, days, fix_count: views, contacts, phone: phone.trim(), agreed_privacy: true, agreed_offer: true, }); window.location.href = data.payment_url; } catch (e) { setError(e.message || 'Ошибка создания заказа. Попробуйте позже или напишите в поддержку.'); } finally { setLoading(false); } }; const noUrlsWarning = inputText.length > 5 && parseGuestAvitoUrls(inputText).length === 0 && urlCount === 0; return (

Авито ПФ

Поведенческие факторы · {pricePerUnit} ₽ за просмотр Без регистрации
{!paymentAvailable && (
Онлайн-оплата временно недоступна. Для заказа напишите в поддержку.
)} {error &&
{error}
}
{/* LEFT */}
Рекомендация
Начните с 15–30 просм./день без контактов в течение недели. После оживления органики постепенно добавляйте 5–8 контактов.
{urlCount > 0 && ( ✓ {urlCount} {urlCount === 1 ? 'объявление' : urlCount < 5 ? 'объявления' : 'объявлений'} )}