import { useEffect, useMemo, useState } from "react"; import { useLocation } from "react-router-dom"; import { useAdminStars } from "~/shared/services/admin"; import { Section, PaginationControls, Badge } from "../components"; import { useAdminContext } from "../context"; import { formatDate, formatStars, numberFormatter } from "../utils/format"; export const AdminStarsPage = () => { const { isAuthorized, handleRequestError } = useAdminContext(); const location = useLocation(); const initialSearch = useMemo(() => { const params = new URLSearchParams(location.search); return params.get("search") ?? ""; }, [location.search]); const [search, setSearch] = useState(initialSearch); const [paidFilter, setPaidFilter] = useState<"all" | "paid" | "unpaid">("all"); const [typeFilter, setTypeFilter] = useState("all"); const [page, setPage] = useState(0); const limit = 50; const normalizedSearch = search.trim(); const starsQuery = useAdminStars( { limit, offset: page * limit, search: normalizedSearch || undefined, type: typeFilter !== "all" ? typeFilter : undefined, paid: paidFilter === "all" ? undefined : paidFilter === "paid", }, { enabled: isAuthorized, keepPreviousData: true, refetchInterval: 60_000, onError: (error) => handleRequestError(error, "Не удалось загрузить платежи"), }, ); useEffect(() => { setSearch(initialSearch); }, [initialSearch]); useEffect(() => { setPage(0); }, [normalizedSearch, paidFilter, typeFilter]); if (starsQuery.isLoading && !starsQuery.data) { return (
Загрузка…
); } if (!starsQuery.data) { return (

Выберите вкладку «Платежи Stars», чтобы загрузить данные.

); } const { items, stats, total } = starsQuery.data; const typeOptions = Object.keys(stats.by_type || {}); const statCards = [ { label: "Всего платежей", value: numberFormatter.format(stats.total) }, { label: "Оплачено", value: `${numberFormatter.format(stats.paid)} · ${formatStars(stats.amount_paid)}` }, { label: "Неоплачено", value: `${numberFormatter.format(stats.unpaid)} · ${formatStars(stats.amount_unpaid)}` }, ]; return (
starsQuery.refetch()} disabled={starsQuery.isFetching} > {starsQuery.isFetching ? "Обновляем…" : "Обновить"} } >
{statCards.map((card) => (

{card.label}

{card.value}

))}
setSearch(event.target.value)} placeholder="ID, ссылка, контент" className="w-full rounded-lg border border-slate-700 bg-slate-900 px-3 py-2 text-sm text-slate-100 placeholder:text-slate-500 focus:border-sky-500 focus:outline-none focus:ring-1 focus:ring-sky-500 md:w-64" />
{items.length === 0 ? ( ) : ( items.map((invoice) => ( )) )}
Инвойс Сумма Пользователь Контент Создан
Платежей не найдено.
#{numberFormatter.format(invoice.id)} · {invoice.type ?? "—"}
{invoice.external_id}
{invoice.invoice_url ? ( Открыть счёт ) : null}
{formatStars(invoice.amount)}
{invoice.status}
{invoice.user ? (
ID {numberFormatter.format(invoice.user.id)} · TG {numberFormatter.format(invoice.user.telegram_id)}
) : (
)}
{invoice.content ? ( <>
{invoice.content.title}
{invoice.content.hash}
) : (
)}
{formatDate(invoice.created_at)}
); };