2026-07-22 16:37:53 +02:00
|
|
|
{% extends "base.html" %} {% block title %}Gestion des utilisateurs - Bolsa{%
|
|
|
|
|
endblock %} {% block header_title %}Gestion utilisateurs{% endblock %} {% block
|
|
|
|
|
content %}
|
|
|
|
|
<div class="flex flex-col items-center justify-center py-6">
|
|
|
|
|
<!-- Box centrée principale -->
|
|
|
|
|
<div
|
2026-07-22 17:54:47 +02:00
|
|
|
class="bg-gray-900 border border-gray-800 p-8 rounded-2xl shadow-2xl w-full max-w-6xl"
|
2026-07-22 16:37:53 +02:00
|
|
|
>
|
|
|
|
|
<!-- En-tête de section -->
|
|
|
|
|
<div
|
|
|
|
|
class="flex justify-between items-center mb-6 border-b border-gray-800 pb-4"
|
|
|
|
|
>
|
|
|
|
|
<div>
|
|
|
|
|
<h2 class="text-2xl font-extrabold text-white">
|
|
|
|
|
Administration des utilisateurs
|
|
|
|
|
</h2>
|
|
|
|
|
<p class="text-gray-400 text-sm">
|
|
|
|
|
Gérez les accès et les comptes autorisés de l'application.
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<a
|
|
|
|
|
href="{{ url_for('main.menu') }}"
|
|
|
|
|
class="px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-200 text-sm font-medium rounded-lg transition duration-200"
|
|
|
|
|
>
|
|
|
|
|
Retour au menu
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-07-22 17:54:47 +02:00
|
|
|
<!-- Grille principale : Gauche (Liste) / Droite (Formulaire) -->
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-12 gap-8 py-4">
|
|
|
|
|
<!-- COLONNE GAUCHE : Liste des utilisateurs réels de la BDD -->
|
|
|
|
|
<div
|
|
|
|
|
class="md:col-span-4 bg-gray-950 border border-gray-800 rounded-xl p-4 flex flex-col h-[520px]"
|
|
|
|
|
>
|
|
|
|
|
<h3
|
|
|
|
|
class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3 px-2"
|
|
|
|
|
>
|
|
|
|
|
Utilisateurs enregistrés
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<!-- Liste scrollable -->
|
|
|
|
|
<div class="overflow-y-auto flex-1 space-y-1 pr-1">
|
|
|
|
|
{% for u in users %}
|
|
|
|
|
<div
|
|
|
|
|
onclick="selectionnerUtilisateur('{{ u.id }}', '{{ u.actif }}', '{{ u.prenom }}', '{{ u.nom }}', '{{ u.login }}', '{{ u.mail }}')"
|
|
|
|
|
class="user-item cursor-pointer px-3 py-2.5 rounded-lg {% if loop.first %}bg-blue-600 text-white{% else %}hover:bg-gray-800 text-gray-300{% endif %} font-medium text-sm transition flex justify-between items-center"
|
|
|
|
|
data-id="{{ u.id }}"
|
|
|
|
|
>
|
|
|
|
|
<span>{{ u.prenom }} {{ u.nom }}</span>
|
|
|
|
|
<span
|
|
|
|
|
class="text-xs {% if loop.first %}bg-blue-800{% else %}bg-gray-800 text-gray-400{% endif %} px-2 py-0.5 rounded"
|
|
|
|
|
>ID: {{ u.id }}</span
|
|
|
|
|
>
|
|
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- COLONNE DROITE : Formulaire des détails -->
|
|
|
|
|
<div
|
|
|
|
|
class="md:col-span-8 bg-gray-950 border border-gray-800 rounded-xl p-6 flex flex-col justify-between"
|
|
|
|
|
>
|
|
|
|
|
<form
|
|
|
|
|
id="user-form"
|
|
|
|
|
method="POST"
|
|
|
|
|
action=""
|
|
|
|
|
class="space-y-4 flex-1 flex flex-col justify-between"
|
|
|
|
|
>
|
|
|
|
|
<div class="space-y-4">
|
|
|
|
|
<h3
|
|
|
|
|
class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-2"
|
|
|
|
|
>
|
|
|
|
|
Détails du compte
|
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
|
|
|
<!-- ID (Lecture seule) -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>ID (Lecture seule)</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
id="field-id"
|
|
|
|
|
name="id"
|
|
|
|
|
readonly
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-gray-400 text-sm cursor-not-allowed"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Actif / Statut -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>Actif (1 = Oui, 0 = Non)</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
id="field-actif"
|
|
|
|
|
name="actif"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
|
|
|
<!-- Prénom -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>Prénom</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
id="field-prenom"
|
|
|
|
|
name="prenom"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Nom -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>Nom</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
id="field-nom"
|
|
|
|
|
name="nom"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="grid grid-cols-2 gap-4">
|
|
|
|
|
<!-- Login -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>Login</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
id="field-login"
|
|
|
|
|
name="login"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Mail -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>E-mail</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="email"
|
|
|
|
|
id="field-mail"
|
|
|
|
|
name="mail"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<!-- Mot de passe -->
|
|
|
|
|
<div>
|
|
|
|
|
<label class="block text-xs font-medium text-gray-400 mb-1"
|
|
|
|
|
>Nouveau mot de passe (laisser vide pour ne pas
|
|
|
|
|
changer)</label
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="password"
|
|
|
|
|
id="field-pass"
|
|
|
|
|
name="pass"
|
|
|
|
|
placeholder="••••••••"
|
|
|
|
|
class="w-full bg-gray-900 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Bas : Trois boutons (Créer, Modifier, Annuler) -->
|
|
|
|
|
<div
|
|
|
|
|
class="flex items-center justify-end space-x-3 pt-6 border-t border-gray-800 mt-6"
|
|
|
|
|
>
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onclick="annulerAction()"
|
|
|
|
|
class="px-4 py-2 bg-gray-800 hover:bg-gray-700 text-gray-300 text-sm font-medium rounded-lg transition duration-200"
|
|
|
|
|
>
|
|
|
|
|
Annuler
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
type="submit"
|
|
|
|
|
name="action"
|
|
|
|
|
value="creer"
|
|
|
|
|
class="px-4 py-2 bg-emerald-600 hover:bg-emerald-500 text-white text-sm font-medium rounded-lg transition duration-200"
|
|
|
|
|
>
|
|
|
|
|
Créer
|
|
|
|
|
</button>
|
|
|
|
|
<button
|
|
|
|
|
type="submit"
|
|
|
|
|
name="action"
|
|
|
|
|
value="modifier"
|
|
|
|
|
class="px-4 py-2 bg-blue-600 hover:bg-blue-500 text-white text-sm font-medium rounded-lg transition duration-200"
|
|
|
|
|
>
|
|
|
|
|
Modifier
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</form>
|
|
|
|
|
</div>
|
2026-07-22 16:37:53 +02:00
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Pied de page interne -->
|
|
|
|
|
<div
|
|
|
|
|
class="border-t border-gray-800 pt-4 text-xs text-gray-400 italic text-center"
|
|
|
|
|
>
|
|
|
|
|
Positions en bourse : Accès sécurisé. Veillez à fermer votre session après
|
|
|
|
|
chaque utilisation.
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-07-22 17:54:47 +02:00
|
|
|
|
|
|
|
|
<!-- Script de gestion de la sélection et du premier utilisateur par défaut -->
|
|
|
|
|
<!-- Script de gestion de la sélection -->
|
|
|
|
|
<script>
|
|
|
|
|
function selectionnerUtilisateur(id, actif, prenom, nom, login, mail) {
|
|
|
|
|
document.getElementById("field-id").value = id;
|
|
|
|
|
document.getElementById("field-actif").value = actif;
|
|
|
|
|
document.getElementById("field-prenom").value = prenom;
|
|
|
|
|
document.getElementById("field-nom").value = nom;
|
|
|
|
|
document.getElementById("field-login").value = login;
|
|
|
|
|
document.getElementById("field-mail").value = mail;
|
|
|
|
|
document.getElementById("field-pass").value = "";
|
|
|
|
|
|
|
|
|
|
document.querySelectorAll(".user-item").forEach((el) => {
|
|
|
|
|
el.classList.remove("bg-blue-600", "text-white");
|
|
|
|
|
el.classList.add("hover:bg-gray-800", "text-gray-300");
|
|
|
|
|
const badge = el.querySelector("span:last-child");
|
|
|
|
|
if (badge) {
|
|
|
|
|
badge.classList.remove("bg-blue-800");
|
|
|
|
|
badge.classList.add("bg-gray-800", "text-gray-400");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const selectedEl = document.querySelector(`[data-id="${id}"]`);
|
|
|
|
|
if (selectedEl) {
|
|
|
|
|
selectedEl.classList.remove("hover:bg-gray-800", "text-gray-300");
|
|
|
|
|
selectedEl.classList.add("bg-blue-600", "text-white");
|
|
|
|
|
const badge = selectedEl.querySelector("span:last-child");
|
|
|
|
|
if (badge) {
|
|
|
|
|
badge.classList.remove("bg-gray-800", "text-gray-400");
|
|
|
|
|
badge.classList.add("bg-blue-800");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function annulerAction() {
|
|
|
|
|
// Sélectionne le tout premier élément de la liste s'il existe
|
|
|
|
|
const premierUser = document.querySelector(".user-item");
|
|
|
|
|
if (premierUser) {
|
|
|
|
|
premierUser.click();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sélectionner automatiquement le premier utilisateur au chargement de la page
|
|
|
|
|
window.addEventListener("DOMContentLoaded", () => {
|
|
|
|
|
const premierUser = document.querySelector(".user-item");
|
|
|
|
|
if (premierUser) {
|
|
|
|
|
premierUser.click();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
2026-07-22 16:37:53 +02:00
|
|
|
{% endblock %}
|