Нужно сделать возможность показать и скрыть такие элементы как "Показать только RPA" , "Поиск по номеру" , "Начать DL установка", "Экспорт Excel", чтобы это работало с данными элементами. Можно просто сделать стрелку чуть выше экспорта Excel вниз и вверх. Вниз значит элементы видны, а вверх значит скрывает элементы. Сделать плавно
<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Рабочая таблица</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='styles_welcome.css') }}">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="{{ url_for('static', filename='js/utils.js') }}"></script>
    <script src="{{ url_for('static', filename='js/table.js') }}"></script>
    <script src="{{ url_for('static', filename='js/date.js') }}"></script>
    <script src="{{ url_for('static', filename='js/statistics.js') }}"></script>
    <script src="{{ url_for('static', filename='js/connectedUser.js') }}"></script>
</head>
<body>
    <div class="header">
        <h1>Рабочая таблица</h1>
        <div class="user-info">
            <span>Пользователь: {{ name }}</span>
            <a href="/logout" class="logout-button">Выход</a>
        </div>
    </div>

    <div class="content-wrapper">
        <div class="date-selector">
            <select id="day">
             
            </select>
            <select id="month">
                <option value="01">Январь</option>
                <option value="02">Февраль</option>
                <option value="03">Март</option>
                <option value="04">Апрель</option>
                <option value="05">Май</option>
                <option value="06">Июнь</option>
                <option value="07">Июль</option>
                <option value="08">Август</option>
                <option value="09">Сентябрь</option>
                <option value="10">Октябрь</option>
                <option value="11">Ноябрь</option>
                <option value="12">Декабрь</option>
            </select>
            <select id="year">
                <!-- JavaScript заполнит годы -->
            </select>
        </div>
        
        <div class="search-container">
            <input type="text" id="searchInput" placeholder="Поиск по номеру...">
            <button id="searchButton">Найти</button>
        </div>

        <div class="statistics-container">
            <div class="stat-box">
                <span class="stat-label">Всего записей:</span>
                <span class="stat-value" id="totalRecords">0</span>
            </div>
            <div class="stat-box">
                <span class="stat-label">Записей за последний час:</span>
                <span class="stat-value" id="lastHourRecords">0</span>
            </div>
        </div>
        <div class="active-users-box">
            <h4>Активные пользователи:</h4>
            <table id="activeUsersTable">
                <thead>
                    <tr>
                        <th>Имя</th>
                        <th>Записей сегодня</th>
                    </tr>
                </thead>
                <tbody id="activeUsersBody">
                </tbody>
            </table>
        </div>
        
        <div class="table-container">
            <table border="1" id="dataTable">
                <thead>
                    <tr>
                        {% for header in table[0] %}
                            {% if header in ["Имя отправителя", "Время создания", "Время упаковки", "Тип АРМА"] %}
                                <th class="sortable" data-column="{{ loop.index0 }}">{{ header }}</th>
                            {% elif loop.index0 == 1 %}
                                <th class="sortable" data-column="1">{{ header }}</th>
                            {% elif loop.index0 == 2 %}
                                <th class="sortable" data-column="2">{{ header }}</th>
                            {% elif loop.index0 == 6 %}
                                <th class="sortable" data-column="6">{{ header }}</th>
                            {% elif loop.index0 == 7 %}  <!-- Новый столбец "Тип АРМА" -->
                                <th class="sortable" data-column="7">{{ header }}</th>
                            {% else %}
                                <th>{{ header }}</th>
                            {% endif %}
                            
                        {% endfor %}
                    </tr>
                </thead>
                
                
                
                
                <tbody id="tableBody">
                    {% for row in table[1:] %}
                        <tr>
                            {% for cell in row %}
                                <td class="{% if loop.index0 == 2 %}editable{% endif %}">{{ cell }}</td>
                            {% endfor %}
                        </tr>
                    {% endfor %}
                </tbody>
            </table>
        </div>

        <div class="controls-container">
            <div class="dl-control">
                <div class="dl-row">
                    <label for="initial-dl">Начать DL:</label>
                    <input type="text" id="initial-dl" placeholder="Введите значение">
                </div>
                <button onclick="setInitialDL()">Установить</button>
            </div>
            <div class="export-container">
                <button class="export-button">Экспорт в Excel</button>
            </div>
            
        </div>
        <div class="notification" id="notification"></div>
        <div class="filter-container">
            <label>
                <input type="checkbox" id="armaFilter">
                Показать только RPA
            </label>
        </div>
    </div>
</body>
</html>
let isEditing = false;
let searchTimeout;
let lastUpdateTime = 0;
const updateInterval = 1000;
let eventSource;
let lastData = null;

// Глобальные переменные для отслеживания сортировки
let globalSortColumn = null;
let globalSortOrder = 'asc';

function getSelectedDate() {
    return $('#datepicker').val();
}

// Функция для получения состояния фильтра
function getArmaFilter() {
    return $('#armaFilter').is(':checked') ? 'RPA' : '';
}

