NEXUS-1: Initial commit of Nexus
This commit is contained in:
43
internal/handler/templates/base.html
Normal file
43
internal/handler/templates/base.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{{define "base"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Nexus Control Panel</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><text y='28' font-size='28'>⚡</text></svg>">
|
||||
<style>
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(-4px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.2s ease-out;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 flex items-center justify-center p-4">
|
||||
<div class="w-full max-w-md">
|
||||
<!-- Logo -->
|
||||
<div class="text-center mb-8">
|
||||
<div class="text-4xl mb-2">⚡</div>
|
||||
<h1 class="text-2xl font-bold text-white tracking-tight">Nexus</h1>
|
||||
<p class="text-slate-400 text-sm mt-1">Control Panel</p>
|
||||
</div>
|
||||
|
||||
<!-- Card -->
|
||||
<div class="bg-slate-800/50 backdrop-blur-sm border border-slate-700/50 rounded-xl shadow-2xl p-8">
|
||||
{{template "content" .}}
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<p class="text-center text-slate-500 text-xs mt-6">
|
||||
Arcline Platform · Single Sign-On
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
||||
|
||||
58
internal/handler/templates/forgot-password.html
Normal file
58
internal/handler/templates/forgot-password.html
Normal file
@@ -0,0 +1,58 @@
|
||||
{{define "content"}}
|
||||
<div id="auth-form">
|
||||
<h2 class="text-xl font-semibold text-white mb-2">Reset your password</h2>
|
||||
<p class="text-slate-400 text-sm mb-6">Enter your email address and we'll send you a link to reset your password.</p>
|
||||
|
||||
{{if .Success}}
|
||||
<div class="bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Success}}
|
||||
</div>
|
||||
|
||||
<p class="text-center text-slate-400 text-sm mt-6">
|
||||
<a href="/login" class="text-indigo-400 hover:text-indigo-300 font-medium transition-colors">Back to sign in</a>
|
||||
</p>
|
||||
{{else}}
|
||||
{{if .Error}}
|
||||
<div class="bg-red-500/10 border border-red-500/30 text-red-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Error}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<form
|
||||
hx-post="/forgot-password"
|
||||
hx-target="#auth-form"
|
||||
hx-swap="outerHTML"
|
||||
hx-disabled-elt="button[type=submit], input"
|
||||
class="space-y-5"
|
||||
>
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-slate-300 mb-1.5">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value="{{.Email}}"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="email"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="you@example.com"
|
||||
>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full py-2.5 px-4 bg-indigo-600 hover:bg-indigo-500 text-white font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-slate-800 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span class="htmx-indicator">Send reset link</span>
|
||||
<span class="htmx-request hidden">Sending...</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-slate-400 text-sm mt-6">
|
||||
<a href="/login" class="text-indigo-400 hover:text-indigo-300 font-medium transition-colors">Back to sign in</a>
|
||||
</p>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
79
internal/handler/templates/login.html
Normal file
79
internal/handler/templates/login.html
Normal file
@@ -0,0 +1,79 @@
|
||||
{{define "content"}}
|
||||
<div id="auth-form">
|
||||
<h2 class="text-xl font-semibold text-white mb-6">Sign in to your account</h2>
|
||||
|
||||
{{if .Error}}
|
||||
<div class="bg-red-500/10 border border-red-500/30 text-red-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Error}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Success}}
|
||||
<div class="bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Success}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<form
|
||||
hx-post="/login"
|
||||
hx-target="#auth-form"
|
||||
hx-swap="outerHTML"
|
||||
hx-disabled-elt="button[type=submit], input"
|
||||
class="space-y-5"
|
||||
>
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-slate-300 mb-1.5">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value="{{.Email}}"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="email"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="you@example.com"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium text-slate-300 mb-1.5">Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
required
|
||||
autocomplete="current-password"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="••••••••"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between text-sm">
|
||||
<label class="flex items-center text-slate-400">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="remember"
|
||||
class="rounded border-slate-600 bg-slate-700 text-indigo-500 focus:ring-indigo-500 mr-2"
|
||||
>
|
||||
Remember me
|
||||
</label>
|
||||
<a href="/forgot-password" class="text-indigo-400 hover:text-indigo-300 transition-colors">Forgot password?</a>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full py-2.5 px-4 bg-indigo-600 hover:bg-indigo-500 text-white font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-slate-800 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span class="htmx-indicator">Sign in</span>
|
||||
<span class="htmx-request hidden">Signing in...</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-slate-400 text-sm mt-6">
|
||||
Don't have an account?
|
||||
<a href="/signup" class="text-indigo-400 hover:text-indigo-300 font-medium transition-colors">Create one</a>
|
||||
</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
68
internal/handler/templates/reset-password.html
Normal file
68
internal/handler/templates/reset-password.html
Normal file
@@ -0,0 +1,68 @@
|
||||
{{define "content"}}
|
||||
<div id="auth-form">
|
||||
<h2 class="text-xl font-semibold text-white mb-6">Set a new password</h2>
|
||||
|
||||
{{if .Error}}
|
||||
<div class="bg-red-500/10 border border-red-500/30 text-red-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Error}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .Success}}
|
||||
<div class="bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Success}}
|
||||
</div>
|
||||
<p class="text-center text-slate-400 text-sm mt-6">
|
||||
<a href="/login" class="text-indigo-400 hover:text-indigo-300 font-medium transition-colors">Sign in with your new password</a>
|
||||
</p>
|
||||
{{else}}
|
||||
<form
|
||||
hx-post="/reset-password"
|
||||
hx-target="#auth-form"
|
||||
hx-swap="outerHTML"
|
||||
hx-disabled-elt="button[type=submit], input"
|
||||
class="space-y-5"
|
||||
>
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium text-slate-300 mb-1.5">New password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
required
|
||||
minlength="8"
|
||||
autofocus
|
||||
autocomplete="new-password"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="At least 8 characters"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password_confirm" class="block text-sm font-medium text-slate-300 mb-1.5">Confirm new password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="password_confirm"
|
||||
required
|
||||
minlength="8"
|
||||
autocomplete="new-password"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="Repeat your password"
|
||||
>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full py-2.5 px-4 bg-indigo-600 hover:bg-indigo-500 text-white font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-slate-800 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span class="htmx-indicator">Reset password</span>
|
||||
<span class="htmx-request hidden">Resetting...</span>
|
||||
</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
90
internal/handler/templates/signup.html
Normal file
90
internal/handler/templates/signup.html
Normal file
@@ -0,0 +1,90 @@
|
||||
{{define "content"}}
|
||||
<div id="auth-form">
|
||||
<h2 class="text-xl font-semibold text-white mb-6">Create your account</h2>
|
||||
|
||||
{{if .Error}}
|
||||
<div class="bg-red-500/10 border border-red-500/30 text-red-400 rounded-lg px-4 py-3 mb-6 text-sm animate-fade-in" role="alert">
|
||||
{{.Error}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<form
|
||||
hx-post="/signup"
|
||||
hx-target="#auth-form"
|
||||
hx-swap="outerHTML"
|
||||
hx-disabled-elt="button[type=submit], input"
|
||||
class="space-y-5"
|
||||
>
|
||||
<div>
|
||||
<label for="display_name" class="block text-sm font-medium text-slate-300 mb-1.5">Full name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="display_name"
|
||||
name="display_name"
|
||||
value="{{.DisplayName}}"
|
||||
required
|
||||
autofocus
|
||||
autocomplete="name"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="Jane Smith"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="email" class="block text-sm font-medium text-slate-300 mb-1.5">Email address</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value="{{.Email}}"
|
||||
required
|
||||
autocomplete="email"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="you@example.com"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-sm font-medium text-slate-300 mb-1.5">Password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password"
|
||||
name="password"
|
||||
required
|
||||
minlength="8"
|
||||
autocomplete="new-password"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="At least 8 characters"
|
||||
>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password_confirm" class="block text-sm font-medium text-slate-300 mb-1.5">Confirm password</label>
|
||||
<input
|
||||
type="password"
|
||||
id="password_confirm"
|
||||
name="password_confirm"
|
||||
required
|
||||
minlength="8"
|
||||
autocomplete="new-password"
|
||||
class="w-full px-4 py-2.5 bg-slate-700/50 border border-slate-600 rounded-lg text-white placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:border-transparent transition-colors"
|
||||
placeholder="Repeat your password"
|
||||
>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
class="w-full py-2.5 px-4 bg-indigo-600 hover:bg-indigo-500 text-white font-medium rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 focus:ring-offset-slate-800 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
>
|
||||
<span class="htmx-indicator">Create account</span>
|
||||
<span class="htmx-request hidden">Creating account...</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-slate-400 text-sm mt-6">
|
||||
Already have an account?
|
||||
<a href="/login" class="text-indigo-400 hover:text-indigo-300 font-medium transition-colors">Sign in</a>
|
||||
</p>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user