Vendaweb-portal/components/checkout/CheckoutProductsTable.tsx

387 lines
17 KiB
TypeScript
Raw Normal View History

2026-01-08 12:09:16 +00:00
import React from "react";
import { OrderItem } from "../../types";
interface CheckoutProductsTableProps {
cart: OrderItem[];
onEdit?: (item: OrderItem) => void;
onDiscount?: (item: OrderItem) => void;
onRemove?: (item: OrderItem) => void;
}
const CheckoutProductsTable: React.FC<CheckoutProductsTableProps> = ({
cart,
onEdit,
onDiscount,
onRemove,
}) => {
// Renderizar badge de condição
const renderConditionBadge = (item: OrderItem) => {
if (item.discount && item.discount > 0) {
return (
<span className="bg-[#cc4b5c] text-white px-2 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Em promoção
</span>
);
}
return null;
};
// Renderizar badge de tipo de entrega
const renderDeliveryTypeBadge = (item: OrderItem) => {
if (item.deliveryType === "RI") {
return (
<span className="bg-[#385942] text-white px-2 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Retira imediata
</span>
);
}
if (item.deliveryType === "EN") {
return (
<span className="bg-[#cc4b5c] text-white px-2 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Entrega
</span>
);
}
if (item.deliveryType === "RP") {
return (
<span className="bg-[#ef7d00] text-white px-2 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Retira posterior
</span>
);
}
if (item.deliveryType === "EF") {
return (
<span className="bg-[#5a3d7a] text-white px-2 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Encomenda
</span>
);
}
return null;
};
return (
<div className="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden mb-8">
{/* Cards View - Mobile/Tablet */}
<div className="lg:hidden">
{cart.length === 0 ? (
<div className="p-8 text-center text-slate-400 italic font-medium">
Nenhum item adicionado ao pedido.
</div>
) : (
<div className="divide-y divide-slate-100">
{cart.map((item, idx) => (
<div
key={item.id}
className="p-4 hover:bg-slate-50/50 transition-colors"
>
{/* Header do Card */}
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
<div className="flex items-center gap-2 mb-2">
<span className="text-xs font-bold text-slate-400">
#{idx + 1}
</span>
<span className="text-xs font-medium text-slate-500">
Cód: {item.code}
</span>
{renderConditionBadge(item)}
</div>
<h3 className="font-bold text-sm text-[#002147] leading-tight mb-2">
{item.name}
</h3>
</div>
</div>
{/* Informações do Produto */}
<div className="space-y-2 mb-3">
<div className="flex items-center justify-between text-xs">
<span className="text-slate-500">Marca:</span>
<span className="font-medium text-slate-700 uppercase">
{item.mark || "-"}
</span>
</div>
<div className="flex items-center justify-between text-xs">
<span className="text-slate-500">Desconto:</span>
<span className="font-semibold text-slate-700">
{item.discount ? `${item.discount.toFixed(2)}%` : "0,00%"}
</span>
</div>
<div className="flex items-center justify-between text-xs">
<span className="text-slate-500">F.Retira:</span>
<span className="font-medium text-slate-700">
{item.stockStore ? `Loja ${item.stockStore}` : "-"}
</span>
</div>
<div className="flex items-center justify-between text-xs">
<span className="text-slate-500">Tipo de entrega:</span>
{renderDeliveryTypeBadge(item)}
</div>
</div>
{/* Valores */}
<div className="bg-slate-50 rounded-lg p-3 mb-3">
<div className="flex items-center justify-between mb-2">
<span className="text-xs text-slate-500">Preço unitário:</span>
<span className="font-bold text-sm text-slate-700">
R$ {item.price.toFixed(2)}
</span>
</div>
<div className="flex items-center justify-between mb-2">
<span className="text-xs text-slate-500">Quantidade:</span>
<span className="font-bold text-sm text-slate-700">
{item.quantity.toFixed(2)}
</span>
</div>
<div className="flex items-center justify-between pt-2 border-t border-slate-200">
<span className="text-xs font-bold text-slate-600">
Valor total:
</span>
<span className="font-black text-base text-[#002147]">
R$ {(item.price * item.quantity).toFixed(2)}
</span>
</div>
</div>
{/* Ações */}
<div className="flex items-center justify-end gap-2 pt-2 border-t border-slate-100">
<button
onClick={() => onEdit && onEdit(item)}
className="flex items-center gap-1.5 px-3 py-2 bg-emerald-50 text-emerald-600 rounded-lg hover:bg-emerald-100 transition-colors text-xs font-bold touch-manipulation"
title="Editar"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
/>
</svg>
Editar
</button>
<button
onClick={() => onDiscount && onDiscount(item)}
className="flex items-center gap-1.5 px-3 py-2 bg-orange-50 text-orange-500 rounded-lg hover:bg-orange-100 transition-colors text-xs font-bold touch-manipulation"
title="Desconto"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
Desconto
</button>
<button
onClick={() => onRemove && onRemove(item)}
className="flex items-center gap-1.5 px-3 py-2 bg-red-50 text-red-500 rounded-lg hover:bg-red-100 transition-colors text-xs font-bold touch-manipulation"
title="Remover"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
Remover
</button>
</div>
</div>
))}
</div>
)}
</div>
{/* Table View - Desktop */}
<div className="hidden lg:block overflow-x-auto custom-scrollbar">
<table className="w-full text-left text-xs border-collapse">
<thead>
<tr className="bg-slate-50 text-slate-500 font-bold uppercase border-b border-slate-200">
<th className="px-4 py-4 border-r border-slate-200">Seq</th>
<th className="px-4 py-4 border-r border-slate-200">Código</th>
<th className="px-4 py-4 border-r border-slate-200 min-w-[300px]">
Produto
</th>
<th className="px-4 py-4 border-r border-slate-200 text-center">
Condição
</th>
<th className="px-4 py-4 border-r border-slate-200">Marca</th>
<th className="px-4 py-4 border-r border-slate-200">Descon</th>
<th className="px-4 py-4 border-r border-slate-200">F.Retira</th>
<th className="px-4 py-4 border-r border-slate-200">
Tipo de entre.
</th>
<th className="px-4 py-4 border-r border-slate-200">Preço</th>
<th className="px-4 py-4 border-r border-slate-200">Qtde</th>
<th className="px-4 py-4 border-r border-slate-200">
Valor total
</th>
<th className="px-4 py-4 text-center">Ações</th>
</tr>
</thead>
<tbody className="divide-y divide-slate-100">
{cart.length === 0 ? (
<tr>
<td
colSpan={12}
className="px-4 py-10 text-center text-slate-400 italic font-medium"
>
Nenhum item adicionado ao pedido.
</td>
</tr>
) : (
cart.map((item, idx) => (
<tr
key={item.id}
className="hover:bg-slate-50/50 transition-colors"
>
<td className="px-4 py-4 border-r border-slate-100 font-medium">
{idx + 1}
</td>
<td className="px-4 py-4 border-r border-slate-100 text-slate-600">
{item.code}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-bold text-[#002147]">
{item.name}
</td>
<td className="px-4 py-4 border-r border-slate-100 text-center">
{item.discount && item.discount > 0 && (
<span className="bg-[#cc4b5c] text-white px-3 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Em promoção
</span>
)}
</td>
<td className="px-4 py-4 border-r border-slate-100 text-slate-600 font-medium uppercase">
{item.mark || "-"}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-semibold text-slate-500">
{item.discount ? `${item.discount.toFixed(2)}%` : "0,00%"}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-medium text-slate-600">
{item.stockStore ? `Loja ${item.stockStore}` : "-"}
</td>
<td className="px-4 py-4 border-r border-slate-100 text-center">
{item.deliveryType === "RI" && (
<span className="bg-[#385942] text-white px-3 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Retira imediata
</span>
)}
{item.deliveryType === "EN" && (
<span className="bg-[#cc4b5c] text-white px-3 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Entrega
</span>
)}
{item.deliveryType === "RP" && (
<span className="bg-[#ef7d00] text-white px-3 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Retira posterior
</span>
)}
{item.deliveryType === "EF" && (
<span className="bg-[#5a3d7a] text-white px-3 py-1 rounded-full text-[9px] font-bold uppercase tracking-tight">
Encomenda
</span>
)}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-bold text-slate-700">
R$ {item.price.toFixed(2)}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-bold text-slate-700">
{item.quantity.toFixed(2)}
</td>
<td className="px-4 py-4 border-r border-slate-100 font-black text-[#002147]">
R$ {(item.price * item.quantity).toFixed(2)}
</td>
<td className="px-4 py-4">
<div className="flex items-center justify-center space-x-1.5">
<button
onClick={() => onEdit && onEdit(item)}
className="p-1.5 bg-slate-100 text-emerald-600 rounded hover:bg-emerald-50 transition-colors"
title="Editar"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
/>
</svg>
</button>
<button
onClick={() => onDiscount && onDiscount(item)}
className="p-1.5 bg-slate-100 text-orange-500 rounded hover:bg-orange-50 transition-colors"
title="Desconto"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</button>
<button
onClick={() => onRemove && onRemove(item)}
className="p-1.5 bg-slate-100 text-red-500 rounded hover:bg-red-50 transition-colors"
title="Remover"
>
<svg
className="w-4 h-4"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2.5"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
</button>
</div>
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
);
};
export default CheckoutProductsTable;