Use HTML swap to display success and error messages

This commit is contained in:
Alphonse Paix
2025-09-17 03:40:23 +02:00
parent 88dad022ce
commit 2d336ed000
18 changed files with 134 additions and 232 deletions

View File

@@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block title %}Admin Dashboard - zero2prod{% endblock %}
{% block title %}Dashboard - zero2prod{% endblock %}
{% block content %}
<div class="max-w-6xl mx-auto">
<div class="mb-8">
@@ -7,6 +7,15 @@
<p class="mt-2 text-gray-600">
Connected as <span class="font-bold">{{ username }}</span>
</p>
<form action="/admin/logout" method="post" class="inline">
<button type="submit"
class="flex items-center text-sm text-gray-500 hover:text-red-600 transition-colors cursor-pointer gap-1">
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
<span>Logout</span>
</button>
</form>
</div>
<div class="grid grid-cols-1 md:grid-cols-4 gap-6 mb-8">
<div class="bg-white rounded-lg shadow-md p-6 border border-gray-200">
@@ -99,7 +108,10 @@
<p class="text-sm text-gray-600 mt-1">Create and send a newsletter issue.</p>
</div>
<div class="p-6">
<form action="/admin/newsletters" method="post" class="space-y-4">
<form hx-post="/admin/newsletters"
hx-target="#newsletter-messages"
hx-swap="innerHTML"
class="space-y-4">
<input type="hidden" name="idempotency_key" value="{{ idempotency_key }}" />
<div>
<label for="title" class="block text-sm font-medium text-gray-700 mb-2">Title</label>
@@ -107,7 +119,6 @@
id="title"
name="title"
required
placeholder="Enter newsletter title..."
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
</div>
<div>
@@ -116,7 +127,6 @@
name="html"
rows="6"
required
placeholder="Enter HTML content..."
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 font-mono text-sm"></textarea>
</div>
<div>
@@ -125,7 +135,6 @@
name="text"
rows="6"
required
placeholder="Enter plain text content..."
class="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"></textarea>
</div>
<button type="submit"
@@ -138,6 +147,7 @@
</svg>
Send
</button>
<div id="newsletter-messages" class="mt-4"></div>
</form>
</div>
</div>
@@ -155,7 +165,10 @@
<p class="text-sm text-gray-600 mt-1">Set a new password for your account.</p>
</div>
<div class="p-6">
<form action="/admin/password" method="post" class="space-y-4">
<form hx-post="/admin/password"
hx-target="#password-messages"
hx-swap="innerHTML"
class="space-y-4">
<div>
<label for="current_password"
class="block text-sm font-medium text-gray-700 mb-2">Current password</label>
@@ -193,60 +206,10 @@
</svg>
Update password
</button>
<div id="password-messages" class="mt-4"></div>
</form>
</div>
</div>
</div>
<div class="mt-8 bg-white rounded-lg shadow-md border border-gray-200">
<div class="p-6 border-b border-gray-200">
<h2 class="text-xl font-semibold text-gray-900">Recent activity</h2>
</div>
<div class="p-6">
<div class="space-y-4">
<div class="flex items-center p-3 bg-gray-50 rounded-lg">
<div class="w-8 h-8 bg-blue-100 rounded-full flex items-center justify-center mr-3">
<svg class="w-4 h-4 text-blue-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 8l7.89 4.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div class="flex-1">
<p class="text-sm font-medium text-gray-900">Newsletter "Weekly Update #23" sent</p>
<p class="text-xs text-gray-500">2 hours ago • 2,143 recipients</p>
</div>
</div>
<div class="flex items-center p-3 bg-gray-50 rounded-lg">
<div class="w-8 h-8 bg-green-100 rounded-full flex items-center justify-center mr-3">
<svg class="w-4 h-4 text-green-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 9v3m0 0v3m0-3h3m-3 0h-3m-2-5a4 4 0 11-8 0 4 4 0 018 0zM3 20a6 6 0 0112 0v1H3v-1z" />
</svg>
</div>
<div class="flex-1">
<p class="text-sm font-medium text-gray-900">5 new subscribers confirmed</p>
<p class="text-xs text-gray-500">1 day ago</p>
</div>
</div>
<div class="flex items-center p-3 bg-gray-50 rounded-lg">
<div class="w-8 h-8 bg-purple-100 rounded-full flex items-center justify-center mr-3">
<svg class="w-4 h-4 text-purple-600"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
<div class="flex-1">
<p class="text-sm font-medium text-gray-900">Password changed successfully</p>
<p class="text-xs text-gray-500">3 days ago</p>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

9
templates/error.html Normal file
View File

@@ -0,0 +1,9 @@
<div class="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-md mb-4">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd">
</path>
</svg>
<span class="font-medium">{{ error_message }}</span>
</div>
</div>

View File

@@ -74,11 +74,14 @@
<div class="max-w-2xl mx-auto text-center">
<h2 class="text-2xl font-bold text-gray-900 mb-4">Stay updated</h2>
<p class="text-gray-600 mb-6">Subscribe to our newsletter to get the latest updates.</p>
<form action="/subscriptions" method="post" class="max-w-md mx-auto">
<form hx-post="/subscriptions"
hx-target="#subscribe-messages"
hx-swap="innerHTML"
class="max-w-md mx-auto">
<div class="flex flex-col sm:flex-row gap-3">
<input type="email"
name="email"
placeholder="Enter your email address"
placeholder="you@example.com"
required
class="flex-1 px-4 py-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500" />
<button type="submit"
@@ -86,8 +89,8 @@
Subscribe
</button>
</div>
<div id="subscribe-messages" class="mt-4"></div>
</form>
<div class="mt-4">{{ message }}</div>
</div>
</div>
<div class="mt-8 bg-gray-50 rounded-lg p-6">

View File

@@ -8,7 +8,10 @@
<p class="mt-2 text-sm text-gray-600">Sign in to access the admin dashboard.</p>
</div>
<div class="bg-white rounded-lg shadow-md p-8 border border-gray-200">
<form action="/login" method="post" class="space-y-6">
<form hx-post="/login"
hx-target="#login-messages"
hx-swap="innerHTML"
class="space-y-6">
<div>
<label for="username" class="block text-sm font-medium text-gray-700 mb-2">Username</label>
<input type="text"
@@ -31,8 +34,8 @@
Continue
</button>
</div>
<div id="login-messages" class="mt-4"></div>
</form>
<div class="mt-4 text-center">{{ error }}</div>
</div>
<div class="text-center">
<a href="/"

9
templates/success.html Normal file
View File

@@ -0,0 +1,9 @@
<div class="bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-md mb-4">
<div class="flex items-center">
<svg class="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd">
</path>
</svg>
<span class="font-medium">{{ success_message }}</span>
</div>
</div>