testes/src_2/features/autolab/views/VendasView.jsx

258 lines
15 KiB
JavaScript

import React, { useState, useMemo } from 'react';
import { useAutoLab } from '../hooks/useAutoLab';
// Importação local do ExcelTable para garantir isolamento total conforme Regra de Ouro
import ExcelTable from '../components/ExcelTable';
import { AutoLabDetailPanel } from '../components/AutoLabDetailPanel';
import {
Plus, FileText, ShoppingCart, Clock, ClipboardCheck,
User, Package, Calendar, Info, Mail, Phone,
Settings, Image, List, Save, Trash2, Tag, Hash, File
} from 'lucide-react';
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button";
import { toast } from 'sonner';
export const VendasView = () => {
const { data: vendas, loading } = useAutoLab('vendas');
const [activeTab, setActiveTab] = useState('orcamentos');
const [selectedVenda, setSelectedVenda] = useState(null);
const [isPanelOpen, setIsPanelOpen] = useState(false);
const handleRowClick = (row) => {
setSelectedVenda(row);
setIsPanelOpen(true);
};
const vendasColumns = [
{ header: 'Cliente', field: 'cliente', width: '250px', className: 'font-bold' },
{ header: 'Data', field: 'data', width: '100px' },
{ header: 'Digitador', field: 'digitador', width: '100px' },
{ header: 'Email', field: 'email', width: '200px' },
{ header: 'Equipamento', field: 'equipamento', width: '150px' },
{ header: 'Frete', field: 'frete', width: '100px' },
{ header: 'Frota', field: 'frota', width: '80px' },
{ header: 'Hora', field: 'hora', width: '100px' },
{ header: 'Cód. Solicitação', field: 'id_solicitacao', width: '120px', className: 'font-bold text-emerald-600' },
{ header: 'Modelo', field: 'modelo', width: '100px' },
{ header: 'Placa', field: 'placa', width: '100px', className: 'font-mono' },
{ header: 'Prazo Entrega', field: 'prazo_entrega', width: '120px' },
{ header: 'Resp. Orç.', field: 'responsavel_orcamento', width: '120px' },
];
return (
<div className="flex flex-col h-full bg-white dark:bg-[#1b1b1b]">
{/* Header Toolbar */}
<div className="p-4 border-b dark:border-zinc-800 bg-slate-50/50 dark:bg-zinc-900/20 flex flex-wrap items-center justify-between gap-4">
<div className="flex items-center gap-4 flex-1">
<Tabs value={activeTab} onValueChange={setActiveTab} className="bg-white dark:bg-zinc-900 p-1 rounded-xl border dark:border-zinc-800 shadow-sm">
<TabsList className="bg-transparent border-none gap-1 h-8">
<TabsTrigger value="orcamentos" className="data-[state=active]:bg-[#1b4332] data-[state=active]:text-white rounded-lg px-4 transition-all uppercase text-[10px] font-bold">
<FileText size={16} className="mr-2" /> Orçamentos
</TabsTrigger>
<TabsTrigger value="realizadas" className="data-[state=active]:bg-[#1b4332] data-[state=active]:text-white rounded-lg px-4 transition-all uppercase text-[10px] font-bold">
<ShoppingCart size={16} className="mr-2" /> Vendas Realizadas
</TabsTrigger>
<TabsTrigger value="os" className="data-[state=active]:bg-[#1b4332] data-[state=active]:text-white rounded-lg px-4 transition-all uppercase text-[10px] font-bold">
<ClipboardCheck size={16} className="mr-2" /> Ordem de Serviço
</TabsTrigger>
</TabsList>
</Tabs>
</div>
<div className="flex items-center gap-3">
<Button className="bg-[#1b4332] hover:bg-[#2d6a4f] text-white rounded-xl px-4 py-2 font-bold shadow-lg shadow-emerald-900/10 flex items-center gap-2 uppercase text-[10px]">
<Plus size={18} /> Novo Orçamento
</Button>
</div>
</div>
{/* Main Table Content */}
<div className="flex-1 overflow-hidden">
<ExcelTable
data={vendas}
loading={loading}
columns={vendasColumns}
onRowClick={handleRowClick}
rowKey="id"
/>
</div>
{/* Slide-over Detail Panel */}
<AutoLabDetailPanel
isOpen={isPanelOpen}
onClose={() => setIsPanelOpen(false)}
title={selectedVenda?.cliente || 'Detalhes da Venda'}
subtitle={`Solicitação #${selectedVenda?.id_solicitacao || ''}`}
status={selectedVenda?.status}
statusColor="bg-orange-500/10 text-orange-600"
actions={[
{ label: 'Salvar', onClick: () => toast.success('Venda Salva!'), variant: 'default', className: 'bg-[#1b4332] hover:bg-[#2d6a4f] text-white' },
{ label: 'Excluir', onClick: () => toast.error('Solicitação excluída'), isDestructive: true }
]}
tabs={[
{
id: 'detalhes',
label: 'Detalhes',
content: (
<div className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<DetailItem label="Aplicação:" value={selectedVenda?.aplicacao} />
<DetailItem label="Data:" value={selectedVenda?.data} />
<DetailItem label="Desconto:" value={selectedVenda?.desconto} />
<DetailItem label="Digitador:" value={selectedVenda?.digitador} />
<DetailItem label="Email:" value={selectedVenda?.email} />
<DetailItem label="Equipamento:" value={selectedVenda?.equipamento} />
<DetailItem label="Frete:" value={selectedVenda?.frete} />
<DetailItem label="Frota:" value={selectedVenda?.frota} />
<DetailItem label="Garantia:" value={selectedVenda?.garantia} />
<DetailItem label="Hora:" value={selectedVenda?.hora} />
<DetailItem label="Cod. Solicitação:" value={selectedVenda?.id_solicitacao} />
<DetailItem label="Cod. Cliente:" value={selectedVenda?.cod_cliente} />
<DetailItem label="Info:" value={selectedVenda?.info_cliente} />
<DetailItem label="Modelo:" value={selectedVenda?.modelo} />
<DetailItem label="Placa:" value={selectedVenda?.placa} />
<DetailItem label="Prazo Entrega:" value={selectedVenda?.prazo_entrega} />
<DetailItem label="Resp. Orç.:" value={selectedVenda?.responsavel_orcamento} />
</div>
<div className="mt-4 p-4 bg-slate-50 dark:bg-zinc-900 rounded-xl border dark:border-zinc-800">
<span className="text-[10px] font-bold uppercase text-slate-400">Descrição:</span>
<p className="text-sm mt-1">{selectedVenda?.descricao}</p>
</div>
</div>
)
},
{
id: 'editar',
label: 'Editar',
content: (
<div className="space-y-6">
<Tabs defaultValue="base" className="w-full">
<TabsList className="bg-slate-100 dark:bg-zinc-800 p-1 rounded-lg w-full justify-start gap-1">
<TabsTrigger value="base" className="h-8 w-8 p-0 rounded-md data-[state=active]:bg-white dark:data-[state=active]:bg-zinc-700 shadow-sm"><User size={16} /></TabsTrigger>
<TabsTrigger value="config" className="h-8 w-8 p-0 rounded-md data-[state=active]:bg-white dark:data-[state=active]:bg-zinc-700 shadow-sm"><Settings size={16} /></TabsTrigger>
<TabsTrigger value="images" className="h-8 w-8 p-0 rounded-md data-[state=active]:bg-white dark:data-[state=active]:bg-zinc-700 shadow-sm"><Image size={16} /></TabsTrigger>
<TabsTrigger value="items" className="h-8 w-8 p-0 rounded-md data-[state=active]:bg-white dark:data-[state=active]:bg-zinc-700 shadow-sm"><List size={16} /></TabsTrigger>
</TabsList>
<div className="mt-6">
<TabsContent value="base" className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<EditField label="Data:" value={selectedVenda?.data} />
<EditField label="Hora:" value={selectedVenda?.hora} />
<EditField label="Digitador:" value={selectedVenda?.digitador} />
<EditField label="Resp. Orçamento:" value={selectedVenda?.responsavel_orcamento} />
<EditField label="Placa:" value={selectedVenda?.placa} />
<EditField label="Modelo:" value={selectedVenda?.modelo} />
<EditField label="Frota:" value={selectedVenda?.frota} />
<EditField label="Equipamento:" value={selectedVenda?.equipamento} />
<EditField label="Aplicação:" value={selectedVenda?.aplicacao} />
<div className="col-span-2">
<EditField label="Cliente:" value={selectedVenda?.cliente} />
</div>
</div>
</TabsContent>
<TabsContent value="config" className="space-y-4">
<div className="space-y-4">
<div className="space-y-1.5">
<label className="text-[10px] font-bold uppercase text-slate-400 ml-1">info_cliente:</label>
<textarea className="w-full bg-slate-50 dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-lg p-3 text-sm min-h-[100px]" defaultValue={selectedVenda?.info_cliente} />
</div>
<div className="space-y-1.5">
<label className="text-[10px] font-bold uppercase text-slate-400 ml-1">relatorio_oficina:</label>
<textarea className="w-full bg-slate-50 dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-lg p-3 text-sm min-h-[100px]" defaultValue={selectedVenda?.relatorio_oficina} />
</div>
<div className="space-y-1.5">
<label className="text-[10px] font-bold uppercase text-slate-400 ml-1">obs:</label>
<textarea className="w-full bg-slate-50 dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-lg p-3 text-sm min-h-[100px]" defaultValue={selectedVenda?.obs} />
</div>
</div>
</TabsContent>
<TabsContent value="images" className="space-y-4">
<div className="border-2 border-dashed border-slate-200 dark:border-zinc-800 rounded-2xl p-8 text-center space-y-3">
<label className="cursor-pointer block">
<div className="bg-slate-100 dark:bg-zinc-800 w-12 h-12 rounded-full flex items-center justify-center mx-auto mb-2 text-slate-400">
<Plus size={24} />
</div>
<span className="text-sm font-bold block">Anexar imagens</span>
<span className="text-xs text-slate-400">Arraste ou clique para selecionar</span>
<input type="file" className="hidden" />
</label>
</div>
</TabsContent>
<TabsContent value="items" className="space-y-6">
<div className="bg-slate-50 dark:bg-zinc-900/50 p-4 rounded-xl border dark:border-zinc-800 space-y-4">
<div className="grid grid-cols-2 gap-4">
<EditField label="Preço:" value="-- Escolha uma opção --" select />
<EditField label="Item:" placeholder="Pesquisar Item..." />
<EditField label="Cod Peças:" />
<EditField label="Qtd Peças:" />
<EditField label="Unid Peças:" value="-- Escolha uma opção --" select />
<EditField label="Modelo:" />
<EditField label="Marca:" />
<EditField label="Fornecedor:" />
<EditField label="Preço Unitário:" />
</div>
<Button className="w-full bg-emerald-600 hover:bg-emerald-700 text-white font-bold h-10 mt-2">
Inserir
</Button>
</div>
<div className="space-y-3">
<h4 className="text-[10px] font-black uppercase text-slate-400 tracking-widest pl-1">Itens Adicionados</h4>
{selectedVenda?.items?.map(item => (
<div key={item.id} className="p-4 bg-emerald-500/5 border border-emerald-500/10 rounded-xl relative group">
<p className="text-xs font-bold text-emerald-800 dark:text-emerald-400 pr-8">{item.item}</p>
<div className="grid grid-cols-3 gap-2 mt-2 text-[10px] text-slate-500">
<span>Qtd: {item.qtd}</span>
<span>Preço: {item.preco}</span>
<span>Marca: {item.marca}</span>
</div>
<button className="absolute top-4 right-4 text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity">
<Trash2 size={16} />
</button>
</div>
))}
</div>
</TabsContent>
</div>
</Tabs>
</div>
)
}
]}
/>
</div>
);
};
// Helper components
const DetailItem = ({ label, value }) => (
<div className="flex flex-col gap-0.5">
<span className="text-[10px] font-black uppercase text-slate-400 tracking-wider leading-none">{label}</span>
<span className="text-sm font-bold text-slate-800 dark:text-slate-100">{value || '---'}</span>
</div>
);
const EditField = ({ label, value, placeholder, select }) => (
<div className="space-y-1.5">
<label className="text-[10px] font-black uppercase text-slate-400 tracking-wider ml-1 leading-none">{label}</label>
{select ? (
<select className="w-full bg-slate-50 dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-lg px-3 h-10 text-xs font-semibold focus:ring-2 focus:ring-emerald-500/20 outline-none transition-all">
<option>{value}</option>
</select>
) : (
<input
type="text"
className="w-full bg-slate-50 dark:bg-zinc-950 border border-slate-200 dark:border-zinc-800 rounded-lg px-3 h-10 text-xs font-semibold placeholder:text-slate-400 focus:ring-2 focus:ring-emerald-500/20 outline-none transition-all"
defaultValue={value}
placeholder={placeholder}
/>
)}
</div>
);
const Separator = () => <div className="h-px w-full bg-slate-100 dark:bg-zinc-800" />;