Verification du statut avant la creation d'un contrat

This commit is contained in:
2026-04-30 13:28:57 +02:00
committed by Soriba SYLLA
parent fcfac71026
commit f6b90e7dd0
269 changed files with 44845 additions and 2 deletions

6
static/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

278
static/css/styles.css Normal file
View File

@@ -0,0 +1,278 @@
/* === Print === */
@media print {
nav, .btn, .sidebar, .form-select, .form-control {
display: none !important;
}
body {
font-size: 12pt;
color: black;
}
table {
border-collapse: collapse;
}
}
@media (max-width: 768px) {
main {
margin-left: 0;
}
}
/* === Body & Container === */
body {
background-color: #e4dccc;
background-attachment: fixed;
}
.dashboard-container {
background-color: #ffffff;
box-shadow: 0 0 10px rgba(0,0,0,0.05);
border-radius: 8px;
padding: 20px;
margin: 30px auto;
max-width: 1200px;
}
.sidebar {
position: fixed;
width: 220px;
}
main {
margin-left: 220px;
}
/* === Sidebar === */
.sidebar {
background: linear-gradient(180deg, #b35400, #993d00); /* dégradé orange foncé */
color: white;
min-height: 100vh; /* prend toute la hauteur */
top: 0;
z-index: 1000;
overflow-y: auto;
padding: 1rem;
}
.sidebar .nav-link {
color: white;
font-weight: 700;
}
.sidebar .nav-link:hover {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 5px;
color: white;
}
.sidebar .dropdown-menu {
display: none;
position: relative;
left: 10px;
top: -5px;
border: none;
padding-left: 1rem;
box-shadow: none;
}
.sidebar .dropdown:hover .dropdown-menu {
display: block;
}
.sidebar a {
color: white;
}
.sidebar a:hover {
color: white;
}
/* === Navbar / Logo / Profil === */
.logo {
max-width: 80px;
}
.img-profil {
width: 80px !important;
height: 80px !important;
object-fit: cover;
border-radius: 50%;
}
/* === Cards === */
.card {
border: 1px solid #dee2e6;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
border-radius: 8px;
transition: transform 0.3s ease;
}
.card:hover {
transform: scale(1.02);
}
.card-header {
background-color: #f8f9fa;
font-weight: bold !important;
color: black !important;
font-size: 1rem;
border-bottom: none;
}
.card-body h5 {
color: black !important;
font-weight: bold;
font-size: 2.2rem;
}
/* === Stat cards === */
.stat-card {
background: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(113, 11, 11, 0.1);
}
/* === Employé / Projet details === */
.employe-detail {
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
}
.employe-detail .card-title {
font-size: 1.8rem;
margin-bottom: 0.5rem;
}
.employe-detail p {
margin-bottom: 0.4rem;
font-size: 1rem;
}
.employe-detail a.btn {
font-weight: 500;
}
.employe-card, .projet-card {
background-color: #fff;
border-radius: 10px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
padding: 2.5rem;
max-width: 1400px;
margin: 0 auto;
font-size: 1.1rem;
}
/* === Forms === */
.form-wrapper {
max-width: 1000px;
margin: auto;
background-color: rgba(255, 255, 255, 0.95);
}
form label {
font-weight: 600;
margin-top: 1rem;
display: block;
}
form input, form select, form textarea {
width: 100%;
padding: 0.5rem;
margin-top: 0.3rem;
border-radius: 5px;
border: 1px solid #ccc;
}
/* === Formation badges === */
.formation-badge {
position: relative;
display: inline-block;
}
.formation-actions {
position: absolute;
top: -5px;
right: -5px;
display: none;
}
.formation-badge:hover .formation-actions {
display: inline-block;
}
.formation-actions button {
background: none;
border: none;
color: #fff;
margin-left: 5px;
font-size: 0.9rem;
}
/* === Context menu === */
#contextMenu {
width: 150px;
}
/* === Transitions / Animations === */
.fade-out {
opacity: 0;
transition: opacity 0.5s ease;
}
#main-content {
transition: opacity 0.3s ease;
}
.login-box {
background: linear-gradient(to right, #f5f7fa, #c3cfe2);
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
width: 100%;
max-width: 400px;
}
/* === Responsive === */
@media (max-width: 576px) {
.modal-dialog {
max-width: 100%;
margin: 0;
height: 100%;
}
.modal-content {
height: 100%;
border-radius: 0;
}
.modal-body {
overflow-y: auto;
}
.modal-footer button {
width: 100%;
}
.img-profil {
width: 50px;
height: 50px;
}
.sidebar {
width: 100%;
padding: 0.5rem 1rem;
}
.sidebar .nav-link {
font-size: 0.9rem;
padding: 0.5rem 1rem;
}
}

File diff suppressed because one or more lines are too long

BIN
static/img/cerfig.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

13
static/js/monprofil.js Normal file
View File

@@ -0,0 +1,13 @@
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
// Vérifie si le formulaire contient des erreurs
var formErrors = {{ complet_form.non_field_errors|length|default:0 }};
if (formErrors > 0) {
// Ouvre la modale
var modal = new bootstrap.Modal(document.getElementById('modalModifierProfil'));
modal.show();
}
});
</script>

102
static/js/rapport.js Normal file
View File

@@ -0,0 +1,102 @@
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);
});
});
}
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); });
});

75
static/js/sirh-index.js Normal file
View File

@@ -0,0 +1,75 @@
<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>
<script>
document.addEventListener("DOMContentLoaded", function() {
var messageModal = new bootstrap.Modal(document.getElementById('messageModal'));
messageModal.show();
});
</script>
<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 lenvoi. Vérifiez lemail.</div>');
}
});
});
</script>