// product-detail.jsx — Página de detalhe do produto com gráfico de histórico
const { useState: useStatePD, useMemo: useMemoPD } = React;
function ProductDetail({ product, onBack, onProduct }) {
const [period, setPeriod] = useStatePD("180");
const [showAlert, setShowAlert] = useStatePD(false);
const [target, setTarget] = useStatePD(Math.round(product.lowestEver * 0.97));
// Gera ofertas multi-loja a partir do título do produto
const multiOffers = useMemoPD(() => {
const t = encodeURIComponent(product.title);
const td = encodeURIComponent(product.title.replace(/ /g, "-"));
const stores = [
{ store: "amz", storeName: "Amazon", price: product.current, pix: Math.round(product.current * 0.95), ship: "Prime grátis", link: `https://www.amazon.com.br/s?k=${t}&tag=yetishopping-20` },
{ store: "ml", storeName: "Mercado Livre", price: Math.round(product.current*1.03), pix: Math.round(product.current*1.03*0.95), ship: "Ver condições", link: `https://lista.mercadolivre.com.br/${td}` },
{ store: "kbm", storeName: "Kabum", price: Math.round(product.current*0.98), pix: Math.round(product.current*0.98*0.92), ship: "Frete grátis", link: `https://www.kabum.com.br/busca/${td}` },
{ store: "mglu", storeName: "Magalu", price: Math.round(product.current*1.01), pix: Math.round(product.current*1.01*0.95), ship: "Frete grátis", link: `https://www.magazineluiza.com.br/busca/${td}/` },
{ store: "shp", storeName: "Shopee", price: Math.round(product.current*0.96), pix: Math.round(product.current*0.96*0.95), ship: "Grátis", link: `https://shopee.com.br/search?keyword=${t}` },
].sort((a, b) => a.price - b.price);
return stores;
}, [product]);
const sortedOffers = multiOffers;
const cheapest = sortedOffers[0];
const savedFromBase = product.base - product.current;
const savedPct = Math.round((savedFromBase / product.base) * 100);
const isAtLow = product.current <= product.lowestEver * 1.03;
// Produtos relacionados: buscados em tempo real pela categoria via YetiAPI
const [relatedProducts, setRelatedProducts] = React.useState([]);
React.useEffect(() => {
const cat = CATEGORIES?.find(c => c.id === product.cat);
const kw = cat?.keyword || product.category || "oferta";
if (window.YetiAPI) {
YetiAPI.search(kw, { size: 8 })
.then(results => setRelatedProducts(results.filter(p => p.id !== product.id).slice(0, 4)))
.catch(() => setRelatedProducts([]));
}
}, [product.id]);
return (
{/* Breadcrumb */}
›
{product.category}
›
{product.title}
{/* Top section: image + main info */}
{/* Image gallery */}
{savedPct >= 10 && (
−{savedPct}%
)}
{[0, 1, 2, 3].map(i => (
))}
{/* Info */}
{product.brand}·{product.category}
{product.title}
{product.rating && (
★★★★★
{product.rating}
{product.reviews && ({product.reviews.toLocaleString("pt-BR")} avaliações)}
)}
{product.rating &&
|}
Comparando {product.offers?.length ?? 1} {(product.offers?.length ?? 1) === 1 ? "loja" : "lojas"}
{/* Big price panel */}
Melhor preço hoje ·
{fmtBRL(cheapest.price)}
{fmtBRL(product.base)}
{fmtBRL(cheapest.pix)} no Pix
ou 12x de {fmtBRL2(cheapest.price / 12)}
{/* Multi-lojas: busca o produto em cada loja */}
{[
{ name: "Amazon", color: "#FF9900", text: "#131A22", url: `https://www.amazon.com.br/s?k=${encodeURIComponent(product.title)}&tag=yetishopping-20` },
{ name: "Mercado Livre",color: "#FFE600", text: "#2D3277", url: `https://lista.mercadolivre.com.br/${encodeURIComponent(product.title.replace(/ /g,"-"))}` },
{ name: "Kabum", color: "#FF6500", text: "#FFFFFF", url: `https://www.kabum.com.br/busca/${encodeURIComponent(product.title.replace(/ /g,"-"))}` },
{ name: "Magalu", color: "#0086FF", text: "#FFFFFF", url: `https://www.magazineluiza.com.br/busca/${encodeURIComponent(product.title.replace(/ /g,"-"))}/` },
{ name: "Shopee", color: "#EE4D2D", text: "#FFFFFF", url: `https://shopee.com.br/search?keyword=${encodeURIComponent(product.title)}` },
].map((s, i) => (
Buscar no {s.name}
→
))}
{/* Verdict */}
{isAtLow ? "🤙" : "🤔"}
{isAtLow ? "Veredito do Yeti: COMPRA!" : "Veredito do Yeti: Pode esperar"}
{isAtLow
? `Tá no menor preço dos últimos ${period === "all" ? "180" : period} dias. Bora!`
: `Já esteve a ${fmtBRL(product.lowestEver)} (${new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "short" }).format(product.lowestDate)}). Vale esperar uma queda.`}
{/* Alert form expanding */}
{showAlert && (
Me avise quando o preço cair para:
setTarget(parseInt(e.target.value || "0", 10))}
style={{ width: "100%", border: "1.5px solid #0E2A47", borderRadius: 10, padding: "10px 14px 10px 36px", fontSize: 16, fontWeight: 700, fontFamily: "inherit", color: "#0E2A47", outline: "none", fontVariantNumeric: "tabular-nums" }}/>
R$
setTarget(parseInt(e.target.value, 10))} style={{ flex: 2 }}/>
Menor histórico: {fmtBRL(product.lowestEver)}
Atual: {fmtBRL(product.current)}
)}
{/* Price chart section */}
Histórico de preço
Evolução em {period === "all" ? "180 dias" : `${period} dias`}
{[
{ v: "30", l: "30d" }, { v: "90", l: "90d" }, { v: "180", l: "180d" }, { v: "all", l: "Tudo" },
].map(opt => (
))}
{[
{ label: "Preço atual", value: fmtBRL(product.current), color: "#FFC72C", sub: "agora mesmo" },
{ label: "Menor histórico", value: fmtBRL(product.lowestEver), color: "#1FB3A6", sub: new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "short" }).format(product.lowestDate) },
{ label: "Maior histórico", value: fmtBRL(product.highestEver), color: "#FF6B5C", sub: new Intl.DateTimeFormat("pt-BR", { day: "2-digit", month: "short" }).format(product.highestDate) },
{ label: "Preço médio", value: fmtBRL(Math.round(product.history.reduce((a, b) => a + b.p, 0) / product.history.length)), color: "#3A4A5E", sub: "últimos 180d" },
].map((s, i) => (
{s.label}
{s.value}
{s.sub}
))}
{/* Offers comparison table */}
Comparação
Mesmo produto em {product.offers.length} lojas
| Loja |
Preço |
Pix |
Parcelado |
Frete |
Ação |
{sortedOffers.map((o, i) => (
|
{i === 0 && ● MELHOR PREÇO}
|
{fmtBRL(o.price)}
|
{fmtBRL(o.pix)}
|
12× {fmtBRL2(o.price / 12)}
|
{o.ship} |
Buscar →
|
))}
{/* Specs + related side by side */}
Sobre o produto
Informações
{(product.spec || [
`Categoria: ${product.category || "Geral"}`,
`Loja: ${product.storeName || product.brand || "Parceiro"}`,
`Menor histórico nos últimos 180 dias: ${fmtBRL(product.lowestEver)}`,
`Maior histórico: ${fmtBRL(product.highestEver)}`,
"Preços atualizados em tempo real",
]).map((s, i) => (
-
✓
{s}
))}
Relacionados
O Yeti também vigia
{relatedProducts.slice(0, 4).map(p => (
))}
);
}
Object.assign(window, { ProductDetail });