Feat: Implement Admin Dashboard UI

This commit introduces the foundational UI for the admin dashboard. It
includes:
- A new `maud`-based layout component for consistent page structure.
- A navigation sidebar and header.
- Basic views for dashboard overview, user management, library settings,
  and about page.
- Integration with Tailwind CSS and Phosphor Icons for styling.
- Added `maud` and `axum-core` as dependencies.
This commit is contained in:
vaibhav
2026-03-15 05:38:48 +05:30
parent c862669b08
commit 3f33bcdf32
17 changed files with 1583 additions and 0 deletions

114
src/admin/views/login.rs Normal file
View File

@@ -0,0 +1,114 @@
use maud::{html, Markup, DOCTYPE};
use axum::{Form, response::Redirect};
use serde::Deserialize;
#[derive(Deserialize)]
pub struct LoginPayload {
pub username: String,
pub password: String,
}
pub async fn login_form() -> Markup {
render_login(None)
}
pub async fn login_post(Form(payload): Form<LoginPayload>) -> Result<Redirect, Markup> {
if payload.username == "admin" && payload.password == "admin" {
Ok(Redirect::to("/admin"))
} else {
Err(render_login(Some("Invalid username or password.")))
}
}
fn render_login(error: Option<&str>) -> Markup {
html! {
(DOCTYPE)
html lang="en" {
head {
meta charset="utf-8";
meta name="viewport" content="width=device-width, initial-scale=1";
title { "SoundSonic Admin - Login" }
script src="https://cdn.tailwindcss.com" {}
script {
(maud::PreEscaped(r##"
tailwind.config = {
darkMode: 'class',
theme: {
extend: {
colors: {
primary: {"50":"#eff6ff","100":"#dbeafe","200":"#bfdbfe","300":"#93c5fd","400":"#60a5fa","500":"#3b82f6","600":"#2563eb","700":"#1d4ed8","800":"#1e40af","900":"#1e3a8a","950":"#172554"}
},
fontFamily: { sans: ['Inter', 'sans-serif'] }
}
}
}
"##))
}
link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet";
script src="https://unpkg.com/@phosphor-icons/web" {}
style {
(maud::PreEscaped(r##"
body { font-family: 'Inter', sans-serif; background-color: #0f172a; color: #f8fafc; }
.glass-card {
background: rgba(30, 41, 59, 0.6);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.5), 0 10px 10px -5px rgba(0, 0, 0, 0.2);
}
"##))
}
}
body class="min-h-screen flex items-center justify-center relative overflow-hidden antialiased selection:bg-primary-500 selection:text-white" {
// Background Glows
div class="absolute top-[20%] left-[20%] w-[30%] h-[30%] rounded-full bg-primary-900/30 blur-[120px] pointer-events-none" {}
div class="absolute bottom-[20%] right-[20%] w-[30%] h-[30%] rounded-full bg-blue-900/20 blur-[120px] pointer-events-none" {}
div class="w-full max-w-sm glass-card rounded-2xl p-8 z-10 relative" {
div class="flex flex-col items-center mb-8" {
div class="w-16 h-16 rounded-full bg-gradient-to-tr from-primary-500 to-indigo-600 flex items-center justify-center border-4 border-black/40 shadow-xl shadow-primary-500/20 mb-4" {
i class="ph-fill ph-waves text-3xl text-white" {}
}
h1 class="text-2xl font-bold text-white tracking-tight" { "SoundSonic Admin" }
p class="text-slate-400 text-sm mt-1" { "Sign in to access control center" }
}
@if let Some(msg) = error {
div class="bg-rose-500/10 border border-rose-500/20 rounded-lg p-3 mb-6 flex items-start gap-3" {
i class="ph-fill ph-warning-circle text-rose-400 text-lg mt-0.5" {}
p class="text-sm text-rose-200" { (msg) }
}
}
form action="/admin/login" method="POST" class="space-y-5" {
div {
label for="username" class="block text-sm font-medium text-slate-300 mb-1.5" { "Username" }
div class="relative" {
div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none" {
i class="ph ph-user text-slate-500 text-lg" {}
}
input type="text" name="username" id="username" required class="block w-full pl-10 pr-4 py-2.5 bg-black/40 border border-white/10 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-primary-500/50 focus:border-primary-500 transition-all sm:text-sm" placeholder="admin" {}
}
}
div {
div class="flex justify-between items-center mb-1.5" {
label for="password" class="block text-sm font-medium text-slate-300" { "Password" }
}
div class="relative" {
div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none" {
i class="ph ph-lock-key text-slate-500 text-lg" {}
}
input type="password" name="password" id="password" required class="block w-full pl-10 pr-4 py-2.5 bg-black/40 border border-white/10 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-primary-500/50 focus:border-primary-500 transition-all sm:text-sm" placeholder="••••••••" {}
}
}
button type="submit" class="w-full flex justify-center py-2.5 px-4 border border-transparent rounded-lg shadow-sm shadow-primary-900/20 text-sm font-medium text-white bg-primary-600 hover:bg-primary-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500 transition-colors mt-2" {
"Sign In"
}
}
}
}
}
}
}