Apply modern SaaS design to all admin pages

Modernize all admin interface pages with consistent design language:
- Add hero sections with gradient backgrounds and blur effects
- Implement modern card designs with hover animations
- Use gradient buttons with shadow effects
- Add emoji icons in colored containers
- Apply consistent color themes per page
- Enhance user experience with smooth transitions

Pages updated:
- /admin/devices (purple theme)
- /admin/mqtt (cyan/blue theme)
- /admin/setup (emerald theme)
- /admin/users (violet theme)
- /admin/settings (indigo theme)
- /admin/emails (pink/rose theme)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-29 23:31:25 +00:00
parent 5f637817ce
commit a39b53151e
6 changed files with 392 additions and 243 deletions

View File

@@ -224,19 +224,26 @@ export default function UsersPage() {
}
return (
<div>
{/* Header */}
<div className="flex justify-between items-center mb-6">
<h2 className="text-3xl font-bold text-gray-900">User Management</h2>
<button
onClick={() => {
setFormData({ username: "", email: "", password: "", role: "VIEWER" });
setShowAddModal(true);
}}
className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700"
>
Add User
</button>
<div className="space-y-8">
{/* Hero Section with Gradient */}
<div className="relative overflow-hidden rounded-2xl bg-gradient-to-br from-violet-600 via-purple-700 to-fuchsia-800 p-8 shadow-xl">
<div className="absolute top-0 right-0 -mt-4 -mr-4 h-40 w-40 rounded-full bg-white/10 blur-3xl"></div>
<div className="absolute bottom-0 left-0 -mb-4 -ml-4 h-40 w-40 rounded-full bg-white/10 blur-3xl"></div>
<div className="relative flex justify-between items-center">
<div>
<h2 className="text-4xl font-bold text-white mb-2">User Management</h2>
<p className="text-violet-100 text-lg">Verwalte Benutzerkonten und Berechtigungen</p>
</div>
<button
onClick={() => {
setFormData({ username: "", email: "", password: "", role: "VIEWER" });
setShowAddModal(true);
}}
className="px-6 py-3 bg-white text-violet-700 rounded-xl hover:bg-violet-50 font-semibold shadow-lg hover:shadow-xl transition-all transform hover:-translate-y-0.5"
>
+ Add User
</button>
</div>
</div>
{/* Users Grid */}
@@ -244,38 +251,50 @@ export default function UsersPage() {
{users.map((user) => (
<div
key={user.id}
className="bg-white rounded-lg shadow-md p-6 border-l-4"
style={{
borderLeftColor: user.role === "ADMIN" ? "#ef4444" : "#3b82f6",
}}
className="group relative overflow-hidden bg-white rounded-2xl shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-1 p-6"
>
<div className={`absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity bg-gradient-to-br ${
user.role === "ADMIN" ? "from-red-50 to-orange-50" : "from-blue-50 to-indigo-50"
}`}></div>
<div className="relative">
<div className="flex items-start justify-between mb-4">
<span
className={`px-2 py-1 text-xs font-medium rounded ${
<div className="flex items-center gap-3">
<div className={`w-12 h-12 rounded-xl shadow-lg flex items-center justify-center text-2xl ring-2 ring-white transform group-hover:scale-110 transition-transform ${
user.role === "ADMIN"
? "bg-red-100 text-red-800"
: "bg-blue-100 text-blue-800"
}`}
>
{user.role}
</span>
? "bg-gradient-to-br from-red-500 to-orange-600"
: "bg-gradient-to-br from-blue-500 to-indigo-600"
}`}>
{user.role === "ADMIN" ? "👑" : "👤"}
</div>
<span
className={`px-3 py-1.5 text-xs font-bold rounded-lg shadow-md ${
user.role === "ADMIN"
? "bg-gradient-to-r from-red-500 to-orange-600 text-white"
: "bg-gradient-to-r from-blue-500 to-indigo-600 text-white"
}`}
>
{user.role}
</span>
</div>
</div>
<div className="space-y-2 text-sm mb-4">
<p>
<span className="font-medium text-gray-700">Username:</span>{" "}
<span className="text-gray-900">{user.username}</span>
<div className="bg-gradient-to-br from-gray-50 to-slate-50 rounded-xl p-4 mb-4 border border-gray-200 space-y-2 text-sm">
<p className="flex items-center justify-between">
<span className="font-semibold text-gray-700">Username:</span>
<span className="text-gray-900 font-mono bg-white px-2 py-0.5 rounded">{user.username}</span>
</p>
<p>
<span className="font-medium text-gray-700">Email:</span>{" "}
<p className="flex items-center justify-between">
<span className="font-semibold text-gray-700">Email:</span>
<span className="text-gray-900">{user.email || "—"}</span>
</p>
<p className="text-gray-600">
Created: {new Date(user.createdAt).toLocaleDateString()}
<p className="flex items-center justify-between text-gray-600">
<span>Created:</span>
<span>{new Date(user.createdAt).toLocaleDateString()}</span>
</p>
{user.lastLoginAt && (
<p className="text-gray-600">
Last login: {new Date(user.lastLoginAt).toLocaleString()}
<p className="flex items-center justify-between text-gray-600">
<span>Last login:</span>
<span>{new Date(user.lastLoginAt).toLocaleString()}</span>
</p>
)}
</div>
@@ -283,13 +302,13 @@ export default function UsersPage() {
<div className="flex gap-2">
<button
onClick={() => openEditModal(user)}
className="flex-1 px-3 py-2 bg-blue-600 text-white text-sm rounded-md hover:bg-blue-700"
className="flex-1 px-4 py-2.5 bg-gradient-to-r from-blue-600 to-blue-700 text-white text-sm font-semibold rounded-lg hover:from-blue-700 hover:to-blue-800 shadow-md hover:shadow-lg transition-all"
>
Edit
</button>
<button
onClick={() => openDeleteModal(user)}
className="flex-1 px-3 py-2 bg-red-600 text-white text-sm rounded-md hover:bg-red-700"
className="flex-1 px-4 py-2.5 bg-gradient-to-r from-red-600 to-red-700 text-white text-sm font-semibold rounded-lg hover:from-red-700 hover:to-red-800 shadow-md hover:shadow-lg transition-all"
>
Delete
</button>
@@ -300,15 +319,15 @@ export default function UsersPage() {
<div className="flex gap-2 mt-2">
<button
onClick={() => handleResendWelcome(user)}
className="flex-1 px-3 py-2 bg-green-600 text-white text-xs rounded-md hover:bg-green-700"
className="flex-1 px-3 py-2 bg-gradient-to-r from-green-500 to-emerald-600 text-white text-xs font-semibold rounded-lg hover:from-green-600 hover:to-emerald-700 shadow-md hover:shadow-lg transition-all"
>
Resend Welcome
📧 Resend Welcome
</button>
<button
onClick={() => handleSendPasswordReset(user)}
className="flex-1 px-3 py-2 bg-orange-600 text-white text-xs rounded-md hover:bg-orange-700"
className="flex-1 px-3 py-2 bg-gradient-to-r from-orange-500 to-red-500 text-white text-xs font-semibold rounded-lg hover:from-orange-600 hover:to-red-600 shadow-md hover:shadow-lg transition-all"
>
Reset Password
🔑 Reset Password
</button>
</div>
)}
@@ -317,8 +336,10 @@ export default function UsersPage() {
</div>
{users.length === 0 && (
<div className="text-center py-12">
<p className="text-gray-600">No users found. Create your first user!</p>
<div className="relative overflow-hidden bg-gradient-to-br from-gray-50 to-slate-50 rounded-2xl shadow-lg p-12 text-center border border-gray-200">
<div className="absolute top-0 right-0 text-9xl opacity-5">👤</div>
<p className="text-xl font-semibold text-gray-600 mb-2">Keine Benutzer gefunden</p>
<p className="text-gray-500">Erstelle deinen ersten Benutzer!</p>
</div>
)}