Skip to content

feat(edit-meeting): show and remove a meeting's linked schedule - #557

Merged
tunile943 merged 4 commits into
masterfrom
feat/linked-schedule-read-ui
Aug 23, 2026
Merged

feat(edit-meeting): show and remove a meeting's linked schedule#557
tunile943 merged 4 commits into
masterfrom
feat/linked-schedule-read-ui

Conversation

@tunile943

@tunile943 tunile943 commented Aug 23, 2026

Copy link
Copy Markdown
Member

@coderabbitai summary

Description

Fifth PR of the linked meeting modes work, stacked on #555. PRs 3 and 4 taught the update and create routes to write a linked schedule; this one is the first that lets an admin see one. After it, the three legacy production meetings that were backfilled into families in PR 1 are visible and manageable in the app — read-only, plus a Remove action. There is still no create UI (PR 6).

  • frontend/app/api/retrieve/meeting/[id]/route.ts, frontend/types/models.ts: an admin response gains linkedSchedules — this meeting's other schedules (Meeting.linkedToMid), each carrying only what the card renders: mode, room, Zoom room, host, recurrence pattern, start/end, and the two sync statuses. Deliberately a separate field from the existing sharedWith: that one is keyed on zid and answers "does another row use this Zoom link", which an In-Person family member — no zid at all — can never appear in, whereas this one answers "which schedules make up this one meeting". Admin-only for the BUG-022 reason (it names rooms, hosts and schedules a public viewer never sees), and omitted entirely rather than sent as [] for the overwhelmingly common single-schedule meeting, matching sharedZoom's shape.
  • frontend/app/components/meeting-form/ScheduleSummaryCard.tsx (new): the read-only summary of one schedule — mode icon + name, the days it meets and its ET time range, where it happens, a "waiting to sync" note, and a link to that schedule's own form. Two details worth a reviewer's eye:
    • Its prop type is structural, not ILinkedSchedule, so PR 6 can hand it a schedule that only exists in form state with no mid or sync status yet. startDateTime/endDateTime accept a string as well as a Date because a saved schedule arrives over JSON and is a string at runtime whatever the declared type says — Intl.format throws on an unwrapped one.
    • 'error' counts as waiting, not broken: a schedule created while the Zoom host pool was exhausted lands there with no calendar events at all, and the fix is the same retry sync as 'pending'. A null status is a legacy/backfilled row that never reported one, and claims nothing.
    • formatScheduleLine is exported so the removal confirmation names the schedule exactly the way the card does.
  • frontend/app/components/meeting-form/EditMeeting.tsx: a "Linked schedule(s)" section above the form, one card per member, each with a Remove action. The section says plainly that the form below edits the schedule you opened — a linked schedule's mode, days, room and host are edited from its own form, since it is an ordinary Meeting row with its own mid, and offering to edit it in-place here would be a second, subtly different editor for the same row.
  • frontend/app/components/meeting-form/RemoveLinkedScheduleModal.tsx (new): removal goes through the ordinary DELETE /api/delete/meeting with deleteOption: 'all' — it is a whole-series delete of a real Meeting row, so it gets the same modal weight as any other delete rather than an inline "×". The modal states the Zoom consequence up front, which is not the same in all three cases: nothing at all for an In-Person schedule (it was never on the Zoom meeting), kept when the surviving schedule still runs on it, deleted when this was the last row pointing at that zid. None of the form's in-progress edits are submitted or discarded; the existing onUpdateSuccess refresh re-reads the meeting without closing the panel.
  • frontend/app/components/meeting-form/ViewMeeting.tsx, frontend/app/(main)/page.tsx: the same card, under an "Also meets" heading, in the read-only detail panel — admin-gated there too, and with no Remove action: removing a schedule is an Edit action.
  • frontend/app/api/delete/meeting/route.ts: deleting the anchor of a family now clears linkedToMid on its surviving members, inside the same transaction as the soft delete, so a lone row never dangles a pointer at a soft-deleted mid — its family drops to one and its Zoom topic and calendar titles fall back to the single-schedule name on the next write. Nothing to do when the deleted row was the linked member instead: the anchor's own linkedToMid was never set. The shared Zoom meeting is untouched either way — syncDeleteAll's existing sibling/zid guard keeps it alive for whichever schedule is left, and only tears it down with the last one.
  • Tests — 6 new EditMeeting cases (the read-only card and its link, silence for a single-schedule meeting, cancel deletes nothing, confirm hits the delete route, and both Zoom-consequence wordings), a new 9-case ScheduleSummaryCard.test.tsx, 2 new ViewMeeting cases (admin sees it with no Remove; a non-admin never does), 5 new delete-meeting-route cases (anchor-vs-member deletion, the shared Zoom meeting surviving the first delete and going with the last, and the survivor's external name falling back), and 6 new retrieve-meeting-detail-route cases (including a Zoom-free member reported despite sharing no zid, a soft-deleted member dropping out of the family, and a USER-role session plus a public caller both getting nothing).

Testing

  • cd frontend && yarn test:all — green (lint, lint:css, typecheck, unit, component, integration, e2e), run against a clear port 3000.
  • yarn test:component --testPathPattern "ScheduleSummaryCard|EditMeeting|ViewMeeting" and yarn test:integration --testPathPattern "retrieve-meeting-detail-route|delete-meeting-route" — the new cases above.
  • Pre-existing-test sweep (pr_convention.md): the behavior-altering edits are the delete route's single update$transaction and the retrieve route's admin body gaining a field, so the existing delete-meeting-route.test.ts and retrieve-meeting-detail-route.test.ts suites passing unchanged is the assertion that a single-schedule meeting deletes and reads back exactly as before; delegated to a subagent rather than run from the implementing context.
  • Reviewer check: open one of the backfilled legacy meetings as an admin — the detail panel shows an "Also meets" card for its other schedule, and Edit shows the same card with a Remove action. Open it as a non-admin: neither appears.
  • Reviewer check: remove the linked schedule of a Hybrid + Zoom-Only family and confirm the modal says the Zoom meeting stays, that only the linked row is soft-deleted, and that the survivor's linkedToMid is cleared when the anchor is the one removed.

Area(s) Touched

Product areas

  • auth — sign-in, sessions, NextAuth, role-based access
  • admin — /admin shell (Diagnostics, Users, Import, Export tabs)
  • docs — /docs Resources page (rendering, navigation, search)
  • ui/ux — frontend layout/styling not tied to a specific integration

Integrations

  • google-calendar — Google Calendar sync
  • zoom-api — Zoom meeting/host sync

Engineering

  • security — auth hardening, data exposure, dependency/security scanning
  • testing — test suite (Jest/Playwright) changes
  • github-actions — workflows, Dependabot config, other .github/ CI tooling
  • cleanup — refactor or dead-code removal, no behavior change
  • documentation — docs/ or README changes only

Pre-merge Checklist

  • Code follows current formatting conventions and passes lint (yarn lint).
  • Comments are appropriate — only where genuinely non-obvious, not restating what the code already says.
  • All test suites pass, both run locally and green in GitHub CI. Do not merge if any test suite is failing.
  • A test suite was added or updated for the feature/fix in this PR. Double-check this if you change a feature and did not update the test suites.
  • Only files relevant to this change are committed — no stray or unrelated files.
  • If this branch has a merge conflict with master, master was merged into this branch first (not the other way around).
  • The rest of this PR description (Description, Testing) is filled out, not left as template placeholders.

@vercel

vercel Bot commented Aug 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ithaca-recovery Ready Ready Preview Aug 23, 2026 6:31pm

@tunile943 tunile943 changed the title feat/linked schedule read ui feat(edit-meeting): show and remove a meeting's linked schedule Aug 23, 2026
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fbbe4315-9bcd-42a0-99fb-b3e64dbcc046

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added scope: google-calendar Google Calendar sync (services/googleCalendar.ts) scope: testing Test suite (Jest/Playwright) changes scope: ui/ux Frontend layout/styling not tied to a specific integration scope: zoom-api Zoom meeting/host sync (services/zoom.ts) labels Aug 23, 2026
@tunile943
tunile943 force-pushed the feat/linked-schedule-create-api branch from b0b785b to 87b151a Compare August 23, 2026 18:18
Base automatically changed from feat/linked-schedule-create-api to master August 23, 2026 18:29
Adds an admin-only linkedSchedules array alongside the existing zid-keyed
sharedWith, keyed on linkedToMid so a Zoom-free In-Person family member is
reported too, and releases a surviving member's linkedToMid when the family
anchor is deleted.
Renders each linked schedule as a read-only ScheduleSummaryCard in the Edit
form and the View popup -- mode, days, time, location, and whether it is still
waiting to sync -- with a confirm-first Remove in Edit and a deep link to the
schedule's own form for anything else.
…removal

Covers ScheduleSummaryCard's fields, waiting-to-sync state and Remove action,
Edit's confirm-then-delete flow (including what each Zoom outcome promises),
and View's admin-only section.
…lete

Retrieve: the card's full shape, resolution from either member, a Zoom-free
member no zid lookup could find, and the admin-only gate (BUG-022). Delete:
the survivor's released pointer, the shared Zoom meeting outliving the first
deletion, and the survivor's name falling back to its single-schedule form.
@tunile943
tunile943 force-pushed the feat/linked-schedule-read-ui branch from 41396e6 to 609597f Compare August 23, 2026 18:30
@tunile943
tunile943 merged commit 518d047 into master Aug 23, 2026
20 of 28 checks passed
@tunile943
tunile943 deleted the feat/linked-schedule-read-ui branch August 23, 2026 18:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: google-calendar Google Calendar sync (services/googleCalendar.ts) scope: testing Test suite (Jest/Playwright) changes scope: ui/ux Frontend layout/styling not tied to a specific integration scope: zoom-api Zoom meeting/host sync (services/zoom.ts)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant