...

Hacks na criação

 Inclua no código abaixo deixando ele completo.....
(Editar chat`s até ele acertar)

 

História do sistema

Sempre fui um péssimo priorizador de atividades e um enrolador por não saber qual tarefa chave de um projeto atacar, sempre me perdi no meio do processo e muitas vezes, não terminei projetos que iniciei por falta de capacidade e organização diante a tantas outras prioridades que surgem diante da nossa jornada. 

Sobre o sistema

O sistema "Ballaminut Networking - Sistema de produtividade"

tem diversas funcionalidades que permitem a gestão de tarefas e eventos de forma organizada e eficiente.
 

     

      As listas de tarefas são interativas, permitindo reordenação dos itens via arrastar e soltar, graças à integração com a biblioteca Sortable.js.

Essas funcionalidades proporcionam um sistema robusto e flexível para o gerenciamento de produtividade, permitindo aos usuários organizarem suas tarefas e eventos de maneira eficiente e personalizada.

Vídeo de explicação

Qual linguagem?

Front End

 

HTML (HyperText Markup Language):

Utilizada para estruturar o conteúdo da página, incluindo elementos como <div>, <table>, <input>, <button>, e <label>. Define a estrutura básica do documento.

 

CSS (Cascading Style Sheets):

Usada para estilizar a página web. No código fornecido, há dois blocos <style> que definem o layout, cores, fontes, espaçamento e outros aspectos visuais dos elementos HTML.

 

JavaScript:

Utilizado para adicionar interatividade e funcionalidade dinâmica à página. O código JavaScript é incluído dentro das tags <script> e fornece funcionalidades como adicionar tarefas, manipular a DOM, armazenar e recuperar dados do localStorage, e implementar um calendário dinâmico.

 

Biblioteca JavaScript (Sortable.js):

Importada através de uma URL (https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.14.0/Sortable.min.js), esta biblioteca é utilizada para permitir a ordenação dos itens da lista de tarefas através de arrastar e soltar (drag and drop).

 

 

Back End

close, x, round, denied

 

Qual código?

<!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>
    </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';

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

            if (task.customFields) {
                for (const fieldName in task.customFields) {
                    const customField = document.createElement('input');
                    customField.type = 'text';
                    customField.value = task.customFields[fieldName];
                    customField.placeholder = fieldName;
                    customField.className = 'custom-field-input';
                    taskHeader.appendChild(customField);
                }
            }

            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);
            if (task.blocker) {
                taskContainer.classList.add('blocker');
            }
            if (task.projectTitle) {
                taskContainer.classList.add('project-title');
            }
            checklistItems.appendChild(taskContainer);

            initializeSortable(nestedList);
            updateCalendar();
        }

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

            initializeSortable(subNestedList);
            updateCalendar();
        }

        function initializeSortable(container) {
            new Sortable(container, {
                group: 'nested',
                animation: 150,
                fallbackOnBody: true,
                swapThreshold: 0.65,
                onEnd: () => {
                    saveChecklistState();
                }
            });

            const nestedLists = container.querySelectorAll('.nested-list');
            nestedLists.forEach(nestedList => {
                new Sortable(nestedList, {
                    group: 'nested',
                    animation: 150,
                    fallbackOnBody: true,
                    swapThreshold: 0.65,
                    onEnd: () => {
                        saveChecklistState();
                    }
                });
            });
        }

        function updateFilterDropdown() {
            const tags = new Set();
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];

            function collectTags(task) {
                if (task.tag) {
                    tags.add(task.tag);
                }
                if (task.subTasks) {
                    task.subTasks.forEach(subTask => collectTags(subTask));
                }
            }

            tasks.forEach((task) => {
                collectTags(task);
            });

            const tagFilter = document.getElementById('tagFilter');
            tagFilter.innerHTML = '<option value="">Todas</option>';
            tags.forEach((tag) => {
                const option = document.createElement('option');
                option.value = tag;
                option.textContent = tag;
                tagFilter.appendChild(option);
            });
        }

        function updatePersonFilterDropdown() {
            const people = new Set();
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];

            function collectPeople(task) {
                if (task.person) {
                    people.add(task.person);
                }
                if (task.subTasks) {
                    task.subTasks.forEach(subTask => collectPeople(subTask));
                }
            }

            tasks.forEach((task) => {
                collectPeople(task);
            });

            const personFilter = document.getElementById('personFilter');
            personFilter.innerHTML = '<option value="">Todas</option>';
            people.forEach((person) => {
                const option = document.createElement('option');
                option.value = person;
                option.textContent = person;
                personFilter.appendChild(option);
            });
        }

        function filterTasks() {
            const selectedTag = document.getElementById('tagFilter').value;
            const selectedPerson = document.getElementById('personFilter').value;
            const customFieldFilter = document.getElementById('customFieldFilter').value.trim().toLowerCase();
            const keywordFilter = document.getElementById('keywordFilter').value.trim().toLowerCase();

            function matchesCustomFilters(taskContainer) {
                const customFieldInputs = taskContainer.querySelectorAll('.custom-field-input');
                for (const input of customFieldInputs) {
                    if (input.value.toLowerCase() === customFieldFilter) {
                        return true;
                    }
                }
                return customFieldFilter === '';
            }

            function matchesKeyword(taskContainer) {
                const label = taskContainer.querySelector('.checklist-label').value.toLowerCase();
                return label.includes(keywordFilter);
            }

            function matchesFilters(taskContainer) {
                const tag = taskContainer.getAttribute('data-tag');
                const person = taskContainer.getAttribute('data-person');
                const matchesTag = selectedTag === '' || tag === selectedTag;
                const matchesPerson = selectedPerson === '' || person === selectedPerson;
                const matchesCustom = matchesCustomFilters(taskContainer);
                const matchesKeywords = matchesKeyword(taskContainer);
                return matchesTag && matchesPerson && matchesCustom && matchesKeywords;
            }

            function filterTask(taskContainer) {
                const showTask = matchesFilters(taskContainer);
                const subTasks = taskContainer.querySelectorAll('.checklist-container');
                let showSubTasks = false;

                subTasks.forEach(subTaskContainer => {
                    if (filterTask(subTaskContainer)) {
                        showSubTasks = true;
                    }
                });

                if (showTask || showSubTasks) {
                    taskContainer.style.display = 'flex';
                } else {
                    taskContainer.style.display = 'none';
                }

                return showTask || showSubTasks;
            }

            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach(taskContainer => {
                filterTask(taskContainer);
            });
        }

        function filterBlockers() {
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach(taskContainer => {
                const isBlocker = taskContainer.classList.contains('blocker');
                const subTasks = taskContainer.querySelectorAll('.checklist-container');
                let showTask = isBlocker;

                subTasks.forEach(subTaskContainer => {
                    if (filterTask(subTaskContainer) && subTaskContainer.classList.contains('blocker')) {
                        showTask = true;
                    }
                });

                if (showTask) {
                    taskContainer.style.display = 'flex';
                } else {
                    taskContainer.style.display = 'none';
                }
            });
        }

        function filterProjectTitles() {
            const checklistItems = document.querySelectorAll('#checklistItems > .checklist-container');
            checklistItems.forEach(taskContainer => {
                const isProjectTitle = taskContainer.classList.contains('project-title');
                const subTasks = taskContainer.querySelectorAll('.checklist-container');
                let showTask = isProjectTitle;

                subTasks.forEach(subTaskContainer => {
                    if (filterTask(subTaskContainer) && subTaskContainer.classList.contains('project-title')) {
                        showTask = true;
                    }
                });

                if (showTask) {
                    taskContainer.style.display = 'flex';
                } else {
                    taskContainer.style.display = 'none';
                }
            });
        }

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

        function generateSortedNumberReport() {
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];
            const sortedNumberReport = document.getElementById('sortedNumberReport');
            sortedNumberReport.innerHTML = '';

            const allTasks = [];

            function collectTasks(task) {
                allTasks.push(task);
                if (task.subTasks) {
                    task.subTasks.forEach(subTask => collectTasks(subTask));
                }
            }

            tasks.forEach(task => collectTasks(task));

            allTasks.sort((a, b) => b.number - a.number);

            allTasks.forEach(task => {
                const taskDiv = document.createElement('div');
                taskDiv.className = 'report-item';
                taskDiv.textContent = `Número: ${task.number}, Nome: ${task.name}, Pessoa: ${task.person}`;
                sortedNumberReport.appendChild(taskDiv);
            });
        }

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

        function moveToCompleted(taskContainer) {
            const completedTasks = document.getElementById('completedTasks');
            taskContainer.classList.add('completed-task');
            completedTasks.appendChild(taskContainer);
        }

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

            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];

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

            for (let i = 0; i < 36; i++) {
                const year = currentYear + Math.floor((currentMonth + i) / 12);
                const monthIndex = (currentMonth + i) % 12;
                const monthDiv = document.createElement('div');
                monthDiv.classList.add('calendar-month');
                monthDiv.textContent = `${getMonthName(monthIndex)} ${year}`;
                calendar.appendChild(monthDiv);

                const firstDayOfMonth = new Date(year, monthIndex, 1).getDay();
                const daysInMonth = new Date(year, monthIndex + 1, 0).getDate();

                let weekDiv = document.createElement('div');
                weekDiv.classList.add('calendar-week');
                calendar.appendChild(weekDiv);

                for (let blank = 0; blank < firstDayOfMonth; blank++) {
                    const blankDay = document.createElement('div');
                    blankDay.classList.add('calendar-day');
                    weekDiv.appendChild(blankDay);
                }

                for (let day = 1; day <= daysInMonth; day++) {
                    if ((day + firstDayOfMonth - 1) % 7 === 0) {
                        weekDiv = document.createElement('div');
                        weekDiv.classList.add('calendar-week');
                        calendar.appendChild(weekDiv);
                    }

                    const date = new Date(year, monthIndex, day);
                    const dateString = date.toISOString().split('T')[0];

                    const dayElement = document.createElement('div');
                    dayElement.classList.add('calendar-day');
                    dayElement.textContent = day;

                    dayElement.addEventListener('click', () => {
                        openTaskModal(dateString);
                    });

                    const eventsForDay = getAllEventsForDay(tasks, dateString);

                    if (eventsForDay.length > 0) {
                        dayElement.classList.add('occupied');
                        eventsForDay.sort((a, b) => a.time.localeCompare(b.time));
                        eventsForDay.forEach(event => {
                            const eventElement = document.createElement('div');
                            eventElement.classList.add('calendar-event');
                            if (event.isEnd) {
                                eventElement.classList.add('end');
                            }
                            eventElement.innerHTML = `${event.time ? event.time + ' - ' : ''}${event.name}`;
                            dayElement.appendChild(eventElement);
                        });
                    }

                    weekDiv.appendChild(dayElement);
                }
            }
        }

        function getAllEventsForDay(tasks, dateString) {
            let events = [];
            tasks.forEach(task => {
                if (task.date === dateString) {
                    events.push({ name: task.name, reason: task.reason, location: task.location, method: task.method, time: task.time });
                }
                if (task.endDate === dateString) {
                    events.push({ name: task.name, reason: task.reason, location: task.location, method: task.method, time: task.time, isEnd: true });
                }
                if (task.subTasks) {
                    events = events.concat(getSubTasksForDay(task.subTasks, dateString));
                }
            });
            return events;
        }

        function getSubTasksForDay(subTasks, dateString) {
            let events = [];
            subTasks.forEach(subTask => {
                if (subTask.date === dateString) {
                    events.push({ name: subTask.name, reason: subTask.reason, location: subTask.location, method: subTask.method, time: subTask.time });
                }
                if (subTask.endDate === dateString) {
                    events.push({ name: subTask.name, reason: subTask.reason, location: subTask.location, method: subTask.method, time: subTask.time, isEnd: true });
                }
                if (subTask.subTasks) {
                    events = events.concat(getSubTasksForDay(subTask.subTasks, dateString));
                }
            });
            return events;
        }

        function getMonthName(monthIndex) {
            const months = ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'];
            return months[monthIndex % 12];
        }

        function generateBlockerReport() {
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];
            const blockerReport = document.getElementById('blockerReport');
            blockerReport.innerHTML = '';

            const blockersByPerson = {};

            function collectBlockers(task) {
                if (task.blocker) {
                    if (!blockersByPerson[task.person]) {
                        blockersByPerson[task.person] = [];
                    }
                    blockersByPerson[task.person].push(task);
                }
                if (task.subTasks) {
                    task.subTasks.forEach(subTask => collectBlockers(subTask));
                }
            }

            tasks.forEach(task => collectBlockers(task));

            for (const person in blockersByPerson) {
                const personDiv = document.createElement('div');
                personDiv.className = 'report-item';
                personDiv.innerHTML = `<h3>${person}</h3>`;

                const taskList = document.createElement('ul');
                blockersByPerson[person].forEach(task => {
                    const taskItem = document.createElement('li');
                    taskItem.textContent = task.name;
                    taskList.appendChild(taskItem);
                });

                personDiv.appendChild(taskList);
                blockerReport.appendChild(personDiv);
            }
        }

        function generateProjectTitleReport() {
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];
            const projectTitleReport = document.getElementById('projectTitleReport');
            projectTitleReport.innerHTML = '';

            const projectTitlesByPerson = {};

            function collectProjectTitles(task) {
                if (task.projectTitle) {
                    if (!projectTitlesByPerson[task.person]) {
                        projectTitlesByPerson[task.person] = [];
                    }
                    projectTitlesByPerson[task.person].push(task);
                }
                if (task.subTasks) {
                    task.subTasks.forEach(subTask => collectProjectTitles(subTask));
                }
            }

            tasks.forEach(task => collectProjectTitles(task));

            for (const person in projectTitlesByPerson) {
                const personDiv = document.createElement('div');
                personDiv.className = 'report-item';
                personDiv.innerHTML = `<h3>${person}</h3>`;

                const taskList = document.createElement('ul');
                projectTitlesByPerson[person].forEach(task => {
                    const taskItem = document.createElement('li');
                    taskItem.textContent = task.name;
                    taskList.appendChild(taskItem);
                });

                personDiv.appendChild(taskList);
                projectTitleReport.appendChild(personDiv);
            }
        }

        function addCustomField(taskContainer) {
            const fieldName = prompt('Digite o nome do novo campo:');
            if (fieldName) {
                const customField = document.createElement('input');
                customField.type = 'text';
                customField.placeholder = fieldName;
                customField.className = 'custom-field-input';
                customField.addEventListener('change', function() {
                    taskContainer.setAttribute(`data-custom-${fieldName}`, customField.value);
                    saveChecklistState();
                });
                taskContainer.querySelector('div').appendChild(customField);
                taskContainer.setAttribute(`data-custom-${fieldName}`, customField.value);
                saveChecklistState();
            }
        }

        function openTaskModal(dateString) {
            const taskInput = document.getElementById('newTask');
            taskInput.value = '';
            document.getElementById('newTag').value = '';
            document.getElementById('newNumber').value = '';
            document.getElementById('newPerson').value = '';
            document.getElementById('newDate').value = dateString;
            document.getElementById('newEndDate').value = '';
            document.getElementById('newTime').value = '';
            document.getElementById('newAmount').value = '';
            document.getElementById('newReason').value = '';
            document.getElementById('newLocation').value = '';
            document.getElementById('newMethod').value = '';

            const addButton = document.querySelector('.add-task-button');
            addButton.onclick = function() {
                addTask();
                updateCalendar();
            };

            const modal = document.createElement('div');
            modal.className = 'modal';
            modal.style.position = 'fixed';
            modal.style.top = '50%';
            modal.style.left = '50%';
            modal.style.transform = 'translate(-50%, -50%)';
            modal.style.backgroundColor = 'white';
            modal.style.padding = '20px';
            modal.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.5)';

            const modalContent = `
                <h2>Adicionar Tarefa para ${dateString}</h2>
                <div class="add-task-container">
                    <input type="text" id="newTaskModal" class="add-task-input" placeholder="Digite uma nova tarefa">
                    <input type="text" id="newTagModal" class="add-tag-input" placeholder="Digite uma tag">
                    <input type="number" id="newNumberModal" class="add-number-input" placeholder="Número" min="1">
                    <input type="text" id="newPersonModal" class="add-person-input" placeholder="Atribuir a">
                    <input type="date" id="newDateModal" class="add-date-input" value="${dateString}">
                    <input type="date" id="newEndDateModal" class="add-end-date-input" placeholder="Data de término">
                    <input type="time" id="newTimeModal" class="add-time-input" placeholder="Horário">
                    <input type="number" id="newAmountModal" class="add-amount-input" placeholder="Quanto" step="0.01">
                    <input type="text" id="newReasonModal" class="add-reason-input" placeholder="Por que da tarefa?">
                    <input type="text" id="newLocationModal" class="add-location-input" placeholder="Onde será a tarefa?">
                    <input type="text" id="newMethodModal" class="add-method-input" placeholder="Como será feita essa tarefa?">
                    <button onclick="addTaskFromModal('${dateString}')" class="add-task-button">Adicionar Tarefa</button>
                </div>
            `;

            modal.innerHTML = modalContent;
            document.body.appendChild(modal);

            const closeButton = document.createElement('button');
            closeButton.textContent = 'Fechar';
            closeButton.onclick = function() {
                document.body.removeChild(modal);
            };
            modal.appendChild(closeButton);
        }

        function addTaskFromModal(dateString) {
            const taskName = document.getElementById('newTaskModal').value.trim();
            const tagName = document.getElementById('newTagModal').value.trim().toLowerCase();
            const taskNumber = document.getElementById('newNumberModal').value.trim();
            const personName = document.getElementById('newPersonModal').value.trim();
            const taskDate = document.getElementById('newDateModal').value;
            const endDate = document.getElementById('newEndDateModal').value;
            const taskTime = document.getElementById('newTimeModal').value;
            const amount = document.getElementById('newAmountModal').value.trim();
            const taskReason = document.getElementById('newReasonModal').value.trim();
            const taskLocation = document.getElementById('newLocationModal').value.trim();
            const taskMethod = document.getElementById('newMethodModal').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);

                document.querySelector('.modal').remove();

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

        function deleteTaskFromCalendar(event, taskId) {
            event.stopPropagation();
            const taskContainer = document.querySelector(`#${taskId}`).closest('.checklist-container');
            if (taskContainer && confirm('Você tem certeza que deseja excluir essa tarefa?')) {
                taskContainer.remove();
                saveChecklistState();
                updateCalendar();
            }
        }

        function completeTaskFromCalendar(event, taskId) {
            event.stopPropagation();
            const taskCheckbox = document.querySelector(`#${taskId}`);
            if (taskCheckbox && !taskCheckbox.checked) {
                taskCheckbox.checked = true;
                const taskContainer = taskCheckbox.closest('.checklist-container');
                const label = taskContainer.querySelector('.checklist-label');
                label.classList.toggle('completed', taskCheckbox.checked);
                moveToCompleted(taskContainer);
                saveChecklistState();
                updateCalendar();
            }
        }

        document.addEventListener("DOMContentLoaded", () => {
            restoreChecklistState();
            const checklistItems = document.getElementById('checklistItems');
            initializeSortable(checklistItems);
            updateCalendar();
        });

        // Function to flatten tasks and subtasks
        function flattenTasks(tasks) {
            const flattened = [];
            function addTasks(task, parentId = null) {
                const { subTasks, ...taskWithoutSubtasks } = task;
                flattened.push({ ...taskWithoutSubtasks, parentId });
                if (subTasks) {
                    subTasks.forEach(subTask => addTasks(subTask, task.id));
                }
            }
            tasks.forEach(task => addTasks(task));
            return flattened;
        }

        // Function to build hierarchical structure from flattened tasks
        function buildHierarchy(flattenedTasks) {
            const taskMap = {};
            flattenedTasks.forEach(task => {
                task.subTasks = [];
                taskMap[task.id] = task;
            });
            const rootTasks = [];
            flattenedTasks.forEach(task => {
                if (task.parentId) {
                    taskMap[task.parentId].subTasks.push(task);
                } else {
                    rootTasks.push(task);
                }
            });
            return rootTasks;
        }

        // Function to download the checklist as an Excel file
        function downloadExcel() {
            const tasks = JSON.parse(localStorage.getItem('checklistItems')) || [];
            const flattenedTasks = flattenTasks(tasks);
            const worksheet = XLSX.utils.json_to_sheet(flattenedTasks);
            const workbook = XLSX.utils.book_new();
            XLSX.utils.book_append_sheet(workbook, worksheet, 'Checklist');
            XLSX.writeFile(workbook, 'checklist.xlsx');
        }

        // Function to upload the Excel file and restore the checklist
        function uploadExcel(event) {
            const file = event.target.files[0];
            if (!file) return;

            const reader = new FileReader();
            reader.onload = function (e) {
                const data = new Uint8Array(e.target.result);
                const workbook = XLSX.read(data, { type: 'array' });
                const sheetName = workbook.SheetNames[0];
                const worksheet = workbook.Sheets[sheetName];
                const flattenedTasks = XLSX.utils.sheet_to_json(worksheet);
                const tasks = buildHierarchy(flattenedTasks);

                localStorage.setItem('checklistItems', JSON.stringify(tasks));
                document.getElementById('checklistItems').innerHTML = '';
                restoreChecklistState();
            };
            reader.readAsArrayBuffer(file);
        }
    </script>
