// mb-account.jsx — Carteira, Minhas Compras, Perfil function EmBreveOverlay({ icon, title, text }) { return (
{title}
{text}
Em breve
); } function CarteiraScreen({ wallet, onOpenCashback, featureEnabled }) { if (!featureEnabled) return (
); return (

BemCash

{/* balance card */}
Saldo disponível
{money(wallet.balance)}
{money(wallet.pending)} a liberar
{/* actions */}
{[["coin", "Usar saldo"], ["receipt", "Extrato"], ["headset", "Ajuda"]].map(([ic, lb]) => ( ))}
{/* how cashback works */} {/* movements */}
Movimentações
{wallet.movements.map((m, i) => (
{m.label}
{m.date}
{m.value < 0 ? "− " : "+"}{money(Math.abs(m.value))}
))}
); } // Cashback explainer (sheet content) function CashbackInfo() { const items = [ { ic: "coin", t: "BemCash", d: "Cada loja define um percentual de cashback nos produtos. Ao comprar, esse valor vira BemCash na sua conta." }, { ic: "bolt", t: "Cashback Turbo", d: "Um percentual extra que o comerciante turbina para destacar a loja. Esse adicional sai da carteira digital exclusiva do comerciante." }, { ic: "wallet", t: "Onde usar", d: "Use o saldo acumulado para abater o valor de qualquer pedido dentro do app, em entrega ou retirada." }, { ic: "clock", t: "Liberação", d: "O cashback fica como “a liberar” durante o prazo de troca/devolução e depois vira saldo disponível." }, ]; return (
Compre e receba de volta
BemCash + Turbo direto na sua conta
{items.map(it => (
{it.t}
{it.d}
))}
); } // ── Minhas Compras ─────────────────────────────────────────── function StatusChip({ label, accent, warn }) { const bg = warn ? "#FEF3E2" : accent ? "var(--accent-50)" : "var(--bg)"; const color = warn ? "#B5751A" : accent ? "var(--accent)" : "var(--muted)"; return {label}; } const ORDER_STEPS = [ { status: "aguardando_pagamento", label: "Aguardando pagamento", icon: "coin" }, { status: "pendente", label: "Pedido recebido", icon: "receipt" }, { status: "em_preparo", label: "Em preparo", icon: "bag" }, { status: "saiu_para_entrega", label: "Saiu para entrega", icon: "bike" }, { status: "entregue", label: "Entregue", icon: "check" }, { status: "concluido", label: "Finalizado", icon: "coin" }, ]; const APPT_STEPS = [ { status: "solicitado", label: "Agendamento recebido", icon: "clock" }, { status: "confirmado", label: "Confirmado", icon: "check" }, { status: "em_atendimento", label: "Em atendimento", icon: "health" }, { status: "concluido", label: "Finalizado", icon: "coin" }, ]; function StatusTimeline({ steps, currentStatus }) { const currentIdx = steps.findIndex(s => s.status === currentStatus); return (
{steps.map((step, i) => { const done = i < currentIdx; const active = i === currentIdx; const future = i > currentIdx; return (
{i < steps.length - 1 &&
}
{step.label}
{active &&
agora
}
); })}
); } function OrderDetail({ order, onBack, onReview, onReorder }) { const raw = order._raw || {}; const shortId = (raw.id || order.id || "").slice(0, 8); const p = partnerById(order.partner) || { name: raw.company_name || "Parceiro", seg: "comer" }; const canReview = raw.status === "concluido" || raw.status === "entregue"; const awaitingPayment = raw.status === "aguardando_pagamento"; const checkoutUrl = order.checkoutUrl || raw.mp_checkout_url; const items = raw.items || []; return (
{/* partner */}
{p.name}
{order.date} · {order.mode}
{/* timeline */}
Acompanhamento
{/* items */} {items.length > 0 && (
Itens
{items.map((it, i) => (
{it.quantity}x {it.name} {money((parseFloat(it.unit_price) || 0) * (it.quantity || 1))}
))}
)} {/* totals */}
{raw.subtotal != null &&
Subtotal{money(parseFloat(raw.subtotal) || 0)}
} {raw.taxa_entrega != null &&
Entrega{parseFloat(raw.taxa_entrega) === 0 ? "Grátis" : money(parseFloat(raw.taxa_entrega) || 0)}
}
Total{money(order.total)}
{/* Awaiting payment — banner + action button */} {awaitingPayment && (
Pagamento pendente
Seu pedido foi reservado mas ainda não foi pago. Conclua o pagamento para confirmar.
{checkoutUrl ? { window.location.href = checkoutUrl; }}>Ir para o Mercado Pago → :
Link de pagamento indisponível. Entre em contato com o suporte.
}
)}
Pedir de novo {canReview && Avaliar}
); } function ApptDetail({ appt, onBack, onReview }) { const raw = appt._raw || {}; const p = partnerById(appt.partner) || { name: raw.company_name || "Prestador", seg: "saude" }; const canReview = raw.status === "concluido"; return (
{/* partner */}
{p.name}
{appt.service}
{/* timeline */}
Acompanhamento
{/* details */}
{appt.date} · {appt.time}
{appt.local === "loja" ? "No estabelecimento" : "Na sua casa"}
{raw.service_price != null && (
{money(parseFloat(raw.service_price) || 0)}
)}
{canReview && ( Avaliar atendimento )}
); } function ComprasScreen({ onReview, onReorder, onAgendaDetail, featureEnabled }) { if (!featureEnabled) return (
); const [seg, setSeg] = React.useState("pedidos"); const segs = [["pedidos", "Pedidos"], ["agenda", "Agendamentos"], ["contatos", "Contatos"]]; const [orderDetail, setOrderDetail] = React.useState(null); const [apptDetail, setApptDetail] = React.useState(null); // Dados reais da API const [apiOrders, setApiOrders] = React.useState(null); const [apiAppts, setApiAppts] = React.useState(null); const [apiLeads, setApiLeads] = React.useState(null); const [loading, setLoading] = React.useState(false); React.useEffect(() => { setLoading(true); Promise.all([ API.orders.list().then(d => setApiOrders((d.orders || []).map(apiOrderToMock))).catch(() => {}), API.appointments.list().then(d => setApiAppts((d.appointments || []).map(apiApptToMock))).catch(() => {}), API.leads.list().then(d => setApiLeads(d.leads || [])).catch(() => {}), ]).finally(() => setLoading(false)); }, []); const orders = apiOrders || ORDERS; const appts = apiAppts || AGENDAMENTOS; const leads = apiLeads || LEADS; return (

Minhas Compras

{/* segmented */}
{segs.map(([id, lb]) => ( ))}
{loading &&
Carregando…
}
{/* PEDIDOS */} {seg === "pedidos" && orders.map(o => { const p = partnerById(o.partner) || { name: o._raw?.company_name || "Parceiro", seg: "comer" }; const toRate = !o.rated; const isPendingPayment = o.rawStatus === "aguardando_pagamento"; return (
setOrderDetail(o)} style={{ background: "var(--surface)", borderRadius: 18, overflow: "hidden", boxShadow: "0 3px 12px rgba(16,18,45,.05)", cursor: "pointer" }}> {isPendingPayment && (
Pagamento pendente — toque para continuar
)}
{p.name}
{o.items.join(", ")}
{o.date}{o.mode}{money(o.total)}
{o.rated &&
}
+{money(o.cashback + o.turbo)} de cashback{o.turbo > 0 ? " (com Turbo)" : ""}
); })} {/* AGENDAMENTOS */} {seg === "agenda" && appts.map(a => { const p = partnerById(a.partner) || { name: a._raw?.company_name || "Prestador", seg: "saude" }; const toRate = a.status === "Concluído" && !a.rated; return (
setApptDetail(a)} style={{ background: "var(--surface)", borderRadius: 18, overflow: "hidden", boxShadow: "0 3px 12px rgba(16,18,45,.05)", cursor: "pointer" }}>
{p.name}
{a.service}
{a.date} · {a.time} {a.local === "loja" ? "No local" : "Na sua casa"}
{a.rated &&
}
{a.upcoming && (
onReorder(a.partner)} style={{ flex: 1, height: 44 }}>Reagendar onAgendaDetail(a)} style={{ flex: 1, height: 44 }}>Ver detalhes
)}
); })} {/* CONTATOS */} {seg === "contatos" && leads.map(l => { const p = partnerById(l.company_id) || { name: l.company_name || "Parceiro", seg: "morar" }; return (
{p.name}
{l.listing_title || l.title || ""}
{l.channel === "whatsapp" ? "WhatsApp" : "Ligação"} · {l.date || new Date(l.created_at).toLocaleDateString("pt-BR", { day: "2-digit", month: "short" })}
onReorder(l.partner)} style={{ height: 44 }}>Ver na vitrine
); })}
{orderDetail && ( setOrderDetail(null)} onReview={() => { setOrderDetail(null); onReview(orderDetail.partner, orderDetail.mode); }} onReorder={() => { setOrderDetail(null); onReorder(orderDetail.partner); }} /> )} {apptDetail && ( setApptDetail(null)} onReview={() => { setApptDetail(null); onReview(apptDetail.partner, "agenda"); }} /> )}
); } // ── Perfil ─────────────────────────────────────────────────── function PerfilEmBreveModal({ icon, title, onClose }) { return (
{ if (e.target === e.currentTarget) onClose(); }}>
{title}
Este recurso estará disponível em breve.
Enquanto isso, explore os parceiros disponíveis na aba Descobrir e aproveite as melhores opções da sua cidade!
Em breve
); } function PerfilScreen({ wallet, user, onOpenCarteira, onOpen, onLogout, onOpenClub, clubMember }) { const [addrCount, setAddrCount] = React.useState(null); const [favCount, setFavCount] = React.useState(null); const [canInstall, setCanInstall] = React.useState(false); const [showIosHint, setShowIosHint] = React.useState(false); const [emBreve, setEmBreve] = React.useState(null); // { icon, title } React.useEffect(() => { API.me.addresses().then(d => setAddrCount((d.addresses || []).length)).catch(() => {}); API.me.favorites().then(d => setFavCount((d.favorites || d.companies || []).length)).catch(() => {}); // PWA: verifica se pode instalar (Android/Chrome) if (window.mbCanInstallPWA && window.mbCanInstallPWA()) setCanInstall(true); const onInstallable = () => setCanInstall(true); const onInstalled = () => setCanInstall(false); window.addEventListener('pwa-installable', onInstallable); window.addEventListener('pwa-installed', onInstalled); // iOS: mostra dica se não estiver em modo standalone const isIos = /iphone|ipad|ipod/i.test(navigator.userAgent); if (isIos && window.mbIsStandalone && !window.mbIsStandalone()) setShowIosHint(true); return () => { window.removeEventListener('pwa-installable', onInstallable); window.removeEventListener('pwa-installed', onInstalled); }; }, []); const rows = [ ["pin", "Endereços", addrCount != null && addrCount > 0 ? `${addrCount} endereço${addrCount !== 1 ? "s" : ""}` : null, "enderecos"], ["card", "Formas de pagamento", "Pix · Cartão MP", "pagamento"], ["heart", "Favoritos", favCount != null && favCount > 0 ? `${favCount} favoritado${favCount !== 1 ? "s" : ""}` : null, "favoritos"], ["bell", "Notificações", null, "notificacoes"], ["ticket", "Cupons", null, "cupons"], ["gift", "Indique e ganhe", null, "indique"], ["headset", "Ajuda e suporte", null, "ajuda"], ["info", "Sobre o Morar Bem", null, "sobre"], ]; const displayName = user?.name || "Usuário"; const initial = displayName[0].toUpperCase(); const since = user?.created_at ? new Date(user.created_at).getFullYear() : new Date().getFullYear(); return ( <>
{initial}

{displayName}

{user?.region_name || "Aracaju"} · Cliente desde {since}
onOpen("editar")} />
{/* wallet quick */} {/* clube */}
{rows.map(([ic, lb, val, id], i) => { const emBreveIds = { cupons: { icon: "ticket", title: "Cupons" }, indique: { icon: "gift", title: "Indique e Ganhe" } }; const isEmBreve = !!emBreveIds[id]; return ( ); })}
{/* Instalar PWA — Android/Chrome */} {canInstall && ( )} {/* Instalar PWA — iOS / Safari */} {showIosHint && (
Instalar o app no iPhone
Toque em Compartilhar () no Safari e depois em "Adicionar à Tela de Início".
)}
Guia Morar Bem · v1.0
{emBreve && setEmBreve(null)} />} ); } Object.assign(window, { CarteiraScreen, CashbackInfo, ComprasScreen, PerfilScreen, OrderDetail, ApptDetail, StatusTimeline });