arbritage/pages/Orders.tsx
2026-01-26 11:20:25 -03:00

270 lines
16 KiB
TypeScript

import React from 'react';
import { Store, Trash2, FileEdit, FileCheck, Printer } from 'lucide-react';
import { useCRM } from '../context/CRMContext';
import { OrderStatus } from '../types';
const Orders: React.FC = () => {
const { orders, updateOrderStatus, resumeOrder, deleteOrder } = useCRM();
const handleDelete = async (id: string) => {
if (window.confirm("Tem certeza que deseja excluir esse pedido?")) {
await deleteOrder(id);
}
};
const handlePrint = (order: any) => {
const printWindow = window.open('', '_blank');
if (printWindow) {
printWindow.document.write(`
<html>
<head>
<title>Pedido #${order.id.substring(0, 8)}</title>
<style>
body { font-family: monospace; padding: 20px; color: #000; }
h1 { font-size: 24px; margin-bottom: 10px; border-bottom: 2px solid #000; padding-bottom: 10px; }
.header { margin-bottom: 30px; display: flex; justify-content: space-between; }
.info { margin-bottom: 15px; font-size: 14px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; font-size: 12px; }
th, td { border-bottom: 1px solid #ddd; padding: 8px; text-align: left; }
th { background: #f5f5f5; text-transform: uppercase; }
.totals { margin-top: 30px; text-align: right; font-size: 14px; }
.footer { margin-top: 50px; text-align: center; font-size: 10px; color: #666; border-top: 1px dashed #ccc; padding-top: 20px; }
</style>
</head>
<body>
<div class="header">
<div>
<h1>Paraguai Imports</h1>
<p>Relatório de Pedido</p>
</div>
<div style="text-align: right;">
<p><strong>Data:</strong> ${new Date(order.date).toLocaleDateString()}</p>
<p><strong>ID:</strong> #${order.id}</p>
<p><strong>Status:</strong> ${order.status}</p>
</div>
</div>
<div class="info">
<p><strong>Fornecedor:</strong> ${order.supplierName}</p>
</div>
<table>
<thead>
<tr>
<th>Produto</th>
<th style="text-align: center;">Qtd</th>
<th style="text-align: right;">Preço Unit. (USD)</th>
<th style="text-align: right;">Total (USD)</th>
<th style="text-align: right;">Total (BRL)</th>
</tr>
</thead>
<tbody>
${order.items.map((item: any) => `
<tr>
<td>${item.name}</td>
<td style="text-align: center;">${item.quantity}</td>
<td style="text-align: right;">$ ${item.priceUSD.toFixed(2)}</td>
<td style="text-align: right;">$ ${(item.priceUSD * item.quantity).toFixed(2)}</td>
<td style="text-align: right;">R$ ${(item.priceBRL * item.quantity).toFixed(2)}</td>
</tr>
`).join('')}
</tbody>
</table>
<div class="totals">
<p><strong>Total USD:</strong> $ ${order.totalUSD.toFixed(2)}</p>
<p><strong>Total BRL (Sem Taxas):</strong> R$ ${order.totalBRL.toFixed(2)}</p>
<p style="font-size: 16px; margin-top: 10px;"><strong>Custo Final Estimado:</strong> R$ ${order.totalCostWithOverhead.toLocaleString('pt-BR')}</p>
<p style="color: green;"><strong>Lucro Estimado:</strong> R$ ${order.estimatedProfit.toLocaleString('pt-BR')}</p>
</div>
<div class="footer">
<p>Gerado automaticamente pelo sistema.</p>
</div>
</body>
</html>
`);
printWindow.document.close();
printWindow.print();
}
};
return (
<div className="glass-card rounded-2xl border border-white/5 shadow-sm overflow-hidden animate-in fade-in duration-500">
<div className="p-6 bg-white/[0.02] border-b border-white/5 flex justify-between items-center">
<div>
<h2 className="text-xl font-bold text-white tracking-tight">Fluxo de Pedidos (Order Flow)</h2>
<p className="text-xs text-slate-500 tracking-wide mt-1">Gestão de ciclo de vida e conciliação.</p>
</div>
</div>
{/* Desktop Table */}
<div className="hidden md:block overflow-x-auto">
<table className="w-full text-left border-collapse">
<thead>
<tr className="bg-black/20 text-[10px] font-bold text-slate-500 uppercase tracking-widest border-b border-white/5">
<th className="px-6 py-4">ID / Data</th>
<th className="px-6 py-4">Fornecedor</th>
<th className="px-6 py-4 text-right">Compra (USD)</th>
<th className="px-6 py-4 text-right">Custo BR (R$)</th>
<th className="px-6 py-4 text-right">Delta ($)</th>
<th className="px-6 py-4 text-center">Status</th>
<th className="px-6 py-4 text-right">Ações</th>
</tr>
</thead>
<tbody className="divide-y divide-white/5">
{orders.map(o => (
<tr key={o.id} className="hover:bg-white/[0.02] transition-colors group">
<td className="px-6 py-4">
<p className="text-xs font-mono text-slate-400">{o.id.substring(0, 8)}...</p>
<p className="text-[10px] text-slate-600 font-medium mt-0.5">{new Date(o.date).toLocaleDateString()}</p>
</td>
<td className="px-6 py-4">
<div className="flex items-center gap-2">
<Store size={14} className="text-slate-600" />
<span className="text-sm font-medium text-slate-300">{o.supplierName}</span>
</div>
</td>
<td className="px-6 py-4 text-xs font-mono text-slate-400 text-right">US$ {o.totalUSD.toFixed(2)}</td>
<td className="px-6 py-4 text-xs font-mono text-slate-200 text-right">R$ {o.totalCostWithOverhead.toLocaleString('pt-BR')}</td>
<td className="px-6 py-4 text-right">
<span className="text-xs font-mono font-bold text-emerald-400">+ {o.estimatedProfit.toLocaleString('pt-BR')}</span>
</td>
<td className="px-6 py-4 text-center">
<select
value={o.status}
onChange={(e) => updateOrderStatus(o.id, e.target.value as OrderStatus)}
className={`px-2 py-1 rounded text-[10px] font-bold uppercase outline-none transition-all cursor-pointer bg-transparent border-0 text-center w-full appearance-none ${o.status === 'Pending' ? 'text-amber-500' :
o.status === 'Received' ? 'text-emerald-500' :
'text-slate-500'
}`}
style={{ textAlignLast: 'center' }}
>
<option value="Pending" className="text-amber-500 bg-[#0F1115]">PENDENTE</option>
<option value="Paid" className="text-blue-500 bg-[#0F1115]">PAGO</option>
<option value="Received" className="text-emerald-500 bg-[#0F1115]">RECEBIDO</option>
<option value="Cancelled" className="text-rose-500 bg-[#0F1115]">CANCELADO</option>
</select>
</td>
<td className="px-6 py-4 text-right opacity-0 group-hover:opacity-100 transition-opacity">
<div className="flex items-center justify-end gap-2">
<button
className="p-1.5 text-slate-500 hover:text-emerald-400 hover:bg-white/5 rounded transition-colors"
title="Emitir Nota Fiscal"
onClick={() => alert('Emissão de NFe iniciada (Simulação)')}
>
<FileCheck size={14} />
</button>
<button
onClick={() => handlePrint(o)}
className="p-1.5 text-slate-500 hover:text-sky-400 hover:bg-white/5 rounded transition-colors"
title="Imprimir"
>
<Printer size={14} />
</button>
<button
onClick={() => {
resumeOrder(o.id);
window.location.hash = '#/sourcing'; // Rough navigation fix
alert(`Ordem ${o.id} carregada.`);
}}
className="p-1.5 text-slate-500 hover:text-indigo-400 hover:bg-white/5 rounded transition-colors"
title="Retomar"
>
<FileEdit size={14} />
</button>
<button
onClick={() => handleDelete(o.id)}
className="p-1.5 text-slate-500 hover:text-rose-400 hover:bg-white/5 rounded transition-colors">
<Trash2 size={14} />
</button>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
{/* Mobile Card View */}
<div className="md:hidden flex flex-col gap-4 p-4">
{orders.map(o => (
<div key={o.id} className="bg-white/[0.03] border border-white/5 rounded-xl p-4 space-y-4">
<div className="flex justify-between items-start">
<div>
<p className="text-[10px] uppercase tracking-widest text-slate-500 font-bold mb-1">Pedido</p>
<p className="text-xs font-mono text-slate-300">{o.id.substring(0, 8)}...</p>
<p className="text-[10px] text-slate-600 mt-1">{new Date(o.date).toLocaleDateString()}</p>
</div>
<div className={`px-2 py-1 rounded text-[10px] font-bold uppercase ${o.status === 'Pending' ? 'text-amber-500 bg-amber-500/10' :
o.status === 'Received' ? 'text-emerald-500 bg-emerald-500/10' :
'text-slate-500 bg-slate-500/10'
}`}>
{o.status}
</div>
</div>
<div className="grid grid-cols-2 gap-4 border-t border-white/5 pt-4">
<div>
<p className="text-[10px] uppercase tracking-widest text-slate-500 font-bold mb-1">Fornecedor</p>
<div className="flex items-center gap-2">
<Store size={12} className="text-slate-600" />
<span className="text-sm font-medium text-slate-300 truncate">{o.supplierName}</span>
</div>
</div>
<div>
<p className="text-[10px] uppercase tracking-widest text-slate-500 font-bold mb-1">Total (BRL)</p>
<p className="text-sm font-mono text-slate-200">R$ {o.totalCostWithOverhead.toLocaleString('pt-BR')}</p>
</div>
</div>
<div className="border-t border-white/5 pt-4 flex items-center justify-between">
<select
value={o.status}
onChange={(e) => updateOrderStatus(o.id, e.target.value as OrderStatus)}
className="bg-black/20 border border-white/10 rounded px-3 py-1.5 text-xs text-slate-300 outline-none"
>
<option value="Pending">PENDENTE</option>
<option value="Paid">PAGO</option>
<option value="Received">RECEBIDO</option>
<option value="Cancelled">CANCELADO</option>
</select>
<div className="flex items-center gap-2">
<button
onClick={() => handlePrint(o)}
className="p-2 text-slate-400 bg-white/5 rounded-lg hover:bg-sky-500/20 hover:text-sky-400 transition-colors"
>
<Printer size={16} />
</button>
<button
onClick={() => {
resumeOrder(o.id);
window.location.hash = '#/sourcing';
alert(`Ordem ${o.id} carregada.`);
}}
className="p-2 text-slate-400 bg-white/5 rounded-lg hover:bg-indigo-500/20 hover:text-indigo-400 transition-colors"
>
<FileEdit size={16} />
</button>
<button
onClick={() => handleDelete(o.id)}
className="p-2 text-slate-400 bg-white/5 rounded-lg hover:bg-rose-500/20 hover:text-rose-400 transition-colors"
>
<Trash2 size={16} />
</button>
</div>
</div>
</div>
))}
</div>
{orders.length === 0 && (
<div className="py-20 text-center text-slate-700 font-mono text-xs">NO ACTIVE ORDERS.</div>
)}
</div>
);
};
export default Orders;