import { useState, useRef, useEffect } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Checkbox } from "@/components/ui/checkbox"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { useToast } from "@/hooks/use-toast"; import { Printer, Save, FileText, Pen, X, RotateCcw, Search, User } from "lucide-react"; interface Person { id: number; fullName: string; cpfCnpj: string; phone?: string; email?: string; } interface TradeInFormProps { onClose: () => void; onSave?: (data: any) => void; initialEvaluation?: any; customerId?: number; } interface ChecklistItem { id: string; description: string; value: "sim" | "nao" | ""; observation: string; } interface PartItem { peca: string; valor: string; } const DEFAULT_CHECKLIST: ChecklistItem[] = [ { id: "liga", description: "Aparelho liga corretamente", value: "", observation: "" }, { id: "avarias", description: "Avarias, travamentos ou toque fantasma", value: "", observation: "" }, { id: "manchas_tela", description: "Manchas na tela", value: "", observation: "" }, { id: "botoes", description: "Botões funcionando", value: "", observation: "" }, { id: "marcas_uso", description: "Marcas de uso", value: "", observation: "" }, { id: "wifi", description: "Wi-Fi funcionando", value: "", observation: "" }, { id: "chip", description: "Chip funcionando", value: "", observation: "" }, { id: "4g5g", description: "4G/5G funcionando", value: "", observation: "" }, { id: "sensores", description: "Sensores funcionando / NFC", value: "", observation: "" }, { id: "faceid", description: "Face ID / Touch ID funcionando", value: "", observation: "" }, { id: "microfones", description: "Microfones funcionando", value: "", observation: "" }, { id: "auricular", description: "Áudio auricular funcionando", value: "", observation: "" }, { id: "altofalante", description: "Áudio alto-falante funcionando", value: "", observation: "" }, { id: "carregamento", description: "Entrada de carregamento funcionando", value: "", observation: "" }, { id: "cameras", description: "Câmeras funcionando / Manchas", value: "", observation: "" }, { id: "flash", description: "Flash funcionando", value: "", observation: "" }, { id: "carregador", description: "Possui carregador", value: "", observation: "" }, { id: "3utools", description: "Análise pelo 3uTools OK", value: "", observation: "" }, ]; export default function TradeInForm({ onClose, onSave, initialEvaluation, customerId }: TradeInFormProps) { const { toast } = useToast(); const printRef = useRef(null); const canvasRef = useRef(null); const employeeCanvasRef = useRef(null); const [formData, setFormData] = useState({ data: new Date().toLocaleDateString("pt-BR"), senha: "", cliente: "", cpf: "", aparelho: "", imei: "", valor: "", consultor: "", venda: "", saudeBateria: "", }); const [availableEvaluations, setAvailableEvaluations] = useState([]); const [showEvaluationPicker, setShowEvaluationPicker] = useState(false); const [loadingEvaluations, setLoadingEvaluations] = useState(false); const [parts, setParts] = useState([ { peca: "", valor: "" }, { peca: "", valor: "" }, { peca: "", valor: "" }, { peca: "", valor: "" }, { peca: "", valor: "" }, ]); const [checklist, setChecklist] = useState(DEFAULT_CHECKLIST); const [declarations, setDeclarations] = useState({ removeuDados: false, transferePropriedade: false, }); const [customerSignature, setCustomerSignature] = useState(null); const [employeeSignature, setEmployeeSignature] = useState(null); const [isSigningCustomer, setIsSigningCustomer] = useState(false); const [isSigningEmployee, setIsSigningEmployee] = useState(false); const [isDrawing, setIsDrawing] = useState(false); const [personsList, setPersonsList] = useState([]); const [filteredPersons, setFilteredPersons] = useState([]); const [showPersonDropdown, setShowPersonDropdown] = useState(false); const [selectedPersonId, setSelectedPersonId] = useState(null); const personSearchRef = useRef(null); useEffect(() => { const loadPersons = async () => { try { const res = await fetch("/api/erp/persons", { credentials: "include" }); if (res.ok) { const data = await res.json(); setPersonsList(data); } } catch (error) { console.error("Error loading persons:", error); } }; loadPersons(); }, []); useEffect(() => { const loadEvaluations = async () => { setLoadingEvaluations(true); try { const res = await fetch("/api/retail/evaluations?status=approved,pending", { credentials: "include" }); if (res.ok) { const data = await res.json(); setAvailableEvaluations(data); } } catch (error) { console.error("Error loading evaluations:", error); } finally { setLoadingEvaluations(false); } }; loadEvaluations(); }, []); useEffect(() => { if (initialEvaluation) { loadEvaluationData(initialEvaluation); } }, [initialEvaluation]); const loadEvaluationData = (evaluation: any) => { const notesData = evaluation.notes ? JSON.parse(evaluation.notes) : {}; setFormData({ data: evaluation.evaluationDate ? new Date(evaluation.evaluationDate).toLocaleDateString("pt-BR") : new Date().toLocaleDateString("pt-BR"), senha: notesData.senha || "", cliente: evaluation.customerName || "", cpf: evaluation.customerCpf || "", aparelho: `${evaluation.brand || ""} ${evaluation.model || ""}`.trim(), imei: evaluation.imei || "", valor: evaluation.estimatedValue ? `R$ ${parseFloat(evaluation.estimatedValue).toLocaleString("pt-BR", { minimumFractionDigits: 2 })}` : "", consultor: notesData.consultor || "", venda: notesData.venda || "", saudeBateria: evaluation.batteryHealth?.toString() || "", }); if (notesData.parts) setParts(notesData.parts); if (notesData.checklist) setChecklist(notesData.checklist); if (notesData.declarations) setDeclarations(notesData.declarations); setShowEvaluationPicker(false); toast({ title: "Dados da avaliação carregados!" }); }; useEffect(() => { if (formData.cliente.length >= 2 && !selectedPersonId) { const filtered = personsList.filter(p => p.fullName.toLowerCase().includes(formData.cliente.toLowerCase()) || (p.cpfCnpj && p.cpfCnpj.includes(formData.cliente)) ); setFilteredPersons(filtered); setShowPersonDropdown(filtered.length > 0); } else { setShowPersonDropdown(false); } }, [formData.cliente, personsList, selectedPersonId]); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (personSearchRef.current && !personSearchRef.current.contains(event.target as Node)) { setShowPersonDropdown(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, []); const selectPerson = (person: Person) => { setFormData({ ...formData, cliente: person.fullName, cpf: person.cpfCnpj || "", }); setSelectedPersonId(person.id); setShowPersonDropdown(false); }; useEffect(() => { if (isSigningCustomer && canvasRef.current) { const canvas = canvasRef.current; const ctx = canvas.getContext("2d"); if (ctx) { ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = "#000000"; ctx.lineWidth = 2; ctx.lineCap = "round"; ctx.lineJoin = "round"; } } }, [isSigningCustomer]); useEffect(() => { if (isSigningEmployee && employeeCanvasRef.current) { const canvas = employeeCanvasRef.current; const ctx = canvas.getContext("2d"); if (ctx) { ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = "#000000"; ctx.lineWidth = 2; ctx.lineCap = "round"; ctx.lineJoin = "round"; } } }, [isSigningEmployee]); const startDrawing = (e: React.MouseEvent | React.TouchEvent, canvas: HTMLCanvasElement | null) => { if (!canvas) return; setIsDrawing(true); const ctx = canvas.getContext("2d"); if (!ctx) return; const rect = canvas.getBoundingClientRect(); const x = "touches" in e ? e.touches[0].clientX - rect.left : e.clientX - rect.left; const y = "touches" in e ? e.touches[0].clientY - rect.top : e.clientY - rect.top; ctx.beginPath(); ctx.moveTo(x, y); }; const draw = (e: React.MouseEvent | React.TouchEvent, canvas: HTMLCanvasElement | null) => { if (!isDrawing || !canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const rect = canvas.getBoundingClientRect(); const x = "touches" in e ? e.touches[0].clientX - rect.left : e.clientX - rect.left; const y = "touches" in e ? e.touches[0].clientY - rect.top : e.clientY - rect.top; ctx.lineTo(x, y); ctx.stroke(); }; const stopDrawing = () => { setIsDrawing(false); }; const clearSignature = (isCustomer: boolean) => { const canvas = isCustomer ? canvasRef.current : employeeCanvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (ctx) { ctx.fillStyle = "#ffffff"; ctx.fillRect(0, 0, canvas.width, canvas.height); } }; const saveSignature = (isCustomer: boolean) => { const canvas = isCustomer ? canvasRef.current : employeeCanvasRef.current; if (!canvas) return; const dataUrl = canvas.toDataURL("image/png"); if (isCustomer) { setCustomerSignature(dataUrl); setIsSigningCustomer(false); } else { setEmployeeSignature(dataUrl); setIsSigningEmployee(false); } }; const updateChecklist = (id: string, field: "value" | "observation", val: any) => { setChecklist(prev => prev.map(item => item.id === id ? { ...item, [field]: val } : item )); }; const updatePart = (index: number, field: "peca" | "valor", val: string) => { setParts(prev => prev.map((p, i) => i === index ? { ...p, [field]: val } : p )); }; const handlePrint = () => { const printContent = printRef.current; if (!printContent) return; const printWindow = window.open("", "_blank"); if (!printWindow) { toast({ title: "Erro ao abrir janela de impressão", variant: "destructive" }); return; } printWindow.document.write(` Checklist Trade-In - ${formData.cliente}

CHECKLIST DE AVALIAÇÃO - TRADE-IN

SUPERSTORE

DATA: ${formData.data} SENHA: ${formData.senha}
CLIENTE: ${formData.cliente}
CPF: ${formData.cpf}
APARELHO: ${formData.aparelho}
IMEI: ${formData.imei}
VALOR: ${formData.valor}
CONSULTOR: ${formData.consultor}
VENDA: ${formData.venda}
VALOR DO APARELHO E PEÇAS – RELATÓRIO INTERNO
${parts.map((p, i) => `
Peça ${i + 1}: ${p.peca}
Valor: ${p.valor}
`).join("")}
TERMO DE TRANSFERÊNCIA DE PROPRIEDADE DO APARELHO (CONTINGÊNCIA)

Na condição de proprietário do aparelho acima descrito, declaro, por livre e espontânea vontade, a boa procedência do equipamento, transferindo neste ato sua propriedade à SUPERSTORE. Declaro que o aparelho não contém dados pessoais ou de terceiros. Autorizo expressamente que, caso sejam encontrados quaisquer dados no dispositivo, seja realizada a remoção e destruição definitiva das informações, sem possibilidade de recuperação. Reconheço que esta decisão é irrevogável e assumo total responsabilidade por ela.
${checklist.map(item => ` `).join("")}
Descrição Sim Não Observações
${item.description} ${item.value === "sim" ? "✓" : ""} ${item.value === "nao" ? "✓" : ""} ${item.observation}
Saúde da Bateria ${formData.saudeBateria}%
DECLARAÇÕES DO CLIENTE
Declaro que removi todas as minhas informações pessoais do dispositivo antes da entrega: ( ${declarations.removeuDados ? "X" : " "} ) Sim ( ${!declarations.removeuDados ? "X" : " "} ) Não
Declaro que estou transferindo a propriedade do meu aparelho: ( ${declarations.transferePropriedade ? "X" : " "} ) Sim ( ${!declarations.transferePropriedade ? "X" : " "} ) Não
${employeeSignature ? `` : ""}
Assinatura do Vendedor
${formData.consultor}
${customerSignature ? `` : ""}
Assinatura do Cliente
${formData.cliente}
CPF: ${formData.cpf}
`); printWindow.document.close(); }; const handleSave = async () => { if (!formData.cliente || !formData.imei || !formData.aparelho) { toast({ title: "Preencha os campos obrigatórios", variant: "destructive" }); return; } try { const res = await fetch("/api/retail/evaluations", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ imei: formData.imei, brand: formData.aparelho.split(" ")[0], model: formData.aparelho, customerName: formData.cliente, customerCpf: formData.cpf, estimatedValue: formData.valor.replace(/[^\d,]/g, "").replace(",", "."), batteryHealth: parseInt(formData.saudeBateria) || null, status: "pending", notes: JSON.stringify({ senha: formData.senha, consultor: formData.consultor, venda: formData.venda, parts, checklist, declarations, }), }), }); if (res.ok) { const evaluation = await res.json(); if (customerSignature) { await fetch("/api/retail/transfer-documents", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ evaluationId: evaluation.id, customerName: formData.cliente, customerCpf: formData.cpf, deviceBrand: formData.aparelho.split(" ")[0], deviceModel: formData.aparelho, deviceImei: formData.imei, agreedValue: formData.valor.replace(/[^\d,]/g, "").replace(",", ".") || "0", customerSignature, employeeSignature, employeeName: formData.consultor, termsAccepted: declarations.transferePropriedade, }), }); } toast({ title: "Avaliação salva com sucesso!" }); onSave?.(evaluation); onClose(); } } catch (error) { toast({ title: "Erro ao salvar avaliação", variant: "destructive" }); } }; return (

Checklist de Avaliação - Trade-In

{showEvaluationPicker && (
Selecionar Avaliação Existente
{loadingEvaluations ? (

Carregando avaliações...

) : availableEvaluations.length === 0 ? (

Nenhuma avaliação pendente ou aprovada encontrada.

) : (
{availableEvaluations.map((evaluation) => (
loadEvaluationData(evaluation)} data-testid={`evaluation-item-${evaluation.id}`} >

{evaluation.brand} {evaluation.model}

IMEI: {evaluation.imei}

Cliente: {evaluation.customerName || "Não informado"}

R$ {parseFloat(evaluation.estimatedValue || 0).toLocaleString("pt-BR", { minimumFractionDigits: 2 })}

{evaluation.status === "approved" ? "Aprovado" : "Pendente"}
))}
)}
)} Dados Gerais
setFormData({...formData, data: e.target.value})} />
setFormData({...formData, senha: e.target.value})} placeholder="Senha do atendimento" />
setFormData({...formData, consultor: e.target.value})} placeholder="Nome do vendedor" />
setFormData({...formData, venda: e.target.value})} placeholder="Nº da venda" />
{ setFormData({...formData, cliente: e.target.value}); if (selectedPersonId) setSelectedPersonId(null); }} placeholder="Digite para buscar cliente..." className="pl-9" />
{showPersonDropdown && (
{filteredPersons.map((person) => (
selectPerson(person)} >
{person.fullName}
{person.cpfCnpj}
))}
)}
setFormData({...formData, cpf: e.target.value})} placeholder="000.000.000-00" readOnly={!!selectedPersonId} />
setFormData({...formData, aparelho: e.target.value})} placeholder="iPhone 13 Pro Max 256GB" />
setFormData({...formData, imei: e.target.value})} placeholder="000000000000000" />
setFormData({...formData, valor: e.target.value})} placeholder="R$ 2.500,00" />
Valor do Aparelho e Peças – Relatório Interno
{parts.map((part, idx) => (
updatePart(idx, "peca", e.target.value)} placeholder="Nome da peça" className="h-8 text-sm" />
updatePart(idx, "valor", e.target.value)} placeholder="R$ 0,00" className="h-8 text-sm" />
))}
TERMO DE TRANSFERÊNCIA DE PROPRIEDADE DO APARELHO (CONTINGÊNCIA)

