/** * SanctionsContext — глобальный контекст активных санкций юзера. * * Дёргает /api-storys/api/v1/storys/me/sanctions ОДИН раз при монтировании * и при изменении localStorage Authorization (логин/логаут). Возвращает: * * sanctions — массив { type, banned_until, reason, ... } * isMuted — true если есть активный user_timed_ban или chat_ban * или comment_ban (то что блокирует ввод текста) * isCantPublish — true если есть user_timed_ban или publish_ban * muteInfo — { type, banned_until, reason } первой найденной мут-санкции * reload() — перезагрузить (например после успешной подачи жалобы) * * Подключи провайдер один раз в корне приложения (Menu.jsx). Дальше * через useSanctions() в любом компоненте, без отдельных запросов. */ import React, { createContext, useContext, useEffect, useState, useCallback } from 'react'; import SanctionsService from '../api/SanctionsService'; const SanctionsContext = createContext({ sanctions: [], isMuted: false, isCantPublish: false, muteInfo: null, loading: true, reload: () => {}, }); export function SanctionsProvider({ children }) { const [sanctions, setSanctions] = useState([]); const [loading, setLoading] = useState(true); const reload = useCallback(async () => { // Без JWT не дёргаем (вернёт пустоту, но всё равно лишний запрос). if (!localStorage.getItem('Authorization')) { setSanctions([]); setLoading(false); return; } try { const r = await SanctionsService.getMySanctions(); setSanctions(Array.isArray(r?.sanctions) ? r.sanctions : []); } catch (_) { setSanctions([]); } finally { setLoading(false); } }, []); useEffect(() => { reload(); }, [reload]); // Перезагрузка при изменении токена (login/logout) useEffect(() => { const onStorage = (e) => { if (e.key === 'Authorization') reload(); }; window.addEventListener('storage', onStorage); return () => window.removeEventListener('storage', onStorage); }, [reload]); // Мут на текст: user_timed_ban или chat_ban или comment_ban const muteInfo = sanctions.find((s) => ['user_timed_ban', 'chat_ban', 'comment_ban'].includes(s.type) ) || null; const isMuted = !!muteInfo; // Запрет публикации: user_timed_ban или publish_ban const cantPublishInfo = sanctions.find((s) => ['user_timed_ban', 'publish_ban'].includes(s.type) ) || null; const isCantPublish = !!cantPublishInfo; return ( {children} ); } export function useSanctions() { return useContext(SanctionsContext); }