Patabugen / Sunsama Daily Shutdownn Today's Progress Generator

// ==UserScript==
// @name         Sunsama Daily Shutdownn Today's Progress Generator
// @namespace    https://www.patabugen.co.uk/
// @version      1.0
// @description  Extract and display today's task progress in Sunsama. Roughly mimicks the pre-AI Daily Shutdown routine.
// @author       Sami Walbury
// @match        https://app.sunsama.com/group/*/shutdownDay/reflect
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
  'use strict';

  function waitForElement(selector, callback) {
    const el = document.querySelector(selector);
    if (el) {
      callback(el);
    }
    else {
      const observer = new MutationObserver(() => {
        const el = document.querySelector(selector);
        if (el) {
          observer.disconnect();
          callback(el);
        }
      });
      observer.observe(document.body, {
        childList: true,
        subtree: true
      });
    }
  }

  function extractTasks() {
    const firstDayContainer = document.querySelector('.kanban-day-tasks-items-container');
    if (!firstDayContainer) return;

    const taskContainers = firstDayContainer.querySelectorAll('.kanban-task-container.kanban-task-container-draggable');
    const groupedTasks = {};

    taskContainers.forEach(task => {
      const titleElement = task.querySelector('.task-item-description');
      const groupElement = task.querySelector('.kanban-task-stream-label');
      if (!titleElement || !groupElement) return;

      const taskTitle = titleElement.textContent.trim();
      const groupTitle = groupElement.textContent.trim();
      const subtaskElements = task.querySelectorAll('.subtask-item-description-container');
      const subtaskTexts = Array.from(subtaskElements).map(s => s.textContent.trim());

      if (!groupedTasks[groupTitle]) {
        groupedTasks[groupTitle] = [];
      }

      groupedTasks[groupTitle].push({
        title: taskTitle,
        subtasks: subtaskTexts
      });
    });

    let output = '<h3>Today\'s Progress:</h3><ul>';

    for (const [group, tasks] of Object.entries(groupedTasks)) {
      output += `<li><strong>${group}</strong><ul>`;

      tasks.forEach(task => {
        output += `<li><strong>${task.title}</strong><ul>`;
        task.subtasks.forEach(sub => {
          output += `<li>${sub}</li>`;
        });
        output += '</ul></li>';
      });

      output += '</ul></li>';
    }

    output += '</ul>';
    displayRichText(output);
  }

  function getInjectedContainer() {
    const groupBodyContainer = document.querySelector('#group-body-container');
    if (!groupBodyContainer) return;

    // Remove an existing container if it exists
    let injectecdContainer = groupBodyContainer.querySelector('#injected-task-summary');
    if (!injectecdContainer) {
      injectecdContainer = document.createElement('div');
      injectecdContainer.className = 'kanban-day-container'
      injectecdContainer.id = 'injected-task-summary';
      injectecdContainer.style.overflow = 'auto';
      injectecdContainer.style.maxWidth = '100%';
      injectecdContainer.style.boxSizing = 'border-box';
      injectecdContainer.style.order = 10; // Put it at the far right of any columns

      let title = document.createElement('div')
      title.className = "kanban-day-label-container"
      title.innerHTML = 'Status Update';
      injectecdContainer.appendChild(title);

      let spacer = document.createElement('div');

      let body = document.createElement('div');
      body.className = 'today-progress-body';
      injectecdContainer.appendChild(body);

    }

    groupBodyContainer.appendChild(injectecdContainer);

    return injectecdContainer.querySelector('.today-progress-body');
  }

  function displayRichText(htmlContent) {
    const richTextEditor = document.createElement('div');
    richTextEditor.contentEditable = 'true';
    richTextEditor.style.width = '100%';
    richTextEditor.style.minHeight = '200px';
    richTextEditor.style.border = '1px solid #ccc';
    richTextEditor.style.padding = '10px';
    richTextEditor.style.backgroundColor = '#fff';
    richTextEditor.style.boxSizing = 'border-box';
    richTextEditor.innerHTML = htmlContent;

    const injectedContainer = getInjectedContainer();
    injectedContainer.replaceChildren(richTextEditor);
  }

  function injectButton() {
    const button = document.createElement('div');
    button.className = 'plan-day-btn';
    button.textContent = "Generate Today's Progress";
    button.style.cursor = 'pointer';
    button.style.padding = '10px';
    button.style.textAlign = 'center';
    button.style.borderRadius = '4px';
    button.style.maxHeight = '40px';
    button.style.overflow = 'hidden';
    button.style.whiteSpace = 'nowrap';
    button.style.textOverflow = 'ellipsis';

    button.addEventListener('click', extractTasks);

    const injectedContainer = getInjectedContainer();
    injectedContainer.replaceChildren(button);
  }

  waitForElement('.kanban-day-container', injectButton);
})();