</body>
</html>

O Sistema funcionando

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

Quais funcionalidades?

Projetos x Tarefas 

Tarefas
Funcionalidade por funcionalidade

 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

Adicionar Subtarefas:

     accept, check, success, tick Cada tarefa pode ter subtarefas aninhadas, permitindo uma estrutura hierárquica de tarefas.

     accept, check, success, tick  Possibilidade de adicionar subtarefas a cada tarefa, com a mesma funcionalidade de detalhamento e edição.

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

     close, x, round, denied Palavras-chave e destaque 
     close, x, round, denied Filtro para mostrar apenas tarefas bloqueantes.
     close, x, round, denied 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).
     close, x, round, denied  Você tem certeza que deseja concluir essa tarefa?

 

accept, check, success, tick

Gerenciamento de Bloqueantes

 

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

    close, x, round, denied Tarefas e subtarefas 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.)

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.

    close, x, round, denied  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.)

    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.

accept, check, success, tick

Relatório de Bloqueantes e tarefas destacadas

      accept, check, success, tick Geração de um relatório detalhado das tarefas bloqueantes agrupadas por pessoa atribuída.
      accept, check, success, tick Criação de relatórios detalhados de atividades bloqueantes, incluindo informações sobre subtarefas e campos personalizados.
       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
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.
    close, x, round, denied  Editar o nome da tarefa

