import React, { useEffect, useMemo, useState } from 'react';
import { createRoot } from 'react-dom/client';
import { BarChart3, Home, LayoutDashboard, LogOut, Menu, Package, Plus, Search, Settings, ShoppingBag, Tag, Ticket, Trash2 } from 'lucide-react';
import { db } from './services/store';
import { Banner, Campaign, Category, Product } from './types';
import { money, slugify, today, uid } from './utils/helpers';
import './style.css';
type Route = { page: string; slug?: string; id?: string };
const routeFromHash = (): Route => { const raw = location.hash.replace('#', '') || '/'; const parts = raw.split('/').filter(Boolean); return { page: parts[0] || 'home', slug: parts[1], id: parts[2] }; };
const go = (path: string) => { location.hash = path; };
function useStore() { const [, setTick] = useState(0); useEffect(() => { const fn = () => setTick(x => x + 1); window.addEventListener('tooca:update', fn); window.addEventListener('hashchange', fn); db.init(); return () => { window.removeEventListener('tooca:update', fn); window.removeEventListener('hashchange', fn); }; }, []); return { products: db.products(), categories: db.categories(), banners: db.banners(), campaigns: db.campaigns(), clicks: db.clicks(), settings: db.settings(), route: routeFromHash(), auth: db.isAuth() }; }
function Header() { const { settings } = useStore(); return ; }
function Footer() { const { settings } = useStore(); return ; }
function Layout({ children }: { children: React.ReactNode }) { return <>{children}>; }
function ProductCard({ product }: { product: Product }) { return 
{product.mercadoLivreId || 'Afiliado ML'}{product.title}
{product.description}
{money(product.price)} {product.oldPrice && {money(product.oldPrice)}}
; }
function ProductGrid({ products }: { products: Product[] }) { return
{products.filter(p => p.active).map(p =>
)} ; }
function HomePage() { const { products, banners } = useStore(); const hero = banners.find(b => b.active && b.position === 'home_top'); return {hero?.title || 'Tooca Loja'}
{hero?.subtitle || 'Achadinhos selecionados para você.'}
Produtos em destaque
p.featured)} />; }
function ProductsPage() { const { products } = useStore(); return } text="Todos os produtos"/>; }
function CategoriesPage() { const { categories } = useStore(); return } text="Categorias"/>{categories.filter(c=>c.active).map(c=>
go(`/categoria/${c.slug}`)} key={c.id}>
)}
; }
function CategoryPage({ slug }: { slug?: string }) { const { categories, products } = useStore(); const cat = categories.find(c => c.slug === slug); return } text={cat?.name || 'Categoria'}/> cat && p.categoryIds.includes(cat.id))}/>; }
function OffersPage() { const { products } = useStore(); return } text="Ofertas"/> !!p.oldPrice)} />; }
function SearchPage() { const { products } = useStore(); const [q,setQ] = useState(''); const filtered = products.filter(p => `${p.title} ${p.description}`.toLowerCase().includes(q.toLowerCase())); return } text="Busca"/>setQ(e.target.value)}/>; }
function ProductPage({ slug }: { slug?: string }) { const { products, categories } = useStore(); const p = products.find(x => x.slug === slug); if (!p) return Produto não encontrado
; return 
{p.mercadoLivreId}{p.title}
{p.description}
{money(p.price)} {p.oldPrice && {money(p.oldPrice)}}
{p.categoryIds.map(id=>categories.find(c=>c.id===id)?.name).filter(Boolean).join(' • ')}
; }
function RedirectPage({ id }: { id?: string }) { const { products, campaigns } = useStore(); const p = products.find(x => x.id === id); useEffect(()=>{ if(p){ db.trackClick(p.id, campaigns.find(c=>c.active)?.id); setTimeout(()=>{ window.open(p.affiliateUrl || p.mercadoLivreUrl, '_blank'); go(`/produto/${p.slug}`); }, 800); } },[p?.id]); return Redirecionando...
Registramos o clique e vamos abrir o Mercado Livre.
; }
function LoginPage() { const [email,setEmail]=useState('admin@tooca.com'); const [password,setPassword]=useState('123456'); const [err,setErr]=useState(''); return ; }
function AdminLayout({children}:{children:React.ReactNode}) { const { auth }=useStore(); if(!auth) return ; const item=(path:string,label:string,icon:React.ReactNode)=>go(path)}>{icon}{label}; return ; }
function Title({icon,text}:{icon:React.ReactNode;text:string}){return {icon}
{text}
}
function Stat({label,value}:{label:string;value:string|number}){return {value}{label}
}
function Dashboard(){ const {products,categories,clicks,banners}=useStore(); const top=[...products].sort((a,b)=>clicks.filter(c=>c.productId===b.id).length-clicks.filter(c=>c.productId===a.id).length).slice(0,5); return } text="Dashboard"/>
Produtos mais clicados
[p.title, money(p.price), clicks.filter(c=>c.productId===p.id).length+' cliques'])}/> }
function Table({rows}:{rows:(string|number)[][]}){return {rows.map((r,i)=>{r.map((c,j)=>| {c} | )}
)}
}
const emptyProduct: Product = { id:'', title:'', slug:'', description:'', price:0, oldPrice:0, imageUrl:'', mercadoLivreUrl:'https://www.mercadolivre.com.br', affiliateUrl:'https://www.mercadolivre.com.br?aff=tooca', mercadoLivreId:'', categoryIds:[], featured:false, active:true, createdAt: today() };
function ProductForm({edit}:{edit?:Product}){ const {categories}=useStore(); const [p,setP]=useState(edit || {...emptyProduct,id:uid('prod')}); const save=()=>{ db.saveProduct({...p, slug:p.slug||slugify(p.title)}); go('/admin/produtos');}; return }
function ProductsAdmin(){ const {products, route}=useStore(); if(route.slug==='novo') return } text="Novo produto"/>; if(route.slug==='editar') return } text="Editar produto"/>p.id===route.id)}/>; return } text="Produtos"/> {products.map(p=> | {p.title} | {money(p.price)} | {p.active?'Ativo':'Inativo'} | |
)}
}
function SimpleAdmin({kind}:{kind:'categorias'|'banners'|'campanhas'}){ const s=useStore(); const title=kind==='categorias'?'Categorias':kind==='banners'?'Banners':'Campanhas'; const rows = kind==='categorias'?s.categories:kind==='banners'?s.banners:s.campaigns; const add=()=>{ if(kind==='categorias'){ const name=prompt('Nome da categoria')||''; if(name) db.saveCategory({id:uid('cat'),name,slug:slugify(name),description:'Nova categoria',imageUrl:'https://images.unsplash.com/photo-1607082349566-187342175e2f?q=80&w=1200',active:true}); } if(kind==='banners') db.saveBanner({id:uid('ban'),title:'Novo banner',subtitle:'SubtÃtulo',imageUrl:'https://images.unsplash.com/photo-1607082349566-187342175e2f?q=80&w=1200',linkUrl:'/produtos',position:'home_top',active:true}); if(kind==='campanhas') db.saveCampaign({id:uid('camp'),name:'Nova campanha',slug:'nova-campanha',description:'Descrição da campanha',startDate:today(),endDate:today(),active:true}); }; return } text={title}/> {rows.map((r:any)=>| {r.name||r.title} | {r.slug||r.position} | {r.active?'Ativo':'Inativo'} |
)}
}
function Affiliates(){ const {products,settings}=useStore(); return } text="Afiliados"/>Tag configurada: {settings.affiliateTag}
}
function ClicksAdmin(){ const {clicks,products,campaigns}=useStore(); return } text="Cliques"/>{clicks.map(c=>| {new Date(c.createdAt).toLocaleString('pt-BR')} | {products.find(p=>p.id===c.productId)?.title} | {campaigns.find(x=>x.id===c.campaignId)?.name||'-'} | {c.source} |
)}
}
function ConfigAdmin(){ const {settings}=useStore(); const [v,setV]=useState(settings); return } text="Configurações"/>setV({...v,storeName:e.target.value})}/>setV({...v,affiliateTag:e.target.value})}/>setV({...v,whatsapp:e.target.value})}/>setV({...v,instagram:e.target.value})}/>
}
function App(){ const {route}=useStore(); if(route.page==='produtos') return ; if(route.page==='categorias') return ; if(route.page==='categoria') return ; if(route.page==='ofertas') return ; if(route.page==='busca') return ; if(route.page==='produto') return ; if(route.page==='redirect') return ; if(route.page==='admin' && route.slug==='login') return ; if(route.page==='admin' && route.slug==='dashboard') return ; if(route.page==='admin' && route.slug==='produtos') return ; if(route.page==='admin' && route.slug==='categorias') return ; if(route.page==='admin' && route.slug==='banners') return ; if(route.page==='admin' && route.slug==='campanhas') return ; if(route.page==='admin' && route.slug==='afiliados') return ; if(route.page==='admin' && route.slug==='cliques') return ; if(route.page==='admin' && route.slug==='config') return ; return ; }
createRoot(document.getElementById('root')!).render();