Ballaminut Networking - Sistema de produtividade

Ballaminut Networking - Sistema de produtividade

>>> Adicione as suas tarefas aqui!!!

Caixinha de Checklist e Agenda

Minha Agenda com Calendário Mensal e Horários

Histórico de Atividades Concluídas

Relatório de Atividades Bloqueantes

Relatório de Títulos de Projeto

Relatório Ordenado por Número

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Ballaminut Networking - Sistema de produtividade</title>
    <style>
        table {
            width: 100%;
            border-collapse: collapse;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
        }
        th {
            background-color: #f2f2f2;
        }
        td {
            vertical-align: top;
        }
        .checklist {
            margin-right: 5px;
        }
        .project-title-button {
            cursor: pointer;
            margin-left: 5px;
            padding: 2px 4px;
            font-size: 14px;
            background-color: transparent;
            color: green;
            border: none;
            border-radius: 3px;
        }
        .project-title-button:hover {
            color: darkgreen;
        }
        .project-title {
            border: 2px solid green;
        }
        .nested-list {
            margin-left: 20px;
            display: none;
        }
        .checklist-container {
            display: flex;
            flex-direction: column;
            margin: 10px 0;
        }
        .checklist-label {
            font-size: 18px;
            margin-left: 10px;
            text-decoration: none;
            cursor: pointer;
        }
        .checklist-label.completed {
            text-decoration: line-through;
        }
        .checklist-input {
            width: 20px;
            height: 20px;
            cursor: pointer;
            accent-color: orange;
        }
        .add-task-container {
            margin-bottom: 20px;
        }
        .add-task-input,
        .add-tag-input,
        .add-number-input,
        .add-person-input,
        .add-date-input,
        .add-end-date-input,
        .add-time-input,
        .add-amount-input,
        .add-reason-input,
        .add-location-input,
        .add-method-input {
            padding: 5px;
            font-size: 16px;
        }
        .add-task-button {
            margin-left: 10px;
            padding: 8px 16px;
            font-size: 16px;
            cursor: pointer;
            background-color: orange;
            color: white;
            border: none;
            border-radius: 5px;
        }
        .add-task-button:hover {
            background-color: black;
        }
        .remove-task-button {
            cursor: pointer;
            margin-left: 5px;
            padding: 2px 4px;
            font-size: 10px;
            background-color: white;
            color: gray;
            border: none;
            border-radius: 3px;
            opacity: 0.8;
        }
        .remove-task-button:hover {
            background-color: lightgray;
        }
        .edit-number-input,
        .edit-tag-input,
        .edit-person-input,
        .edit-date-input,
        .edit-end-date-input,
        .edit-time-input,
        .edit-amount-input,
        .edit-reason-input,
        .edit-location-input,
        .edit-method-input {
            width: 100px;
            font-size: 14px;
            padding: 2px;
            margin-left: 10px;
        }
        .filter-container {
            margin-bottom: 20px;
        }
        .filter-dropdown {
            padding: 5px;
            font-size: 16px;
        }
        .sort-button {
            padding: 5px 10px;
            font-size: 16px;
            cursor: pointer;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            margin-left: 10px;
        }
        .sort-button:hover {
            background-color: #0056b3;
        }
        .blocker-button {
            cursor: pointer;
            margin-left: 5px;
            padding: 2px 4px;
            font-size: 14px;
            background-color: transparent;
            color: red;
            border: none;
            border-radius: 3px;
        }
        .blocker-button:hover {
            color: darkred;
        }
        .blocker {
            background-color: #ffcccc;
        }
        .toggle {
            cursor: pointer;
            font-weight: bold;
            margin-right: 10px;
        }
        .calendar {
            display: flex;
            flex-wrap: wrap;
            gap: 5px;
            margin-top: 20px;
        }
        .calendar-month {
            width: 100%;
            text-align: center;
            font-weight: bold;
            margin: 20px 0;
        }
        .calendar-day {
            width: calc(100% / 7 - 10px);
            text-align: center;
            border: 1px solid #ccc;
            padding: 5px;
            cursor: pointer;
        }
        .calendar-day.occupied {
            background-color: #ccc;
        }
        .calendar-hour {
            font-size: 0.8em;
            margin-top: 2px;
        }
        .calendar-week {
            display: flex;
            justify-content: space-between;
            width: 100%;
        }
        .calendar-event {
            background-color: orange;
            color: white;
            margin: 2px 0;
            padding: 2px;
        }
        .calendar-event.end {
            background-color: blue;
            color: white;
        }
        .completed-tasks-container {
            margin-top: 40px;
        }
        .completed-task {
            text-decoration: line-through;
            color: gray;
        }
        .report-container {
            margin-top: 40px;
        }
        .report-item {
            margin-bottom: 10px;
        }
        .modal {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background-color: white;
            padding: 20px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
        }
    </style>
