UNPKG

storenest-commerce

Version:

Complete e-commerce SDK for Storenest platform with React components, multi-language support, secure checkout, and enterprise-grade security

711 lines 61.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CheckoutBox = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const checkout_1 = require("../checkout"); const utils_1 = require("../utils"); // Ensure this component is only used client-side const isClient = typeof window !== 'undefined'; // Create a safe wrapper that prevents SSR issues const createSafeComponent = () => { if (!isClient) { return () => ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '400px', background: '#f8f9fa', borderRadius: '8px' }, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '24px', marginBottom: '16px' }, children: "\uD83D\uDD04" }), (0, jsx_runtime_1.jsx)("div", { children: "Loading checkout component..." })] }) })); } // Only import React hooks when on client side const React = require('react'); const { useState, useEffect } = React; return function CheckoutBoxClient({ config = {}, onSuccess, onError, onCancel }) { const [checkout] = useState(() => new (require('../checkout').StorenestCheckout)(config)); const [loading, setLoading] = useState(false); const [currentStep, setCurrentStep] = useState('shipping'); const [session, setSession] = useState(null); const [shippingMethods, setShippingMethods] = useState([]); const [paymentMethods, setPaymentMethods] = useState([]); const [formData, setFormData] = useState({ firstName: '', lastName: '', email: '', phone: '', address: '', city: '', state: '', zipCode: '', country: 'US', notes: '', marketingConsent: false }); const [errors, setErrors] = useState({}); const [orderSummary, setOrderSummary] = useState({ subtotal: 0, shipping: 0, tax: 0, total: 0, currency: config.currency || 'EUR' }); // Initialize checkout session useEffect(() => { const initCheckout = async () => { try { setLoading(true); const { getOrCreateUserId } = require('../utils'); const userId = getOrCreateUserId(); if (!userId) { throw new Error('User ID not found'); } const response = await fetch('/api/checkout/init', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cartId: userId }) }); if (!response.ok) { throw new Error('Failed to create checkout session'); } const sessionData = await response.json(); setSession(sessionData); // Load shipping and payment methods await loadShippingMethods(); await loadPaymentMethods(); } catch (err) { onError?.(err.message); } finally { setLoading(false); } }; initCheckout(); }, []); const loadShippingMethods = async () => { try { const address = { firstName: formData.firstName, lastName: formData.lastName, email: formData.email, address: formData.address, city: formData.city, state: formData.state, zipCode: formData.zipCode, country: formData.country }; const response = await fetch('/api/checkout/shipping-methods', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address }) }); if (response.ok) { const methods = await response.json(); setShippingMethods(methods); // Auto-select first method if (methods.length > 0 && !formData.shippingMethodId) { setFormData(prev => ({ ...prev, shippingMethodId: methods[0].id })); updateOrderSummary(methods[0].price); } } } catch (err) { console.error('Failed to load shipping methods:', err); } }; const loadPaymentMethods = async () => { try { const response = await fetch('/api/checkout/payment-methods', { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { const methods = await response.json(); setPaymentMethods(methods); // Auto-select first method if (methods.length > 0 && !formData.paymentMethodId) { setFormData(prev => ({ ...prev, paymentMethodId: methods[0].id })); } } } catch (err) { console.error('Failed to load payment methods:', err); } }; const updateOrderSummary = (shippingCost) => { const subtotal = 80; // Mock subtotal - in real app, get from cart const tax = subtotal * 0.08; // 8% tax const total = subtotal + shippingCost + tax; setOrderSummary({ subtotal, shipping: shippingCost, tax, total, currency: config.currency || 'EUR' }); }; const validateForm = () => { const newErrors = {}; // Required fields if (!formData.firstName) newErrors.firstName = 'First name is required'; if (!formData.lastName) newErrors.lastName = 'Last name is required'; if (!formData.email) newErrors.email = 'Email is required'; if (!formData.address) newErrors.address = 'Address is required'; if (!formData.city) newErrors.city = 'City is required'; if (!formData.zipCode) newErrors.zipCode = 'Zip code is required'; if (!formData.country) newErrors.country = 'Country is required'; // Email validation if (formData.email && !/\S+@\S+\.\S+/.test(formData.email)) { newErrors.email = 'Please enter a valid email address'; } // Payment method validation if (!formData.paymentMethodId) { newErrors.paymentMethod = 'Please select a payment method'; } // Shipping method validation if (!formData.shippingMethodId) { newErrors.shippingMethod = 'Please select a shipping method'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); // Clear error when user starts typing if (errors[field]) { setErrors(prev => ({ ...prev, [field]: '' })); } }; const handleShippingMethodChange = (methodId) => { const method = shippingMethods.find(m => m.id === methodId); setFormData(prev => ({ ...prev, shippingMethodId: methodId })); if (method) { updateOrderSummary(method.price); } }; const handleNextStep = () => { if (validateForm()) { if (currentStep === 'shipping') { setCurrentStep('payment'); } else if (currentStep === 'payment') { setCurrentStep('review'); } } }; const handlePreviousStep = () => { if (currentStep === 'payment') { setCurrentStep('shipping'); } else if (currentStep === 'review') { setCurrentStep('payment'); } }; const handleSubmit = async () => { if (!validateForm()) return; try { setLoading(true); // In a real implementation, this would call the backend to process the order const orderId = `order_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // Simulate processing delay await new Promise(resolve => setTimeout(resolve, 2000)); onSuccess?.(orderId); } catch (err) { onError?.(err.message); } finally { setLoading(false); } }; const formatPrice = (amount) => { return new Intl.NumberFormat(config.locale || 'en-US', { style: 'currency', currency: config.currency || 'EUR' }).format(amount); }; if (loading && !session) { return ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '400px', background: '#f8f9fa', borderRadius: '8px' }, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '24px', marginBottom: '16px' }, children: "\uD83D\uDD04" }), (0, jsx_runtime_1.jsx)("div", { children: "Initializing checkout..." })] }) })); } return ((0, jsx_runtime_1.jsxs)("div", { style: { maxWidth: '800px', margin: '0 auto', background: '#fff', borderRadius: '12px', boxShadow: '0 4px 20px rgba(0, 0, 0, 0.1)', overflow: 'hidden' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { background: config.theme === 'modern' ? '#0070f3' : '#f8f9fa', padding: '24px', borderBottom: '1px solid #e1e5e9' }, children: [(0, jsx_runtime_1.jsx)("h2", { style: { margin: 0, color: config.theme === 'modern' ? '#fff' : '#333', fontSize: '24px', fontWeight: '600' }, children: "Secure Checkout" }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'space-between', marginTop: '16px' }, children: ['shipping', 'payment', 'review'].map((step, index) => ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', color: config.theme === 'modern' ? '#fff' : '#666' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { width: '32px', height: '32px', borderRadius: '50%', background: currentStep === step ? '#fff' : 'rgba(255,255,255,0.3)', color: currentStep === step ? '#0070f3' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: '600', fontSize: '14px' }, children: index + 1 }), (0, jsx_runtime_1.jsx)("span", { style: { marginLeft: '8px', fontSize: '14px' }, children: step.charAt(0).toUpperCase() + step.slice(1) })] }, step))) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { flex: 1, padding: '32px' }, children: [currentStep === 'shipping' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: { margin: '0 0 24px 0', color: '#333' }, children: "Shipping Information" }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "First Name *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.firstName, onChange: (e) => handleInputChange('firstName', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.firstName ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "First name" }), errors.firstName && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.firstName }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Last Name *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.lastName, onChange: (e) => handleInputChange('lastName', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.lastName ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Last name" }), errors.lastName && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.lastName }))] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Email Address *" }), (0, jsx_runtime_1.jsx)("input", { type: "email", value: formData.email, onChange: (e) => handleInputChange('email', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.email ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "your@email.com" }), errors.email && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.email }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Address *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.address, onChange: (e) => handleInputChange('address', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.address ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Street address" }), errors.address && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.address }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "City *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.city, onChange: (e) => handleInputChange('city', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.city ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "City" }), errors.city && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.city }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Zip Code *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.zipCode, onChange: (e) => handleInputChange('zipCode', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.zipCode ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Zip code" }), errors.zipCode && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.zipCode }))] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Country *" }), (0, jsx_runtime_1.jsxs)("select", { value: formData.country, onChange: (e) => handleInputChange('country', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.country ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, children: [(0, jsx_runtime_1.jsx)("option", { value: "US", children: "United States" }), (0, jsx_runtime_1.jsx)("option", { value: "CA", children: "Canada" }), (0, jsx_runtime_1.jsx)("option", { value: "GB", children: "United Kingdom" }), (0, jsx_runtime_1.jsx)("option", { value: "DE", children: "Germany" }), (0, jsx_runtime_1.jsx)("option", { value: "FR", children: "France" })] }), errors.country && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.country }))] }), shippingMethods.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("h4", { style: { margin: '0 0 16px 0', color: '#333' }, children: "Shipping Method" }), shippingMethods.map((method) => ((0, jsx_runtime_1.jsxs)("label", { style: { display: 'flex', alignItems: 'center', padding: '16px', border: `1px solid ${formData.shippingMethodId === method.id ? '#0070f3' : '#dee2e6'}`, borderRadius: '6px', marginBottom: '8px', cursor: 'pointer', background: formData.shippingMethodId === method.id ? '#f0f8ff' : '#fff' }, children: [(0, jsx_runtime_1.jsx)("input", { type: "radio", name: "shippingMethod", value: method.id, checked: formData.shippingMethodId === method.id, onChange: (e) => handleShippingMethodChange(e.target.value), style: { marginRight: '12px' } }), (0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontWeight: '500' }, children: method.name }), (0, jsx_runtime_1.jsxs)("div", { style: { color: '#666', fontSize: '14px' }, children: [method.estimatedDays, " \u2022 ", formatPrice(method.price)] })] })] }, method.id))), errors.shippingMethod && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.shippingMethod }))] }))] })), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', marginTop: '32px' }, children: [currentStep !== 'shipping' && ((0, jsx_runtime_1.jsx)("button", { onClick: handlePreviousStep, style: { padding: '12px 24px', border: '1px solid #dee2e6', background: '#fff', borderRadius: '6px', cursor: 'pointer', fontSize: '16px' }, children: "\u2190 Previous" })), (0, jsx_runtime_1.jsx)("div", { style: { marginLeft: 'auto' }, children: currentStep === 'review' ? ((0, jsx_runtime_1.jsx)("button", { onClick: handleSubmit, disabled: loading, style: { padding: '12px 32px', background: loading ? '#ccc' : '#0070f3', color: '#fff', border: 'none', borderRadius: '6px', cursor: loading ? 'not-allowed' : 'pointer', fontSize: '16px', fontWeight: '500' }, children: loading ? 'Processing...' : 'Place Order' })) : ((0, jsx_runtime_1.jsx)("button", { onClick: handleNextStep, style: { padding: '12px 32px', background: '#0070f3', color: '#fff', border: 'none', borderRadius: '6px', cursor: 'pointer', fontSize: '16px', fontWeight: '500' }, children: "Continue \u2192" })) })] })] }), config.showOrderSummary !== false && ((0, jsx_runtime_1.jsxs)("div", { style: { width: '300px', background: '#f8f9fa', padding: '24px', borderLeft: '1px solid #e1e5e9' }, children: [(0, jsx_runtime_1.jsx)("h3", { style: { margin: '0 0 24px 0', color: '#333' }, children: "Order Summary" }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }, children: [(0, jsx_runtime_1.jsx)("span", { children: "Subtotal" }), (0, jsx_runtime_1.jsx)("span", { children: formatPrice(orderSummary.subtotal) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }, children: [(0, jsx_runtime_1.jsx)("span", { children: "Shipping" }), (0, jsx_runtime_1.jsx)("span", { children: formatPrice(orderSummary.shipping) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', marginBottom: '8px' }, children: [(0, jsx_runtime_1.jsx)("span", { children: "Tax" }), (0, jsx_runtime_1.jsx)("span", { children: formatPrice(orderSummary.tax) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', justifyContent: 'space-between', paddingTop: '16px', borderTop: '1px solid #dee2e6', fontWeight: '600', fontSize: '18px' }, children: [(0, jsx_runtime_1.jsx)("span", { children: "Total" }), (0, jsx_runtime_1.jsx)("span", { children: formatPrice(orderSummary.total) })] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { fontSize: '14px', color: '#666', lineHeight: '1.5' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { marginBottom: '8px' }, children: "\uD83D\uDD12 Secure checkout powered by Storenest" }), (0, jsx_runtime_1.jsx)("div", { children: "Your payment information is encrypted and secure" })] })] }))] })] })); }; }; exports.CheckoutBox = createSafeComponent(); exports.default = exports.CheckoutBox; config ? : { theme: 'modern' | 'classic' | 'minimal', currency: string, locale: string, showOrderSummary: boolean, enableGuestCheckout: boolean }; onSuccess ? : (orderId) => void ; onError ? : (error) => void ; onCancel ? : () => void ; const CheckoutBox = ({ config = {}, onSuccess, onError, onCancel }) => { // Only render on client side if (!isClient) { return ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '400px', background: '#f8f9fa', borderRadius: '8px' }, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '24px', marginBottom: '16px' }, children: "\uD83D\uDD04" }), (0, jsx_runtime_1.jsx)("div", { children: "Loading checkout component..." })] }) })); } // Client-side only - React hooks are safe here return (0, jsx_runtime_1.jsx)(CheckoutBoxClient, { config: config, onSuccess: onSuccess, onError: onError, onCancel: onCancel }); }; exports.CheckoutBox = CheckoutBox; // Separate client component that uses React hooks const CheckoutBoxClient = ({ config = {}, onSuccess, onError, onCancel }) => { const [checkout] = (0, react_1.useState)(() => new checkout_1.StorenestCheckout(config)); const [loading, setLoading] = (0, react_1.useState)(false); const [currentStep, setCurrentStep] = (0, react_1.useState)('shipping'); const [session, setSession] = (0, react_1.useState)(null); const [shippingMethods, setShippingMethods] = (0, react_1.useState)([]); const [paymentMethods, setPaymentMethods] = (0, react_1.useState)([]); const [formData, setFormData] = (0, react_1.useState)({ firstName: '', lastName: '', email: '', phone: '', address: '', city: '', state: '', zipCode: '', country: 'US', notes: '', marketingConsent: false }); const [errors, setErrors] = (0, react_1.useState)({}); const [orderSummary, setOrderSummary] = (0, react_1.useState)({ subtotal: 0, shipping: 0, tax: 0, total: 0, currency: config.currency || 'EUR' }); // Initialize checkout session (0, react_1.useEffect)(() => { const initCheckout = async () => { try { setLoading(true); const userId = (0, utils_1.getOrCreateUserId)(); if (!userId) { throw new Error('User ID not found'); } const response = await fetch('/api/checkout/init', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ cartId: userId }) }); if (!response.ok) { throw new Error('Failed to create checkout session'); } const sessionData = await response.json(); setSession(sessionData); // Load shipping and payment methods await loadShippingMethods(); await loadPaymentMethods(); } catch (err) { onError?.(err.message); } finally { setLoading(false); } }; initCheckout(); }, []); const loadShippingMethods = async () => { try { const address = { firstName: formData.firstName, lastName: formData.lastName, email: formData.email, address: formData.address, city: formData.city, state: formData.state, zipCode: formData.zipCode, country: formData.country }; const response = await fetch('/api/checkout/shipping-methods', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ address }) }); if (response.ok) { const methods = await response.json(); setShippingMethods(methods); // Auto-select first method if (methods.length > 0 && !formData.shippingMethodId) { setFormData(prev => ({ ...prev, shippingMethodId: methods[0].id })); updateOrderSummary(methods[0].price); } } } catch (err) { console.error('Failed to load shipping methods:', err); } }; const loadPaymentMethods = async () => { try { const response = await fetch('/api/checkout/payment-methods', { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { const methods = await response.json(); setPaymentMethods(methods); // Auto-select first method if (methods.length > 0 && !formData.paymentMethodId) { setFormData(prev => ({ ...prev, paymentMethodId: methods[0].id })); } } } catch (err) { console.error('Failed to load payment methods:', err); } }; const updateOrderSummary = (shippingCost) => { const subtotal = 80; // Mock subtotal - in real app, get from cart const tax = subtotal * 0.08; // 8% tax const total = subtotal + shippingCost + tax; setOrderSummary({ subtotal, shipping: shippingCost, tax, total, currency: config.currency || 'EUR' }); }; const validateForm = () => { const newErrors = {}; // Required fields if (!formData.firstName) newErrors.firstName = 'First name is required'; if (!formData.lastName) newErrors.lastName = 'Last name is required'; if (!formData.email) newErrors.email = 'Email is required'; if (!formData.address) newErrors.address = 'Address is required'; if (!formData.city) newErrors.city = 'City is required'; if (!formData.zipCode) newErrors.zipCode = 'Zip code is required'; if (!formData.country) newErrors.country = 'Country is required'; // Email validation if (formData.email && !/\S+@\S+\.\S+/.test(formData.email)) { newErrors.email = 'Please enter a valid email address'; } // Payment method validation if (!formData.paymentMethodId) { newErrors.paymentMethod = 'Please select a payment method'; } // Shipping method validation if (!formData.shippingMethodId) { newErrors.shippingMethod = 'Please select a shipping method'; } setErrors(newErrors); return Object.keys(newErrors).length === 0; }; const handleInputChange = (field, value) => { setFormData(prev => ({ ...prev, [field]: value })); // Clear error when user starts typing if (errors[field]) { setErrors(prev => ({ ...prev, [field]: '' })); } }; const handleShippingMethodChange = (methodId) => { const method = shippingMethods.find(m => m.id === methodId); setFormData(prev => ({ ...prev, shippingMethodId: methodId })); if (method) { updateOrderSummary(method.price); } }; const handleNextStep = () => { if (validateForm()) { if (currentStep === 'shipping') { setCurrentStep('payment'); } else if (currentStep === 'payment') { setCurrentStep('review'); } } }; const handlePreviousStep = () => { if (currentStep === 'payment') { setCurrentStep('shipping'); } else if (currentStep === 'review') { setCurrentStep('payment'); } }; const handleSubmit = async () => { if (!validateForm()) return; try { setLoading(true); // In a real implementation, this would call the backend to process the order const orderId = `order_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; // Simulate processing delay await new Promise(resolve => setTimeout(resolve, 2000)); onSuccess?.(orderId); } catch (err) { onError?.(err.message); } finally { setLoading(false); } }; const formatPrice = (amount) => { return new Intl.NumberFormat(config.locale || 'en-US', { style: 'currency', currency: config.currency || 'EUR' }).format(amount); }; if (loading && !session) { return ((0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: '400px', background: '#f8f9fa', borderRadius: '8px' }, children: (0, jsx_runtime_1.jsxs)("div", { style: { textAlign: 'center' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontSize: '24px', marginBottom: '16px' }, children: "\uD83D\uDD04" }), (0, jsx_runtime_1.jsx)("div", { children: "Initializing checkout..." })] }) })); } return ((0, jsx_runtime_1.jsxs)("div", { style: { maxWidth: '800px', margin: '0 auto', background: '#fff', borderRadius: '12px', boxShadow: '0 4px 20px rgba(0, 0, 0, 0.1)', overflow: 'hidden' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { background: config.theme === 'modern' ? '#0070f3' : '#f8f9fa', padding: '24px', borderBottom: '1px solid #e1e5e9' }, children: [(0, jsx_runtime_1.jsx)("h2", { style: { margin: 0, color: config.theme === 'modern' ? '#fff' : '#333', fontSize: '24px', fontWeight: '600' }, children: "Secure Checkout" }), (0, jsx_runtime_1.jsx)("div", { style: { display: 'flex', justifyContent: 'space-between', marginTop: '16px' }, children: ['shipping', 'payment', 'review'].map((step, index) => ((0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex', alignItems: 'center', color: config.theme === 'modern' ? '#fff' : '#666' }, children: [(0, jsx_runtime_1.jsx)("div", { style: { width: '32px', height: '32px', borderRadius: '50%', background: currentStep === step ? '#fff' : 'rgba(255,255,255,0.3)', color: currentStep === step ? '#0070f3' : '#fff', display: 'flex', alignItems: 'center', justifyContent: 'center', fontWeight: '600', fontSize: '14px' }, children: index + 1 }), (0, jsx_runtime_1.jsx)("span", { style: { marginLeft: '8px', fontSize: '14px' }, children: step.charAt(0).toUpperCase() + step.slice(1) })] }, step))) })] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'flex' }, children: [(0, jsx_runtime_1.jsxs)("div", { style: { flex: 1, padding: '32px' }, children: [currentStep === 'shipping' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: { margin: '0 0 24px 0', color: '#333' }, children: "Shipping Information" }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "First Name *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.firstName, onChange: (e) => handleInputChange('firstName', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.firstName ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "First name" }), errors.firstName && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.firstName }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Last Name *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.lastName, onChange: (e) => handleInputChange('lastName', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.lastName ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Last name" }), errors.lastName && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.lastName }))] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Email Address *" }), (0, jsx_runtime_1.jsx)("input", { type: "email", value: formData.email, onChange: (e) => handleInputChange('email', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.email ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "your@email.com" }), errors.email && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.email }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Address *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.address, onChange: (e) => handleInputChange('address', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.address ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Street address" }), errors.address && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.address }))] }), (0, jsx_runtime_1.jsxs)("div", { style: { display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '16px', marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "City *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.city, onChange: (e) => handleInputChange('city', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.city ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "City" }), errors.city && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.city }))] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Zip Code *" }), (0, jsx_runtime_1.jsx)("input", { type: "text", value: formData.zipCode, onChange: (e) => handleInputChange('zipCode', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.zipCode ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, placeholder: "Zip code" }), errors.zipCode && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.zipCode }))] })] }), (0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("label", { style: { display: 'block', marginBottom: '8px', fontWeight: '500' }, children: "Country *" }), (0, jsx_runtime_1.jsxs)("select", { value: formData.country, onChange: (e) => handleInputChange('country', e.target.value), style: { width: '100%', padding: '12px', border: `1px solid ${errors.country ? '#dc3545' : '#dee2e6'}`, borderRadius: '6px', fontSize: '16px' }, children: [(0, jsx_runtime_1.jsx)("option", { value: "US", children: "United States" }), (0, jsx_runtime_1.jsx)("option", { value: "CA", children: "Canada" }), (0, jsx_runtime_1.jsx)("option", { value: "GB", children: "United Kingdom" }), (0, jsx_runtime_1.jsx)("option", { value: "DE", children: "Germany" }), (0, jsx_runtime_1.jsx)("option", { value: "FR", children: "France" })] }), errors.country && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.country }))] }), shippingMethods.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("h4", { style: { margin: '0 0 16px 0', color: '#333' }, children: "Shipping Method" }), shippingMethods.map((method) => ((0, jsx_runtime_1.jsxs)("label", { style: { display: 'flex', alignItems: 'center', padding: '16px', border: `1px solid ${formData.shippingMethodId === method.id ? '#0070f3' : '#dee2e6'}`, borderRadius: '6px', marginBottom: '8px', cursor: 'pointer', background: formData.shippingMethodId === method.id ? '#f0f8ff' : '#fff' }, children: [(0, jsx_runtime_1.jsx)("input", { type: "radio", name: "shippingMethod", value: method.id, checked: formData.shippingMethodId === method.id, onChange: (e) => handleShippingMethodChange(e.target.value), style: { marginRight: '12px' } }), (0, jsx_runtime_1.jsxs)("div", { style: { flex: 1 }, children: [(0, jsx_runtime_1.jsx)("div", { style: { fontWeight: '500' }, children: method.name }), (0, jsx_runtime_1.jsxs)("div", { style: { color: '#666', fontSize: '14px' }, children: [method.estimatedDays, " \u2022 ", formatPrice(method.price)] })] })] }, method.id))), errors.shippingMethod && ((0, jsx_runtime_1.jsx)("div", { style: { color: '#dc3545', fontSize: '14px', marginTop: '4px' }, children: errors.shippingMethod }))] }))] })), currentStep === 'payment' && ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h3", { style: { margin: '0 0 24px 0', color: '#333' }, children: "Payment Information" }), paymentMethods.length > 0 && ((0, jsx_runtime_1.jsxs)("div", { style: { marginBottom: '24px' }, children: [(0, jsx_runtime_1.jsx)("h4", { style: { margin: '0 0 16px 0', color: '#333' }, children: "Payment Method" }), paymentMethods.map((method) => ((0, jsx_runtime_1.jsxs)("label", { style: { display: 'flex', alignItems: 'center', padding: '16px', border: `1px solid ${formData.paymentMethodId === method.id ? '#0070f3'