webcodelab's picture
Update app/templates/settings.html
024c1b2 verified
Raw
History Blame Contribute Delete
13.3 kB
{% extends "base.html" %}
{% block title %}Settings – Resume Ranker API{% endblock %}
{% block extra_head %}
{# No extra head elements are strictly needed here if dashboard.css covers all form/card styles #}
<style>
/* Specific styling for the settings content if not fully covered by dashboard.css */
.settings-form-group {
margin-bottom: 1.5rem;
}
.settings-form-group label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--text-color);
}
.settings-form-group input[type="text"],
.settings-form-group input[type="email"],
.settings-form-group input[type="password"] {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
background-color: var(--input-bg);
color: var(--input-text);
box-sizing: border-box;
font-size: 1rem;
}
.settings-form-group input[readonly] {
background-color: var(--bg-light);
opacity: 0.8;
cursor: not-allowed;
}
.danger-zone .btn-danger {
background-color: var(--danger-color);
color: var(--btn-text-color);
border: none;
}
.danger-zone .btn-danger:hover {
background-color: var(--danger-hover);
}
/* Adjust mt/mb spacing if needed */
.content-padding .mt-3 { margin-top: 1rem; }
.content-padding .mt-4 { margin-top: 1.5rem; }
.content-padding .mb-4 { margin-bottom: 1.5rem; }
</style>
{% endblock %}
{% block content %}
<div class="dashboard-wrapper">
<aside class="sidebar" id="sidebar">
<div class="sidebar-header">
<div class="logo">ResumeRanker<span style="color:var(--accent)">.API</span></div>
<button class="close-sidebar" id="closeSidebar" aria-label="Close menu">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-x"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>
</button>
</div>
<nav class="sidebar-nav">
{# Use Flask's request.endpoint to set 'active' class #}
<a href="{{ url_for('auth.dashboard') }}" class="nav-item {% if request.endpoint == 'auth.dashboard' %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-grid"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
<span>Dashboard</span>
</a>
<a href="{{ url_for('auth.api_keys') }}" class="nav-item {% if request.endpoint == 'auth.api_keys' %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-key"><path d="M19 10H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2z"></path><circle cx="12" cy="16" r="2"></circle><path d="M15 10V4.5a2.5 2.5 0 0 0-5 0V10"></path></svg>
<span>My API Keys</span>
</a>
<a href="{{ url_for('auth.rank_resumes') }}" class="nav-item {% if request.endpoint == 'auth.resume_rankings' %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-award"><circle cx="12" cy="8" r="7"></circle><polyline points="8.21 13.89 7 23 12 20 17 23 15.79 13.89"></polyline></svg>
<span>Resume Rankings</span>
</a>
<a href="{{ url_for('auth.try_api') }}" class="nav-item {% if request.endpoint == 'auth.try_api' %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-play-circle"><circle cx="12" cy="12" r="10"></circle><polygon points="10 8 16 12 10 16 10 8"></polygon></svg>
<span>Try It Now</span>
</a>
<a href="#" class="nav-item {% if request.endpoint == 'auth.api_docs' %}active{% endif %}">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-book"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20V6.5A2.5 2.5 0 0 0 17.5 4h-11A2.5 2.5 0 0 0 4 6.5v13z"></path><path d="M11 6h6"></path><path d="M11 10h6"></path><path d="M11 14h6"></path></svg>
<span>API Docs</span>
</a>
<a href="{{ url_for('auth.api_docs') }}" class="nav-item">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-book-open">
<path d="M2 3h6a4 4 0 0 1 4 4v13H6a4 4 0 0 0-4-4z"></path>
<path d="M22 3h-6a4 4 0 0 0-4 4v13h6a4 4 0 0 1 4-4z"></path>
</svg>
<span>API Docs</span>
</a>
<a href="{{ url_for('auth.logout') }}" class="nav-item logout-item">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-log-out"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="17 16 22 12 17 8"></polyline><line x1="22" y1="12" x2="10" y2="12"></line></svg>
<span>Logout</span>
</a>
</nav>
</aside>
<div class="main-content-area" id="mainContentArea">
<header class="dashboard-header">
<button class="hamburger-dashboard" id="hamburgerDashboard" aria-label="Open sidebar menu">
<span></span><span></span><span></span>
</button>
<div class="user-settings">
<span class="user-name">{{ user.username }}</span>
<div class="user-avatar">
<img src="https://ui-avatars.com/api/?name={{ user.username | urlencode }}&background=2563eb&color=fff&size=30" alt="User Avatar">
</div>
<button class="theme-toggle" id="themeToggleDashboard" aria-label="Toggle dark mode">🌙</button>
</div>
</header>
<div class="content-padding">
<h1 class="welcome-title">Account Settings</h1>
<p class="subtitle">Manage your profile, password, and preferences.</p>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="flash-message flash-{{ category }}">{{ message }}</div>
{% endfor %}
{% endif %}
{% endwith %}
<div class="section-card profile-settings">
<h3 class="section-title">Profile Information</h3>
<form action="{{ url_for('auth.update_profile') }}" method="POST">
<div class="settings-form-group">
<label for="username">Username</label>
<input type="text" id="username" name="username" value="{{ user.username }}" readonly>
</div>
<div class="settings-form-group">
<label for="email">Email Address</label>
<input type="email" id="email" name="email" value="{{ user.email }}" required>
</div>
{# Add more profile fields if you have them, e.g., first_name, last_name #}
<button type="submit" class="btn primary-btn">Update Profile</button>
</form>
</div>
<div class="section-card password-settings mt-4">
<h3 class="section-title">Change Password</h3>
<form action="{{ url_for('auth.change_password') }}" method="POST">
<div class="settings-form-group">
<label for="current_password">Current Password</label>
<input type="password" id="current_password" name="current_password" required>
</div>
<div class="settings-form-group">
<label for="new_password">New Password</label>
<input type="password" id="new_password" name="new_password" required>
</div>
<div class="settings-form-group">
<label for="confirm_new_password">Confirm New Password</label>
<input type="password" id="confirm_new_password" name="confirm_new_password" required>
</div>
<button type="submit" class="btn primary-btn">Change Password</button>
</form>
</div>
<div class="section-card theme-settings mt-4">
<h3 class="section-title">Theme Settings</h3>
<p class="section-description">Choose your preferred application theme.</p>
<div class="settings-form-group">
<label for="theme_select">Select Theme:</label>
<select id="theme_select" class="form-input" onchange="setTheme(this.value)">
<option value="light" {% if user.theme == 'light' %}selected{% endif %}>Light</option>
<option value="dark" {% if user.theme == 'dark' %}selected{% endif %}>Dark</option>
</select>
</div>
</div>
<div class="section-card danger-zone mt-4">
<h3 class="section-title">Danger Zone</h3>
<p class="section-description">Proceed with caution. These actions are irreversible.</p>
<form action="{{ url_for('auth.delete_account') }}" method="POST" onsubmit="return confirm('Are you sure you want to delete your account? This action cannot be undone.');">
<button type="submit" class="btn btn-danger">Delete My Account</button>
</form>
</div>
<p class="mt-4"><a href="{{ url_for('auth.dashboard') }}" class="btn secondary-btn">← Back to Dashboard</a></p>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
// Theme toggle (specific to dashboard header) - duplicated for consistency across pages
const themeToggleDashboard = document.getElementById('themeToggleDashboard');
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
themeToggleDashboard.textContent = theme === 'dark' ? '☀️' : '🌙';
// Also update the select dropdown if it exists
const themeSelect = document.getElementById('theme_select');
if (themeSelect) {
themeSelect.value = theme;
}
}
const savedTheme = localStorage.getItem('theme');
setTheme(savedTheme || (prefersDark ? 'dark' : 'light'));
themeToggleDashboard.onclick = () => {
const current = document.documentElement.getAttribute('data-theme');
setTheme(current === 'dark' ? 'light' : 'dark');
};
// Sidebar toggle for mobile - duplicated for consistency across pages
const hamburgerDashboard = document.getElementById('hamburgerDashboard');
const sidebar = document.getElementById('sidebar');
const mainContentArea = document.getElementById('mainContentArea');
const closeSidebarBtn = document.getElementById('closeSidebar');
hamburgerDashboard.onclick = () => {
sidebar.classList.add('open');
mainContentArea.classList.add('shifted');
};
closeSidebarBtn.onclick = () => {
sidebar.classList.remove('open');
mainContentArea.classList.remove('shifted');
};
mainContentArea.onclick = (event) => {
if (sidebar.classList.contains('open') && !sidebar.contains(event.target) && !hamburgerDashboard.contains(event.target)) {
sidebar.classList.remove('open');
mainContentArea.classList.remove('shifted');
}
};
Array.from(sidebar.getElementsByClassName('nav-item')).forEach(item => {
item.onclick = () => {
if (window.innerWidth <= 900) {
sidebar.classList.remove('open');
mainContentArea.classList.remove('shifted');
}
};
});
</script>
{% endblock %}