Na condição de proprietário do aparelho acima descrito, declaro, por livre e espontânea vontade, a boa procedência do equipamento, transferindo neste ato sua propriedade à SUPERSTORE. Declaro que o aparelho não contém dados pessoais ou de terceiros. Autorizo expressamente que, caso sejam encontrados quaisquer dados no dispositivo, seja realizada a remoção e destruição definitiva das informações, sem possibilidade de recuperação. Reconheço que esta decisão é irrevogável e assumo total responsabilidade por ela.

Checklist de Avaliação
{checklist.map((item) => ( ))}
Descrição Sim Não Observações
{item.description} updateChecklist(item.id, "value", item.value === "sim" ? "" : "sim")} /> updateChecklist(item.id, "value", item.value === "nao" ? "" : "nao")} /> updateChecklist(item.id, "observation", e.target.value)} placeholder="Obs..." className="h-8 text-sm" />
Saúde da Bateria
setFormData({...formData, saudeBateria: e.target.value})} placeholder="85" className="w-24 h-8" /> %
Declarações do Cliente
setDeclarations({...declarations, removeuDados: v === true})} />
setDeclarations({...declarations, transferePropriedade: v === true})} />
Assinaturas

Assinatura do Vendedor

{employeeSignature ? (
Assinatura do Vendedor
) : isSigningEmployee ? (
startDrawing(e, employeeCanvasRef.current)} onMouseMove={(e) => draw(e, employeeCanvasRef.current)} onMouseUp={stopDrawing} onMouseLeave={stopDrawing} onTouchStart={(e) => startDrawing(e, employeeCanvasRef.current)} onTouchMove={(e) => draw(e, employeeCanvasRef.current)} onTouchEnd={stopDrawing} />
) : ( )}

{formData.consultor || "Nome do vendedor"}

Assinatura do Cliente

{customerSignature ? (
Assinatura do Cliente
) : isSigningCustomer ? (
startDrawing(e, canvasRef.current)} onMouseMove={(e) => draw(e, canvasRef.current)} onMouseUp={stopDrawing} onMouseLeave={stopDrawing} onTouchStart={(e) => startDrawing(e, canvasRef.current)} onTouchMove={(e) => draw(e, canvasRef.current)} onTouchEnd={stopDrawing} />
) : ( )}

{formData.cliente || "Nome do cliente"}
CPF: {formData.cpf || "___.___.___-__"}

); }