'use client'; import { useCallback, useEffect, useState } from 'react'; import { consumeHashToken, fetchMe, isAdmin, yandexLoginUrl, type AuthUser, } from '@/lib/auth'; import { clubApi, type ClubTier, type ClubTierId, type MyAccessRequest, type RequestStatus, } from '@/lib/club'; import AdminRequests from '@/components/AdminRequests'; // Фолбэк-описание уровней (если API недоступен) — синхронно с backend CLUB_TIERS. const FALLBACK_TIERS: ClubTier[] = [ { id: 'vip', title: 'VIP', desc: 'Полный доступ ко всем закрытым работам, приоритет на аукционах, личные превью.' }, { id: 'collector', title: 'Коллекционеры', desc: 'Ранний доступ к новым работам и коллекционным сериям, консультации по подбору.' }, { id: 'partner', title: 'Партнёры', desc: 'Совместные проекты и коллаборации, специальные условия сотрудничества.' }, { id: 'photographer', title: 'Фотографы', desc: 'Backstage-материалы и совместные съёмки body art.' }, { id: 'organizer', title: 'Организаторы', desc: 'Работы и материалы для выставок, перформансов и мероприятий.' }, { id: 'press', title: 'Пресса', desc: 'Пресс-материалы, изображения в высоком разрешении, интервью.' }, ]; const STATUS_LABEL: Record = { pending: 'на рассмотрении', approved: 'одобрена', declined: 'отклонена', }; function tierTitle(tiers: ClubTier[], id: ClubTierId): string { return tiers.find((t) => t.id === id)?.title ?? id; } export default function ClubPage() { const [ready, setReady] = useState(false); const [user, setUser] = useState(null); const [tiers, setTiers] = useState(FALLBACK_TIERS); const [clubTier, setClubTier] = useState(null); const [myRequest, setMyRequest] = useState(null); // Форма заявки. const [selected, setSelected] = useState(''); const [note, setNote] = useState(''); const [busy, setBusy] = useState(false); const [msg, setMsg] = useState<{ ok: boolean; text: string } | null>(null); const refreshMine = useCallback(async () => { try { const r = await clubApi.myRequest(); setClubTier(r.club_tier); setMyRequest(r.request); } catch { /* не критично */ } }, []); useEffect(() => { consumeHashToken(); clubApi.tiers().then(setTiers).catch(() => setTiers(FALLBACK_TIERS)); (async () => { const me = await fetchMe(); setUser(me); if (me) await refreshMine(); setReady(true); })(); }, [refreshMine]); async function onSubmit(e: React.FormEvent) { e.preventDefault(); if (!selected) return; setBusy(true); setMsg(null); try { await clubApi.submit(selected, note.trim()); setMsg({ ok: true, text: 'Заявка отправлена. Мы сообщим о решении.' }); setNote(''); setSelected(''); await refreshMine(); } catch (err) { const m = (err as { message?: string })?.message || 'Не удалось отправить заявку.'; setMsg({ ok: false, text: m }); } finally { setBusy(false); } } const canRequest = user && !myRequest && !clubTier; const pendingSame = myRequest?.status === 'pending'; return (
{/* Заголовок */}

Только по приглашению

Закрытый клуб

Пространство для тех, кто ближе к искусству Ники: закрытые серии body art, приватные превью, приоритет на аукционах и прямой диалог. Доступ — по заявке и решению автора.

{/* Уровни доступа */}
{tiers.map((t) => { const active = clubTier === t.id; return (

{t.title}

{active && ( ваш уровень )}

{t.desc}

); })}
{/* Блок действия: вход / заявка / статус */}
{!ready ? (
) : !user ? (

Войдите, чтобы подать заявку

Быстрый вход через Яндекс ID — без пароля и регистрации.

Я Войти через Яндекс
) : clubTier ? (

Добро пожаловать

Вы — {tierTitle(tiers, clubTier)}

Закрытая галерея открыта для вас.

Открыть закрытую галерею
) : myRequest && pendingSame ? (

Заявка на рассмотрении

Уровень «{tierTitle(tiers, myRequest.tier)}» — статус:{' '} {STATUS_LABEL[myRequest.status]}. Мы сообщим о решении.

) : (

Подать заявку

{myRequest?.status === 'declined' && (

Предыдущая заявка («{tierTitle(tiers, myRequest.tier)}») была отклонена. Вы можете подать новую.

)}