Implémente système multi-utilisateurs avec classement
- Auth cookie simple (SSO-ready) : login/logout, redirection si non authentifié
- Données isolées par utilisateur dans /data/users/{user_id}/
- Migration automatique des données legacy au premier login
- Page classement avec podium et tableau comparatif (score, précision zéro, conformité)
- Nav mise à jour : Classement, affichage utilisateur courant, déconnexion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
109
app/templates/login.html
Normal file
109
app/templates/login.html
Normal file
@ -0,0 +1,109 @@
|
||||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<div class="login-wrap">
|
||||
<div class="login-card">
|
||||
<div class="login-header">
|
||||
<span class="login-eyebrow">Décompte Horaire</span>
|
||||
<h1 class="login-title">Connexion</h1>
|
||||
</div>
|
||||
|
||||
{% if error %}
|
||||
<div class="login-error">{{ error }}</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/login" class="login-form">
|
||||
<label class="login-label" for="username">Identifiant</label>
|
||||
<input
|
||||
id="username"
|
||||
class="login-input"
|
||||
type="text"
|
||||
name="username"
|
||||
autocomplete="username"
|
||||
autofocus
|
||||
placeholder="prenom.nom"
|
||||
pattern="[a-zA-Z0-9_\-]{1,32}"
|
||||
required
|
||||
>
|
||||
<p class="login-hint">Lettres, chiffres, tirets — 1 à 32 caractères.</p>
|
||||
<button class="login-btn" type="submit">Entrer</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.login-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
padding-top: 4rem;
|
||||
}
|
||||
.login-card {
|
||||
background: var(--surface);
|
||||
border: 1.5px solid var(--rule);
|
||||
padding: 2.5rem 3rem;
|
||||
width: 380px;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
.login-header { display: flex; flex-direction: column; gap: .35rem; }
|
||||
.login-eyebrow {
|
||||
font-family: var(--mono);
|
||||
font-size: 10px;
|
||||
letter-spacing: .12em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
.login-title {
|
||||
font-family: var(--mono);
|
||||
font-size: 22px;
|
||||
font-weight: 500;
|
||||
color: var(--text);
|
||||
letter-spacing: -.01em;
|
||||
}
|
||||
.login-error {
|
||||
background: var(--neg-bg);
|
||||
border-left: 3px solid var(--neg);
|
||||
color: var(--neg);
|
||||
font-size: 12px;
|
||||
padding: .6rem .9rem;
|
||||
font-family: var(--mono);
|
||||
}
|
||||
.login-form { display: flex; flex-direction: column; gap: .75rem; }
|
||||
.login-label {
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .06em;
|
||||
text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
.login-input {
|
||||
font-family: var(--mono);
|
||||
font-size: 15px;
|
||||
padding: .6rem .75rem;
|
||||
border: 1.5px solid var(--rule);
|
||||
background: var(--ground);
|
||||
color: var(--text);
|
||||
outline: none;
|
||||
transition: border-color .15s;
|
||||
}
|
||||
.login-input:focus { border-color: var(--accent); }
|
||||
.login-hint { font-size: 11px; color: var(--muted); }
|
||||
.login-btn {
|
||||
margin-top: .5rem;
|
||||
font-family: var(--mono);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
letter-spacing: .08em;
|
||||
text-transform: uppercase;
|
||||
padding: .7rem 1.5rem;
|
||||
background: var(--text);
|
||||
color: var(--surface);
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: background .15s;
|
||||
}
|
||||
.login-btn:hover { background: var(--accent); }
|
||||
</style>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user