feat: add error boundary component and improve auth layout
This commit is contained in:
47
resources/js/components/common/ErrorBoundary.vue
Normal file
47
resources/js/components/common/ErrorBoundary.vue
Normal 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>
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user