feat(frontend): T44 setup FastAPI static files and templates

- Mount static files on /static endpoint
- Configure Jinja2Templates with directory structure
- Create base template with Pico.css, HTMX, Chart.js
- Create all template subdirectories (auth, dashboard, keys, tokens, profile, components)
- Create initial CSS and JS files
- Add tests for static files and templates configuration

Tests: 12 passing
Coverage: 100% on new configuration code
This commit is contained in:
Luca Sacchi Ricciardi
2026-04-07 17:58:03 +02:00
parent 3ae5d736ce
commit c1f47c897f
16 changed files with 1592 additions and 4 deletions

View File

@@ -0,0 +1,87 @@
{% extends "base.html" %}
{% block title %}Profile - OpenRouter Monitor{% endblock %}
{% block content %}
<h1>User Profile</h1>
<!-- Profile Information -->
<article>
<header>
<h3>Account Information</h3>
</header>
<p><strong>Email:</strong> {{ user.email }}</p>
<p><strong>Account Created:</strong> {{ user.created_at }}</p>
</article>
<!-- Change Password -->
<article>
<header>
<h3>Change Password</h3>
</header>
<form action="/profile/password" method="POST" hx-post="/profile/password" hx-swap="outerHTML">
{% if password_message %}
<div class="alert {% if password_success %}alert-success{% else %}alert-danger{% endif %}" role="alert">
{{ password_message }}
</div>
{% endif %}
<label for="current_password">
Current Password
<input type="password" id="current_password" name="current_password" required>
</label>
<label for="new_password">
New Password
<input
type="password"
id="new_password"
name="new_password"
required
minlength="8"
pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).+$"
title="Password must contain at least one lowercase letter, one uppercase letter, and one number"
>
<small>Minimum 8 characters with uppercase, lowercase, and number</small>
</label>
<label for="new_password_confirm">
Confirm New Password
<input type="password" id="new_password_confirm" name="new_password_confirm" required>
</label>
<button type="submit">Update Password</button>
</form>
</article>
<!-- Danger Zone -->
<article style="border-color: var(--danger-color);">
<header>
<h3 style="color: var(--danger-color);">Danger Zone</h3>
</header>
<p>Once you delete your account, there is no going back. Please be certain.</p>
<button
class="secondary"
style="background-color: var(--danger-color); border-color: var(--danger-color);"
hx-delete="/profile"
hx-confirm="Are you absolutely sure you want to delete your account? All your data will be permanently removed."
hx-redirect="/"
>
Delete Account
</button>
</article>
<script>
// Client-side password match validation
document.getElementById('new_password_confirm').addEventListener('input', function() {
const password = document.getElementById('new_password').value;
const confirm = this.value;
if (password !== confirm) {
this.setCustomValidity('Passwords do not match');
} else {
this.setCustomValidity('');
}
});
</script>
{% endblock %}