Files
ryan d005080aca Add attendee cap with required login for capped events
Hosts can optionally cap total attendance (RSVPs + plus-ones) when
creating an event. Capped events require guests to log in via the
existing email code flow; RSVPs are tied to accounts and deduped per
user. The event page shows spots left and replaces the form with a
full notice when the cap is reached; the server rejects over-cap
RSVPs and edits with 409 as a race backstop.

Also threads a safeNext-validated ?next= param through the login and
name-setup flow so guests land back on the event after signing in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:36:57 -04:00

60 lines
2.1 KiB
HTML

{{define "slots-inner"}}
<div class="section-label">What's needed</div>
<div class="slots-grid">
{{range .Slots}}
<div class="slot-card{{if .IsFull}} full{{end}}">
<div class="slot-info">
<div class="slot-name">{{.Slot.Emoji}} {{.Slot.Name}}</div>
<div class="slot-claims">
{{if .Claims}}
{{range .Claims}}
<span class="claim-chip">
{{.Name}}{{if .Note}} <small style="color:#888">({{.Note}})</small>{{end}}
<button hx-delete="/e/{{$.Event.Slug}}/claim/{{.ID}}"
hx-target="#slots-container"
hx-swap="innerHTML settle:0.1s"
hx-confirm="Remove {{.Name}}?"
title="Remove">&#215;</button>
</span>
{{end}}
{{else}}
<span class="nobody">nobody yet</span>
{{end}}
</div>
<div class="progress-bar">
<div class="progress-fill{{if .IsFull}} full{{end}}" style="width:{{.Pct}}%"></div>
</div>
</div>
<div class="slot-right">
<span class="slot-count{{if .IsFull}} warn{{end}}">{{.ClaimCount}} / {{.Slot.MaxClaims}}{{if .IsFull}} &#10003;{{end}}</span>
</div>
</div>
{{end}}
</div>
<div class="section-label">Going ({{.TotalGoing}}{{if .Capped}} / {{.Event.AttendeeCap}}{{end}})</div>
<div class="rsvp-list">
{{if .GoingList}}
{{range .GoingList}}
<span class="claim-chip">
{{if gt .RsvpID 0}}<span class="rsvp-name-link"
hx-get="/e/{{$.Event.Slug}}/rsvp/{{.RsvpID}}/edit"
hx-target="#edit-modal"
hx-swap="innerHTML">{{.Name}}</span>{{else}}{{.Name}}{{end}}{{if gt .PlusOne 0}} +{{.PlusOne}}{{end}}{{if .Note}} <small style="color:#888">({{.Note}})</small>{{end}}
{{if gt .RsvpID 0}}
<button hx-delete="/e/{{$.Event.Slug}}/rsvp/{{.RsvpID}}"
hx-target="#slots-container"
hx-swap="innerHTML settle:0.1s"
hx-confirm="Remove {{.Name}}?"
title="Remove">&#215;</button>
{{end}}
</span>
{{end}}
{{else}}
<span class="nobody">no one yet</span>
{{end}}
</div>
{{end}}
{{define "slots.html"}}{{template "slots-inner" .}}{{end}}