function updateTable(force = false, highlightNew = false) {
    return new Promise((resolve, reject) => {
        const now = Date.now();
        if (!force && now - lastUpdateTime < updateInterval) {
            resolve();
            return;
        }
        if (isEditing) {
            resolve();
            return;
        }

        $.ajax({
            url: '/get_table_data',
            type: 'GET',
            data: { date: getSelectedDate(),
            filter_arma: getArmaFilter()
             },
            success: function(response) {
                var tableBody = $('#tableBody');

                // Обновляем содержимое таблицы
                updateTableContent(response.data, tableBody, highlightNew);

                // Применяем текущую сортировку
                if (globalSortColumn !== null) {
                    sortTable(globalSortColumn, globalSortOrder);
                }

                updateStatistics();
                lastUpdateTime = now;

                // Проверяем и подсвечиваем дубликаты
                highlightDuplicates(response.duplicates);

                resolve();
            },
            error: function(xhr, status, error) {
                console.error('Error updating table:', error);
                reject(error);
            }
        });
    });
}

function highlightDuplicates(duplicates) {
    // Очищаем предыдущие выделения
    $('#tableBody td').removeClass('duplicate-highlight');

    // Подсвечиваем дубликаты номеров
    for (let number in duplicates.numbers) {
        duplicates.numbers[number].forEach(index => {
            $(`#tableBody tr:eq(${index}) td:nth-child(3)`).addClass('duplicate-highlight');
        });
    }

    // Подсвечиваем дубликаты серийных номеров
    for (let serial in duplicates.serials) {
        duplicates.serials[serial].forEach(index => {
            $(`#tableBody tr:eq(${index}) td:nth-child(4)`).addClass('duplicate-highlight');
        });
    }
}

function updateCell(cell, newValue, rowId, cellIndex, rowData) {
    console.log(`Updating cell: index=${cellIndex}, value=${newValue}, rowId=${rowId}`);

    const excludedArmaTypes = ["CFA", "VND", "SRC"];

    if (cellIndex === 4) { // Столбец "Графа"
        if (rowData.arma_type === 'RPA' && !excludedArmaTypes.includes(rowData.arma_type)) {
            if (newValue && newValue.startsWith('DL')) {
                cell.text(newValue)
                    .addClass('clickable')
                    .css('cursor', 'pointer')
                    .off('click') // Удаляем предыдущие обработчики
                    .on('click', function() {
                        copyToClipboard(newValue);
                        $(this).addClass('copied');
                        setTimeout(() => {
                            $(this).removeClass('copied');
                        }, 200);
                    });
            } else {
                cell.html('<button class="generate-button">Генерировать</button>')
                    .find('button')
                    .click(function() {
                        generateDL(rowId);
                    });
            }
        } else if (!excludedArmaTypes.includes(rowData.arma_type)) {
            if (newValue && newValue.startsWith('DL')) {
                cell.text(newValue)
                    .addClass('clickable')
                    .css('cursor', 'pointer')
                    .off('click')
                    .on('click', function() {
                        copyToClipboard(newValue);
                        $(this).addClass('copied');
                        setTimeout(() => {
                            $(this).removeClass('copied');
                        }, 200);
                    });
            } else {
                cell.text(newValue || '');
            }
        } else {
            cell.text(newValue || '');
        }
    } else if (cellIndex === 6) { // Столбец "Время упаковки"
        const dlCell = cell.parent().find('td').eq(4);
        const dlValue = dlCell.text().trim();
        const armaType = rowData.arma_type;

        if (dlValue.startsWith('DL') && !newValue && !excludedArmaTypes.includes(armaType)) {
            cell.html('<button class="pack-button">Упаковать</button>')
                .find('button')
                .click(function() {
                    packItem(rowId);
                });
        } else {
            cell.text(newValue);
        }
    } else if (cellIndex === 7) { // Столбец "Тип АРМА"
        if (!newValue || newValue.trim() === '') {
            newValue = 'RPA';
        }
        cell.text(newValue)
            .toggleClass('editable', true)
            .attr('data-column', cellIndex);
    } else {
        cell.text(newValue)
            .toggleClass('editable', cellIndex === 2 || cellIndex === 3)
            .attr('data-column', cellIndex);
    }
}

