feat(dashboard): a guests page for an event - #356
Conversation
Greptile SummaryThe PR adds an event guest-management page backed by a read-authorized API for submitted tickets.
Confidence Score: 4/5The PR is not yet safe to merge because read-only team members still receive write-protected event metadata on the guest page, producing an incorrect breadcrumb. The previously reported access mismatch remains: the guest API permits team read access, but the page separately invokes Files Needing Attention: dashboard/src/pages/manage/events/EventGuests.vue, dashboard/src/data/events.ts
|
| Filename | Overview |
|---|---|
| buzz/api/events/services.py | Adds the read-authorized guest-list service, submitted-ticket projection, title resolution, and registration-status calculation. |
| dashboard/src/pages/manage/events/EventGuests.vue | Adds the guest summary, searchable list, and shared event header integration. |
| dashboard/src/components/dashboard/events/EventGuestItem.vue | Renders each submitted ticket’s guest identity, add-ons, and ticket type. |
| dashboard/src/router.ts | Registers the guest page as a dedicated event-workspace route. |
| e2e/tests/manage-event.spec.ts | Covers guest navigation, list totals, labels, registration status, and client-side search. |
Reviews (5): Last reviewed commit: "feat(dashboard): a glance at the turnout..." | Re-trigger Greptile
| const route = useRoute(); | ||
| const eventId = route.params.eventId as string; | ||
|
|
||
| const event = eventDetail(eventId); |
There was a problem hiding this comment.
Write-only metadata breaks read access
When a Viewer or another read-only team member opens this page, eventDetail(eventId) invokes the write-protected event-detail API even though the guest endpoint permits read access, causing that metadata request to be rejected and the breadcrumb to display the generic “Event” fallback instead of the event title.
Prompt To Fix With AI
This is a comment left during a code review.
Path: dashboard/src/pages/manage/events/EventGuests.vue
Line: 12
Comment:
**Write-only metadata breaks read access**
When a Viewer or another read-only team member opens this page, `eventDetail(eventId)` invokes the write-protected event-detail API even though the guest endpoint permits read access, causing that metadata request to be rejected and the breadcrumb to display the generic “Event” fallback instead of the event title.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.f07ae4b to
3ed8280
Compare
dca02a6 to
bf146a1
Compare
3ed8280 to
a03d5d1
Compare
bf146a1 to
262bade
Compare
a03d5d1 to
42d87f1
Compare
262bade to
eef8f42
Compare
❌ UI Demo Check failedThis pull request changes the UI (8 file(s) under 🛠️ How to fix
Either one re-runs this check automatically. |
Attendees becomes Guests in the event sidebar, and the destination is now a page rather than the placeholder: everyone holding a ticket, listed by name. Only submitted tickets count — a draft is a booking still being paid for, not somebody coming. The team permission hooks already scope Event Ticket, so the list is a plain query with no endpoint behind it. The page header both event pages share moves into EventPageHeader, with the section name as a prop and a slot for whatever the page puts on the right. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A count of registrations sits above the list, and a row now carries the person rather than just their name: avatar, name, email, the add-ons they picked as badges, and the ticket type they hold. Add-ons live in a child table, which a plain list query cannot reach, so the page moves onto get_event_guests. Both the ticket type and the add-ons are named rather than numbered — Event Ticket Type and Ticket Add-on are autonamed, so the link value on its own is a docname nobody recognises. Their titles are looked up in one query each, keyed by string, since an autonamed doctype returns integer names while every link to it travels as a string. Read access is the bar, not write: the list shows the team what the doctype already shows it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The border was packaging around a number that reads fine without it, and the box stretched the full column to hold two short lines. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The page opens on how the event is doing — the number registered, and whether registrations are still open — then the list itself, searchable by name or email. Filtering happens over the list already loaded, so a keystroke costs nothing. Whether registrations are closed is the booking flow's own rule, reused rather than restated: an explicit cutoff if the event sets one, otherwise the end of the event. A guest row now reads as a line rather than a stack, with the email beside the name — it is what tells two people of the same name apart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
42d87f1 to
ef955eb
Compare
eef8f42 to
1ab6f08
Compare
Stacked on #355. The event workspace's second section: who is coming.
What this adds
Guests replaces Attendees in the event sidebar, and the destination is a page rather than the placeholder.
A glance at the turnout — the number registered, and whether registrations are still open. Whether they are closed is the booking flow's own rule (
are_registrations_closed), reused rather than restated: an explicit cutoff if the event sets one, otherwise the end of the event.The guest list — one row per submitted ticket, showing avatar, name, email beside the name, the add-ons that ticket holds as badges, and its ticket type. Searchable by name or email, filtered over the list already loaded so a keystroke costs nothing.
Only submitted tickets count. A draft belongs to a booking still being paid for, not somebody coming.
API
buzz.api.events.get_event_guestsRead access is the bar, not write — the list shows the team what the doctype already shows it.
Add-ons live in a child table that a plain list query cannot reach, which is what this endpoint is for. Two details worth knowing, both caught by tests:
Event Ticket TypeandTicket Add-onare autonamed, so the link value alone is a docname nobody recognises (18213). Both are resolved to their titles, one batched query each.get_allwith integer names while every link to it travels as a string, so the title map is keyed bystr(name)— without that it silently never matches.Considered and dropped
A capacity bar, as on the reference design.
create_eventgives every event a published ticket type with no limit, so capacity resolved to "uncapped" on essentially every event and the bar would never have drawn. Left out rather than shipped as decoration.Tests
buzz.api.events.test_events— 37 pass, 8 new forget_event_guests: the count and list, a draft ticket excluded, add-ons carried through, the ticket type named rather than numbered, an empty event, registrations open and closed, a non-member refused, an unknown event.e2e/tests/manage-event.spec.ts— 14 pass, including the guest list (count matches row count, rows carry an email, the badge is not a bare number) and search narrowing to one row and back.Known, not addressed here
One row per ticket, so somebody who booked six tickets under one name appears six times. Grouping by person is a separate decision.
🤖 Generated with Claude Code