Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/JS_Template.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/jsLibraryMappings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 0 additions & 13 deletions index.html

This file was deleted.

64 changes: 64 additions & 0 deletions src/analytics.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html lang="uk">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Task Analytics</title>
<!-- Підключення основних стилів додатку -->
<link rel="stylesheet" href="style.css" />
<!-- Підключення CSS бібліотеки WebDataRocks для створення pivot таблиць -->
<!-- Ця бібліотека надає готові стилі для інтерактивних таблиць аналітики -->
<link href="https://cdn.webdatarocks.com/latest/webdatarocks.min.css" rel="stylesheet"/>
</head>
<body>
<!-- Основний контейнер сторінки, що забезпечує правильну структуру layout -->
<div class="container">
<!-- Фіксований заголовок, який залишається на місці при прокрутці -->
<div class="fixed-header">
<!-- Заголовок сторінки з емодзі для візуальної привабливості -->
<h1>📊 Task Analytics</h1>

<!-- Секція навігації для переходу між сторінками -->
<div class="navigation">
<!-- Кнопка повернення до головної сторінки зі списком завдань -->
<!-- Стрілка ← вказує напрямок навігації назад -->
<a href="index.html" class="stats-back-btn">← Back to Tasks</a>
</div>

<!-- Панель статистики, яка буде заповнена JavaScript -->
<!-- id="stats-bar" використовується для динамічного наповнення контенту -->
<div class="stats-bar" id="stats-bar">
<!-- Тут JavaScript згенерує картки зі статистичними показниками:
- Загальна кількість завдань
- Кількість виконаних завдань
- Кількість невиконаних завдань
- Відсоток прогресу
- Кількість завдань з високим пріоритетом -->
</div>
</div>

<!-- Обгортка для pivot таблиці з відступами та стилізацією -->
<div class="pivot-wrapper">
<!-- Контейнер для WebDataRocks pivot таблиці -->
<!-- Цей div буде замінений на інтерактивну таблицю бібліотекою WebDataRocks -->
<div id="pivot-container">
<!-- Тут JavaScript створить детальну аналітичну таблицю
з можливістю групування, фільтрування та аналізу завдань -->
</div>
</div>
</div>

<!-- Підключення JavaScript бібліотек WebDataRocks -->
<!-- Ці скрипти завантажуються з CDN для забезпечення актуальної версії -->

<!-- WebDataRocks Toolbar - надає панель інструментів для роботи з таблицею -->
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.toolbar.min.js"></script>

<!-- Основна бібліотека WebDataRocks для створення pivot таблиць -->
<script src="https://cdn.webdatarocks.com/latest/webdatarocks.js"></script>

