192 lines
8.1 KiB
TypeScript
192 lines
8.1 KiB
TypeScript
import { Head, Link } from '@inertiajs/react';
|
|
import {
|
|
ArrowRight,
|
|
CheckCheck,
|
|
ClipboardList,
|
|
Clock3,
|
|
Plus,
|
|
Wallet,
|
|
} from 'lucide-react';
|
|
import { PageTitle, Panel, RequisitionTable } from '@/components/procurement';
|
|
import { Button } from '@/components/ui/button';
|
|
import { money } from '@/types/procurement';
|
|
import type { Company, Requisition } from '@/types/procurement';
|
|
|
|
type Props = {
|
|
company: Company | null;
|
|
stats: {
|
|
total: number;
|
|
pending: number;
|
|
approved: number;
|
|
approvedMinor: number;
|
|
awaitingMe: number;
|
|
};
|
|
recent: Requisition[];
|
|
approvals: Requisition[];
|
|
};
|
|
export default function Dashboard({
|
|
company,
|
|
stats,
|
|
recent,
|
|
approvals,
|
|
}: Props) {
|
|
const cards = [
|
|
{
|
|
label: 'Requisições',
|
|
value: stats.total,
|
|
icon: ClipboardList,
|
|
detail: 'Total de pedidos visíveis',
|
|
},
|
|
{
|
|
label: 'Em aprovação',
|
|
value: stats.pending,
|
|
icon: Clock3,
|
|
detail: `${stats.awaitingMe} aguardam a sua decisão`,
|
|
},
|
|
{
|
|
label: 'Aprovadas',
|
|
value: stats.approved,
|
|
icon: CheckCheck,
|
|
detail: 'Todas as etapas concluídas',
|
|
},
|
|
{
|
|
label: 'Valor aprovado',
|
|
value: money(Number(stats.approvedMinor)),
|
|
icon: Wallet,
|
|
detail: 'Estimativa em MZN, com IVA',
|
|
},
|
|
];
|
|
return (
|
|
<>
|
|
<Head title="Visão geral" />
|
|
<div className="mx-auto flex w-full max-w-7xl flex-col gap-7 p-5 lg:p-8">
|
|
<PageTitle
|
|
eyebrow={company?.name ?? 'Bem-vindo ao SGC'}
|
|
title="Visão geral das compras"
|
|
description="Acompanhe os pedidos, as aprovações e a actividade da sua empresa."
|
|
action={
|
|
<Button
|
|
asChild
|
|
className="bg-teal-700 text-white hover:bg-teal-800"
|
|
>
|
|
<Link
|
|
href={
|
|
company
|
|
? '/requisicoes/criar'
|
|
: '/empresa/iniciar'
|
|
}
|
|
>
|
|
<Plus className="size-4" />
|
|
{company
|
|
? 'Nova requisição'
|
|
: 'Configurar empresa'}
|
|
</Link>
|
|
</Button>
|
|
}
|
|
/>
|
|
{!company ? (
|
|
<Panel
|
|
title="Vamos configurar a sua empresa"
|
|
description="Crie a organização e o primeiro departamento. Depois pode adicionar a equipa e começar a registar pedidos."
|
|
>
|
|
<Button asChild>
|
|
<Link href="/empresa/iniciar">
|
|
Começar configuração{' '}
|
|
<ArrowRight className="size-4" />
|
|
</Link>
|
|
</Button>
|
|
</Panel>
|
|
) : (
|
|
<>
|
|
<div className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
|
|
{cards.map((card) => (
|
|
<div
|
|
key={card.label}
|
|
className="rounded-xl border bg-card p-5 shadow-xs"
|
|
>
|
|
<div className="flex items-center justify-between text-sm text-muted-foreground">
|
|
<span>{card.label}</span>
|
|
<card.icon className="size-4 text-teal-700 dark:text-teal-400" />
|
|
</div>
|
|
<p className="mt-5 text-2xl font-semibold tracking-tight">
|
|
{card.value}
|
|
</p>
|
|
<p className="mt-2 text-xs text-muted-foreground">
|
|
{card.detail}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
{company.rules_provisional && (
|
|
<div className="rounded-xl border border-amber-200 bg-amber-50 px-5 py-4 text-sm text-amber-900 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-100">
|
|
<strong>
|
|
Ambiente de desenvolvimento · regras
|
|
provisórias.
|
|
</strong>{' '}
|
|
Escalões de {money(company.first_limit_minor)} e{' '}
|
|
{money(company.second_limit_minor)}, calculados{' '}
|
|
{company.approval_includes_tax ? 'com' : 'sem'}{' '}
|
|
IVA. Os parâmetros precisam de validação antes
|
|
de compras reais.
|
|
</div>
|
|
)}
|
|
{approvals.length > 0 && (
|
|
<Panel
|
|
title="À espera da sua aprovação"
|
|
description="Abra um pedido para conferir os artigos e registar a decisão."
|
|
>
|
|
<div className="divide-y">
|
|
{approvals.map((r) => (
|
|
<Link
|
|
key={r.id}
|
|
href={`/requisicoes/${r.id}`}
|
|
className="flex items-center justify-between gap-4 py-3"
|
|
>
|
|
<div>
|
|
<p className="font-medium">
|
|
{r.number}
|
|
</p>
|
|
<p className="mt-1 line-clamp-1 text-sm text-muted-foreground">
|
|
{r.justification}
|
|
</p>
|
|
</div>
|
|
<span className="flex shrink-0 items-center gap-3 text-sm font-medium">
|
|
{money(r.total_minor)}
|
|
<ArrowRight className="size-4" />
|
|
</span>
|
|
</Link>
|
|
))}
|
|
</div>
|
|
</Panel>
|
|
)}
|
|
<Panel
|
|
title="Requisições recentes"
|
|
description="Últimos pedidos disponíveis para o seu perfil."
|
|
>
|
|
<RequisitionTable rows={recent} />
|
|
<div className="mt-4 border-t pt-4">
|
|
<Link
|
|
href="/requisicoes"
|
|
className="inline-flex items-center gap-2 text-sm font-medium text-teal-700 dark:text-teal-400"
|
|
>
|
|
Ver todas as requisições{' '}
|
|
<ArrowRight className="size-4" />
|
|
</Link>
|
|
</div>
|
|
</Panel>
|
|
</>
|
|
)}
|
|
</div>
|
|
</>
|
|
);
|
|
}
|
|
|
|
Dashboard.layout = {
|
|
breadcrumbs: [
|
|
{
|
|
title: 'Visão geral',
|
|
href: '/dashboard',
|
|
},
|
|
],
|
|
};
|