Spaces:
Runtime error
Runtime error
File size: 12,412 Bytes
4b63522 f472dc2 9e1a061 f472dc2 4b63522 f472dc2 e366cf8 f472dc2 4ea3acc f472dc2 9e1a061 f472dc2 8be9313 f472dc2 4b63522 f472dc2 4b63522 f472dc2 4b63522 f472dc2 4b63522 f472dc2 4b63522 f472dc2 9e1a061 f472dc2 9e1a061 c785583 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 4b63522 f472dc2 9e1a061 f472dc2 9e1a061 f472dc2 9e1a061 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | {% 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 %}
|