File "table_001.php"

Full Path: /home/analogde/www/aaa/2024_PHP_01_05_2025/table_001.php
File size: 125.06 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;
}

function getFrenchHolidays($year) {
    $easterDate = easter_date($year);
    $holidays = [];

    // Jours fériés fixes
    $holidays[] = "$year-01-01"; // Jour de l'An
    $holidays[] = "$year-05-01"; // Fête du Travail
    $holidays[] = "$year-05-08"; // Victoire 1945
    $holidays[] = "$year-07-14"; // Fête Nationale
    $holidays[] = "$year-08-15"; // Assomption
    $holidays[] = "$year-11-01"; // Toussaint
    $holidays[] = "$year-11-11"; // Armistice
    $holidays[] = "$year-12-25"; // Noël

    // Jours fériés variables (calculés à partir de Pâques)
    $easter = new DateTime("@$easterDate");
    $easter->setTimezone(new DateTimeZone(date_default_timezone_get()));

    $holidays[] = $easter->format("Y-m-d"); // Pâques (non férié officiellement mais utile)
    $holidays[] = $easter->modify('+1 day')->format("Y-m-d"); // Lundi de Pâques
    $holidays[] = $easter->modify('+38 days')->format("Y-m-d"); // Ascension
    $holidays[] = $easter->modify('+11 days')->format("Y-m-d"); // Lundi de Pentecôte

    return $holidays;
}

$year = 2025;
$holidays = [];

$holidays = getFrenchHolidays($year);

// Liste des jours fériés et fêtes religieuses à exclure (exemple pour la France, à compléter avec d'autres fêtes)
$old_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>
        .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;
            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;
        }

        .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>

    <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>

<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>

<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>

<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">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" data-dismiss="modal">OK</button>
            </div>
        </div>
    </div>
</div>

<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>

<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">
                    </select>
                </div>
                <div id="rangeResult" class="form-group">
                </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="logButton" class="btn">Log</button>

<button id="buildButton" class="btn">Build</button>

<button id="blablaButton" class="btn">Blabla</button>

<button id="query" class="btn">Query</button>

<div id="generatedDataOutput"></div>

<div id="jsonOutput"></div>
<div id="debugOutput"></div>

