// WorkOrders.jsx 'use strict'; const { useState, useEffect, useRef } = React; const STATUSES = ['Aberta','Em andamento','Aguardando peça','Concluída','Entregue']; const EQUIP_TYPES = ['Smartphone','Notebook','Desktop','Tablet','TV','Impressora','Outro']; const equipIcon = { Smartphone:'Smartphone', Notebook:'Laptop', Desktop:'Monitor', TV:'Tv', Tablet:'Smartphone' }; // ── Print Template ────────────────────────────────────────────────────────── function PrintOS({ os, company }) { if (!os) return null; const c = company || {}; const printNode = (
{/* Header */}
{c.name
{c.cnpj &&
CNPJ: {c.cnpj}
} {c.address &&
{c.address}
}
{[c.phone, c.email, c.website].filter(Boolean).join(' • ')}
ORDEM DE SERVIÇO
#{os.num}
Entrada{fmtDate(os.entryDate)}
Prazo{fmtDate(os.deadline)}
Status{os.status}
{/* Client + Equipment */}
Dados do Cliente
Nome: {os.clientName}
Telefone: {os.clientPhone||'—'}
E-mail: {os.clientEmail||'—'}
Dados do Equipamento
Tipo: {os.equipment?.type}
Marca/Modelo: {os.equipment?.brand} {os.equipment?.model}
Série: {os.equipment?.serial||'—'}
Acessórios: {os.equipment?.accessories||'—'}
{/* Defect + Diagnosis */}
Defeito Relatado
{os.defect||'—'}
Diagnóstico Técnico
{os.diagnosis||'—'}
{/* Items table */}
Serviços e Peças
{(os.items||[]).map((item,i) => ( ))}
Descrição Qtd. Valor Unit. Total
{item.desc} {item.qty} {fmtCurrency(item.unit)} {fmtCurrency(item.total)}
TOTAL GERAL {fmtCurrency(os.total||0)}
{/* Signature + Footer */}
Assinatura do Cliente
Assinatura do Técnico — {os.tech}
Ao assinar este documento, o cliente declara estar ciente dos serviços realizados e concorda com os valores cobrados. {c.terms && <>
{c.terms}}
{[c.name, c.cnpj && ('CNPJ ' + c.cnpj), c.email, c.phone].filter(Boolean).join(' • ')}
); return ReactDOM.createPortal(printNode, document.body); } // ── OS Modal (create/edit) ────────────────────────────────────────────────── function OSModal({ open, onClose, onSave, clients, services, editOS }) { const empty = { clientId:'', clientName:'', clientPhone:'', clientEmail:'', equipment:{ type:'Smartphone', brand:'', model:'', serial:'', password:'', accessories:'' }, defect:'', diagnosis:'', items:[], status:'Aberta', entryDate:new Date().toISOString().split('T')[0], deadline:'', notes:'', tech:'Carlos Ferreira' }; const [form, setForm] = useState(empty); const [errors, setErrors] = useState({}); useEffect(() => { if (open) setForm(editOS ? { ...editOS } : { ...empty, items:[] }); }, [open, editOS]); const set = (key, val) => setForm(f => ({ ...f, [key]: val })); const setEquip = (key, val) => setForm(f => ({ ...f, equipment: { ...f.equipment, [key]: val } })); const addItem = () => setForm(f => ({ ...f, items:[...f.items,{ desc:'', qty:1, unit:0, total:0 }] })); const removeItem = i => setForm(f => ({ ...f, items: f.items.filter((_,idx)=>idx!==i) })); const setItem = (i, key, val) => setForm(f => { const items = f.items.map((item, idx) => { if (idx !== i) return item; const updated = { ...item, [key]: key==='qty'||key==='unit' ? parseFloat(val)||0 : val }; updated.total = updated.qty * updated.unit; return updated; }); return { ...f, items }; }); const total = form.items.reduce((s,i) => s + (i.total||0), 0); const onClientChange = id => { const c = clients.find(x => x.id === id); if (c) set('clientId', id); setForm(f=>({...f, clientId:id, clientName:c?.name||'', clientPhone:c?.phone||'', clientEmail:c?.email||''})); }; const addServiceItem = svcId => { const s = services.find(x => x.id === svcId); if (!s) return; setForm(f=>({...f, items:[...f.items,{ desc:s.name, qty:1, unit:s.basePrice, total:s.basePrice }]})); }; const validate = () => { const e = {}; if (!form.clientId) e.clientId = 'Selecione um cliente'; if (!form.equipment.brand) e.brand = 'Informe a marca'; if (!form.equipment.model) e.model = 'Informe o modelo'; if (!form.defect) e.defect = 'Descreva o defeito'; if (!form.deadline) e.deadline = 'Informe o prazo'; setErrors(e); return Object.keys(e).length === 0; }; const handleSave = (print=false) => { if (!validate()) return; onSave({ ...form, total }, print); onClose(); }; return (
{/* Client */}

Cliente

set('clientPhone',e.target.value)} placeholder="(11) 99999-9999"/> set('clientEmail',e.target.value)} placeholder="cliente@email.com"/>
{/* Equipment */}

Equipamento

setEquip('brand',e.target.value)} placeholder="Samsung, Apple..."/> setEquip('model',e.target.value)} placeholder="Galaxy S23..."/> setEquip('serial',e.target.value)} placeholder="SN123456"/> setEquip('password',e.target.value)} placeholder="1234"/> setEquip('accessories',e.target.value)} placeholder="Carregador, capa..."/>
{/* Defect + Diagnosis */}