// cart.jsx — Cart drawer, checkout, confirmation const CopyChip = ({ value }) => { const [copied, setCopied] = useState(false); const onCopy = () => { const txt = value.replace(/\s+/g,''); if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(txt); } else { const t = document.createElement('textarea'); t.value = txt; document.body.appendChild(t); t.select(); try { document.execCommand('copy'); } catch(e){} document.body.removeChild(t); } setCopied(true); setTimeout(()=>setCopied(false), 1500); }; return ( ); }; const sendOrderToGoogleSheet = async (orderData) => { const url = window.SJ_DATA?.brand?.googleSheetsWebhook; if (!url) { console.warn('Google Sheets webhook URL is not configured'); return false; } const body = JSON.stringify(orderData); try { console.log('Sending Google Sheets webhook (cors / text/plain)...', url, orderData); const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body, keepalive: true, mode: 'cors', }); if (response.ok) { const text = await response.text(); console.log('Google Sheets webhook success:', text); try { const parsed = JSON.parse(text); if (parsed.success) return true; } catch (e) { return true; } } console.warn('Google Sheets webhook returned non-ok status:', response.status, response.statusText); } catch (err) { console.warn('Google Sheets webhook primary request failed. Retrying with no-cors...', err); try { await fetch(url, { method: 'POST', headers: { 'Content-Type': 'text/plain' }, body, keepalive: true, mode: 'no-cors', }); console.log('Google Sheets webhook sent via no-cors fallback'); return true; } catch (fallbackErr) { console.warn('Google Sheets webhook no-cors fallback failed:', fallbackErr); } if (navigator.sendBeacon) { try { const blob = new Blob([body], { type: 'text/plain' }); const beaconResult = navigator.sendBeacon(url, blob); console.log('Google Sheets beacon fallback result:', beaconResult); if (beaconResult) return true; } catch (beaconErr) { console.warn('Google Sheets beacon fallback failed:', beaconErr); } } } return false; }; const CartDrawer = ({ open, onClose, cart, updateQty, removeItem, goto }) => { const subtotal = cart.reduce((s,it)=>s + it.price * it.qty, 0); return ( <>
> ); }; const CheckoutPage = ({ cart, goto, onPlace }) => { const [pay, setPay] = useState('razorpay'); const [form, setForm] = useState({ name:'', phone:'', email:'', line1:'', line2:'', city:'', state:'', pin:'' }); useEffect(() => { if (window.fbq) { const total = cart.reduce((s, it) => s + ((it.price || 0) * (it.qty || 0)), 0); const ids = cart.map(it => String(it.id || it.sku || it.slug || "")); const count = cart.reduce((s, it) => s + (it.qty || 0), 0); window.fbq("track", "InitiateCheckout", { value: total, currency: "INR", content_ids: ids, content_type: "product", num_items: count }); } }, []); const [webhookStatus, setWebhookStatus] = useState(null); const [payProcessing, setPayProcessing] = useState(false); const upd = (k) => (e) => setForm(f => ({...f, [k]: e.target.value})); const subtotal = cart.reduce((s,it)=>s + it.price * it.qty, 0); const MIN_ORDER = 220; const belowMin = subtotal < MIN_ORDER; const codFee = pay === 'cod' ? 50 : 0; const partialPrepay = pay === 'cod' ? 100 : 0; const prepaidDiscount = pay === 'razorpay' ? Math.round(subtotal * 0.05) : 0; const total = subtotal + codFee - prepaidDiscount; const codBalance = total - partialPrepay; const submitOrder = async (e) => { e.preventDefault(); const orderId = 'SJ' + Date.now().toString().slice(-6); const lines = cart.map(it => `• ${it.name} (${it.weight}) × ${it.qty} — ${fmt(it.price * it.qty)}`).join('\n'); let payLabel = 'Paid Online via Razorpay'; if (pay === 'cod') { payLabel = `Cash on Delivery (₹50 COD fee)\n• Partial prepayment: ${fmt(partialPrepay)} (Paid Online via Razorpay)\n• Balance on delivery: ${fmt(codBalance)}`; } const msg = `*New Order — Shudh Jain* Order #${orderId} *Customer* ${form.name} ${form.phone}${form.email ? `\n${form.email}` : ''} *Shipping* ${form.line1}${form.line2 ? `, ${form.line2}` : ''} ${form.city}, ${form.state} — ${form.pin} *Items* ${lines} *Subtotal:* ${fmt(subtotal)}${codFee ? `\n*COD fee:* ${fmt(codFee)}` : ''} *Total:* ${fmt(total)} *Payment* ${payLabel} (Sent from shudhjain.com)`; const orderData = { orderId, createdAt: new Date().toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }), razorpayPaymentId: '', paymentStatus: 'pending', customer: { name: form.name, phone: form.phone, email: form.email, }, shipping: { line1: form.line1, line2: form.line2, city: form.city, state: form.state, pin: form.pin, }, payment: { method: pay, subtotal, codFee, total, partialPrepay, codBalance, }, items: cart.map(it => ({ name: it.name, weight: it.weight, qty: it.qty, unitPrice: it.price, total: it.price * it.qty })), source: window.location.href, }; if (pay === 'razorpay' || pay === 'cod') { if (!window.Razorpay) { alert("Razorpay payment gateway load nahi hua. Internet connection check karein."); return; } setPayProcessing(true); // 1. Send pending order details to Google Sheet immediately console.log('Sending pending order to Google Sheets first...'); await sendOrderToGoogleSheet(orderData); const rzpAmount = pay === 'cod' ? partialPrepay : total; const rzpOptions = { key: window.SJ_DATA?.brand?.razorpayKeyId || "rzp_test_yourKeyHere", amount: rzpAmount * 100, // amount in paise currency: "INR", name: "Shudh Jain", description: pay === 'cod' ? `COD Prepayment for Order #${orderId}` : `Order #${orderId}`, image: "assets/logo.jpeg", prefill: { name: form.name, contact: form.phone, email: form.email || "", }, notes: { orderId: orderId, address: `${form.line1}, ${form.city}, ${form.state} - ${form.pin}`, }, handler: async function (response) { console.log('Razorpay payment success:', response); const paymentId = response.razorpay_payment_id; const statusVal = pay === 'cod' ? 'partially_paid' : 'paid'; const orderDataPaid = { ...orderData, razorpayPaymentId: paymentId, paymentStatus: statusVal, payment: { ...orderData.payment, paymentId: paymentId, status: statusVal, } }; const webhookSaved = await sendOrderToGoogleSheet(orderDataPaid); setWebhookStatus(webhookSaved ? 'saved' : 'failed'); let paidMsg = msg; if (pay === 'cod') { paidMsg += `\n\n*Payment Details*\n• Status: PARTIALLY PAID (via Razorpay)\n• Razorpay Payment ID: ${paymentId}\n• Paid Online: ${fmt(partialPrepay)}\n• Balance on Delivery: ${fmt(codBalance)}`; } else { paidMsg += `\n\n*Payment Details*\n• Status: PAID (via Razorpay)\n• Razorpay Payment ID: ${paymentId}`; } const url = `https://wa.me/${window.SJ_DATA.brand.whatsapp}?text=${encodeURIComponent(paidMsg)}`; window.open(url, '_blank'); setPayProcessing(false); if (window.fbq) { const __ids = cart.map(it => String(it.id || it.sku || it.slug || "")); const __count = cart.reduce((s, it) => s + (it.qty || 0), 0); window.fbq("track", "Purchase", { value: rzpAmount, currency: "INR", content_ids: __ids, content_type: "product", num_items: __count }); } onPlace({ pay, total, subtotal, codFee, orderId, paymentId, ...form }); }, modal: { ondismiss: function () { console.log('Razorpay modal dismissed by user'); setPayProcessing(false); }, escape: true, confirm_close: true, }, theme: { color: "#1f5f3d", // Brand green color } }; console.log('Opening Razorpay with options:', { ...rzpOptions, key: '***hidden***' }); const rzp = new window.Razorpay(rzpOptions); rzp.on('payment.failed', function (response) { console.error('Razorpay payment failed:', response.error); setPayProcessing(false); alert("Payment fail ho gaya: " + (response.error?.description || "Unknown error") + "\n\nDobara try karein."); }); rzp.open(); } }; if (cart.length === 0) { return (Add a jar before you checkout.
Anil Jain · SBIScan QR with any UPI app — GPay, PhonePe, Paytm, BHIM. After paying, share the screenshot on WhatsApp.
Your order has been sent to us on WhatsApp. We'll confirm shortly and ship within 24 hours.{order && order.orderId ? <>
Order #{order.orderId}> : null}