Files
pointeuse-optimisator/app/templates/settings.html
Antoine c2d7d0e3ac Rend les plages horaires et les rappels ntfy configurables, supprime le
classement, ajoute une suite de tests pytest

- calcul.py: matin_debut/fin, aprem_debut/fin et pause_dejeuner_fin sont
  paramétrables via config.json > plages (moteur de calcul de l'heure de
  sortie optimale inclus, pas seulement l'affichage). Défauts identiques
  à l'ancien comportement, validé par la suite de tests.
- stats.py: les seuils de conformité utilisent la même config.
- main.py/templates: warn de saisie et suffixes de cible dynamiques.
- Rappels ntfy: serveur, topic et plage horaire (rappel_debut_h/fin_h)
  configurables par utilisateur depuis /settings, plus en dur dans le code.
- Page classement supprimée (pas de compétition entre utilisateurs).
- Nouvelle suite pytest (app/tests/), à lancer via
  `docker compose run --rm pointeuse pytest -v`.
2026-07-17 22:40:55 +02:00

130 lines
4.2 KiB
HTML

{% extends "base.html" %}
{% block content %}
<div class="stats-head">
<div>
<span class="stats-title">Réglages</span>
<div class="stats-meta">Rappels de pointage sur ton téléphone</div>
</div>
</div>
<div class="settings-card">
<span class="hist-label">Notifications (ntfy)</span>
<p class="settings-p">
Crée un topic sur ton serveur <a href="https://ntfy.sh" target="_blank" rel="noopener">ntfy</a>
(public ou auto-hébergé), un identifiant secret que toi seul connais, abonne-toi dessus avec
l'app ntfy sur ton téléphone, puis renseigne les deux champs ci-dessous.
</p>
{% if saved %}
<div class="settings-saved">Enregistré.</div>
{% endif %}
<form method="post" action="/settings" class="settings-form">
<label class="login-label" for="ntfy_server">Serveur ntfy</label>
<input
id="ntfy_server"
class="login-input"
type="text"
name="ntfy_server"
value="{{ ntfy_server }}"
placeholder="https://ntfy.sh"
autocomplete="off"
>
<label class="login-label" for="ntfy_topic">Topic ntfy</label>
<input
id="ntfy_topic"
class="login-input"
type="text"
name="ntfy_topic"
value="{{ ntfy_topic }}"
placeholder="ex: antoine-pointeuse-x7f2"
autocomplete="off"
>
<label class="login-label" for="rappel_debut_h">Plage horaire des rappels</label>
<div class="settings-range">
<input
id="rappel_debut_h"
class="login-input settings-range-input"
type="number" min="0" max="23" name="rappel_debut_h"
value="{{ rappel_debut_h }}"
>
<span class="settings-range-sep">h → </span>
<input
id="rappel_fin_h"
class="login-input settings-range-input"
type="number" min="1" max="24" name="rappel_fin_h"
value="{{ rappel_fin_h }}"
>
<span class="settings-range-sep">h, jours ouvrés</span>
</div>
<button class="login-btn" type="submit">Enregistrer</button>
</form>
</div>
<div class="settings-card">
<span class="hist-label">Détection de présence (Tasker)</span>
<p class="settings-p">
Crée une automatisation Tasker déclenchée par une géofence autour du bureau : à l'<b>entrée</b> de la
zone, appelle l'URL "arrivée" ; à la <b>sortie</b>, l'URL "départ". Tant que tu es détecté présent sans
avoir pointé l'entrée du matin, ou parti sans avoir pointé la sortie, tu reçois un rappel toutes les
5 minutes, dans la plage horaire réglée ci-dessus (jours ouvrés).
</p>
<div class="settings-urlrow">
<span class="settings-urllabel">Arrivée</span>
<code class="settings-url">{{ arrivee_url }}</code>
</div>
<div class="settings-urlrow">
<span class="settings-urllabel">Départ</span>
<code class="settings-url">{{ depart_url }}</code>
</div>
<p class="settings-hint">
Ces URLs sont secrètes (elles contiennent ton token) — ne les partage pas.
</p>
</div>
<style>
.settings-card {
background: var(--surface);
border: 1.5px solid var(--rule);
padding: 1.25rem 1.5rem;
display: flex;
flex-direction: column;
gap: .75rem;
}
.settings-p { font-size: 13px; color: var(--text); line-height: 1.6; }
.settings-p a { color: var(--accent); }
.settings-form { display: flex; flex-direction: column; gap: .5rem; max-width: 420px; }
.settings-saved {
background: var(--pos-bg);
border-left: 3px solid var(--pos);
color: var(--pos);
font-size: 12px;
padding: .5rem .8rem;
font-family: var(--mono);
}
.settings-urlrow { display: flex; align-items: center; gap: .75rem; flex-wrap: wrap; }
.settings-urllabel {
font-family: var(--mono);
font-size: 10px;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--muted);
width: 70px;
flex-shrink: 0;
}
.settings-url {
font-family: var(--mono);
font-size: 12px;
color: var(--text);
background: var(--ground);
border: 1px solid var(--rule);
padding: .4rem .6rem;
word-break: break-all;
}
.settings-hint { font-size: 11px; color: var(--muted); }
.settings-range { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.settings-range-input { width: 70px; text-align: center; }
.settings-range-sep { font-size: 12px; color: var(--muted); font-family: var(--mono); }
</style>
{% endblock %}