'use client'; import { useState, useCallback } from 'react'; import { orderStore, type PaymentInfo } from '@/store/useOrderStore'; const inputStyle: React.CSSProperties = { width: '100%', padding: '0.6rem 0.75rem', borderRadius: '0.375rem', border: '1px solid rgba(0, 0, 0, 0.08)', background: 'rgba(255, 255, 255, 0.8)', color: '#1a1a2e', fontSize: '0.8rem', outline: 'none', transition: 'border-color 0.2s ease', }; const labelStyle: React.CSSProperties = { fontSize: '0.7rem', fontWeight: 500, color: '#94a3b8', marginBottom: '0.3rem', display: 'block', }; const errorStyle: React.CSSProperties = { fontSize: '0.65rem', color: '#ef4444', marginTop: '0.2rem', }; interface FormErrors { [key: string]: string; } function formatCardNumber(value: string): string { const digits = value.replace(/\D/g, '').slice(0, 16); return digits.replace(/(\d{4})(?=\d)/g, '$1 '); } function formatExpiry(value: string): string { const digits = value.replace(/\D/g, '').slice(0, 4); if (digits.length > 2) { return `${digits.slice(0, 2)}/${digits.slice(2)}`; } return digits; } export function PaymentStep() { const [form, setForm] = useState({ cardNumber: '', expiry: '', cvv: '', nameOnCard: '', }); const [errors, setErrors] = useState({}); const handleChange = useCallback((field: keyof PaymentInfo, value: string) => { let processed = value; if (field === 'cardNumber') processed = formatCardNumber(value); if (field === 'expiry') processed = formatExpiry(value); if (field === 'cvv') processed = value.replace(/\D/g, '').slice(0, 3); setForm((prev) => ({ ...prev, [field]: processed })); setErrors((prev) => { const next = { ...prev }; delete next[field]; return next; }); }, []); const validate = (): boolean => { const errs: FormErrors = {}; const digits = form.cardNumber.replace(/\s/g, ''); if (digits.length < 16) errs.cardNumber = 'Enter a valid 16-digit card number'; if (form.expiry.length < 5) errs.expiry = 'Enter a valid expiry (MM/YY)'; if (form.cvv.length < 3) errs.cvv = 'Enter a valid 3-digit CVV'; if (!form.nameOnCard.trim()) errs.nameOnCard = 'Name on card is required'; setErrors(errs); return Object.keys(errs).length === 0; }; const handleSubmit = () => { if (!validate()) return; orderStore.getState().setPayment(form); orderStore.getState().setStep('review'); }; return (

Payment Details

This is a demo checkout. No real payment will be processed.
handleChange('cardNumber', e.target.value)} placeholder="4242 4242 4242 4242" style={{ ...inputStyle, fontFamily: 'monospace', letterSpacing: '0.1em', borderColor: errors.cardNumber ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)' }} onFocus={(e) => { e.currentTarget.style.borderColor = 'rgba(59, 130, 246, 0.5)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = errors.cardNumber ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)'; }} /> {errors.cardNumber &&
{errors.cardNumber}
}
handleChange('expiry', e.target.value)} placeholder="MM/YY" style={{ ...inputStyle, fontFamily: 'monospace', borderColor: errors.expiry ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)' }} onFocus={(e) => { e.currentTarget.style.borderColor = 'rgba(59, 130, 246, 0.5)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = errors.expiry ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)'; }} /> {errors.expiry &&
{errors.expiry}
}
handleChange('cvv', e.target.value)} placeholder="123" style={{ ...inputStyle, fontFamily: 'monospace', borderColor: errors.cvv ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)' }} onFocus={(e) => { e.currentTarget.style.borderColor = 'rgba(59, 130, 246, 0.5)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = errors.cvv ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)'; }} /> {errors.cvv &&
{errors.cvv}
}
handleChange('nameOnCard', e.target.value)} placeholder="John Doe" style={{ ...inputStyle, borderColor: errors.nameOnCard ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)' }} onFocus={(e) => { e.currentTarget.style.borderColor = 'rgba(59, 130, 246, 0.5)'; }} onBlur={(e) => { e.currentTarget.style.borderColor = errors.nameOnCard ? 'rgba(239, 68, 68, 0.4)' : 'rgba(0, 0, 0, 0.08)'; }} /> {errors.nameOnCard &&
{errors.nameOnCard}
}
); }