// SGAB v2 — Componentes UI Compartilhados const { useState } = React; // ── ICONS ────────────────────────────────────────────────────── const SVG_ICONS = { dashboard:'M3 3h7v7H3zm11 0h7v7h-7zM3 14h7v7H3zm11 7v-4h4v4zm4-7h-7v3h3v4h4z', agenda:'M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z', clientes:'M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2m8-10a4 4 0 100-8 4 4 0 000 8zm7.5 2.5a4 4 0 010 7.5M23 21v-2a4 4 0 00-3-3.87', equipamentos:'M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5', ordens:'M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4', calibracao:'M9 3H5a2 2 0 00-2 2v4m6-6h10a2 2 0 012 2v4M9 3v18m0 0h10a2 2 0 002-2V9M9 21H5a2 2 0 01-2-2V9m0 0h18', propostas:'M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z', financeiro:'M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z', estoque:'M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4', relatorios:'M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z', config:'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z M15 12a3 3 0 11-6 0 3 3 0 016 0z', bell:'M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9', plus:'M12 4v16m8-8H4', edit:'M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z', trash:'M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16', eye:'M15 12a3 3 0 11-6 0 3 3 0 016 0z M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z', check:'M5 13l4 4L19 7', x:'M6 18L18 6M6 6l12 12', search:'M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z', alert:'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z', printer:'M17 17h2a2 2 0 002-2v-4a2 2 0 00-2-2H5a2 2 0 00-2 2v4a2 2 0 002 2h2m2 4h6a2 2 0 002-2v-4a2 2 0 00-2-2H9a2 2 0 00-2 2v4a2 2 0 002 2zm8-12V5a2 2 0 00-2-2H9a2 2 0 00-2 2v4h10z', download:'M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4', logout:'M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1', chevR:'M9 5l7 7-7 7', chevL:'M15 19l-7-7 7-7', chevD:'M19 9l-7 7-7-7', menu:'M4 6h16M4 12h16M4 18h16', close:'M6 18L18 6M6 6l12 12', trend:'M13 7h8m0 0v8m0-8l-8 8-4-4-6 6', scale:'M3 6h18M3 12h18M9 3v18M15 3v18', pkg:'M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4', arrowUp:'M5 10l7-7m0 0l7 7m-7-7v18', arrowDown:'M19 14l-7 7m0 0l-7-7m7 7V3', refresh:'M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15', filter:'M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z', copy:'M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z', mail:'M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z', phone:'M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z', location:'M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z M15 11a3 3 0 11-6 0 3 3 0 016 0z', info:'M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z' }; function Icon({ name, size=18, color='currentColor', style={} }) { const d = SVG_ICONS[name]; if (!d) return null; return ( {d.split(' M').map((part, i) => )} ); } // ── BTN ───────────────────────────────────────────────────────── function Btn({ children, onClick, variant='primary', size='md', icon, disabled=false, type='button', full=false, style:extStyle={} }) { const [hov, setHov] = useState(false); const V = { primary: { bg:'#1E6FD9', hbg:'#1557B0', c:'#fff', b:'transparent' }, secondary: { bg:'#F1F5F9', hbg:'#E2E8F0', c:'#334155', b:'transparent' }, danger: { bg:'#DC2626', hbg:'#B91C1C', c:'#fff', b:'transparent' }, success: { bg:'#16A34A', hbg:'#15803D', c:'#fff', b:'transparent' }, ghost: { bg:'transparent', hbg:'#F1F5F9', c:'#475569', b:'transparent' }, outline: { bg:'transparent', hbg:'#EFF6FF', c:'#1E6FD9', b:'#1E6FD9' }, warning: { bg:'#F59E0B', hbg:'#D97706', c:'#fff', b:'transparent' } }; const S = { sm:{p:'5px 12px',f:12,g:4}, md:{p:'8px 16px',f:14,g:6}, lg:{p:'11px 24px',f:15,g:8} }; const v=V[variant]||V.primary, s=S[size]||S.md; return ( ); } // ── BADGE ─────────────────────────────────────────────────────── function Badge({ children, color='gray' }) { const C={green:{bg:'#DCFCE7',c:'#15803D'},red:{bg:'#FEE2E2',c:'#B91C1C'},yellow:{bg:'#FEF9C3',c:'#A16207'}, blue:{bg:'#DBEAFE',c:'#1D4ED8'},gray:{bg:'#F1F5F9',c:'#475569'},orange:{bg:'#FFEDD5',c:'#C2410C'}, purple:{bg:'#F3E8FF',c:'#7C3AED'},teal:{bg:'#CCFBF1',c:'#0F766E'}}; const cc=C[color]||C.gray; return {children}; } function StatusBadge({ status }) { const MAP={'Concluída':'green','Recebida':'green','Paga':'green','Aprovada':'green','CONFORME':'green','Ativo':'green', 'Em Andamento':'blue','Enviada':'blue','Em Elaboração':'blue','Pendente':'yellow','Agendada':'purple', 'Cancelada':'red','Recusada':'red','Vencida':'red','NÃO CONFORME':'red','Inativo':'red'}; return {status}; } // ── CARD ───────────────────────────────────────────────────────── function Card({ children, style={}, onClick }) { const [hov,setHov]=useState(false); return (
onClick&&setHov(true)} onMouseLeave={()=>setHov(false)} style={{background:'#fff',borderRadius:12,border:'1px solid #E8EDF4', boxShadow:hov&&onClick?'0 4px 12px rgba(30,111,217,0.15)':'0 1px 3px rgba(0,0,0,0.07)', padding:24, cursor:onClick?'pointer':'default', transition:'all 0.15s', ...style}}> {children}
); } // ── MODAL ──────────────────────────────────────────────────────── function Modal({ open, onClose, title, children, width=600, footer }) { if (!open) return null; return (
e.target===e.currentTarget&&onClose()}>

{title}

{children}
{footer &&
{footer}
}
); } // ── CONFIRM ────────────────────────────────────────────────────── function Confirm({ open, msg='Tem certeza?', onConfirm, onCancel }) { if (!open) return null; return (

Confirmar ação

{msg}

Cancelar Confirmar
); } // ── FORM FIELDS ────────────────────────────────────────────────── function FormField({ label, required, children, error, help, col }) { return (
{label&&} {children} {help&&

{help}

} {error&&

{error}

}
); } function Inp({ value, onChange, placeholder, type='text', disabled=false, min, max, step, ...rest }) { const [f,setF]=useState(false); return onChange&&onChange(e.target.value)} placeholder={placeholder} disabled={disabled} min={min} max={max} step={step} onFocus={()=>setF(true)} onBlur={()=>setF(false)} style={{width:'100%',padding:'9px 12px',border:`1.5px solid ${f?'#1E6FD9':'#D1D5DB'}`,borderRadius:8,fontSize:14, background:disabled?'#F9FAFB':'#fff',color:'#111827',outline:'none',fontFamily:'inherit',boxSizing:'border-box',transition:'border-color 0.15s'}} {...rest}/>; } function Sel({ value, onChange, options=[], placeholder='Selecione...', disabled=false }) { const [f,setF]=useState(false); return ( ); } function Txta({ value, onChange, placeholder, rows=3, disabled=false }) { const [f,setF]=useState(false); return