/* MIL GRAU RP — Shared UI Components */ const { useState, useEffect, useRef, useMemo } = React; // ===== HEADER ===== function Header({ cartCount, onCartClick, onNav, currentPage, onSupport, searchQuery, onSearchChange, onSearchSubmit }) { return (
🎁 PRIMEIRA COMPRA: Use o cupom BEMVINDOMG e ganhe 10% OFF
onNav('home')} style={{cursor:'pointer'}}> MIL GRAU RP
{ e.preventDefault(); if ((searchQuery || '').trim()) onSearchSubmit(searchQuery); }}> onSearchChange(e.target.value)} /> {searchQuery ? ( ) : null}
); } // ===== FOOTER ===== function Footer({ onNav }) { return ( ); } // ===== PRODUCT THUMB ===== function ProductThumb({ p, big = false }) { return (
{/* Decorative pattern overlay */}
); } // ===== PRODUCT CARD ===== function ProductCard({ p, idx = 0, onClick, onAdd }) { return (
{p.bestseller &&
MAIS VENDIDO
}
{p.discount && -{p.discount}%} {p.stock} em estoque {p.popular && !p.bestseller && POPULAR}
{p.cat}
{p.name}
{p.oldPrice && {window.MGRP_DATA.fmtBRL(p.oldPrice)}} {window.MGRP_DATA.fmtBRL(p.price)}
À vista no Pix
); } // ===== TOAST SYSTEM ===== function ToastStack({ toasts }) { return (
{toasts.map(t => (
{t.title}
{t.msg}
))}
); } // ===== CART DRAWER ===== function CartDrawer({ open, items, onClose, onQty, onRemove, onCheckout }) { if (!open) return null; const total = items.reduce((s, i) => s + i.price * i.qty, 0); return ( <>

Seu carrinho ({items.length})

{items.length === 0 ? (

Seu carrinho está vazio

Adicione produtos da loja para continuar.

) : items.map(item => (
{item.name}
{window.MGRP_DATA.fmtBRL(item.price * item.qty)}
{item.qty}
))}
{items.length > 0 && (
Valor total {window.MGRP_DATA.fmtBRL(total)}
)}
); } // ===== SUPPORT MODAL (channels picker) ===== function SupportModal({ open, onClose }) { if (!open) return null; const channels = [ { name: 'Discord', sub: 'Comunidade oficial · 100k+ membros', icon: 'discord', color: '#5865F2', href: 'https://discord.gg/milgrau' }, { name: 'Instagram', sub: '@milgraurp', icon: 'instagram', color: '#E1306C', href: 'https://www.instagram.com/milgraurp/' }, { name: 'WhatsApp', sub: '(47) 99136-0760 · Resposta em até 1h', icon: 'whatsapp', color: '#25D366', href: 'https://wa.me/5547991360760' }, { name: 'TikTok', sub: '@1000graurp', icon: 'tiktok', color: '#000', href: 'https://www.tiktok.com/@1000graurp' }, ]; return (
e.stopPropagation()}>

Canais de atendimento

Escolha o canal mais conveniente. Nosso time responde em minutos.

