Skip to content

feat: Update /admin to list/add/edit Organizers. Add "Change Organizer" to Events Dashboard. Clarify when "Overview" sidebar heading relates to Events -v- Organizer 🤖#1187

Open
mrjbj wants to merge 2 commits intoHiEventsDev:developfrom
mrjbj:feature/event-organizer-reassignment
Open

Conversation

@mrjbj
Copy link
Copy Markdown
Contributor

@mrjbj mrjbj commented May 2, 2026


What changes I've made

1. Events Page: Reassign organizer

Two entry points, both end-user-facing (no superadmin needed):

  • Change Organizer button positioned next to "Share Event" on event header. Opens a modal that mirrors the look of the existing SwitchOrganizerModal but performs an UpdateEvent mutation instead of navigating.
  • Event Settings → Organizer dropdown Pre-filled with the current organizer; allows change to any organizers still active in the same account.

2. Superadmin /admin/organizers page

New entry in the admin sidebar between Users and Events, modelled directly on the existing admin Users page:

  • Clicking a card navigates to /manage/organizer/{id} so the superadmin can use the existing organizer dashboard / settings flow to edit
  • "Create Organizer" button reuses the existing CreateOrganizerModal. An info banner clarifies that creation is scoped to the superadmin's own account; to create in another account, impersonate a user there first.

3. Sidebar disambiguation

The sidebar group header Overview appeared identically on both the event sidebar and the organizer sidebar, with no visual cue of which scope you were in. Renamed:

  • Event layout: OverviewEvent Overview
  • Organizer layout: OverviewOrganizer Overview

Backend changes

File Change
Services/Application/Handlers/Event/DTO/UpdateEventDTO.php Added ?int $organizer_id = null
Http/Request/Event/UpdateEventRequest.php Was actively unset-ing organizer_id; now ['sometimes', 'integer']
Services/Application/Handlers/Event/UpdateEventHandler.php When organizer_id is set and differs from current, calls OrganizerFetchService::fetchOrganizer($id, $accountId) (existing service, same pattern as CreateEventHandler); throws OrganizerNotFoundException if cross-account
Http/Actions/Events/UpdateEventAction.php Catches OrganizerNotFoundException → returns clean 422 with organizer_id field error
Models/Organizer.php New account() belongsTo relationship
Repository/Eloquent/OrganizerRepository.php + interface New getAllOrganizersForAdmin(?string $search, int $perPage): LengthAwarePaginator, eager-loads account and organizer_settings, search by name/email/account name
Http/Actions/Admin/Organizers/GetAllOrganizersAction.php (new) Role::SUPERADMIN gated, identical structure to GetAllUsersAction
Services/Application/Handlers/Admin/GetAllOrganizersHandler.php + DTO (new) Paginate via repo
Resources/Organizer/AdminOrganizerResource.php (new) Includes nested account info
routes/api.php New GET /admin/organizers route

Why I've made these changes

Today an event's organizer_id is set at creation and cannot be changed. There is no UI or API path to move an event between organizer brands within the same account.

I hit this in practice: I created an event while impersonating another user in my account, but the event landed under the default organizer (the one tied to my own user) rather than the organizer associated with the impersonated user's brand. The event's public page therefore showed the wrong brand. The only way to fix it was a direct DB update.

Separately, organizer management has poor discoverability — organizers only appear inside SwitchOrganizerModal, never as a dedicated page, and superadmins have no cross-account view of organizers analogous to the existing Users / Accounts / Events admin pages.

How I've tested these changes

Tests

backend/tests/Unit/Services/Application/Handlers/Event/UpdateEventHandlerTest.php (new) — 4 cases:

  1. reassigns_organizer_when_organizer_id_provided_and_different
  2. does_not_include_organizer_id_when_omitted (regression guard for previous behavior)
  3. does_not_reassign_when_organizer_id_matches_current (no wasted writes)
  4. rejects_cross_account_organizer (security boundary)

Full Unit suite: 357 passed, 0 failures (only the existing 1 deprecated + 1 skipped). Pint clean on all new files.

Translations

14 new strings, translated into 14 locales: de, es, fr, hu, it, nl, pl, pt, pt-br, se, tr, vi, zh-cn, zh-hk. ru intentionally untouched (matches existing project convention — that catalog is largely empty and the project does not require ru parity).

Checklist

mrjbj and others added 2 commits May 2, 2026 12:16
…nagement

- Event organizer is now editable post-creation via a Select in Event Settings and a "Change Organizer" button on the event layout (next to "Share Event"), routed through a new ChangeEventOrganizerModal
- New /admin/organizers superadmin page lists organizers across all accounts with search, click-through to the organizer dashboard, and a Create Organizer button
- Sidebar group headings disambiguated: "Overview" -> "Event Overview" / "Organizer Overview"
- Backend: UpdateEventDTO/Handler/Request now accept organizer_id; same-account validation enforced via OrganizerFetchService, with 422 returned when the target organizer belongs to another account
- New GET /admin/organizers endpoint (SUPERADMIN-gated) plus AdminOrganizerResource, repository method, and handler/DTO
- 4 new unit tests cover reassignment, no-op when omitted, no-op when unchanged, and cross-account rejection
- Translations added for 14 new strings across all 14 supported non-Russian locales

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The event settings form binds to eventQuery.data.organizer_id, but the
API only returned the nested organizer relationship — so the Organizer
Select did not restore the saved value on refresh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant