import { useState } from 'react'; import { Alert, Badge, Button, Card, Col, Collapse, Flex, Form, Input, InputNumber, Modal, Row, Select, Skeleton, Space, Tag, Tooltip, Typography, } from 'antd'; import { ArrowRightOutlined, DeleteOutlined, EditOutlined, PlusOutlined, TrophyOutlined, } from '@ant-design/icons'; import type { Oportunidade, EtapaFunil, CreateOportunidadeDto, UpdateOportunidadeDto, } from '@sar/api-interface'; import { ETAPAS_FUNIL } from '@sar/api-interface'; import { useFunil, useCreateOportunidade, useUpdateOportunidade, useDeleteOportunidade, } from '../../lib/queries/funil'; const { Title, Text } = Typography; const ETAPA_CONFIG: Record = { lead: { label: 'Lead', cor: '#64748b', corBg: '#F8FAFC' }, proposta: { label: 'Proposta', cor: '#2563EB', corBg: '#EFF6FF' }, negociacao: { label: 'Negociação', cor: '#D97706', corBg: '#FFFBEB' }, ganho: { label: 'Ganho', cor: '#16A34A', corBg: '#F0FDF4' }, perdido: { label: 'Perdido', cor: '#DC2626', corBg: '#FEF2F2' }, }; const PROXIMA: Partial> = { lead: 'proposta', proposta: 'negociacao', negociacao: 'ganho', }; const ANTERIOR: Partial> = { proposta: 'lead', negociacao: 'proposta', ganho: 'negociacao', }; function fmt(v: string | null | undefined): string { if (!v) return ''; return Number(v).toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' }); } function diasDesde(iso: string): number { return Math.floor((Date.now() - new Date(iso).getTime()) / 86_400_000); } function nomePrincipal(op: Oportunidade): string { return op.nomeCliente ?? op.nomeProspect ?? op.empresaProspect ?? `Oport. #${op.id}`; } // ─── Card ──────────────────────────────────────────────────────────────────── function OportCard({ op, onEdit, onMover, onDeletar, }: { op: Oportunidade; onEdit: () => void; onMover: (etapa: EtapaFunil) => void; onDeletar: () => void; }) { const dias = diasDesde(op.updatedAt); const prox = PROXIMA[op.etapa as EtapaFunil]; const ant = ANTERIOR[op.etapa as EtapaFunil]; return (
{nomePrincipal(op)} {op.titulo && ( {op.titulo} )}
)}
{op.etapa !== 'perdido' && op.etapa !== 'ganho' && ( )} {prox && ( )} {op.etapa === 'ganho' && ( Ganho )} ); } // ─── Modal criar/editar ─────────────────────────────────────────────────────── type FormValues = { titulo: string; etapa: EtapaFunil; nomeProspect?: string; empresaProspect?: string; valorEstimado?: number; observacoes?: string; }; function OportModal({ open, initial, etapaInicial, onClose, onSave, }: { open: boolean; initial?: Oportunidade | null; etapaInicial: EtapaFunil; onClose: () => void; onSave: (dto: CreateOportunidadeDto | UpdateOportunidadeDto) => Promise; }) { const [form] = Form.useForm(); const [saving, setSaving] = useState(false); const handleOk = async () => { const values = await form.validateFields(); setSaving(true); try { await onSave({ titulo: values.titulo, etapa: values.etapa, nomeProspect: values.nomeProspect ?? null, empresaProspect: values.empresaProspect ?? null, valorEstimado: values.valorEstimado ?? null, observacoes: values.observacoes ?? null, }); onClose(); } finally { setSaving(false); } }; return ( { if (vis) { form.setFieldsValue( initial ? { titulo: initial.titulo, etapa: initial.etapa as EtapaFunil, nomeProspect: initial.nomeProspect ?? undefined, empresaProspect: initial.empresaProspect ?? undefined, valorEstimado: initial.valorEstimado ? Number(initial.valorEstimado) : undefined, observacoes: initial.observacoes ?? undefined, } : { etapa: etapaInicial }, ); } else { form.resetFields(); } }} >
String(v).replace(/\B(?=(\d{3})+(?!\d))/g, '.')} parser={(v) => Number((v ?? '').replace(/\./g, '').replace(',', '.'))} placeholder="0,00" />