feat: add error boundary component and improve auth layout

This commit is contained in:
2026-02-21 14:04:01 +01:00
parent 619d84383f
commit f49326f8df
3 changed files with 57 additions and 4 deletions

View File

@@ -0,0 +1,47 @@
<script setup lang="ts">
import { onErrorCaptured, ref } from 'vue'
const hasError = ref(false)
const errorMessage = ref('')
const isDev = import.meta.env.DEV
onErrorCaptured((err) => {
hasError.value = true
errorMessage.value = err instanceof Error ? err.message : String(err)
if (import.meta.env.DEV) {
console.error('[ErrorBoundary] Caught error:', err)
}
// Prevent error from propagating further
return false
})
function retry() {
hasError.value = false
errorMessage.value = ''
}
</script>
<template>
<div v-if="hasError" class="flex flex-col items-center justify-center py-12 px-4 text-center">
<UIcon name="i-lucide-alert-triangle" class="size-12 text-warning mb-4" />
<h3 class="text-lg font-semibold text-default mb-2">
Something went wrong
</h3>
<p class="text-sm text-muted mb-4 max-w-md">
An unexpected error occurred. Please try again.
</p>
<p v-if="isDev && errorMessage" class="text-xs text-error mb-4 max-w-lg font-mono bg-error/5 p-2 rounded">
{{ errorMessage }}
</p>
<UButton
label="Try Again"
icon="i-lucide-refresh-cw"
color="primary"
variant="outline"
@click="retry"
/>
</div>
<slot v-else />
</template>

View File

@@ -1,19 +1,22 @@
<script setup lang="ts"> <script setup lang="ts">
import { Link } from '@inertiajs/vue3'
import { useAuth } from '@/composables/useAuth' import { useAuth } from '@/composables/useAuth'
withDefaults(defineProps<{ withDefaults(defineProps<{
size?: 'sm' | 'md' | 'lg' size?: 'sm' | 'md' | 'lg'
showText?: boolean showText?: boolean
linkToHome?: boolean
}>(), { }>(), {
size: 'md', size: 'md',
showText: true, showText: true,
linkToHome: true,
}) })
const { config } = useAuth() const { config } = useAuth()
</script> </script>
<template> <template>
<div class="flex items-center gap-3"> <component :is="linkToHome ? Link : 'div'" :href="linkToHome ? '/' : undefined" class="flex items-center gap-3">
<!-- <!--
Replace this placeholder with your actual logo: Replace this placeholder with your actual logo:
<img src="/images/logo.svg" alt="Logo" :class="iconSizeClass"> <img src="/images/logo.svg" alt="Logo" :class="iconSizeClass">
@@ -40,5 +43,5 @@ const { config } = useAuth()
> >
{{ config.appName }} {{ config.appName }}
</span> </span>
</div> </component>
</template> </template>

View File

@@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import ErrorBoundary from '@/components/common/ErrorBoundary.vue'
import Logo from '@/components/common/Logo.vue' import Logo from '@/components/common/Logo.vue'
</script> </script>
@@ -9,11 +10,13 @@ import Logo from '@/components/common/Logo.vue'
<UPageCard :ui="{ wrapper: 'flex flex-col flex-1 items-center', header: 'mb-4' }"> <UPageCard :ui="{ wrapper: 'flex flex-col flex-1 items-center', header: 'mb-4' }">
<template #header> <template #header>
<slot name="logo"> <slot name="logo">
<Logo /> <Logo size="lg" :link-to-home="false" />
</slot> </slot>
</template> </template>
<slot /> <ErrorBoundary>
<slot />
</ErrorBoundary>
</UPageCard> </UPageCard>
</div> </div>
</div> </div>