diff --git a/index.html b/index.html
index d3dd4bc..a0f0be3 100644
--- a/index.html
+++ b/index.html
@@ -462,7 +462,22 @@
-
+
+
+
+
+ | Status |
+ Prioriteetti |
+ Tehtävä |
+ Vastuuhenkilö |
+ Deadline |
+ Tunnit |
+ 💬 |
+
+
+
+
+
Ei tehtäviä.
@@ -585,7 +600,20 @@
-
+
+
+
+
+ | Status |
+ Ehdotus |
+ Ehdottaja |
+ Päivämäärä |
+ 💬 |
+
+
+
+
+
Ei kehitysehdotuksia.
diff --git a/script.js b/script.js
index 4255524..d0a1b94 100644
--- a/script.js
+++ b/script.js
@@ -3943,28 +3943,45 @@ function renderTasksList() {
if (query) tasks = tasks.filter(t => (t.title||'').toLowerCase().includes(query) || (t.description||'').toLowerCase().includes(query) || (t.assigned_to||'').toLowerCase().includes(query));
if (statusF) tasks = tasks.filter(t => t.status === statusF);
if (assignF) tasks = tasks.filter(t => t.assigned_to === assignF);
- const grid = document.getElementById('tasks-grid');
- const noEl = document.getElementById('no-tasks');
- if (!grid) return;
- if (!tasks.length) { grid.innerHTML = ''; if (noEl) noEl.style.display = ''; return; }
- if (noEl) noEl.style.display = 'none';
+
+ // Lajittelu: deadline lähimmät ensin (null-deadlinet loppuun), sitten prioriteetti
const today = new Date().toISOString().slice(0,10);
- grid.innerHTML = tasks.map(t => {
+ const prioOrder = { kiireellinen: 0, tarkea: 1, normaali: 2 };
+ const statusOrder = { avoin: 0, kaynnissa: 1, odottaa: 2, valmis: 3 };
+ tasks.sort((a, b) => {
+ // Valmiit aina loppuun
+ if ((a.status === 'valmis') !== (b.status === 'valmis')) return a.status === 'valmis' ? 1 : -1;
+ // Deadline: lähimmät ensin, null loppuun
+ const da = a.deadline || '9999-99-99';
+ const db = b.deadline || '9999-99-99';
+ if (da !== db) return da.localeCompare(db);
+ // Prioriteetti
+ const pa = prioOrder[a.priority] ?? 2;
+ const pb = prioOrder[b.priority] ?? 2;
+ if (pa !== pb) return pa - pb;
+ return 0;
+ });
+
+ const tbody = document.getElementById('tasks-tbody');
+ const table = document.getElementById('tasks-table');
+ const noEl = document.getElementById('no-tasks');
+ if (!tbody) return;
+ if (!tasks.length) { tbody.innerHTML = ''; table.style.display = 'none'; if (noEl) noEl.style.display = ''; return; }
+ if (noEl) noEl.style.display = 'none';
+ table.style.display = 'table';
+ tbody.innerHTML = tasks.map(t => {
const overdue = t.deadline && t.status !== 'valmis' && t.deadline < today;
const soon = t.deadline && t.status !== 'valmis' && !overdue && t.deadline <= new Date(Date.now()+3*86400000).toISOString().slice(0,10);
- return `
-
- ${todoPriorityLabels[t.priority]||t.priority}
- ${todoStatusLabels[t.status]||t.status}
-
-
${esc(t.title)}
-
- ${t.assigned_to ? `👤 ${esc(t.assigned_to)}` : ''}
- ${t.deadline ? `📅 ${t.deadline}` : ''}
- ${t.total_hours > 0 ? `⏱ ${t.total_hours}h` : ''}
- ${t.comment_count > 0 ? `💬 ${t.comment_count}` : ''}
-
-
`;
+ const rowClass = overdue ? 'todo-row-overdue' : (soon ? 'todo-row-soon' : (t.status === 'valmis' ? 'todo-row-done' : ''));
+ return `
+ | ${todoStatusLabels[t.status]||t.status} |
+ ${todoPriorityLabels[t.priority]||t.priority} |
+ ${esc(t.title)} |
+ ${t.assigned_to ? esc(t.assigned_to) : '—'} |
+ ${t.deadline ? `${t.deadline}` : '—'} |
+ ${t.total_hours > 0 ? t.total_hours + 'h' : '—'} |
+ ${t.comment_count > 0 ? t.comment_count : ''} |
+
`;
}).join('');
}
@@ -4093,20 +4110,33 @@ function renderFeaturesList() {
let features = todosData.filter(t => t.type === 'feature_request');
if (query) features = features.filter(t => (t.title||'').toLowerCase().includes(query) || (t.description||'').toLowerCase().includes(query));
if (statusF) features = features.filter(t => t.status === statusF);
- const grid = document.getElementById('features-grid');
+
+ // Lajittelu: uusimmat ensin, toteutetut/hylätyt loppuun
+ features.sort((a, b) => {
+ const doneA = (a.status === 'toteutettu' || a.status === 'hylatty') ? 1 : 0;
+ const doneB = (b.status === 'toteutettu' || b.status === 'hylatty') ? 1 : 0;
+ if (doneA !== doneB) return doneA - doneB;
+ return (b.luotu || '').localeCompare(a.luotu || '');
+ });
+
+ const tbody = document.getElementById('features-tbody');
+ const table = document.getElementById('features-table');
const noEl = document.getElementById('no-features');
- if (!grid) return;
- if (!features.length) { grid.innerHTML = ''; if (noEl) noEl.style.display = ''; return; }
+ if (!tbody) return;
+ if (!features.length) { tbody.innerHTML = ''; table.style.display = 'none'; if (noEl) noEl.style.display = ''; return; }
if (noEl) noEl.style.display = 'none';
- grid.innerHTML = features.map(t => `
-
${todoStatusLabels[t.status]||t.status}
-
${esc(t.title)}
-
- 👤 ${esc(t.created_by)}
- ${(t.luotu||'').slice(0,10)}
- ${t.comment_count > 0 ? `💬 ${t.comment_count}` : ''}
-
-
`).join('');
+ table.style.display = 'table';
+ tbody.innerHTML = features.map(t => {
+ const done = t.status === 'toteutettu' || t.status === 'hylatty';
+ const rowClass = done ? 'todo-row-done' : '';
+ return `
+ | ${todoStatusLabels[t.status]||t.status} |
+ ${esc(t.title)} |
+ ${esc(t.created_by)} |
+ ${(t.luotu||'').slice(0,10)} |
+ ${t.comment_count > 0 ? t.comment_count : ''} |
+
`;
+ }).join('');
}
function showFeatureListView() {
diff --git a/style.css b/style.css
index 8a7eb42..d3897d3 100644
--- a/style.css
+++ b/style.css
@@ -1129,6 +1129,12 @@ span.empty {
.todo-card:hover { transform:translateY(-2px); box-shadow:0 4px 12px rgba(0,0,0,0.1); border-color:var(--primary-color); }
.todo-card.overdue { border-color:#e74c3c; }
.todo-card.deadline-soon { border-color:#f39c12; }
+.todo-row-overdue { background:#fef2f2 !important; }
+.todo-row-overdue:hover { background:#fde8e8 !important; }
+.todo-row-soon { background:#fffbeb !important; }
+.todo-row-soon:hover { background:#fef3c7 !important; }
+.todo-row-done { opacity:0.55; }
+.todo-row-done:hover { opacity:0.75; }
.priority-badge { display:inline-block; padding:2px 8px; border-radius:10px; font-size:0.72rem; font-weight:600; }
.priority-normaali { background:#e8ebf0; color:#555; }
.priority-tarkea { background:#fff3cd; color:#856404; }