Sprint 5 : integration et production -- securite, performance, API publique, documentation
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>
This commit is contained in:
70
frontend/app/components/common/ErrorBoundary.vue
Normal file
70
frontend/app/components/common/ErrorBoundary.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user