This commit is contained in:
2026-10-29 22:42:37 +02:00
parent 78e89a51d2
commit 53ff46b0a2
52 changed files with 2082 additions and 79 deletions
+4 -2
View File
@@ -1,10 +1,11 @@
import React, { useEffect, useRef, useState } from 'react';
import {visibleWorkshopSections} from './workshop-menu.js';
const kindLabels={assignment:'Responsável atribuído',task:'Tarefa',authorization:'Autorização registada',start:'Início autorizado',time:'Tempo relatado',material:'Material observado'};
const eventLabels={required:'Requisitado',delivered:'Entregue',consumed:'Aplicado/consumido',returned:'Devolvido'};
const decisionLabels={verified:'Verificado',refused:'Recusado',acknowledged:'Ocorrência reconhecida para auditoria — continua fora do âmbito'};
const iso=v=>new Date(v).toISOString();
export default function WorkshopWorkspace({context,can,api,busy}) {
const [data,setData]=useState(null),[orderId,setOrderId]=useState(''),[error,setError]=useState(''),[working,setWorking]=useState(false),[taskId,setTaskId]=useState('');
export default function WorkshopWorkspace({context,can,api,busy,initialOrderId=null,navigate}) {
const [data,setData]=useState(null),[orderId,setOrderId]=useState(initialOrderId??''),[error,setError]=useState(''),[working,setWorking]=useState(false),[taskId,setTaskId]=useState('');
const attempt=useRef(null);
const allowed=r=>can(`workshop.${r}`,context.unit?.id??null);
const load=async()=>{const d=await api('/api/workshop');setData(d);return d;};
@@ -33,6 +34,7 @@ export default function WorkshopWorkspace({context,can,api,busy}) {
}
const correctionFields=kind=><><label>Versão anterior a corrigir (opcional)<select name="previous_id"><option value="">Novo acontecimento</option>{order.entries.filter(e=>e.kind===kind&&e.current).map(e=><option key={e.id} value={e.id}>#{e.id} · {e.origin} v{e.version}</option>)}</select></label><label>Motivo de correcção (se aplicável)<input name="correction_reason"/></label></>;
return <>
{navigate&&<nav className="billing-section-tabs" aria-label="Submenus de oficinas">{visibleWorkshopSections(can,context.unit?.id??null).map(s=><button key={s.id} aria-current={s.id==='workshop'?'page':undefined} onClick={()=>{if(s.id!=='workshop')navigate(s.id);}}>{s.label}</button>)}</nav>}
<section className="panel"><p className="eyebrow">WORKSHOP-RESOURCE-RECORD-v1</p><h1>Oficina — registo de recursos</h1><div className="alert error"><strong>TESTE — SEM UTILIZAÇÃO OPERACIONAL</strong><p>Sem stock, custos, facturação ou recebimentos.</p></div>{error&&<p role="alert" className="alert error">{error}</p>}<button disabled={disabled} onClick={()=>load().catch(e=>setError(e.message))}>Actualizar revisão explicitamente</button><p className="help">Abertura não autoriza trabalho. Relatar uma ocorrência passada não lhe dá autorização retroactiva. Alterações concorrentes exigem nova revisão.</p></section>
{!data?<p>A carregar…</p>:data.blocked?<section className="panel"><h2>Utilização operacional bloqueada</h2><p>Disponível apenas na instância isolada ligada à base de testes.</p></section>:<>
{allowed('open')&&<section className="panel"><h2>Abrir ordem de teste</h2><Form label="Abrir ordem" disabled={disabled} save={v=>send('/orders',{...v,client_id:Number(v.client_id)})}><label>Referência operacional<input name="reference" required/></label><label>Cliente existente<select name="client_id">{data.clients.map(c=><option key={c.id} value={c.id}>#{c.id} · {c.name}</option>)}</select></label><label>Identificação individual do equipamento<input name="equipment_identifier" required/></label><label>Descrição / marca / modelo<input name="equipment_description" required/></label><label>Número de série (se conhecido)<input name="serial"/></label><label>Pedido / avaria<textarea name="request" required/></label><label>Localização<input name="location" required/></label><label>Evidência do pedido<input name="evidence" required/></label></Form><p className="help">Para reutilizar equipamento já identificado, a API aceita o seu ID; não criar outro só por existir uma nova ordem.</p></section>}