function sortTable(column, order) {
    const rows = $('#tableBody > tr').get();

    rows.sort(function(a, b) {
        let A = $(a).children('td').eq(column).text().trim();
        let B = $(b).children('td').eq(column).text().trim();

        // Обработка пустых значений
        if (A === '' && B === '') return 0;
        if (A === '') return order === 'asc' ? 1 : -1;
        if (B === '') return order === 'asc' ? -1 : 1;

        // Различные типы данных в зависимости от столбца
        if (column === 1 || column === 6) {  // Столбцы с датой или временем
            const dateA = new Date(A.replace(/(\d{2})\.(\d{2})\.(\d{4}) (\d{2}):(\d{2}):(\d{2})/, '$3-$2-$1T$4:$5:$6'));
            const dateB = new Date(B.replace(/(\d{2})\.(\d{2})\.(\d{4}) (\d{2}):(\d{2})\:(\d{2})/, '$3-$2-$1T$4:$5:$6'));
            return order === 'asc' ? dateA - dateB : dateB - dateA;
        }

        if (column === 0 || column === 2) {  // Столбцы с числами (№ и Номер)
            const numA = parseFloat(A) || 0;
            const numB = parseFloat(B) || 0;
            return order === 'asc' ? numA - numB : numB - numA;
        }

        if (column === 5) {  // Столбец с именем workers
            A = A.toLowerCase();
            B = B.toLowerCase();
        }

        // Строковое сравнение для остальных столбцов
        A = A.toUpperCase();
        B = B.toUpperCase();
        if (A < B) return order === 'asc' ? -1 : 1;
        if (A > B) return order === 'asc' ? 1 : -1;
        return 0;
    });

    // Очистка тела таблицы
    $('#tableBody').empty();

    // Получаем список типов АРМА, для которых не нужны кнопки
    const excludedArmaTypes = ["CFA", "VND", "SRC"];

    // Добавление отсортированных строк
    $.each(rows, function(index, row) {
        const $row = $(row);
        const rowId = $row.attr('data-id');

        const armaType = $row.find('td:eq(7)').text().trim(); // Столбец "Тип АРМА"

        // Обработка ячейки "Графа" (dl_number)
        const dlCell = $row.find('td:eq(4)');
        const dlValue = dlCell.text().trim();
        const packCell = $row.find('td:eq(6)'); // Столбец "Время упаковки"

        // Очищаем предыдущие кнопки
        if (!$row.hasClass('packed-row')) {
            if (armaType === 'RPA' && !excludedArmaTypes.includes(armaType)) {
                if (!dlValue.startsWith('DL')) {
                    dlCell.html('<button class="generate-button">Генерировать</button>')
                        .find('button')
                        .click(function() {
                            generateDL(rowId);
                        });
                }
            }
        }

        if (dlValue.startsWith('DL') && !packCell.text().trim() && !excludedArmaTypes.includes(armaType)) {
            packCell.html('<button class="pack-button">Упаковать</button>')
                .find('button')
                .click(function() {
                    packItem(rowId);
                });
        }

        // Добавляем строку в таблицу
        $('#tableBody').append($row);
    });

    checkDuplicates();
}

function generateDL(rowId) {
    console.log(`Generating DL for row ID ${rowId}`);
    const selectedDate = getSelectedDate();
    console.log("Selected date:", selectedDate);

    $.ajax({
        url: '/generate_dl',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            id: rowId,
            date: selectedDate
        }),
        success: function(response) {
            if (response.status === 'success') {
                console.log('DL успешно сгенерирован:', response.dl_number);
                var row = $(`#tableBody tr[data-id='${rowId}']`);
                var dlCell = row.find('td:eq(4)');
                var packCell = row.find('td:eq(6)'); // Столбец "Время упаковки"
                var armaType = row.find('td:eq(7)').text().trim();

                dlCell.text(response.dl_number)
                    .addClass('clickable')
                    .css('cursor', 'pointer')
                    .off('click') // Удаляем предыдущие обработчики
                    .on('click', function() {
                        copyToClipboard(response.dl_number);
                        $(this).addClass('copied');
                        setTimeout(() => {
                            $(this).removeClass('copied');
                        }, 200);
                    });

                // Добавляем кнопку упаковки только если arma_type не исключен
                const excludedArmaTypes = ["CFA", "VND", "SRC"];
                if (!excludedArmaTypes.includes(armaType)) {
                    packCell.html('<button class="pack-button">Упаковать</button>')
                        .find('button')
                        .click(function() {
                            packItem(rowId);
                        });
                }
            } else {
                alert('Ошибка при генерации DL: ' + response.message);
            }
        },
        error: function(xhr, status, error) {
            console.error('Ошибка при генерации DL:', status, error);
            alert('Ошибка при генерации DL: ' + error);
        }
    });
}

function packItem(rowId) {
    console.log(`Упаковка элемента для строки ID ${rowId}`);
    const selectedDate = getSelectedDate();
    console.log("Selected date:", selectedDate);

    $.ajax({
        url: '/pack_item',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({
            id: rowId,
            date: selectedDate
        }),
        success: function(response) {
            console.log("Ответ сервера:", response);
            if (response.status === 'success') {
                var row = $(`#tableBody tr[data-id='${rowId}']`);
                row.addClass('packed-row');
                var cell = row.find('td:eq(6)'); // Столбец "Время упаковки"
                cell.text(response.pack_time);
                updateStatistics();

                // Удаляем кнопку "Упаковать", так как запись уже упакована
                cell.find('button.pack-button').remove();
            } else {
                alert('Ошибка при упаковке: ' + response.message);
            }
        },
        error: function(xhr, status, error) {
            console.error("Ошибка AJAX:", xhr, status, error);
            alert('Ошибка при упаковке: ' + error);
        }
    });
}

function areSimilarNumbers(num1, num2) {
    // Очищаем строки от нецифровых символов и пробелов
    const clean1 = num1.toString().replace(/\D/g, '').trim();
    const clean2 = num2.toString().replace(/\D/g, '').trim();
    
    // Если строки пустые или разной длины - не дубликаты
    if (!clean1 || !clean2 || clean1.length !== clean2.length) {
        return false;
    }
    
    // Проверяем на точное совпадение
    return clean1 === clean2;
}