{channels.map(c => (
{c.name}
{c.sub}
))}
); } // ===== CHAT WIDGET (Crisp-style live chat) ===== function ChatWidget({ open, onClose, onOpen }) { const [messages, setMessages] = useState([ { from: 'bot', text: 'Olá! Como posso ajudar você? 😊', t: Date.now() } ]); const [input, setInput] = useState(''); const [showPhone, setShowPhone] = useState(true); const [phoneCollected, setPhoneCollected] = useState(false); const [phone, setPhone] = useState(''); const [phoneInputOpen, setPhoneInputOpen] = useState(false); const [typing, setTyping] = useState(false); const [unread, setUnread] = useState(0); const bodyRef = useRef(); useEffect(() => { if (bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight; }, [messages, typing]); useEffect(() => { if (open) setUnread(0); }, [open]); const send = async (text) => { if (!text || !text.trim()) return; const userMsg = { from: 'user', text: text.trim(), t: Date.now() }; setMessages(prev => [...prev, userMsg]); setInput(''); setTyping(true); // Pseudo-random delay then reply let reply = ''; try { const claude = window.claude; if (claude && claude.complete) { const sys = `Você é o atendente da loja virtual MIL GRAU RP, servidor brasileiro de FiveM Roleplay. Responda em português, curto (máximo 2 frases), simpático e direto. Conhecimentos: temos passes (Inicial R$47,90, Premium R$77,90, Lendário R$247,90), pacotes de dinheiro (50k/100k/250k/500k), VIPs (Bronze/Prata/Ouro/Diamante/Mensal), MG Coins, combos, especiais. Cupom BEMVINDOMG dá 10% OFF na primeira compra. Pagamentos via PIX, MercadoPago e PayPal. Entrega imediata após pagamento. Suporte 24/7 no Discord (discord.gg/milgrau) e WhatsApp (47 99136-0760). Para dúvidas técnicas detalhadas, recomende canais como Discord ou WhatsApp.`; reply = await claude.complete({ messages: [ { role: 'user', content: sys + '\n\nUsuário: ' + text.trim() } ] }); reply = (reply || '').trim(); } } catch (e) { reply = ''; } if (!reply) { // Fallback canned response const t = text.toLowerCase(); if (t.match(/cupom|desconto|primeira/)) reply = 'Sim! Use o cupom BEMVINDOMG no checkout e ganhe 10% OFF na sua primeira compra. 🎁'; else if (t.match(/entrega|prazo|demora/)) reply = 'A entrega é imediata após a confirmação do pagamento. Os benefícios caem na sua conta da cidade em segundos. ⚡'; else if (t.match(/pix|pagamento|cart[ãa]o|pagar/)) reply = 'Aceitamos PIX (com aprovação imediata), MercadoPago e PayPal. Recomendamos PIX por ser o mais rápido. 💳'; else if (t.match(/preço|valor|quanto/)) reply = 'Temos opções pra todos os bolsos! Passe Inicial sai por R$47,90, Premium R$77,90 e o Lendário R$247,90. Dá uma olhada na loja! 💰'; else if (t.match(/passe|vip/)) reply = 'Os passes liberam combos exclusivos e prioridade no servidor. O Lendário é nosso mais vendido! Posso te indicar qual escolher?'; else reply = 'Recebi sua mensagem! Para um atendimento personalizado, entre em contato pelo nosso Discord (discord.gg/milgrau) ou WhatsApp (47 99136-0760). 💬'; } setTimeout(() => { setTyping(false); setMessages(prev => [...prev, { from: 'bot', text: reply, t: Date.now() }]); if (!open) setUnread(u => u + 1); }, 700 + Math.random() * 800); }; const submitPhone = () => { if (!phone || phone.replace(/\D/g, '').length < 10) return; setPhoneCollected(true); setShowPhone(false); setPhoneInputOpen(false); setMessages(prev => [...prev, { from: 'user', text: `📱 Telefone para retorno: ${phone}`, t: Date.now() }, { from: 'bot', text: 'Perfeito! Anotamos seu telefone. Caso a conversa se encerre, retornamos por aí. ✅', t: Date.now() + 1 } ]); }; const handleKey = (e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(input); } }; const today = new Date(); const day = today.toLocaleDateString('pt-BR', { weekday: 'long', day: 'numeric', month: 'long' }); const dayCap = day.charAt(0).toUpperCase() + day.slice(1); return ( <> {!open && ( )} {open && (
Conversação
{[0,1,2].map(i => (
))}
Dúvidas? Fale conosco!
Time online · responde em minutos
{messages.slice(0, 1).map((m, i) => ( ))}
{dayCap}
{messages.slice(1).map((m, i) => ( ))} {showPhone && !phoneCollected && (
Se você sair ou demorarmos:
Como você gostaria de receber a resposta?
{phoneInputOpen && (
setPhone(e.target.value)} autoFocus />
)}
)} {typing && (
)}