Careeroza
Real World Example
Checkout Address Form Like Amazon
Amazon, Flipkart and Swiggy all validate the delivery address on the server (pincode serviceability, phone format) and show field errors without losing what you typed. With Server Actions:
// app/checkout/actions.ts
'use server';
import { z } from 'zod';
import { redirect } from 'next/navigation';
import { auth } from '@/auth';
import { isServiceable } from '@/lib/delivery';
import { prisma } from '@/lib/prisma';
const Address = z.object({
fullName: z.string().trim().min(2),
phone: z.string().regex(/^[6-9]\d{9}$/, 'Enter a 10-digit Indian mobile number'),
pincode: z.string().regex(/^\d{6}$/, 'Pincode must be 6 digits'),
line1: z.string().trim().min(5),
city: z.string().trim().min(2),
});
export type AddressState = { errors?: Partial<Record<keyof z.infer<typeof Address>, string[]>>; values?: Record<string, string> };
export async function saveAddress(prev: AddressState, formData: FormData): Promise<AddressState> {
const session = await auth();
if (!session?.user) redirect('/login?next=/checkout');
const values = Object.fromEntries(formData) as Record<string, string>;
const parsed = Address.safeParse(values);
if (!parsed.success) return { errors: parsed.error.flatten().fieldErrors, values };
if (!(await isServiceable(parsed.data.pincode))) {
return { errors: { pincode: ['We do not deliver to this pincode yet'] }, values };
}
await prisma.address.create({ data: { ...parsed.data, userId: session.user.id } });
redirect('/checkout/payment');
}Checking the Fields
Example
The two regular expressions from the schema, tested on their own:
const phone = /^[6-9]\d{9}$/;
const pincode = /^\d{6}$/;
for (const p of ['9876543210', '1234567890', '98765 43210', '987654321']) {
console.log('phone ', p.padEnd(12), phone.test(p));
}
for (const p of ['560001', '5600', '56OO01']) {
console.log('pincode', p.padEnd(12), pincode.test(p));
}Output
phone 9876543210 true phone 1234567890 false phone 98765 43210 false phone 987654321 false pincode 560001 true pincode 5600 false pincode 56OO01 false