mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-30 02:23:47 +00:00
- Channel subscription blocking screen with per-channel status display - Safe URL handling with protocol validation (no open redirect) - Race-condition-safe subscription check with useRef guard - Admin channel management page with create, toggle, delete - Error handlers on all admin mutations with haptic feedback - Proper type guard for channel subscription error detection - Accessibility: aria-labels on icon-only buttons - Localization: en, ru, zh, fa translations
82 lines
1.9 KiB
TypeScript
82 lines
1.9 KiB
TypeScript
import { create } from 'zustand';
|
|
|
|
export type BlockingType = 'maintenance' | 'channel_subscription' | 'blacklisted' | null;
|
|
|
|
interface MaintenanceInfo {
|
|
message: string;
|
|
reason?: string;
|
|
}
|
|
|
|
/**
|
|
* User-facing channel subscription status returned by the blocking 403 response.
|
|
* Intentionally separate from `RequiredChannel` (api/adminChannels.ts) which
|
|
* represents the admin CRUD entity with `is_active` / `sort_order` fields.
|
|
*/
|
|
interface ChannelInfo {
|
|
channel_id: string;
|
|
channel_link?: string;
|
|
title?: string;
|
|
is_subscribed: boolean;
|
|
}
|
|
|
|
interface ChannelSubscriptionInfo {
|
|
message: string;
|
|
channel_link?: string;
|
|
channels?: ChannelInfo[];
|
|
}
|
|
|
|
interface BlacklistedInfo {
|
|
message: string;
|
|
}
|
|
|
|
interface BlockingState {
|
|
blockingType: BlockingType;
|
|
maintenanceInfo: MaintenanceInfo | null;
|
|
channelInfo: ChannelSubscriptionInfo | null;
|
|
blacklistedInfo: BlacklistedInfo | null;
|
|
|
|
setMaintenance: (info: MaintenanceInfo) => void;
|
|
setChannelSubscription: (info: ChannelSubscriptionInfo) => void;
|
|
setBlacklisted: (info: BlacklistedInfo) => void;
|
|
clearBlocking: () => void;
|
|
}
|
|
|
|
export const useBlockingStore = create<BlockingState>((set) => ({
|
|
blockingType: null,
|
|
maintenanceInfo: null,
|
|
channelInfo: null,
|
|
blacklistedInfo: null,
|
|
|
|
setMaintenance: (info) =>
|
|
set({
|
|
blockingType: 'maintenance',
|
|
maintenanceInfo: info,
|
|
channelInfo: null,
|
|
blacklistedInfo: null,
|
|
}),
|
|
|
|
setChannelSubscription: (info) =>
|
|
set({
|
|
blockingType: 'channel_subscription',
|
|
channelInfo: info,
|
|
maintenanceInfo: null,
|
|
blacklistedInfo: null,
|
|
}),
|
|
|
|
setBlacklisted: (info) =>
|
|
set({
|
|
blockingType: 'blacklisted',
|
|
blacklistedInfo: info,
|
|
maintenanceInfo: null,
|
|
channelInfo: null,
|
|
}),
|
|
|
|
clearBlocking: () =>
|
|
set({
|
|
blockingType: null,
|
|
maintenanceInfo: null,
|
|
channelInfo: null,
|
|
blacklistedInfo: null,
|
|
}),
|
|
}));
|