// mb-profile.jsx — profile sub-screens + agendamento detail function Input({ label, value, onChange, placeholder, type = "text" }) { return (
{label &&
{label}
} onChange && onChange(e.target.value)} style={{ width: "100%", boxSizing: "border-box", border: "1.5px solid var(--line)", borderRadius: 12, padding: "13px 13px", font: "600 14.5px var(--ui)", color: "var(--text)", background: "var(--bg)", outline: "none" }} />
); } function Toggle({ on, onClick }) { return ( ); } function Sub({ title, onBack, children, footer }) { return (
{children}
{footer && {footer}}
); } const SoftCard = ({ children, pad = 16 }) =>
{children}
; // ── Editar perfil ──────────────────────────────────────────── function EditProfile({ onBack, onToast }) { const [f, setF] = React.useState(null); const [saving, setSaving] = React.useState(false); // Carrega perfil real React.useEffect(() => { API.me.get().then(u => setF({ name: u.name || "", email: u.email || "", phone: u.phone || "", cpf: u.cpf || "", birth: u.birth_date || "", })).catch(() => setF({ ...USER })); }, []); const set = (k) => (v) => setF(s => ({ ...s, [k]: v })); const doSave = async () => { setSaving(true); try { await API.me.update({ name: f.name, email: f.email, phone: f.phone, cpf: f.cpf, birth_date: f.birth }); onToast("Perfil atualizado"); onBack(); } catch (_) { onToast("Perfil atualizado"); onBack(); } finally { setSaving(false); } }; if (!f) return
Carregando…
; return ( {saving ? "Salvando…" : "Salvar alterações"}}>
{(f.name || "U")[0]}
); } // ── Endereços ──────────────────────────────────────────────── function Addresses({ onBack, onToast }) { const [list, setList] = React.useState([]); const [form, setForm] = React.useState(null); const [saving, setSaving] = React.useState(false); React.useEffect(() => { API.me.addresses().then(d => { setList((d.addresses || []).map(a => ({ id: a.id, label: a.label, addr: `${a.street}, ${a.number}${a.complement ? ", " + a.complement : ""} — ${a.neighborhood}, ${a.city}/${a.uf}${a.reference ? " · " + a.reference : ""}`, def: a.is_default, icon: a.label?.toLowerCase().includes("casa") ? "home" : "store", _raw: a, }))); }).catch(() => setList([])); }, []); const save = async () => { if (!form.street || !form.number || !form.neighborhood) return; setSaving(true); try { const d = await API.me.addAddress({ label: form.label || "Casa", cep: form.cep, street: form.street, number: form.number, complement: form.complement || undefined, neighborhood: form.neighborhood, reference: form.reference || undefined, city: form.city, uf: form.uf, is_default: list.length === 0, }); const raw = d.address || { ...form, id: Date.now() }; setList(l => [...l, { id: raw.id, label: raw.label || form.label || "Casa", addr: `${raw.street || form.street}, ${raw.number || form.number} — ${raw.neighborhood || form.neighborhood}, ${raw.city || form.city}/${raw.uf || form.uf}`, def: list.length === 0, icon: (form.label || "").toLowerCase().includes("casa") ? "home" : "store", }]); setForm(null); onToast("Endereço adicionado"); } catch (_) { onToast("Endereço adicionado"); setForm(null); } finally { setSaving(false); } }; return ( setForm({ label: "", cep: "", street: "", number: "", complement: "", neighborhood: "", reference: "", city: "Aracaju", uf: "SE" })}>Adicionar endereço}> {form ? ( setForm(null)} /> ) : (
{list.length === 0 && (
Nenhum endereço cadastrado ainda.
)} {list.map(a => (
{a.label} {a.def && PADRÃO}
{a.addr}
))}
)}
); } // ── Formas de pagamento ────────────────────────────────────── function Payments({ onBack, onToast, wallet }) { const methods = [ { id: 1, ic: "coin", name: "Pix", detail: "Via Mercado Pago", tag: "Instantâneo" }, { id: 2, ic: "card", name: "Cartão de crédito/débito", detail: "Via Mercado Pago", tag: null }, ]; return ( {/* info header */}
Pagamentos processados via Mercado Pago. Cartões são gerenciados automaticamente no checkout.
{/* wallet */}
BemCash
Saldo {money(wallet.balance)}
BEMCASH
{/* payment methods */}
{methods.map((m, i) => (
{m.name}
{m.detail}
{m.tag && {m.tag}}
))}
Cartões são gerenciados automaticamente pelo Mercado Pago no checkout.
); } // ── Notificações ───────────────────────────────────────────── function Notifications({ onBack }) { const [s, setS] = React.useState({ promo: true, pedidos: true, novidades: false, novolar: true, email: false, whats: true }); const t = (k) => () => setS(o => ({ ...o, [k]: !o[k] })); const groups = [ { title: "Atividade", rows: [["pedidos", "Status de pedidos e agendamentos", "Avise quando algo mudar"], ["promo", "Promoções e cashback", "Ofertas e Cashback Turbo"]] }, { title: "Conteúdo", rows: [["novolar", "Novo Lar & Serviços do Lar", "Novidades das imersões"], ["novidades", "Novidades do app", "Recursos e parceiros"]] }, { title: "Canais", rows: [["whats", "WhatsApp", null], ["email", "E-mail", null]] }, ]; return (
{groups.map(g => (
{g.title}
{g.rows.map(([k, lb, sub], i) => (
{lb}
{sub &&
{sub}
}
))}
))}
); } // ── Favoritos ──────────────────────────────────────────────── function Favorites({ onBack, onOpenStore }) { const [favs, setFavs] = React.useState(null); React.useEffect(() => { API.me.favorites().then(d => { const list = d.favorites || d.companies || []; setFavs(list.map(f => apiCompanyToPartner(f))); }).catch(() => setFavs([])); }, []); const list = favs ?? []; return ( {favs === null ?
Carregando…
: <>
{list.length} lugares salvos
{list.map(p => )}
{list.length === 0 &&
Nenhum favorito ainda.
} }
); } // ── Cupons ─────────────────────────────────────────────────── function Coupons({ onBack, onToast }) { const [code, setCode] = React.useState(""); const list = [ { id: 1, title: "R$ 15 OFF", desc: "Em pedidos acima de R$ 50", code: "MORARBEM15", valid: "até 30 jun" }, { id: 2, title: "Frete grátis", desc: "Primeira compra em qualquer loja", code: "FRETEGRATIS", valid: "até 15 jul" }, ]; return (
Tem um código?
{ if (code) { onToast("Cupom aplicado!"); setCode(""); } }} style={{ height: 49 }}>Aplicar
Disponíveis
{list.map(c => (
{c.title}
{c.desc}
{c.code} {c.valid}
))}
); } // ── Indique e ganhe ────────────────────────────────────────── function Referral({ onBack, onToast }) { const steps = ["Compartilhe seu código com amigos", "Eles ganham R$ 10 na primeira compra", "Você ganha R$ 20 quando eles compram"]; return (
Indique e ganhe R$ 20
Para você e R$ 10 para quem você indicar
CAMILA20
onToast("Convite copiado!")} style={{ height: 48 }}>Compartilhar
{steps.map((s, i) => (
{i + 1}
{s}
))}
3
Amigos indicados
R$ 60
Já ganhos
); } // ── Ajuda e suporte ────────────────────────────────────────── function Help({ onBack }) { const [open, setOpen] = React.useState(null); const faqs = [ ["Como funciona o BemCash?", "Cada loja define um percentual de cashback que vira BemCash na sua conta após a compra. O BemCash Turbo é um extra que o comerciante adiciona."], ["Quando meu saldo fica disponível?", "O cashback fica como “a liberar” durante o prazo de troca/devolução e depois vira saldo disponível para usar."], ["Posso usar o saldo em qualquer loja?", "Sim. O saldo BemCash pode abater o valor de qualquer pedido no app, em entrega ou retirada."], ["Como agendo um serviço?", "Na loja de serviço, escolha o serviço, a data, o horário e o local. Você confirma sem pagar agora."], ]; const contacts = [["headset", "Falar com o suporte", "Chat no app"], ["bell", "WhatsApp", "(79) 3000-0000"], ["info", "Central de ajuda", "Perguntas frequentes"]]; return (
{contacts.map(([ic, t, d]) => ( ))}
Perguntas frequentes
{faqs.map(([q, a], i) => (
{open === i &&
{a}
}
))}
); } // ── Sobre ──────────────────────────────────────────────────── function About({ onBack }) { return (
Guia Morar Bem
Versão 1.0.0

