quest-vorteq/src/app/(portal)/notifications/page.tsx

71 lines
2 KiB
TypeScript
Raw Normal View History

'use client';
import { useEffect, useState } from 'react';
import { Card, CardContent } from '@/components/ui/card';
import { NotificationList } from '@/components/notifications/notification-list';
import type { NotificationItem } from '@/types/notifications';
function NotificationsSkeleton() {
return (
<div className="space-y-3">
{[...Array(3)].map((_, i) => (
<Card key={i}>
<CardContent className="p-6">
<div className="space-y-2">
<div className="h-5 w-48 animate-pulse rounded bg-muted" />
<div className="h-4 w-32 animate-pulse rounded bg-muted" />
<div className="h-4 w-full animate-pulse rounded bg-muted" />
</div>
</CardContent>
</Card>
))}
</div>
);
}
export default function NotificationsPage() {
const [notifications, setNotifications] = useState<NotificationItem[] | null>(
null
);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('/api/notifications')
.then((res) => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then((json) => setNotifications(json))
.catch((err) => setError(err.message));
}, []);
const handleMarkRead = async (id: string) => {
const res = await fetch(`/api/notifications/${id}/read`, {
method: 'POST',
});
if (!res.ok) {
throw new Error('Failed to mark notification as read');
}
};
return (
<div>
<h1 className="mb-6 text-3xl font-bold">Notifications</h1>
{error ? (
<Card>
<CardContent className="p-6 text-center text-destructive">
Failed to load notifications: {error}
</CardContent>
</Card>
) : notifications === null ? (
<NotificationsSkeleton />
) : (
<NotificationList
notifications={notifications}
onMarkRead={handleMarkRead}
/>
)}
</div>
);
}