accept, check, success, tick

Exclusão de Tarefas:

 

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

     close, x, round, denied  Você tem certeza que você deseja excluir essa tarefa?

close, x, round, denied Histórico de Tarefas Concluídas:

 

    close, x, round, denied Registro de tarefas concluídas com possibilidade de visualização de um histórico.

 

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:

 

     accept, check, success, tick Cada tarefa pode ter subtarefas aninhadas e desaninhadas, permitindo uma estrutura hierárquica de tarefas.

     accept, check, success, tick  Possibilidade de adicionar  e retirar subtarefas a cada tarefa, com a mesma funcionalidade de detalhamento e edição.
     accept, check, success, tick Permite adicionar e retirar subtarefas aninhadas dentro de uma tarefa.

     accept, check, success, tick Permite mover tarefas e subtarefas de maneira livre entre todas as tarefas e subtarefas

     accept, check, success, tick Permite mover subtarefas para que elas virem tarefas também

     accept, check, success, tick Cada tarefa pode ter subtarefas aninhadas.

     accept, check, success, tick Subtarefas podem ser adicionadas, editadas e removidas.     accept, check, success, tick 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 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.



 

O sistema acima, "Ballaminut Networking - Sistema de produtividade", é uma aplicação web para gerenciamento de tarefas e produtividade. Abaixo estão listadas as principais funcionalidades do sistema:

