File "table0021_split_001.php"

Full Path: /home/analogde/www/Chart burndown/table0021_split_001.php
File size: 72.23 KB
MIME-type: text/x-php
Charset: utf-8

<?php

function getWorkingDays($startDate, $endDate, $holidays = []) {
    $start = strtotime($startDate);
    $end = strtotime($endDate);
    $workingDays = [];

    setlocale(LC_TIME, 'fr_FR.UTF-8');

    for ($currentDate = $start; $currentDate <= $end; $currentDate = strtotime("+1 day", $currentDate)) {
        $dayOfWeek = date("N", $currentDate);

        if ($dayOfWeek < 6 && !in_array(date("Y-m-d", $currentDate), $holidays)) {
            $workingDays[] = [
                'day' => date("d", $currentDate),
                'day_of_week_initial' => strtoupper(strftime("%A", $currentDate)[0]),
                'week_number' => date("W", $currentDate),
                'full_date' => date("Y-m-d", $currentDate) // Ajout de la date complète
            ];
        }
    }

    return $workingDays;
}

// Liste des jours fériés et fêtes religieuses à exclure (exemple pour la France, à compléter avec d'autres fêtes)
$holidays = [
    "2025-01-01", // Jour de l'An
    "2025-04-14", // Lundi de Pâques
    "2025-05-01", // Fête du Travail
    "2025-05-08", // Victoire 1945
    "2025-07-14", // Bastille
    "2025-08-15", // Assomption
    "2025-11-01", // Toussaint
    "2025-12-25", // Noël
    "2026-01-01", // Jour de l'An
    "2026-04-06", // Lundi de Pâques
    // Ajouter d'autres jours fériés ici...
];

// Définir la période de début et de fin
$startDate = "2025-01-10";
$endDate = "2026-02-14";

// Appeler la fonction pour obtenir les jours ouvrés entre les deux dates
$workingDays = getWorkingDays($startDate, $endDate, $holidays);

?>

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tableau Sticky - 3 Lignes Fixes</title>
    <style>
        /* Votre CSS ici */
        .table-wrapper {
            width: 100%;
            height: calc(100vh - 100px);
            overflow: auto;
            border: 1px solid #ccc;
            position: relative;
        }

        table {
            border-collapse: collapse;
            width: max-content;
            table-layout: fixed;
        }

        th, td {
            padding: 3px;
            text-align: center;
            height: 40px;
            border: 1px solid #ccc;
            white-space: nowrap;
            min-width: 120px;
            position: relative;
            background-color: white;
            box-sizing: border-box;
        }

        th {
            background-color: #f2f2f2;
            position: sticky;
            top: 0;
            z-index: 100;
        }

        th:first-child, td:first-child {
            position: sticky;
            left: 0;
            z-index: 101;
            background-color: white;
        }

        th:nth-child(2), td:nth-child(2) {
            position: sticky;
            left: 120px;
            z-index: 100;
            background-color: white;
        }

        th:nth-child(3), td:nth-child(3) {
            position: sticky;
            left: 240px;
            z-index: 99;
            background-color: white;
        }

        th:first-child::after, td:first-child::after,
        th:nth-child(2)::after, td:nth-child(2)::after,
        th:nth-child(3)::after, td:nth-child(3)::after {
            content: "";
            position: absolute;
            right: 0;
            top: 0;
            width: 2px;
            height: 100%;
            background-color: #ccc;
            z-index: 102;
        }

        tbody tr:nth-child(odd) {
            background-color: #f9f9f9;
        }

        th:nth-child(n+4), td:nth-child(n+4) {
            min-width: 40px;
            max-width: 40px;
            width: 40px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
        }

        .second-header th {
            background-color: #f2f2f2;
            position: sticky;
            top: 40px;
            z-index: 99;
        }

        .third-header th {
            background-color: #f2f2f2;
            position: sticky;
            top: 80px;
            z-index: 98;
        }

        .second-header th:first-child, .third-header th:first-child {
            left: 0;
            z-index: 101;
            background-color: white;
        }

        .second-header th:nth-child(2), .third-header th:nth-child(2) {
            left: 120px;
            z-index: 100;
            background-color: white;
        }

        .second-header th:nth-child(3), .third-header th:nth-child(3) {
            left: 240px;
            z-index: 99;
            background-color: white;
        }

        thead tr:first-child th:first-child,
        thead tr:first-child th:nth-child(2),
        thead tr:first-child th:nth-child(3) {
            z-index: 105;
            background-color: #ddd;
        }

        .second-header th:first-child,
        .second-header th:nth-child(2),
        .second-header th:nth-child(3) {
            z-index: 104;
        }

        .third-header th:first-child,
        .third-header th:nth-child(2),
        .third-header th:nth-child(3) {
            z-index: 103;
        }

        thead tr:first-child th,
        .second-header th,
        .third-header th {
            box-shadow: inset 0 -2px #aaa;
            background-clip: padding-box;
            padding-bottom: 2px;
            margin-bottom: -2px;
            z-index: 100;
        }

        .second-header th {
            top: calc(40px + 2px);
            margin-top: 2px;
        }

        .third-header th {
            top: calc(80px + 2px);
            margin-top: 2px;
        }

        .even-week {
            background-color: #ffcc99 !important;
        }

        .odd-week {
            background-color: #e6b3ff !important;
        }

        .fourth-header th {
            background-color: #f2f2f2;
            position: sticky;
            top: 120px;
            z-index: 97;
        }

        .fourth-header th:first-child {
            left: 0;
            z-index: 101;
            background-color: white;
        }

        .fourth-header th:nth-child(2) {
            left: 120px;
            z-index: 100;
            background-color: white;
        }

        .fourth-header th:nth-child(3) {
            left: 240px;
            z-index: 99;
            background-color: white;
        }

        .fourth-header th:first-child,
        .fourth-header th:nth-child(2),
        .fourth-header th:nth-child(3) {
            z-index: 102;
        }

        .fourth-header th {
            top: calc(120px + 2px);
            margin-top: 2px;
        }

        .fourth-header th {
            box-shadow: inset 0 -2px #aaa;
            background-clip: padding-box;
            padding-bottom: 2px;
            margin-bottom: -2px;
            z-index: 97;
        }

        .even-week {
            background-color: #ffcc99 !important;
        }

        .odd-week {
            background-color: #e6b3ff !important;
        }

        .month-even {
            background-color: #99ccff !important;
        }

        .month-odd {
            background-color: #ff9999 !important;
        }

        .btn {
            margin-bottom: 20px;
            padding: 10px;
            background-color: #4CAF50;
            color: white;
            border: none;
            cursor: pointer;
            font-size: 16px;
            border-radius: 5px;
            transition: background-color 0.3s ease;
        }

        .btn:hover {
            background-color: #45a049;
        }

        .btn-special {
            background-color: #2196F3;
        }

        .btn-special:hover {
            background-color: #1e88e5;
        }

        .btn-special:hover {
            background-color: #1e88e5;
        }

        #contextMenu {
            position: absolute;
            display: none;
            flex-direction: column;
            background: white;
            border: 1px solid #ccc;
            box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
            border-radius: 5px;
            z-index: 1000;
            min-width: 180px;
        }

        #contextMenu .dropdown-item {
            display: block;
            width: 100%;
            padding: 8px 12px;
            text-align: left;
            color: #333;
            cursor: pointer;
        }

        #contextMenu .dropdown-item:hover {
            background: #f8f9fa;
        }

        #specialContextMenu {
            position: absolute;
            display: none;
            flex-direction: column;
            background: white;
            border: 1px solid #ccc;
            box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
            border-radius: 5px;
            z-index: 1000;
            min-width: 180px;
        }

        #specialContextMenu .dropdown-item {
            display: block;
            width: 100%;
            padding: 8px 12px;
            text-align: left;
            color: #333;
            cursor: pointer;
        }

        #specialContextMenu .dropdown-item:hover {
            background: #f8f9fa;
        }

        #colorContextMenu {
            position: absolute;
            display: none;
            flex-direction: column;
            background: white;
            border: 1px solid #ccc;
            box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
            border-radius: 5px;
            z-index: 1000;
            min-width: 180px;
        }

        #colorContextMenu .dropdown-item {
            display: block;
            width: 100%;
            padding: 8px 12px;
            text-align: left;
            color: #333;
            cursor: pointer;
        }

        #colorContextMenu .dropdown-item:hover {
            background: #f8f9fa;
        }

        .add-button {
            background-color: orange;
            color: white;
            border: none;
            padding: 5px 10px;
            cursor: pointer;
            margin-left: 5px;

        }

        .editable-input {
            width: 65px;
            box-sizing: border-box;
        }

        .collapsed {
            display: none;
        }

        #jsonOutput {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            background-color: #f9f9f9;
            white-space: pre-wrap;
            word-wrap: break-word;
        }

        #logOutput {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            background-color: #f9f9f9;
            white-space: pre-wrap;
            word-wrap: break-word;
        }

        .no-click {
            pointer-events: none;
        }

        #debugOutput {
            margin-top: 20px;
            padding: 10px;
            border: 1px solid #ccc;
            background-color: #f9f9f9;
            white-space: pre-wrap;
            word-wrap: break-word;
        }
    </style>

    <!-- Autres liens et méta-informations -->
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.4/dist/umd/popper.min.js"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>

