Refactor Org Inbox Context and Enhance Club Creation Management
Some checks failed
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Failing after 1m21s
Some checks failed
Deploy Development / deploy (push) Successful in 47s
Test Suite / pytest-backend (push) Successful in 42s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 13s
Test Suite / k6 /health Baseline (push) Successful in 33s
Test Suite / playwright-tests (push) Failing after 1m21s
- Updated the OrgInboxContext to include handling for club creation requests, allowing for better management of inbox items. - Refactored components to utilize the new `canShowInboxNav` and `canAccessClubCreationInbox` flags for improved access control. - Enhanced the InboxPage to display club creation requests with appropriate actions for approval and rejection. - Updated the DashboardOrgInboxWidget to show both club creation and join requests, improving the user interface for managing inbox items.
This commit is contained in:
parent
8ee8f52e0f
commit
37785135b1
|
|
@ -88,9 +88,9 @@ function AppRouteFallback() {
|
||||||
|
|
||||||
// Bottom Navigation (Mobile)
|
// Bottom Navigation (Mobile)
|
||||||
function Nav({ showAdminNav, onboardingOnly }) {
|
function Nav({ showAdminNav, onboardingOnly }) {
|
||||||
const { canAccessOrgInbox, inboxCount } = useOrgInbox()
|
const { canShowInboxNav, inboxCount } = useOrgInbox()
|
||||||
const items = getMainNavItems(showAdminNav, {
|
const items = getMainNavItems(showAdminNav, {
|
||||||
showInbox: canAccessOrgInbox,
|
showInbox: canShowInboxNav,
|
||||||
onboardingOnly,
|
onboardingOnly,
|
||||||
})
|
})
|
||||||
const loc = useLocation()
|
const loc = useLocation()
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,30 @@ import { useOrgInbox } from '../context/OrgInboxContext'
|
||||||
* Desktop-Dashboard: Hinweis auf offene Beitrittsanträge (nur ab 1024px sichtbar via CSS).
|
* Desktop-Dashboard: Hinweis auf offene Beitrittsanträge (nur ab 1024px sichtbar via CSS).
|
||||||
*/
|
*/
|
||||||
export default function DashboardOrgInboxWidget() {
|
export default function DashboardOrgInboxWidget() {
|
||||||
const { canAccessOrgInbox, inboxJoinRequests, inboxCount } = useOrgInbox()
|
const {
|
||||||
|
canShowInboxNav,
|
||||||
|
inboxJoinRequests,
|
||||||
|
inboxClubCreationRequests,
|
||||||
|
clubCreationRequestCount,
|
||||||
|
inboxCount,
|
||||||
|
} = useOrgInbox()
|
||||||
|
|
||||||
if (!canAccessOrgInbox) return null
|
if (!canShowInboxNav) return null
|
||||||
|
|
||||||
const preview = (inboxJoinRequests || []).slice(0, 5)
|
const preview = [
|
||||||
|
...(inboxClubCreationRequests || []).map((req) => ({
|
||||||
|
key: `creation-${req.id}`,
|
||||||
|
club: req.proposed_name || 'Neuer Verein',
|
||||||
|
applicant: req.applicant_name || req.applicant_email || 'Antragsteller/in',
|
||||||
|
kind: 'creation',
|
||||||
|
})),
|
||||||
|
...(inboxJoinRequests || []).map((req) => ({
|
||||||
|
key: `${req.club_id}-${req.id}`,
|
||||||
|
club: req.club_name || 'Verein',
|
||||||
|
applicant: req.applicant_name || req.applicant_email || 'Bewerber/in',
|
||||||
|
kind: 'join',
|
||||||
|
})),
|
||||||
|
].slice(0, 5)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
|
|
@ -31,17 +50,27 @@ export default function DashboardOrgInboxWidget() {
|
||||||
</div>
|
</div>
|
||||||
<p className="muted dashboard-org-inbox-widget__lead">
|
<p className="muted dashboard-org-inbox-widget__lead">
|
||||||
{inboxCount === 0
|
{inboxCount === 0
|
||||||
? 'Keine offenen Beitrittsanträge.'
|
? 'Keine offenen Anträge.'
|
||||||
: `${inboxCount} offene Beitrittsantrag${inboxCount === 1 ? '' : 'e'}.`}
|
: [
|
||||||
|
clubCreationRequestCount > 0
|
||||||
|
? `${clubCreationRequestCount} Gründungsantrag${clubCreationRequestCount === 1 ? '' : 'e'}`
|
||||||
|
: null,
|
||||||
|
(inboxJoinRequests || []).length > 0
|
||||||
|
? `${(inboxJoinRequests || []).length} Beitrittsantrag${(inboxJoinRequests || []).length === 1 ? '' : 'e'}`
|
||||||
|
: null,
|
||||||
|
]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(' · ')}
|
||||||
</p>
|
</p>
|
||||||
{preview.length > 0 ? (
|
{preview.length > 0 ? (
|
||||||
<ul className="dashboard-org-inbox-widget__list">
|
<ul className="dashboard-org-inbox-widget__list">
|
||||||
{preview.map((req) => (
|
{preview.map((req) => (
|
||||||
<li key={`${req.club_id}-${req.id}`} className="dashboard-org-inbox-widget__item">
|
<li key={req.key} className="dashboard-org-inbox-widget__item">
|
||||||
<span className="dashboard-org-inbox-widget__club">{req.club_name || 'Verein'}</span>
|
<span className="dashboard-org-inbox-widget__club">
|
||||||
<span className="dashboard-org-inbox-widget__applicant">
|
{req.kind === 'creation' ? 'Gründung: ' : ''}
|
||||||
{req.applicant_name || req.applicant_email || 'Bewerber/in'}
|
{req.club}
|
||||||
</span>
|
</span>
|
||||||
|
<span className="dashboard-org-inbox-widget__applicant">{req.applicant}</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,9 @@ export default function DesktopSidebar({
|
||||||
onLogout
|
onLogout
|
||||||
}) {
|
}) {
|
||||||
const loc = useLocation()
|
const loc = useLocation()
|
||||||
const { canAccessOrgInbox, inboxCount } = useOrgInbox()
|
const { canShowInboxNav, inboxCount } = useOrgInbox()
|
||||||
const items = getMainNavItems(showAdminNav, {
|
const items = getMainNavItems(showAdminNav, {
|
||||||
showInbox: canAccessOrgInbox,
|
showInbox: canShowInboxNav,
|
||||||
onboardingOnly,
|
onboardingOnly,
|
||||||
})
|
})
|
||||||
const tier = user?.tier || ''
|
const tier = user?.tier || ''
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@ export function canAccessOrgInbox(user) {
|
||||||
return activeClubMemberships(user.clubs).some((c) => (c.roles || []).includes('club_admin'))
|
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) {
|
function canSeeContentReports(user) {
|
||||||
if (user?.role === 'admin' || user?.role === 'superadmin') return true
|
if (user?.role === 'admin' || user?.role === 'superadmin') return true
|
||||||
return activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin'))
|
return activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin'))
|
||||||
|
|
@ -28,8 +33,13 @@ export function notifyOrgInboxChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Eine konsistente Ladepfad-Logik für Join-Requests + Content-Reports (ein Codepfad für Mount + refresh). */
|
/** Eine konsistente Ladepfad-Logik für Join-Requests + Content-Reports (ein Codepfad für Mount + refresh). */
|
||||||
async function fetchOrgInboxSnapshot(canAccess, canAccessReports) {
|
async function fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation) {
|
||||||
const out = { items: [], contentReports: [], contentReportsError: null }
|
const out = {
|
||||||
|
items: [],
|
||||||
|
clubCreationRequests: [],
|
||||||
|
contentReports: [],
|
||||||
|
contentReportsError: null,
|
||||||
|
}
|
||||||
if (canAccess) {
|
if (canAccess) {
|
||||||
try {
|
try {
|
||||||
const data = await api.getInboxJoinRequests()
|
const data = await api.getInboxJoinRequests()
|
||||||
|
|
@ -38,6 +48,14 @@ async function fetchOrgInboxSnapshot(canAccess, canAccessReports) {
|
||||||
out.items = []
|
out.items = []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (canAccessClubCreation) {
|
||||||
|
try {
|
||||||
|
const data = await api.listAdminClubCreationRequests()
|
||||||
|
out.clubCreationRequests = Array.isArray(data) ? data : []
|
||||||
|
} catch {
|
||||||
|
out.clubCreationRequests = []
|
||||||
|
}
|
||||||
|
}
|
||||||
if (canAccessReports) {
|
if (canAccessReports) {
|
||||||
try {
|
try {
|
||||||
const data = await api.getInboxContentReports()
|
const data = await api.getInboxContentReports()
|
||||||
|
|
@ -52,27 +70,33 @@ async function fetchOrgInboxSnapshot(canAccess, canAccessReports) {
|
||||||
|
|
||||||
export function OrgInboxProvider({ user, children }) {
|
export function OrgInboxProvider({ user, children }) {
|
||||||
const [items, setItems] = useState([])
|
const [items, setItems] = useState([])
|
||||||
|
const [clubCreationRequests, setClubCreationRequests] = useState([])
|
||||||
const [contentReports, setContentReports] = useState([])
|
const [contentReports, setContentReports] = useState([])
|
||||||
const [contentReportsError, setContentReportsError] = useState(null)
|
const [contentReportsError, setContentReportsError] = useState(null)
|
||||||
const canAccess = useMemo(() => canAccessOrgInbox(user), [user])
|
const canAccess = useMemo(() => canAccessOrgInbox(user), [user])
|
||||||
const canAccessReports = useMemo(() => canSeeContentReports(user), [user])
|
const canAccessReports = useMemo(() => canSeeContentReports(user), [user])
|
||||||
|
const canAccessClubCreation = useMemo(() => canAccessClubCreationInbox(user), [user])
|
||||||
|
const hasInboxAccess = canAccess || canAccessReports || canAccessClubCreation
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
if (!canAccess && !canAccessReports) {
|
if (!hasInboxAccess) {
|
||||||
setItems([])
|
setItems([])
|
||||||
|
setClubCreationRequests([])
|
||||||
setContentReports([])
|
setContentReports([])
|
||||||
setContentReportsError(null)
|
setContentReportsError(null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports)
|
const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation)
|
||||||
setItems(snap.items)
|
setItems(snap.items)
|
||||||
|
setClubCreationRequests(snap.clubCreationRequests)
|
||||||
setContentReports(snap.contentReports)
|
setContentReports(snap.contentReports)
|
||||||
setContentReportsError(canAccessReports ? snap.contentReportsError : null)
|
setContentReportsError(canAccessReports ? snap.contentReportsError : null)
|
||||||
}, [canAccess, canAccessReports])
|
}, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canAccess && !canAccessReports) {
|
if (!hasInboxAccess) {
|
||||||
setItems([])
|
setItems([])
|
||||||
|
setClubCreationRequests([])
|
||||||
setContentReports([])
|
setContentReports([])
|
||||||
setContentReportsError(null)
|
setContentReportsError(null)
|
||||||
return undefined
|
return undefined
|
||||||
|
|
@ -82,9 +106,10 @@ export function OrgInboxProvider({ user, children }) {
|
||||||
let timeoutId = null
|
let timeoutId = null
|
||||||
|
|
||||||
const load = async () => {
|
const load = async () => {
|
||||||
const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports)
|
const snap = await fetchOrgInboxSnapshot(canAccess, canAccessReports, canAccessClubCreation)
|
||||||
if (cancelled) return
|
if (cancelled) return
|
||||||
setItems(snap.items)
|
setItems(snap.items)
|
||||||
|
setClubCreationRequests(snap.clubCreationRequests)
|
||||||
setContentReports(snap.contentReports)
|
setContentReports(snap.contentReports)
|
||||||
setContentReportsError(canAccessReports ? snap.contentReportsError : null)
|
setContentReportsError(canAccessReports ? snap.contentReportsError : null)
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +141,7 @@ export function OrgInboxProvider({ user, children }) {
|
||||||
}
|
}
|
||||||
if (timeoutId != null) window.clearTimeout(timeoutId)
|
if (timeoutId != null) window.clearTimeout(timeoutId)
|
||||||
}
|
}
|
||||||
}, [canAccess, canAccessReports, user?.id])
|
}, [hasInboxAccess, canAccess, canAccessReports, canAccessClubCreation, user?.id])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onChange = () => { refresh() }
|
const onChange = () => { refresh() }
|
||||||
|
|
@ -124,21 +149,42 @@ export function OrgInboxProvider({ user, children }) {
|
||||||
return () => window.removeEventListener('shinkan:inbox-changed', onChange)
|
return () => window.removeEventListener('shinkan:inbox-changed', onChange)
|
||||||
}, [refresh])
|
}, [refresh])
|
||||||
|
|
||||||
|
const clubCreationCount = clubCreationRequests.length
|
||||||
|
const joinCount = items.length
|
||||||
|
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
inboxJoinRequests: items,
|
inboxJoinRequests: items,
|
||||||
inboxCount: items.length,
|
inboxClubCreationRequests: clubCreationRequests,
|
||||||
|
clubCreationRequestCount: clubCreationCount,
|
||||||
|
inboxCount: joinCount + clubCreationCount,
|
||||||
contentReports,
|
contentReports,
|
||||||
contentReportCount: contentReports.filter((r) => r.status === 'submitted').length,
|
contentReportCount: contentReports.filter((r) => r.status === 'submitted').length,
|
||||||
contentReportsError,
|
contentReportsError,
|
||||||
refreshOrgInbox: refresh,
|
refreshOrgInbox: refresh,
|
||||||
canAccessOrgInbox: canAccess,
|
canAccessOrgInbox: canAccess,
|
||||||
canAccessContentReports: canAccessReports,
|
canAccessContentReports: canAccessReports,
|
||||||
|
canAccessClubCreationInbox: canAccessClubCreation,
|
||||||
|
canShowInboxNav: hasInboxAccess,
|
||||||
isSuperadmin: user?.role === 'superadmin',
|
isSuperadmin: user?.role === 'superadmin',
|
||||||
isPlatformAdmin: user?.role === 'admin' || user?.role === 'superadmin',
|
isPlatformAdmin: user?.role === 'admin' || user?.role === 'superadmin',
|
||||||
isClubAdmin: activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin')),
|
isClubAdmin: activeClubMemberships(user?.clubs || []).some((c) => (c.roles || []).includes('club_admin')),
|
||||||
}),
|
}),
|
||||||
[items, contentReports, contentReportsError, refresh, canAccess, canAccessReports, user?.role, user?.clubs]
|
[
|
||||||
|
items,
|
||||||
|
clubCreationRequests,
|
||||||
|
clubCreationCount,
|
||||||
|
joinCount,
|
||||||
|
contentReports,
|
||||||
|
contentReportsError,
|
||||||
|
refresh,
|
||||||
|
canAccess,
|
||||||
|
canAccessReports,
|
||||||
|
canAccessClubCreation,
|
||||||
|
hasInboxAccess,
|
||||||
|
user?.role,
|
||||||
|
user?.clubs,
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
return <OrgInboxContext.Provider value={value}>{children}</OrgInboxContext.Provider>
|
return <OrgInboxContext.Provider value={value}>{children}</OrgInboxContext.Provider>
|
||||||
|
|
|
||||||
|
|
@ -324,11 +324,14 @@ export default function InboxPage() {
|
||||||
const {
|
const {
|
||||||
canAccessOrgInbox,
|
canAccessOrgInbox,
|
||||||
canAccessContentReports,
|
canAccessContentReports,
|
||||||
|
canAccessClubCreationInbox,
|
||||||
|
canShowInboxNav,
|
||||||
isSuperadmin,
|
isSuperadmin,
|
||||||
isPlatformAdmin,
|
isPlatformAdmin,
|
||||||
isClubAdmin,
|
isClubAdmin,
|
||||||
refreshOrgInbox,
|
refreshOrgInbox,
|
||||||
inboxJoinRequests,
|
inboxJoinRequests,
|
||||||
|
inboxClubCreationRequests,
|
||||||
contentReports,
|
contentReports,
|
||||||
contentReportCount,
|
contentReportCount,
|
||||||
contentReportsError,
|
contentReportsError,
|
||||||
|
|
@ -339,7 +342,7 @@ export default function InboxPage() {
|
||||||
const [showArchive, setShowArchive] = useState(false)
|
const [showArchive, setShowArchive] = useState(false)
|
||||||
|
|
||||||
const load = useCallback(async () => {
|
const load = useCallback(async () => {
|
||||||
if (!canAccessOrgInbox && !canAccessContentReports) {
|
if (!canShowInboxNav) {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -349,13 +352,13 @@ export default function InboxPage() {
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}, [canAccessOrgInbox, canAccessContentReports, refreshOrgInbox])
|
}, [canShowInboxNav, refreshOrgInbox])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
load()
|
load()
|
||||||
}, [load])
|
}, [load])
|
||||||
|
|
||||||
if (!canAccessOrgInbox && !canAccessContentReports) {
|
if (!canShowInboxNav) {
|
||||||
return (
|
return (
|
||||||
<div className="app-page">
|
<div className="app-page">
|
||||||
<h1 className="page-title">Posteingang</h1>
|
<h1 className="page-title">Posteingang</h1>
|
||||||
|
|
@ -375,7 +378,7 @@ export default function InboxPage() {
|
||||||
Posteingang
|
Posteingang
|
||||||
</h1>
|
</h1>
|
||||||
<p className="muted" style={{ marginTop: 0 }}>
|
<p className="muted" style={{ marginTop: 0 }}>
|
||||||
Beitrittsanträge und Inhaltsmeldungen für deine Zuständigkeitsbereiche.
|
Beitrittsanträge, Vereinsgründungen und Inhaltsmeldungen für deine Zuständigkeitsbereiche.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" className="btn btn-secondary" onClick={() => load()} disabled={loading}>
|
<button type="button" className="btn btn-secondary" onClick={() => load()} disabled={loading}>
|
||||||
|
|
@ -389,7 +392,107 @@ export default function InboxPage() {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
{/* Abschnitt 1: Beitrittsanträge */}
|
{/* Abschnitt: Vereinsgründungen (nur Superadmin) */}
|
||||||
|
{canAccessClubCreationInbox && (
|
||||||
|
<section style={{ marginBottom: '2rem' }}>
|
||||||
|
<h2 style={{ fontSize: '1rem', fontWeight: 600, marginBottom: '0.75rem', color: 'var(--text2)' }}>
|
||||||
|
Vereinsgründungen
|
||||||
|
{inboxClubCreationRequests.length > 0 && (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
background: 'var(--accent)',
|
||||||
|
color: '#fff',
|
||||||
|
borderRadius: '12px',
|
||||||
|
padding: '1px 8px',
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
marginLeft: '0.5rem',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{inboxClubCreationRequests.length}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
{inboxClubCreationRequests.length === 0 ? (
|
||||||
|
<div className="card" style={{ padding: '1.25rem' }}>
|
||||||
|
<p style={{ margin: 0 }} className="muted">Keine offenen Gründungsanträge.</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="inbox-page__list">
|
||||||
|
{inboxClubCreationRequests.map((req) => (
|
||||||
|
<div key={`creation-${req.id}`} className="card inbox-request-card">
|
||||||
|
<div className="inbox-request-card__main">
|
||||||
|
<div className="inbox-request-card__club">
|
||||||
|
{req.proposed_name}
|
||||||
|
{req.proposed_abbreviation ? (
|
||||||
|
<span className="muted" style={{ marginLeft: '0.35rem' }}>
|
||||||
|
({req.proposed_abbreviation})
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<strong className="inbox-request-card__applicant">
|
||||||
|
{req.applicant_name || req.applicant_email || 'Antragsteller/in'}
|
||||||
|
</strong>
|
||||||
|
<div className="muted inbox-request-card__meta">
|
||||||
|
{req.applicant_email} · Profil #{req.profile_id} · {formatWhen(req.created_at)}
|
||||||
|
</div>
|
||||||
|
{req.proposed_description ? (
|
||||||
|
<p className="inbox-request-card__message">{req.proposed_description}</p>
|
||||||
|
) : null}
|
||||||
|
{req.message ? (
|
||||||
|
<p className="inbox-request-card__message" style={{ fontStyle: 'italic' }}>
|
||||||
|
Nachricht: {req.message}
|
||||||
|
</p>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div className="inbox-request-card__actions">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={async () => {
|
||||||
|
if (
|
||||||
|
!confirm(
|
||||||
|
'Verein anlegen und Antragsteller als Hauptverwalter eintragen?'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await api.approveClubCreationRequest(req.id)
|
||||||
|
notifyOrgInboxChanged()
|
||||||
|
await load()
|
||||||
|
} catch (err) {
|
||||||
|
alert(err.message || String(err))
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Freigeben
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-secondary"
|
||||||
|
onClick={async () => {
|
||||||
|
if (!confirm('Gründungsantrag ablehnen?')) return
|
||||||
|
try {
|
||||||
|
await api.rejectClubCreationRequest(req.id)
|
||||||
|
notifyOrgInboxChanged()
|
||||||
|
await load()
|
||||||
|
} catch (err) {
|
||||||
|
alert(err.message || String(err))
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Ablehnen
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Abschnitt: Beitrittsanträge */}
|
||||||
{canAccessOrgInbox && (
|
{canAccessOrgInbox && (
|
||||||
<section style={{ marginBottom: '2rem' }}>
|
<section style={{ marginBottom: '2rem' }}>
|
||||||
<h2 style={{ fontSize: '1rem', fontWeight: 600, marginBottom: '0.75rem', color: 'var(--text2)' }}>
|
<h2 style={{ fontSize: '1rem', fontWeight: 600, marginBottom: '0.75rem', color: 'var(--text2)' }}>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user