Funcionalidades de Tarefas:

  1. Adicionar Tarefas: Permite adicionar novas tarefas com diversos campos:

    • Nome da tarefa
    • Tag
    • Número
    • Pessoa atribuída
    • Data de realização
    • Data de término
    • Horário
    • Quantia (monetária ou outra)
    • Razão da tarefa
    • Localização
    • Método de execução
  2. Adicionar Subtarefas: As tarefas podem ter subtarefas associadas.

  3. Adicionar Campos Personalizados: Permite adicionar campos personalizados às tarefas para atender a necessidades específicas.

  4. Marcar Tarefas como Concluídas: As tarefas podem ser marcadas como concluídas através de um checkbox. Tarefas concluídas são movidas para o histórico de atividades concluídas.

  5. Excluir Tarefas: As tarefas podem ser excluídas.

  6. Marcar Tarefas como Bloqueantes: Tarefas podem ser marcadas como bloqueantes para indicar que estão impedindo o progresso de outras tarefas.

  7. Marcar Tarefas como Títulos de Projeto: Tarefas podem ser marcadas como títulos de projeto para diferenciar projetos principais de tarefas normais.

Funcionalidades de Filtros e Ordenação:

  1. Filtrar Tarefas: Permite filtrar tarefas por tag, pessoa atribuída, campo personalizado e palavras-chave.

  2. Ordenar Tarefas por Número: Permite ordenar tarefas de acordo com o número associado a elas.

  3. Mostrar Bloqueantes: Permite filtrar a visualização para mostrar apenas tarefas bloqueantes.

  4. Mostrar Títulos de Projeto: Permite filtrar a visualização para mostrar apenas tarefas marcadas como títulos de projeto.