function checkDuplicates() {
    console.log("Checking for duplicates...");
    const rows = $('#tableBody tr');
    
    // Очищаем предыдущие выделения
    rows.find('td').removeClass('duplicate-highlight');
    
    // Создаем массивы для хранения номеров и их индексов
    const numbers = new Map();
    const serials = new Map();
    
    // Собираем все номера и серийные номера
    rows.each(function(index) {
        const number = $(this).find('td:nth-child(3)').text().trim();
        const serial = $(this).find('td:nth-child(4)').text().trim();
        
        if (number) {
            if (!numbers.has(number)) {
                numbers.set(number, []);
            }
            numbers.get(number).push(index);
        }
        
        if (serial) {
            if (!serials.has(serial)) {
                serials.set(serial, []);
            }
            serials.get(serial).push(index);
        }
    });
    
    // Подсвечиваем дубликаты
    let duplicatesFound = false;
    
    // Проверяем номера
    numbers.forEach((indices, number) => {
        if (indices.length > 1) {
            indices.forEach(index => {
                rows.eq(index).find('td:nth-child(3)').addClass('duplicate-highlight');
            });
            duplicatesFound = true;
        }
    });
    
    // Проверяем серийные номера
    serials.forEach((indices, serial) => {
        if (indices.length > 1) {
            indices.forEach(index => {
                rows.eq(index).find('td:nth-child(4)').addClass('duplicate-highlight');
            });
            duplicatesFound = true;
        }
    });

    return duplicatesFound;
}

function appendNewRow(tableBody, rowData) {
    console.log("Добавление новой строки:", rowData);

    // Создаем элемент строки и присваиваем уникальный data-id
    var tr = $('<tr>').attr('data-id', rowData.id);

    // Если есть время упаковки и это не заголовок, добавляем класс 'packed-row'
    if (rowData.pack_time && rowData.pack_time !== "Время упаковки") {
        tr.addClass('packed-row');
    }

    // Добавляем ячейки в строку
    tr.append($('<td>').text(rowData.row_number));
    tr.append($('<td>').text(rowData.timestamp));
    tr.append($('<td>').text(rowData.number));
    tr.append($('<td>').text(rowData.serial));

    /**
     * Обработка ячейки "Графа" (dl_number)
     */
    var dlCell = $('<td>');

    // Список типов АРМА, для которых не нужны кнопки
    const excludedArmaTypes = ["CFA", "VND", "SRC"];

    if (rowData.arma_type === 'RPA' && !excludedArmaTypes.includes(rowData.arma_type)) {
        // Для типа АРМА 'RPA', проверяем наличие и формат dl_number
        if (!rowData.dl_number || !rowData.dl_number.startsWith('DL')) {
            // Если dl_number отсутствует или не начинается с 'DL', отображаем кнопку "Генерировать"
            dlCell.html('<button class="generate-button">Генерировать</button>')
                .find('button')
                .click(function() {
                    generateDL(rowData.id); // Передаем уникальный ID строки
                });
        } else {
            // Если dl_number присутствует и начинается с 'DL', делаем его кликабельным для копирования
            dlCell.text(rowData.dl_number)
                .addClass('clickable')
                .css('cursor', 'pointer')
                .on('click', function() {
                    copyToClipboard(rowData.dl_number);
                    $(this).addClass('copied');
                    setTimeout(() => {
                        $(this).removeClass('copied');
                    }, 200);
                });
        }
    } else if (!excludedArmaTypes.includes(rowData.arma_type)) {
        // Для других типов АРМА, которые не исключены, отображаем или скрываем кнопку
        if (rowData.dl_number && rowData.dl_number.startsWith('DL')) {
            dlCell.text(rowData.dl_number)
                .addClass('clickable')
                .css('cursor', 'pointer')
                .on('click', function() {
                    copyToClipboard(rowData.dl_number);
                    $(this).addClass('copied');
                    setTimeout(() => {
                        $(this).removeClass('copied');
                    }, 200);
                });
        } else {
            dlCell.text(rowData.dl_number || '');
        }
    } else {
        // Для типов АРМА "CFA", "VND", "SRC" оставляем ячейку пустой или с текущим значением
        dlCell.text(rowData.dl_number || '');
    }

    tr.append(dlCell);

    // Добавляем ячейку с именем отправителя
    tr.append($('<td>').text(rowData.worker_name));

    /**
     * Обработка ячейки "Время упаковки" (pack_time)
     */
    var packCell = $('<td>');

    if (rowData.dl_number && rowData.dl_number.startsWith('DL') && !rowData.pack_time && !excludedArmaTypes.includes(rowData.arma_type)) {
        // Если dl_number с 'DL', pack_time отсутствует и arma_type не исключен, показываем кнопку "Упаковать"
        packCell.html('<button class="pack-button">Упаковать</button>')
            .find('button')
            .click(function() {
                packItem(rowData.id); // Передаем уникальный ID строки
            });
    } else {
        // Иначе отображаем время упаковки или оставляем пустым
        packCell.text(rowData.pack_time || '');
    }

    tr.append(packCell);

    // Добавляем ячейку с типом АРМА
    tr.append($('<td>').text(rowData.arma_type || ''));

    // Добавляем ячейку с последней графой
    tr.append($('<td>').text(rowData.last_graf || ''));

    /**
     * Добавление ячейки "Действие" с кнопкой "Удалить"
     */
    var actionTd = $('<td>');
    var deleteButton = $('<button>').text('Удалить').addClass('delete-button');
    deleteButton.click(function() {
        deleteRow(rowData.id); // Передаем уникальный ID строки
    });
    actionTd.append(deleteButton);
    tr.append(actionTd);

    // Добавляем строку в тело таблицы
    tableBody.append(tr);

    /**
     * Дополнительная обработка после добавления строки
     */
    setTimeout(() => {
        const dlValue = dlCell.text().trim();
        const packValue = packCell.text().trim();

        if (dlValue.startsWith('DL') && !packValue && !excludedArmaTypes.includes(rowData.arma_type)) {
            console.log('Добавляем кнопку упаковки для DL:', dlValue);
            packCell.html('<button class="pack-button">Упаковать</button>')
                .find('button')
                .click(function() {
                    packItem(rowData.id); // Передаем уникальный ID строки
                });
        }

        // Проверяем дубликаты после добавления новой строки
        checkDuplicates();
    }, 100);
}

