Skip to content

Closing a signup is one-way; need a Reopen affordance #20

@richshaw

Description

@richshaw

Context

Today, closing a signup is a one-way door. The status machine in src/services/signups.ts allows draft → open (publish) and open → closed (close), but there's no closed → open transition. An organizer who accidentally closes a signup, or who closes one early but later wants to extend it, has no recovery — their only option is to archive it and start over.

The detail header now exposes Close while the signup is open (#19), but a closed signup shows no action at all besides Preview / Export. The status pill says closed and that's the end of it.

Proposed approach

Add a reopenSignup service + API + header button that mirrors the close path:

  • Service (src/services/signups.ts): new reopenSignup(db, actor, id) delegating to transitionStatus(db, actor, id, 'closed', 'open', 'signup.reopened'). Add signup.reopened as an activity event kind.
  • API (src/app/api/signups/[id]/reopen/route.ts): POST handler matching …/close/route.ts.
  • Action (src/app/app/(chrome)/signups/[id]/actions.ts): reopenAction(signupId) analogous to closeAction.
  • UI (src/components/signup/SignupHeader.tsx): when status === 'closed', render a Reopen button next to Preview/Export — same brand-fill styling as Publish/Close, mutually exclusive with both.

Status machine after this change:

  • draft → open (publish)
  • open ↔ closed (close / reopen)
  • any → archived (terminal — still one-way, intentionally)

archived stays terminal because it implies the organizer is done; reopening from archive is out of scope.

Open questions

  • Reminder jobs on reopen: closing a signup doesn't currently cancel pending reminders (worth confirming) — does reopen need to re-schedule anything, or does the existing singletonKey: commitmentId job model handle it?
  • Public page caching: /s/[slug] renders different copy for closed vs open — confirm the existing layout revalidation in revalidateSignup is sufficient (it should be, since close already relies on it).
  • Confirmation prompt: close currently has no confirm step. Reopen probably doesn't need one either, but worth a thought — accidental reopen is much less destructive than accidental close.

Tests

  • Unit: extend the status-transition tests in src/services/*.test.ts to cover the new edge.
  • DB: add a closed → open → closed round-trip in src/services/*.db.test.ts to confirm activity log entries land correctly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions