monacousa-portal/error.vue

215 lines
6.3 KiB
Vue

<template>
<div class="error-page">
<v-app>
<v-main>
<v-container class="fill-height">
<v-row justify="center" align="center" class="fill-height">
<v-col cols="12" md="8" lg="6" class="text-center">
<!-- Logo -->
<v-img
src="/MONACOUSA-Flags_376x376.png"
width="120"
height="120"
class="mx-auto mb-6"
/>
<!-- Error Code -->
<h1 class="text-h1 font-weight-bold mb-4" style="color: #a31515;">
{{ error.statusCode }}
</h1>
<!-- Error Title -->
<h2 class="text-h3 mb-4 text-grey-darken-2">
{{ getErrorTitle(error.statusCode) }}
</h2>
<!-- Error Message -->
<p class="text-h6 mb-6 text-medium-emphasis" style="max-width: 600px; margin: 0 auto;">
{{ getErrorMessage(error.statusCode) }}
</p>
<!-- Additional Info for 403 -->
<v-alert
v-if="error.statusCode === 403"
type="warning"
variant="tonal"
class="mb-6 text-left"
style="max-width: 500px; margin: 0 auto;"
>
<v-alert-title>Access Restricted</v-alert-title>
<p class="mb-2">This resource requires specific permissions:</p>
<ul class="ml-4">
<li v-if="error.statusMessage?.includes('Board')">Board membership required</li>
<li v-if="error.statusMessage?.includes('Admin')">Administrator privileges required</li>
<li v-if="!error.statusMessage?.includes('Board') && !error.statusMessage?.includes('Admin')">
Higher access level required
</li>
</ul>
</v-alert>
<!-- Action Buttons -->
<div class="d-flex flex-column flex-sm-row justify-center gap-4 mb-6">
<v-btn
color="primary"
size="large"
style="background-color: #a31515;"
@click="goHome"
>
<v-icon start>mdi-home</v-icon>
Go to Dashboard
</v-btn>
<v-btn
variant="outlined"
size="large"
style="border-color: #a31515; color: #a31515;"
@click="goBack"
>
<v-icon start>mdi-arrow-left</v-icon>
Go Back
</v-btn>
</div>
<!-- Contact Support for 403 -->
<div v-if="error.statusCode === 403" class="mt-8">
<v-divider class="mb-4" />
<p class="text-body-2 text-medium-emphasis mb-3">
Need access to this resource?
</p>
<v-btn
variant="text"
color="primary"
@click="contactSupport"
>
<v-icon start>mdi-email</v-icon>
Contact Administrator
</v-btn>
</div>
<!-- Debug Info (development only) -->
<div v-if="isDevelopment" class="mt-8 pa-4 bg-grey-lighten-4 rounded">
<p class="text-caption text-grey-darken-1 mb-2">Debug Information:</p>
<p class="text-caption font-mono">{{ error.statusMessage }}</p>
<p class="text-caption font-mono">{{ error.url }}</p>
</div>
</v-col>
</v-row>
</v-container>
</v-main>
</v-app>
</div>
</template>
<script setup lang="ts">
interface ErrorProps {
error: {
statusCode: number;
statusMessage: string;
url?: string;
};
}
const props = defineProps<ErrorProps>();
// Check if we're in development mode
const isDevelopment = process.dev;
// Error title mapping
const getErrorTitle = (code: number): string => {
switch (code) {
case 403: return 'Access Denied';
case 404: return 'Page Not Found';
case 500: return 'Server Error';
case 401: return 'Unauthorized';
default: return 'Something Went Wrong';
}
};
// Error message mapping
const getErrorMessage = (code: number): string => {
switch (code) {
case 403:
return 'You do not have the required permissions to access this resource. Please contact your administrator if you believe this is an error.';
case 404:
return 'The page you are looking for could not be found. It may have been moved, deleted, or you may have entered the wrong URL.';
case 500:
return 'An internal server error occurred. Our team has been notified and is working to resolve the issue. Please try again later.';
case 401:
return 'You need to be logged in to access this resource. Please sign in and try again.';
default:
return 'An unexpected error occurred. Please try refreshing the page or contact support if the problem persists.';
}
};
// Navigation methods
const goHome = () => {
navigateTo('/dashboard');
};
const goBack = () => {
if (window.history.length > 1) {
window.history.back();
} else {
navigateTo('/dashboard');
}
};
const contactSupport = () => {
// TODO: Implement support contact (email, help desk, etc.)
window.location.href = 'mailto:support@monacousa.org?subject=Access Request&body=I need access to a restricted resource.';
};
// Set page title
useHead({
title: `Error ${props.error.statusCode} - MonacoUSA Portal`,
meta: [
{ name: 'robots', content: 'noindex' }
]
});
</script>
<style scoped>
.error-page {
min-height: 100vh;
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
}
.v-main {
background: transparent !important;
}
.font-mono {
font-family: 'Courier New', monospace;
}
.v-btn {
text-transform: none !important;
}
.v-alert {
text-align: left;
}
.v-alert ul {
margin-bottom: 0;
}
.v-alert li {
margin-bottom: 4px;
}
@media (max-width: 600px) {
.text-h1 {
font-size: 4rem !important;
}
.text-h3 {
font-size: 1.75rem !important;
}
.text-h6 {
font-size: 1.1rem !important;
}
}
</style>