import { createContext, useCallback, useContext, useEffect, useMemo, useState, } from 'react' import api from '../utils/api' import { activeClubMemberships } from '../utils/activeClub' const OrgInboxContext = createContext(null) export function canAccessOrgInbox(user) { if (!user?.id) return false if (user.role === 'admin' || user.role === 'superadmin') return true return activeClubMemberships(user.clubs).some((c) => (c.roles || []).includes('club_admin')) } /** Gründungsanträge freigeben — aktuell nur Superadmin (platform.club_creation.approve). */ export function canAccessClubCreationInbox(user) { return user?.role === 'superadmin' } function canSeeContentReports(user) { if (user?.role === 'admin' || user?.role === 'superadmin') return true return activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin')) } /** Nach Annahme/Ablehnung: Posteingang-Badges & Widget aktualisieren */ export function notifyOrgInboxChanged() { window.dispatchEvent(new Event('shinkan:inbox-changed')) } /** Eine konsistente Ladepfad-Logik für Join-Requests + Content-Reports (ein Codepfad für Mount + refresh). */ async function fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation) { const out = { items: [], clubCreationRequests: [], contentReports: [], contentReportsError: null, } if (canAccess) { try { const data = await api.getInboxJoinRequests() out.items = Array.isArray(data) ? data : [] } catch { out.items = [] } } if (canAccessClubCreation) { try { const data = await api.listAdminClubCreationRequests() out.clubCreationRequests = Array.isArray(data) ? data : [] } catch { out.clubCreationRequests = [] } } if (canAccessReports) { try { const data = await api.getInboxContentReports() out.contentReports = Array.isArray(data) ? data : [] } catch (err) { out.contentReports = [] out.contentReportsError = err?.message || String(err) } } return out } export function OrgInboxProvider({ user, children }) { const [items, setItems] = useState([]) const [clubCreationRequests, setClubCreationRequests] = useState([]) const [contentReports, setContentReports] = useState([]) const [contentReportsError, setContentReportsError] = useState(null) const canAccess = useMemo(() => canAccessOrgInbox(user), [user]) const canAccessReports = useMemo(() => canSeeContentReports(user), [user]) const canAccessClubCreation = useMemo(() => canAccessClubCreationInbox(user), [user]) const hasInboxAccess = canAccess || canAccessReports || canAccessClubCreation const refresh = useCallback(async () => { if (!hasInboxAccess) { setItems([]) setClubCreationRequests([]) setContentReports([]) setContentReportsError(null) return } const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation) setItems(snap.items) setClubCreationRequests(snap.clubCreationRequests) setContentReports(snap.contentReports) setContentReportsError(canAccessReports ? snap.contentReportsError : null) }, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation]) useEffect(() => { if (!hasInboxAccess) { setItems([]) setClubCreationRequests([]) setContentReports([]) setContentReportsError(null) return undefined } let cancelled = false let idleId = null let timeoutId = null const load = async () => { const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation) if (cancelled) return setItems(snap.items) setClubCreationRequests(snap.clubCreationRequests) setContentReports(snap.contentReports) setContentReportsError(canAccessReports ? snap.contentReportsError : null) } const schedule = () => { if (cancelled) return if (typeof window.requestIdleCallback === 'function') { idleId = window.requestIdleCallback( () => { idleId = null void load() }, { timeout: 1500 }, ) } else { timeoutId = window.setTimeout(() => { timeoutId = null void load() }, 0) } } schedule() return () => { cancelled = true if (idleId != null && typeof window.cancelIdleCallback === 'function') { window.cancelIdleCallback(idleId) } if (timeoutId != null) window.clearTimeout(timeoutId) } }, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation, user?.id]) useEffect(() => { const onChange = () => { refresh() } window.addEventListener('shinkan:inbox-changed', onChange) return () => window.removeEventListener('shinkan:inbox-changed', onChange) }, [refresh]) const clubCreationCount = clubCreationRequests.length const joinCount = items.length const value = useMemo( () => ({ inboxJoinRequests: items, inboxClubCreationRequests: clubCreationRequests, clubCreationRequestCount: clubCreationCount, inboxCount: joinCount + clubCreationCount, contentReports, contentReportCount: contentReports.filter((r) => r.status === 'submitted').length, contentReportsError, refreshOrgInbox: refresh, canAccessOrgInbox: canAccess, canAccessContentReports: canAccessReports, canAccessClubCreationInbox: canAccessClubCreation, canShowInboxNav: hasInboxAccess, isSuperadmin: user?.role === 'superadmin', isPlatformAdmin: user?.role === 'admin' || user?.role === 'superadmin', isClubAdmin: activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin')), }), [ items, clubCreationRequests, clubCreationCount, joinCount, contentReports, contentReportsError, refresh, canAccess, canAccessReports, canAccessClubCreation, hasInboxAccess, user?.role, user?.clubs, ] ) return {children} } export function useOrgInbox() { const ctx = useContext(OrgInboxContext) if (!ctx) { throw new Error('useOrgInbox must be used within OrgInboxProvider') } return ctx }