/* global React, window, fmt */ // ======================================================================= // DinnerDrawer — configurador do jantar Dia dos Namorados // // Fluxo: // 1. Pessoa abre o drawer (vindo do botão "Reservar o jantar") // 2. Escolhe número de pessoas (1–8) // 3. Para cada pessoa: harmonização (sim/não) + entrada + principal + sobremesa // 4. "Adicionar ao carrinho" → wcAddToCartDinner() → redireciona para /cart // // Produtos Woo necessários (IDs em ZUZU_JD_CONFIG.dinnerIds): // jantar_sem_harm — variation_id da variação "Sem harmonização" (R$ 210) // jantar_com_harm — variation_id da variação "Com harmonização de vinhos e espumantes" (R$ 295) // ======================================================================= const { useState: useSt, useEffect: useEf, useCallback: useCb } = React; /* ─── dados do cardápio ─────────────────────────────────────── */ const ENTRADAS = [ { id: "burrata", title: "Mini burrata", desc: "Uvas assadas com tomilho e azeite verde — acompanha focaccia da casa tostada no azeite.", }, { id: "rosbife", title: "Rosbife de filé mignon", desc: "Molho de dijon, chuva de alagoa, rúcula selvagem e azeite trufado — acompanha pão da casa tostado.", }, ]; const PRINCIPAIS = [ { id: "couve-flor", title: '"Filé" de couve-flor grelhada', desc: "Purê de cenoura aromático, creme de cogumelos e vinagrete de mexerica com coentro, tomate e cebola roxa.", veg: true, }, { id: "risonni", title: "Camarões salteados na manteiga de ervas", desc: "Com risonni de limão siciliano e toban djan.", }, { id: "ossobuco", title: "Ossobuco cozido ao vinho", desc: "Choux de mandioquinha recheada com purê de mandioquinha e queijo parmesão.", }, ]; const SOBREMESAS = [ { id: "torta", title: "Torta chocolatuda" }, { id: "pavlova", title: "Pavlova de inverno" }, ]; /* ─── preços (fácil de ajustar) ─────────────────────────────── */ const PRICE_SEM_HARM = 210; // por pessoa, sem harmonização const PRICE_COM_HARM = 295; // por pessoa, com harmonização (fácil de ajustar) /* ─── pessoa vazia ────────────────────────────────────────────── */ function emptyGuest() { return { harmonizado: false, entrada: null, principal: null, sobremesa: null }; } /* ─── helper WC AJAX ──────────────────────────────────────────── */ async function wcAddItem(productId, qty = 1, meta = {}, isVariation = false) { const cfg = window.ZUZU_JD_CONFIG || {}; const parentId = cfg.dinnerIds?.jantar_produto_pai || productId; const ajaxUrl = (window.wc_add_to_cart_params?.wc_ajax_url || "/?wc-ajax=%%endpoint%%") .replace("%%endpoint%%", "add_to_cart"); const body = new URLSearchParams({ product_id: isVariation ? parentId : productId, quantity: qty, }); if (isVariation) { body.append("variation_id", productId); const v = meta.attribute_harmonizacao || ""; if (v) { body.append("attribute_harmonizacao", v); } } Object.entries(meta).forEach(([k, v]) => { if (!k.startsWith("attribute_")) body.append(k, v); }); try { const res = await fetch(ajaxUrl, { method : "POST", headers: { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8" }, body : body.toString(), }); const json = await res.json(); console.log("WC add_to_cart response:", json); console.log("WC add_to_cart body sent:", body.toString()); return !json.error; } catch (err) { console.error("WC add_to_cart error:", err); return false; } } /* ─── sub-componente: seletor de prato ───────────────────────── */ function DishPicker({ label, options, value, onChange }) { return (
{label}
{options.map((opt) => { const sel = value === opt.id; return ( ); })}
); } /* ─── lê reservation_id da URL (vindo do sistema de reservas) ── */ function getReservationIdFromUrl() { const params = new URLSearchParams(window.location.search); const rid = params.get("rid"); return rid ? parseInt(rid, 10) : null; } function DinnerDrawer({ open, onClose }) { const hasRid = !!getReservationIdFromUrl(); const [step, setStep] = useSt(1); const [count, setCount] = useSt(hasRid ? 0 : 2); const [guests, setGuests] = useSt(hasRid ? [] : [emptyGuest(), emptyGuest()]); const [active, setActive] = useSt(0); const [loading, setLoading] = useSt(false); const [error, setError] = useSt(null); // Reserva vinculada — número de pessoas travado pelo rid da URL const [reservation, setReservation] = useSt(null); const [resLoading, setResLoading] = useSt(false); const [resError, setResError] = useSt(null); // Ao abrir: busca dados da reserva e trava o número de pessoas useEf(() => { if (!open) { setTimeout(() => { setStep(1); setCount(2); setGuests([emptyGuest(), emptyGuest()]); setActive(0); setError(null); setReservation(null); setResError(null); }, 300); return; } const rid = getReservationIdFromUrl(); if (!rid) return; setResLoading(true); setResError(null); const ajaxUrl = window.ZUZU_JD_CONFIG?.ajaxUrl || '/wp-admin/admin-ajax.php'; console.log('[DinnerDrawer] fetching guests for rid:', rid, 'ajaxUrl:', ajaxUrl); fetch(`${ajaxUrl}?action=zuzu_jd_get_reservation_guests&rid=${rid}`) .then((r) => r.json()) .then((json) => { console.log('[DinnerDrawer] guests response:', json); if (json.success && json.data) { const n = json.data.guests_count; setReservation(json.data); setCount(n); setGuests(Array.from({ length: n }, emptyGuest)); } else { setResError('Não foi possível carregar os dados da reserva.'); } }) .catch((e) => { console.error('[DinnerDrawer] fetch error:', e); setResError('Erro ao buscar a reserva.'); }) .finally(() => setResLoading(false)); }, [open]); function updateCount(n) { setCount(n); setGuests((prev) => { if (n > prev.length) return [...prev, ...Array.from({ length: n - prev.length }, emptyGuest)]; return prev.slice(0, n); }); } function updateGuest(idx, field, val) { setGuests((prev) => prev.map((g, i) => i === idx ? { ...g, [field]: val } : g)); } function guestComplete(g) { return g.entrada && g.principal && g.sobremesa; } const allComplete = guests.every(guestComplete); const subtotal = guests.reduce((sum, g) => { return sum + (g.harmonizado ? PRICE_COM_HARM : PRICE_SEM_HARM); }, 0); function addToCart() { setLoading(true); setError(null); const cfg = window.ZUZU_JD_CONFIG || {}; const dinnerIds = cfg.dinnerIds || {}; const varSemHarm = dinnerIds.jantar_sem_harm; const varComHarm = dinnerIds.jantar_com_harm; const parentId = dinnerIds.jantar_produto_pai; if (!varSemHarm || !varComHarm || !parentId) { setError("Produto não configurado. Fale com a gente pelo WhatsApp."); setLoading(false); return; } const reservationId = getReservationIdFromUrl(); const semHarmCount = guests.filter((g) => !g.harmonizado).length; const comHarmCount = guests.filter((g) => g.harmonizado).length; // Salva dados do jantar no sessionStorage para o checkout usar const allGuestData = guests.map((g, i) => ({ pessoa : i + 1, harmonizado : g.harmonizado, entrada : ENTRADAS.find((e) => e.id === g.entrada)?.title || "—", principal : PRINCIPAIS.find((p) => p.id === g.principal)?.title || "—", sobremesa : SOBREMESAS.find((s) => s.id === g.sobremesa)?.title || "—", })); sessionStorage.setItem("zuzu_jd_dinner_guests", JSON.stringify(allGuestData)); if (reservationId) sessionStorage.setItem("zuzu_jd_reservation_id", String(reservationId)); // Usa URL direta — mais confiável que AJAX para produtos variáveis const base = window.location.origin; const checkout = cfg.wcCheckoutUrl || (base + "/checkout/"); const semVal = encodeURIComponent("Sem harmonização"); const comVal = encodeURIComponent("Com harmonização de vinhos e espumantes"); const ridParam = reservationId ? "&rid=" + reservationId : ""; let addUrl; if (comHarmCount > 0 && semHarmCount === 0) { // Todos com harmonização addUrl = base + "/?add-to-cart=" + parentId + "&variation_id=" + varComHarm + "&quantity=" + comHarmCount + "&attribute_harmonizacao=" + comVal + ridParam + "&checkout=1"; } else if (semHarmCount > 0 && comHarmCount === 0) { // Todos sem harmonização addUrl = base + "/?add-to-cart=" + parentId + "&variation_id=" + varSemHarm + "&quantity=" + semHarmCount + "&attribute_harmonizacao=" + semVal + ridParam + "&checkout=1"; } else { // Mistos — passa os dois grupos via parâmetro extra que o PHP vai processar // O hook zuzu_jd_handle_mixed_cart lê zuzu_jd_add2 e adiciona o segundo grupo addUrl = base + "/?add-to-cart=" + parentId + "&variation_id=" + varSemHarm + "&quantity=" + semHarmCount + "&attribute_harmonizacao=" + semVal + "&zuzu_jd_add2=" + varComHarm + "&zuzu_jd_add2_qty=" + comHarmCount + "&zuzu_jd_add2_attr=" + comVal + ridParam + "&checkout=1"; } window.location.href = addUrl; } /* ── render ── */ const drawerStyle = { position : "fixed", top : 0, right : open ? 0 : "-100%", width : "min(460px, 100vw)", height : "100dvh", background : "var(--paper)", boxShadow : "-4px 0 40px rgba(0,0,0,0.12)", display : "flex", flexDirection : "column", zIndex : 1100, transition : "right .3s cubic-bezier(.4,0,.2,1)", overflowY : "auto", }; const scrimStyle = { position : "fixed", inset : 0, background : "rgba(0,0,0,0.35)", zIndex : 1099, opacity : open ? 1 : 0, pointerEvents : open ? "auto" : "none", transition : "opacity .3s", }; return ( <>
); } Object.assign(window, { DinnerDrawer, DINNER_MENU: { ENTRADAS, PRINCIPAIS, SOBREMESAS, PRICE_SEM_HARM, PRICE_COM_HARM } });