import { Modal, Tag, Skeleton, Typography, Row, Col, Statistic, Divider } from 'antd';
import {
BarcodeOutlined,
InboxOutlined,
PercentageOutlined,
TagsOutlined,
} from '@ant-design/icons';
import type { PautaPreco } from '@sar/api-interface';
import { useProdutoDetail } from '../../lib/queries/catalog';
import { useCondicoesComerciais, type CondicaoComercial } from '../../lib/condicoes-comerciais';
import { CondicaoTag } from '../../components/CondicaoTag';
const { Text, Title } = Typography;
function fmtPrice(v: string | null | undefined): string {
const n = Number(v ?? 0);
return n > 0 ? n.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }) : '—';
}
function fmtNum(v: string | null | undefined, decimals = 3): string {
const n = Number(v ?? 0);
return n > 0
? n.toLocaleString('pt-BR', {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
})
: '—';
}
// ─── Bloco de seção ───────────────────────────────────────────────────────────
function Section({
icon,
title,
children,
}: {
icon: React.ReactNode;
title: string;
children: React.ReactNode;
}) {
return (
{icon}
{title}
{children}
);
}
// ─── Campo label/valor ────────────────────────────────────────────────────────
function Field({
label,
value,
span = 1,
}: {
label: string;
value: React.ReactNode;
span?: number;
}) {
return (
1 ? 'span 2' : undefined, marginBottom: 12 }}>
{label}
{value ?? '—'}
);
}
// ─── Card de preço ────────────────────────────────────────────────────────────
function PrecoCard({
label,
value,
highlight,
}: {
label: string;
value: string;
highlight?: boolean;
}) {
const n = Number(value ?? 0);
const empty = n <= 0;
return (
{label}
{fmtPrice(value)}
);
}
// ─── Lista de pautas ──────────────────────────────────────────────────────────
function PautaPrecoList({ items }: { items: PautaPreco[] }) {
if (items.length === 0) {
return (
Produto não está em nenhuma pauta ativa.
);
}
return (
{items.map((item) => (
Pauta {item.codigo}
{item.descricao}
{fmtPrice(item.preco)}
))}
);
}
// ─── Condições comerciais vigentes ────────────────────────────────────────────
function fmtData(iso: string): string {
const [y, m, d] = iso.split('-');
return `${d}/${m}/${y}`;
}
function CondicoesList({ conds }: { conds: CondicaoComercial[] }) {
return (
{conds.map((c, i) => (
{c.tipo === 'promocao' ? 'Promoção' : 'Condição especial'} · válida até{' '}
{fmtData(c.dataFim)}
{c.descricao}
{c.descPct.toLocaleString('pt-BR')}% desc.
))}
);
}
// ─── Modal principal ──────────────────────────────────────────────────────────
interface Props {
idErp: number | null;
onClose: () => void;
}
export function ProductDetailDrawer({ idErp, onClose }: Props) {
const { data, isLoading } = useProdutoDetail(idErp ?? undefined);
const condicoesDe = useCondicoesComerciais();
const conds = data ? condicoesDe(data) : [];
return (
{isLoading || !data ? (
) : (
<>
{/* ── Cabeçalho ──────────────────────────────────────────── */}
Código {data.codigo.trim()}
{data.referencia ? ` · Ref. ${data.referencia.trim()}` : ''}
{data.descricao.trim()}
{data.descricaoDetalhada && (
{data.descricaoDetalhada.trim()}
)}
{data.marca && {data.marca.trim()}}
{data.unidade && {data.unidade}}
{data.ativo ? 'Ativo' : 'Inativo'}
{/* ── Corpo ──────────────────────────────────────────────── */}
{/* Coluna esquerda */}
{/* Condições comerciais vigentes */}
{conds.length > 0 && (
} title="Condições Comerciais">
)}
{/* Classificação */}
} title="Classificação">
{/* Preços Base */}
} title="Preços Base">
Alíq. IPI
{data.aliqIpi ? `${Number(data.aliqIpi).toLocaleString('pt-BR')}%` : '—'}
{/* Estoque & Logística */}
} title="Estoque & Logística">
0
? '#1F2937'
: '#EF4444',
}}
formatter={(v) => (v != null ? Number(v).toLocaleString('pt-BR') : '—')}
/>
(v != null ? String(v) : '—')}
/>
fmtNum(String(v))}
/>
fmtNum(String(v), 0)}
/>
{/* Divisor vertical */}
{/* Coluna direita — Pautas */}
}
title={`Preços por Pauta (${data.pautaPrecos.length})`}
>
>
)}
);
}