Bug : Affichage des demandes de conges
This commit is contained in:
16
SIRH/asgi.py
16
SIRH/asgi.py
@@ -1,16 +0,0 @@
|
||||
"""
|
||||
ASGI config for SIRH project.
|
||||
|
||||
It exposes the ASGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.2/howto/deployment/asgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SIRH.settings')
|
||||
|
||||
application = get_asgi_application()
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 58 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 180 KiB |
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 131 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 85 KiB |
@@ -1,157 +0,0 @@
|
||||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PRINCICALA</title>
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'icons.css' %}">
|
||||
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<style>
|
||||
.bg-orange-dark {
|
||||
background: linear-gradient(90deg, #993d00, #b34700); /* oranges plus sombres */
|
||||
color: white;
|
||||
}
|
||||
.sidebar .nav-link {
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
}
|
||||
.sidebar .nav-link:hover {
|
||||
background-color: rgba(255,255,255,0.2);
|
||||
border-radius: 5px;
|
||||
}
|
||||
.logo {
|
||||
max-width: 90px;
|
||||
|
||||
}
|
||||
main {
|
||||
margin-left: 220px;
|
||||
}
|
||||
.stat-card {
|
||||
background: rgb(255, 255, 255);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 2px 5px rgba(113, 11, 11, 0.1);
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row flex-nowrap">
|
||||
|
||||
<nav class="col-12 col-md-3 col-lg-2 sidebar p-3">
|
||||
<div class="text-center mb-4">
|
||||
<img src="{% static 'CERFIF.jpg' %}" alt="Logo" class="logo mb-5">
|
||||
<h4 class="text-white">CERFIG</h4>
|
||||
</div>
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item mb-2">
|
||||
<a href="/" class="nav-link"><i class="bi bi-speedometer2"></i> Tableau de bord</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class=" bi bi-airplane"></i> Demande de congé </a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class="bi bi-people"></i> Gestion des Employés</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class="bi bi-folder"></i> Gestion des Projets</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class="bi bi-airplane"></i> Gestion des Congés</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class="bi bi-graph-up"></i>Rapports et Statistiques</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="#" class="nav-link"><i class="bi bi-gear"></i> Paramètres</a>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="nav-link"><i class="bi bi-box-arrow-right"></i> Déconnexion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Contenu principal -->
|
||||
<main class="col px-4 py-4">
|
||||
<h1 class="mb-4">Bienvenue sur le tableau de bord</h1>
|
||||
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<h5><i class="bi bi-airplane"></i> Congés en attente</h5>
|
||||
|
||||
<p class="display-6 fw-bold"> {{ nombre_conges_attente }}</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<h5><i class="bi bi-people"></i> Nombre Employés </h5>
|
||||
<p class="display-6 fw-bold">{{ nombre_employes }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="stat-card">
|
||||
<h5><i class="bi bi-kanban"></i> Projets en cours</h5>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card p-3">
|
||||
<h3>
|
||||
<i class="bi bi-people"></i> La liste des employés en congé</h3>
|
||||
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Employé</th>
|
||||
<th>Type de congé</th>
|
||||
<th>Date de début</th>
|
||||
<th>Date de fin</th>
|
||||
<th>Statut</th>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{% for employe in personnes_en_conge %}
|
||||
<tr>
|
||||
<td>{{ employe.nom }} {{ employe.prenom }}</td>
|
||||
<td>{{ employe.type }}</td>
|
||||
<td>{{ employe.date_debut }}</td>
|
||||
<td>{{ employe.date_fin }}</td>
|
||||
<td>
|
||||
<span class="badge bg-success">{{ employe.statut }} </span>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="5" class="text-center">Personne en conge </td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,197 +0,0 @@
|
||||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Connexion SI-RH</title>
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
</head>
|
||||
|
||||
|
||||
<body class="d-flex justify-content-center align-items-center min-vh-100 ">
|
||||
|
||||
<style>
|
||||
.bg-orange-dark {
|
||||
background: linear-gradient(90deg, #b35400, #cc6600);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
<!-- Formulaire de connexion -->
|
||||
<div class="p-4 shadow-sm rounded bg-white" style="max-width: 400px; margin: auto;">
|
||||
<img src="{% static 'CERFIF.jpg' %}" alt="Logo" class="logo mb-3"
|
||||
style="display: block; margin-left: auto; margin-right: auto; width: 60%; max-width: 500px; height: auto;">
|
||||
|
||||
|
||||
|
||||
{% if messages %}
|
||||
<!-- Modal message -->
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark
|
||||
{% if messages.0.tags == 'error' %}bg-orange-dark text-white
|
||||
{% elif messages.0.tags == 'success' %}bg-orange-dark text-white
|
||||
{% else %}bg-orange-dark text-white{% endif %}">
|
||||
<h5 class="modal-title" id="messageModalLabel">
|
||||
{% if messages.0.tags == 'error' %}Erreur
|
||||
{% elif messages.0.tags == 'success' %}Succès
|
||||
{% else %}Information{% endif %}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% for message in messages %}
|
||||
<p>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var messageModal = new bootstrap.Modal(document.getElementById('messageModal'));
|
||||
messageModal.show();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
<form method="POST" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="username">Nom d’utilisateur</label>
|
||||
<input type="text" name="username" class="form-control" placeholder="Entrez votre nom d’utilisateur" required>
|
||||
</div>
|
||||
<div class="mb-3 position-relative">
|
||||
<label for="password">Mot de passe</label>
|
||||
<input type="password" name="password" class="form-control" placeholder="Entrez votre mot de passe" required>
|
||||
<i class="bi bi-eye toggle-password" onclick="togglePassword()"
|
||||
style="position:absolute; right:10px; top:38px; cursor:pointer;"></i>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Se connecter</button>
|
||||
</form>
|
||||
|
||||
<p class="mt-3 text-center">
|
||||
<a href="#" data-bs-toggle="modal" data-bs-target="#resetPasswordModal">Mot de passe oublié ?</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Modale de réinitialisation -->
|
||||
<div class="modal fade" id="resetPasswordModal" tabindex="-1" aria-labelledby="resetPasswordModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content p-4">
|
||||
<h5 class="modal-title mb-3" id="resetPasswordModalLabel">Réinitialisation du mot de passe</h5>
|
||||
<form id="resetPasswordForm">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="email">Entrez votre email</label>
|
||||
<input type="email" name="email" class="form-control" placeholder="Email" required>
|
||||
</div>
|
||||
<div id="resetMessage" class="mb-3"></div>
|
||||
<button type="submit" class="btn btn-warning w-100">Envoyer le lien</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if show_politique_modal %}
|
||||
<!-- Modal Politique d'utilisation -->
|
||||
<div class="modal fade" id="politiqueModal" tabindex="-1" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">Politique d'utilisation de SI-RH</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Veuillez lire et accepter notre politique d'utilisation avant d'accéder à votre compte.</p>
|
||||
<h6>Confidentialité des données</h6>
|
||||
<p>Vos informations personnelles et professionnelles sont protégées. Toute divulgation non autorisée est strictement interdite.</p>
|
||||
<h6>Utilisation autorisée</h6>
|
||||
<p>L’application est réservée à un usage professionnel. Toute utilisation à des fins personnelles ou non autorisées est prohibée.</p>
|
||||
<h6>Sécurité des comptes</h6>
|
||||
<p>Ne partagez jamais vos identifiants. Changez votre mot de passe régulièrement et en cas de suspicion d’intrusion.</p>
|
||||
<h6>Responsabilités de l’utilisateur</h6>
|
||||
<p>Vous êtes responsable des actions effectuées via votre compte. Signalez toute anomalie ou problème à l’équipe RH ou à l’administrateur.</p>
|
||||
<h6>Acceptation et conformité</h6>
|
||||
<p>En cliquant sur <strong>“J’accepte”</strong>, vous confirmez avoir lu et accepté cette politique. Le non-respect peut entraîner une suspension ou une révocation de l’accès.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<form method="POST" action="{% url 'accepter-politique' %}" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-success">J'accepte</button>
|
||||
</form>
|
||||
<form method="POST" action="{% url 'refuser-politique' %}" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-danger">Refuser</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var politiqueModal = new bootstrap.Modal(document.getElementById('politiqueModal'));
|
||||
politiqueModal.show();
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var politiqueModal = new bootstrap.Modal(document.getElementById('politiqueModal'));
|
||||
politiqueModal.show();
|
||||
});
|
||||
</script>
|
||||
>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var modal = new bootstrap.Modal(document.getElementById('politiqueModal'));
|
||||
modal.show();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
|
||||
<script>
|
||||
// Afficher / masquer le mot de passe
|
||||
function togglePassword() {
|
||||
const input = document.querySelector('input[name="password"]');
|
||||
input.type = input.type === 'password' ? 'text' : 'password';
|
||||
}
|
||||
|
||||
// AJAX pour réinitialisation
|
||||
$('#resetPasswordForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
const email = $('input[name="email"]').val();
|
||||
const csrfToken = $('[name=csrfmiddlewaretoken]').val();
|
||||
|
||||
$.ajax({
|
||||
url: "{% url 'password_reset' %}",
|
||||
type: 'POST',
|
||||
data: {
|
||||
'email': email,
|
||||
'csrfmiddlewaretoken': csrfToken
|
||||
},
|
||||
success: function(response) {
|
||||
$('#resetMessage').html('<div class="alert alert-success">Email envoyé ! Vérifiez votre boîte de réception.</div>');
|
||||
},
|
||||
error: function() {
|
||||
$('#resetMessage').html('<div class="alert alert-danger">Erreur lors de l’envoi. Vérifiez l’email.</div>');
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
{% load static %}
|
||||
{% load roles %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PRINCICALA</title>
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- ===================== -->
|
||||
<!-- SIDEBAR RESPONSIVE -->
|
||||
<!-- ===================== -->
|
||||
<nav class="sidebar bg-orange-dark text-white d-none d-md-block col-md-3 col-lg-2 p-3"
|
||||
style="background: linear-gradient(90deg, #993d00, #b34700); position: fixed; height: 100vh; overflow-y: auto;">
|
||||
|
||||
<!-- Profil utilisateur -->
|
||||
<div class="text-center mb-4 d-flex flex-column align-items-center" style="margin-top:20px;">
|
||||
<h6 class="fw-bold text-white mb-2">{{ user.first_name }} {{ user.last_name }}</h6>
|
||||
<a href="{% url 'mon_profil' %}">
|
||||
{% if user.photo %}
|
||||
<img src="{{ user.photo.url }}" alt="Profil"
|
||||
class="rounded-circle img-profil mx-auto"
|
||||
style="width: 80px; height: 80px; object-fit: cover;">
|
||||
{% else %}
|
||||
<div class="rounded-circle bg-secondary d-flex justify-content-center align-items-center"
|
||||
style="width: 80px; height: 80px;">
|
||||
<i class="bi bi-person-circle text-white" style="font-size: 2rem;"></i>
|
||||
</div>
|
||||
{% endif %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Liens du menu -->
|
||||
<ul class="nav flex-column">
|
||||
{% if user|has_role:"Employe" or user|has_role:"Administrateur" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'mon_profil' %}" class="nav-link text-white"><i class="bi bi-person-circle"></i> Mon profil</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'activites-projet' %}" class="nav-link text-white"><i class="bi bi-list-task"></i> Suivi des Activités</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'employe-conge' %}" class="nav-link text-white"><i class="bi bi-airplane"></i> Mes Congés</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'mes_formations' %}" class="nav-link text-white"><i class="bi bi-journal-text"></i> Mes certificats</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'salle' %}" class="nav-link text-white"><i class="bi bi-calendar-check"></i> Réserver une salle</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if user|has_role:"RH" or user|has_role:"Directeur" or user|has_role:"Assistante" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'employe-index' %}" class="nav-link text-white"><i class="bi bi-speedometer2"></i> Tableau de bord</a>
|
||||
</li>
|
||||
{% if user|has_role:"Assistante" or user|has_role:"RH" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'activites-projet' %}" class="nav-link text-white"><i class="bi bi-list-task"></i> Suivi des Activités</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if user|has_role:"Directeur" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'directeur' %}" class="nav-link text-white"><i class="bi bi-graph-up"></i> Suivi des Projets</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'projet-index' %}" class="nav-link text-white"><i class="bi bi-folder"></i> Gestion des Projets</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'conge' %}" class="nav-link text-white"><i class="bi bi-airplane"></i> Congés</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'mes_formations' %}" class="nav-link text-white"><i class="bi bi-journal-text"></i> Mes certificats</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'salle' %}" class="nav-link text-white"><i class="bi bi-calendar-check"></i> Réserver une salle</a>
|
||||
</li>
|
||||
{% if user|has_role:"RH" or user|has_role:"Directeur" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'rapport-rh' %}" class="nav-link text-white"><i class="bi bi-graph-up"></i> Rapports et Statistiques</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'mon_profil' %}" class="nav-link text-white"><i class="bi bi-person-circle"></i> Mon profil</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
{% if user|has_role:"Administrateur" %}
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'gestion-utilisateurs' %}" class="nav-link text-white"><i class="bi bi-person-gear"></i> Gestion des Utilisateurs</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'parametres-rh' %}" class="nav-link text-white"><i class="bi bi-gear"></i> Paramètres</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'deconnexion' %}" class="nav-link text-white"><i class="bi bi-box-arrow-right"></i> Déconnexion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- ===================== -->
|
||||
<!-- MENU MOBILE (offcanvas) -->
|
||||
<!-- ===================== -->
|
||||
<!-- Bouton burger (visible uniquement sur téléphone) -->
|
||||
<nav class="navbar navbar-dark bg-orange-dark d-md-none p-2" style="background: linear-gradient(90deg, #993d00, #b34700);">
|
||||
<button class="btn btn-light" type="button" data-bs-toggle="offcanvas" data-bs-target="#menuMobile">
|
||||
<i class="bi bi-list"></i> Menu
|
||||
</button>
|
||||
</nav>
|
||||
|
||||
<!-- Menu Offcanvas mobile -->
|
||||
<div class="offcanvas offcanvas-start" tabindex="-1" id="menuMobile" style="background: linear-gradient(90deg, #993d00, #b34700); color: white;">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title">{{ user.first_name }} {{ user.last_name }}</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<!-- Tu peux copier ici le même <ul> du menu principal -->
|
||||
<ul class="nav flex-column">
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'mon_profil' %}" class="nav-link text-white"><i class="bi bi-person-circle"></i> Mon profil</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'activites-projet' %}" class="nav-link text-white"><i class="bi bi-list-task"></i> Activités</a>
|
||||
</li>
|
||||
<li class="nav-item mb-2">
|
||||
<a href="{% url 'deconnexion' %}" class="nav-link text-white"><i class="bi bi-box-arrow-right"></i> Déconnexion</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
<div class="alert alert-{{ message.tags }} d-flex align-items-center" role="alert">
|
||||
{% if message.tags == 'success' %}
|
||||
<i class="bi bi-check-circle-fill me-2"></i>
|
||||
{% elif message.tags == 'warning' %}
|
||||
<i class="bi bi-exclamation-triangle-fill me-2"></i>
|
||||
{% elif message.tags == 'error' %}
|
||||
<i class="bi bi-x-circle-fill me-2"></i>
|
||||
{% endif %}
|
||||
{{ message }}
|
||||
</div>
|
||||
@@ -1,384 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Profil utilisateur</title>
|
||||
|
||||
<!-- CSS -->
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
|
||||
<style>
|
||||
.bg-orange-dark {
|
||||
background: linear-gradient(90deg, #993d00, #b34700); /* oranges plus sombres */
|
||||
color: white;
|
||||
}
|
||||
.card-body p { margin-bottom: 0.5rem; }
|
||||
|
||||
.main {
|
||||
margin-left: 0px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row flex-nowrap">
|
||||
<!-- Sidebar -->
|
||||
{% include 'menu_principal.html' %}
|
||||
|
||||
<!-- Main -->
|
||||
<main class="col px-2 py-4" style="margin-left: 280px;">
|
||||
|
||||
{% if messages %}
|
||||
<!-- Modal Message Django -->
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">
|
||||
{% if messages.0.tags == 'error' %}
|
||||
Erreur
|
||||
{% elif messages.0.tags == 'success' %}
|
||||
Succès
|
||||
{% else %}
|
||||
Information
|
||||
{% endif %}
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% for message in messages %}
|
||||
<p>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Icône Notification -->
|
||||
<div class="notification-bell position-fixed top-0 end-0 m-3" data-bs-toggle="modal" data-bs-target="#modalNotifications" style="z-index:1050; cursor:pointer;">
|
||||
<i class="bi bi-bell-fill fs-4"></i>
|
||||
<span class="badge bg-danger">{{ notifications_contrats|length }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Modal Notifications Contrats -->
|
||||
<div class="modal fade" id="modalNotifications" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title"><i class="bi bi-bell me-2"></i>Contrats proches de la fin</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if notifications_contrats %}
|
||||
<ul class="list-group">
|
||||
{% for notif in notifications_contrats %}
|
||||
<h5>Votre Contrat <strong>{{ notif.numero }}</strong> signé le <strong>{{ notif.date }}</strong>
|
||||
se termine dans
|
||||
<span class="badge bg-danger rounded-pill">{{ notif.jours_restants }} jours</span>
|
||||
</h5>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p class="text-muted">Aucun contrat proche de la fin.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Profil -->
|
||||
|
||||
<div class="container py-4">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12 col-md-10 col-lg-8">
|
||||
<div class="card border-0 shadow-sm">
|
||||
|
||||
<div class="card-header bg-light d-flex justify-content-between align-items-center">
|
||||
<h4 class="mb-0 fw-bold">
|
||||
<i class="bi bi-person-circle me-2"></i> Mon Profil
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-3">
|
||||
<!-- Infos personnelles -->
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<p><strong>Nom :</strong> {{ employe.last_name|default:"Non renseigné" }}</p>
|
||||
<p><strong>Prénom :</strong> {{ employe.first_name|default:"Non renseigné" }}</p>
|
||||
<p><strong>Matricule :</strong> {{ employe.matricule|default:"Non renseigné" }}</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p><strong>Département :</strong> {{ employe.departement|default:"Non renseigné" }}</p>
|
||||
<p><strong>Email :</strong> {{ employe.email|default:"Non renseigné" }}</p>
|
||||
<p><strong>Téléphone :</strong> {{ employe.telephone|default:"Non renseigné" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Contrats -->
|
||||
<h5 class="mt-3">Contrats</h5>
|
||||
{% for contrat in contrats %}
|
||||
<div class="mb-3 p-3 border rounded">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<p><strong>Numéro :</strong> {{ contrat.numero_contrat }}</p>
|
||||
<p><strong>Type :</strong> {{ contrat.type_contrat }}</p>
|
||||
<p><strong>Date début :</strong> {{ contrat.date_debut|date:"d/m/Y" }}</p>
|
||||
<p><strong>Date fin :</strong> {{ contrat.date_fin|date:"d/m/Y"|default:"Non précisée" }}</p>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<p><strong>Salaire mensuel :</strong>
|
||||
{% if contrat.salaire_mensuel %}
|
||||
{{ contrat.salaire_mensuel }} GNF
|
||||
{% else %}
|
||||
Non précisé
|
||||
{% endif %}
|
||||
</p>
|
||||
<p><strong>Statut :</strong>
|
||||
<span class="badge
|
||||
{% if contrat.statut_auto == 'Actif' %}bg-success
|
||||
{% elif contrat.statut_auto == 'Terminé' %}bg-danger
|
||||
{% elif contrat.statut_auto == 'Suspendu' %}bg-warning text-dark
|
||||
{% else %}bg-secondary{% endif %}">
|
||||
{{ contrat.statut_auto }}
|
||||
</span>
|
||||
</p>
|
||||
<p><strong>Solde congé :</strong> {{ contrat.solde_conge|default:"Non précisé" }} jours</p>
|
||||
<p><strong>Fichier :</strong>
|
||||
{% if contrat.fichier_contrat %}
|
||||
<a href="{{ contrat.fichier_contrat.url }}" target="_blank">
|
||||
<i class="bi bi-file-earmark-pdf me-1"></i> Télécharger
|
||||
</a>
|
||||
{% else %}
|
||||
<span class="text-muted">Aucun fichier</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p class="text-danger">Aucun contrat trouvé.</p>
|
||||
{% endfor %}
|
||||
|
||||
<!-- Projets -->
|
||||
<h5 class="mt-3">Projets</h5>
|
||||
<ul class="list-group mb-3">
|
||||
{% for a in affectations %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
{{ a.projet.nom_projet }} - {{ a.temps_affectation }}%
|
||||
{% if a.projet.statut %}
|
||||
- <span class="badge bg-info text-dark">{{ a.projet.statut }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
||||
<button type="button" class="btn bg-orange-dark btn-sm text-white"
|
||||
data-bs-toggle="modal" data-bs-target="#modalFicheProjet{{ a.projet.id }}">
|
||||
<i class="bi bi-info-circle"></i> Détails
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-muted text-center">Aucun projet assigné.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="card-footer bg-white d-flex justify-content-end">
|
||||
<button type="button" class="btn btn-outline-secondary me-2" onclick="window.history.back()">Fermer</button>
|
||||
<a href="{% url 'profil' %}" class="btn bg-orange-dark text-white">
|
||||
<i class="bi bi-pencil-square me-1"></i> Renseigner les autres informations
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% for a in affectations %}
|
||||
<!-- Modal Détails Projet -->
|
||||
<div class="modal fade" id="modalFicheProjet{{ a.projet.id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">
|
||||
<i class="bi bi-info-circle me-2"></i>Détails du projet {{ a.projet.nom_projet }}
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<p><strong>Nom :</strong> {{ a.projet.nom_projet }}</p>
|
||||
<p><strong>Numéro convention :</strong> {{ a.projet.numero_convention }}</p>
|
||||
<p><strong>Dates :</strong> {{ a.projet.date_debut|date:"d/m/Y" }} → {{ a.projet.date_fin|date:"d/m/Y" }}</p>
|
||||
<p><strong>Type :</strong> {{ a.projet.get_type_projet_display }}</p>
|
||||
<p><strong>Domaine :</strong> {{ a.projet.get_domaine_recherche_display }}</p>
|
||||
<p><strong>Budget :</strong> {{ a.projet.budget }} GNF</p>
|
||||
<p><strong>Budget RH :</strong> {{ a.projet.budget_RH }} GNF</p>
|
||||
<p><strong>Statut :</strong> <span class="badge bg-info">{{ a.projet.statut }}</span></p>
|
||||
<p><strong>Description :</strong> {{ a.projet.description }}</p>
|
||||
|
||||
<h6 class="mt-4">Employés affectés :</h6>
|
||||
<ul class="list-group mb-3">
|
||||
{% for aff in a.projet.affectations.all %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ aff.employe }} <span class="badge bg-orange-dark">{{ aff.temps_affectation }}%</span>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-muted">Aucun employé affecté</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h6>Bailleurs :</h6>
|
||||
<ul class="list-group mb-3">
|
||||
{% for f in a.projet.financements.all %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ f.bailleur.nom }} <span class="badge bg-success">{{ f.pourcentage }}%</span>
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-muted">Aucun bailleur enregistré</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<h6 class="mt-4">Documents du projet :</h6>
|
||||
<ul class="list-group">
|
||||
{% for doc in a.projet.documents.all %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<div>
|
||||
<strong>{{ doc.get_nom_document_display }}</strong><br>
|
||||
pour le projet {{ a.projet.nom_projet }}<br>
|
||||
{% if doc.description %}
|
||||
<small class="text-muted">{{ doc.description }}</small><br>
|
||||
{% endif %}
|
||||
<small class="text-muted">
|
||||
{% if doc.numero %}
|
||||
{{ doc.numero }}
|
||||
{% endif %}
|
||||
</small>
|
||||
<br> <small></small>
|
||||
document ajouter le {{ doc.date_ajout|date:"d/m/Y" }}</small>
|
||||
{% if doc.date_validite %}
|
||||
<br><small class="text-muted"> et Valide jusqu'au {{ doc.date_validite|date:"d/m/Y" }}</small>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="list-group-item text-muted">Aucun document disponible</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer bg-light">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
|
||||
<i class="bi bi-x-circle me-1"></i> Fermer
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endfor %}
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JS -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
// Ferme les modales ouvertes avant d'en ouvrir une autre
|
||||
const modals = document.querySelectorAll('.modal');
|
||||
modals.forEach(modal => {
|
||||
modal.addEventListener('show.bs.modal', function () {
|
||||
document.querySelectorAll('.modal.show').forEach(openModal => {
|
||||
if (openModal !== modal) {
|
||||
const instance = bootstrap.Modal.getInstance(openModal);
|
||||
if (instance) instance.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Répare le bug d'écran figé après fermeture
|
||||
document.addEventListener('hidden.bs.modal', function () {
|
||||
if (!document.querySelector('.modal.show')) {
|
||||
document.body.classList.remove('modal-open');
|
||||
document.body.style.removeProperty('padding-right');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
const forms = document.querySelectorAll('form[action*="ajouter-document"]');
|
||||
forms.forEach(form => {
|
||||
form.addEventListener('submit', function (e) {
|
||||
const btn = form.querySelector('button[type="submit"]');
|
||||
const modalEl = form.closest('.modal');
|
||||
if (btn) {
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="bi bi-hourglass-split"></i> Enregistrement...';
|
||||
}
|
||||
if (modalEl) {
|
||||
const modalInstance = bootstrap.Modal.getInstance(modalEl);
|
||||
if (modalInstance) modalInstance.hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const messageModalEl = document.getElementById('messageModal');
|
||||
if (messageModalEl) {
|
||||
const messageModal = new bootstrap.Modal(messageModalEl);
|
||||
messageModal.show();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Paramètres RH</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<style>
|
||||
.bg-orange-dark {
|
||||
background: linear-gradient(90deg, #993d00, #b34700);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row flex-nowrap">
|
||||
<!-- Sidebar -->
|
||||
{% include 'menu_principal.html' %}
|
||||
|
||||
<!-- Main -->
|
||||
<main class="col px-2 py-4" style="margin-left: 280px;">
|
||||
|
||||
|
||||
{% if messages %}
|
||||
<!-- Modal message -->
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark
|
||||
{% if messages.0.tags == 'error' %}bg-orange-dark text-white
|
||||
{% elif messages.0.tags == 'success' %}bg-orange-dark text-white
|
||||
{% else %}bg-orange-dark text-white{% endif %}">
|
||||
<h5 class="modal-title" id="messageModalLabel">
|
||||
{% if messages.0.tags == 'error' %}Erreur
|
||||
{% elif messages.0.tags == 'success' %}Succès
|
||||
{% else %}Information{% endif %}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% for message in messages %}
|
||||
<p>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var messageModal = new bootstrap.Modal(document.getElementById('messageModal'));
|
||||
messageModal.show();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
<h2 class="mb-4"><i class="bi bi-gear-fill"></i> Paramètres Administration</h2>
|
||||
|
||||
<div class="row">
|
||||
<!-- Colonne Départements -->
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h5><i class="bi bi-building"></i> Départements</h5>
|
||||
<button class="btn bg-orange-dark btn-sm" data-bs-toggle="modal" data-bs-target="#modalAjouterDepartement">
|
||||
<i class="bi bi-plus-circle"></i> Ajouter
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Modal Ajout -->
|
||||
<div class="modal fade" id="modalAjouterDepartement" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="ajouter_departement" value="1">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">Ajouter un département</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ form_departement.as_p }}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn bg-orange-dark">Enregistrer</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Liste des départements -->
|
||||
<ul class="list-group">
|
||||
{% for d in departements %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ d.nom }}
|
||||
<div>
|
||||
<!-- Bouton détails -->
|
||||
<button class="btn btn-sm btn-outline-info" data-bs-toggle="modal" data-bs-target="#modalDetailDepartement{{ d.id }}">
|
||||
<i class="bi bi-eye"></i> Détails
|
||||
</button>
|
||||
|
||||
<!-- Bouton modification -->
|
||||
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" data-bs-target="#modalModifierDepartement{{ d.id }}">
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
|
||||
|
||||
<form method="POST" style="display:inline;">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="supprimer_departement" value="1">
|
||||
<input type="hidden" name="departement_id" value="{{ d.id }}">
|
||||
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('Voulez-vous vraiment supprimer ce département ?');">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</li><!-- Modal détails -->
|
||||
<div class="modal fade" id="modalDetailDepartement{{ d.id }}" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">Détails du département</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p><strong>Nom :</strong> {{ d.nom }}</p>
|
||||
<p><strong>Chef :</strong> {% if d.chef %}{{ d.chef.first_name }} {{ d.chef.last_name }}{% else %}Non défini{% endif %}</p>
|
||||
|
||||
<!-- Liste des employés du département -->
|
||||
{% for emp in d.employe_set.all %}
|
||||
<p>- {{ emp.username }}</p>
|
||||
{% empty %}
|
||||
<p>Aucun employé associé</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="modal fade" id="modalModifierDepartement{{ d.id }}" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="modifier_departement" value="1">
|
||||
<input type="hidden" name="departement_id" value="{{ d.id }}">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark text-white">
|
||||
<h5 class="modal-title">Modifier le département</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<!-- Nom du département -->
|
||||
<div class="mb-3">
|
||||
<label for="nom_{{ d.id }}" class="form-label">Nom du département</label>
|
||||
<input type="text" class="form-control" id="nom_{{ d.id }}" name="nom" value="{{ d.nom }}" required>
|
||||
</div>
|
||||
|
||||
<!-- Sélection du chef -->
|
||||
<div class="mb-3">
|
||||
<label for="chef_{{ d.id }}" class="form-label">Chef du département</label>
|
||||
<select class="form-select" id="chef_{{ d.id }}" name="chef">
|
||||
<option value="">-- Aucun chef --</option>
|
||||
{% for emp in employes %}
|
||||
<option value="{{ emp.id }}" {% if d.chef and emp.id == d.chef.id %}selected{% endif %}>
|
||||
{{ emp.first_name }} {{ emp.last_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn bg-orange-dark">Modifier</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Colonne Groupes -->
|
||||
<div class="col-md-6">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<h5><i class="bi bi-person-badge-fill"></i> Groupes et rôles</h5>
|
||||
<button class="btn bg-orange-dark btn-sm">Ajouter</button>
|
||||
</div>
|
||||
|
||||
<ul class="list-group">
|
||||
{% for g in groupes %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ g.name }}
|
||||
<a href="{% url 'admin:auth_group_change' g.id %}" class="btn btn-sm btn-outline-secondary">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,205 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tableau de Bord RH</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
|
||||
|
||||
<style>
|
||||
h1 { font-weight: 700; }
|
||||
.card { border-radius: 15px; }
|
||||
.chart-container { position: relative; height: 350px; }
|
||||
table { min-width: 100%; }
|
||||
|
||||
/* Couleurs oranges */
|
||||
.bg-orange-dark { background: linear-gradient(90deg, #b35400, #cc6600); color: white; }
|
||||
.bg-orange { background: #ff9f1c; color: white; }
|
||||
.bg-orange-light { background: #ffc107; color: #212529; }
|
||||
|
||||
/* Badges */
|
||||
.badge-warning { background-color: #ffc107; color: #212529; }
|
||||
.badge-success { background-color: #28a745; color: #fff; }
|
||||
.badge-primary { background-color: #007bff; color: #fff; }
|
||||
|
||||
@media print {
|
||||
body * { visibility: hidden; }
|
||||
.printable-table, .printable-table * { visibility: visible; }
|
||||
.printable-table { position: absolute; top: 0; left: 0; width: 100%; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid py-4">
|
||||
<div class="row flex-nowrap">
|
||||
{% include 'menu_principal.html' %}
|
||||
|
||||
<main class="col px-2 py-4" style="margin-left: 280px;">
|
||||
<h1 class="mb-5 text-center"><i class="bi bi-bar-chart-line-fill me-2"></i>Tableau de Bord RH</h1>
|
||||
|
||||
|
||||
<!-- Filtres -->
|
||||
<form method="GET" class="row g-3 mb-5">
|
||||
<div class="col-md-4">
|
||||
<select name="mois" class="form-select">
|
||||
<option value="">Tous les mois</option>
|
||||
{% for num, nom in mois_liste %}
|
||||
<option value="{{ num }}" {% if mois_selectionne == num %}selected{% endif %}>{{ nom }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select name="departement" class="form-select">
|
||||
<option value="">Tous les départements</option>
|
||||
{% for d in departements %}
|
||||
<option value="{{ d.id }}" {% if departement_selectionne == d.id %}selected{% endif %}>{{ d.nom }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button type="submit" class="btn btn-outline-primary w-100"><i class="bi bi-search"></i> Filtrer</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Cartes statistiques -->
|
||||
<div class="row g-4 mb-5">
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-body"><h6 class="fw-bold"><i class="bi bi-people me-2"></i>Total Employés</h6><h3 class="fw-bold">{{ total_employes }}</h3></div></div></div>
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-body"><h6 class="fw-bold"><i class="bi bi-gender-male me-2"></i>Hommes</h6><h3 class="fw-bold">{{ hommes }}</h3></div></div></div>
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-body"><h6 class="fw-bold"><i class="bi bi-gender-female me-2"></i>Femmes</h6><h3 class="fw-bold">{{ femmes }}</h3></div></div></div>
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-body"><h6 class="fw-bold"><i class="bi bi-clock-history me-2"></i>Contrats expirants(2mois)</h6><h3 class="fw-bold">{{ expirants }}</h3></div></div></div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-5">
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-header fw-bold"><i class="bi bi-airplane me-2"></i>Congés en attente</div><div class="card-body"><h5 class="display-6 fw-bold">{{ conges_attente }}</h5></div></div></div>
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-body"><h6 class="fw-bold"><i class="bi bi-kanban me-2"></i>Projets</h6><h6>(actifs / total)</h6><h3 class="fw-bold">{{ nb_projets_actifs }} / {{ nb_projets }}</h3></div></div></div>
|
||||
<div class="col-md-3"><div class="card text-center"><div class="card-header fw-bold"><i class="bi bi-clock-history me-2"></i>Âge moyen</div><div class="card-body"><h5 class="display-6 fw-bold">{{ age_moyen }} ans</h5></div></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Graphiques -->
|
||||
<div class="row g-4 mb-5">
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow"><div class="card-header bg-orange-dark text-white"><i class="bi bi-pie-chart-fill me-2"></i> Répartition par Département</div>
|
||||
<div class="card-body chart-container"><canvas id="chartDepartement"></canvas></div></div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow"><div class="card-header bg-orange-dark text-white"><i class="bi bi-pie-chart-fill me-2"></i> Répartition par genre</div>
|
||||
<div class="card-body chart-container"><canvas id="chartSexe"></canvas></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4 mb-6">
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow"><div class="card-header bg-orange-dark text-white"><i class="bi bi-bar-chart-fill me-2"></i> Projets (En cours / Terminés)</div>
|
||||
<div class="card-body chart-container"><canvas id="chartProjets"></canvas></div></div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="card shadow"><div class="card-header bg-orange-dark text-white"><i class="bi bi-bar-chart-fill me-2"></i> Projets par domaine de recherche</div>
|
||||
<div class="card-body chart-container"><canvas id="chartDomaine"></canvas></div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
const couleursOrange = ['#b35400', '#ff9f1c', '#ffc107', '#ffb84d', '#ffcc80'];
|
||||
const departementLabels = {{ departement_labels|safe }};
|
||||
const departementCounts = {{ departement_counts|safe }};
|
||||
const sexeLabels = {{ sexe_labels|safe }};
|
||||
const sexeCounts = {{ sexe_counts|safe }};
|
||||
const projetLabels = {{ projet_labels|safe }};
|
||||
const projetCounts = {{ projet_counts|safe }};
|
||||
const ticketsLabels = ["Traités", "Non traités"];
|
||||
const ticketsCounts = [{{ tickets_traite }}, {{ tickets_non_traite }}];
|
||||
const domaineLabels = {{ domaine_labels|safe }};
|
||||
const domaineCounts = {{ domaine_counts|safe }};
|
||||
|
||||
new Chart(document.getElementById("chartDepartement"), {
|
||||
type: 'pie',
|
||||
plugins: [ChartDataLabels],
|
||||
data: {
|
||||
labels: departementLabels,
|
||||
datasets: [{ data: departementCounts, backgroundColor: couleursOrange }]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: { position: 'bottom' },
|
||||
datalabels: { color: '#fff', font: { weight: 'bold', size: 14 }, formatter: v => v }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Chart(document.getElementById("chartSexe"), {
|
||||
type: 'doughnut',
|
||||
plugins: [ChartDataLabels],
|
||||
data: {
|
||||
labels: sexeLabels,
|
||||
datasets: [{ data: sexeCounts, backgroundColor: couleursOrange }]
|
||||
},
|
||||
options: {
|
||||
plugins: {
|
||||
legend: { position: 'bottom' },
|
||||
datalabels: { color: '#fff', font: { weight: 'bold', size: 14 }, formatter: v => v }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Chart(document.getElementById("chartProjets"), {
|
||||
type: 'bar',
|
||||
plugins: [ChartDataLabels],
|
||||
data: {
|
||||
labels: projetLabels,
|
||||
datasets: [{ label:'Nombre de projets', data: projetCounts, backgroundColor: couleursOrange }]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
datalabels: { anchor:'end', align:'top', color:'#000', font:{ weight:'bold', size:16 }, formatter:v => v }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero:true, ticks:{ stepSize:1, precision:0 }, title:{ display:true, text:'Nombre de projets' } },
|
||||
x: { title:{ display:true, text:'' } }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Chart(document.getElementById("chartDomaine"), {
|
||||
type: 'bar',
|
||||
plugins: [ChartDataLabels],
|
||||
data: {
|
||||
labels: domaineLabels,
|
||||
datasets: [{ label:'Nombre de projets', data: domaineCounts, backgroundColor: couleursOrange }]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
datalabels: { anchor:'end', align:'top', color:'#000', font:{ weight:'bold', size:14 }, formatter:v => v }
|
||||
},
|
||||
scales: {
|
||||
y: { beginAtZero:true, title:{ display:true, text:'Nombre de projets' }, ticks:{ precision:0, stepSize:1 } },
|
||||
x: {
|
||||
ticks:{ autoSkip:false, maxRotation:100, minRotation:30, callback: function(value){ return this.getLabelForValue(value); } }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('btnVoirRapport').addEventListener('click', function() {
|
||||
const projetId = document.getElementById('projetId').value;
|
||||
if(!projetId) return alert("Veuillez sélectionner un projet.");
|
||||
fetch(`/rapports/projet/${projetId}/`)
|
||||
.then(resp => { if(!resp.ok) throw new Error("Projet non trouvé"); return resp.text(); })
|
||||
.then(html => { document.getElementById('contenuRapportProjet').innerHTML = html; })
|
||||
.catch(err => { document.getElementById('contenuRapportProjet').innerHTML = "<p class='text-danger'>Erreur lors du chargement.</p>"; console.error(err); });
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,33 +0,0 @@
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Mot de passe oublié</title>
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
</head>
|
||||
<body class="container mt-5">
|
||||
<div class="p-4 shadow-sm rounded bg-white" style="max-width: 400px; margin:auto;">
|
||||
<h2 class="mb-4 text-center" style="color:rgba(255, 157, 0, 0.895);">🔑 Réinitialiser le mot de passe</h2>
|
||||
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-info">{{ message }}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
<form method="POST">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="email">Adresse e-mail</label>
|
||||
<input type="email" name="email" class="form-control" placeholder="Entrez votre email" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Envoyer le lien</button>
|
||||
</form>
|
||||
<p class="mt-3 text-center">
|
||||
<a href="{% url 'login' %}">Retour à la connexion</a>
|
||||
</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,620 +0,0 @@
|
||||
{% load static %}
|
||||
{% load roles %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Mes demandes</title>
|
||||
<link rel="stylesheet" href="{% static 'bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link rel="stylesheet" href="{% static 'styles.css' %}">
|
||||
<style>
|
||||
@keyframes pulse {
|
||||
0% { transform: scale(1); }
|
||||
50% { transform: scale(1.2); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.bg-orange-dark {
|
||||
background: linear-gradient(90deg, #b35400, #cc6600);
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="row flex-nowrap">
|
||||
<nav class="col-12 col-md-3 col-lg-2 sidebar p-3">
|
||||
{% include 'menu_principal.html' %}
|
||||
</nav>
|
||||
|
||||
<main class="col px-4 py-4">
|
||||
|
||||
<!-- Boutons Notifications -->
|
||||
{% if notifications %}
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<button type="button" class="btn position-relative" data-bs-toggle="modal" data-bs-target="#modalNotifications">
|
||||
<i class="bi bi-bell-fill"></i> Notifications
|
||||
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
||||
{{ notifications|length }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Bouton Notifications -->
|
||||
{% if notifications_employe %}
|
||||
<div class="d-flex justify-content-end mb-3">
|
||||
<button type="button" class="btn position-relative" data-bs-toggle="modal" data-bs-target="#modalNotifications">
|
||||
<i class="bi bi-bell-fill"></i> Notifications
|
||||
<span id="badgeNotifications" class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
|
||||
{{ notifications_employe|length }}
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Modal Notifications -->
|
||||
<div class="modal fade" id="modalNotifications" tabindex="-1" aria-labelledby="modalNotificationsLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalNotificationsLabel">Mes Notifications</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if notifications_employe %}
|
||||
<ul class="list-group">
|
||||
{% for notif in notifications_employe %}
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
{{ notif.message|default:"Nouvelle notification" }}
|
||||
<small class="text-muted">{{ notif.date_created|date:"d/m/Y H:i" }}</small>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p class="text-muted">Aucune notification pour le moment.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>document.addEventListener('DOMContentLoaded', function () {
|
||||
var modal = document.getElementById('modalNotifications');
|
||||
|
||||
modal.addEventListener('show.bs.modal', function () {
|
||||
fetch("{% url 'notifications-lues' %}", {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRFToken': '{{ csrf_token }}',
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({})
|
||||
})
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
if(data.status === "ok"){
|
||||
document.getElementById('badgeNotifications').style.display = 'none';
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<h1 class="mb-4">La liste des demandes de congés</h1>
|
||||
<!-- Cartes Statistiques -->
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white ">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title"><i class="bi bi-list-check me-2"></i> Total Demandes</h6>
|
||||
<p class="card-text fs-4">{{ total }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white ">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title"><i class="bi bi-check-circle me-2"></i> Validés</h6>
|
||||
<p class="card-text fs-4">{{ valides }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-white ">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title"><i class="bi bi-x-circle me-2"></i> Refusés</h6>
|
||||
<p class="card-text fs-4">{{ refuses }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-dark ">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title"><i class="bi bi-hourglass-split me-2"></i> En attente</h6>
|
||||
<p class="card-text fs-4">{{ attentes }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% if messages %}
|
||||
<!-- Modal message -->
|
||||
<div class="modal fade" id="messageModal" tabindex="-1" aria-labelledby="messageModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark
|
||||
{% if messages.0.tags == 'error' %}bg-danger text-white
|
||||
{% elif messages.0.tags == 'success' %}bg-success text-white
|
||||
{% else %}bg-info text-white{% endif %}">
|
||||
<h5 class="modal-title" id="messageModalLabel">
|
||||
{% if messages.0.tags == 'error' %}Erreur
|
||||
{% elif messages.0.tags == 'success' %}Succès
|
||||
{% else %}Information{% endif %}
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% for message in messages %}
|
||||
<p>{{ message }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
var messageModal = new bootstrap.Modal(document.getElementById('messageModal'));
|
||||
messageModal.show();
|
||||
});
|
||||
</script>
|
||||
{% endif %}
|
||||
|
||||
|
||||
<!-- Bouton Nouvelle Demande -->
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h2><i class="bi bi-people"></i> Liste</h2>
|
||||
<button type="button" class="btn btn-primary mb-3" data-bs-toggle="modal" data-bs-target="#modalDemandeConge">
|
||||
<i class="bi bi-calendar-plus"></i> Nouvelle demande de congé
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Modal Nouvelle Demande -->
|
||||
<div class="modal fade" id="modalDemandeConge" tabindex="-1" aria-labelledby="modalDemandeCongeLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title" id="modalDemandeCongeLabel">
|
||||
<i class="bi bi-calendar-plus me-2"></i> Nouvelle demande de congé
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<fieldset class="border p-3 rounded">
|
||||
<legend class="fw-bold">Informations du congé
|
||||
Il vous reste {{ employe.solde_conge }} jours de congé Annuel
|
||||
</legend>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
{{ form.type.label_tag }} {{ form.type }}
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
{{ form.date_debut.label_tag }} {{ form.date_debut }}
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
{{ form.date_fin.label_tag }} {{ form.date_fin }}
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
{{ form.nombre_jours.label_tag }} {{ form.nombre_jours }}
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-success">
|
||||
<i class="bi bi-send"></i> Envoyer
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
|
||||
<i class="bi bi-x-circle"></i> Annuler
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tableau des demandes -->
|
||||
<table class="table table-striped mt-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Employe</th>
|
||||
<th>Date demande</th>
|
||||
<th>Type</th>
|
||||
<th>Date début</th>
|
||||
<th>Date fin</th>
|
||||
<th>Nombre jours</th>
|
||||
<th>Jours restant</th>
|
||||
<th>Statut</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for conge in conges %}
|
||||
<tr>
|
||||
<td>{{ conge.employe.first_name }} {{ conge.employe.last_name }}</td>
|
||||
|
||||
<td>{{ conge.date_demande|date:"d/m/Y" }}</td>
|
||||
<td>{{ conge.type }}</td>
|
||||
<td>{{ conge.date_debut|date:"d/m/Y"}}</td>
|
||||
<td>{{ conge.date_fin|date:"d/m/Y" }}</td>
|
||||
<td>{{ conge.nombre_jours }}</td>
|
||||
|
||||
<td>{{ conge.employe.solde_conge }} </td>
|
||||
|
||||
<td>
|
||||
{% if conge.statut == "Refusé" %}
|
||||
<span class="badge bg-danger">Refusé</span>
|
||||
{% elif conge.statut == "Validé directeur" %}
|
||||
<span class="badge bg-success">Valide </span>
|
||||
{% elif conge.statut == "Validé chef" %}
|
||||
<span class="badge bg-warning">Approuvé </span>
|
||||
{% elif conge.statut == "Refusé par chef" %}
|
||||
<span class="badge bg-danger">Refusé </span>
|
||||
{% elif conge.statut == "En attente" %}
|
||||
<span class="badge bg-warning">En attente </span>
|
||||
{% endif %}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<button class="btn btn-sm btn-info"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#detailsCongeModal{{ conge.id }}">
|
||||
<i class="bi bi-eye"></i> Voir
|
||||
</button>
|
||||
{% if conge.statut == "En attente" and conge.employe == request.user %}
|
||||
<!-- Bouton modifier -->
|
||||
<button class="btn btn-sm btn-primary"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modifierCongeModal{{ conge.id }}">
|
||||
Modifier
|
||||
</button>
|
||||
|
||||
<!-- Bouton supprimer -->
|
||||
<button class="btn btn-sm btn-danger"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#supprimerCongeModal{{ conge.id }}">
|
||||
Supprimer
|
||||
</button>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
|
||||
|
||||
|
||||
{% for conge in conges %}
|
||||
<div class="modal fade" id="modifierCongeModal{{ conge.id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="conge_id" value="{{ conge.id }}">
|
||||
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title">Modifier la demande de congé</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="mb-2">
|
||||
<label>Type de congé</label>
|
||||
<select name="type" class="form-select">
|
||||
<option value="Conge Annuel" {% if conge.type == "Conge Annuel" %}selected{% endif %}>Conge Annuel</option>
|
||||
<option value="Maladie" {% if conge.type == "Maladie" %}selected{% endif %}>Maladie</option>
|
||||
<option value="Vacances" {% if conge.type == "Vacances" %}selected{% endif %}>Vacances</option>
|
||||
<option value="Maternité" {% if conge.type == "Maternité" %}selected{% endif %}>Maternité</option>
|
||||
|
||||
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label>Nombre de jours</label>
|
||||
<input type="number" name="nombre_jours" class="form-control" value="{{ conge.nombre_jours }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label>Date début</label>
|
||||
<input type="date" name="date_debut" class="form-control" value="{{ conge.date_debut|date:'Y-m-d' }}">
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<label>Date fin</label>
|
||||
<input type="date" name="date_fin" class="form-control" value="{{ conge.date_fin|date:'Y-m-d' }}">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
||||
<button type="submit" class="btn btn-primary">Enregistrer</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% for conge in conges %}
|
||||
<div class="modal fade" id="detailsCongeModal{{ conge.id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title">Détails de la demande</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item"><strong>Employé :</strong> {{ conge.employe.first_name }} {{ conge.employe.last_name }}</li>
|
||||
<li class="list-group-item"><strong>Type de congé :</strong> {{ conge.type }}</li>
|
||||
<li class="list-group-item"><strong>Date début :</strong> {{ conge.date_debut|date:"d/m/Y" }}</li>
|
||||
<li class="list-group-item"><strong>Date fin :</strong> {{ conge.date_fin|date:"d/m/Y" }}</li>
|
||||
<li class="list-group-item"><strong>Nombre de jours :</strong> {{ conge.nombre_jours }}</li>
|
||||
<li class="list-group-item"><strong>Solde restant :</strong> {{ conge.employe.solde_conge }}</li>
|
||||
<li class="list-group-item">
|
||||
<strong>Statut :</strong>
|
||||
{% if conge.statut == "En attente" %}
|
||||
<span class="badge bg-warning text-dark">{{ conge.statut }}</span>
|
||||
{% elif conge.statut == "Validé directeur" %}
|
||||
<span class="badge bg-success">Validé</span>
|
||||
{% elif conge.statut == "Refusé" %}
|
||||
<span class="badge bg-danger">Refusé</span>
|
||||
{% else %}
|
||||
<span class="badge bg-secondary">{{ conge.statut }}</span>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li class="list-group-item"><strong>Motif :</strong> {{ conge.motif_refus|default:"—" }}</li>
|
||||
<li class="list-group-item"><strong>Date de la demande :</strong> {{ conge.date_demande|date:"d/m/Y H:i" }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
|
||||
{% for conge in conges %}
|
||||
<!-- Modal supprimer -->
|
||||
<div class="modal fade" id="supprimerCongeModal{{ conge.id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="delete_id" value="{{ conge.id }}">
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title">Supprimer la demande</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Voulez-vous vraiment supprimer la demande de congé du
|
||||
<strong>{{ conge.date_debut|date:"d/m/Y" }}</strong> au
|
||||
<strong>{{ conge.date_fin|date:"d/m/Y" }}</strong> ?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
||||
<button type="submit" class="btn btn-danger">Supprimer</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="10" class="text-center text-muted">Aucune demande trouvée.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
<!-- Pagination -->
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{% for page_num in conges.paginator.page_range %}
|
||||
<li class="page-item {% if conges.number == page_num %}active{% endif %}">
|
||||
<a class="page-link" href="?page={{ page_num }}&search={{ search }}">{{ page_num }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
<!-- Modal Notifications Chef -->
|
||||
<div class="modal fade" id="modalNotifications" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl modal-dialog-scrollable">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title"><i class="bi bi-bell-fill me-2"></i> Demandes de congé en attente</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% if notifications %}
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Employé</th>
|
||||
<th>Période</th>
|
||||
<th>Jours</th>
|
||||
<th>Type</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for conge in notifications %}
|
||||
<tr>
|
||||
<td>{{ conge.employe.first_name }} {{ conge.employe.last_name }}</td>
|
||||
<td>{{ conge.date_debut|date:"d/m/Y" }} - {{ conge.date_fin|date:"d/m/Y" }}</td>
|
||||
<td>{{ conge.nombre_jours }}</td>
|
||||
<td>{{ conge.type }}</td>
|
||||
<td class="d-flex gap-1">
|
||||
|
||||
<!-- Valider -->
|
||||
<form method="POST" action="{% url 'valider-par-chef' conge.id %}">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-success btn-sm" title="Valider">
|
||||
<i class="bi bi-check-circle"></i>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<!-- Refuser -->
|
||||
<button class="btn btn-danger btn-sm btn-refuser"
|
||||
data-id="{{ conge.id }}"
|
||||
data-nom="{{ conge.employe.first_name }} {{ conge.employe.last_name }}"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#modalRefuserGlobal">
|
||||
<i class="bi bi-x-circle"></i>
|
||||
</button>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="alert alert-info">Aucune demande en attente.</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Modal Refuser -->
|
||||
<div class="modal fade" id="modalRefuserGlobal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<form method="POST" id="formRefuser">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header bg-orange-dark">
|
||||
<h5 class="modal-title">Refuser la demande</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p id="texteConge"></p>
|
||||
<div class="mb-3">
|
||||
<label class="form-label">Motif du refus</label>
|
||||
{{ form.motif_refus }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" class="btn btn-danger">Refuser</button>
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Annuler</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const modal = new bootstrap.Modal(document.getElementById('modalRefuserGlobal'));
|
||||
const texteConge = document.getElementById('texteConge');
|
||||
const formRefuser = document.getElementById('formRefuser');
|
||||
|
||||
document.querySelectorAll('.btn-refuser').forEach(button => {
|
||||
button.addEventListener('click', function() {
|
||||
const congeId = this.getAttribute('data-id');
|
||||
const nomEmploye = this.getAttribute('data-nom');
|
||||
|
||||
texteConge.innerHTML = `Refuser le congé de <strong>${nomEmploye}</strong> ?`;
|
||||
formRefuser.action = `/refuser-par-chef/${congeId}/`; // URL dynamique vers Django
|
||||
formRefuser.reset();
|
||||
modal.show();
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script>
|
||||
if ('serviceWorker' in navigator) {
|
||||
window.addEventListener('load', function() {
|
||||
navigator.serviceWorker.register('{% static "sw.js" %}').then(function(reg) {
|
||||
console.log('Service worker registered.', reg);
|
||||
}).catch(function(err) {
|
||||
console.warn('Service worker registration failed:', err);
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
@@ -1,31 +0,0 @@
|
||||
{% load static %}
|
||||
{% load tags_personnaliser %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
|
||||
<link href="https://unpkg.com/tabulator-tables@6.4.0/dist/css/tabulator_bootstrap5.min.css" rel="stylesheet">
|
||||
|
||||
{% block 'css' %}{% endblock %}
|
||||
<title> {% block 'titre_page'%}{% endblock%}</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="row flex-nowrap">
|
||||
{% include 'parts/menu_principal.html' %}
|
||||
<div class="col-9 p-4">
|
||||
{% block 'contenu' %} {% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
{% block 'modal' %} {% endblock %}
|
||||
</div>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/3.7.2/luxon.min.js"></script>
|
||||
<script type="text/javascript" src="https://unpkg.com/tabulator-tables/dist/js/tabulator.min.js"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.8/js/bootstrap.min.js"></script>
|
||||
{% block 'js' %} {% endblock%}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,43 +0,0 @@
|
||||
{% load static %}
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
|
||||
<title>Login - SIRH</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid vh-100">
|
||||
<div class="row">
|
||||
<div class="col-6 vh-100 d-flex flex-column justify-content-center align-items-center">
|
||||
<img src="{% static 'img/cerfig.jpg' %}" class="w-50">
|
||||
<h5 class="text-center">Bienvenue sur les systèmes de gestion du CERFIG</h5>
|
||||
</div>
|
||||
<div class="col-6 vh-100 d-flex justify-content-center align-items-center">
|
||||
<form method="POST" action="{% url 'login' %}" class="w-100 shadow rounded px-3 py-5">
|
||||
<h2 class="text-center">Connexion</h2>
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{% if message.tags == 'error' %}danger{% else %}success{% endif %}">{{message}}</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="mail">Votre adresse email :</label>
|
||||
<input type="text" name="mail" class="form-control" placeholder="Entrez votre e-mail" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="mot_de_passe">Mot de passe</label>
|
||||
<input type="password" name="mot_de_passe" class="form-control" placeholder="Entrez votre mot de passe" required>
|
||||
<i class="bi bi-eye toggle-password" onclick="togglePassword()"
|
||||
style="position:absolute; right:10px; top:38px; cursor:pointer;"></i>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Se connecter</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
67
SIRH/urls.py
67
SIRH/urls.py
@@ -1,67 +0,0 @@
|
||||
"""
|
||||
URL configuration for SIRH project.
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/5.2/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: path('', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.urls import include, path
|
||||
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.contrib import admin
|
||||
from django.urls import include, path
|
||||
from django.conf.urls.static import static
|
||||
from django.conf import settings
|
||||
# from simple_sso.sso_server.server import Server
|
||||
|
||||
from . import views
|
||||
|
||||
# server_sso = Server()
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
'',
|
||||
views.login_view,
|
||||
name='index'
|
||||
),
|
||||
|
||||
path('login/',
|
||||
views.login_view,
|
||||
name='login'
|
||||
),
|
||||
path(
|
||||
'deconnexion/',
|
||||
views.deconnexion_view,
|
||||
name='deconnexion'
|
||||
),
|
||||
path(
|
||||
'employé/',
|
||||
include("gestion_employe.urls")
|
||||
),
|
||||
path(
|
||||
'gestion-conge/',
|
||||
include("gestion_conge.urls")
|
||||
),
|
||||
path(
|
||||
'gestion-projet/',
|
||||
include("gestion_projet.urls")
|
||||
),
|
||||
path(
|
||||
'gestion-salle/',
|
||||
include("gestion_salle.urls")
|
||||
),
|
||||
path(
|
||||
'admin/',
|
||||
admin.site.urls
|
||||
),
|
||||
# path(
|
||||
# 'sso',
|
||||
# include(server_sso.get_urls())
|
||||
# )
|
||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||
@@ -1,37 +0,0 @@
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.shortcuts import render, redirect
|
||||
from django.contrib import messages
|
||||
|
||||
def login_view(request):
|
||||
"""
|
||||
Gère la connexion des utilisateurs avec redirection selon le rôle et
|
||||
vérification de l'acceptation de la politique d'utilisation.
|
||||
"""
|
||||
if request.method == 'POST':
|
||||
email = request.POST.get('mail')
|
||||
password = request.POST.get('mot_de_passe')
|
||||
|
||||
if not (email and password):
|
||||
messages.error(request, "Veuillez remplir tous les champs.")
|
||||
return render(request, 'login.html')
|
||||
|
||||
user = authenticate(request, username=email, password=password)
|
||||
|
||||
if user is None:
|
||||
messages.error(request, "Nom d’utilisateur ou mot de passe incorrect.")
|
||||
return render(request, 'login.html')
|
||||
|
||||
if not user.is_active:
|
||||
messages.error(request, "Compte inactif. Contactez l'administrateur.")
|
||||
return render(request, 'login.html')
|
||||
|
||||
login(request, user)
|
||||
|
||||
return redirect("gestion_conges:conge")
|
||||
|
||||
return render(request, 'login.html')
|
||||
|
||||
def deconnexion_view(request):
|
||||
"""Gère la déconnexion de l'utilisateur."""
|
||||
logout(request)
|
||||
return redirect('login')
|
||||
16
SIRH/wsgi.py
16
SIRH/wsgi.py
@@ -1,16 +0,0 @@
|
||||
"""
|
||||
WSGI config for SIRH project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/5.2/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SIRH.settings')
|
||||
|
||||
application = get_wsgi_application()
|
||||
Reference in New Issue
Block a user