Files
Project-Monitor/frontend/src/routes/+layout.svelte
2025-10-12 14:54:53 +02:00

92 lines
2.6 KiB
Svelte

<script lang="ts">
import '../app.css';
import Icon from '@iconify/svelte';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
import { checkHealth } from '$lib/api';
let { children } = $props();
interface Notification {
id: number;
type: 'success' | 'error';
message: string;
}
let notifications: Notification[] = $state([]);
let notificationId = 0;
let healthStatus = writable<'healthy' | 'unhealthy'>('unhealthy');
async function updateHealthStatus() {
const status = await checkHealth();
healthStatus.set(status);
}
function showNotification(type: 'success' | 'error', message: string): void {
const id = notificationId++;
notifications = [...notifications, { id, type, message }];
setTimeout(() => {
notifications = notifications.filter((n) => n.id !== id);
}, 4000);
}
onMount(() => {
window.showNotification = showNotification;
updateHealthStatus();
setInterval(updateHealthStatus, 10000); // Check health every 10 seconds
});
</script>
<nav class="bg-gray-800 text-white shadow-md">
<div class="container mx-auto flex justify-between items-center p-4">
<a href="/" class="text-2xl font-bold hover:text-gray-400">Project Monitor</a>
<div class="flex space-x-6">
<a href="/" class="text-lg hover:text-gray-400">Home</a>
<a href="/scripts" class="text-lg hover:text-gray-400">Scripts</a>
<a href="/notifications" class="text-lg hover:text-gray-400">Notifications</a>
<a href="/settings" class="text-lg hover:text-gray-400">
<Icon icon="material-symbols:settings" width="24" height="24" />
</a>
</div>
</div>
</nav>
<div class="relative">
{@render children()}
<div class="fixed bottom-4 right-4 space-y-2">
{#each notifications as notification (notification.id)}
<div
class="p-4 rounded shadow-lg text-white"
class:bg-green-500={notification.type === 'success'}
class:bg-red-500={notification.type === 'error'}
>
{notification.message}
</div>
{/each}
</div>
</div>
<div class="fixed bottom-4 left-4 group">
{#if $healthStatus === 'healthy'}
<Icon
icon="material-symbols:check-circle-rounded"
width="24"
height="24"
class="text-green-400"
/>
<div
class="absolute bottom-full left-1/2 hidden group-hover:flex group-hover:w-max bg-green-500 text-white px-2 py-1 rounded shadow-lg"
>
Connected to backend
</div>
{:else}
<Icon icon="ix:disconnected-circle-filled" width="24" height="24" class="text-red-400" />
<div
class="absolute bottom-full left-1/2 hidden group-hover:flex group-hover:w-max bg-red-500 text-white px-2 py-1 rounded shadow-lg"
>
Not connected
</div>
{/if}
</div>