import React, { useEffect, useState } from 'react'; export const serviceAreas = { clients: 'Clientes', services: 'Serviços', service_drafts: 'Prestações em rascunho', billing_drafts: 'Rascunhos de facturação' }; const actions = { view: 'Consultar', create: 'Criar', edit: 'Editar', manage: 'Gerir concessões' }; const isDraft = area => area === 'service_drafts' || area === 'billing_drafts'; const newLine = () => ({ service_id: '', quantity: '', unit_price: '', description: '' }); export default function ServicesWorkspace({ area, context, can, api, perform, busy, initialId, navigate }) { const unit = isDraft(area) ? context.unit?.id ?? null : null; const allowed = action => can(`${area}.${action}`, unit); const [records, setRecords] = useState([]); const [selected, setSelected] = useState(null); const [form, setForm] = useState(null); const [references, setReferences] = useState({ clients: [], services: [], source: [] }); const [error, setError] = useState(''); const [key, setKey] = useState(() => crypto.randomUUID()); const [access, setAccess] = useState(false); const path = `/api/a/${area}`; async function load() { const result = await api(path); setRecords(result.records); } async function open(id) { setError(''); try { setSelected(await api(`${path}/${id}`)); setForm(null); } catch (e) { setError(e.message); } } useEffect(() => { load().catch(e => setError(e.message)); if (initialId) open(initialId); }, [area, context.token]); async function start(record = null) { setError(''); setAccess(false); try { if (isDraft(area)) { const [clients, services, source] = await Promise.all([ api('/api/a/clients'), api('/api/a/services'), area === 'billing_drafts' ? api('/api/a/service_drafts') : Promise.resolve({ records: [] }) ]); setReferences({ clients: clients.records, services: services.records, source: source.records }); } setSelected(record); setForm(record ? { name: record.name, description: record.data.description || '', client_id: record.client_id || '', source_id: record.source_id || '', currency: record.data.currency || '', lines: record.data.lines?.map(line => ({ ...line, quantity: line.quantity ?? '', unit_price: line.unit_price ?? '' })) || [newLine()] } : { name: '', description: '', client_id: '', source_id: '', currency: '', lines: [newLine()] }); setKey(crypto.randomUUID()); } catch (e) { setError(e.message); } } async function save(event) { event.preventDefault(); let body = { name: form.name.trim() }; if (area === 'services') body.description = form.description || null; if (isDraft(area)) { body = { ...(form.name.trim() ? { name: form.name.trim() } : {}), description: form.description || null }; if (area === 'billing_drafts' && !selected) body.source_id = Number(form.source_id); else { body.currency = form.currency || null; body.lines = form.lines.map(line => ({ service_id: Number(line.service_id), description: line.description || null, quantity: line.quantity || null, unit_price: line.unit_price || null })); if (area === 'service_drafts') body.client_id = Number(form.client_id); } } if (selected) body.version = selected.version; await perform(async () => { const result = await api(selected ? `${path}/${selected.id}` : path, selected ? 'PATCH' : 'POST', body, context.token, key); await load(); await open(result.id); setKey(crypto.randomUUID()); }, 'Rascunho ou cadastro guardado com histórico e captura durável.'); } async function prepareBilling() { await perform(async () => { const result = await api('/api/a/billing_drafts', 'POST', { source_id: selected.id }, context.token, key); navigate('billing_drafts', result.id); }, 'Rascunho de facturação preparado a partir da prestação. Nenhuma factura foi emitida.'); } function changeLine(index, field, value) { setForm({ ...form, lines: form.lines.map((line, n) => n === index ? { ...line, [field]: value } : line) }); } if (!allowed('view')) return

{serviceAreas[area]}

Sem consulta autorizada neste contexto.

; return <>

ENTREGA A · PREPARAÇÃO

{serviceAreas[area]}

{isDraft(area) ? `Unidade: ${context.unit?.name || 'não seleccionada'}` : 'Cadastro partilhado pelas unidades da empresa'}

{allowed('create') && }{allowed('manage') && }
{error &&
{error}
} {isDraft(area) &&
Apenas rascunhos. Sem emissão fiscal, confirmação de serviço ou lançamentos contabilísticos.
} {access ? : <>

Registos

{!records.length &&

Ainda não há registos neste âmbito.

}{records.map(record => )}
{form ?

{selected ? 'Editar' : 'Criar'} {isDraft(area) ? 'rascunho' : 'cadastro'}

{area !== 'clients' &&