function updateTableContent(data, tableBody, highlightNew = false) {
    tableBody.empty();  // Очищаем текущее содержимое таблицы
    data.forEach(function(rowData, index) {
        appendNewRow(tableBody, rowData);
        if (highlightNew && index === data.length - 1) {
            // Можно добавить подсветку новой строки, если нужно
            // Например:
            // $('tr:last').addClass('highlight-new').fadeOut(2000, function() {
            //     $(this).removeClass('highlight-new');
            // });
        }
    });
    checkDuplicates();  // Проверяем дубликаты после обновления таблицы
}

function scheduleNextUpdate() {
    setTimeout(() => {
        if (!isEditing) {
            updateTable(false, false).then(() => {
                scheduleNextUpdate();
            });
        } else {
            scheduleNextUpdate();
        }
    }, 3000);
}

function initializeEventSource() {
    if (eventSource) {
        eventSource.close();
    }

    eventSource = new EventSource('/stream');

    eventSource.onmessage = function(event) {
        const data = JSON.parse(event.data);
        if (data.type === 'update' && data.date === getSelectedDate()) {
            updateTable(true);
        }
    };

    eventSource.onerror = function(error) {
        console.error('EventSource failed:', error);
        eventSource.close();
        setTimeout(initializeEventSource, 5000);  // Попытка переподключения через 5 секунд
    };
}

// Обработчики событий для таблицы
$(document).ready(function() {
    initializeDateSelectors(); // Убедитесь, что эта функция определена
    updateTable();
    updateStatistics(); // Убедитесь, что эта функция определена
    initializeEventSource();
    scheduleNextUpdate();
    loadCurrentDL();
    // Обработчик сортировки
    $('.sortable').click(function() {
        const column = $(this).data('column');
        const order = $(this).hasClass('asc') ? 'desc' : 'asc';
        
        // Удаляем классы сортировки со всех заголовков
        $('.sortable').removeClass('asc desc');
        // Добавляем класс текущей сортировки
        $(this).addClass(order);
        
        // Сохраняем текущие параметры сортировки
        globalSortColumn = column;
        globalSortOrder = order;
        
        // Сортируем таблицу
        sortTable(column, order);
    });

    // Обработчик поиска
    $('#searchButton').click(function() {
        searchNumber();
    });
    $('#searchInput').keypress(function(e) {
        if (e.which === 13) {
            searchNumber();
        }
    });
    $('#armaFilter').on('change', function() {
        updateTable();
    });
});

// Обработчик изменения даты
$('#datepicker').on('change', function() {
    initializeEventSource();
    updateTable();
});

// Обработчик экспорта в Excel
$(document).ready(function() {
    $('.export-button').on('click', function(e) {
        e.preventDefault();
        
        // Получаем информацию о сортировке
        const sortableColumn = $('.sortable.asc, .sortable.desc');
        const sortColumn = sortableColumn.length ? sortableColumn.data('column') : '';
        const sortOrder = $('.sortable.asc').length ? 'asc' : 'desc';
        
        // Формируем URL
        const date = getSelectedDate();
        const queryParams = new URLSearchParams({
            date: date,
            sort_column: sortColumn || '',
            sort_order: sortOrder
        });
        
        // Создаем и отправляем запрос
        fetch(`/export_excel?${queryParams.toString()}`)
        .then(response => {
            if (response.ok) {
                return response.blob();
            }
            throw new Error('Network response was not ok.');
        })
        .then(blob => {
            // Создаем ссылку для скачивания
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = `export_${date}.xlsx`;
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(url);
            a.remove();
        })
        .catch(error => {
            console.error('Error:', error);
            alert('Ошибка при экспорте файла');
        });
    });
});

// Инициализация выбора даты с помощью flatpickr
let currentDate;

$(document).ready(function() {
    flatpickr("#datepicker", {
        dateFormat: "Y-m-d",
        defaultDate: "today",
        onChange: function(selectedDates, dateStr, instance) {
            currentDate = dateStr;
            updateTable();
        }
    });

    currentDate = new Date().toISOString().split('T')[0];
    initializeEventSource();
    updateTable();
    updateStatistics();
});

