Files
reservas/resources/js/pages/notifications/index.tsx

124 lines
5.1 KiB
TypeScript

import { Head, Link, router } from '@inertiajs/react';
import { Bell, CheckCheck } from 'lucide-react';
import { PageHeading } from '@/components/page-heading';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
import type { Paginated } from '@/types';
type PortalNotification = {
id: string;
data: {
message: string;
url?: string;
reference?: string;
};
read_at: string | null;
created_at: string;
};
export default function NotificationsIndex({
notifications,
}: {
notifications: Paginated<PortalNotification>;
}) {
function openNotification(notification: PortalNotification) {
router.post(`/notificacoes/${notification.id}/ler`);
}
return (
<>
<Head title="Notificações" />
<main className="mx-auto flex w-full max-w-4xl flex-1 flex-col gap-7 p-5 sm:p-8">
<PageHeading
eyebrow="Caixa interna"
title="Notificações"
description="Atualizações sobre requisições, decisões e pedidos de esclarecimento."
action={
<Button
variant="outline"
onClick={() =>
router.post('/notificacoes/ler-todas')
}
>
<CheckCheck /> Marcar todas como lidas
</Button>
}
/>
<section className="overflow-hidden rounded-xl border bg-card">
{notifications.data.map((notification) => (
<button
type="button"
key={notification.id}
onClick={() => openNotification(notification)}
className={cn(
'flex w-full gap-4 border-b p-5 text-left last:border-0 hover:bg-slate-50 dark:hover:bg-slate-900',
notification.read_at === null && 'bg-primary/5',
)}
>
<span className="mt-0.5 rounded-full bg-primary/10 p-2 text-primary">
<Bell className="size-4" />
</span>
<div className="min-w-0 flex-1">
<p className="text-sm font-medium">
{notification.data.message}
</p>
<p className="mt-1 text-xs text-muted-foreground">
{new Intl.DateTimeFormat('pt-PT', {
dateStyle: 'medium',
timeStyle: 'short',
}).format(
new Date(notification.created_at),
)}
</p>
</div>
{notification.read_at === null && (
<span className="mt-2 size-2 rounded-full bg-primary" />
)}
</button>
))}
{notifications.data.length === 0 && (
<div className="py-16 text-center text-sm text-muted-foreground">
Não existem notificações.
</div>
)}
</section>
{notifications.last_page > 1 && (
<nav className="flex justify-center gap-2">
{notifications.links.map((link, index) => (
<Button
key={index}
asChild={Boolean(link.url)}
disabled={!link.url}
variant={link.active ? 'default' : 'outline'}
size="sm"
>
{link.url ? (
<Link
href={link.url}
preserveScroll
dangerouslySetInnerHTML={{
__html: link.label,
}}
/>
) : (
<span
dangerouslySetInnerHTML={{
__html: link.label,
}}
/>
)}
</Button>
))}
</nav>
)}
</main>
</>
);
}
NotificationsIndex.layout = {
breadcrumbs: [{ title: 'Notificações', href: '/notificacoes' }],
};