<!-- Підключення нашого основного JavaScript файлу -->
<!-- Цей файл містить всю логіку роботи з завданнями та генерації аналітики -->
<script src="analytics.js"></script>
</body>
</html>
156 changes: 156 additions & 0 deletions src/analytics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/**
* Ініціалізація статистичної панелі та pivot таблиці після завантаження DOM
*/
document.addEventListener('DOMContentLoaded', () => {
// Завантажуємо завдання з localStorage з fallback на порожній масив
const tasks = JSON.parse(localStorage.getItem('tasks')) || [];

// Розраховуємо ключові метрики для швидкого огляду продуктивності користувача

const totalTasks = tasks.length; // Загальна кількість завдань

// filter() створює новий масив з елементів що відповідають умові
// Більш читабельно ніж циклі for або reduce для простого підрахунку
const completedTasks = tasks.filter(t => t.completed).length;

// Обчислюємо кількість незавершених завдань через віднімання
const pendingTasks = totalTasks - completedTasks;

// Розраховуємо відсоток завершення з округленням до цілого числа
// Перевіряємо на ділення на нуль для уникнення NaN
const completionRate = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;

// Підраховуємо завдання з високим пріоритетом для виділення критичних задач
const highPriorityTasks = tasks.filter(t => t.priority === 'high').length;

// ===== ВІДОБРАЖЕННЯ СТАТИСТИЧНИХ КАРТОК =====
// Використовуємо innerHTML для швидкого створення статичного контенту
// Template literals забезпечують чисту інтерполяцию змінних
document.getElementById('stats-bar').innerHTML = `
<div class="stat-card">
<div class="stat-number">${totalTasks}</div>
<div class="stat-label">Total Tasks</div>
</div>
<div class="stat-card">
<div class="stat-number">${completedTasks}</div>
<div class="stat-label">Completed</div>
</div>
<div class="stat-card">
<div class="stat-number">${pendingTasks}</div>
<div class="stat-label">Pending</div>
</div>
<div class="stat-card">
<div class="stat-number">${completionRate}%</div>
<div class="stat-label">Progress</div>
</div>
<div class="stat-card">
<div class="stat-number">${highPriorityTasks}</div>
<div class="stat-label">High Priority</div>
</div>
`;

// Трансформуємо сирі дані завдань у структуру придатну для аналітики
// map() створює новий масив з трансформованими об'єктами
const reportData = tasks.map(task => {
// Створюємо об'єкт Date для роботи з датою завдання
const dateObj = new Date(task.date);

// Витягуємо компоненти дати для різних рівнів групування
const year = dateObj.getFullYear();
const month = dateObj.getMonth() + 1; // +1 оскільки getMonth() повертає 0-11
const day = dateObj.getDate();

// Отримуємо назви днів тижня та місяців для кращої читабельності
const dayName = dateObj.toLocaleDateString('en-US', { weekday: 'short' });
const monthName = dateObj.toLocaleDateString('en-US', { month: 'long' });

// Мапінг пріоритетів для відображення з великої літери
const priorityMap = { 'high': 'High', 'medium': 'Medium', 'low': 'Low' };

// Повертаємо структуровані дані для pivot таблиці
// Кожне поле стане доступним для групування та аналізу
return {
'Month': `${monthName} ${year}`, // Комбінована мітка для місячного групування
'Day': `${day} (${dayName})`, // День з назвою дня тижня для контексту
'Task': task.title, // Назва завдання для деталізації
'Priority': priorityMap[task.priority], // Пріоритет з правильним форматуванням
'Status': task.completed ? 'Completed' : 'Pending', // Статус у зрозумілому форматі
'Count': 1 // Лічильник для агрегації (кожне завдання = 1 одиниця)
};
});

// WebDataRocks - стороння бібліотека для створення інтерактивних pivot таблиць
const pivot = new WebDataRocks({
container: '#pivot-container', // CSS селектор контейнера
toolbar: true, // Показуємо панель інструментів для користувача
height: 500, // Фіксована висота для консистентного вигляду

report: {
// Джерело даних - наш трансформований масив
dataSource: { data: reportData },

// Конфігурація структури pivot таблиці
slice: {
// Рядки - ієрархічне групування даних
// collapsed: false/true контролює початковий стан розгортання
rows: [
{ uniqueName: 'Month', collapsed: false }, // Місяці розгорнуті за замовчанням
{ uniqueName: 'Day', collapsed: true }, // Дні згорнуті для компактності
{ uniqueName: 'Task', collapsed: true }, // Індивідуальні завдання згорнуті
{ uniqueName: 'Priority', collapsed: true } // Пріоритети згорнуті
],

// Стовпці - горизонтальне групування
columns: [
{ uniqueName: 'Status' } // Розділення на Completed/Pending
],

// Метрики - що рахуємо та як відображаємо
measures: [
{
uniqueName: 'Count',
aggregation: 'sum', // Сумуємо значення Count (кількість завдань)
format: 'count' // Використовуємо кастомний формат для відображення
}
]
},

// Налаштування форматування чисел
formats: [
{
name: 'count',
decimalPlaces: 0, // Цілі числа без десяткових знаків
thousandsSeparator: '', // Без розділювача тисяч для простоти
currencySymbol: '' // Без валютних символів
}
],

// Додаткові опції відображення
options: {
grid: {
type: 'classic', // Класичний вигляд таблиці
showTotals: 'off', // Вимикаємо проміжні підсумки для чистоти
showGrandTotals: 'off', // Вимикаємо загальні підсумки
dragging: true, // Дозволяємо перетягування полів для реорганізації
showEmptyData: false // Приховуємо порожні комірки
}
},

// Локалізація текстових міток
localization: {
grid: {
blankMember: '(Empty)', // Мітка для порожніх значень
total: 'Total', // Мітка для підсумків
grandTotal: 'Grand Total' // Мітка для загальних підсумків
},
toolbar: {
connect: 'Connect', // Кнопка підключення до джерел даних
clear: 'Clear', // Кнопка очищення
format: 'Format', // Кнопка форматування
export: 'Export', // Кнопка експорту
settings: 'Settings' // Кнопка налаштувань
}
}
}
});
});
Loading