// Обработчик двойного клика для редактирования ячеек
$(document).on('dblclick', '.editable', function() {
    isEditing = true;
    var td = $(this);
    var currentValue = td.text();
    var input = $('<input type="text">')
        .val(currentValue)
        .addClass('edit-input');
    
    td.html(input);
    input.focus();

    input.on('blur', function() {
        var newValue = $(this).val();
        var rowIndex = td.parent().index();
        var columnIndex = td.attr('data-column');
        
        const url = columnIndex === '2' ? '/update_number' : '/update_serial';
        
        $.ajax({
            url: url,
            type: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({
                row_index: rowIndex,
                new_value: newValue,
                date: getSelectedDate()
            }),
            success: function(response) {
                if (response.status === 'success') {
                    td.text(newValue);
                    const duplicatesFound = checkDuplicates();
                    console.log("Duplicates found after edit:", duplicatesFound)
                } else {
                    alert('Ошибка при обновлении значения');
                    td.text(currentValue);
                }
                isEditing = false;
            },
            error: function() {
                alert('Ошибка при отправке данных');
                td.text(currentValue);
                isEditing = false;
            }
        });
    });

    input.on('keypress', function(e) {
        if (e.which === 13) {
            $(this).blur();
        }
    });
});

function searchNumber() {
    const searchValue = $('#searchInput').val().trim();
    if (!searchValue) return;

    // Удаляем предыдущую подсветку
    $('.highlight-search').removeClass('highlight-search');

    const rows = $('#tableBody tr');
    let found = false;

    rows.each(function() {
        const numberCell = $(this).find('td:nth-child(3)');
        const cellText = numberCell.text().trim();
        if (cellText === searchValue) {
            numberCell.addClass('highlight-search');
            
            // Прокрутка к найденной строке
            $('.table-container').animate({
                scrollTop: $(this).offset().top - $('.table-container').offset().top + $('.table-container').scrollTop() - 100
            }, 500);

            found = true;

            // Устанавливаем таймер на удаление подсветки через 3 секунды
            setTimeout(() => {
                numberCell.removeClass('highlight-search');
            }, 3000);

            // Выводим сообщение в консоль для отладки
            console.log('Найдено совпадение:', cellText);

            return false; // Прерываем цикл, так как нашли нужную строку
        }
    });

    if (!found) {
        alert('Точное совпадение номера не найдено');
    }
}

function deleteRow(rowId) {
    $.ajax({
        url: '/delete_row',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({ id: rowId }),
        success: function(response) {
            if (response.status === 'success') {
                // Удаляем строку из таблицы без уведомления
                $(`tr[data-id='${rowId}']`).remove();
            } else {
                // Логируем ошибку в консоль вместо alert
                console.error('Ошибка при удалении записи:', response.message);
            }
        },
        error: function(xhr, status, error) {
            // Логируем ошибку в консоль вместо alert
            console.error('Произошла ошибка при удалении записи:', error);
        }
    });
}

function loadCurrentDL() {
    const selectedDate = getSelectedDate();
    $.ajax({
        url: '/get_current_dl',
        type: 'GET',
        data: { date: selectedDate },
        success: function(response) {
            if (response.status === 'success') {
                $('#initial-dl').val(response.current_dl);
            } else {
                $('#initial-dl').val(''); // Можно установить значение по умолчанию или показать сообщение
                console.warn(response.message);
            }
        },
        error: function(xhr, status, error) {
            console.error('Ошибка при получении текущего DL:', error);
            $('#initial-dl').val('');
        }
    });
}


