Files
nika-gallery/frontend/lib/club.ts
T
germanandClaude Opus 4.8 a355188301 feat(club): frontend закрытого клуба + вход через Яндекс
Страница /club (уровни, форма заявки, статус, админ-модерация),
/club/gallery (закрытая галерея), /login (кнопка «Войти через
Яндекс» + email-вход, разбор #token). Хелперы lib/auth.ts,
lib/club.ts, компонент AdminRequests. Ссылки «Клуб»/«Войти» в Nav.
Эстетика по существующим токенам (paper/ink/accent, Cormorant/Inter).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-05 21:49:15 +03:00

65 lines
1.6 KiB
TypeScript

// Типы и API-обёртки закрытого клуба (клиентская сторона).
'use client';
import { authFetch } from './auth';
export type ClubTierId =
| 'vip'
| 'collector'
| 'partner'
| 'photographer'
| 'organizer'
| 'press';
export interface ClubTier {
id: ClubTierId;
title: string;
desc: string;
}
export type RequestStatus = 'pending' | 'approved' | 'declined';
export interface MyAccessRequest {
id: string;
tier: ClubTierId;
status: RequestStatus;
note: string | null;
admin_note?: string | null;
created_at: string;
reviewed_at?: string | null;
}
export interface AdminAccessRequest extends MyAccessRequest {
user_id: string;
user_name: string;
user_email: string;
user_avatar: string | null;
user_current_tier: ClubTierId | null;
}
export const clubApi = {
tiers: () => authFetch<{ tiers: ClubTier[] }>('/club/tiers').then((r) => r.tiers),
myRequest: () =>
authFetch<{ club_tier: ClubTierId | null; request: MyAccessRequest | null }>(
'/club/my-request',
),
submit: (tier: ClubTierId, note: string) =>
authFetch<{ request: MyAccessRequest }>('/club/request', {
method: 'POST',
body: JSON.stringify({ tier, note }),
}),
listRequests: (status = 'pending') =>
authFetch<{ items: AdminAccessRequest[] }>(
`/club/requests?status=${encodeURIComponent(status)}`,
).then((r) => r.items),
approve: (id: string) =>
authFetch(`/club/requests/${id}/approve`, { method: 'POST', body: '{}' }),
decline: (id: string) =>
authFetch(`/club/requests/${id}/decline`, { method: 'POST', body: '{}' }),
};