Files
compras/resources/js/pages/workflow/notices.tsx
T
2026-11-02 08:08:05 +02:00

127 lines
5.6 KiB
TypeScript

import { Head, Link, router } from '@inertiajs/react';
import { PageTitle, Panel } from '@/components/procurement';
import { Button } from '@/components/ui/button';
import { roleLabels, statusLabels } from '@/types/procurement';
type Props = {
ready: boolean;
unread: number;
view: string;
notices: {
total: number;
data: {
id: number;
reference: string;
role: string;
kind: string;
outcome: string | null;
current_status: string;
created_at: string;
read_at: string | null;
href: string;
}[];
prev_page_url: string | null;
next_page_url: string | null;
};
};
export default function Notices({ ready, unread, view, notices }: Props) {
return (
<>
<Head title="Avisos de aprovação" />
<div className="space-y-6 p-6">
<PageTitle
eyebrow="Compras"
title="Avisos de aprovação"
description="As suas intervenções pendentes e os resultados das requisições que submeteu. Ler um aviso não aprova o pedido."
/>
<div className="flex flex-wrap gap-4">
<Link href="/requisicoes/avisos">Todos os visíveis</Link>
<Link href="/requisicoes/avisos?view=tasks">
Intervenções pendentes
</Link>
<Link href="/requisicoes/avisos?view=outcomes">
Resultados dos meus pedidos
</Link>
<Link href="/requisicoes/avisos?view=unread">
Por ler ({unread})
</Link>
<Link href="/requisicoes?view=approvals">
As minhas aprovações
</Link>
</div>
<Panel
title={
view === 'unread'
? 'Por ler'
: view === 'outcomes'
? 'Resultados dos meus pedidos'
: view === 'tasks'
? 'Intervenções pendentes'
: 'Avisos internos'
}
description="Intervenções concluídas deixam a fila pendente. Resultados registados mantêm-se visíveis ao requisitante com acesso actual. Não são criados avisos retroactivos para decisões antigas."
>
{!ready ? (
<p>Instalação dos avisos internos pendente.</p>
) : notices.data.length === 0 ? (
<p>Sem avisos neste âmbito.</p>
) : (
notices.data.map((notice) => (
<div
className="mb-3 rounded-md border p-4"
key={notice.id}
>
<Link
className="font-medium underline"
href={notice.href}
>
{notice.reference} ·{' '}
{roleLabels[notice.role] ?? notice.role}
</Link>
{notice.kind === 'outcome' && (
<p className="mt-2 text-sm">
Resultado registado:{' '}
{notice.outcome === 'approved'
? 'requisição aprovada'
: 'requisição rejeitada'}
. Estado actual:{' '}
{statusLabels[notice.current_status] ??
notice.current_status}
. Consulte o processo para conhecer o
fundamento e os passos seguintes.
</p>
)}
<p className="mt-2 text-sm">
{notice.read_at ? 'Lido' : 'Por ler'} ·
Criado em {notice.created_at}
</p>
{!notice.read_at && (
<Button
className="mt-3"
variant="outline"
onClick={() =>
router.post(
`/requisicoes/avisos/${notice.id}/ler`,
)
}
>
Marcar como lido
</Button>
)}
</div>
))
)}
<div className="mt-4 flex gap-4">
{notices.prev_page_url && (
<Link href={notices.prev_page_url}>Anterior</Link>
)}
{notices.next_page_url && (
<Link href={notices.next_page_url}>Seguinte</Link>
)}
</div>
</Panel>
</div>
</>
);
}