AI-Resume-Ranker-API / app /templates /dashboard.html
webcodelab's picture
Update app/templates/dashboard.html
c785583 verified
Raw
History Blame Contribute Delete
12.4 kB
{% extends "base.html" %}
{% block title %}Dashboard – Resume Ranker API{% endblock %}
{% block extra_head %}
{#
Ensure your main dashboard CSS is linked, likely in base.html now.
If you split it out, link it here:
<link rel="stylesheet" href="{{ url_for('static', filename='css/dashboard.css') }}">
#}
{% 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">
<a href="{{ url_for('auth.dashboard') }}" class="nav-item active">
<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">
<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="#" 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-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"> {# Updated link for "Try It Now" #}
<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> {# Updated text for "Try It Now" #}
</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.settings') }}" 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-settings"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l-.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
<span>Settings</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">Welcome, {{ user.username }}!</h1>
<p class="subtitle">Here's an overview of your ResumeRanker API activity.</p>
{% if error %}
<div class="error-message">{{ error }}</div>
{% endif %}
{% if success %}
<div class="success-message">{{ success }}</div>
{% endif %}
<div class="analytics-grid">
<div class="analytics-card">
<p class="card-label">Average Score</p>
<h2 class="card-value">{{ analytics.average_score | default('N/A') }}</h2>
</div>
<div class="analytics-card">
<p class="card-label">Top Resume</p>
<h2 class="card-value">{{ analytics.top_resume | default('N/A') }}</h2>
</div>
<div class="analytics-card">
<p class="card-label">Last Upload</p>
<h2 class="card-value">{{ analytics.last_upload_date | default('N/A') }}</h2>
</div>
</div>
<div class="section-card api-key-summary">
<h3 class="section-title">Your API Key</h3>
<p class="section-description">
{% if user.api_key %}
API Key: <span class="api-key-display">{{ user.api_key[:8] }}...</span>
<a href="{{ url_for('auth.api_keys') }}" class="link-small">View Full Key & Manage</a>
{% else %}
<span class="no-api-key">No API key generated yet.</span>
<form method="POST" action="{{ url_for('auth.generate_initial_api_key') }}" style="display: inline;">
<button type="submit" class="link-small" style="background: none; border: none; color: #007BFF; text-decoration: underline; cursor: pointer;">Generate API Key</button>
</form>
{% endif %}
</p>
</div>
<div class="section-card recent-uploads-summary">
<h3 class="section-title">Recent Uploads</h3>
{% if recent_uploads %}
<div class="table-responsive-summary">
<table class="data-table">
<thead>
<tr>
<th>Resume Name</th>
<th>Score</th>
</tr>
</thead>
<tbody>
{% for resume in recent_uploads[:3] %} {# Show only top 3 recent uploads #}
<tr>
<td data-label="Resume Name">{{ resume.name }}</td>
<td data-label="Score">{{ resume.score }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p class="section-description text-center">
<a href="{{ url_for('auth.resume_rankings') }}" class="link-small">View All Rankings</a>
</p>
{% else %}
<p class="no-data-message">No recent uploads yet. <a href="{{ url_for('auth.try_api') }}">Try it now!</a></p>
{% endif %}
</div>
<div class="section-card try-it-now-summary">
<h3 class="section-title">Try It Now</h3>
<p class="section-description">Quickly test the ResumeRanker API with your own data.</p>
<div class="text-center">
<a href="{{ url_for('auth.try_api') }}" class="btn primary-btn">Go to API Tester</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script>
// Theme toggle (specific to dashboard header)
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' ? '☀️' : '🌙';
}
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
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');
};
// Close sidebar if click outside on mobile
mainContentArea.onclick = (event) => {
// Check if sidebar is open and click is outside sidebar and not on hamburger
if (sidebar.classList.contains('open') && !sidebar.contains(event.target) && !hamburgerDashboard.contains(event.target)) {
sidebar.classList.remove('open');
mainContentArea.classList.remove('shifted');
}
};
// Close sidebar when clicking a nav item on mobile
Array.from(sidebar.getElementsByClassName('nav-item')).forEach(item => {
item.onclick = () => {
if (window.innerWidth <= 900) { // Assuming 900px is your mobile breakpoint
sidebar.classList.remove('open');
mainContentArea.classList.remove('shifted');
}
};
});
// Remove any previous API Key Copy or Drag and Drop scripts from the main dashboard.html
// These will now be on their dedicated pages.
</script>
{% endblock %}