Add password reset, order confirmation email with editable templates, and fix missing account entry points

Password reset uses Payload's built-in forgot/reset-password flow,
customized to link to this app instead of the Payload admin. Order
confirmation email and the password-reset email's wording both come from
a new Payload email-templates collection, editable without a deploy and
previewable via Live Preview at /email-preview/[type] (same mechanism as
Posts/LegalPages/Testimonials, sample data instead of a real document).

Also: order numbers get a random suffix (prevents guessing, motivated by
a considered-and-deferred guest order-lookup feature); the discount code
field only shows in the cart when a code is actually active (codes now
apply via a ?code= link instead of manual entry); and three navigation
gaps found while testing — no reachable login link with an empty cart, no
logout link anywhere, no way back from profile to order history.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Marco
2026-07-22 08:14:08 +00:00
parent adca6e0f64
commit f0df359db4
26 changed files with 865 additions and 81 deletions
+1 -18
View File
@@ -1,21 +1,4 @@
import nodemailer from "nodemailer";
// Server-only. Deliberately its own SMTP transport, independent of
// Payload's (which now also sends mail — see Customers.ts's verification
// email) — the whole point of this module is alerting when something is
// broken, and if Payload itself is what's broken, routing the alert
// through it could mean the alert never arrives. Same Hostinger account
// either way (already proven working via Diun's update notifications),
// just a second, separate connection to it.
const transport = nodemailer.createTransport({
host: "smtp.hostinger.com",
port: 587,
secure: false,
auth: {
user: process.env.SMTP_USER || "",
pass: process.env.SMTP_PASSWORD || "",
},
});
import { transport } from "./mailer";
// Fire-and-forget by design — callers should not await this in a way that
// blocks or fails the actual error response the customer sees. Wrap