Add frontend support for notifications
This commit is contained in:
133
frontend/src/routes/notifications/[subscription_id]/+page.svelte
Normal file
133
frontend/src/routes/notifications/[subscription_id]/+page.svelte
Normal file
@@ -0,0 +1,133 @@
|
||||
<script lang="ts">
|
||||
import { deleteNotification, addNotification, setViewed } from '$lib/api';
|
||||
import type { Notification, Subscription } from '$lib/api';
|
||||
|
||||
export let data: { notifications: Notification[]; subscription: Subscription };
|
||||
|
||||
let notifications: Notification[] = data.notifications;
|
||||
let newNotificationTitle = '';
|
||||
let newNotificationMessage = '';
|
||||
let newNotificationPriority = 3;
|
||||
let selectedNotification: Notification | null = null;
|
||||
|
||||
async function openNotificationPopup(notification: Notification) {
|
||||
if (!notification.viewed) {
|
||||
await setViewed(notification.id);
|
||||
notifications = notifications.map((n) =>
|
||||
n.id === notification.id ? { ...n, viewed: true } : n
|
||||
);
|
||||
notification.viewed = true;
|
||||
}
|
||||
|
||||
selectedNotification = notification;
|
||||
}
|
||||
|
||||
function closeNotificationPopup() {
|
||||
selectedNotification = null;
|
||||
}
|
||||
|
||||
async function handleDeleteNotification(id: number) {
|
||||
try {
|
||||
await deleteNotification(id);
|
||||
notifications = notifications.filter((notification) => notification.id !== id);
|
||||
window.showNotification('success', 'Notification deleted successfully.');
|
||||
} catch (error) {
|
||||
window.showNotification('error', 'Failed to delete notification - ' + error);
|
||||
}
|
||||
}
|
||||
async function markAllViewed() {
|
||||
try {
|
||||
await Promise.all(
|
||||
notifications
|
||||
.filter((notification) => !notification.viewed)
|
||||
.map((notification) => setViewed(notification.id))
|
||||
);
|
||||
notifications = notifications.map((notification) =>
|
||||
notification.viewed ? notification : { ...notification, viewed: true }
|
||||
);
|
||||
window.showNotification('success', 'All notifications marked as viewed.');
|
||||
} catch (error) {
|
||||
window.showNotification('error', 'Failed to mark all notifications as viewed.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<main class="p-4">
|
||||
<h1 class="text-2xl font-bold mb-4">Notifications for {data.subscription.topic}:</h1>
|
||||
|
||||
<div class="flex justify-between items-center mb-4">
|
||||
<a href="/notifications" class="text-blue-500 hover:underline">← Return to Subscriptions</a>
|
||||
<button class="bg-blue-500 text-white px-4 py-2 rounded" on:click={markAllViewed}>
|
||||
Mark All Viewed
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if notifications.length === 0}
|
||||
<p>No notifications found for this topic.</p>
|
||||
{:else}
|
||||
<ul class="space-y-4">
|
||||
{#each notifications as notification (notification.id)}
|
||||
<li
|
||||
class="p-2 rounded flex justify-between items-center border-s-slate-400 border-1"
|
||||
class:bg-green-200={notification.viewed}
|
||||
>
|
||||
<button class="p-2 w-full text-left" on:click={() => openNotificationPopup(notification)}>
|
||||
<div>
|
||||
<p class="font-semibold">{notification.title}</p>
|
||||
<p class="text-sm text-gray-500">
|
||||
{new Date(notification.created_at).toLocaleString()}
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="px-2 py-1 bg-red-500 text-white rounded hover:bg-red-600 block"
|
||||
on:click|stopPropagation={() => handleDeleteNotification(notification.id)}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{#if selectedNotification}
|
||||
<div class="fixed inset-0 bg-opacity-30 backdrop-blur-sm flex items-center justify-center z-50">
|
||||
<div class="bg-white p-6 rounded shadow-lg w-3/4 max-w-2xl max-h-[80vh] overflow-y-auto">
|
||||
<h3 class="text-lg font-bold mb-4">Notification Details</h3>
|
||||
<div class="mb-4">
|
||||
<p class="font-semibold">Title:</p>
|
||||
<pre
|
||||
class="whitespace-pre-wrap bg-gray-100 p-2 rounded border">{selectedNotification.title}</pre>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p class="font-semibold">Message:</p>
|
||||
<pre
|
||||
class="whitespace-pre-wrap bg-gray-100 p-2 rounded border">{selectedNotification.message}</pre>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p class="font-semibold">Priority:</p>
|
||||
<pre
|
||||
class="whitespace-pre-wrap bg-gray-100 p-2 rounded border">{selectedNotification.priority}</pre>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<p class="font-semibold">Created At:</p>
|
||||
<pre class="whitespace-pre-wrap bg-gray-100 p-2 rounded border">{new Date(
|
||||
selectedNotification.created_at
|
||||
).toLocaleString()}</pre>
|
||||
</div>
|
||||
<button
|
||||
class="mt-4 px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600"
|
||||
on:click={closeNotificationPopup}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
<style>
|
||||
main {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user