Funcionalidades de Relatórios:

  1. Gerar Relatório de Bloqueantes: Gera um relatório de todas as tarefas bloqueantes, agrupadas por pessoa atribuída.

  2. Gerar Relatório de Títulos de Projeto: Gera um relatório de todas as tarefas marcadas como títulos de projeto, agrupadas por pessoa atribuída.

  3. Gerar Relatório Ordenado por Número: Gera um relatório de todas as tarefas, ordenadas por número.

Funcionalidades de Calendário:

  1. Visualização de Calendário Mensal: Exibe um calendário mensal com as tarefas distribuídas nos respectivos dias.

  2. Adicionar Tarefas através do Calendário: Permite adicionar tarefas diretamente no calendário, selecionando o dia desejado.

 

  1.  

Funcionalidades de Armazenamento:

  1. Armazenamento Local: As tarefas e seu estado são armazenados no localStorage do navegador, permitindo que os dados persistam entre sessões.

Funcionalidades de UI e Interatividade:

  1. Interface de Usuário Interativa: A interface é interativa, permitindo arrastar e soltar tarefas, adicionar subtarefas e campos personalizados dinamicamente.
  2. Modal para Adição de Tarefas: Modal interativo para adição de tarefas diretamente pelo calendário.

Bibliotecas Utilizadas:

  1. SortableJS: Para arrastar e soltar itens na lista de tarefas.
  2. XLSX.js: Para manipulação de arquivos Excel (download e upload).

