2026-05-09 09:13:38 +02:00
|
|
|
import {
|
|
|
|
|
createContext,
|
|
|
|
|
useCallback,
|
|
|
|
|
useContext,
|
|
|
|
|
useEffect,
|
|
|
|
|
useMemo,
|
|
|
|
|
useState,
|
|
|
|
|
} from 'react'
|
|
|
|
|
import api from '../utils/api'
|
2026-05-09 10:42:56 +02:00
|
|
|
import { activeClubMemberships } from '../utils/activeClub'
|
2026-05-09 09:13:38 +02:00
|
|
|
|
|
|
|
|
const OrgInboxContext = createContext(null)
|
|
|
|
|
|
|
|
|
|
export function canAccessOrgInbox(user) {
|
|
|
|
|
if (!user?.id) return false
|
|
|
|
|
if (user.role === 'admin' || user.role === 'superadmin') return true
|
2026-05-09 10:42:56 +02:00
|
|
|
return activeClubMemberships(user.clubs).some((c) => (c.roles || []).includes('club_admin'))
|
2026-05-09 09:13:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Nach Annahme/Ablehnung: Posteingang-Badges & Widget aktualisieren */
|
|
|
|
|
export function notifyOrgInboxChanged() {
|
|
|
|
|
window.dispatchEvent(new Event('shinkan:inbox-changed'))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function OrgInboxProvider({ user, children }) {
|
|
|
|
|
const [items, setItems] = useState([])
|
|
|
|
|
const canAccess = useMemo(() => canAccessOrgInbox(user), [user])
|
|
|
|
|
|
|
|
|
|
const refresh = useCallback(async () => {
|
|
|
|
|
if (!canAccess) {
|
|
|
|
|
setItems([])
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
const data = await api.getInboxJoinRequests()
|
|
|
|
|
setItems(Array.isArray(data) ? data : [])
|
|
|
|
|
} catch {
|
|
|
|
|
setItems([])
|
|
|
|
|
}
|
|
|
|
|
}, [canAccess])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!canAccess) {
|
|
|
|
|
setItems([])
|
|
|
|
|
return undefined
|
|
|
|
|
}
|
|
|
|
|
let cancelled = false
|
|
|
|
|
;(async () => {
|
|
|
|
|
try {
|
|
|
|
|
const data = await api.getInboxJoinRequests()
|
|
|
|
|
if (!cancelled) setItems(Array.isArray(data) ? data : [])
|
|
|
|
|
} catch {
|
|
|
|
|
if (!cancelled) setItems([])
|
|
|
|
|
}
|
|
|
|
|
})()
|
|
|
|
|
return () => {
|
|
|
|
|
cancelled = true
|
|
|
|
|
}
|
|
|
|
|
}, [canAccess, user?.id])
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const onChange = () => {
|
|
|
|
|
refresh()
|
|
|
|
|
}
|
|
|
|
|
window.addEventListener('shinkan:inbox-changed', onChange)
|
|
|
|
|
return () => window.removeEventListener('shinkan:inbox-changed', onChange)
|
|
|
|
|
}, [refresh])
|
|
|
|
|
|
|
|
|
|
const value = useMemo(
|
|
|
|
|
() => ({
|
|
|
|
|
inboxJoinRequests: items,
|
|
|
|
|
inboxCount: items.length,
|
|
|
|
|
refreshOrgInbox: refresh,
|
|
|
|
|
canAccessOrgInbox: canAccess,
|
|
|
|
|
}),
|
|
|
|
|
[items, refresh, canAccess]
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return <OrgInboxContext.Provider value={value}>{children}</OrgInboxContext.Provider>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function useOrgInbox() {
|
|
|
|
|
const ctx = useContext(OrgInboxContext)
|
|
|
|
|
if (!ctx) {
|
|
|
|
|
throw new Error('useOrgInbox must be used within OrgInboxProvider')
|
|
|
|
|
}
|
|
|
|
|
return ctx
|
|
|
|
|
}
|