:root {
    --primary-color: #5c5c5c;
    --secondary-color: #2b2b2b;
    --background-color: #ecf0f1;
    --text-color: #34495e;
    --hover-color: #e74c3c;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
/* Центрирование контейнера */
body {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    margin: 0 auto;
    font-family: Arial, sans-serif;
    background-color: #f4f4f9;
    zoom: 1.22;
    overflow-y: hidden;
}

.content-wrapper {
    max-width: 1200px;
    margin: 80px auto 20px;
    padding: 20px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 20px;
}

.table-container {
    text-align: center;
    margin-top: -180px;
    margin-right: 120px;
    height: 500px;
    overflow-y: auto;
    overflow-x: hidden;
}

/* Оформление заголовка */
h3 {
    margin: 0;
    padding-bottom: 60px;
    font-size: 30px;
    color: #333;
}

/* Стиль таблицы */
table {
    border-collapse: collapse;
    width: 100%;
    max-width: 1100px;
    margin: 0 auto;
    background-color: #fff;
    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
}

th {
    width: 400px;
    padding: 10px;
    border: 1px solid #ddd;
    text-align: center;
    background-color: #71d693;
    color: rgb(0, 0, 0);
    height: 30px;
}

td {
    height: 50px;
    padding: 10px;
    border: 1px solid #ddd;
    text-align: center;
    vertical-align: middle;
    min-width: 120px;
}


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

tbody tr:hover {
    background-color: #e0f7fa;
}

.editable {
    cursor: pointer;
}

.editable:hover {
    background-color: #f0f0f0;
}

.edit-input {
    width: 90%;
    height: 80%;
    padding: 5px;
    border: 1px solid #4CAF50;
    border-radius: 4px;
    text-align: center;
}

.edit-input:focus {
    outline: none;
    border-color: #45a049;
    box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
}

.dl-control {
    padding: 20px 25px;
    border-radius: 8px;
    margin: 10px auto;
    max-width: 400px;
    font-family: Arial, sans-serif;
    position: relative;
    left: 360px; /* Это смещение может вызывать проблемы с выравниванием */
}

.dl-row {
    display: flex;
    align-items: center; /* Выравнивание по вертикали */
    margin-bottom: 10px; /* Отступ снизу между строкой и кнопкой */
}

.dl-row label {
    min-width: 110px;
    font-weight: bold;
    color: #333;
}

.dl-row input {
    flex: 1;
    padding: 10px 12px;
    border: 1px solid #ccc;
    border-radius: 6px;
    font-size: 16px;
    transition: border-color 0.3s, box-shadow 0.3s;
}

.dl-row input:focus {
    border-color: #4CAF50;
    box-shadow: 0 0 5px rgba(76, 175, 80, 0.5);
    outline: none;
}

.dl-control button {
    width: 300px; /* Жесткая ширина может вызвать проблемы на разных экранах */
    padding: 12px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 6px;
    position: relative;
    left: 20px;
    font-size: 16px;
    cursor: pointer;
    transition: background-color 0.3s, transform 0.2s, margin-top 0.3s;
}

.dl-control button:hover {
    background-color: #45a049;
    transform: translateY(-2px);
}

.dl-control button:active {
    transform: translateY(0);
}

.dl-control input::placeholder {
    color: #aaa;
    font-style: italic;
}


.controls-container {
    display: flex;
    justify-content: space-between;
    width: 100%;
    gap: 20px;
    position: relative; /* Убедитесь, что контейнер имеет относительное позиционирование */
}


/* Стиль для эффекта копирования */
.copied {
    background-color: #e8f5e9 !important;
    transition: background-color 0.2s;
}

/* Стили для уведомления */
.notification {
    position: fixed;
    bottom: 20px;
    right: 20px;
    background-color: #333;
    color: white;
    padding: 10px 20px;
    border-radius: 4px;
    z-index: 1000;
    animation: fadeIn 0.3s, fadeOut 0.3s 1.7s;
}

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes fadeOut {
    from {
        opacity: 1;
        transform: translateY(0);
    }
    to {
        opacity: 0;
        transform: translateY(20px);
    }
}

/* Стиль для ячеек с DL номером */
td[onclick] {
    cursor: pointer;
}

td[onclick]:hover {
    background-color: #f5f5f5;
}


.statistics-container {
    display: flex;
    position: fixed;
    right: 0;
    top: 60px;
    justify-content: flex-end;
    gap: 20px;
    padding: 15px;
    margin-bottom: 20px;
}

.stat-box {
    background-color: #f8f9fa;
    padding: 10px 15px;
    border-radius: 6px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.stat-label {
    font-weight: 500;
    color: #666;
    margin-right: 8px;
}

.stat-value {
    font-weight: 600;
    color: #2196F3;
}

.export-container {
    text-align: center;
    position: relative;
    left: 230px;
    /* Убираем fixed и absolute позиционирование */
    margin-top: 65px;
    zoom: 1.2;
    flex: 1; /* Позволяет контейнеру занимать доступное пространство */
    display: flex; /* Используем flex для центрирования содержимого */
    justify-content: center; /* Центрируем содержимое */
}

.export-button {
    text-align: center;
    vertical-align:middle;
    display: inline-block;
    background-color: #4CAF50;
    color: white;
    outline: none;
    text-decoration: none;
    border-radius: 4px;
    font-weight: bold;
    transition: background-color 0.3s;
    width: 140px;
    height: 35px;
    border: none;
    cursor: pointer;
}

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

.duplicate-highlight {
    background-color: #ffcad1 !important;
    transition: background-color 0.3s;
}

.editable {
    cursor: pointer;
}


.date-selector {
    margin: 20px 0;
    padding: 10px;
    position: absolute;
    top: 50px;
    left:20px;
    background-color: #f5f5f5; /* Light background for the date selector */
    border-radius: 5px; /* Rounded corners */
    display: flex;
    gap: 10px; /* Space between the dropdowns */
    justify-content: center; /* Center the dropdowns */
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* Subtle shadow for depth */
}

.date-selector select {
    padding: 10px; /* Increased padding for better touch targets */
    font-size: 16px; /* Larger font size for readability */
    border: 1px solid #ddd; /* Light border */
    border-radius: 4px; /* Rounded corners */
    background-color: white; /* White background for dropdowns */
    transition: border-color 0.3s; /* Smooth transition for border color */
}

.date-selector select:focus {
    outline: none; /* Remove default outline */
    border-color: #007bff; /* Change border color on focus */
    box-shadow: 0 0 5px rgba(0, 123, 255, 0.5); /* Add shadow on focus */
}

.date-selector select option {
    padding: 10px; /* Padding for options */
}



.packed-row td {
    background-color: #e8f5e9 !important; /* светло-зеленый цвет */
}


.sortable {
    cursor: pointer;
    position: relative;
}

.sortable:after {
    content: '↕️';
    position: absolute;
    right: 4px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 12px;
}

.sortable.asc:after {
    content: '↑';
}

.sortable.desc:after {
    content: '↓';
}


/* Стиль для кнопки "Генерировать" */
td button {
    padding: 8px 15px;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-weight: 500;
    transition: background-color 0.3s;
}

/* Специфичный стиль для кнопки "Генерировать" */
td button:contains('Генерировать') {
    background-color: #007bff; /* синий цвет */
    color: white;
}

td button:contains('Генерировать'):hover {
    background-color: #0056b3; /* более темный синий при наведении */
}

/* Стиль для кнопки "Упаковать" остается зеленым */
td button:contains('Упаковать') {
    background-color: #4CAF50;
    color: white;
}

td button:contains('Упаковать'):hover {
    background-color: #45a049;
}


/* Стиль для кнопки "Генерировать" */
.generate-button {
    padding: 8px 15px;
    background-color: #007bff !important; /* синий цвет */
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-weight: 500;
    transition: background-color 0.3s;
}

.generate-button:hover {
    background-color: #0056b3 !important; /* более темный синий при наведении */
}

.header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    background-color: #fff;
    padding: 10px 20px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
    display: flex;
    justify-content: space-between;
    align-items: center;
    z-index: 1000;
}

.header h1 {
    margin: 0;
    font-size: 24px;
    color: #333;
}

.user-info {
    display: flex;
    align-items: center;
    gap: 20px;
}

.logout-button {
    padding: 8px 15px;
    background-color: #dc3545;
    color: white;
    text-decoration: none;
    border-radius: 4px;
    transition: background-color 0.3s;
}

.logout-button:hover {
    background-color: #c82333;
}

.search-container {
    position: relative; /* Используем фиксированное позиционирование */
    display: flex;
    gap: 10px;
    top: 415px;
    right: 430px;
    padding: 10px;
    background-color: #f5f5f5;
    border-radius: 5px;
    zoom: 1.2; /* Можно убрать, если не требуется */
    z-index: 1000; /* Убедитесь, что контейнер находится выше других элементов */
}

#searchInput {
    padding: 8px;
    border: 1px solid #ddd;
    border-radius: 4px;
    width: 200px; /* Можно использовать относительные единицы, например, % */
}

