// Cadastro de operadores (pessoas alocaveis no grid HRC). Arquivo proprio, mesmo // motivo do instancias.jsx: nao inflar mais views.jsx. const { useState: useStateO, useEffect: useEffectO } = React; function OperadoresView({ podeEditar }) { const [operadores, setOperadores] = useStateO([]); const [loading, setLoading] = useStateO(true); const [saving, setSaving] = useStateO(false); const [error, setError] = useStateO(''); const [form, setForm] = useStateO({ nome: '', apelido: '', cor: '' }); const [editando, setEditando] = useStateO(null); // { id, nome, apelido, cor } const carregar = async () => { setLoading(true); setError(''); try { const r = await window.rcFetch('/api/operadores?incluir_inativos=1'); if (!r.ok) { const d = await r.json().catch(() => ({})); setError(d.detail || 'Falha ao carregar operadores'); return; } setOperadores(await r.json()); } catch (_) { setError('Erro de conexao'); } finally { setLoading(false); } }; useEffectO(() => { carregar(); }, []); const setField = (key, value) => setForm(prev => ({ ...prev, [key]: value })); const criar = async (e) => { e?.preventDefault?.(); if (!form.nome.trim()) { setError('Informe o nome'); return; } setSaving(true); setError(''); try { const r = await window.rcFetch('/api/operadores', { method: 'POST', body: JSON.stringify({ nome: form.nome.trim(), apelido: form.apelido.trim() || null, cor: form.cor || null, }), }); if (!r.ok) { const d = await r.json().catch(() => ({})); setError(d.detail || 'Falha ao criar operador'); return; } setForm({ nome: '', apelido: '', cor: '' }); await carregar(); } catch (_) { setError('Erro de conexao'); } finally { setSaving(false); } }; const atualizar = async (operador, patch) => { setSaving(true); setError(''); try { const r = await window.rcFetch(`/api/operadores/${operador.id}`, { method: 'PUT', body: JSON.stringify(patch), }); if (!r.ok) { const d = await r.json().catch(() => ({})); setError(d.detail || 'Falha ao atualizar operador'); return; } await carregar(); } catch (_) { setError('Erro de conexao'); } finally { setSaving(false); } }; const salvarEdicao = async () => { if (!editando) return; await atualizar(editando, { nome: editando.nome.trim(), apelido: editando.apelido.trim() || null, cor: editando.cor || null, }); setEditando(null); }; return (
{podeEditar ? (
Novo operador
setField('nome', v)} placeholder="Nome completo" icon="user" />
setField('apelido', v)} placeholder="Como aparece no grid" />
setField('cor', e.target.value)} style={{ width: 36, height: 28, padding: 0, border: '1px solid var(--line)', borderRadius: 5, background: 'transparent', cursor: 'pointer' }} /> {form.cor ? ( setField('cor', '')}>Cor automática ) : ( Sem cor definida usa uma cor automática por id )}
{error && (
{error}
)} {saving ? 'Salvando...' : 'Criar operador'}
) : (error && (
{error}
))}
Operadores {operadores.length}
Atualizar
{podeEditar ? : null} {loading ? ( ) : !operadores.length ? ( ) : operadores.map(op => ( {podeEditar ? ( ) : null} ))}
Nome Apelido StatusAções
Carregando...
Nenhum operador cadastrado.
{op.nome} {op.apelido || '-'} {op.ativo ? Ativo : Inativo}
setEditando({ id: op.id, nome: op.nome, apelido: op.apelido || '', cor: op.cor || '' })} disabled={saving} /> atualizar(op, { ativo: !op.ativo })} disabled={saving}> {op.ativo ? 'Desativar' : 'Ativar'}
{editando ? (
setEditando(null)}>
e.stopPropagation()}>

Editar operador

setEditando(m => ({ ...m, nome: v }))} icon="user" />
setEditando(m => ({ ...m, apelido: v }))} />
setEditando(m => ({ ...m, cor: e.target.value }))} style={{ width: 36, height: 28, padding: 0, border: '1px solid var(--line)', borderRadius: 5, background: 'transparent', cursor: 'pointer' }} />
setEditando(null)} disabled={saving}>Cancelar {saving ? 'Salvando…' : 'Salvar'}
) : null}
); } Object.assign(window, { OperadoresView });