// Main app — wires sections together, owns tweaks + checkout state.
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"finish": "brass",
"paperWarmth": 0,
"showProcess": true,
"showGallery": true,
"showReviews": true,
"showShipping": true
}/*EDITMODE-END*/;
function App() {
const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
const [order, setOrder] = React.useState(null);
// expose finish setter for the in-customizer swatches
window.__setFinish = (f) => setTweak('finish', f);
// apply paper warmth (subtle hue shift on cream paper)
React.useEffect(() => {
const w = tweaks.paperWarmth || 0;
const baseH = 80;
const h = baseH + w * 12;
const c = Math.max(0.005, 0.025 + w * 0.006);
document.documentElement.style.setProperty('--paper', `oklch(92% ${c} ${h})`);
document.documentElement.style.setProperty('--paper-2', `oklch(89% ${c} ${h})`);
document.documentElement.style.setProperty('--paper-3', `oklch(83% ${c + 0.005} ${h})`);
}, [tweaks.paperWarmth]);
const onCheckout = (o) => setOrder(o);
const onPay = (o) => {
// ============================================================
// STRIPE INTEGRATION — replace placeholders to go live
// ============================================================
// 1. Set your publishable key: const STRIPE_PK = "pk_live_xxx";
// 2. Create a Price in Stripe for "Classic Round – $99" and use its id:
// const PRICE_ID = "price_xxx";
// 3. Either call your backend to create a Checkout Session and redirect
// to session.url, or use Stripe.js redirectToCheckout (below).
// ============================================================
const STRIPE_PK = "pk_test_DEMO_REPLACE_ME";
const PRICE_ID = "price_DEMO_REPLACE_ME";
if (STRIPE_PK.startsWith("pk_test_DEMO") || !window.Stripe) {
// Demo path — open simulated Stripe Checkout page in a new tab
const amount = (o.total || 99) * 100;
const sim = encodeURIComponent(JSON.stringify({
product: 'Classic Round Pet Tag',
engraving: o.name,
phone: o.phone,
breed: o.breed,
finish: o.finish,
goldPlated: !!o.goldPlated,
amount,
}));
window.open(`stripe-sim.html?o=${sim}`, '_blank', 'noopener');
return;
}
// Live path — separate line items keep the upgrade tracked in Stripe.
const stripe = window.Stripe(STRIPE_PK);
const lineItems = [{ price: PRICE_ID, quantity: 1 }];
if (o.goldPlated) {
// const GOLD_PRICE_ID = "price_gold_xxx";
// lineItems.push({ price: GOLD_PRICE_ID, quantity: 1 });
}
stripe.redirectToCheckout({
lineItems,
mode: 'payment',
successUrl: window.location.origin + '/success.html',
cancelUrl: window.location.href,
clientReferenceId: JSON.stringify({
engraving: o.name, phone: o.phone, breed: o.breed,
finish: o.finish, goldPlated: !!o.goldPlated,
}),
});
};
return (
{tweaks.showProcess && }
{tweaks.showGallery && }
{tweaks.showReviews && }
{tweaks.showShipping && }
setOrder(null)} onPay={onPay} />
setTweak('finish', v)}
/>
setTweak('paperWarmth', v)}
/>
setTweak('showProcess', v)} />
setTweak('showGallery', v)} />
setTweak('showReviews', v)} />
setTweak('showShipping', v)} />
);
}
ReactDOM.createRoot(document.getElementById('root')).render();