Detect checkout email collisions and show login state in the navbar

Registering with an email that already has an account previously just
failed with a generic error and no clear next step. registerCustomer()
now flags emailExists specifically, and checkout switches straight to the
login toggle (email pre-filled, scrolled into view) instead. The account
icon also gets a small underline while logged in, matching the nav links'
active-state styling — it was otherwise the only nav element that gave no
visual signal of session state.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-22 08:26:00 +00:00
parent f0df359db4
commit ec75a480bd
4 changed files with 58 additions and 6 deletions
+17 -2
View File
@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
import { useRef, useState } from "react";
import Link from "next/link";
import Image from "next/image";
import { useRouter } from "next/navigation";
@@ -67,6 +67,7 @@ export function CheckoutContent({
const [purchaseError, setPurchaseError] = useState<string | null>(null);
const [purchasing, setPurchasing] = useState(false);
const [showLogin, setShowLogin] = useState(false);
const accountGateRef = useRef<HTMLDivElement>(null);
const [loginEmail, setLoginEmail] = useState("");
const [loginPassword, setLoginPassword] = useState("");
const [loginError, setLoginError] = useState<string | null>(null);
@@ -156,6 +157,16 @@ export function CheckoutContent({
});
const data = await res.json();
if (!data.ok) {
// The email typed into Card 1 already belongs to an existing
// account — registering was never going to work here. Switch
// straight to the login toggle with that email pre-filled instead
// of just showing an error with no clear next step; the customer
// only needs to add their password and resubmit.
if (data.emailExists) {
setLoginEmail(body.email);
setShowLogin(true);
accountGateRef.current?.scrollIntoView({ behavior: "smooth", block: "center" });
}
setPurchaseError(data.reason || "Die Bestellung konnte nicht abgeschlossen werden.");
setPurchasing(false);
return;
@@ -234,7 +245,10 @@ export function CheckoutContent({
{/* Account gate — an account is required to buy, so this either
confirms the active session or offers "already a customer?"
login inline (registration itself happens as part of the main
form submit below, via the password field in Card 1). */}
form submit below, via the password field in Card 1). Ref used
to scroll this into view if a checkout submit turns out to
collide with an existing account (see handleSubmit). */}
<div ref={accountGateRef} className="w-full">
{customerEmail ? (
<p className="text-body-sm text-text-primary">
Eingeloggt als <span className="font-bold">{customerEmail}</span>{" "}
@@ -278,6 +292,7 @@ export function CheckoutContent({
{loginError && <p className="text-label text-red-600 w-full">{loginError}</p>}
</div>
)}
</div>
</Reveal>
<form onSubmit={handleSubmit} className="flex flex-col lg:flex-row gap-8 lg:gap-10 items-start pb-10 pt-2 px-[var(--layout-padding-x)] w-full">