Kuldvillak MVP ei forki, Randel, fork you Randel Mandre SASS license peal
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

104 lines
3.5 KiB

<script lang="ts">
import { onMount } from "svelte";
import type { Snippet } from "svelte";
import * as m from "$lib/paraglide/messages";
interface Props {
children: Snippet;
fallback?: Snippet<[Error]>;
}
let { children, fallback }: Props = $props();
let error = $state<Error | null>(null);
let hasError = $state(false);
onMount(() => {
// Catch unhandled errors
const handleError = (event: ErrorEvent) => {
console.error("ErrorBoundary caught:", event.error);
error = event.error;
hasError = true;
event.preventDefault();
};
// Catch unhandled promise rejections
const handleRejection = (event: PromiseRejectionEvent) => {
console.error("ErrorBoundary caught rejection:", event.reason);
error =
event.reason instanceof Error
? event.reason
: new Error(String(event.reason));
hasError = true;
event.preventDefault();
};
window.addEventListener("error", handleError);
window.addEventListener("unhandledrejection", handleRejection);
return () => {
window.removeEventListener("error", handleError);
window.removeEventListener("unhandledrejection", handleRejection);
};
});
function retry() {
hasError = false;
error = null;
}
function goHome() {
window.location.href = "/";
}
</script>
{#if hasError && error}
{#if fallback}
{@render fallback(error)}
{:else}
<div
class="min-h-screen flex items-center justify-center bg-gray-900 p-4"
role="alert"
aria-live="assertive"
>
<div class="bg-gray-800 rounded-lg p-8 max-w-md w-full text-center">
<div class="text-red-500 text-6xl mb-4" aria-hidden="true">
</div>
<h1 class="text-white text-2xl font-bold mb-2 uppercase">
{m.error_title?.() ?? "Something went wrong"}
</h1>
<p class="text-gray-400 mb-4 uppercase">
{m.error_description?.() ??
"An unexpected error occurred. Please try again."}
</p>
<details class="text-left mb-4">
<summary
class="text-gray-500 uppercase cursor-pointer hover:text-gray-400"
>
{m.error_details?.() ?? "Technical details"}
</summary>
<pre
class="mt-2 p-2 bg-gray-900 rounded text-red-400 text-xs overflow-auto max-h-32">{error.message}
{error.stack}</pre>
</details>
<div class="flex gap-4 justify-center">
<button
onclick={retry}
class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
>
{m.error_retry?.() ?? "Try Again"}
</button>
<button
onclick={goHome}
class="px-4 py-2 bg-gray-600 text-white rounded hover:bg-gray-700 transition-colors"
>
{m.error_go_home?.() ?? "Go Home"}
</button>
</div>
</div>
</div>
{/if}
{:else}
{@render children()}
{/if}