Affichage de historique de demande avec toutes lesétats et les information nécessaire et la pièce jointe s'il est type"arretMaladie"

This commit is contained in:
2025-08-08 16:54:35 +02:00
parent 011620fb39
commit 4a3cded08c
4 changed files with 136 additions and 136 deletions

View File

@@ -1,73 +1,41 @@
<?php <?php
// Récupération des demandes en attente pour un manager
header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: GET, OPTIONS"); header("Access-Control-Allow-Methods: GET, OPTIONS");
header("Access-Control-Allow-Headers: Content-Type"); header("Access-Control-Allow-Headers: Content-Type");
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') { if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
http_response_code(200); http_response_code(200);
exit(); exit();
} }
header("Content-Type: application/json"); header("Content-Type: application/json");
// Log des erreurs pour debug
ini_set('display_errors', 1); ini_set('display_errors', 1);
ini_set('display_startup_errors', 1); ini_set('display_startup_errors', 1);
error_reporting(E_ALL); error_reporting(E_ALL);
// Connexion DB
$host = "192.168.0.4"; $host = "192.168.0.4";
$dbname = "DemandeConge"; $dbname = "DemandeConge";
$username = "wpuser"; $username = "wpuser";
$password = "-2b/)ru5/Bi8P[7_"; $password = "-2b/)ru5/Bi8P[7_";
$conn = new mysqli($host, $username, $password, $dbname); $conn = new mysqli($host, $username, $password, $dbname);
if ($conn->connect_error) { if ($conn->connect_error) {
error_log("Erreur connexion DB getPendingRequests: " . $conn->connect_error); error_log("Erreur connexion DB: " . $conn->connect_error);
echo json_encode(["success" => false, "message" => "Erreur de connexion à la base de données"]); echo json_encode(["success" => false, "message" => "Erreur de connexion DB"]);
exit(); exit();
} }
$managerId = $_GET['manager_id'] ?? null;
if ($managerId === null) { // Récupération ID manager
echo json_encode(["success" => false, "message" => "ID manager manquant"]); $managerId = $_GET['SuperieurId'] ?? null;
if (!$managerId) {
echo json_encode(["success" => false, "message" => "Paramètre SuperieurId manquant"]);
exit(); exit();
} }
error_log("getPendingRequests - Manager ID: $managerId"); $sql = "
// Fonction pour calculer les jours ouvrés
function getWorkingDays($startDate, $endDate) {
$workingDays = 0;
$current = new DateTime($startDate);
$end = new DateTime($endDate);
while ($current <= $end) {
$dayOfWeek = (int)$current->format('N');
if ($dayOfWeek < 6) {
$workingDays++;
}
$current->modify('+1 day');
}
return $workingDays;
}
try {
// D'abord, récupérer le service du manager
$queryManagerService = "SELECT ServiceId FROM Users WHERE ID = ?";
$stmtManager = $conn->prepare($queryManagerService);
$stmtManager->bind_param("i", $managerId);
$stmtManager->execute();
$resultManager = $stmtManager->get_result();
if ($managerRow = $resultManager->fetch_assoc()) {
$serviceId = $managerRow['ServiceId'];
error_log("getPendingRequests - Service ID du manager: $serviceId");
// Récupérer les demandes en attente de l'équipe
$queryRequests = "
SELECT SELECT
dc.Id, dc.Id,
dc.DateDebut, dc.DateDebut,
@@ -75,6 +43,7 @@ try {
dc.Statut, dc.Statut,
dc.DateDemande, dc.DateDemande,
dc.Commentaire, dc.Commentaire,
dc.DocumentJoint,
dc.EmployeeId, dc.EmployeeId,
CONCAT(u.Prenom, ' ', u.Nom) as employee_name, CONCAT(u.Prenom, ' ', u.Nom) as employee_name,
u.Email as employee_email, u.Email as employee_email,
@@ -82,75 +51,56 @@ try {
FROM DemandeConge dc FROM DemandeConge dc
JOIN Users u ON dc.EmployeeId = u.ID JOIN Users u ON dc.EmployeeId = u.ID
JOIN TypeConge tc ON dc.TypeCongeId = tc.Id JOIN TypeConge tc ON dc.TypeCongeId = tc.Id
WHERE u.ServiceId = ? JOIN HierarchieValidation hv ON hv.EmployeId = u.ID
AND dc.Statut = 'En attente' WHERE hv.SuperieurId = ?
AND u.ID != ? ORDER BY dc.DateDemande DESC
ORDER BY dc.DateDemande ASC ";
";
$stmtRequests = $conn->prepare($queryRequests); $stmt = $conn->prepare($sql);
$stmtRequests->bind_param("ii", $serviceId, $managerId); $stmt->bind_param("i", $managerId);
$stmtRequests->execute(); $stmt->execute();
$resultRequests = $stmtRequests->get_result();
$requests = []; // ✅ Manquant dans ton code
while ($row = $resultRequests->fetch_assoc()) { $result = $stmt->get_result();
$workingDays = getWorkingDays($row['DateDebut'], $row['DateFin']);
$requests = [];
while ($row = $result->fetch_assoc()) {
$startDate = new DateTime($row['DateDebut']); $startDate = new DateTime($row['DateDebut']);
$endDate = new DateTime($row['DateFin']); $endDate = new DateTime($row['DateFin']);
$submittedDate = new DateTime($row['DateDemande']); $submittedDate = new DateTime($row['DateDemande']);
$days = 0;
if ($row['DateDebut'] === $row['DateFin']) { $tmp = clone $startDate;
$dateDisplay = $startDate->format('d/m/Y'); while ($tmp <= $endDate) {
} else { if ((int)$tmp->format('N') < 6) $days++;
$dateDisplay = $startDate->format('d/m/Y') . ' - ' . $endDate->format('d/m/Y'); $tmp->modify('+1 day');
} }
$requests[] = [ $requests[] = [
'id' => (int)$row['Id'], "id" => (int)$row['Id'],
'employee_id' => (int)$row['EmployeeId'], "employee_id" => (int)$row['EmployeeId'],
'employee_name' => $row['employee_name'], "employee_name" => $row['employee_name'],
'employee_email' => $row['employee_email'], "employee_email" => $row['employee_email'],
'type' => $row['type'], "type" => $row['type'],
'start_date' => $row['DateDebut'], "start_date" => $row['DateDebut'],
'end_date' => $row['DateFin'], "end_date" => $row['DateFin'],
'date_display' => $dateDisplay, "date_display" => $row['DateDebut'] === $row['DateFin']
'days' => $workingDays, ? $startDate->format('d/m/Y')
'status' => $row['Statut'], : $startDate->format('d/m/Y') . ' - ' . $endDate->format('d/m/Y'),
'reason' => $row['Commentaire'] ?: '', "days" => $days,
'submitted_at' => $row['DateDemande'], "status" => $row['Statut'],
'submitted_display' => $submittedDate->format('d/m/Y') "reason" => $row['Commentaire'] ?: '',
"file" => $row['DocumentJoint'] ?: null,
"submitted_at" => $row['DateDemande'],
"submitted_display" => $submittedDate->format('d/m/Y')
]; ];
}
error_log("getPendingRequests - Demandes en attente trouvées: " . count($requests));
echo json_encode([
"success" => true,
"message" => "Demandes en attente récupérées avec succès",
"requests" => $requests,
"service_id" => $serviceId
]);
$stmtRequests->close();
} else {
error_log("getPendingRequests - Manager non trouvé: $managerId");
echo json_encode([
"success" => false,
"message" => "Manager non trouvé"
]);
}
$stmtManager->close();
} catch (Exception $e) {
error_log("Erreur getPendingRequests: " . $e->getMessage());
echo json_encode([
"success" => false,
"message" => "Erreur lors de la récupération des demandes: " . $e->getMessage()
]);
} }
echo json_encode([
"success" => true,
"requests" => $requests
]);
$stmt->close();
$conn->close(); $conn->close();
?> ?>

View File

@@ -76,7 +76,7 @@ const Manager = () => {
const fetchAllTeamRequests = async () => { const fetchAllTeamRequests = async () => {
try { try {
const response = await fetch(`http://localhost/GTA/project/public/getAllTeamRequests.php?manager_id=${user.id}`); const response = await fetch(`http://localhost/GTA/project/public/getAllTeamRequests.php?SuperieurId=${user.id}`);
const text = await response.text(); const text = await response.text();
console.log('Réponse toutes demandes équipe:', text); console.log('Réponse toutes demandes équipe:', text);
@@ -85,7 +85,9 @@ const Manager = () => {
setAllRequests(data.requests || []); setAllRequests(data.requests || []);
} }
} catch (error) { } catch (error) {
console.error('Erreur récupération toutes demandes:', error); console.error('Erreur récupération toutes demandes:', error);
console.log('Réponse brute:', text);
setAllRequests([]); setAllRequests([]);
} }
}; };
@@ -385,9 +387,8 @@ const Manager = () => {
) : ( ) : (
<div className="space-y-3 max-h-80 overflow-y-auto"> <div className="space-y-3 max-h-80 overflow-y-auto">
{allRequests.map((request) => ( {allRequests.map((request) => (
<div key={request.id} className="flex items-center justify-between p-3 border border-gray-100 rounded-lg hover:bg-gray-50 transition-colors"> <div key={request.id} className="p-3 border border-gray-100 rounded-lg hover:bg-gray-50 transition-colors">
<div className="flex-1"> <div className="flex items-center gap-2 mb-2">
<div className="flex items-center gap-2 mb-1">
<p className="font-medium text-gray-900">{request.employee_name}</p> <p className="font-medium text-gray-900">{request.employee_name}</p>
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getTypeColor(request.type)}`}> <span className={`px-2 py-1 rounded-full text-xs font-medium ${getTypeColor(request.type)}`}>
{request.type} {request.type}
@@ -397,13 +398,33 @@ const Manager = () => {
</span> </span>
</div> </div>
<p className="text-sm text-gray-600">{request.date_display}</p> <p className="text-sm text-gray-600">{request.date_display}</p>
<p className="text-xs text-gray-500">Soumis le {request.submitted_display}</p> <p className="text-xs text-gray-500 mb-2">Soumis le {request.submitted_display}</p>
{request.reason && (
<p className="text-sm text-gray-700 mb-1"><strong>Motif :</strong> {request.reason}</p>
)}
{request.file && (
<div className="text-sm mt-1">
<p className="text-gray-500">Document joint</p>
<a
href={`http://localhost/GTA/project/uploads/${request.file}`}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline flex items-center gap-1 mt-1"
>
<Eye className="w-4 h-4" />
Voir le fichier
</a>
</div> </div>
<div className="text-right"> )}
<div className="text-right mt-2">
<p className="font-medium text-gray-900">{request.days}j</p> <p className="font-medium text-gray-900">{request.days}j</p>
</div> </div>
</div> </div>
))} ))}
</div> </div>
)} )}
</div> </div>
@@ -413,25 +434,51 @@ const Manager = () => {
</div> </div>
{/* Modal de validation */} {/* Modal de validation */}
{showValidationModal && selectedRequest && ( {showValidationModal && selectedRequest && (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"> <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-xl shadow-xl max-w-md w-full"> <div className="bg-white rounded-xl shadow-xl max-w-md w-full">
{/* Header */}
<div className="p-6 border-b border-gray-100"> <div className="p-6 border-b border-gray-100">
<h3 className="text-lg font-semibold text-gray-900"> <h3 className="text-lg font-semibold text-gray-900">
{validationAction === 'approve' ? 'Approuver' : 'Refuser'} la demande {validationAction === 'approve' ? 'Approuver' : 'Refuser'} la demande
</h3> </h3>
</div> </div>
{/* Corps du contenu */}
<div className="p-6"> <div className="p-6">
<div className="mb-4 p-4 bg-gray-50 rounded-lg"> <div className="mb-4 p-4 bg-gray-50 rounded-lg">
<p className="font-medium text-gray-900">{selectedRequest.employee_name}</p> <p className="font-medium text-gray-900">{selectedRequest.employee_name}</p>
<p className="text-sm text-gray-600">{selectedRequest.type} - {selectedRequest.date_display}</p> <p className="text-sm text-gray-600">
{selectedRequest.type} - {selectedRequest.date_display}
</p>
<p className="text-sm text-gray-600">{selectedRequest.days} jour(s)</p> <p className="text-sm text-gray-600">{selectedRequest.days} jour(s)</p>
{selectedRequest.reason && ( {selectedRequest.reason && (
<p className="text-sm text-gray-600 mt-2"><strong>Motif:</strong> {selectedRequest.reason}</p> <p className="text-sm text-gray-600 mt-2">
<strong>Motif:</strong> {selectedRequest.reason}
</p>
)} )}
{selectedRequest.file && (
<div>
<p className="text-gray-500">Document joint</p>
<a
href={`http://localhost/GTA/project/uploads/${selectedRequest.file}`}
target="_blank"
rel="noopener noreferrer"
className="text-blue-600 hover:underline flex items-center gap-2"
>
<Eye className="w-4 h-4" />
Voir le fichier
</a>
</div>
)}
</div> </div>
{/* Champ commentaire */}
<div className="mb-4"> <div className="mb-4">
<label className="block text-sm font-medium text-gray-700 mb-2"> <label className="block text-sm font-medium text-gray-700 mb-2">
Commentaire {validationAction === 'reject' ? '(obligatoire)' : '(optionnel)'} Commentaire {validationAction === 'reject' ? '(obligatoire)' : '(optionnel)'}
@@ -445,6 +492,7 @@ const Manager = () => {
/> />
</div> </div>
{/* Boutons */}
<div className="flex gap-3"> <div className="flex gap-3">
<button <button
onClick={() => setShowValidationModal(false)} onClick={() => setShowValidationModal(false)}
@@ -453,7 +501,9 @@ const Manager = () => {
Annuler Annuler
</button> </button>
<button <button
onClick={() => handleValidateRequest(selectedRequest.id, validationAction, validationComment)} onClick={() =>
handleValidateRequest(selectedRequest.id, validationAction, validationComment)
}
disabled={validationAction === 'reject' && !validationComment.trim()} disabled={validationAction === 'reject' && !validationComment.trim()}
className={`flex-1 px-4 py-2 text-white rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${validationAction === 'approve' className={`flex-1 px-4 py-2 text-white rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed ${validationAction === 'approve'
? 'bg-green-600 hover:bg-green-700' ? 'bg-green-600 hover:bg-green-700'

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 KiB