As principais funcionalidades

Não mude nada, só confirme para mim se esse código está condizente com:

 

 IDE: 1xjgb-5xt7SB0WzmwtWUYZQodKzMym2iAlzWzy8qRyFE
Aba da planilha: Projects
Link da Instalação do Script: https://script.google.com/macros/s/AKfycbz3GuCR5O2Gw1pK4YTURCzZI5bImw0nzXFw9UyDxmTFD9MlF9FyZxi3ZCwVw4IfVLqbrg/exec

Código do GS que está no google apps:

function doPost(e) {
    var action = e.parameter.action;
    if (action == 'addProject') {
        return addProject(e);
    } else if (action == 'getProjects') {
        return getProjects();
    }
    return ContentService.createTextOutput(JSON.stringify({ status: 'failure', message: 'Action not recognized' }));
}

function addProject(e) {
    var projectName = e.parameter.projectName;
    var activities = JSON.parse(e.parameter.activities);
    var sheet = SpreadsheetApp.openById('1xjgb-5xt7SB0WzmwtWUYZQodKzMym2iAlzWzy8qRyFE').getSheetByName('Projects');
    var row = [projectName];
    activities.forEach(function(activity) {
        row.push(activity);
    });
    sheet.appendRow(row);
    return ContentService.createTextOutput(JSON.stringify({ status: 'success' }));
}

