feat(ui): add error handling, flash messages and SEO optimization
- Add custom error pages (404, 403, 500) with user-friendly messages
- Add flash message system with signed cookies for security
- Add toast notifications with auto-dismiss and manual close
- Add comprehensive SEO meta tags (description, keywords, OG, Twitter)
- Add canonical URLs for SEO
- Update routes to use slug-based URLs (/posts/{slug} instead of /posts/{id})
- Add Open Graph and Twitter Card meta tags for social sharing
- Add favicon SVG
- Update all templates with proper meta tags and URLs
- Add error handlers registration in main.py
- Add flash middleware for request handling
- Install itsdangerous dependency
This commit is contained in:
111
app/presentation/templates/pages/error.html
Normal file
111
app/presentation/templates/pages/error.html
Normal file
@@ -0,0 +1,111 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}{{ error_code }} - {{ error_title }}{% endblock %}
|
||||
{% block meta_description %}{{ error_message }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="error-page" data-testid="error-page">
|
||||
<div class="error-content" data-testid="error-content">
|
||||
<div class="error-icon" data-testid="error-icon">
|
||||
{% if error_code == 404 %}
|
||||
🔍
|
||||
{% elif error_code == 403 %}
|
||||
🚫
|
||||
{% elif error_code == 500 %}
|
||||
⚠️
|
||||
{% else %}
|
||||
❌
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<h1 class="error-code" data-testid="error-code">{{ error_code }}</h1>
|
||||
<h2 class="error-title" data-testid="error-title">{{ error_title }}</h2>
|
||||
<p class="error-message" data-testid="error-message">{{ error_message }}</p>
|
||||
|
||||
<div class="error-actions" data-testid="error-actions">
|
||||
<a href="/" class="btn btn-primary" data-testid="btn-error-home">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" style="margin-right: 0.5rem;">
|
||||
<path d="M2 8L8 2L14 8M4 6V13H12V6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
Go Home
|
||||
</a>
|
||||
|
||||
{% if error_code == 403 %}
|
||||
<a href="/auth/login" class="btn" data-testid="btn-error-login">
|
||||
Sign In
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<button onclick="window.history.back()" class="btn btn-ghost" data-testid="btn-error-back">
|
||||
Go Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.error-page {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 60vh;
|
||||
padding: 2rem 1rem;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.error-code {
|
||||
font-size: 6rem;
|
||||
font-weight: 700;
|
||||
color: var(--color-primary);
|
||||
margin: 0;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.error-title {
|
||||
font-size: 1.5rem;
|
||||
color: var(--color-text-dark);
|
||||
margin: 1rem 0 0.5rem;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--color-text-light);
|
||||
font-size: 1.125rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
display: flex;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.error-code {
|
||||
font-size: 4rem;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 3.5rem;
|
||||
}
|
||||
|
||||
.error-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.error-actions .btn {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user