</head>
<body>
    <center><h1>Ballaminut Networking - Sistema de produtividade</h1>
    <table>
        <b>
        <subtitle> >>> Adicione as suas tarefas aqui!!!</subtitle>
        <br>
        <br>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Caixinha de Checklist e Agenda</title>
    </b></table>
    </center>
    <div class="add-task-container">
        <input type="text" id="newTask" class="add-task-input" placeholder="Digite uma nova tarefa" onkeydown="handleKeyPress(event)">
        <input type="text" id="newTag" class="add-tag-input" placeholder="Digite uma tag">
        <input type="number" id="newNumber" class="add-number-input" placeholder="Número" min="1">
        <input type="text" id="newPerson" class="add-person-input" placeholder="Atribuir a">
        <input type="date" id="newDate" class="add-date-input" placeholder="Data de realização">
        <input type="date" id="newEndDate" class="add-end-date-input" placeholder="Data de término">
        <input type="time" id="newTime" class="add-time-input" placeholder="Horário">
        <input type="number" id="newAmount" class="add-amount-input" placeholder="Quanto" step="0.01">
        <input type="text" id="newReason" class="add-reason-input" placeholder="Por que da tarefa?">
        <input type="text" id="newLocation" class="add-location-input" placeholder="Onde será a tarefa?">
        <input type="text" id="newMethod" class="add-method-input" placeholder="Como será feita essa tarefa?">
        <button onclick="addTask()" class="add-task-button">Adicionar Tarefa</button>
        <button onclick="addCustomField()" class="add-task-button">Adicionar Campo Personalizado</button>
        <button onclick="saveChecklistToFile()" class="add-task-button">Salvar Checklist</button>
        <button onclick="loadChecklistFromFile()" class="add-task-button">Carregar Checklist</button>
        <button onclick="window.print()" class="add-task-button">Imprimir Checklist</button>
        <button onclick="downloadHTMLBackup()" class="add-task-button">Baixar Backup HTML</button>
        <input type="file" id="uploadFile" class="add-task-button" style="display: none;" onchange="loadChecklistFromFile()">
        <button onclick="document.getElementById('uploadHTML').click()" class="add-task-button">Subir HTML</button>
        <input type="file" id="uploadHTML" class="add-task-button" style="display: none;" onchange="uploadHTML(event)">
    </div>
    <div class="filter-container">
        <label for="tagFilter">Filtrar por tag:</label>
        <select id="tagFilter" class="filter-dropdown" onchange="filterTasks()">
            <option value="">Todas</option>
        </select>
        <label for="personFilter">Filtrar por pessoa:</label>
        <select id="personFilter" class="filter-dropdown" onchange="filterTasks()">
            <option value="">Todas</option>
        </select>
        <label for="customFieldFilter">Filtrar por campo personalizado:</label>
        <input type="text" id="customFieldFilter" class="filter-dropdown" placeholder="Digite o valor exato" oninput="filterTasks()">
        <label for="keywordFilter">Filtrar por palavras-chave:</label>
        <input type="text" id="keywordFilter" class="filter-dropdown" placeholder="Digite a palavra-chave" oninput="filterTasks()">
        <button onclick="sortTasksByNumber()" class="sort-button">Ordenar por Número</button>
        <button onclick="filterBlockers()" class="sort-button">Mostrar Bloqueantes</button>
        <button onclick="generateBlockerReport()" class="sort-button">Gerar Relatório de Bloqueantes</button>
        <button onclick="filterProjectTitles()" class="sort-button">Mostrar Títulos de Projeto</button>
        <button onclick="generateProjectTitleReport()" class="sort-button">Gerar Relatório de Títulos de Projeto</button>
        <button onclick="generateSortedNumberReport()" class="sort-button">Gerar Relatório Ordenado por Número</button>
        <button onclick="downloadExcel()" class="sort-button">Baixar Checklist em Excel</button>
        <input type="file" id="uploadExcel" class="sort-button" onchange="uploadExcel(event)" style="display:none;">
        <button onclick="document.getElementById('uploadExcel').click()" class="sort-button">Subir Checklist Excel</button>
    </div>
    <div id="projectTitle" class="project-title"></div>
    <div id="checklistItems">
        <!-- Itens de checklist serão adicionados aqui dinamicamente -->
    </div>
    <div class="agenda">
        <h1>Minha Agenda com Calendário Mensal e Horários</h1>
        <div id="eventsList">
            <!-- Lista de eventos será preenchida dinamicamente -->
        </div>
        <div class="calendar" id="calendar">
            <!-- Calendário será preenchido dinamicamente -->
        </div>
    </div>
    <div class="completed-tasks-container">
        <h2>Histórico de Atividades Concluídas</h2>
        <div id="completedTasks">
            <!-- Atividades concluídas serão adicionadas aqui dinamicamente -->
        </div>
    </div>
    <div class="report-container">
        <h2>Relatório de Atividades Bloqueantes</h2>
        <div id="blockerReport">
            <!-- Relatório de bloqueantes será preenchido dinamicamente -->
        </div>
    </div>
    <div class="report-container">
        <h2>Relatório de Títulos de Projeto</h2>
        <div id="projectTitleReport">
            <!-- Relatório de títulos de projeto será preenchido dinamicamente -->
        </div>
    </div>
    <div class="report-container">
        <h2>Relatório Ordenado por Número</h2>
        <div id="sortedNumberReport">
            <!-- Relatório ordenado por número será preenchido dinamicamente -->
        </div>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.17.0/xlsx.full.min.js"></script>
    <script>
        function addTask() {
            const taskInput = document.getElementById('newTask');
            const taskName = taskInput.value.trim();
            const tagInput = document.getElementById('newTag');
            const tagName = tagInput.value.trim().toLowerCase();
            const numberInput = document.getElementById('newNumber');
            const taskNumber = numberInput.value.trim();
            const personInput = document.getElementById('newPerson');
            const personName = personInput.value.trim();
            const dateInput = document.getElementById('newDate');
            const taskDate = dateInput.value;
            const endDateInput = document.getElementById('newEndDate');
            const endDate = endDateInput.value;
            const timeInput = document.getElementById('newTime');
            const taskTime = timeInput.value;
            const amountInput = document.getElementById('newAmount');
            const amount = amountInput.value.trim();
            const reasonInput = document.getElementById('newReason');
            const taskReason = reasonInput.value.trim();
            const locationInput = document.getElementById('newLocation');
            const taskLocation = locationInput.value.trim();
            const methodInput = document.getElementById('newMethod');
            const taskMethod = methodInput.value.trim();

            if (taskName !== '' && taskNumber !== '') {
                const checklistItems = document.getElementById('checklistItems');
                const newTaskId = `task-${Date.now()}`;
                const taskContainer = document.createElement('div');
                taskContainer.className = 'checklist-container';
                taskContainer.setAttribute('data-tag', tagName);
                taskContainer.setAttribute('data-number', taskNumber);
                taskContainer.setAttribute('data-person', personName);
                taskContainer.setAttribute('data-date', taskDate);
                taskContainer.setAttribute('data-end-date', endDate);
                taskContainer.setAttribute('data-time', taskTime);
                taskContainer.setAttribute('data-amount', amount);
                taskContainer.setAttribute('data-reason', taskReason);
                taskContainer.setAttribute('data-location', taskLocation);
                taskContainer.setAttribute('data-method', taskMethod);

                const taskHeader = document.createElement('div');
                taskHeader.style.display = 'flex';
                taskHeader.style.alignItems = 'center';

                const toggleButton = document.createElement('span');
                toggleButton.className = 'toggle';
                toggleButton.textContent = '+';
                toggleButton.addEventListener('click', function() {
                    const nested = taskContainer.querySelector('.nested-list');
                    if (nested.style.display === 'block') {
                        nested.style.display = 'none';
                        toggleButton.textContent = '+';
                    } else {
                        nested.style.display = 'block';
                        toggleButton.textContent = '-';
                    }
                });

                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.id = newTaskId;
                checkbox.className = 'checklist-input';
                checkbox.addEventListener('change', function() {
                    if (checkbox.checked) {
                        if (confirm('Você tem certeza que deseja concluir essa tarefa?')) {
                            label.classList.toggle('completed', checkbox.checked);
                            moveToCompleted(taskContainer);
                            saveChecklistState();
                        } else {
                            checkbox.checked = false;
                        }
                    } else {
                        label.classList.toggle('completed', checkbox.checked);
                        checklistItems.appendChild(taskContainer);
                        saveChecklistState();
                    }
                });

                const label = document.createElement('input');
                label.type = 'text';
                label.className = 'checklist-label';
                label.value = taskName;
                label.addEventListener('change', function() {
                    saveChecklistState();
                });

                const numberInputField = document.createElement('input');
                numberInputField.type = 'number';
                numberInputField.value = taskNumber;
                numberInputField.className = 'edit-number-input';
                numberInputField.placeholder = "Número";
                numberInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-number', numberInputField.value);
                    saveChecklistState();
                });

                const tagInputField = document.createElement('input');
                tagInputField.type = 'text';
                tagInputField.value = tagName;
                tagInputField.className = 'edit-tag-input';
                tagInputField.placeholder = "Tag";
                tagInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-tag', tagInputField.value.toLowerCase());
                    saveChecklistState();
                    updateFilterDropdown();
                });

                const personInputField = document.createElement('input');
                personInputField.type = 'text';
                personInputField.value = personName;
                personInputField.className = 'edit-person-input';
                personInputField.placeholder = "Atribuir a";
                personInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-person', personInputField.value);
                    saveChecklistState();
                    updatePersonFilterDropdown();
                });

                const dateInputField = document.createElement('input');
                dateInputField.type = 'date';
                dateInputField.value = taskDate;
                dateInputField.className = 'edit-date-input';
                dateInputField.placeholder = "Data de realização";
                dateInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-date', dateInputField.value);
                    saveChecklistState();
                    updateCalendar();
                });

                const endDateInputField = document.createElement('input');
                endDateInputField.type = 'date';
                endDateInputField.value = endDate;
                endDateInputField.className = 'edit-end-date-input';
                endDateInputField.placeholder = "Data de término";
                endDateInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-end-date', endDateInputField.value);
                    saveChecklistState();
                    updateCalendar();
                });

                const timeInputField = document.createElement('input');
                timeInputField.type = 'time';
                timeInputField.value = taskTime;
                timeInputField.className = 'edit-time-input';
                timeInputField.placeholder = "Horário";
                timeInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-time', timeInputField.value);
                    saveChecklistState();
                    updateCalendar();
                });

                const amountInputField = document.createElement('input');
                amountInputField.type = 'number';
                amountInputField.value = amount;
                amountInputField.className = 'edit-amount-input';
                amountInputField.placeholder = "Quanto";
                amountInputField.step = "0.01";
                amountInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-amount', amountInputField.value);
                    saveChecklistState();
                });

                const reasonInputField = document.createElement('input');
                reasonInputField.type = 'text';
                reasonInputField.value = taskReason;
                reasonInputField.className = 'edit-reason-input';
                reasonInputField.placeholder = "Por que da tarefa?";
                reasonInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-reason', reasonInputField.value);
                    saveChecklistState();
                });

                const locationInputField = document.createElement('input');
                locationInputField.type = 'text';
                locationInputField.value = taskLocation;
                locationInputField.className = 'edit-location-input';
                locationInputField.placeholder = "Onde será a tarefa?";
                locationInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-location', locationInputField.value);
                    saveChecklistState();
                });

                const methodInputField = document.createElement('input');
                methodInputField.type = 'text';
                methodInputField.value = taskMethod;
                methodInputField.className = 'edit-method-input';
                methodInputField.placeholder = "Como será feita essa tarefa?";
                methodInputField.addEventListener('change', function() {
                    taskContainer.setAttribute('data-method', methodInputField.value);
                    saveChecklistState();
                });

                const removeButton = document.createElement('button');
                removeButton.type = 'button';
                removeButton.className = 'remove-task-button';
                removeButton.textContent = 'x';
                removeButton.addEventListener('click', function() {
                    if (confirm('Você tem certeza que deseja excluir essa tarefa?')) {
                        taskContainer.remove();
                        saveChecklistState();
                        updateCalendar();
                    }
                });

                const blockerButton = document.createElement('button');
                blockerButton.type = 'button';
                blockerButton.className = 'blocker-button';
                blockerButton.innerHTML = '&#9888;';
                blockerButton.addEventListener('click', function() {
                    taskContainer.classList.toggle('blocker');
                    saveChecklistState();
                });

                const projectTitleButton = document.createElement('button');
                projectTitleButton.type = 'button';
                projectTitleButton.className = 'project-title-button';
                projectTitleButton.innerHTML = '&#9733;';
                projectTitleButton.addEventListener('click', function() {
                    taskContainer.classList.toggle('project-title');
                    saveChecklistState();
                });

                const addSubTaskButton = document.createElement('button');
                addSubTaskButton.type = 'button';
                addSubTaskButton.className = 'add-task-button';
                addSubTaskButton.textContent = 'Adicionar Subtarefa';
                addSubTaskButton.style.marginLeft = '10px';
                addSubTaskButton.addEventListener('click', function() {
                    const subTaskName = prompt('Digite a nova subtarefa:');
                    if (subTaskName) {
                        addSubTask(taskContainer, subTaskName);
                    }
                });

                const customFieldButton = document.createElement('button');
                customFieldButton.type = 'button';
                customFieldButton.className = 'add-task-button';
                customFieldButton.textContent = 'Adicionar Campo Personalizado';
                customFieldButton.style.marginLeft = '10px';
                customFieldButton.addEventListener('click', function() {
                    addCustomField(taskContainer);
                });

                const nestedList = document.createElement('div');
                nestedList.className = 'nested-list';

                taskHeader.appendChild(toggleButton);
                taskHeader.appendChild(checkbox);
                taskHeader.appendChild(label);
                taskHeader.appendChild(tagInputField);
                taskHeader.appendChild(numberInputField);
                taskHeader.appendChild(personInputField);
                taskHeader.appendChild(dateInputField);
                taskHeader.appendChild(endDateInputField);
                taskHeader.appendChild(timeInputField);
                taskHeader.appendChild(amountInputField);
                taskHeader.appendChild(reasonInputField);
                taskHeader.appendChild(locationInputField);
                taskHeader.appendChild(methodInputField);
                taskHeader.appendChild(blockerButton);
                taskHeader.appendChild(projectTitleButton);
                taskHeader.appendChild(removeButton);
                taskHeader.appendChild(addSubTaskButton);
                taskHeader.appendChild(customFieldButton);

                taskContainer.appendChild(taskHeader);
                taskContainer.appendChild(nestedList);
                checklistItems.appendChild(taskContainer);

                taskInput.value = '';
                tagInput.value = '';
                numberInput.value = '';
                personInput.value = '';
                dateInput.value = '';
                endDateInput.value = '';
                timeInput.value = '';
                amountInput.value = '';
                reasonInput.value = '';
                locationInput.value = '';
                methodInput.value = '';

                saveChecklistState();
                updateFilterDropdown();
                updatePersonFilterDropdown();
                updateCalendar();
                initializeSortable(nestedList);
            }
        }

        function addSubTask(parentTaskContainer, subTaskName) {
            const nestedList = parentTaskContainer.querySelector('.nested-list');
            const subTaskId = `subtask-${Date.now()}`;
            const subTaskContainer = document.createElement('div');
            subTaskContainer.className = 'checklist-container';
            subTaskContainer.setAttribute('data-tag', '');
            subTaskContainer.setAttribute('data-number', '');
            subTaskContainer.setAttribute('data-person', '');
            subTaskContainer.setAttribute('data-date', '');
            subTaskContainer.setAttribute('data-end-date', '');
            subTaskContainer.setAttribute('data-time', '');
            subTaskContainer.setAttribute('data-amount', '');
            subTaskContainer.setAttribute('data-reason', '');
            subTaskContainer.setAttribute('data-location', '');
            subTaskContainer.setAttribute('data-method', '');

            const subTaskHeader = document.createElement('div');
            subTaskHeader.style.display = 'flex';
            subTaskHeader.style.alignItems = 'center';

            const toggleButton = document.createElement('span');
            toggleButton.className = 'toggle';
            toggleButton.textContent = '+';
            toggleButton.addEventListener('click', function() {
                const nested = subTaskContainer.querySelector('.nested-list');
                if (nested.style.display === 'block') {
                    nested.style.display = 'none';
                    toggleButton.textContent = '+';
                } else {
                    nested.style.display = 'block';
                    toggleButton.textContent = '-';
                }
            });

            const subCheckbox = document.createElement('input');
            subCheckbox.type = 'checkbox';
            subCheckbox.id = subTaskId;
            subCheckbox.className = 'checklist-input';
            subCheckbox.addEventListener('change', function() {
                if (subCheckbox.checked) {
                    if (confirm('Você tem certeza que deseja concluir essa tarefa?')) {
                        subLabel.classList.toggle('completed', subCheckbox.checked);
                        moveToCompleted(subTaskContainer);
                        saveChecklistState();
                    } else {
                        subCheckbox.checked = false;
                    }
                } else {
                    subLabel.classList.toggle('completed', subCheckbox.checked);
                    nestedList.appendChild(subTaskContainer);
                    saveChecklistState();
                }
            });

            const subLabel = document.createElement('input');
            subLabel.type = 'text';
            subLabel.className = 'checklist-label';
            subLabel.value = subTaskName;
            subLabel.addEventListener('change', function() {
                saveChecklistState();
            });

            const subNumberInputField = document.createElement('input');
            subNumberInputField.type = 'number';
            subNumberInputField.value = '';
            subNumberInputField.className = 'edit-number-input';
            subNumberInputField.placeholder = "Número";
            subNumberInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-number', subNumberInputField.value);
                saveChecklistState();
            });

            const subTagInputField = document.createElement('input');
            subTagInputField.type = 'text';
            subTagInputField.value = '';
            subTagInputField.className = 'edit-tag-input';
            subTagInputField.placeholder = "Tag";
            subTagInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-tag', subTagInputField.value.toLowerCase());
                saveChecklistState();
                updateFilterDropdown();
            });

            const subPersonInputField = document.createElement('input');
            subPersonInputField.type = 'text';
            subPersonInputField.value = '';
            subPersonInputField.className = 'edit-person-input';
            subPersonInputField.placeholder = "Atribuir a";
            subPersonInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-person', subPersonInputField.value);
                saveChecklistState();
                updatePersonFilterDropdown();
            });

            const subDateInputField = document.createElement('input');
            subDateInputField.type = 'date';
            subDateInputField.value = '';
            subDateInputField.className = 'edit-date-input';
            subDateInputField.placeholder = "Data de realização";
            subDateInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-date', subDateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subEndDateInputField = document.createElement('input');
            subEndDateInputField.type = 'date';
            subEndDateInputField.value = '';
            subEndDateInputField.className = 'edit-end-date-input';
            subEndDateInputField.placeholder = "Data de término";
            subEndDateInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-end-date', subEndDateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subTimeInputField = document.createElement('input');
            subTimeInputField.type = 'time';
            subTimeInputField.value = '';
            subTimeInputField.className = 'edit-time-input';
            subTimeInputField.placeholder = "Horário";
            subTimeInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-time', subTimeInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subAmountInputField = document.createElement('input');
            subAmountInputField.type = 'number';
            subAmountInputField.value = '';
            subAmountInputField.className = 'edit-amount-input';
            subAmountInputField.placeholder = "Quanto";
            subAmountInputField.step = "0.01";
            subAmountInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-amount', subAmountInputField.value);
                saveChecklistState();
            });

            const subReasonInputField = document.createElement('input');
            subReasonInputField.type = 'text';
            subReasonInputField.value = '';
            subReasonInputField.className = 'edit-reason-input';
            subReasonInputField.placeholder = "Por que da tarefa?";
            subReasonInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-reason', subReasonInputField.value);
                saveChecklistState();
            });

            const subLocationInputField = document.createElement('input');
            subLocationInputField.type = 'text';
            subLocationInputField.value = '';
            subLocationInputField.className = 'edit-location-input';
            subLocationInputField.placeholder = "Onde será a tarefa?";
            subLocationInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-location', subLocationInputField.value);
                saveChecklistState();
            });

            const subMethodInputField = document.createElement('input');
            subMethodInputField.type = 'text';
            subMethodInputField.value = '';
            subMethodInputField.className = 'edit-method-input';
            subMethodInputField.placeholder = "Como será feita essa tarefa?";
            subMethodInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-method', subMethodInputField.value);
                saveChecklistState();
            });

            const subRemoveButton = document.createElement('button');
            subRemoveButton.type = 'button';
            subRemoveButton.className = 'remove-task-button';
            subRemoveButton.textContent = 'x';
            subRemoveButton.addEventListener('click', function() {
                if (confirm('Você tem certeza que deseja excluir essa tarefa?')) {
                    subTaskContainer.remove();
                    saveChecklistState();
                    updateCalendar();
                }
            });

            const subBlockerButton = document.createElement('button');
            subBlockerButton.type = 'button';
            subBlockerButton.className = 'blocker-button';
            subBlockerButton.innerHTML = '&#9888;';
            subBlockerButton.addEventListener('click', function() {
                subTaskContainer.classList.toggle('blocker');
                saveChecklistState();
            });

            const subProjectTitleButton = document.createElement('button');
            subProjectTitleButton.type = 'button';
            subProjectTitleButton.className = 'project-title-button';
            subProjectTitleButton.innerHTML = '&#9733;';
            subProjectTitleButton.addEventListener('click', function() {
                subTaskContainer.classList.toggle('project-title');
                saveChecklistState();
            });

            const addSubSubTaskButton = document.createElement('button');
            addSubSubTaskButton.type = 'button';
            addSubSubTaskButton.className = 'add-task-button';
            addSubSubTaskButton.textContent = 'Adicionar Subtarefa';
            addSubSubTaskButton.style.marginLeft = '10px';
            addSubSubTaskButton.addEventListener('click', function() {
                const subSubTaskName = prompt('Digite a nova subtarefa:');
                if (subSubTaskName) {
                    addSubTask(subTaskContainer, subSubTaskName);
                }
            });

            const customFieldButton = document.createElement('button');
            customFieldButton.type = 'button';
            customFieldButton.className = 'add-task-button';
            customFieldButton.textContent = 'Adicionar Campo Personalizado';
            customFieldButton.style.marginLeft = '10px';
            customFieldButton.addEventListener('click', function() {
                addCustomField(subTaskContainer);
            });

            subTaskHeader.appendChild(toggleButton);
            subTaskHeader.appendChild(subCheckbox);
            subTaskHeader.appendChild(subLabel);
            subTaskHeader.appendChild(subTagInputField);
            subTaskHeader.appendChild(subNumberInputField);
            subTaskHeader.appendChild(subPersonInputField);
            subTaskHeader.appendChild(subDateInputField);
            subTaskHeader.appendChild(subEndDateInputField);
            subTaskHeader.appendChild(subTimeInputField);
            subTaskHeader.appendChild(subAmountInputField);
            subTaskHeader.appendChild(subReasonInputField);
            subTaskHeader.appendChild(subLocationInputField);
            subTaskHeader.appendChild(subMethodInputField);
            subTaskHeader.appendChild(subBlockerButton);
            subTaskHeader.appendChild(subProjectTitleButton);
            subTaskHeader.appendChild(subRemoveButton);
            subTaskHeader.appendChild(addSubSubTaskButton);
            subTaskHeader.appendChild(customFieldButton);

            subTaskContainer.appendChild(subTaskHeader);

            const subNestedList = document.createElement('div');
            subNestedList.className = 'nested-list';
            subTaskContainer.appendChild(subNestedList);

            nestedList.appendChild(subTaskContainer);

            initializeSortable(subNestedList);
            updateCalendar();
        }

        function setProjectTitle(title) {
            const projectTitle = document.getElementById('projectTitle');
            projectTitle.textContent = title;
        }

        function saveChecklistState() {
            const tasks = [];
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const taskHeader = taskContainer.querySelector('div');
                const checkbox = taskContainer.querySelector('.checklist-input');
                const label = taskContainer.querySelector('.checklist-label');
                const tag = taskContainer.querySelector('.edit-tag-input').value.toLowerCase();
                const number = taskContainer.querySelector('.edit-number-input').value;
                const person = taskContainer.querySelector('.edit-person-input').value;
                const date = taskContainer.querySelector('.edit-date-input').value;
                const endDate = taskContainer.querySelector('.edit-end-date-input').value;
                const time = taskContainer.querySelector('.edit-time-input').value;
                const amount = taskContainer.querySelector('.edit-amount-input').value;
                const reason = taskContainer.querySelector('.edit-reason-input').value;
                const location = taskContainer.querySelector('.edit-location-input').value;
                const method = taskContainer.querySelector('.edit-method-input').value;
                const isBlocker = taskContainer.classList.contains('blocker');
                const isProjectTitle = taskContainer.classList.contains('project-title');
                const subTasks = Array.from(taskContainer.querySelector('.nested-list').children).map(subTask => getTaskData(subTask));
                const customFields = getCustomFields(taskContainer);
                tasks.push({
                    id: checkbox.id,
                    name: label.value,
                    checked: checkbox.checked,
                    tag: tag,
                    number: number,
                    person: person,
                    date: date,
                    endDate: endDate,
                    time: time,
                    amount: amount,
                    reason: reason,
                    location: location,
                    method: method,
                    blocker: isBlocker,
                    projectTitle: isProjectTitle,
                    subTasks: subTasks,
                    customFields: customFields
                });
            });
            localStorage.setItem('checklistItems', JSON.stringify(tasks));
        }

        function getTaskData(taskContainer) {
            const checkbox = taskContainer.querySelector('.checklist-input');
            const label = taskContainer.querySelector('.checklist-label');
            const tag = taskContainer.querySelector('.edit-tag-input').value.toLowerCase();
            const number = taskContainer.querySelector('.edit-number-input').value;
            const person = taskContainer.querySelector('.edit-person-input').value;
            const date = taskContainer.querySelector('.edit-date-input').value;
            const endDate = taskContainer.querySelector('.edit-end-date-input').value;
            const time = taskContainer.querySelector('.edit-time-input').value;
            const amount = taskContainer.querySelector('.edit-amount-input').value;
            const reason = taskContainer.querySelector('.edit-reason-input').value;
            const location = taskContainer.querySelector('.edit-location-input').value;
            const method = taskContainer.querySelector('.edit-method-input').value;
            const isBlocker = taskContainer.classList.contains('blocker');
            const isProjectTitle = taskContainer.classList.contains('project-title');
            const subTasks = Array.from(taskContainer.querySelector('.nested-list').children).map(subTask => getTaskData(subTask));
            const customFields = getCustomFields(taskContainer);
            return {
                id: checkbox.id,
                name: label.value,
                checked: checkbox.checked,
                tag: tag,
                number: number,
                person: person,
                date: date,
                endDate: endDate,
                time: time,
                amount: amount,
                reason: reason,
                location: location,
                method: method,
                blocker: isBlocker,
                projectTitle: isProjectTitle,
                subTasks: subTasks,
                customFields: customFields
            };
        }

        function getCustomFields(taskContainer) {
            const customFields = {};
            const customFieldInputs = taskContainer.querySelectorAll('.custom-field-input');
            customFieldInputs.forEach(input => {
                customFields[input.placeholder] = input.value;
            });
            return customFields;
        }

        function restoreChecklistState() {
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];
            tasks.forEach((task) => {
                addTaskFromData(task);
            });
            updateFilterDropdown();
            updatePersonFilterDropdown();
            updateCalendar();
        }

        function addTaskFromData(task) {
            const checklistItems = document.getElementById('checklistItems');
            const taskContainer = document.createElement('div');
            taskContainer.className = 'checklist-container';
            taskContainer.setAttribute('data-tag', task.tag);
            taskContainer.setAttribute('data-number', task.number);
            taskContainer.setAttribute('data-person', task.person);
            taskContainer.setAttribute('data-date', task.date);
            taskContainer.setAttribute('data-end-date', task.endDate);
            taskContainer.setAttribute('data-time', task.time);
            taskContainer.setAttribute('data-amount', task.amount);
            taskContainer.setAttribute('data-reason', task.reason);
            taskContainer.setAttribute('data-location', task.location);
            taskContainer.setAttribute('data-method', task.method);

            const taskHeader = document.createElement('div');
            taskHeader.style.display = 'flex';
            taskHeader.style.alignItems = 'center';

            const toggleButton = document.createElement('span');
            toggleButton.className = 'toggle';
            toggleButton.textContent = '+';
            toggleButton.addEventListener('click', function() {
                const nested = taskContainer.querySelector('.nested-list');
                if (nested.style.display === 'block') {
                    nested.style.display = 'none';
                    toggleButton.textContent = '+';
                } else {
                    nested.style.display = 'block';
                    toggleButton.textContent = '-';
                }
            });

            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = task.id;
            checkbox.className = 'checklist-input';
            checkbox.checked = task.checked;
            checkbox.addEventListener('change', function() {
                if (checkbox.checked) {
                    if (confirm('Você tem certeza que deseja concluir essa tarefa?')) {
                        label.classList.toggle('completed', checkbox.checked);
                        moveToCompleted(taskContainer);
                        saveChecklistState();
                    } else {
                        checkbox.checked = false;
                    }
                } else {
                    label.classList.toggle('completed', checkbox.checked);
                    checklistItems.appendChild(taskContainer);
                    saveChecklistState();
                }
            });

            const label = document.createElement('input');
            label.type = 'text';
            label.className = 'checklist-label';
            label.value = task.name;
            if (task.checked) {
                label.classList.add('completed');
            }
            label.addEventListener('change', function() {
                saveChecklistState();
            });

            const numberInputField = document.createElement('input');
            numberInputField.type = 'number';
            numberInputField.value = task.number;
            numberInputField.className = 'edit-number-input';
            numberInputField.placeholder = "Número";
            numberInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-number', numberInputField.value);
                saveChecklistState();
            });

            const tagInputField = document.createElement('input');
            tagInputField.type = 'text';
            tagInputField.value = task.tag;
            tagInputField.className = 'edit-tag-input';
            tagInputField.placeholder = "Tag";
            tagInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-tag', tagInputField.value.toLowerCase());
                saveChecklistState();
                updateFilterDropdown();
            });

            const personInputField = document.createElement('input');
            personInputField.type = 'text';
            personInputField.value = task.person;
            personInputField.className = 'edit-person-input';
            personInputField.placeholder = "Atribuir a";
            personInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-person', personInputField.value);
                saveChecklistState();
                updatePersonFilterDropdown();
            });

            const dateInputField = document.createElement('input');
            dateInputField.type = 'date';
            dateInputField.value = task.date;
            dateInputField.className = 'edit-date-input';
            dateInputField.placeholder = "Data de realização";
            dateInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-date', dateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const endDateInputField = document.createElement('input');
            endDateInputField.type = 'date';
            endDateInputField.value = task.endDate;
            endDateInputField.className = 'edit-end-date-input';
            endDateInputField.placeholder = "Data de término";
            endDateInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-end-date', endDateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const timeInputField = document.createElement('input');
            timeInputField.type = 'time';
            timeInputField.value = task.time;
            timeInputField.className = 'edit-time-input';
            timeInputField.placeholder = "Horário";
            timeInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-time', timeInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const amountInputField = document.createElement('input');
            amountInputField.type = 'number';
            amountInputField.value = task.amount;
            amountInputField.className = 'edit-amount-input';
            amountInputField.placeholder = "Quanto";
            amountInputField.step = "0.01";
            amountInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-amount', amountInputField.value);
                saveChecklistState();
            });

            const reasonInputField = document.createElement('input');
            reasonInputField.type = 'text';
            reasonInputField.value = task.reason;
            reasonInputField.className = 'edit-reason-input';
            reasonInputField.placeholder = "Por que da tarefa?";
            reasonInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-reason', reasonInputField.value);
                saveChecklistState();
            });

            const locationInputField = document.createElement('input');
            locationInputField.type = 'text';
            locationInputField.value = task.location;
            locationInputField.className = 'edit-location-input';
            locationInputField.placeholder = "Onde será a tarefa?";
            locationInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-location', locationInputField.value);
                saveChecklistState();
            });

            const methodInputField = document.createElement('input');
            methodInputField.type = 'text';
            methodInputField.value = task.method;
            methodInputField.className = 'edit-method-input';
            methodInputField.placeholder = "Como será feita essa tarefa?";
            methodInputField.addEventListener('change', function() {
                taskContainer.setAttribute('data-method', methodInputField.value);
                saveChecklistState();
            });

            const removeButton = document.createElement('button');
            removeButton.type = 'button';
            removeButton.className = 'remove-task-button';
            removeButton.textContent = 'x';
            removeButton.addEventListener('click', function() {
                if (confirm('Você tem certeza que deseja excluir essa tarefa?')) {
                    taskContainer.remove();
                    saveChecklistState();
                    updateCalendar();
                }
            });

            const blockerButton = document.createElement('button');
            blockerButton.type = 'button';
            blockerButton.className = 'blocker-button';
            blockerButton.innerHTML = '&#9888;';
            blockerButton.addEventListener('click', function() {
                taskContainer.classList.toggle('blocker');
                saveChecklistState();
            });

            const projectTitleButton = document.createElement('button');
            projectTitleButton.type = 'button';
            projectTitleButton.className = 'project-title-button';
            projectTitleButton.innerHTML = '&#9733;';
            projectTitleButton.addEventListener('click', function() {
                taskContainer.classList.toggle('project-title');
                saveChecklistState();
            });

            const addSubTaskButton = document.createElement('button');
            addSubTaskButton.type = 'button';
            addSubTaskButton.className = 'add-task-button';
            addSubTaskButton.textContent = 'Adicionar Subtarefa';
            addSubTaskButton.style.marginLeft = '10px';
            addSubTaskButton.addEventListener('click', function() {
                const subTaskName = prompt('Digite a nova subtarefa:');
                if (subTaskName) {
                    addSubTask(taskContainer, subTaskName);
                }
            });

            const customFieldButton = document.createElement('button');
            customFieldButton.type = 'button';
            customFieldButton.className = 'add-task-button';
            customFieldButton.textContent = 'Adicionar Campo Personalizado';
            customFieldButton.style.marginLeft = '10px';
            customFieldButton.addEventListener('click', function() {
                addCustomField(taskContainer);
            });

            const nestedList = document.createElement('div');
            nestedList.className = 'nested-list';

            taskHeader.appendChild(toggleButton);
            taskHeader.appendChild(checkbox);
            taskHeader.appendChild(label);
            taskHeader.appendChild(tagInputField);
            taskHeader.appendChild(numberInputField);
            taskHeader.appendChild(personInputField);
            taskHeader.appendChild(dateInputField);
            taskHeader.appendChild(endDateInputField);
            taskHeader.appendChild(timeInputField);
            taskHeader.appendChild(amountInputField);
            taskHeader.appendChild(reasonInputField);
            taskHeader.appendChild(locationInputField);
            taskHeader.appendChild(methodInputField);
            taskHeader.appendChild(blockerButton);
            taskHeader.appendChild(projectTitleButton);
            taskHeader.appendChild(removeButton);
            taskHeader.appendChild(addSubTaskButton);
            taskHeader.appendChild(customFieldButton);

            taskContainer.appendChild(taskHeader);
            taskContainer.appendChild(nestedList);
            checklistItems.appendChild(taskContainer);

            task.subTasks.forEach(subTask => {
                addSubTaskFromData(nestedList, subTask);
            });

            for (const [key, value] of Object.entries(task.customFields)) {
                addCustomFieldFromData(taskContainer, key, value);
            }

            initializeSortable(nestedList);
        }

        function addSubTaskFromData(nestedList, subTask) {
            const subTaskContainer = document.createElement('div');
            subTaskContainer.className = 'checklist-container';
            subTaskContainer.setAttribute('data-tag', subTask.tag);
            subTaskContainer.setAttribute('data-number', subTask.number);
            subTaskContainer.setAttribute('data-person', subTask.person);
            subTaskContainer.setAttribute('data-date', subTask.date);
            subTaskContainer.setAttribute('data-end-date', subTask.endDate);
            subTaskContainer.setAttribute('data-time', subTask.time);
            subTaskContainer.setAttribute('data-amount', subTask.amount);
            subTaskContainer.setAttribute('data-reason', subTask.reason);
            subTaskContainer.setAttribute('data-location', subTask.location);
            subTaskContainer.setAttribute('data-method', subTask.method);

            const subTaskHeader = document.createElement('div');
            subTaskHeader.style.display = 'flex';
            subTaskHeader.style.alignItems = 'center';

            const toggleButton = document.createElement('span');
            toggleButton.className = 'toggle';
            toggleButton.textContent = '+';
            toggleButton.addEventListener('click', function() {
                const nested = subTaskContainer.querySelector('.nested-list');
                if (nested.style.display === 'block') {
                    nested.style.display = 'none';
                    toggleButton.textContent = '+';
                } else {
                    nested.style.display = 'block';
                    toggleButton.textContent = '-';
                }
            });

            const subCheckbox = document.createElement('input');
            subCheckbox.type = 'checkbox';
            subCheckbox.id = subTask.id;
            subCheckbox.className = 'checklist-input';
            subCheckbox.checked = subTask.checked;
            subCheckbox.addEventListener('change', function() {
                if (subCheckbox.checked) {
                    if (confirm('Você tem certeza que deseja concluir essa tarefa?')) {
                        subLabel.classList.toggle('completed', subCheckbox.checked);
                        moveToCompleted(subTaskContainer);
                        saveChecklistState();
                    } else {
                        subCheckbox.checked = false;
                    }
                } else {
                    subLabel.classList.toggle('completed', subCheckbox.checked);
                    nestedList.appendChild(subTaskContainer);
                    saveChecklistState();
                }
            });

            const subLabel = document.createElement('input');
            subLabel.type = 'text';
            subLabel.className = 'checklist-label';
            subLabel.value = subTask.name;
            if (subTask.checked) {
                subLabel.classList.add('completed');
            }
            subLabel.addEventListener('change', function() {
                saveChecklistState();
            });

            const subNumberInputField = document.createElement('input');
            subNumberInputField.type = 'number';
            subNumberInputField.value = subTask.number;
            subNumberInputField.className = 'edit-number-input';
            subNumberInputField.placeholder = "Número";
            subNumberInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-number', subNumberInputField.value);
                saveChecklistState();
            });

            const subTagInputField = document.createElement('input');
            subTagInputField.type = 'text';
            subTagInputField.value = subTask.tag;
            subTagInputField.className = 'edit-tag-input';
            subTagInputField.placeholder = "Tag";
            subTagInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-tag', subTagInputField.value.toLowerCase());
                saveChecklistState();
                updateFilterDropdown();
            });

            const subPersonInputField = document.createElement('input');
            subPersonInputField.type = 'text';
            subPersonInputField.value = subTask.person;
            subPersonInputField.className = 'edit-person-input';
            subPersonInputField.placeholder = "Atribuir a";
            subPersonInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-person', subPersonInputField.value);
                saveChecklistState();
                updatePersonFilterDropdown();
            });

            const subDateInputField = document.createElement('input');
            subDateInputField.type = 'date';
            subDateInputField.value = subTask.date;
            subDateInputField.className = 'edit-date-input';
            subDateInputField.placeholder = "Data de realização";
            subDateInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-date', subDateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subEndDateInputField = document.createElement('input');
            subEndDateInputField.type = 'date';
            subEndDateInputField.value = subTask.endDate;
            subEndDateInputField.className = 'edit-end-date-input';
            subEndDateInputField.placeholder = "Data de término";
            subEndDateInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-end-date', subEndDateInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subTimeInputField = document.createElement('input');
            subTimeInputField.type = 'time';
            subTimeInputField.value = subTask.time;
            subTimeInputField.className = 'edit-time-input';
            subTimeInputField.placeholder = "Horário";
            subTimeInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-time', subTimeInputField.value);
                saveChecklistState();
                updateCalendar();
            });

            const subAmountInputField = document.createElement('input');
            subAmountInputField.type = 'number';
            subAmountInputField.value = subTask.amount;
            subAmountInputField.className = 'edit-amount-input';
            subAmountInputField.placeholder = "Quanto";
            subAmountInputField.step = "0.01";
            subAmountInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-amount', subAmountInputField.value);
                saveChecklistState();
            });

            const subReasonInputField = document.createElement('input');
            subReasonInputField.type = 'text';
            subReasonInputField.value = subTask.reason;
            subReasonInputField.className = 'edit-reason-input';
            subReasonInputField.placeholder = "Por que da tarefa?";
            subReasonInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-reason', subReasonInputField.value);
                saveChecklistState();
            });

            const subLocationInputField = document.createElement('input');
            subLocationInputField.type = 'text';
            subLocationInputField.value = subTask.location;
            subLocationInputField.className = 'edit-location-input';
            subLocationInputField.placeholder = "Onde será a tarefa?";
            subLocationInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-location', subLocationInputField.value);
                saveChecklistState();
            });

            const subMethodInputField = document.createElement('input');
            subMethodInputField.type = 'text';
            subMethodInputField.value = subTask.method;
            subMethodInputField.className = 'edit-method-input';
            subMethodInputField.placeholder = "Como será feita essa tarefa?";
            subMethodInputField.addEventListener('change', function() {
                subTaskContainer.setAttribute('data-method', subMethodInputField.value);
                saveChecklistState();
            });

            const subRemoveButton = document.createElement('button');
            subRemoveButton.type = 'button';
            subRemoveButton.className = 'remove-task-button';
            subRemoveButton.textContent = 'x';
            subRemoveButton.addEventListener('click', function() {
                if (confirm('Você tem certeza que deseja excluir essa tarefa?')) {
                    subTaskContainer.remove();
                    saveChecklistState();
                    updateCalendar();
                }
            });

            const subBlockerButton = document.createElement('button');
            subBlockerButton.type = 'button';
            subBlockerButton.className = 'blocker-button';
            subBlockerButton.innerHTML = '&#9888;';
            subBlockerButton.addEventListener('click', function() {
                subTaskContainer.classList.toggle('blocker');
                saveChecklistState();
            });

            const subProjectTitleButton = document.createElement('button');
            subProjectTitleButton.type = 'button';
            subProjectTitleButton.className = 'project-title-button';
            subProjectTitleButton.innerHTML = '&#9733;';
            subProjectTitleButton.addEventListener('click', function() {
                subTaskContainer.classList.toggle('project-title');
                saveChecklistState();
            });

            const addSubSubTaskButton = document.createElement('button');
            addSubSubTaskButton.type = 'button';
            addSubSubTaskButton.className = 'add-task-button';
            addSubSubTaskButton.textContent = 'Adicionar Subtarefa';
            addSubSubTaskButton.style.marginLeft = '10px';
            addSubSubTaskButton.addEventListener('click', function() {
                const subSubTaskName = prompt('Digite a nova subtarefa:');
                if (subSubTaskName) {
                    addSubTask(subTaskContainer, subSubTaskName);
                }
            });

            const customFieldButton = document.createElement('button');
            customFieldButton.type = 'button';
            customFieldButton.className = 'add-task-button';
            customFieldButton.textContent = 'Adicionar Campo Personalizado';
            customFieldButton.style.marginLeft = '10px';
            customFieldButton.addEventListener('click', function() {
                addCustomField(subTaskContainer);
            });

            subTaskHeader.appendChild(toggleButton);
            subTaskHeader.appendChild(subCheckbox);
            subTaskHeader.appendChild(subLabel);
            subTaskHeader.appendChild(subTagInputField);
            subTaskHeader.appendChild(subNumberInputField);
            subTaskHeader.appendChild(subPersonInputField);
            subTaskHeader.appendChild(subDateInputField);
            subTaskHeader.appendChild(subEndDateInputField);
            subTaskHeader.appendChild(subTimeInputField);
            subTaskHeader.appendChild(subAmountInputField);
            subTaskHeader.appendChild(subReasonInputField);
            subTaskHeader.appendChild(subLocationInputField);
            subTaskHeader.appendChild(subMethodInputField);
            subTaskHeader.appendChild(subBlockerButton);
            subTaskHeader.appendChild(subProjectTitleButton);
            subTaskHeader.appendChild(subRemoveButton);
            subTaskHeader.appendChild(addSubSubTaskButton);
            subTaskHeader.appendChild(customFieldButton);

            subTaskContainer.appendChild(subTaskHeader);

            const subNestedList = document.createElement('div');
            subNestedList.className = 'nested-list';
            subTaskContainer.appendChild(subNestedList);

            nestedList.appendChild(subTaskContainer);

            subTask.subTasks.forEach(subSubTask => {
                addSubTaskFromData(subNestedList, subSubTask);
            });

            for (const [key, value] of Object.entries(subTask.customFields)) {
                addCustomFieldFromData(subTaskContainer, key, value);
            }

            initializeSortable(subNestedList);
        }

        function addCustomField(taskContainer) {
            const fieldName = prompt('Digite o nome do novo campo:');
            if (fieldName) {
                const customFieldInput = document.createElement('input');
                customFieldInput.type = 'text';
                customFieldInput.className = 'custom-field-input';
                customFieldInput.placeholder = fieldName;
                customFieldInput.addEventListener('change', function() {
                    saveChecklistState();
                });

                taskContainer.appendChild(customFieldInput);
                saveChecklistState();
            }
        }

        function addCustomFieldFromData(taskContainer, fieldName, fieldValue) {
            const customFieldInput = document.createElement('input');
            customFieldInput.type = 'text';
            customFieldInput.className = 'custom-field-input';
            customFieldInput.placeholder = fieldName;
            customFieldInput.value = fieldValue;
            customFieldInput.addEventListener('change', function() {
                saveChecklistState();
            });

            taskContainer.appendChild(customFieldInput);
        }

        function moveToCompleted(taskContainer) {
            const completedTasks = document.getElementById('completedTasks');
            completedTasks.appendChild(taskContainer);
        }

        function handleKeyPress(event) {
            if (event.key === 'Enter') {
                addTask();
            }
        }

        function filterTasks() {
            const tagFilter = document.getElementById('tagFilter').value.toLowerCase();
            const personFilter = document.getElementById('personFilter').value;
            const customFieldFilter = document.getElementById('customFieldFilter').value.toLowerCase();
            const keywordFilter = document.getElementById('keywordFilter').value.toLowerCase();
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const tag = taskContainer.getAttribute('data-tag').toLowerCase();
                const person = taskContainer.getAttribute('data-person');
                const customFields = getCustomFields(taskContainer);
                const taskName = taskContainer.querySelector('.checklist-label').value.toLowerCase();
                const isTagMatch = tagFilter === '' || tag.includes(tagFilter);
                const isPersonMatch = personFilter === '' || person === personFilter;
                const isCustomFieldMatch = customFieldFilter === '' || Object.values(customFields).some(value => value.toLowerCase().includes(customFieldFilter));
                const isKeywordMatch = keywordFilter === '' || taskName.includes(keywordFilter);
                if (isTagMatch && isPersonMatch && isCustomFieldMatch && isKeywordMatch) {
                    taskContainer.style.display = 'block';
                } else {
                    taskContainer.style.display = 'none';
                }
            });
        }

        function updateFilterDropdown() {
            const tagFilter = document.getElementById('tagFilter');
            const tags = Array.from(document.querySelectorAll('.edit-tag-input')).map(input => input.value.toLowerCase()).filter(tag => tag !== '');
            const uniqueTags = [...new Set(tags)];
            tagFilter.innerHTML = '<option value="">Todas</option>';
            uniqueTags.forEach((tag) => {
                const option = document.createElement('option');
                option.value = tag;
                option.textContent = tag;
                tagFilter.appendChild(option);
            });
        }

        function updatePersonFilterDropdown() {
            const personFilter = document.getElementById('personFilter');
            const persons = Array.from(document.querySelectorAll('.edit-person-input')).map(input => input.value).filter(person => person !== '');
            const uniquePersons = [...new Set(persons)];
            personFilter.innerHTML = '<option value="">Todas</option>';
            uniquePersons.forEach((person) => {
                const option = document.createElement('option');
                option.value = person;
                option.textContent = person;
                personFilter.appendChild(option);
            });
        }

        function sortTasksByNumber() {
            const checklistItems = document.getElementById('checklistItems');
            const tasks = Array.from(checklistItems.children);
            tasks.sort((a, b) => {
                const aNumber = parseInt(a.getAttribute('data-number'), 10);
                const bNumber = parseInt(b.getAttribute('data-number'), 10);
                return aNumber - bNumber;
            });
            tasks.forEach(task => checklistItems.appendChild(task));
            saveChecklistState();
        }

        function filterBlockers() {
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const isBlocker = taskContainer.classList.contains('blocker');
                if (isBlocker) {
                    taskContainer.style.display = 'block';
                } else {
                    taskContainer.style.display = 'none';
                }
            });
        }

        function generateBlockerReport() {
            const blockerReport = document.getElementById('blockerReport');
            blockerReport.innerHTML = '';
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const isBlocker = taskContainer.classList.contains('blocker');
                if (isBlocker) {
                    const taskName = taskContainer.querySelector('.checklist-label').value;
                    const blockerItem = document.createElement('div');
                    blockerItem.className = 'report-item';
                    blockerItem.textContent = taskName;
                    blockerReport.appendChild(blockerItem);
                }
            });
        }

        function filterProjectTitles() {
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const isProjectTitle = taskContainer.classList.contains('project-title');
                if (isProjectTitle) {
                    taskContainer.style.display = 'block';
                } else {
                    taskContainer.style.display = 'none';
                }
            });
        }

        function generateProjectTitleReport() {
            const projectTitleReport = document.getElementById('projectTitleReport');
            projectTitleReport.innerHTML = '';
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach((taskContainer) => {
                const isProjectTitle = taskContainer.classList.contains('project-title');
                if (isProjectTitle) {
                    const taskName = taskContainer.querySelector('.checklist-label').value;
                    const projectTitleItem = document.createElement('div');
                    projectTitleItem.className = 'report-item';
                    projectTitleItem.textContent = taskName;
                    projectTitleReport.appendChild(projectTitleItem);
                }
            });
        }

        function generateSortedNumberReport() {
            const sortedNumberReport = document.getElementById('sortedNumberReport');
            sortedNumberReport.innerHTML = '';
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            const tasks = Array.from(checklistItems).map(taskContainer => {
                const taskName = taskContainer.querySelector('.checklist-label').value;
                const taskNumber = taskContainer.getAttribute('data-number');
                return { taskName, taskNumber };
            });
            tasks.sort((a, b) => a.taskNumber - b.taskNumber);
            tasks.forEach(task => {
                const sortedNumberItem = document.createElement('div');
                sortedNumberItem.className = 'report-item';
                sortedNumberItem.textContent = `${task.taskNumber} - ${task.taskName}`;
                sortedNumberReport.appendChild(sortedNumberItem);
            });
        }

        function initializeSortable(nestedList) {
            new Sortable(nestedList, {
                group: 'nested',
                animation: 150,
                fallbackOnBody: true,
                swapThreshold: 0.65
            });
        }

        function updateCalendar() {
            const calendar = document.getElementById('calendar');
            calendar.innerHTML = '';

            const tasks = getAllTasks();
            const events = tasks.map(task => ({
                date: task.date,
                endDate: task.endDate,
                time: task.time,
                title: task.name,
                id: task.id
            }));

            const currentMonth = new Date().getMonth();
            const currentYear = new Date().getFullYear();

            const monthNames = [
                'Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho',
                'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'
            ];

            const firstDay = new Date(currentYear, currentMonth, 1).getDay();
            const daysInMonth = new Date(currentYear, currentMonth + 1, 0).getDate();

            const calendarMonth = document.createElement('div');
            calendarMonth.className = 'calendar-month';
            calendarMonth.textContent = `${monthNames[currentMonth]} ${currentYear}`;
            calendar.appendChild(calendarMonth);

            const calendarWeek = document.createElement('div');
            calendarWeek.className = 'calendar-week';
            calendar.appendChild(calendarWeek);

            const daysOfWeek = ['Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb'];
            daysOfWeek.forEach(day => {
                const dayOfWeek = document.createElement('div');
                dayOfWeek.className = 'calendar-day';
                dayOfWeek.textContent = day;
                calendarWeek.appendChild(dayOfWeek);
            });

            let day = 1;
            for (let i = 0; i < 6; i++) {
                const calendarWeek = document.createElement('div');
                calendarWeek.className = 'calendar-week';
                calendar.appendChild(calendarWeek);

                for (let j = 0; j < 7; j++) {
                    const calendarDay = document.createElement('div');
                    calendarDay.className = 'calendar-day';

                    if (i === 0 && j < firstDay) {
                        calendarDay.textContent = '';
                    } else if (day > daysInMonth) {
                        calendarDay.textContent = '';
                    } else {
                        calendarDay.textContent = day;
                        const eventForDay = events.filter(event => new Date(event.date).getDate() === day);
                        eventForDay.forEach(event => {
                            const eventDiv = document.createElement('div');
                            eventDiv.className = 'calendar-event';
                            eventDiv.textContent = event.title;
                            calendarDay.appendChild(eventDiv);
                        });
                        day++;
                    }
                    calendarWeek.appendChild(calendarDay);
                }
            }
        }

        function getAllTasks() {
            const tasks = [];
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach(taskContainer => {
                const taskData = getTaskData(taskContainer);
                tasks.push(taskData);
                taskData.subTasks.forEach(subTask => {
                    tasks.push(subTask);
                });
            });
            return tasks;
        }

        function saveChecklistToFile() {
            const checklistHTML = document.getElementById('checklistItems').innerHTML;
            const blob = new Blob([checklistHTML], { type: 'text/html' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'checklist.html';
            a.click();
            URL.revokeObjectURL(url);
        }

        function loadChecklistFromFile() {
            const fileInput = document.getElementById('uploadFile');
            const file = fileInput.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(event) {
                    const html = event.target.result;
                    document.getElementById('checklistItems').innerHTML = html;
                    restoreChecklistState();
                    updateCalendar();
                };
                reader.readAsText(file);
            }
        }

        function downloadHTMLBackup() {
            const tasks = getAllTasks();
            const htmlContent = JSON.stringify(tasks, null, 2);
            const blob = new Blob([htmlContent], { type: 'application/json' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = 'backup.html';
            a.click();
            URL.revokeObjectURL(url);
        }

        function uploadHTML(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const htmlContent = e.target.result;
                    const tasks = JSON.parse(htmlContent);
                    document.getElementById('checklistItems').innerHTML = '';
                    tasks.forEach(task => {
                        addTaskFromData(task);
                    });
                    updateCalendar();
                };
                reader.readAsText(file);
            }
        }

        function downloadExcel() {
            const tasks = getAllTasks();
            const worksheet = XLSX.utils.json_to_sheet(tasks);
            const workbook = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(workbook, worksheet, 'Checklist');
            XLSX.writeFile(workbook, 'checklist.xlsx');
        }

        function uploadExcel(event) {
            const file = event.target.files[0];
            if (file) {
                const reader = new FileReader();
                reader.onload = function(e) {
                    const data = new Uint8Array(e.target.result);
                    const workbook = XLSX.read(data, { type: 'array' });
                    const firstSheetName = workbook.SheetNames[0];
                    const worksheet = workbook.Sheets[firstSheetName];
                    const tasks = XLSX.utils.sheet_to_json(worksheet);
                    document.getElementById('checklistItems').innerHTML = '';
                    tasks.forEach(task => {
                        addTaskFromData(task);
                    });
                    updateCalendar();
                };
                reader.readAsArrayBuffer(file);
            }
        }

        document.addEventListener('DOMContentLoaded', function() {
            restoreChecklistState();
        });
    </script>
</body>
</html>

Todas as funcionalidades

 

 

 accept, check, success, tick Adicionar Tarefas:

     accept, check, success, tick  Permite ao usuário adicionar novas tarefas com vários atributos, como nome, tag, número, pessoa atribuída, datas (início e término), horário, quantidade, razão, local e método de execução.
      accept, check, success, tick  Possibilidade de adicionar subtarefas a uma tarefa principal.

 

accept, check, success, tick Adicionar Subtarefas:

 

     close, x, round, denied Cada tarefa pode ter subtarefas aninhadas e desaninhadas, permitindo uma estrutura hierárquica de tarefas.

     close, x, round, denied  Possibilidade de adicionar  e retirar subtarefas a cada tarefa, com a mesma funcionalidade de detalhamento e edição.
     close, x, round, denied Permite adicionar e retirar subtarefas aninhadas dentro de uma tarefa.

     close, x, round, denied Permite mover tarefas e subtarefas de maneira livre entre todas as tarefas e subtarefas

     close, x, round, denied Permite mover subtarefas para que elas virem tarefas também

     close, x, round, denied Cada tarefa pode ter subtarefas aninhadas.

     close, x, round, denied Subtarefas podem ser adicionadas, editadas e removidas.
     close, x, round, denied As subtarefas possuem os mesmos campos personalizados das tarefas principais.

 

accept, check, success, tick Personalização de Tarefas:

      accept, check, success, tick Cada tarefa e subtarefa pode ser personalizada com campos adicionais criados pelo usuário.

Estas funcionalidades permitem ao usuário gerenciar eficientemente suas tarefas, subtarefas e eventos, oferecendo flexibilidade e personalização para adaptar o sistema às suas necessidades específicas.

       accept, check, success, tick  Adição de campos personalizados a cada tarefa para maior flexibilidade na descrição de tarefas.

 

accept, check, success, tick Movimentação de Tarefas e Subtarefas:

    accept, check, success, tick Tarefas e subtarefas podem ser movidas livremente entre listas, permitindo a criação de hierarquias flexíveis.

    accept, check, success, tick Subtarefas podem ser movidas para se tornarem tarefas principais e vice-versa.

 


 

accept, check, success, tick Campos Personalizados:

    accept, check, success, tick Possibilidade de adicionar campos personalizados a cada tarefa, permitindo a customização conforme as necessidades do usuário.

    accept, check, success, tick Usuário pode adicionar novos campos personalizados a uma tarefa ou subtarefa


accept, check, success, tick Filtros

     accept, check, success, tick Filtro por tag,

     accept, check, success, tick Pessoa atribuída

     accept, check, success, tick  Campos personalizados, permitindo ao usuário visualizar tarefas específicas com base nesses critérios.

     accept, check, success, tick Palavras-chave e destaque (Inclua a funcionalidade de filtrar por Palavras-chave, mesmo que as tarefas e subtarefas estejam minizadas)
     close, x, round, denied  Filtro para mostrar apenas tarefas bloqueantes. (Filtragem de tarefas bloqueantes)

     close, x, round, denied Filtrar por títulos de projetos (Destaque (tarefas destacadas)..)
   
     

accept, check, success, tick Ordenação:

     accept, check, success, tick Função para ordenar tarefas pelo número associado a elas.

     close, x, round, denied  (Ordenar da maior para a menor independente de ser tarefa ou subtarefas

 

accept, check, success, tick Marcar como Concluída:

     accept, check, success, tick Tarefas podem ser marcadas como concluídas, sendo movidas para a seção de atividades concluídas e exibidas com um estilo diferente (riscadas).
     accept, check, success, tick  Você tem certeza que deseja concluir essa tarefa?

 

accept, check, success, tick Gerenciamento de Bloqueantes e títulos de projetos

    accept, check, success, tick Tarefas podem ser marcadas como bloqueantes. (borda fica vermelha)  Há uma funcionalidade para filtrar e gerar relatórios de tarefas bloqueantes.

    accept, check, success, tick Tarefas podem ser marcadas como título de projeto. (borda fica verde) Há uma funcionalidade para filtrar e gerar relatórios de títulos de projetos, (Objetivo de  se destacar para facilitar a visualização e diferenciação das tarefas que representam inicio de etapas mais importantes.) (Permite marcar tarefas e subtarefas como títulos de projeto (borda verde).)
 


accept, check, success, tick Agenda com Calendário Integrado:

    accept, check, success, tick Exibição de um calendário mensal que mostra os eventos/tarefas agendadas. O calendário destaca os dias com tarefas e exibe detalhes dos eventos ao clicar.
    accept, check, success, tick Integração com tarefas para mostrar eventos no calendário.

    accept, check, success, tick Eventos são exibidos nos dias correspondentes, incluindo eventos de início e término.

    accept, check, success, tick  Adicionar Tarefas Direto no Calendário: Permite adicionar tarefas diretamente clicando em um dia específico no calendário, com os mesmos campos das tarefas principais. (Posso clicar no calendário para adicionar uma tarefa e a mesma tarefa será adicionada no checklist lá em cima. ( tarefas podem ser adicionados diretamente tanto no checklist como no calendário.) Como se ao clicar o calendário eu estivesse clicando no botão Sub tarefa, quero que tenha a função exatada desse botão no checklist lá em cima.)

    close, x, round, denied  Posso editar no calendário que a mesma tarefa será editada lá em cima no calendário (Integração dos eventos das tarefas com o calendário espelhados, permitindo edição simultanea de todas as edições dos campos mudando automaticamente tanto no checklist da tarefa como no calendário.)
    close, x, round, denied Permitir concluir a atividade a partir do click da tarefa também através do calendário.

    close, x, round, denied Permitir excluir a atividade a partir do click da tarefa também através do calendário.
    close, x, round, denied Permitir que eu arraste a terafa do calendário para outro dia do calendário e que a tarefa acima lá no checklist se atualize sozinha
     close, x, round, denied  Funcionalidade para excluir ou marcar como concluída uma tarefa diretamente do calendário.

 

 

accept, check, success, tick Relatório de Bloqueantes e tarefas destacadas (Títulos de Projeto) e Relatório de Tarefas Ordenadas por Número: :

      accept, check, success, tick Geração de um relatório detalhado das tarefas bloqueantes agrupadas por pessoa atribuída. (Gera um relatório de todas as tarefas e subtarefas bloqueantes.)
      accept, check, success, tick Criação de relatórios detalhados de atividades bloqueantes, incluindo informações sobre subtarefas e campos personalizados. (Gera um relatório de todas as tarefas e subtarefas marcadas como títulos de projeto.)
      accept, check, success, tick Geração de relatórios de tarefas bloqueantes e títulos de projeto, agrupados por pessoa atribuída.
       close, x, round, denied  Impressão do relatório de bloqueantes
       close, x, round, denied Geração de um relatório detalhado das tarefas destacadas agrupadas por pessoa atribuída..

      accept, check, success, tick Gera um relatório de todas as tarefas e subtarefas ordenadas por número, da maior para a menor.

 

accept, check, success, tick Armazenamento Local:

    accept, check, success, tick Uso do localStorage para salvar e restaurar o estado das tarefas, mantendo a persistência de dados mesmo após recarregar a página.

    close, x, round, denied  Banco de dados próprio
    close, x, round, denied  Banco de dados no servidor


accept, check, success, tick Edição de Tarefas:

    accept, check, success, tick Tarefas podem ser editadas diretamente na interface, incluindo a alteração de atributos como tag, número, pessoa, datas, horário, etc.
    accept, check, success, tick  Editar o nome da tarefa e subtarefas ( O nome das tarefas e subtarefas também podem ser editadas (Permite a edição do nome das tarefas e subtarefas.)
    accept, check, success, tick  Tarefas do calendário podem ser editadas e sincronizadas com o checklist.

 

accept, check, success, tick Exclusão de Tarefas:

     accept, check, success, tick Tarefas e subtarefas podem ser removidas da lista.

     accept, check, success, tick  Você tem certeza que você deseja excluir essa tarefa?

 

 

accept, check, success, tick Histórico de Tarefas Concluídas:

    accept, check, success, tick Registro de tarefas concluídas com possibilidade de visualização de um histórico.

 

 

accept, check, success, tick Interface Responsiva: e Usabilidade Interativa:

    accept, check, success, tick Expansão e contração de listas de tarefas e subtarefas. (Permite expandir e contrair subtarefas para melhor organização visual.)

    accept, check, success, tick Marcação de tarefas como concluídas com a opção de mover para o histórico de atividades concluídas.

    accept, check, success, tick Uso de botões para adicionar, editar e remover tarefas e subtarefas.

    accept, check, success, tick Integração com LocalStorage para salvar o estado do checklist.
    accept, check, success, tick  Eventos de Teclado: Permite adicionar tarefas pressionando a tecla Enter.

    accept, check, success, tick Modal para adicionar tarefas específicas para datas selecionadas no calendário.

    accept, check, success, tick  Funções para Atualizar o Calendário: Funções para atualizar o calendário com base nas tarefas adicionadas e modificadas.

 

accept, check, success, tick Interação com o Usuário:

    accept, check, success, tick Confirmar ao excluir tarefas: "Você tem certeza que deseja excluir essa tarefa?

    accept, check, success, tick Confirmar ao concluir tarefas: "Você tem certeza que deseja concluir essa tarefa?

 

 

accept, check, success, tick Manipulação de Elementos DOM:
    accept, check, success, tick Utilização de eventos DOM para adicionar, remover, editar e marcar tarefas diretamente na interface do usuário.


accept, check, success, tick Drag and Drop
    accept, check, success, tick Implementação de arrastar e soltar para reordenar tarefas e subtarefas usando a biblioteca Sortable.

O código acima implementa um sistema de produtividade com várias funcionalidades organizadas em torno de um checklist e um calendário mensal. Aqui estão as principais funcionalidades presentes:

 

accept, check, success, tick Salvamento e Carregamento:

Salvar o estado da checklist no localStorage.

Exportar e importar checklists em formato HTML e Excel.

Baixar backups em HTML e Excel e carregar arquivos de checklist desses formatos.

Impressão e Backup:

 

accept, check, success, tick Funcionalidades de Backup e Restauração:

     accept, check, success, tick Download do Checklist em Excel: Permite fazer o download do checklist de tarefas e subtarefas em formato Excel

     accept, check, success, tick Upload de Checklist em Excel: Permite fazer o upload de um arquivo Excel para restaurar o checklist de tarefas e subtarefas.




Próxima atualização fazer com que o calendário possa tudo isso que já tem. 
close, x, round, denied  Funções para Atualizar o Calendário: Funções para atualizar o calendário com base nas tarefas adicionadas e modificadas.
close, x, round, denied  Funcionalidade para excluir ou marcar como concluída uma tarefa diretamente do calendário.
     close, x, round, denied Tarefas podem ser marcadas como concluídas, sendo movidas para a seção de atividades concluídas e exibidas com um estilo diferente (riscadas).
     close, x, round, denied  Você tem certeza que deseja concluir essa tarefa?
     close, x, round, denied Tarefas podem ser editadas diretamente na interface, incluindo a alteração de atributos como tag, número, pessoa, datas, horário, etc.
    close, x, round, denied  Editar o nome da tarefa e subtarefas ( O nome das tarefas e subtarefas também podem ser editadas (Permite a edição do nome das tarefas e subtarefas.)
    close, x, round, denied  Tarefas do calendário podem ser editadas e sincronizadas com o checklist.

 

Adicionar Tarefas e Subtarefas:

Adicionar novas tarefas com campos personalizados como tag, número, pessoa responsável, data, horário, valor, razão, local, e método de execução.

Adicionar subtarefas dentro de tarefas principais.

Campos Personalizados:

Adicionar e gerenciar campos personalizados para cada tarefa.

Filtragem e Ordenação:

Filtrar tarefas por tag, pessoa, campo personalizado e palavras-chave.

Ordenar tarefas por número.

Checklist Interativo:

Marcar tarefas como concluídas, movendo-as para um histórico de atividades concluídas.

Identificar e marcar tarefas bloqueantes e títulos de projetos.

Relatórios:

Gerar relatórios de tarefas bloqueantes, títulos de projetos, e tarefas ordenadas por número.

Visualizar tarefas bloqueantes e títulos de projetos filtrados.

Agenda e Calendário:

Visualizar as tarefas e eventos em um calendário mensal, com horários específicos.

Destacar eventos ocupados no calendário.

Salvamento e Carregamento:

Salvar o estado da checklist no localStorage.

Exportar e importar checklists em formato HTML e Excel.

Baixar backups em HTML e Excel e carregar arquivos de checklist desses formatos.

Impressão e Backup:

Imprimir a checklist.

Baixar um backup em formato HTML.

Subir arquivos HTML para restaurar a checklist.

Interface Interativa:

Usar botões interativos para expandir/colapsar subtarefas, marcar tarefas como bloqueantes ou títulos de projetos, e remover tarefas.

Implementação de sortable para arrastar e soltar tarefas dentro da checklist.

Essas funcionalidades permitem uma gestão detalhada e personalizada de tarefas e projetos, auxiliando na organização e na visualização do progresso das atividades.