import { useState, useEffect } from "react"; import { useSearch, Link } from "wouter"; import { useQuery, useMutation } from "@tanstack/react-query"; import { queryClient, apiRequest } from "../lib/queryClient"; import { toast } from "../hooks/use-toast"; import { Package, User, LogOut, Mail } from "lucide-react"; interface Customer { id: number; email: string; firstName?: string; lastName?: string; phone?: string; } interface Order { id: number; orderNumber: string; status: string; paymentStatus: string; fulfillmentStatus: string; total: string; createdAt: string; trackingNumber?: string; trackingCarrier?: string; } function LoginForm() { const [email, setEmail] = useState(""); const [sent, setSent] = useState(false); const [loading, setLoading] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); setLoading(true); try { await apiRequest("POST", "/api/auth/magic-link", { email }); setSent(true); } catch (err: any) { toast({ title: "Error", description: err.message, variant: "destructive" }); } finally { setLoading(false); } }; if (sent) { return (

Check your email

We sent a sign-in link to {email}. Click it to sign in.

Link expires in 15 minutes.

); } return (

Sign in

We'll send a magic link to your email — no password needed.

setEmail(e.target.value)} required placeholder="you@example.com" className="w-full px-3 py-2 border border-border rounded-md text-sm bg-background focus:outline-none focus:ring-2 focus:ring-primary/30" data-testid="input-login-email" />
); } function AccountDashboard({ customer }: { customer: Customer }) { const { data: orders, isLoading } = useQuery({ queryKey: ["/api/account/orders"], queryFn: async () => { const r = await fetch("/api/account/orders", { credentials: "include" }); return r.json(); }, }); const logoutMutation = useMutation({ mutationFn: () => apiRequest("POST", "/api/auth/logout"), onSuccess: () => queryClient.invalidateQueries({ queryKey: ["/api/auth/me"] }), }); const statusBadge = (status: string) => { const colors: Record = { confirmed: "bg-blue-100 text-blue-700", pending: "bg-yellow-100 text-yellow-700", cancelled: "bg-red-100 text-red-700", fulfilled: "bg-green-100 text-green-700", }; return colors[status] || "bg-muted text-muted-foreground"; }; return (

My Account

{customer.email}

Orders

{isLoading ? (
{[1, 2, 3].map((i) =>
)}
) : !orders?.length ? (

No orders yet

Start shopping
) : (
{orders.map((order) => (

#{order.orderNumber}

{new Date(order.createdAt).toLocaleDateString("en-US", { year: "numeric", month: "short", day: "numeric" })}

{order.status} ${parseFloat(order.total).toFixed(2)}
{order.trackingNumber && (

Tracking: {order.trackingNumber}{order.trackingCarrier && ` (${order.trackingCarrier})`}

)}
))}
)}
); } export default function AccountPage() { const search = useSearch(); const token = new URLSearchParams(search).get("token"); const [verifying, setVerifying] = useState(!!token); const { data, isLoading } = useQuery<{ customer: Customer | null }>({ queryKey: ["/api/auth/me"], queryFn: async () => { const r = await fetch("/api/auth/me", { credentials: "include" }); return r.json(); }, }); useEffect(() => { if (!token) return; (async () => { try { const res = await fetch(`/api/auth/verify?token=${token}`, { credentials: "include" }); if (res.ok) { await queryClient.invalidateQueries({ queryKey: ["/api/auth/me"] }); toast({ title: "Signed in!", description: "Welcome back." }); } else { toast({ title: "Link expired", description: "Please request a new sign-in link.", variant: "destructive" }); } } finally { setVerifying(false); window.history.replaceState({}, "", "/account"); } })(); }, [token]); if (isLoading || verifying) { return
Loading...
; } return (
{data?.customer ? ( ) : ( )}
); }