function getProjects() {
    var sheet = SpreadsheetApp.openById('1xjgb-5xt7SB0WzmwtWUYZQodKzMym2iAlzWzy8qRyFE').getSheetByName('Projects');
    var data = sheet.getDataRange().getValues();
    return ContentService.createTextOutput(JSON.stringify(data));
}
 

backend

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Editores 

de código

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Google 

Planilhas 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Plataforma

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

GS

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Plataforma 

Google Apps

 

 

 

 

 

 

 

 

 


 

Url da implantação

https://script.google.com/macros/s/AKfycbyEfLdcASrTYzLh_mE_rLKMsGOrQOxl4z0KBKQtVQjvrrQIbhy2mkK96xKbIO-4HLEC7A/exec

 

NODE .png

 

 

 

 

 

 

 

 

 

 

 

 

 

Funcionalidades

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

FrontEnd

 

 

 

 

 

 

 

 

 

Google sites

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Linguagens

 

 

 

 

 

 

 

 

HTML.png
CSS.png
JAVA.png

Sistemas

 

 

 

 

 

 

 

 

 

 

Sistemas

 

 

 

 

 

 

 

 

 

Para criar um sistema web completo com banco de dados, interconexões entre páginas e funcionalidades de login, aqui estão os passos gerais que você pode seguir:

