Backend: rate limiter, security headers, blockchain cache service avec RPC, public API (7 endpoints read-only), WebSocket auth + heartbeat, DB connection pooling, structured logging, health check DB. Frontend: API retry/timeout, WebSocket auth + heartbeat + typed events, notifications toast, mobile hamburger + drawer, error boundary, offline banner, loading skeletons, dashboard enrichi. Documentation: guides utilisateur complets (demarrage, vote, sanctuaire, FAQ 30+), guide deploiement, politique securite. 123 tests, 155 fichiers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
71 lines
1.9 KiB
Vue
71 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
/**
|
|
* Error boundary component.
|
|
*
|
|
* Wraps slot content with NuxtErrorBoundary and displays a user-friendly
|
|
* error message in French when child components crash.
|
|
* Logs error details to console and emits error event for monitoring.
|
|
*/
|
|
|
|
const emit = defineEmits<{
|
|
error: [error: any]
|
|
}>()
|
|
|
|
const hasError = ref(false)
|
|
const errorDetails = ref<string | null>(null)
|
|
|
|
function handleError(error: any) {
|
|
hasError.value = true
|
|
errorDetails.value = error?.message || error?.toString() || 'Erreur inconnue'
|
|
|
|
// Log to console for debugging
|
|
console.error('[ErrorBoundary] Erreur capturee:', error)
|
|
|
|
// Emit for external monitoring
|
|
emit('error', error)
|
|
}
|
|
|
|
function retry() {
|
|
hasError.value = false
|
|
errorDetails.value = null
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<NuxtErrorBoundary @error="handleError">
|
|
<template v-if="!hasError">
|
|
<slot />
|
|
</template>
|
|
<template v-else>
|
|
<div class="flex flex-col items-center justify-center p-8 text-center">
|
|
<div class="max-w-md space-y-4">
|
|
<UIcon
|
|
name="i-lucide-alert-triangle"
|
|
class="text-5xl text-warning mx-auto"
|
|
/>
|
|
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">
|
|
Une erreur est survenue
|
|
</h3>
|
|
<p class="text-sm text-gray-600 dark:text-gray-400">
|
|
Un probleme inattendu s'est produit lors du chargement de ce contenu.
|
|
Vous pouvez essayer de recharger cette section.
|
|
</p>
|
|
<p
|
|
v-if="errorDetails"
|
|
class="text-xs text-gray-400 dark:text-gray-500 font-mono bg-gray-100 dark:bg-gray-800 p-2 rounded"
|
|
>
|
|
{{ errorDetails }}
|
|
</p>
|
|
<UButton
|
|
icon="i-lucide-refresh-cw"
|
|
label="Reessayer"
|
|
color="primary"
|
|
variant="soft"
|
|
@click="retry"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</NuxtErrorBoundary>
|
|
</template>
|