Add a news review workflow and a staff notification area

News gains a PENDING_REVIEW status between draft and published. A
non-editor author (can_add_news but not can_publish_news -- a
coach_manager, not an ADMIN/EDITOR) gets a "Send for review" button
instead of Publish; an editor/admin always sees Publish directly, no
review step. Submitting notifies every ADMIN/EDITOR in-app only (see
notify_members' new send_email=False) -- a review queue that emailed
on every submission would get noisy fast.

The notification area itself: a topbar bell (badge + dropdown, same
<details>/<summary> convention as the sidebar's user-menu, generalised
to a shared .dismissable-details close handler) visible on every page,
plus a fuller "Notifications" card on the dashboard, both fed by a new
notification_bell context processor. "Mark all read" clears the
signed-in staff member's own unread notifications for this club.

This is the reusable notification system's first consumer beyond news
publishing itself -- validates that notify_members()/Notification
generalise the way they were meant to.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
This commit is contained in:
2026-08-21 09:52:59 +02:00
parent 20a44a915f
commit 0ecdeac354
16 changed files with 421 additions and 26 deletions

View File

@@ -2747,6 +2747,9 @@
}
}
}
.-top-1 {
top: calc(var(--spacing) * -1);
}
.top-1 {
top: var(--spacing);
}
@@ -2765,6 +2768,9 @@
.top-full {
top: 100%;
}
.-right-1 {
right: calc(var(--spacing) * -1);
}
.right-0 {
right: 0;
}
@@ -4015,6 +4021,9 @@
.w-72 {
width: calc(var(--spacing) * 72);
}
.w-80 {
width: calc(var(--spacing) * 80);
}
.w-\[7px\] {
width: 7px;
}
@@ -4081,6 +4090,9 @@
.min-w-0 {
min-width: 0;
}
.min-w-4 {
min-width: calc(var(--spacing) * 4);
}
.min-w-40 {
min-width: calc(var(--spacing) * 40);
}
@@ -4828,6 +4840,9 @@
--otp-size: calc(var(--size-field, 0.25rem) * 12);
}
}
.text-\[9px\] {
font-size: 9px;
}
.text-\[10px\] {
font-size: 10px;
}

File diff suppressed because one or more lines are too long