<!-- Modal Structure -->
<div class="modal fade" id="confirmationModal" tabindex="-1" aria-labelledby="confirmationModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="confirmationModalLabel">Confirmation</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                Voulez-vous vraiment supprimer cette ligne ?
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" id="cancelDelete">Annuler</button>
                <button type="button" class="btn btn-danger" id="confirmDelete">OK</button>
            </div>
        </div>
    </div>
</div>

<!-- Success Modal Structure -->
<div class="modal fade" id="successModal" tabindex="-1" aria-labelledby="successModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="successModalLabel">Succès</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                Données sauvegardées avec succès !
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" id="closeSuccessModal">OK</button>
            </div>
        </div>
    </div>
</div>

<!-- Message Modal Structure -->
<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">
                <h5 class="modal-title" id="messageModalLabel">Message</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body" id="messageModalBody">
                <!-- Le contenu du message sera inséré ici -->
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
            </div>
        </div>
    </div>
</div>

<!-- Color Context Menu Structure -->
<div id="colorContextMenu" class="dropdown-menu" style="display: none;">
    <button class="dropdown-item" style="background-color: green;" data-color="green">Vert</button>
    <button class="dropdown-item" style="background-color: blue;" data-color="blue">Bleu</button>
    <button class="dropdown-item" style="background-color: red;" data-color="red">Rouge</button>
    <button class="dropdown-item" style="background-color: yellow;" data-color="yellow">Jaune</button>
    <button class="dropdown-item" style="background-color: orange;" data-color="orange">Orange</button>
    <button class="dropdown-item" style="background-color: purple;" data-color="purple">Violet</button>
    <button class="dropdown-item" style="background-color: pink;" data-color="pink">Rose</button>
    <button class="dropdown-item" style="background-color: brown;" data-color="brown">Marron</button>
    <button class="dropdown-item" style="background-color: cyan;" data-color="cyan">Cyan</button>
    <button class="dropdown-item" style="background-color: gray;" data-color="gray">Gris</button>
</div>

<!-- Range Selection Modal Structure -->
<div class="modal fade" id="rangeSelectionModal" tabindex="-1" aria-labelledby="rangeSelectionModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="rangeSelectionModalLabel">Sélection de Plage</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="startCellId">Cellule de Départ</label>
                    <input type="text" class="form-control" id="startCellId" disabled>
                </div>
                <div class="form-group">
                    <label for="endCellId">Cellule de Fin</label>
                    <input type="text" class="form-control" id="endCellId">
                </div>
                <div class="form-group">
                    <label for="rangeComboBox">Sélectionnez une valeur</label>
                    <select class="form-control" id="rangeComboBox">
                        <!-- Les options seront ajoutées ici par JavaScript -->
                    </select>
                </div>
                <div id="rangeResult" class="form-group">
                    <!-- Le résultat de la soustraction sera affiché ici -->
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" id="cancelRangeSelection">Annuler</button>
                <button type="button" class="btn btn-primary" id="confirmRangeSelection">Valider</button>
            </div>
        </div>
    </div>
</div>

<div class="table-wrapper">
    <table>
        <thead>
            <tr>
                <th></th>
                <th>plouf</th>
                <th>cretin</th>
                <?php foreach ($workingDays as $dateData): ?>
                    <th>
                        <?php echo $dateData['day']; ?> <br>
                    </th>
                <?php endforeach; ?>
            </tr>

            <tr class="second-header">
                <th></th>
                <th>Valeur 1</th>
                <th>Valeur 2</th>
                <?php
                $currentWeek = null;
                $weekClass = "";

                foreach ($workingDays as $dateData):
                    if ($currentWeek !== $dateData['week_number']) {
                        $currentWeek = $dateData['week_number'];
                        $weekClass = ($currentWeek % 2 === 0) ? 'even-week' : 'odd-week';
                    }
                    ?>
                    <th class="<?= $weekClass; ?>"><?php echo $dateData['day_of_week_initial']; ?></th>
                <?php endforeach; ?>
            </tr>

            <tr class="third-header">
                <th></th>
                <th>Info 1</th>
                <th>Info 2</th>
                <?php
                $currentWeek = null;
                $colspan = 0;
                foreach ($workingDays as $index => $dateData):
                    if ($currentWeek !== $dateData['week_number']) {
                        if ($currentWeek !== null) {
                            $weekClass = $currentWeek % 2 === 0 ? 'even-week' : 'odd-week';
                            echo '<th class="' . $weekClass . '" colspan="' . $colspan . '">' . $currentWeek . '</th>';
                        }
                        $currentWeek = $dateData['week_number'];
                        $colspan = 1;
                    } else {
                        $colspan++;
                    }
                endforeach;
                if ($currentWeek !== null) {
                    $weekClass = $currentWeek % 2 === 0 ? 'even-week' : 'odd-week';
                    echo '<th class="' . $weekClass . '" colspan="' . $colspan . '">' . $currentWeek . '</th>';
                }
                ?>
            </tr>

            <tr class="fourth-header">
                <th></th>
                <th>Label 1</th>
                <th>Label 2</th>
                <?php
                $currentMonthYear = null;
                $colspan = 0;
                $monthClass = "";
                $colorIndex = 0;
                $colors = ['month-even', 'month-odd'];

                foreach ($workingDays as $index => $dateData):
                    $monthYear = ucfirst(strftime("%B %Y", strtotime($dateData['full_date'])));

                    if ($currentMonthYear !== $monthYear) {
                        if ($currentMonthYear !== null) {
                            echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>';
                        }
                        $currentMonthYear = $monthYear;
                        $colspan = 1;
                        $monthClass = $colors[$colorIndex % 2];
                        $colorIndex++;
                    } else {
                        $colspan++;
                    }
                endforeach;

                if ($currentMonthYear !== null) {
                    echo '<th class="' . $monthClass . '" colspan="' . $colspan . '">' . $currentMonthYear . '</th>';
                }
                ?>
            </tr>
        </thead>

        <tbody>
        </tbody>
    </table>
