StudentLouiseO
CategoryOverall
Prompt Titlemake groups
Prompt

What I wrote:

I want to create communites/groups for users, so different sports teams/clubs etc can use the website. I want the role of captain to stay the same for all of the groups, to create a group a user creates the join code, that other users will use to join the group. You can leave, edit, and add more groups under the account tab. One user can participate in multiple groups and toggle between them. The role of captain can vary for each group, and the user that creates a new group is automatically a captain.

What AI wrote:

I have a PHP app called "Seat Saver" at /Users/louiseoconnell/Herd/seat-saver (Laravel Herd local dev, plain PHP, no framework — includes/functions.php holds all DB queries as procedural functions, includes/header.php/footer.php are shared layout, pages/*.php are individual pages, config/schema.sql is the canonical schema for fresh installs, config/migrations/*.sql holds incremental ALTER scripts applied to the existing local database). It's currently a single-team rideshare/events app: users.role (member/captain) is a single global flag on the user, and events/trips/reservations aren't scoped to anything beyond the whole app.

I want to turn this into a multi-tenant app supporting separate groups/communities — different sports teams or clubs each running their own independent space on the same site. Please design and build:

Data model

  • A groups table (name, a unique join code, who created it, created-at).
  • A group_members table linking a user to a group, with a per-group role (member/captain) — captain status is scoped to one group, not global. A user can belong to many groups, and hold a different role in each.
  • events need to belong to a group (add a group_id). Trips and reservations don't need their own group column since they're already reachable through their event.
  • Cars stay global to the user (not scoped to a group) — the same physical car is usable across whichever groups its owner drives for. State this assumption clearly in your plan; flag it to me if you think it should work differently.

Migrating existing data

  • The live local database already has real users (some with role = 'captain') and no groups. The migration needs to create a default/legacy group, add every existing user to it as a group_member with their current role carried over, and assign all existing events to that group — so nothing currently in the database breaks or disappears. Don't just drop the old users.role column and lose that information.

Permissions

  • is_captain() and require_captain() in includes/functions.php currently check a global session role — change them to check the caller's role within whichever group is currently active (see below), not a global flag.

Creating, joining, editing, and leaving groups

  • Any logged-in user can create a new group by giving it a name; this generates a join code and makes that user its captain automatically.
  • Any logged-in user can join an existing group by entering its join code, joining as a regular member.
  • A group's captain(s) can edit that group (e.g. rename it, regenerate its join code).
  • Any member can leave a group they're in (should probably be blocked, or handled sensibly, if they're that group's only captain — use your judgment, just don't leave a group captain-less with no way to ever manage it again).
  • Put all of this — the list of groups a user belongs to (with their role in each), join, create, edit, and leave — under the existing pages/account.php page.

Switching between groups

  • A user in multiple groups needs to toggle which one is "active" — store the active group in the session, and everything group-scoped (the rides dashboard on index.php, pages/events.php, event creation/editing, the captain-only UI) should reflect whichever group is currently active. Add a simple switcher somewhere sensible in the nav/header for changing it.
  • Handle the case of a brand-new user with zero groups yet (e.g. right after registering) — they should land somewhere that lets them join or create their first group, not hit a broken/empty dashboard.

Match all existing conventions: CSRF (csrf_field()/csrf_verify()) on every form, prepared PDO statements, declare(strict_types=1), htmlspecialchars() on all output, and reuse the existing .card/.form-group/.btn/.ride-list CSS classes rather than inventing new styles. Write this as both an update to config/schema.sql (for fresh installs) and a new numbered file in config/migrations/ (for the existing local database) — check that directory for the next available number.

This is a big change — before considering it done, trace through the app as if you were two different users in two different groups and confirm events/rides genuinely don't leak across groups, and that every new page (create group, join group, switch group) is actually reachable by clicking through the UI, not just present in the code. A past pass on this app shipped a fully-coded page with no nav link pointing to it, so don't repeat that.

ProgressCompleted