109 lines
3.4 KiB
TypeScript
109 lines
3.4 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import { router } from '@inertiajs/react';
|
|
import { portalRequest } from '@/lib/portal-api';
|
|
import { button } from '@/pages/management/shared';
|
|
|
|
export default function TechnicalIncidentNotice({
|
|
actorId,
|
|
reference,
|
|
unread,
|
|
}: {
|
|
actorId: number;
|
|
reference: string;
|
|
unread: boolean;
|
|
}) {
|
|
const [read, setRead] = useState(!unread),
|
|
[busy, setBusy] = useState(false),
|
|
[error, setError] = useState('');
|
|
const scope = useRef({ actorId, reference }),
|
|
alive = useRef(true),
|
|
active = useRef(false),
|
|
confirmed = useRef(!unread);
|
|
const current = useRef({ actorId, reference });
|
|
current.current = { actorId, reference };
|
|
useEffect(() => {
|
|
alive.current = true;
|
|
return () => {
|
|
alive.current = false;
|
|
};
|
|
}, []);
|
|
useEffect(() => {
|
|
if (!unread) {
|
|
confirmed.current = true;
|
|
setRead(true);
|
|
setError('');
|
|
}
|
|
}, [unread]);
|
|
function applicable() {
|
|
return (
|
|
alive.current &&
|
|
current.current.actorId === scope.current.actorId &&
|
|
current.current.reference === scope.current.reference
|
|
);
|
|
}
|
|
async function mark() {
|
|
if (!applicable() || active.current || confirmed.current) return;
|
|
active.current = true;
|
|
setBusy(true);
|
|
setError('');
|
|
try {
|
|
const value = await portalRequest<unknown>(
|
|
'/suporte-tecnico/incidentes/' +
|
|
scope.current.reference +
|
|
'/consultado',
|
|
{
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: '{}',
|
|
},
|
|
);
|
|
if (!applicable() || confirmed.current) return;
|
|
if (
|
|
!value ||
|
|
typeof value !== 'object' ||
|
|
!('actor_id' in value) ||
|
|
value.actor_id !== scope.current.actorId ||
|
|
!('reference' in value) ||
|
|
value.reference !== scope.current.reference ||
|
|
!('read' in value) ||
|
|
value.read !== true
|
|
)
|
|
throw new Error('Unconfirmed receipt');
|
|
confirmed.current = true;
|
|
setRead(true);
|
|
router.reload({
|
|
only: ['incidents', 'profileAccess', 'notice'],
|
|
});
|
|
} catch {
|
|
if (applicable() && !confirmed.current)
|
|
setError(
|
|
'Não foi possível confirmar a consulta. Pode repetir esta acção; o tratamento e as notas mantêm-se.',
|
|
);
|
|
} finally {
|
|
if (applicable()) {
|
|
active.current = false;
|
|
setBusy(false);
|
|
}
|
|
}
|
|
}
|
|
return (
|
|
<div className="space-y-2">
|
|
{read ? (
|
|
<p>Aviso consultado por si.</p>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
className={button}
|
|
disabled={busy}
|
|
onClick={() => void mark()}
|
|
>
|
|
{error
|
|
? 'Repetir confirmação de consulta'
|
|
: 'Marcar aviso como consultado'}
|
|
</button>
|
|
)}
|
|
{error && <p role="alert">{error}</p>}
|
|
</div>
|
|
);
|
|
}
|