1. Aprender Tecnologias Fundamentais:

  • HTML/CSS/JavaScript: Dominar essas linguagens para criar a interface do usuário e adicionar interatividade.
  • Banco de Dados: Aprender sobre bancos de dados relacionais (como MySQL, PostgreSQL) ou não relacionais (como MongoDB) para armazenar dados.
  • Backend: Aprender uma linguagem de programação para backend, como JavaScript (Node.js), Python (Django, Flask), PHP (Laravel), Ruby (Ruby on Rails), entre outras.

2. Escolher um Ambiente de Desenvolvimento:

  • IDE (Integrated Development Environment): Utilizar um ambiente de desenvolvimento como Visual Studio Code, Atom, ou qualquer outro de sua preferência.
  • Servidor Web: Pode começar localmente usando um servidor local como XAMPP (para PHP), ou configurar um ambiente de desenvolvimento usando Node.js.

3. Criar o Banco de Dados:

  • Escolher um Banco de Dados: Decidir entre um banco de dados relacional (SQL) ou não relacional (NoSQL) baseado nas necessidades do seu projeto.
  • Configurar e Conectar: Configurar o banco de dados localmente ou através de um provedor de serviços de banco de dados na nuvem como AWS RDS, Azure SQL Database, MongoDB Atlas, etc.

4. Desenvolver o Backend:

  • Escolher uma Tecnologia Backend: Baseado na linguagem escolhida (Node.js, Python, PHP, etc.), desenvolver APIs RESTful para interação com o banco de dados e processamento de dados do frontend.
  • Implementar Autenticação: Utilizar bibliotecas ou frameworks para implementar autenticação segura, como JWT (JSON Web Tokens) para tokens de autenticação.

5. Implementar o Frontend:

  • Desenvolver Páginas Web: Utilizar HTML, CSS, JavaScript (possivelmente com frameworks como React, Angular, Vue.js) para criar a interface do usuário interativa.
  • Integrar com Backend: Consumir APIs RESTful do backend para enviar e receber dados do banco de dados.

6. Deploy e Manutenção:

  • Hospedagem: Escolher um serviço de hospedagem web (como AWS, Heroku, DigitalOcean) para implantar seu aplicativo.
  • Monitoramento e Manutenção: Monitorar o desempenho, corrigir bugs e fazer atualizações conforme necessário.

Recursos de Aprendizagem:

  • Cursos Online: Plataformas como Udemy, Coursera, edX oferecem cursos completos sobre desenvolvimento web, bancos de dados e segurança.
  • Documentação e Tutoriais: Utilizar a documentação oficial das tecnologias e tutoriais online para orientações passo a passo.

Dicas Adicionais:

  • Comunidade e Fóruns: Participar de comunidades online, como Stack Overflow, Reddit, e grupos no LinkedIn para obter suporte e compartilhar conhecimentos.
  • Projetos de Prática: Criar pequenos projetos para praticar as habilidades aprendidas e ganhar confiança.

Com dedicação e prática constante, você poderá desenvolver sistemas web completos com banco de dados e funcionalidades avançadas de login.