</div>

<button id="addRowButton" class="btn">Ajouter une ligne</button>
<button id="addSpecialRowButton" class="btn btn-special">Ajouter une ligne spéciale</button>
<button id="testButton" class="btn">TEST</button> <!-- Nouveau bouton TEST -->
<button id="queryButton" class="btn">Query</button> <!-- Nouveau bouton Query -->
<button id="memButton" class="btn">Mem</button> <!-- Nouveau bouton Mem -->
<!--
<button id="saveToDBButton" class="btn">Save to DB</button>
-->
<!--
<button id="traceButton" class="btn">Trace</button>
-->
<!--
<button id="loadFromDBButton" class="btn">Load from DB</button>
-->
<!--
<button id="runButton" class="btn">RUN</button>
-->
<button id="saveButton" class="btn">Save</button>
<button id="readButton" class="btn">Read</button>
<button id="logButton" class="btn">Log</button> <!-- Nouveau bouton Log -->
<div id="generatedDataOutput"></div>

<div id="jsonOutput"></div>
<div id="debugOutput"></div>
<!--
<div id="logOutput"></div>
            -->
<!-- Zone de visualisation pour le log -->

<script>
document.addEventListener("DOMContentLoaded", function () {
    const tableBody = document.querySelector("tbody");
    let specialRowCounter = 1;
    let rowCounter = 1; // Compteur pour les identifiants uniques des lignes
    let linkageCounter = 1; // Compteur pour les identifiants uniques des liaisons
    const specialRowStates = {}; // Objet pour stocker l'état des lignes spéciales
    const associations = {}; // Objet pour stocker les associations entre lignes spéciales et standards
    const linkages = []; // Tableau pour stocker les objets de liaison
    const standardRowsData = []; // Tableau pour stocker les objets de ligne standard
    const estimationRowsData = []; // Tableau pour stocker les objets de ligne d'estimation
    let currentCell = null;

    const contextMenu = document.createElement("div");
    contextMenu.id = "contextMenu";
    contextMenu.classList.add("dropdown-menu");
    contextMenu.style.display = "none";
    document.body.appendChild(contextMenu);

    const specialContextMenu = document.createElement("div");
    specialContextMenu.id = "specialContextMenu";
    specialContextMenu.classList.add("dropdown-menu");
    specialContextMenu.style.display = "none";
    document.body.appendChild(specialContextMenu);

    const colorContextMenu = document.getElementById("colorContextMenu");
    const colorButtons = colorContextMenu.querySelectorAll(".dropdown-item");

    colorButtons.forEach(button => {
        button.addEventListener("click", function () {
            const color = this.getAttribute("data-color");
            const cell = document.querySelector(".selected-cell");
            if (cell) {
                cell.style.backgroundColor = color;
                cell.dataset.cellColor = color; // Mettre à jour l'attribut de données
                hideColorContextMenu();
            }
        });
    });

    function addRow(afterRow = null) {
        const rowNumber = tableBody.rows.length + 1;
        const newRow = document.createElement("tr");
        newRow.setAttribute("draggable", "true");
        newRow.dataset.rowId = `standard-row-${rowCounter}`; // Attribuer un identifiant unique

        // Créer un objet pour stocker les valeurs par défaut de la ligne standard
        const rowData = {
            id: newRow.dataset.rowId,
            name: `Row ${rowNumber}`,
            selectValue: "1",
            count: "0",
            cells: []
        };

        const firstCells = ["Row " + rowNumber, "", "0"];
        firstCells.forEach((text, index) => {
            const td = document.createElement("td");
            td.dataset.cellId = `cell-${rowCounter}-${index}`; // Attribuer un identifiant unique à chaque cellule
            if (index === 0) {
                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = rowData.name;
                input.addEventListener("click", function (event) {
                    event.stopPropagation();
                    input.focus();
                    input.style.width = "130px"; // Augmenter la largeur de l'input
                    //displayRowId(newRow); // Afficher l'identifiant de la ligne
                });
                input.addEventListener("blur", function () {
                    input.classList.remove("editing");
                    input.style.width = "65px"; // Restaurer la largeur d'origine
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px"; // Restaurer la largeur d'origine
                    }
                });
                td.appendChild(input);
            } else if (index === 1) {
                const select = document.createElement("select");
                for (let i = 1; i <= 10; i++) {
                    const option = document.createElement("option");
                    option.value = i;
                    option.textContent = `Option ${i}`;
                    select.appendChild(option);
                }
                select.value = rowData.selectValue;
                td.appendChild(select);
            } else {
                td.textContent = text;
            }

            if (index === 0) {
                td.classList.add("row-header");
                td.addEventListener("contextmenu", function (event) {
                    event.preventDefault();
                    showContextMenu(event, newRow);
                });
            }

            newRow.appendChild(td);
        });

        const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
        const workingDaysCount = headerCells.length;

        for (let i = 0; i < workingDaysCount - 3; i++) {
            const td = document.createElement("td");
            td.dataset.cellId = `cell-${rowCounter}-${i}`; // Attribuer un identifiant unique en commençant à l'indice 0
            td.dataset.cellValue = "0"; // Stocker la valeur dans un attribut de données
            td.dataset.cellColor = "white"; // Stocker la couleur de fond dans un attribut de données
            td.textContent = "0";
            td.style.backgroundColor = "white";

            td.addEventListener("click", function () {
                const newValue = td.dataset.cellValue === "0" ? "1" : "0";
                td.dataset.cellValue = newValue;
                td.textContent = newValue;
                td.style.backgroundColor = newValue === "1" ? "green" : "white";
                td.dataset.cellColor = newValue === "1" ? "green" : "white";
                updateCountCell(newRow);

                // Mettre à jour l'objet de la ligne
                rowData.cells[i] = { value: newValue, color: td.dataset.cellColor };
            });

            td.addEventListener("contextmenu", function (event) {
                event.preventDefault();
                if (td.dataset.cellValue === "1") {
                    showColorContextMenu(event, td);
                }
            });

            // Ajouter l'attribut title pour l'info-bulle uniquement pour les cellules des jours de travail
            td.title = `ID: ${td.dataset.cellId}`;

            newRow.appendChild(td);

            // Initialiser les cellules dans l'objet rowData
            rowData.cells[i] = { value: "0", color: "white" };
        }

        if (afterRow) {
            tableBody.insertBefore(newRow, afterRow.nextSibling);
        } else {
            tableBody.appendChild(newRow);
        }

        newRow.addEventListener("dragstart", dragStart);
        newRow.addEventListener("dragover", dragOver);
        newRow.addEventListener("drop", drop);

        rowCounter++; // Incrémenter le compteur pour le prochain identifiant

        // Ajouter l'objet de la ligne au tableau
        standardRowsData.push(rowData);

        // Ajouter une ligne d'estimation
        const estimationRow = document.createElement("tr");
        estimationRow.setAttribute("draggable", "true");
        estimationRow.dataset.rowId = `estimation-row-${rowCounter}`; // Attribuer un identifiant unique
        estimationRow.classList.add("estimation-row");

        // Créer un objet pour stocker les valeurs par défaut de la ligne d'estimation
        const estimationRowData = {
            id: estimationRow.dataset.rowId,
            name: `Estimation ${rowNumber}`,
            selectValue: "1",
            estimationValue: "0"
        };

        const estimationFirstCells = [`Estimation ${rowNumber}`, "", "0"];
        estimationFirstCells.forEach((text, index) => {
            const td = document.createElement("td");
            td.dataset.cellId = `cell-${rowCounter}-${index}`; // Attribuer un identifiant unique à chaque cellule
            if (index === 0) {
                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = estimationRowData.name;
                input.addEventListener("click", function (event) {
                    event.stopPropagation();
                    input.focus();
                    input.style.width = "130px"; // Augmenter la largeur de l'input
                    //displayRowId(newRow); // Afficher l'identifiant de la ligne
                });
                input.addEventListener("blur", function () {
                    input.classList.remove("editing");
                    input.style.width = "65px"; // Restaurer la largeur d'origine
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px"; // Restaurer la largeur d'origine
                    }
                });
                td.appendChild(input);
            } else if (index === 1) {
                const select = document.createElement("select");
                for (let i = 1; i <= 10; i++) {
                    const option = document.createElement("option");
                    option.value = i;
                    option.textContent = `Option ${i}`;
                    select.appendChild(option);
                }
                select.value = estimationRowData.selectValue;
                td.appendChild(select);
            } else {
                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = text;
                input.addEventListener("blur", function () {
                    const value = parseInt(input.value, 10);
                    if (isNaN(value) || value < 1 || value > 365) {
                        input.value = "0"; // Réinitialiser la valeur si elle n'est pas valide
                        showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                    }
                });
                td.appendChild(input);
            }

            if (index === 0) {
                td.classList.add("row-header");
                td.addEventListener("contextmenu", function (event) {
                    event.preventDefault();
                    showContextMenu(event, estimationRow);
                });
            }

            estimationRow.appendChild(td);
        });

        // Ajouter une cellule fusionnée pour les cellules entre la quatrième et la dernière
        const mergedCell = document.createElement("td");
        mergedCell.colSpan = workingDaysCount - 3; // Fusionner toutes les cellules entre la quatrième et la dernière
        mergedCell.textContent = ""; // Aucune valeur à l'intérieur
        mergedCell.classList.add("no-click");
        estimationRow.appendChild(mergedCell);

        if (afterRow) {
            tableBody.insertBefore(estimationRow, newRow.nextSibling);
        } else {
            tableBody.appendChild(estimationRow);
        }

        estimationRow.addEventListener("dragstart", dragStart);
        estimationRow.addEventListener("dragover", dragOver);
        estimationRow.addEventListener("drop", drop);

        // Créer un objet de liaison et l'ajouter au tableau
        const linkage = {
            id: `linkage-${linkageCounter}`, // Attribuer un identifiant unique
            standardRowId: newRow.dataset.rowId,
            estimationRowId: estimationRow.dataset.rowId
        };
        linkages.push(linkage);

        // Afficher le contenu du tableau de liaisons dans la zone d'affichage texte
        displayLinkages();

        rowCounter++; // Incrémenter le compteur pour le prochain identifiant
        linkageCounter++; // Incrémenter le compteur pour le prochain identifiant de liaison

        // Ajouter l'objet de la ligne d'estimation au tableau
        estimationRowsData.push(estimationRowData);
    }

    function displayLinkages() {
        const debugOutputElement = document.getElementById("debugOutput");
        debugOutputElement.textContent = JSON.stringify(linkages, null, 2);
    }

    function updateCountCell(row) {
        const countCell = row.cells[2];
        const count = Array.from(row.cells).slice(3).filter(cell => cell.dataset.cellValue === "1").length;
        countCell.textContent = count;
    }

    function addSpecialRow(afterRow = null) {
        const newRow = document.createElement("tr");
        newRow.classList.add("special-row");
        newRow.setAttribute("draggable", "true");
        newRow.dataset.rowId = `special-row-${specialRowCounter}`; // Attribuer un identifiant unique

        const firstCell = document.createElement("td");
        firstCell.classList.add("row-header");

        const input = document.createElement("input");
        input.type = "text";
        input.classList.add("editable-input");
        input.placeholder = `Ligne spéciale ${specialRowCounter}`;
        input.addEventListener("click", function (event) {
            event.stopPropagation();
            input.focus();
            input.style.width = "130px"; // Augmenter la largeur de l'input
            //displayRowId(newRow); // Afficher l'identifiant de la ligne
        });
        input.addEventListener("blur", function () {
            input.classList.remove("editing");
            input.style.width = "65px"; // Restaurer la largeur d'origine
        });
        input.addEventListener("keydown", function (event) {
            if (event.key === "Escape" || event.key === "Enter") {
                input.classList.remove("editing");
                input.blur();
                input.style.width = "65px"; // Restaurer la largeur d'origine
            }
        });

        const addButton = document.createElement("button");
        addButton.classList.add("add-button");
        addButton.textContent = "+";
        addButton.addEventListener("click", function () {
            toggleCollapse(newRow);
        });

        firstCell.appendChild(input);
        firstCell.appendChild(addButton);
        firstCell.addEventListener("contextmenu", function (event) {
            event.preventDefault();
            showSpecialContextMenu(event, newRow);
        });

        newRow.appendChild(firstCell);

        // Supprimer la deuxième cellule et modifier la troisième cellule pour qu'elle soit vide et ait un colspan de 2
        const mergedCell = document.createElement("td");
        mergedCell.colSpan = 2;
        mergedCell.textContent = "";
        newRow.appendChild(mergedCell);

        const td = document.createElement("td");
        td.textContent = `Ligne spéciale ${specialRowCounter} - Détails`;
        td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3;
        newRow.appendChild(td);

        if (afterRow) {
            tableBody.insertBefore(newRow, afterRow.nextSibling);
        } else {
            tableBody.appendChild(newRow);
        }

        newRow.addEventListener("dragstart", dragStart);
        newRow.addEventListener("dragover", dragOver);
        newRow.addEventListener("drop", drop);

        specialRowCounter++;
    }

    function displayRowId(row) {
        const rowId = row.dataset.rowId;
        alert(`Identifiant de la ligne : ${rowId}`);
    }

    function toggleCollapse(specialRow) {
        const nextSpecialRow = getNextSpecialRow(specialRow);
        const rowsToToggle = [];
        let currentRow = specialRow.nextElementSibling;

        while (currentRow && currentRow !== nextSpecialRow) {
            if (!currentRow.classList.contains("special-row")) {
                rowsToToggle.push(currentRow);
            }
            currentRow = currentRow.nextElementSibling;
        }

        rowsToToggle.forEach(row => {
            row.classList.toggle("collapsed");
        });
    }

    function getNextSpecialRow(specialRow) {
        let currentRow = specialRow.nextElementSibling;
        while (currentRow) {
            if (currentRow.classList.contains("special-row")) {
                return currentRow;
            }
            currentRow = currentRow.nextElementSibling;
        }
        return null;
    }

    function showContextMenu(event, row) {
        contextMenu.innerHTML = `
            <button class="dropdown-item" id="add-row">Ajouter une ligne</button>
            <button class="dropdown-item text-danger" id="delete-row">Supprimer cette ligne</button>
            <button class="dropdown-item" id="show-linkage">Afficher la liaison</button>
        `;

        contextMenu.style.top = `${event.clientY}px`;
        contextMenu.style.left = `${event.clientX}px`;
        contextMenu.style.display = "flex";
        contextMenu.style.flexDirection = "column";

        document.getElementById("add-row").addEventListener("click", function () {
            addRow(row);
            hideContextMenu();
        });

        document.getElementById("delete-row").addEventListener("click", function () {
            showConfirmationModal(row);
            hideContextMenu();
        });

        document.getElementById("show-linkage").addEventListener("click", function () {
            const linkage = linkages.find(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId);
            if (linkage) {
                alert(`Liaison trouvée :\nID: ${linkage.id}\nLigne standard: ${linkage.standardRowId}\nLigne estimation: ${linkage.estimationRowId}`);
            } else {
                alert("Aucune liaison trouvée pour cette ligne.");
            }
            hideContextMenu();
        });
    }

    function showSpecialContextMenu(event, row) {
        specialContextMenu.innerHTML = `
            <button class="dropdown-item" id="add-special-row">Ajouter une ligne spéciale</button>
            <button class="dropdown-item text-danger" id="delete-special-row">Supprimer cette ligne</button>
            <label class="dropdown-item">
                <input type="checkbox" id="special-checkbox"> Attacher
            </label>
        `;

        specialContextMenu.style.top = `${event.clientY}px`;
        specialContextMenu.style.left = `${event.clientX}px`;
        specialContextMenu.style.display = "flex";
        specialContextMenu.style.flexDirection = "column";

        const checkbox = document.getElementById("special-checkbox");
        const rowId = row.dataset.rowId;

        // Vérifier s'il y a des lignes standards immédiatement en dessous de la ligne spéciale
        let hasStandardRowsBelow = false;
        let currentRow = row.nextElementSibling;
        const standardRows = [];
        while (currentRow && !currentRow.classList.contains("special-row")) {
            if (!currentRow.classList.contains("special-row")) {
                hasStandardRowsBelow = true;
                standardRows.push(currentRow);
            }
            currentRow = currentRow.nextElementSibling;
        }

        if (hasStandardRowsBelow) {
            checkbox.disabled = false;
        } else {
            checkbox.disabled = true;
            checkbox.checked = false;
        }

        // Restaurer l'état de la case à cocher
        if (specialRowStates[rowId]) {
            checkbox.checked = specialRowStates[rowId].checked;
        }

        checkbox.addEventListener("change", function () {
            specialRowStates[rowId] = {
                checked: checkbox.checked,
                rows: standardRows
            };

            standardRows.forEach(standardRow => {
                const firstCell = standardRow.querySelector("td:first-child");
                if (checkbox.checked) {
                    firstCell.style.backgroundColor = "yellow";
                    standardRow.classList.add("no-drag");
                } else {
                    firstCell.style.backgroundColor = "";
                    standardRow.classList.remove("no-drag");
                }
            });

            // Créer ou mettre à jour l'association
            if (checkbox.checked) {
                associations[rowId] = standardRows.map(row => row.dataset.rowId);
            } else {
                delete associations[rowId];
            }

            console.log(`Lignes standards concernées : ${standardRows.map(row => row.rowIndex).join(", ")}`);
        });

        document.getElementById("add-special-row").addEventListener("click", function () {
            addSpecialRow(row);
            hideSpecialContextMenu();
        });

        document.getElementById("delete-special-row").addEventListener("click", function () {
            showConfirmationModal(row);
            hideSpecialContextMenu();
        });
    }

    function showColorContextMenu(event, cell) {
        colorContextMenu.style.top = `${event.clientY}px`;
        colorContextMenu.style.left = `${event.clientX}px`;
        colorContextMenu.style.display = "flex";
        colorContextMenu.style.flexDirection = "column";

        // Marquer la cellule comme sélectionnée
        document.querySelectorAll(".selected-cell").forEach(c => c.classList.remove("selected-cell"));
        cell.classList.add("selected-cell");
    }

    function queryTableData() {
        const tableData = [];
        const rows = tableBody.querySelectorAll("tr");

        rows.forEach(row => {
            const rowData = {};
            const cells = row.querySelectorAll("td");

            if (row.dataset.rowId.startsWith("special-row-")) {
                // Si c'est une ligne spéciale, prendre uniquement l'identifiant et le contenu de l'input text
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
            } else if (row.dataset.rowId.startsWith("estimation-row-")) {
                // Si c'est une ligne d'estimation, prendre l'identifiant et la valeur de l'input text
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
                rowData.estimationValue = cells[2].querySelector("input").value; // Ajouter la valeur d'estimation
                rowData.selectValue = cells[1].querySelector("select").value; // Ajouter la valeur de la combo box
            } else {
                // Pour les lignes standards, prendre toutes les cellules
                rowData.id = row.dataset.rowId;
                rowData.name = cells[0].querySelector("input").value;
                rowData.selectValue = cells[1].querySelector("select").value;
                rowData.count = cells[2].textContent.trim();
                rowData.cells = [];

                cells.forEach((cell, index) => {
                    if (index > 2) {
                        rowData.cells.push({
                            value: cell.dataset.cellValue,
                            color: cell.dataset.cellColor
                        });
                    }
                });
            }

            tableData.push(rowData);
        });

        displayQueryData(tableData);
    }

    function displayQueryData(data) {
        const debugOutputElement = document.getElementById("debugOutput");
        const queryDataText = data.map(rowData => {
            if (rowData.id.startsWith("special-row-")) {
                return `ID: ${rowData.id}\nName: ${rowData.name}\n`;
            } else if (rowData.id.startsWith("estimation-row-")) {
                return `ID: ${rowData.id}\nName: ${rowData.name}\nEstimation Value: ${rowData.estimationValue}\nSelect Value: ${rowData.selectValue}\n`;
            } else {
                return `ID: ${rowData.id}\nName: ${rowData.name}\nSelect Value: ${rowData.selectValue}\nCount: ${rowData.count}\nCells: ${rowData.cells ? rowData.cells.map(cell => `${cell.value} (${cell.color})`).join(", ") : ""}\n`;
            }
        }).join("\n");
        debugOutputElement.textContent = queryDataText;
    }

    function showConfirmationModal(row) {
        const modal = new bootstrap.Modal(document.getElementById('confirmationModal'));
        modal.show();

        document.getElementById('confirmDelete').addEventListener('click', function () {
            //const estimationRow = row.nextElementSibling.classList.contains("estimation-row") ? row.nextElementSibling : row.previousElementSibling;
            //row.remove();
            //estimationRow.remove();

            // Trouver l'index de l'objet liaison dans le tableau linkages
            const linkageIndex = linkages.findIndex(link => link.standardRowId === row.dataset.rowId || link.estimationRowId === row.dataset.rowId);

            if (linkageIndex !== -1) {
                // Supprimer l'objet du tableau linkages
                linkages.splice(linkageIndex, 1);
            }

            // Régénérer le tableau après la suppression
            regenerateTableAfterDeletion();

            // Afficher les contenus des cellules de la ligne standard et de la ligne d'estimation
            logRowContents(row);
            const estimationRow = row.nextElementSibling.classList.contains("estimation-row") ? row.nextElementSibling : row.previousElementSibling;

            console.log(">>>>>> " + estimationRow);

            logRowContents(estimationRow);

            modal.hide();
        });

        document.getElementById('cancelDelete').addEventListener('click', function () {
            modal.hide();
        });
    }

    function regenerateTableAfterDeletion() {
        // Vider le contenu actuel du tableau
        tableBody.innerHTML = "";

        // Parcourir les objets de liaison restants et ajouter les lignes correspondantes
        linkages.forEach(linkage => {
            // Ajouter la ligne standard
            const standardRow = document.createElement("tr");
            standardRow.setAttribute("draggable", "true");
            standardRow.dataset.rowId = linkage.standardRowId;

            const firstCells = ["Row", "", "0"];
            firstCells.forEach((text, index) => {
                const td = document.createElement("td");
                td.dataset.cellId = `cell-${linkage.standardRowId}-${index}`;
                if (index === 0) {
                    const input = document.createElement("input");
                    input.type = "text";
                    input.classList.add("editable-input");
                    input.addEventListener("click", function (event) {
                        event.stopPropagation();
                        input.focus();
                        input.style.width = "130px";
                    });
                    input.addEventListener("blur", function () {
                        input.classList.remove("editing");
                        input.style.width = "65px";
                    });
                    input.addEventListener("keydown", function (event) {
                        if (event.key === "Escape" || event.key === "Enter") {
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                        }
                    });
                    td.appendChild(input);
                } else if (index === 1) {
                    const select = document.createElement("select");
                    for (let i = 1; i <= 10; i++) {
                        const option = document.createElement("option");
                        option.value = i;
                        option.textContent = `Option ${i}`;
                        select.appendChild(option);
                    }
                    td.appendChild(select);
                } else {
                    td.textContent = text;
                }

                if (index === 0) {
                    td.classList.add("row-header");
                    td.addEventListener("contextmenu", function (event) {
                        event.preventDefault();
                        showContextMenu(event, standardRow);
                    });
                }

                standardRow.appendChild(td);
            });

            const headerCells = document.querySelectorAll("thead tr:nth-child(2) th:not(.weekend):not(.holiday)");
            const workingDaysCount = headerCells.length;

            for (let i = 0; i < workingDaysCount - 3; i++) {
                const td = document.createElement("td");
                td.dataset.cellId = `cell-${linkage.standardRowId}-${i}`;
                td.dataset.cellValue = "0";
                td.dataset.cellColor = "white";
                td.textContent = "0";
                td.style.backgroundColor = "white";

                td.addEventListener("click", function () {
                    const newValue = td.dataset.cellValue === "0" ? "1" : "0";
                    td.dataset.cellValue = newValue;
                    td.textContent = newValue;
                    td.style.backgroundColor = newValue === "1" ? "green" : "white";
                    td.dataset.cellColor = newValue === "1" ? "green" : "white";
                    updateCountCell(standardRow);
                });

                td.addEventListener("contextmenu", function (event) {
                    event.preventDefault();
                    if (td.dataset.cellValue === "1") {
                        showColorContextMenu(event, td);
                    }
                });

                td.title = `ID: ${td.dataset.cellId}`;

                standardRow.appendChild(td);
            }

            tableBody.appendChild(standardRow);

            standardRow.addEventListener("dragstart", dragStart);
            standardRow.addEventListener("dragover", dragOver);
            standardRow.addEventListener("drop", drop);

            // Ajouter la ligne d'estimation
            const estimationRow = document.createElement("tr");
            estimationRow.setAttribute("draggable", "true");
            estimationRow.dataset.rowId = linkage.estimationRowId;
            estimationRow.classList.add("estimation-row");

            const estimationFirstCells = ["Estimation", "", "0"];
            estimationFirstCells.forEach((text, index) => {
                const td = document.createElement("td");
                td.dataset.cellId = `cell-${linkage.estimationRowId}-${index}`;
                if (index === 0) {
                    const input = document.createElement("input");
                    input.type = "text";
                    input.classList.add("editable-input");
                    input.value = "Estimation";
                    input.addEventListener("click", function (event) {
                        event.stopPropagation();
                        input.focus();
                        input.style.width = "130px";
                    });
                    input.addEventListener("blur", function () {
                        input.classList.remove("editing");
                        input.style.width = "65px";
                    });
                    input.addEventListener("keydown", function (event) {
                        if (event.key === "Escape" || event.key === "Enter") {
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                        }
                    });
                    td.appendChild(input);
                } else if (index === 1) {
                    const select = document.createElement("select");
                    for (let i = 1; i <= 10; i++) {
                        const option = document.createElement("option");
                        option.value = i;
                        option.textContent = `Option ${i}`;
                        select.appendChild(option);
                    }
                    td.appendChild(select);
                } else {
                    const input = document.createElement("input");
                    input.type = "text";
                    input.classList.add("editable-input");
                    input.value = text;
                    input.addEventListener("blur", function () {
                        const value = parseInt(input.value, 10);
                        if (isNaN(value) || value < 1 || value > 365) {
                            input.value = "0";
                            showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                        }
                    });
                    td.appendChild(input);
                }

                if (index === 0) {
                    td.classList.add("row-header");
                    td.addEventListener("contextmenu", function (event) {
                        event.preventDefault();
                        showContextMenu(event, estimationRow);
                    });
                }

                estimationRow.appendChild(td);
            });

            const mergedCell = document.createElement("td");
            mergedCell.colSpan = workingDaysCount - 3;
            mergedCell.textContent = "";
            mergedCell.classList.add("no-click");
            estimationRow.appendChild(mergedCell);

            tableBody.appendChild(estimationRow);

            estimationRow.addEventListener("dragstart", dragStart);
            estimationRow.addEventListener("dragover", dragOver);
            estimationRow.addEventListener("drop", drop);
        });

        // Mettre à jour le contenu du tableau de liaisons dans la zone d'affichage texte
        displayLinkages();
    }

    function showMessageModal(message) {
        const modal = new bootstrap.Modal(document.getElementById('messageModal'));
        const modalBody = document.getElementById('messageModalBody');
        modalBody.textContent = message;
        modal.show();
    }

    document.addEventListener("click", function (event) {
        if (!contextMenu.contains(event.target)) {
            hideContextMenu();
        }
        if (!specialContextMenu.contains(event.target)) {
            hideSpecialContextMenu();
        }
        if (!colorContextMenu.contains(event.target)) {
            hideColorContextMenu();
        }
        const inputs = document.querySelectorAll(".editable-input");
        inputs.forEach(input => {
            if (!input.contains(event.target)) {
                input.classList.remove("editing");
            }
        });
    });

    // Ajouter un gestionnaire d'événements pour écouter les événements de touche
    document.addEventListener("keydown", function (event) {
        if (event.key === "Escape") {
            hideContextMenu();
            hideSpecialContextMenu();
            hideColorContextMenu();
        }
    });

    function hideContextMenu() {
        contextMenu.style.display = "none";
    }

    function hideSpecialContextMenu() {
        specialContextMenu.style.display = "none";
    }

    function hideColorContextMenu() {
        colorContextMenu.style.display = "none";
    }

    document.getElementById("addRowButton").addEventListener("click", addRow);
    document.getElementById("addSpecialRowButton").addEventListener("click", addSpecialRow);

    document.getElementById("testButton").addEventListener("click", function () {
        // Exemple de comportement : afficher une alerte
        alert("Le bouton TEST a été cliqué !");

        fetch("get_values.php")
            .then(response => response.json())
            .then(data => {
                // Traiter les données reçues
                console.log("Données reçues :", data);
                // Vous pouvez ajouter ici le comportement souhaité pour traiter les données
                displayValues(data);
            })
            .catch(error => {
                console.error("Erreur lors de la récupération des données :", error);
                showMessageModal("Une erreur est survenue lors de la récupération des données.");
            });

        // Vous pouvez ajouter ici le comportement souhaité pour le bouton TEST
    });

    function displayValues(data) {
        // Exemple de fonction pour afficher les valeurs reçues
        const jsonOutputElement = document.getElementById("jsonOutput");
        const valuesText = data.map(row => row.join(", ")).join("\n");
        jsonOutputElement.textContent = valuesText;
    }

    document.querySelectorAll("tbody tr td:first-child").forEach(td => {
        td.addEventListener("contextmenu", function (event) {
            event.preventDefault();
            showContextMenu(event, td.parentElement);
        });
    });

    function dragStart(event) {
        const row = event.target.closest("tr");
        if (row.classList.contains("no-drag")) {
            event.preventDefault();
            return;
        }

        event.dataTransfer.setData("text/plain", row.rowIndex);
        row.classList.add("dragging");
    }

    function dragOver(event) {
        event.preventDefault();
        const draggingRow = document.querySelector(".dragging");
        const targetRow = event.target.closest("tr");

        if (targetRow && draggingRow !== targetRow && !targetRow.classList.contains("no-drag")) {
            const rect = targetRow.getBoundingClientRect();
            const offset = rect.top + (rect.height / 2);
            if (event.clientY - offset > 0) {
                tableBody.insertBefore(draggingRow, targetRow.nextSibling);
            } else {
                tableBody.insertBefore(draggingRow, targetRow);
            }
        }
    }

    function drop(event) {
        event.preventDefault();
        const draggingRow = document.querySelector(".dragging");
        draggingRow.classList.remove("dragging");

        // Si la ligne est une ligne spéciale, déplacer les lignes standards associées
        if (draggingRow.classList.contains("special-row")) {
            const specialRowId = draggingRow.dataset.rowId;
            if (associations[specialRowId]) {
                const associatedRowIds = associations[specialRowId];
                associatedRowIds.forEach(rowId => {
                    const associatedRow = document.querySelector(`tr[data-row-id="${rowId}"]`);
                    if (associatedRow) {
                        tableBody.insertBefore(associatedRow, draggingRow.nextSibling);
                    }
                });
            }
        }
    }

    function traceTable() {
        const tableData = [];
        const rows = tableBody.querySelectorAll("tr");

        rows.forEach(row => {
            const rowData = {}; // Créer un objet pour chaque ligne
            const cells = row.querySelectorAll("td");

            if (row.dataset.rowId.startsWith("special-row-")) {
                // Si c'est une ligne spéciale, prendre uniquement l'identifiant et le contenu de l'input text
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
            } else if (row.dataset.rowId.startsWith("estimation-row-")) {
                // Si c'est une ligne d'estimation, prendre l'identifiant et la valeur de l'input text
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
                rowData.estimationValue = cells[2].querySelector("input").value; // Ajouter la valeur d'estimation
                rowData.selectValue = cells[1].querySelector("select").value; // Ajouter la valeur de la combo box
            } else {
                // Pour les lignes standards, prendre toutes les cellules
                rowData.id = row.dataset.rowId;
                rowData.name = cells[0].querySelector("input").value;
                rowData.selectValue = cells[1].querySelector("select").value;
                rowData.count = cells[2].textContent.trim();
                rowData.cells = [];

                cells.forEach((cell, index) => {
                    if (index > 2) {
                        rowData.cells.push({
                            value: cell.dataset.cellValue,
                            color: cell.dataset.cellColor
                        });
                    }
                });
            }

            tableData.push(rowData); // Ajouter l'objet de la ligne au tableau global
        });

        return tableData; // Retourner les données du tableau
    }

    function saveToDB() {
        const tableData = traceTable(); // Utiliser traceTable pour obtenir les données du tableau

        if (tableData.length === 0) {
            // Afficher une fenêtre modale pour signaler que le tableau est vide
            const modal = new bootstrap.Modal(document.getElementById('messageModal'));
            const modalBody = document.getElementById('messageModalBody');
            modalBody.textContent = "Le tableau est vide. Veuillez ajouter des lignes avant de sauvegarder.";
            modal.show();
            return;
        }

        fetch("save_mysql.php", {
            method: "POST",
            headers: {
                "Content-Type": "application/json"
            },
            body: JSON.stringify(tableData) // Envoyer les données sous forme de JSON
        })
        .then(response => response.json())
        .then(data => {
            if (data.status === "success") {
                showMessageModal("Données sauvegardées avec succès !");
            } else {
                showMessageModal("Une erreur est survenue lors de la sauvegarde des données.");
            }
        })
        .catch(error => {
            console.error("Erreur :", error);
            showMessageModal("Une erreur est survenue lors de la sauvegarde des données.");
        });
    }

    function loadFromDB() {
        fetch("load_mysql.php")
            .then(response => response.json())
            .then(data => {
                regenerateTable(data);
                displayTableData(data);
                displayJSONData(data); // Afficher les données au format JSON
            })
            .catch(error => {
                console.error("Erreur :", error);
                showMessageModal("Une erreur est survenue lors du chargement des données.");
            });
    }

    function displayJSONData(data) {
        const jsonOutputElement = document.getElementById("jsonOutput");
        const jsonOutput = JSON.stringify(data, null, 2); // Convertir les données en JSON formaté
        jsonOutputElement.textContent = jsonOutput; // Afficher le contenu JSON au format texte
    }

    function regenerateTable(data) {
        tableBody.innerHTML = ""; // Vider le contenu actuel du tableau

        data.forEach(rowData => {
            const rowId = rowData.id;
            if (rowId.startsWith("special-row-")) {
                addSpecialRow();
                const specialRow = tableBody.lastElementChild;
                specialRow.dataset.rowId = rowId;
                specialRow.querySelector("input").value = rowData.name;
            } else if (rowId.startsWith("estimation-row-")) {
                addRow();
                const estimationRow = tableBody.lastElementChild;
                estimationRow.dataset.rowId = rowId;
                const cells = estimationRow.querySelectorAll("td");
                cells[0].querySelector("input").value = rowData.name;
                cells[1].querySelector("select").value = rowData.selectValue;
                cells[2].querySelector("input").value = rowData.estimationValue; // Ajouter la valeur d'estimation
            } else {
                addRow();
                const standardRow = tableBody.lastElementChild;
                standardRow.dataset.rowId = rowId;
                const cells = standardRow.querySelectorAll("td");
                cells[0].querySelector("input").value = rowData.name;
                cells[1].querySelector("select").value = rowData.selectValue;
                cells[2].textContent = rowData.count;
                rowData.cells.forEach((cellData, index) => {
                    const cell = cells[index + 3];
                    cell.dataset.cellValue = cellData.value;
                    cell.dataset.cellColor = cellData.color;
                    cell.textContent = cellData.value;
                    cell.style.backgroundColor = cellData.color;
                });
            }
        });
    }

    function displayTableData(data) {
        const jsonOutputElement = document.getElementById("jsonOutput");
        const tableDataText = data.map(rowData => {
            return `ID: ${rowData.id}\nName: ${rowData.name}\nSelect Value: ${rowData.selectValue}\nCount: ${rowData.count}\nCells: ${rowData.cells ? rowData.cells.map(cell => `${cell.value} (${cell.color})`).join(", ") : ""}\n`;
        }).join("\n");
        jsonOutputElement.textContent = tableDataText; // Afficher le contenu au format texte
    }

    function openRangeSelectionModal(cell) {
        const modal = new bootstrap.Modal(document.getElementById('rangeSelectionModal'));
        const startCellIdInput = document.getElementById('startCellId');
        const endCellIdInput = document.getElementById('endCellId');
        const rangeResult = document.getElementById('rangeResult');
        const rangeComboBox = document.getElementById('rangeComboBox');

        // Remplir la combo box avec les valeurs de 1 à 50
        rangeComboBox.innerHTML = "";
        for (let i = 1; i <= 50; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.textContent = i;
            rangeComboBox.appendChild(option);
        }

        // Ajouter un gestionnaire d'événements pour écouter les changements de la combo box
        rangeComboBox.addEventListener("change", function () {
            const startCellId = startCellIdInput.value;
            const startParts = startCellId.split('-');
            const startNumber = parseInt(startParts[2], 10);
            const comboValue = parseInt(rangeComboBox.value, 10);
            const totalDays = startNumber + comboValue;
            //const endCellId = `cell-${startParts[0]}-${startParts[1]}-${totalDays}`;
            const endCellId = `${startParts[0]}-${startParts[1]}-${totalDays}`;

            console.log("Valeur sélectionnée :", comboValue);
            console.log("Nb jours :", totalDays);
            rangeResult.textContent = `Nb jours : ${totalDays}`;

            // Mettre à jour l'input de fin avec la nouvelle valeur
            endCellIdInput.value = endCellId;
        });

        startCellIdInput.value = cell.dataset.cellId;
        endCellIdInput.value = "";
        rangeResult.textContent = "Nb jours : 0"; // Initialiser le résultat

        modal.show();

        document.getElementById('confirmRangeSelection').addEventListener('click', function () {
            const startCellId = startCellIdInput.value;
            const endCellId = endCellIdInput.value;
            const comboValue = rangeComboBox.value;

            alert(startCellId + "  " + endCellId);

            updateCellRange(startCellId, endCellId, comboValue);
            modal.hide();
        });

        document.getElementById('cancelRangeSelection').addEventListener('click', function () {
            modal.hide();
        });

        // Ajouter la fonctionnalité de déplacement de la fenêtre modale
        const modalHeader = modal._dialog.querySelector('.modal-header');
        let isDragging = false;
        let offsetX, offsetY;

        modalHeader.addEventListener('mousedown', function (event) {
            isDragging = true;
            offsetX = event.clientX - modal._dialog.offsetLeft;
            offsetY = event.clientY - modal._dialog.offsetTop;
            modal._dialog.style.pointerEvents = 'none';
        });

        document.addEventListener('mousemove', function (event) {
            if (isDragging) {
                modal._dialog.style.left = `${event.clientX - offsetX}px`;
                modal._dialog.style.top = `${event.clientY - offsetY}px`;
            }
        });

        document.addEventListener('mouseup', function () {
            isDragging = false;
            modal._dialog.style.pointerEvents = 'all';
        });

        // Mettre à jour le résultat de la soustraction en temps réel
        endCellIdInput.addEventListener('input', function () {
            const startParts = startCellIdInput.value.split('-');
            const endParts = endCellIdInput.value.split('-');

            if (startParts.length === 3 && endParts.length === 3 && startParts[0] === endParts[0] && startParts[1] === endParts[1]) {
                const startValue = parseInt(startParts[2], 10);
                const endValue = parseInt(endParts[2], 10);

                console.log(" ++  " + startValue + " " + endValue);

                const result = endValue - startValue;
                rangeResult.textContent = `Nb jours : ${result} jours`;
                if (result > 0) {
                    alert(`Nb jours : ${result} jours`);
                }
            } else {
                rangeResult.textContent = "Nb jours : 0";
            }
        });
    }

    function updateCellRange(startCellId, endCellId) {
        const startCell = document.querySelector(`td[data-cell-id="${startCellId}"]`);
        const endCell = document.querySelector(`td[data-cell-id="${endCellId}"]`);

        if (startCell && endCell && startCell.parentElement === endCell.parentElement) {
            const startIndex = Array.from(startCell.parentElement.cells).indexOf(startCell);
            const endIndex = Array.from(endCell.parentElement.cells).indexOf(endCell);

            for (let i = startIndex; i <= endIndex; i++) {
                const cell = startCell.parentElement.cells[i];
                cell.dataset.cellValue = "1";
                cell.textContent = "1";
                cell.style.backgroundColor = "green";
                cell.dataset.cellColor = "green";
            }

            updateCountCell(startCell.parentElement);
        } else {
            showMessageModal("Les cellules doivent être sur la même ligne.");
        }
    }

    tableBody.addEventListener("mouseover", function (event) {
        const cell = event.target.closest("td");
        if (cell) {
            currentCell = cell;
        }
    });

    document.addEventListener("keydown", function (event) {
        if (event.key === "p" && currentCell) {
            openRangeSelectionModal(currentCell);
        }
    });

    document.getElementById("saveButton").addEventListener("click", function () {
        const tableData = traceTable();
        const jsonOutput = JSON.stringify(tableData, null, 2);
        const jsonOutputElement = document.getElementById("jsonOutput");
        jsonOutputElement.textContent = jsonOutput; // Afficher le contenu JSON au format texte
        saveToDB(); // Sauvegarder les données dans la base de données
    });

    document.getElementById("readButton").addEventListener("click", loadFromDB);

    document.getElementById("logButton").addEventListener("click", function () {
        const tableData = traceTable();
        displayJSONData(tableData); // Afficher les données JSON dans le div jsonOutput
    });

    document.getElementById("queryButton").addEventListener("click", queryTableData);

    function displayObjets() {
        console.log(standardRowsData);
        console.log(estimationRowsData); // Afficher les objets de ligne d'estimation
    }

    document.getElementById("memButton").addEventListener("click", displayObjets);
});
</script>

</body>
</html>