Files
bedolaga-cabinet/src/store/blocking.ts
Fringg a767fe96d3 feat: add multi-channel subscription blocking UI and admin management
- 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
2026-02-24 02:51:03 +03:00

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,
}),
}));