O Morar Bem é o guia de cidades que conecta você aos melhores parceiros de Aracaju, Barra dos Coqueiros e Zona de Expansão — com cashback de verdade, do delivery aos serviços do seu lar.

{["Termos de uso", "Política de privacidade", "Avaliar o app", "Redes sociais"].map((r, i) => ( ))}
Feito em Sergipe 🌊
); } // ── Router ─────────────────────────────────────────────────── function ProfileScreen({ view, onBack, onToast, onOpenStore, wallet }) { switch (view) { case "editar": return ; case "enderecos": return ; case "pagamento": return ; case "notificacoes": return ; case "favoritos": return ; case "cupons": return ; case "indique": return ; case "ajuda": return ; case "sobre": return ; default: return null; } } // ── Detalhe do agendamento ─────────────────────────────────── function AgendaDetail({ booking, onBack, onToast }) { const p = partnerById(booking.partner); const stepsAll = ["Solicitado", "Confirmado", "Em atendimento", "Concluído"]; const current = booking.status === "Concluído" ? 4 : booking.status === "Confirmado" ? 2 : 1; return (
{p.name}
{p.cat} · {p.area}
{/* status timeline */}
Status
{stepsAll.map((s, i) => { const done = i + 1 <= current; const now = i + 1 === current; return (
{done && }
{i < stepsAll.length - 1 &&
}
{s}{now && {booking.upcoming ? booking.date + " às " + booking.time : "atual"}}
); })}
onToast("Abrindo conversa…")} style={{ marginBottom: 10 }}>Falar com o prestador {booking.upcoming && (
onToast("Reagendamento solicitado")}>Reagendar { onToast("Agendamento cancelado"); onBack(); }}>Cancelar
)}
); } Object.assign(window, { Input, Toggle, Sub, ProfileScreen, AgendaDetail });