Add yes/no RSVP answers with required login

RSVPs now carry a status ('yes'/'no'). When auth is enabled, answering
requires login for all events, not just capped ones. Answers are deduped
one per user and re-answering updates in place. A 'no' zeroes plus_one,
is excluded from Going counts and cap math, frees the person's slot
claims, and shows in a separate "Can't make it" list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 07:59:33 -04:00
parent 891b49b4c0
commit cf2ef77bb0
12 changed files with 341 additions and 107 deletions
+18 -11
View File
@@ -41,25 +41,25 @@
<div class="section-label" style="margin-top:40px">Sign up</div>
{{if and .Capped .CapFull}}
<div class="claim-form-wrapper">
<div class="form-title">Event is full</div>
<p style="font-family:'DM Mono',monospace;font-size:0.8rem;color:#555;">
All {{.Event.AttendeeCap}} spots are taken.
</p>
</div>
{{else if and .Capped (not .User)}}
{{if and .AuthEnabled (not .User)}}
<div class="claim-form-wrapper">
<div class="form-title">Log in to RSVP</div>
<p style="font-family:'DM Mono',monospace;font-size:0.8rem;color:#555;margin-bottom:16px;">
This event has limited spots ({{.SpotsLeft}} left), so RSVPs require an account.
{{if .Capped}}This event has limited spots ({{.SpotsLeft}} left), so RSVPs{{else}}RSVPs{{end}} require an account.
</p>
<a class="btn-submit" style="display:inline-block;text-decoration:none;text-align:center;"
href="/login?next=/e/{{.Event.Slug}}">Log in to RSVP &#8599;</a>
</div>
{{else}}
<div class="claim-form-wrapper">
<div class="form-title">I'm coming &#8594;</div>
{{if .CapFull}}
<div class="form-title">Event is full</div>
<p style="font-family:'DM Mono',monospace;font-size:0.8rem;color:#555;margin-bottom:16px;">
All {{.Event.AttendeeCap}} spots are taken. You can still let them know you can't make it.
</p>
{{else}}
<div class="form-title">Are you coming?</div>
{{end}}
<form hx-post="/e/{{.Event.Slug}}/rsvp"
hx-target="#slots-container"
hx-swap="innerHTML settle:0.1s"
@@ -68,6 +68,7 @@
<label>Your name</label>
<input type="text" name="name" placeholder="e.g. Sam" required value="{{if .User}}{{.User.Name}}{{end}}">
</div>
{{if not .CapFull}}
{{if .Slots}}
<div class="form-row">
<label>Bringing something?</label>
@@ -83,11 +84,17 @@
<label>Bringing anyone?</label>
<input type="number" name="plus_one" value="0" min="0" max="{{if .Capped}}{{.PlusOneMax}}{{else}}10{{end}}">
</div>
{{end}}
<div class="form-row" id="claim-note">
<label>Note (optional)</label>
<input type="text" id="claim-note-input" name="note" placeholder="e.g. arriving late, dietary restrictions, etc.">
</div>
<button class="btn-submit" type="submit">Count me in &#8599;</button>
<div style="display:flex;gap:10px">
{{if not .CapFull}}
<button class="btn-submit" type="submit" name="status" value="yes">Count me in &#8599;</button>
{{end}}
<button class="btn-submit btn-no" type="submit" name="status" value="no">Can't make it</button>
</div>
</form>
</div>
{{end}}