Send activation link immediately for walk-in and manual registration accounts

Accounts created by staff on someone's behalf now get their activation
link (email or WhatsApp) sent right away, instead of only on a first
failed login attempt, matching what the Terms of Use already promised.
This also fixed a real account with a real email being silently
activated with a fixed, undisclosed password (Hope123).

Also fixes the self-service kiosk's "Create an account" password field,
which never actually took effect server-side, and removes the "Guest
(no account)" checkboxes that no longer had any backend effect once
every walk-in account started behaving the same way.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 13:29:38 +02:00
co-authored by Claude Sonnet 5
parent 7eed7a01df
commit d6da2c8227
8 changed files with 121 additions and 111 deletions
@@ -76,7 +76,6 @@ export default function ManualRegistrationPage() {
const [allUsers, setAllUsers] = useState<any[]>([]);
const [guest, setGuest] = useState({ name: "", email: "", phoneNumber: "" });
const [registerAsGuest, setRegisterAsGuest] = useState(false);
const [notifPref, setNotifPref] = useState<"email" | "whatsapp" | "both">("email");
const [quantities, setQuantities] = useState<Record<string, number>>({});
@@ -287,7 +286,7 @@ export default function ManualRegistrationPage() {
setError(null);
setMessage(null);
if (!selectedEventId) { setError("Please select an event."); return; }
if (!guest.name || (!registerAsGuest && !guest.email)) { setError("Guest name and email are required."); return; }
if (!guest.name || (!guest.email.trim() && !guest.phoneNumber.trim())) { setError("Guest name and at least one of email or phone are required."); return; }
const opts = Object.entries(quantities)
.filter(([, qty]) => qty > 0)
.map(([key, quantity]) => {
@@ -308,7 +307,6 @@ export default function ManualRegistrationPage() {
eventId: selectedEventId,
options: opts,
user: guest,
guestOnly: registerAsGuest,
notificationPreference: resolvedPref,
}
});
@@ -324,7 +322,6 @@ export default function ManualRegistrationPage() {
// Reset guest/ticket fields so the next registration starts from a clean slate
setGuest({ name: "", email: "", phoneNumber: "" });
setRegisterAsGuest(false);
setNotifPref("email");
setUserQuery("");
setDropdownOpen(false);
@@ -442,13 +439,6 @@ export default function ManualRegistrationPage() {
)}
</div>
<div className="border-t pt-3 mb-3">
<div className="flex items-center gap-2">
<input id="registerAsGuest" type="checkbox" checked={registerAsGuest} onChange={e => setRegisterAsGuest(e.target.checked)} />
<label htmlFor="registerAsGuest" className="text-sm text-gray-700">Guest (do not link to an existing account)</label>
</div>
</div>
<div className="grid gap-2">
<input
className="border rounded px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400"
@@ -458,11 +448,10 @@ export default function ManualRegistrationPage() {
/>
<input
className="border rounded px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400"
placeholder={registerAsGuest ? "Email (optional for guest)" : "Email"}
placeholder="Email (or provide a phone number below)"
type="email"
value={guest.email}
onChange={e => setGuest({ ...guest, email: e.target.value })}
required={!registerAsGuest}
/>
<input
className="border rounded px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400"