#searchButton {
    padding: 8px 15px;
    background-color: #4CAF50;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
}

#searchButton:hover {
    background-color: #45a049;
}


.highlight-search {
    background-color: yellow !important;
    transition: background-color 0.3s ease;
}



.pack-button {
    background-color: #4CAF50; /* Зеленый цвет */
    color: white; /* Белый текст */
    border: none; /* Без границы */
    padding: 10px 20px; /* Отступы */
    text-align: center; /* Центрирование текста */
    text-decoration: none; /* Без подчеркивания */
    display: inline-block; /* Инлайн-блок для правильного отображения */
    font-size: 12px; /* Размер шрифта */
    margin: 4px 2px; /* Отступы */
    cursor: pointer; /* Указатель при наведении */
    border-radius: 5px; /* Закругленные углы */
    transition: background-color 0.3s; /* Плавный переход цвета */
}

.pack-button:hover {
    background-color: #45a049; /* Темнее при наведении */
}


.new-highlight {
    animation: highlightFade 3s;
}

@keyframes highlightFade {
    from { background-color: #ffff99; }
    to { background-color: transparent; }
}

.duplicate-highlight {
    background-color: #ffcad1 !important; /* Светло-красный цвет для дубликатов */
    transition: background-color 0.3s;
}

.active-users-box {
    position: fixed;
    right: 60px;
    top: 160px;
    width: 350px;
    padding: 15px;
    background-color: white;
    border-radius: 8px;
    box-shadow: 0 4px 8px rgba(0,0,0,0.1);
    font-size: 14px;
    z-index: 1000;
    display: none;
}

.active-users-box h4 {
    margin-top: 0;
    margin-bottom: 10px;
    font-size: 16px;
    color: #333;
    text-align: center;
}

#activeUsersTable {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    margin-top: 10px;
}

#activeUsersTable th,
#activeUsersTable td {
    padding: 8px;
    text-align: left;
    border-bottom: 1px solid #eee;
}

#activeUsersTable th {
    background-color: #f8f8f8;
    font-weight: bold;
    color: #555;
    text-transform: uppercase;
    font-size: 12px;
}

#activeUsersTable tr:last-child td {
    border-bottom: none;
}

#activeUsersTable tr:hover {
    background-color: #f5f5f5;
}

/* Стили для скролла, если будет много пользователей */
#activeUsersBody {
    max-height: 200px;
    overflow-y: auto;
}

/* Стили для скроллбара */
#activeUsersBody::-webkit-scrollbar {
    width: 6px;
}

#activeUsersBody::-webkit-scrollbar-track {
    background: #f1f1f1;
}

#activeUsersBody::-webkit-scrollbar-thumb {
    background: #888;
    border-radius: 3px;
}

#activeUsersBody::-webkit-scrollbar-thumb:hover {
    background: #555;
}

.delete-button {
    background-color: rgb(255, 79, 79);
}

.filter-container {
    text-align: center;
    position: relative;
    bottom: 110px;
    right: 480px;
    zoom: 1.2;
    flex: 1; /* Позволяет контейнеру занимать доступное пространство */
    display: flex; /* Используем flex для центрирования содержимого */
    justify-content: center; /* Центрируем содержимое */
    
}