<script>
document.addEventListener("DOMContentLoaded", function () {
    const tableBody = document.querySelector("tbody");
    let specialRowCounter = 1;
    let rowCounter = 1;
    let linkageCounter = 1;
    let standardRowsData = [];
    let estimationRowsData = [];
    let specialRowsData = []; // Tableau dédié pour stocker les objets des lignes spéciales
    let linkages = [];
    const specialRowStates = {};
    const associations = {};
    let currentCell = null;
    let keydownHandled = false;
    let alertShown = false;

    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;
                hideColorContextMenu();
                updateRowData(cell);
            }
        });
    });

    function generateRandomId(length = 8) {
        const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        let result = '';
        for (let i = 0; i < length; i++) {
            result += characters.charAt(Math.floor(Math.random() * characters.length));
        }
        return result;
    }

    function addRow(afterRow = null) {
        const rowNumber = tableBody.rows.length + 1;
        const newRow = document.createElement("tr");
        newRow.setAttribute("draggable", "true");
        newRow.dataset.rowId = `standard-${generateRandomId()}`;
        newRow.dataset.selection = "OFF"; // Ajouter la propriété selection
        newRow.title = newRow.dataset.rowId; // Ajoutez cette ligne

        const rowData = {
            id: newRow.dataset.rowId,
            name: `Row ${rowNumber}`,
            selectValue: "1",
            count: "0",
            cells: [],
            selection: "OFF" // Ajouter la propriété selection
        };

        const firstCells = [`Row ${rowNumber}`, "", "0"];
        firstCells.forEach((text, index) => {
            const td = document.createElement("td");
            td.dataset.cellId = `cell-${rowData.id}-${index}`;
            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";
                });
                input.addEventListener("blur", function () {
                    if (!keydownHandled && !alertShown) {
                        alertShown = true;
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px";
                        console.clear;
                        updateRowData(input);
                    }
                    keydownHandled = false;
                    alertShown = false;
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        keydownHandled = true;
                        if (!alertShown) {
                            alertShown = true;
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                            console.clear;
                            updateRowData(input);
                        }
                    }
                });
                td.appendChild(input);

                // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                td.addEventListener("click", function () {
                    toggleSelection(newRow);
                });
            } 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;
                select.addEventListener("change", function () {
                    updateRowData(select);
                });
                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-${rowData.id}-${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(newRow);
                updateRowData(td);
            });

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

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

            newRow.appendChild(td);

            rowData.cells.push({
                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++;

        standardRowsData.push(rowData);

        const estimationRow = document.createElement("tr");
        estimationRow.setAttribute("draggable", "true");
        estimationRow.dataset.rowId = `estimation-${generateRandomId()}`;
        estimationRow.dataset.selection = "OFF"; // Ajouter la propriété selection
        estimationRow.classList.add("estimation-row");
        estimationRow.title = estimationRow.dataset.rowId; // Ajoutez cette ligne

        const estimationRowData = {
            id: estimationRow.dataset.rowId,
            name: `Estimation ${rowNumber}`,
            selectValue: "1",
            estimationValue: "0",
            selection: "OFF" // Ajouter la propriété selection
        };

        const estimationFirstCells = [`Estimation ${rowNumber}`, "", "0"];
        estimationFirstCells.forEach((text, index) => {
            const td = document.createElement("td");
            td.dataset.cellId = `cell-${estimationRowData.id}-${index}`;
            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";
                });
                input.addEventListener("blur", function () {
                    if (!keydownHandled && !alertShown) {
                        alertShown = true;
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px";
                        console.clear;
                        updateRowData(input);
                    }
                    keydownHandled = false;
                    alertShown = false;
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        keydownHandled = true;
                        if (!alertShown) {
                            alertShown = true;
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                            console.clear;
                            updateRowData(input);
                        }
                    }
                });
                td.appendChild(input);

                // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                td.addEventListener("click", function () {
                    toggleSelection(estimationRow);
                });
            } 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;
                select.addEventListener("change", function () {
                    updateRowData(select);
                });
                td.appendChild(select);
            } else {
                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = "1";
                input.addEventListener("click", function (event) {
                    event.stopPropagation();
                    input.focus();
                    input.style.width = "130px";
                });
                input.addEventListener("blur", function () {
                    if (!keydownHandled && !alertShown) {
                        alertShown = true;
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px";
                        console.clear;
                        const value = parseInt(input.value, 10);
                        if (isNaN(value) || value < 1 || value > 365) {
                            input.value = "1";
                            showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                        } else {
                            updateRowData(input);
                        }
                    }
                    keydownHandled = false;
                    alertShown = false;
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        keydownHandled = true;
                        if (!alertShown) {
                            alertShown = true;
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                            console.clear;
                            const value = parseInt(input.value, 10);
                            if (isNaN(value) || value < 1 || value > 365) {
                                input.value = "1";
                                showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                            } else {
                                updateRowData(input);
                            }
                        }
                    }
                });
                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);

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

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

        const linkage = {
            id: `linkage-${generateRandomId()}`, // Remplacez linkageId par id
            standardRowId: newRow.dataset.rowId,
            estimationRowId: estimationRow.dataset.rowId
        };
        linkages.push(linkage);

        displayLinkages();

        rowCounter++;

        estimationRowsData.push(estimationRowData);
    }

    function updateRowData(element) {
        const row = element.closest("tr");
        const rowId = row.dataset.rowId;

        if (rowId.startsWith("standard-")) {
            let standardRowData = standardRowsData.find(data => data.id === rowId);
            if (!standardRowData) {
                standardRowData = {
                    id: rowId,
                    name: "",
                    selectValue: "",
                    count: "",
                    cells: [],
                    selection: "OFF" // Ajouter la propriété selection
                };
                standardRowsData.push(standardRowData);
            }
            const cells = row.querySelectorAll("td");
            standardRowData.name = cells[0].querySelector("input").value;
            standardRowData.selectValue = cells[1].querySelector("select").value;
            standardRowData.count = cells[2].textContent.trim();
            standardRowData.cells = [];

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

            console.log(`Mise à jour de la ligne standard : ${rowId}`);
        } else if (rowId.startsWith("estimation-")) {
            let estimationRowData = estimationRowsData.find(data => data.id === rowId);
            if (!estimationRowData) {
                estimationRowData = {
                    id: rowId,
                    name: "",
                    selectValue: "",
                    estimationValue: "",
                    selection: "OFF" // Ajouter la propriété selection
                };
                estimationRowsData.push(estimationRowData);
            }
            const cells = row.querySelectorAll("td");
            estimationRowData.name = cells[0].querySelector("input").value;
            estimationRowData.selectValue = cells[1].querySelector("select").value;
            estimationRowData.estimationValue = cells[2].querySelector("input").value;

            console.log(`Mise à jour de la ligne d'estimation : ${rowId}`);
        } else if (rowId.startsWith("special-")) {
            let specialRowData = specialRowsData.find(data => data.id === rowId);
            if (!specialRowData) {
                specialRowData = {
                    id: rowId,
                    name: "",
                    selection: "OFF" // Ajouter la propriété selection
                };
                specialRowsData.push(specialRowData);
            }
            specialRowData.name = row.querySelector("input").value;

            console.log(`Mise à jour de la ligne spéciale : ${rowId}`);
        }

        //const objetTache = createObjetTache();
        //console.log("Objet Tache :", JSON.stringify(objetTache, null, 2));
    }

    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 displaySpecialRowsData() {
        console.log("Contenu de specialRowsData :");
        specialRowsData.forEach((rowData, index) => {
            console.log(`Ligne spéciale ${index + 1} :`, rowData);
        });
    }

    function addSpecialRow(afterRow = null) {
        const newRow = document.createElement("tr");
        newRow.classList.add("special-row");
        newRow.setAttribute("draggable", "true");
        newRow.dataset.rowId = `special-${generateRandomId()}`;
        newRow.dataset.selection = "OFF"; // Ajouter la propriété selection
        newRow.title = newRow.dataset.rowId; // Ajoutez cette ligne

        const specialRowData = {
            id: newRow.dataset.rowId,
            name: `Ligne spéciale ${specialRowCounter}`,
            selection: "OFF" // Ajouter la propriété selection
        };

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

        const input = document.createElement("input");
        input.type = "text";
        input.classList.add("editable-input");
        input.value = specialRowData.name;
        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";
            updateRowData(input);
        });
        input.addEventListener("keydown", function (event) {
            if (event.key === "Escape" || event.key === "Enter") {
                input.classList.remove("editing");
                input.blur();
                input.style.width = "65px";
                updateRowData(input);
            }
        });
        input.addEventListener("input", function () {
            updateRowData(input);
        });

        // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
        input.addEventListener("click", function () {
            toggleSelection(newRow);
        });

        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);

        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);

        specialRowsData.push(specialRowData); // Ajouter l'objet dans le tableau dédié
        specialRowCounter++;

        // Afficher le contenu du tableau specialRowsData après l'ajout
        displaySpecialRowsData();
    }

    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>
        `;

        if (row.dataset.rowId.startsWith("standard-")) {
            contextMenu.innerHTML += `<button class="dropdown-item" id="up-insert-special">Up Insert special</button>`;
        } else if (row.dataset.rowId.startsWith("estimation-")) {
            contextMenu.innerHTML += `<button class="dropdown-item" id="down-insert-special">Down Insert special</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();
        });

        document.getElementById("up-insert-special")?.addEventListener("click", function () {
            addSpecialRow(row);
            hideContextMenu();
        });

        document.getElementById("down-insert-special")?.addEventListener("click", function () {
            addSpecialRow(row);
            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;

        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;
        }

        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");
                }
            });

            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";

        document.querySelectorAll(".selected-cell").forEach(c => c.classList.remove("selected-cell"));
        cell.classList.add("selected-cell");
    }

    function displayStandardRowsData() {
        console.log("Contenu de standardRowsData :");
        standardRowsData.forEach((rowData, index) => {
            console.log(`Ligne ${index + 1} :`, rowData);
        });
    }

    function displayEstimationRowsData() {
        console.log("Contenu de estimationRowsData :");
        estimationRowsData.forEach((rowData, index) => {
            console.log(`Ligne ${index + 1} :`, rowData);
        });
    }

    function displaySpecialRowsData() {
        console.log("Contenu de specialRowsData :");
        specialRowsData.forEach((rowData, index) => {
            console.log(`Ligne ${index + 1} :`, rowData);
        });
    }

    function displayLinkagesData() {
        console.log("Contenu de LinkagesData :");
        linkages.forEach((rowData, index) => {
            console.log(`Ligne ${index + 1} :`, rowData);
        });
    }

    function toggleSelection(row) {
        const firstCell = row.querySelector("td:first-child");
        if (row.dataset.selection === "OFF") {
            row.dataset.selection = "ON";
            firstCell.style.backgroundColor = "blue";
        } else {
            row.dataset.selection = "OFF";
            firstCell.style.backgroundColor = "";
        }
        updateRowData(firstCell); // Mettre à jour les données de la ligne
    }

    /********************************************************************************************/

    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");
            }
        });
    });

    /********************************************************************************************/

    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.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");

        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 showConfirmationModal(row) {
        const modal = new bootstrap.Modal(document.getElementById('confirmationModal'));
        modal.show();

        document.getElementById('confirmDelete').addEventListener('click', function () {
            let linkageIndex = -1;

            const rowId = row.dataset.rowId;
            const isStandardRow = rowId.startsWith("standard-");
            const isEstimationRow = rowId.startsWith("estimation-");
            const isSpecialRow = rowId.startsWith("special-");

            if (isStandardRow) {
                linkageIndex = linkages.findIndex(link => link.standardRowId === rowId);
            } else if (isEstimationRow) {
                linkageIndex = linkages.findIndex(link => link.estimationRowId === rowId);
            } else if (isSpecialRow) {
                linkageIndex = linkages.findIndex(link => link.specialRowId === rowId);
            }

            if (linkageIndex !== -1) {
                const linkage = linkages[linkageIndex];
                console.log("Liaison trouvée :");
                console.log("Index de la liaison :", linkageIndex); // Afficher l'indice de la liaison
                console.log("ID de la liaison :", linkage.id);
                console.log("ID de la ligne standard :", linkage.standardRowId);
                console.log("ID de la ligne d'estimation :", linkage.estimationRowId);

            }

            let standardRowId = null;
            let estimationRowId = null;
            let linkageId = null;

            if (isStandardRow) {
                standardRowId = rowId;
                const linkage = linkages.find(link => link.standardRowId === standardRowId);
                if (linkage) {
                    estimationRowId = linkage.estimationRowId;
                    linkageId = linkage.id;
                }
            } else if (isEstimationRow) {
                estimationRowId = rowId;
                const linkage = linkages.find(link => link.estimationRowId === estimationRowId);
                if (linkage) {
                    standardRowId = linkage.standardRowId;
                    linkageId = linkage.id;
                }
            } else if (isSpecialRow) {
                // Handle special row deletion if needed
            }

            if (standardRowId && estimationRowId && linkageId) {
                // Remove the corresponding sub-arrays in tableData
                const tableData = traceTable();
                const standardIndex = tableData.findIndex(item => item.id === standardRowId);
                const estimationIndex = tableData.findIndex(item => item.id === estimationRowId);
                const linkageIndex = tableData.findIndex(item => item.id === linkageId);

                if (standardIndex !== -1) {
                    tableData.splice(standardIndex, 1);
                }
                if (estimationIndex !== -1) {
                    tableData.splice(estimationIndex, 1);
                }
                if (linkageIndex !== -1) {
                    tableData.splice(linkageIndex, 1);
                }

                // Remove the rows from the DOM
                const standardRow = document.querySelector(`tr[data-row-id="${standardRowId}"]`);
                const estimationRow = document.querySelector(`tr[data-row-id="${estimationRowId}"]`);

                if (standardRow) {
                    standardRow.remove();
                }
                if (estimationRow) {
                    estimationRow.remove();
                }

                // Update the linkages array
                const linkageIndexInLinkages = linkages.findIndex(link => link.id === linkageId);
                if (linkageIndexInLinkages !== -1) {
                    linkages.splice(linkageIndexInLinkages, 1);
                }

                // Display the updated tableData
                displayJSONData(tableData);
            }

            if (isSpecialRow) {
                // Remove the corresponding sub-array in tableData
                const tableData = traceTable();
                const indexToRemove = tableData.findIndex(item => item.id === rowId);
                if (indexToRemove !== -1) {
                    tableData.splice(indexToRemove, 1);
                    console.log("Sous-tableau supprimé :", rowId);
                }

                // Remove the row from the DOM
                row.remove();

                // Display the updated tableData
                displayJSONData(tableData);
            }

            modal.hide();
        });

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

    /*********************************************************************************************/

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

        // Parcourir les liaisons pour recréer les lignes
        linkages.forEach(linkage => {
            // Trouver les données correspondantes pour les lignes standard et d'estimation
            const standardRowData = standardRowsData.find(row => row.id === linkage.standardRowId);
            const estimationRowData = estimationRowsData.find(row => row.id === linkage.estimationRowId);
            const specialRowData = specialRowsData.find(row => row.id === linkage.specialRowId);

            // Créer une nouvelle ligne standard
            const standardRow = document.createElement("tr");
            standardRow.setAttribute("draggable", "true");
            standardRow.dataset.rowId = standardRowData.id;
            standardRow.dataset.selection = standardRowData.selection; // Ajouter la propriété selection

            // Ajouter les cellules pour la ligne standard
            const firstCells = [standardRowData.name, "", standardRowData.count];
            firstCells.forEach((text, index) => {
                const td = document.createElement("td");
                td.dataset.cellId = `cell-${standardRowData.id}-${index}`;
                if (index === 0) {
                    const input = document.createElement("input");
                    input.type = "text";
                    input.classList.add("editable-input");
                    input.value = standardRowData.name;
                    input.addEventListener("click", function (event) {
                        event.stopPropagation();
                        input.focus();
                        input.style.width = "130px";
                    });
                    input.addEventListener("blur", function () {
                        if (!keydownHandled && !alertShown) {
                            alertShown = true;
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                            console.clear;
                            updateRowData(input);
                        }
                        keydownHandled = false;
                        alertShown = false;
                    });
                    input.addEventListener("keydown", function (event) {
                        if (event.key === "Escape" || event.key === "Enter") {
                            keydownHandled = true;
                            if (!alertShown) {
                                alertShown = true;
                                input.classList.remove("editing");
                                input.blur();
                                input.style.width = "65px";
                                console.clear;
                                updateRowData(input);
                            }
                        }
                    });
                    td.appendChild(input);

                    // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                    td.addEventListener("click", function () {
                        toggleSelection(standardRow);
                    });
                } 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 = standardRowData.selectValue;
                    select.addEventListener("change", function () {
                        updateRowData(select);
                    });
                    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);
            });

            // Ajouter les cellules de jours ouvrés
            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-${standardRowData.id}-${i}`;
                td.dataset.cellValue = standardRowData.cells[i].value;
                td.dataset.cellColor = standardRowData.cells[i].color;
                td.textContent = standardRowData.cells[i].value;
                td.style.backgroundColor = standardRowData.cells[i].color;

                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);
                    updateRowData(td);
                });

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

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

                standardRow.appendChild(td);
            }

            // Ajouter la ligne standard au tableau
            tableBody.appendChild(standardRow);

            // Ajouter les événements de drag-and-drop
            standardRow.addEventListener("dragstart", dragStart);
            standardRow.addEventListener("dragover", dragOver);
            standardRow.addEventListener("drop", drop);

            // Créer une nouvelle ligne d'estimation
            const estimationRow = document.createElement("tr");
            estimationRow.setAttribute("draggable", "true");
            estimationRow.dataset.rowId = estimationRowData.id;
            estimationRow.dataset.selection = estimationRowData.selection; // Ajouter la propriété selection
            estimationRow.classList.add("estimation-row");

            // Ajouter les cellules pour la ligne d'estimation
            const estimationFirstCells = [estimationRowData.name, "", estimationRowData.estimationValue];
            estimationFirstCells.forEach((text, index) => {
                const td = document.createElement("td");
                td.dataset.cellId = `cell-${estimationRowData.id}-${index}`;
                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";
                    });
                    input.addEventListener("blur", function () {
                        if (!keydownHandled && !alertShown) {
                            alertShown = true;
                            input.classList.remove("editing");
                            input.blur();
                            input.style.width = "65px";
                            console.clear;
                            updateRowData(input);
                        }
                        keydownHandled = false;
                        alertShown = false;
                    });
                    input.addEventListener("keydown", function (event) {
                        if (event.key === "Escape" || event.key === "Enter") {
                            keydownHandled = true;
                            if (!alertShown) {
                                alertShown = true;
                                input.classList.remove("editing");
                                input.blur();
                                input.style.width = "65px";
                                console.clear;
                                updateRowData(input);
                            }
                        }
                    });
                    td.appendChild(input);

                    // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                    td.addEventListener("click", function () {
                        toggleSelection(estimationRow);
                    });
                } 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;
                    select.addEventListener("change", function () {
                        updateRowData(select);
                    });
                    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 = "1";
                            showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                        } else {
                            updateRowData(input);
                        }
                    });
                    input.addEventListener("keydown", function (event) {
                        if (event.key === "Escape" || event.key === "Enter") {
                            const value = parseInt(input.value, 10);
                            if (isNaN(value) || value < 1 || value > 365) {
                                input.value = "1";
                                showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                            } else {
                                updateRowData(input);
                            }
                        }
                    });
                    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);

            // Ajouter la ligne d'estimation au tableau
            tableBody.appendChild(estimationRow);

            // Ajouter les événements de drag-and-drop
            estimationRow.addEventListener("dragstart", dragStart);
            estimationRow.addEventListener("dragover", dragOver);
            estimationRow.addEventListener("drop", drop);

            // Créer une nouvelle ligne spéciale
            if (specialRowData) {
                const specialRow = document.createElement("tr");
                specialRow.classList.add("special-row");
                specialRow.setAttribute("draggable", "true");
                specialRow.dataset.rowId = specialRowData.id;
                specialRow.dataset.selection = specialRowData.selection; // Ajouter la propriété selection

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

                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = specialRowData.name;
                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";
                    updateRowData(input);
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px";
                        updateRowData(input);
                    }
                });
                input.addEventListener("input", function () {
                    updateRowData(input);
                });

                // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                input.addEventListener("click", function () {
                    toggleSelection(specialRow);
                });

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

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

                specialRow.appendChild(firstCell);

                const mergedCell = document.createElement("td");
                mergedCell.colSpan = 2;
                mergedCell.textContent = "";
                specialRow.appendChild(mergedCell);

                const td = document.createElement("td");
                td.textContent = `${specialRowData.name} - Détails`;
                td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3;
                specialRow.appendChild(td);

                tableBody.appendChild(specialRow);

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

        // Afficher les liaisons dans la console
        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");
            }
        });
    });

    /*********************************************************************************************/

    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.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");

        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 query() {
        const tableData = [];
        const rows = tableBody.querySelectorAll("tr");

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

            if (row.dataset.rowId.startsWith("special-")) {
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
                rowData.selection = row.dataset.selection; // Ajouter la propriété selection
            } else if (row.dataset.rowId.startsWith("estimation-")) {
                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;
                rowData.selectValue = cells[1].querySelector("select").value;
                rowData.selection = row.dataset.selection; // Ajouter la propriété selection
            } else {
                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.selection = row.dataset.selection; // Ajouter la propriété selection
                //rowData.cells = [];

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

            tableData.push(rowData);
        });

        // Ajouter les objets linkage au tableau de données
        linkages.forEach(linkage => {
            tableData.push({
                id: linkage.id,
                standardRowId: linkage.standardRowId,
                estimationRowId: linkage.estimationRowId
            });
        });

        //return tableData;

        //const tableData = traceTable();
        console.log("Données retournées par traceTable():", JSON.stringify(tableData, null, 2));

    }

    /*********************************************************************************************/

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

        // Parcourir chaque ligne du tableau et récupérer les données des cellules
        rows.forEach(row => {
            const rowData = {};
            const cells = row.querySelectorAll("td");

            if (row.dataset.rowId.startsWith("special-")) {
                const inputCell = cells[0];
                const inputValue = inputCell.querySelector("input").value;
                rowData.id = row.dataset.rowId;
                rowData.name = inputValue;
                rowData.selection = row.dataset.selection; // Ajouter la propriété selection
            } else if (row.dataset.rowId.startsWith("estimation-")) {
                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;
                rowData.selectValue = cells[1].querySelector("select").value;
                rowData.selection = row.dataset.selection; // Ajouter la propriété selection
            } else {
                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 = [];
                rowData.selection = row.dataset.selection; // Ajouter la propriété selection

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

            tableData.push(rowData);
        });

        // Ajouter les objets linkage au tableau de données
        linkages.forEach(linkage => {
            tableData.push({
                id: linkage.id,
                standardRowId: linkage.standardRowId,
                estimationRowId: linkage.estimationRowId
            });
        });

        return tableData;
    }

    /*********************************************************************************************/

    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');

        rangeComboBox.innerHTML = "";
        for (let i = 1; i <= 50; i++) {
            const option = document.createElement("option");
            option.value = i;
            option.textContent = i;
            rangeComboBox.appendChild(option);
        }

        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 = `${startParts[0]}-${startParts[1]}-${totalDays}`;

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

            endCellIdInput.value = endCellId;
        });

        startCellIdInput.value = cell.dataset.cellId;
        endCellIdInput.value = "";
        rangeResult.textContent = "Nb jours : 0";

        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();
        });

        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';
        });

        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";
                updateRowData(cell);
            }

            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("buildButton").addEventListener("click", function () {
        console.log("Build ...");
        //logRowTypes();

        Jsondata();
        //const tableData = traceTable();
        //console.log("Building data... " + tableData);

    });

    /*********************************************************************************************/

    document.getElementById("query").addEventListener("click", query);

    function aaaaquery() {

        const tableData = traceTable();
        console.log("Données retournées par traceTable():", JSON.stringify(tableData, null, 2));

    }

    function Jsondata() {
        /*
        const jsonData = [];

        linkages.forEach(linkage => {
            const standardRowData = standardRowsData.find(row => row.id === linkage.standardRowId);
            const estimationRowData = estimationRowsData.find(row => row.id === linkage.estimationRowId);
            const specialRowData = specialRowsData.find(row => row.id === linkage.specialRowId);

            jsonData.push({
                linkage: linkage,
                standardRow: standardRowData,
                estimationRow: estimationRowData,
                specialRow: specialRowData
            });
        });

        const jsonOutputElement = document.getElementById("generatedDataOutput");
        jsonOutputElement.textContent = JSON.stringify(jsonData, null, 2);
        */

        /*
        const jsonData = [];

        // Ajouter les objets linkage
        linkages.forEach(linkage => {
            jsonData.push({
                id: linkage.id,
                standardRowId: linkage.standardRowId,
                estimationRowId: linkage.estimationRowId
            });
        });

        // Ajouter les objets specialRow
        specialRowsData.forEach(specialRow => {
            jsonData.push({
                id: specialRow.id,
                name: specialRow.name,
                selection: specialRow.selection // Ajouter la propriété selection
            });
        });

        // Ajouter les objets standardRow
        standardRowsData.forEach(standardRow => {
            jsonData.push({
                id: standardRow.id,
                name: standardRow.name,
                selectValue: standardRow.selectValue,
                count: standardRow.count,
                cells: standardRow.cells,
                selection: standardRow.selection // Ajouter la propriété selection
            });
        });
        */
        // Ajouter les objets estimationRow
        /*
        estimationRowsData.forEach(estimationRow => {
            jsonData.push({
                id: estimationRow.id,
                name: estimationRow.name,
                selectValue: estimationRow.selectValue,
                estimationValue: estimationRow.estimationValue,
                selection: estimationRow.selection // Ajouter la propriété selection
            });
        });

        const jsonOutputElement = document.getElementById("generatedDataOutput");
        jsonOutputElement.textContent = JSON.stringify(jsonData, null, 2);
        */

        const jsonData = [];
        const rows = document.querySelectorAll("tbody tr");

        rows.forEach(row => {
            const rowId = row.dataset.rowId;
            const cells = row.querySelectorAll("td");

            if (rowId.startsWith("standard-")) {
                const standardRow = {
                    id: rowId,
                    name: cells[0].querySelector("input").value,
                    selectValue: cells[1].querySelector("select").value,
                    count: cells[2].textContent.trim(),
                    cells: [],
                    selection: row.dataset.selection // Ajouter la propriété selection
                };

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

                jsonData.push(standardRow);
            } else if (rowId.startsWith("estimation-")) {
                const estimationRow = {
                    id: rowId,
                    name: cells[0].querySelector("input").value,
                    selectValue: cells[1].querySelector("select").value,
                    estimationValue: cells[2].querySelector("input").value,
                    selection: row.dataset.selection // Ajouter la propriété selection
                };

                jsonData.push(estimationRow);
            } else if (rowId.startsWith("special-")) {
                const specialRow = {
                    id: rowId,
                    name: cells[0].querySelector("input").value,
                    selection: row.dataset.selection // Ajouter la propriété selection
                };

                jsonData.push(specialRow);
            }
        });

        // Ajouter les objets linkage
        linkages.forEach(linkage => {
            jsonData.push({
                id: linkage.id,
                standardRowId: linkage.standardRowId,
                estimationRowId: linkage.estimationRowId
            });
        });

        console.log(JSON.stringify(jsonData, null, 2));

        sendDataToPHP(jsonData);

    }

    function logRowTypes() {
        console.log("TRACE Start");

        const rowDataArray = [];

        const rows = tableBody.querySelectorAll("tr");
        const rowTypes = {
            standard: 0,
            estimation: 0,
            special: 0
        };

        linkages.forEach((linkage, index) => {
            rowDataArray.push(linkage);
        });

        rows.forEach(row => {
            const rowId = row.dataset.rowId;
            if (rowId.startsWith("standard-")) {
                rowTypes.standard++;
            } else if (rowId.startsWith("estimation-")) {
                rowTypes.estimation++;
            } else if (rowId.startsWith("special-")) {
                rowTypes.special++;
            }

            let rowData = null;
            if (rowId.startsWith("standard-")) {
                rowData = standardRowsData.find(data => data.id === rowId);
            } else if (rowId.startsWith("estimation-")) {
                rowData = estimationRowsData.find(data => data.id === rowId);
            } else if (rowId.startsWith("special-")) {
                rowData = specialRowsData.find(data => data.id === rowId);
            }

            if (rowData) {
                console.log("Identifiant de la ligne :", rowId);
                console.log("Détails de l'objet :", rowData);
                rowDataArray.push(rowData);
            } else {
                console.log("Aucune donnée trouvée pour l'identifiant de la ligne :", rowId);
            }
        });

        linkages.forEach((linkage, index) => {
            console.log(`Liaison ${index + 1} :`, linkage);
        });

        console.log("Nombre de lignes standard :", rowTypes.standard);
        console.log("Nombre de lignes d'estimation :", rowTypes.estimation);
        console.log("Nombre de lignes spéciales :", rowTypes.special);

        sendDataToPHP(rowDataArray);

        console.log("TRACE end");
    }

    function sendDataToPHP(rowDataArray) {
        // Afficher les données dans la console
        console.log("Données envoyées à PHP :", rowDataArray);

        // Envoyer les données au script PHP
        fetch('script_export.php', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(rowDataArray)
        })
        .then(response => response.json())
        .then(data => {
            // Gérer les différents types de messages renvoyés
            if (data.status === 'success') {
                console.log('Succès :', data.message);
                showMessageModal(data.message);
            } else if (data.status === 'error') {
                console.error('Erreur :', data.message);
                showMessageModal(data.message);
            } else {
                console.error('Réponse inattendue :', data);
                showMessageModal('Réponse inattendue du serveur.');
            }
        })
        .catch(error => {
            console.error('Erreur :', error);
            showMessageModal('Une erreur est survenue lors de l\'envoi des données.');
        });
    }

    /*********************************************************************************************/

    document.getElementById("blablaButton").addEventListener("click", fetchJsonData);

    /*********************************************************************************************/

    function fetchJsonData() {
        // Envoyer une requête GET au script PHP
        fetch('script_import.php')
            .then(response => response.json())
            .then(data => {
                // Gérer les différents types de messages renvoyés
                if (data.status === 'success') {

                    //console.log("<--------------- Début file.json  --------------------->");

                    //console.log('Données JSON récupérées :', data.data);

                    // Parcourir chaque élément (sous-tableau JSON) de data
                    data.data.forEach((item, index) => {
                        //console.log("<------------------------------------>");
                        //console.log(`Élément ${index + 1} :`);

                        if (item.id.includes('standard')) {
                            //console.log('Détails de la ligne standard :');
                            for (const key in item) {
                                if (item.hasOwnProperty(key)) {
                                    if (key === 'cells' && Array.isArray(item[key])) {
                                        //console.log(`  ${key}:`);
                                        /* pas utile de voir le détail de chaque cellule
                                        item[key].forEach((cell, cellIndex) => {
                                            console.log(`    Cell ${cellIndex + 1}:`);
                                            for (const cellKey in cell) {
                                                if (cell.hasOwnProperty(cellKey)) {
                                                    console.log(`      ${cellKey}: ${cell[cellKey]}`);
                                                }
                                            }
                                        });*/
                                    }
                                    else {
                                        // console.log(`  ${key}: ${item[key]}`);
                                    }
                                }
                            }
                        }

                        else if (item.id.includes('estimation')) {
                            //console.log('Détails de la ligne d\'estimation :');
                            for (const key in item) {
                                if (item.hasOwnProperty(key)) {
                                    //console.log(`  ${key}: ${item[key]}`);
                                }
                            }
                        } else if (item.id.includes('special')) {
                            //console.log('Détails de la ligne spéciale :');
                            for (const key in item) {
                                if (item.hasOwnProperty(key)) {
                                    //console.log(`  ${key}: ${item[key]}`);
                                }
                            }
                        }

                        else if (item.id.includes('linkage')) {
                            //console.log('Détails de la liaison :');
                            for (const key in item) {
                                if (item.hasOwnProperty(key)) {
                                    //console.log(`  ${key}: ${item[key]}`);
                                }
                            }
                        }

                        else {
                            //console.log('Type de ligne inconnu :', item.id);
                        }

                        // Afficher les détails de chaque sous-tableau JSON
                        /*if (item.standardRow) {
                            console.log('Détails de la ligne standard :', item.standardRow);
                        }
                        if (item.estimationRow) {
                            console.log('Détails de la ligne d\'estimation :', item.estimationRow);
                        }
                        if (item.specialRow) {
                            console.log('Détails de la ligne spéciale :', item.specialRow);
                        }*/
                    });

                    //console.log("<--------------- FIN file.json  --------------------->");

                    preparation(data.data);

                }
                else if (data.status === 'error') {
                    console.error('Erreur :', data.message);
                    showMessageModal(data.message);
                }
                else {
                    console.error('Réponse inattendue :', data);
                    showMessageModal('Réponse inattendue du serveur.');
                }
            })
            .catch(error => {
                console.error('Erreur :', error);
                showMessageModal('Une erreur est survenue lors de la récupération des données.');
            });
    }

    /*********************************************************************************************/

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

    /*********************************************************************************************/

    function preparation(data) {

        regeneration(data);
        //display_import(data);
    }

    /*********************************************************************************************/

    function display_import(data) {

        // Parcourir chaque élément (sous-tableau JSON) de data
        data.forEach((item, index) => {
            console.log(`Élément ${index + 1} :`);

            // Vérifier si l'id contient 'standard', 'estimation' ou 'special'
            if (item.id.includes('standard')) {
                console.log('Import : détails de la ligne standard :');
                for (const key in item) {
                    if (item.hasOwnProperty(key)) {
                        if (key === 'cells' && Array.isArray(item[key])) {
                            console.log(`  ${key}:`);
                            // pas utile de voir le détail de chaque cellule
                            /*item[key].forEach((cell, cellIndex) => {
                                console.log(`    Cell ${cellIndex + 1}:`);
                                for (const cellKey in cell) {
                                    if (cell.hasOwnProperty(cellKey)) {
                                        console.log(`      ${cellKey}: ${cell[cellKey]}`);
                                    }
                                }
                            });*/
                        } else {
                            console.log(`  ${key}: ${item[key]}`);
                        }
                    }
                }
            } else if (item.id.includes('estimation')) {
                console.log('Import : Détails de la ligne d\'estimation :');
                for (const key in item) {
                    if (item.hasOwnProperty(key)) {
                        console.log(`  ${key}: ${item[key]}`);
                    }
                }
            } else if (item.id.includes('special')) {
                console.log('Import :Détails de la ligne spéciale :');
                for (const key in item) {
                    if (item.hasOwnProperty(key)) {
                        console.log(`  ${key}: ${item[key]}`);
                    }
                }
            }
            else if (item.id.includes('linkage')) {
                console.log('Détails de la liaison :');
                for (const key in item) {
                    if (item.hasOwnProperty(key)) {
                        console.log(`  ${key}: ${item[key]}`);
                    }
                }
            }

            else {
                console.log('Type de ligne inconnu :', item.id);
            }
        });

    }

    /*********************************************************************************************/

    function code_annexe(data) {
        /*
        console.log(" ********** Début recherche ******************** ");

        // Afficher le contenu détaillé des objets
        //console.log("Contenu de standardRowsData :");
        standardRowsData.forEach((row, index) => {
            console.log(`Ligne standard ${index + 1} :`, row);
        });

        //console.log("Contenu de estimationRowsData :");
        estimationRowsData.forEach((row, index) => {
            console.log(`Ligne d'estimation ${index + 1} :`, row);
        });

        //console.log("Contenu de specialRowsData :");
        specialRowsData.forEach((row, index) => {
            console.log(`Ligne spéciale ${index + 1} :`, row);
        });

        //console.log("Contenu de linkages :");
        linkages.forEach((linkage, index) => {
            console.log(`Liaison ${index + 1} :`, linkage);
        });

        console.log(" ********** Fin recherche ******************** ");

        console.log(" ********** Début vérification purge  ******************** ");

        standardRowsData.length = 0;
        estimationRowsData.length = 0;
        specialRowsData.length = 0;
        linkages.length = 0;

        if (standardRowsData.length === 0) {
            console.log("  standardRowsData empty");
        }
        if (estimationRowsData.length === 0) {
            console.log("  estimationRowsData empty");
        }
        if (specialRowsData.length === 0) {
            console.log("  specialRowsData empty");
        }
        if (linkages.length === 0) {
            console.log("  linkages  empty");
        }

        console.log(" ********** Fin vérification purge  ******************** ");
        */
        // Afficher le nombre de sous-tableaux dans data
        //console.log("Nombre de sous-tableaux dans data :", data.length);

        /*for (const item of data) {
            if (item.id.includes('special')) {
                const specialRowData = {
                    id: item.id,
                    name: item.name
                };
                specialRowsData.push(specialRowData);
            }
        }*/

        /*for (let i = 0; i < data.length; i++) {
            console.log(" Indice " + i);
        }*/

    }

    /*********************************************************************************************/

    function regeneration(data) {
        console.log("Purging table and regenerating rows...");

        // Clear existing table data
        tableBody.innerHTML = "";
        standardRowsData.length = 0;
        estimationRowsData.length = 0;
        specialRowsData.length = 0;
        linkages.length = 0;

        data.forEach(item => {
            if (item.id.includes('linkage')) {
                console.log("Creating a linkage...");
                const linkage = {
                    id: item.id,
                    standardRowId: item.standardRowId,
                    estimationRowId: item.estimationRowId,
                };
                linkages.push(linkage);
            }

            if (item.id.includes('standard')) {
                console.log("Creating a standard row...");
                const standardRowData = {
                    id: item.id,
                    name: item.name,
                    selectValue: item.selectValue,
                    count: item.count,
                    cells: item.cells,
                    selection: item.selection // Ajouter la propriété selection
                };
                standardRowsData.push(standardRowData);

                const standardRow = document.createElement("tr");
                standardRow.setAttribute("draggable", "true");
                standardRow.dataset.rowId = item.id;
                standardRow.dataset.selection = item.selection; // Ajouter la propriété selection
                standardRow.title = standardRow.dataset.rowId; // Ajoutez cette ligne

                const firstCells = [item.name, "", item.count];
                firstCells.forEach((text, index) => {
                    const td = document.createElement("td");
                    td.dataset.cellId = `cell-${item.id}-${index}`;
                    if (index === 0) {
                        const input = document.createElement("input");
                        input.type = "text";
                        input.classList.add("editable-input");
                        input.value = item.name;
                        input.addEventListener("click", function (event) {
                            event.stopPropagation();
                            input.focus();
                            input.style.width = "130px";
                            console.log("Input clicked, setting width to 130px");
                        });
                        input.addEventListener("blur", function () {
                            if (!keydownHandled && !alertShown) {
                                alertShown = true;
                                input.classList.remove("editing");
                                input.blur();
                                input.style.width = "65px";
                                console.clear;
                                updateRowData(input);
                            }
                            keydownHandled = false;
                            alertShown = false;
                        });
                        input.addEventListener("keydown", function (event) {
                            if (event.key === "Escape" || event.key === "Enter") {
                                keydownHandled = true;
                                if (!alertShown) {
                                    alertShown = true;
                                    input.classList.remove("editing");
                                    input.blur();
                                    input.style.width = "65px";
                                    console.clear;
                                    updateRowData(input);
                                }
                            }
                        });
                        td.appendChild(input);

                        // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                        td.addEventListener("click", function () {
                            toggleSelection(standardRow);
                        });
                    } 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 = item.selectValue;
                        select.addEventListener("change", function () {
                            updateRowData(select);
                        });
                        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-${item.id}-${i}`;
                    td.dataset.cellValue = item.cells[i].value;
                    td.dataset.cellColor = item.cells[i].color;
                    td.textContent = item.cells[i].value;
                    td.style.backgroundColor = item.cells[i].color;

                    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);
                        updateRowData(td);
                    });

                    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);
            }

            if (item.id.includes('estimation')) {
                console.log("Creating an estimation row...");
                const estimationRowData = {
                    id: item.id,
                    name: item.name,
                    selectValue: item.selectValue,
                    estimationValue: item.estimationValue,
                    selection: item.selection // Ajouter la propriété selection
                };
                estimationRowsData.push(estimationRowData);

                const estimationRow = document.createElement("tr");
                estimationRow.setAttribute("draggable", "true");
                estimationRow.dataset.rowId = item.id;
                estimationRow.dataset.selection = item.selection; // Ajouter la propriété selection
                estimationRow.classList.add("estimation-row");
                estimationRow.title = estimationRow.dataset.rowId; // Ajoutez cette ligne

                const estimationFirstCells = [item.name, "", item.estimationValue];
                estimationFirstCells.forEach((text, index) => {
                    const td = document.createElement("td");
                    td.dataset.cellId = `cell-${item.id}-${index}`;
                    if (index === 0) {
                        const input = document.createElement("input");
                        input.type = "text";
                        input.classList.add("editable-input");
                        input.value = item.name;
                        input.addEventListener("click", function (event) {
                            event.stopPropagation();
                            input.focus();
                            input.style.width = "130px";
                            console.log("Input clicked, setting width to 130px");
                        });
                        input.addEventListener("blur", function () {
                            if (!keydownHandled && !alertShown) {
                                alertShown = true;
                                input.classList.remove("editing");
                                input.blur();
                                input.style.width = "65px";
                                console.clear;
                                updateRowData(input);
                            }
                            keydownHandled = false;
                            alertShown = false;
                        });
                        input.addEventListener("keydown", function (event) {
                            if (event.key === "Escape" || event.key === "Enter") {
                                keydownHandled = true;
                                if (!alertShown) {
                                    alertShown = true;
                                    input.classList.remove("editing");
                                    input.blur();
                                    input.style.width = "65px";
                                    console.clear;
                                    updateRowData(input);
                                }
                            }
                        });
                        td.appendChild(input);

                        // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                        td.addEventListener("click", function () {
                            toggleSelection(estimationRow);
                        });
                    } 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 = item.selectValue;
                        select.addEventListener("change", function () {
                            updateRowData(select);
                        });
                        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 = "1";
                                showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                            } else {
                                updateRowData(input);
                            }
                            input.classList.remove("editing");
                            input.style.width = "65px";
                        });
                        input.addEventListener("keydown", function (event) {
                            if (event.key === "Escape" || event.key === "Enter") {
                                const value = parseInt(input.value, 10);
                                if (isNaN(value) || value < 1 || value > 365) {
                                    input.value = "1";
                                    showMessageModal("La valeur doit être un nombre entier compris entre 1 et 365.");
                                } else {
                                    updateRowData(input);
                                }
                                input.classList.remove("editing");
                                input.blur();
                                input.style.width = "65px";
                            }
                        });
                        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 = document.querySelector("thead tr:nth-child(2)").cells.length - 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);
            }

            if (item.id.includes('special')) {
                console.log("Creating a special row...");
                const specialRowData = {
                    id: item.id,
                    name: item.name,
                    selection: item.selection // Ajouter la propriété selection
                };
                specialRowsData.push(specialRowData);

                const specialRow = document.createElement("tr");
                specialRow.classList.add("special-row");
                specialRow.setAttribute("draggable", "true");
                specialRow.dataset.rowId = item.id;
                specialRow.dataset.selection = item.selection; // Ajouter la propriété selection
                specialRow.title = specialRow.dataset.rowId; // Ajoutez cette ligne

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

                const input = document.createElement("input");
                input.type = "text";
                input.classList.add("editable-input");
                input.value = item.name;
                input.addEventListener("click", function (event) {
                    event.stopPropagation();
                    input.focus();
                    input.style.width = "130px";
                    console.log("Input clicked, setting width to 130px");
                });
                input.addEventListener("blur", function () {
                    input.classList.remove("editing");
                    input.style.width = "65px";
                    updateRowData(input);
                });
                input.addEventListener("keydown", function (event) {
                    if (event.key === "Escape" || event.key === "Enter") {
                        input.classList.remove("editing");
                        input.blur();
                        input.style.width = "65px";
                        updateRowData(input);
                    }
                });
                input.addEventListener("input", function () {
                    updateRowData(input);
                });

                // Ajouter un gestionnaire d'événements pour détecter les clics sur la première cellule
                input.addEventListener("click", function () {
                    toggleSelection(specialRow);
                });

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

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

                specialRow.appendChild(firstCell);

                const mergedCell = document.createElement("td");
                mergedCell.colSpan = 2;
                mergedCell.textContent = "";
                specialRow.appendChild(mergedCell);

                const td = document.createElement("td");
                td.textContent = `${item.name} - Détails`;
                td.colSpan = document.querySelector("thead tr:nth-child(2)").cells.length - 3;
                specialRow.appendChild(td);

                tableBody.appendChild(specialRow);

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

        // Afficher les liaisons dans la console
        displayLinkages();
    }

    /*********************************************************************************************/

    document.getElementById("logButton").addEventListener("click", function () {
        const tableData = traceTable();
        displayJSONData(tableData);
    });

    /*********************************************************************************************/

    function displayJSONData(data) {
        const jsonOutputElement = document.getElementById("jsonOutput");
        const jsonOutput = JSON.stringify(data, null, 2);
        jsonOutputElement.textContent = jsonOutput;
    }

</script>

</body>
</html>