import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { formatAmd } from '@barev/i18n'; import { Badge, Button, Chip } from '@barev/ui'; import { confirmDialog, errorText, useI18n, useToast, useTRPC } from '@barev/web'; import { useState } from 'react'; const STATUSES = ['NEW', 'LINKED', 'ORDERED', 'CANCELLED'] as const; type Status = (typeof STATUSES)[number]; const STATUS_TONE: Record = { NEW: 'var(--bc-perks)', LINKED: 'var(--bc-pink)', ORDERED: 'var(--bc-home)', CANCELLED: 'var(--bc-line)', }; /** Заявки с сайта (barevclub.com/clean): появляются сразу после отправки формы, список обновляется сам */ export function WebRequests() { const { t, dt, locale } = useI18n(); const trpc = useTRPC(); const qc = useQueryClient(); const toast = useToast(); const [status, setStatus] = useState(); const list = useQuery({ ...trpc.admin.webRequests.list.queryOptions({ status }), refetchInterval: 15_000 }); const update = useMutation( trpc.admin.webRequests.update.mutationOptions({ onSuccess: () => { toast(t('admin.saved')); void qc.invalidateQueries(); }, onError: (e) => toast(errorText(t, e), 'error'), }), ); return ( <>

{t('admin.nav.webRequests')}

setStatus(undefined)}> {t('admin.webRequests.all')} {STATUSES.map((s) => ( setStatus(s)}> {t(`admin.webRequests.status_${s}`)} ))}
{list.data?.length === 0 ? (

{t('admin.webRequests.empty')}

) : ( {list.data?.map((r) => { const p = r.params as { cleaningType?: string; rooms?: number; bathrooms?: number; extras?: Record }; const extras = Object.entries(p.extras ?? {}); return ( ); })}
{t('admin.webRequests.number')} {t('admin.webRequests.when')} {t('admin.webRequests.what')} {t('admin.webRequests.address')} {t('admin.webRequests.contact')} {t('admin.webRequests.price')} {t('admin.webRequests.status')} {t('admin.webRequests.note')}
{r.number}
{t('admin.webRequests.created', { date: dt(r.createdAt, { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' }) })}
{dt(r.preferredAt, { weekday: 'short', day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })} {t(`params.cleaning.cleaningType.${p.cleaningType ?? 'regular'}`)}
{t('params.cleaning.rooms.count', { count: p.rooms ?? 1 })}, {t('params.cleaning.bathrooms.count', { count: p.bathrooms ?? 1 })}
{extras.length > 0 && (
{extras.map(([code, qty]) => `${t(`extras.${code}.name`)}${qty > 1 ? ` × ${qty}` : ''}`).join(', ')}
)}
{t(`districts.${r.district.code}`)}
{r.addressText}
{r.note &&
{r.note}
}
{r.name && {r.name}} {r.client && (
{r.client.user.username ? `@${r.client.user.username}` : `${r.client.user.firstName ?? ''} ${r.client.user.lastName ?? ''}`}
)}
{r.locale.toUpperCase()}
{formatAmd(locale, r.totalPrice)} {t(`admin.webRequests.status_${r.status}`)} {r.order && (
{t('admin.webRequests.order', { number: r.order.number })}
)}
{r.status === 'CANCELLED' ? ( ) : ( r.status !== 'ORDERED' && ( ) )}
update.mutate({ id: r.id, adminNote })} />
)} ); } function NoteEditor({ initial, onSave }: { initial: string; onSave: (v: string) => void }) { const { t } = useI18n(); const [value, setValue] = useState(initial); return (