arbritage/pages/Sourcing.tsx

235 lines
16 KiB
TypeScript
Raw Permalink Normal View History

2026-01-26 14:20:25 +00:00
import React from 'react';
import { Search, Package, Plus, Calculator, Trash2, Minus, ShoppingCart, CheckCircle2, Facebook, Tag, ToggleLeft, ToggleRight } from 'lucide-react';
import { useCRM } from '../context/CRMContext';
import MarketplaceAnalytic from '../components/MarketplaceAnalytic';
const Sourcing: React.FC = () => {
const {
searchTerm, setSearchTerm, handleSearch, handleOpportunitySearch, products,
selectedProduct, setSelectedProduct, addToShoppingList,
shoppingList, removeFromShoppingList,
updateShoppingItemQuantity, saveOrderAsQuotation,
calculateShoppingTotals, overheadPercent,
useOverhead, setUseOverhead,
searchLoading, searchError, searchType, setSearchType
} = useCRM();
const onSearchSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (searchType === 'specific') {
handleSearch(e);
} else {
handleOpportunitySearch(searchTerm);
}
};
const handleUpdateQuantity = (item: any, delta: number) => {
updateShoppingItemQuantity(item.id, delta);
};
const handleRemoveItem = (id: string) => {
removeFromShoppingList(id);
};
return (
<div className="grid grid-cols-1 xl:grid-cols-12 gap-8 items-start animate-in fade-in duration-500">
{/* COLUNA 1: BUSCA */}
<div className="xl:col-span-3 space-y-6">
<div className="bg-white/5 rounded-[32px] p-6 border border-white/5 shadow-sm backdrop-blur-sm">
{/* TABS */}
<div className="flex bg-slate-900/50 rounded-2xl p-1 mb-6 border border-white/5">
<button
onClick={() => setSearchType('specific')}
className={`flex-1 py-2 text-[10px] font-bold uppercase tracking-wider rounded-xl transition-all ${searchType === 'specific' ? 'bg-indigo-600 text-white shadow-lg' : 'text-slate-500 hover:text-slate-300'}`}
>
Busca Específica
</button>
<button
onClick={() => setSearchType('opportunity')}
className={`flex-1 py-2 text-[10px] font-bold uppercase tracking-wider rounded-xl transition-all ${searchType === 'opportunity' ? 'bg-emerald-600 text-white shadow-lg' : 'text-slate-500 hover:text-slate-300'}`}
>
Oportunidades
</button>
</div>
<div className="flex items-center gap-2 mb-6">
{searchType === 'specific' ? <Search size={16} className="text-indigo-400" /> : <Tag size={16} className="text-emerald-400" />}
<h2 className="text-[11px] font-bold text-slate-500 uppercase tracking-widest">
{searchType === 'specific' ? 'Sourcing Real-Time' : 'Caçador de Margem (>25%)'}
</h2>
</div>
<form onSubmit={onSearchSubmit} className="relative group mb-8">
<input
type="text" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)}
placeholder={searchType === 'specific' ? "Ex: iPhone 16 Pro Max" : "Ex: Celulares, Drones, Games"}
className={`w-full bg-slate-900/50 border border-white/10 rounded-2xl py-4 pl-12 pr-4 text-sm font-semibold outline-none transition-all text-white placeholder-slate-600 shadow-inner ${searchType === 'specific' ? 'focus:border-indigo-500' : 'focus:border-emerald-500'}`}
/>
<Search className={`absolute left-4 top-1/2 -translate-y-1/2 transition-colors ${searchType === 'specific' ? 'text-slate-500 group-focus-within:text-indigo-500' : 'text-slate-500 group-focus-within:text-emerald-500'}`} size={20} />
</form>
{searchError && (
<div className="mb-6 p-4 bg-rose-500/10 border border-rose-500/20 rounded-2xl flex items-center gap-3 text-rose-400">
<div className="w-2 h-2 bg-rose-500 rounded-full animate-pulse"></div>
<p className="text-xs font-bold uppercase tracking-wide">{searchError}</p>
</div>
)}
<div className="space-y-4 max-h-[600px] overflow-y-auto pr-2 custom-scrollbar">
{searchLoading ? (
<div className="py-20 text-center animate-pulse">
<div className="w-10 h-10 border-4 border-indigo-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"></div>
<p className="text-[10px] font-bold text-slate-500 uppercase">Consultando Compras Paraguai...</p>
</div>
) : products.map((p, idx) => (
<div
key={idx}
onClick={() => setSelectedProduct(p)}
className={`p-5 rounded-3xl border-2 cursor-pointer transition-all hover:scale-[1.02] active:scale-95 ${selectedProduct?.name === p.name
? 'border-indigo-500 bg-indigo-500/10 shadow-md'
: 'border-white/5 bg-white/5 hover:border-white/10 hover:bg-white/10'
}`}
>
<div className="flex justify-between items-start">
<span className="text-[8px] font-bold uppercase bg-slate-800 border border-slate-700 px-2 py-0.5 rounded-lg text-slate-400">{p.store}</span>
</div>
<h4 className="text-sm font-bold text-slate-200 leading-tight mt-3 mb-4 line-clamp-2">{p.name}</h4>
<div className="flex items-end justify-between">
<div>
<p className="text-xl font-bold text-white tracking-tight">US$ {p.priceUSD.toFixed(2)}</p>
<p className="text-[10px] font-bold text-slate-500 uppercase">R$ {p.priceBRL.toLocaleString('pt-BR')}</p>
</div>
<div className="flex flex-col items-end gap-2">
{p.salesVolume && (
<span className="text-[9px] font-bold uppercase tracking-widest bg-emerald-500/10 text-emerald-400 px-2 py-1 rounded-lg border border-emerald-500/20 shadow-[0_0_10px_rgba(16,185,129,0.1)]">
{p.salesVolume}
</span>
)}
<button
onClick={(e) => { e.stopPropagation(); addToShoppingList(p); }}
className="p-3 bg-indigo-600 text-white rounded-2xl hover:bg-indigo-500 transition-all shadow-lg active:scale-90"
>
<Plus size={18} />
</button>
</div>
</div>
</div>
))}
{!searchLoading && products.length === 0 && (
<div className="py-24 text-center opacity-20">
<Package size={48} strokeWidth={1.5} className="mx-auto mb-4 text-slate-400" />
<p className="text-[10px] font-bold text-slate-500 uppercase tracking-widest">Aguardando seu input</p>
</div>
)}
</div>
</div>
</div>
{/* COLUNA 2: ANÁLISE DETALHADA */}
<div className="xl:col-span-6">
{selectedProduct ? (
<MarketplaceAnalytic product={selectedProduct} overheadPercent={overheadPercent} useOverhead={useOverhead} />
) : (
<div className="bg-white/5 rounded-[40px] border border-white/5 shadow-sm min-h-[600px] flex flex-col items-center justify-center p-20 text-center backdrop-blur-sm">
<div className="w-24 h-24 bg-slate-800/50 rounded-[32px] flex items-center justify-center mb-8 border border-white/5 shadow-inner">
<Calculator size={40} className="text-slate-600" />
</div>
<h3 className="text-2xl font-bold text-white mb-4 tracking-tight">Analítica de Arbitragem</h3>
<p className="text-slate-500 max-w-sm text-sm font-medium leading-relaxed">Selecione um produto para ver a comparação de margem real entre os marketplaces do Brasil e sua venda direta no Facebook.</p>
</div>
)}
</div>
{/* COLUNA 3: COTAÇÃO / CRM CHECKOUT */}
<div className="xl:col-span-3">
<div className="bg-white/5 rounded-[40px] border border-white/5 shadow-sm flex flex-col min-h-[700px] sticky top-[120px] overflow-hidden backdrop-blur-sm">
<div className="p-8 border-b border-white/5 flex justify-between items-center bg-white/5">
<div>
<h2 className="text-sm font-bold text-white uppercase tracking-widest leading-none">Minha Cotação</h2>
<p className="text-[9px] font-bold text-indigo-400 uppercase mt-1">Sourcing Ativo</p>
</div>
<span className="w-9 h-9 bg-indigo-600 text-white text-xs font-bold rounded-xl flex items-center justify-center shadow-lg shadow-indigo-500/30">{shoppingList.length}</span>
</div>
<div className="flex-grow p-6 space-y-4 overflow-y-auto max-h-[450px] custom-scrollbar">
{shoppingList.length > 0 ? (
shoppingList.map(item => (
<div key={item.id} className="p-5 bg-slate-900/50 rounded-3xl border border-white/5 group transition-all hover:border-indigo-500/30 hover:shadow-md">
<div className="flex justify-between items-start mb-4">
<div className="flex-grow pr-4">
<span className="text-[9px] font-bold text-slate-500 uppercase tracking-wider">{item.store}</span>
<h4 className="text-xs font-bold text-slate-200 leading-tight mt-1">{item.name}</h4>
</div>
<button onClick={() => handleRemoveItem(item.id)} className="text-slate-600 hover:text-rose-500 transition-colors">
<Trash2 size={16} />
</button>
</div>
<div className="flex items-center justify-between">
<p className="text-sm font-bold text-white">US$ {item.priceUSD.toFixed(2)}</p>
<div className="flex items-center gap-3 bg-black/20 rounded-xl p-1 border border-white/5">
<button onClick={() => handleUpdateQuantity(item, -1)} className="p-1.5 hover:bg-white/10 rounded-lg text-slate-400"><Minus size={12} /></button>
<span className="text-xs font-bold text-slate-300 w-5 text-center">{item.quantity}</span>
<button onClick={() => handleUpdateQuantity(item, 1)} className="p-1.5 hover:bg-white/10 rounded-lg text-slate-400"><Plus size={12} /></button>
</div>
</div>
</div>
))
) : (
<div className="py-24 text-center opacity-10">
<ShoppingCart size={64} strokeWidth={1.5} className="mx-auto text-white" />
<p className="text-[10px] font-bold text-white uppercase mt-4 tracking-widest">Carrinho Vazio</p>
</div>
)}
</div>
<div className="p-8 bg-slate-900 text-white rounded-t-[40px] space-y-5 border-t border-white/5">
<div className="space-y-3">
<div className="flex justify-between items-center opacity-80 hover:opacity-100 transition-opacity">
<button
onClick={() => setUseOverhead(!useOverhead)}
className="flex items-center gap-2 cursor-pointer group"
title={useOverhead ? "Desativar Taxas (20%)" : "Ativar Taxas (20%)"}
>
{useOverhead ? (
<ToggleRight size={20} className="text-indigo-400 group-hover:text-indigo-300 transition-colors" />
) : (
<ToggleLeft size={20} className="text-slate-500 group-hover:text-slate-400 transition-colors" />
)}
<span className={`text-[10px] font-bold uppercase tracking-widest ${useOverhead ? 'text-indigo-300' : 'text-slate-500'} transition-colors`}>
Custo Final Est. ({useOverhead ? 'c/ Taxas' : 's/ Taxas'})
</span>
</button>
<span className={`text-sm font-bold ${useOverhead ? 'text-indigo-100' : 'text-slate-500'} transition-colors`}>
R$ {calculateShoppingTotals().totalCostWithOverhead.toLocaleString('pt-BR')}
</span>
</div>
<div className="flex justify-between items-center opacity-60">
<span className="text-[10px] font-bold uppercase tracking-widest">Subtotal Paraguai</span>
<span className="text-sm font-bold">US$ {calculateShoppingTotals().totalUSD.toLocaleString('en-US')}</span>
</div>
<div className="pt-4 border-t border-white/10 flex justify-between items-center">
<div className="flex items-center gap-2">
<span className="text-[11px] font-bold text-emerald-400 uppercase tracking-widest">Lucro Est. Final</span>
<Facebook size={12} className="text-emerald-400" />
</div>
<span className="text-2xl font-bold text-emerald-400">R$ {calculateShoppingTotals().totalApproxProfit.toLocaleString('pt-BR')}</span>
</div>
</div>
<button
onClick={saveOrderAsQuotation}
disabled={shoppingList.length === 0}
className="w-full bg-indigo-600 text-white font-bold py-5 rounded-[24px] hover:bg-indigo-500 transition-all flex items-center justify-center gap-2 disabled:opacity-20 active:scale-95 shadow-xl shadow-indigo-900/40"
>
<CheckCircle2 size={20} />
SALVAR NO CRM
</button>
</div>
</div>
</div>
</div>
);
};
export default Sourcing;