Color on right - Better Handling

This commit is contained in:
Honey committed 2026-02-17 18:45:16 +01:00
1 parent 83a79dd346
commit 7f5384d0bc
6 files changed
+884 -746

No files matched your search

+28 -58
View File
@@ -7,17 +7,14 @@ const fs = require('fs');
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '../public')));
// Ensure data directory exists
const dataDir = path.join(__dirname, '../data');
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
// Initialize SQLite database
const dbPath = process.env.DATABASE_PATH || path.join(dataDir, 'tasks.db');
const db = new sqlite3.Database(dbPath, (err) => {
if (err) {
@@ -39,6 +36,8 @@ function initDatabase() {
completed INTEGER DEFAULT 0,
archived INTEGER DEFAULT 0,
expand_description INTEGER DEFAULT 0,
due_date TEXT,
color TEXT DEFAULT '#6366f1',
position INTEGER,
subtasks TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
@@ -46,15 +45,13 @@ function initDatabase() {
)
`, (err) => {
if (err) return;
// Migrate: add columns if missing on existing databases
db.run(`ALTER TABLE tasks ADD COLUMN archived INTEGER DEFAULT 0`, () => {});
db.run(`ALTER TABLE tasks ADD COLUMN expand_description INTEGER DEFAULT 0`, () => {});
db.run(`ALTER TABLE tasks ADD COLUMN due_date TEXT`, () => {});
db.run(`ALTER TABLE tasks ADD COLUMN color TEXT DEFAULT '#6366f1'`, () => {});
});
}
// API Routes
// Get tasks — ?archived=1 returns archived, default returns active
app.get('/api/tasks', (req, res) => {
const archived = req.query.archived === '1' ? 1 : 0;
db.all('SELECT * FROM tasks WHERE archived = ? ORDER BY position ASC, created_at ASC', [archived], (err, rows) => {
@@ -62,7 +59,6 @@ app.get('/api/tasks', (req, res) => {
console.error('Error fetching tasks:', err);
return res.status(500).json({ error: 'Failed to fetch tasks' });
}
const tasks = rows.map(row => ({
id: row.id,
title: row.title,
@@ -72,53 +68,45 @@ app.get('/api/tasks', (req, res) => {
completed: row.completed === 1,
archived: row.archived === 1,
expandDescription: row.expand_description === 1,
dueDate: row.due_date || null,
color: row.color || '#6366f1',
subtasks: row.subtasks ? JSON.parse(row.subtasks) : []
}));
res.json(tasks);
});
});
// Create a new task
app.post('/api/tasks', (req, res) => {
const { title, description, size, reward, expandDescription } = req.body;
const { title, description, size, reward, expandDescription, dueDate, color } = req.body;
const id = Date.now().toString();
db.run(
`INSERT INTO tasks (id, title, description, size, reward, expand_description, archived, position)
VALUES (?, ?, ?, ?, ?, ?, 0, (SELECT COALESCE(MAX(position), 0) + 1 FROM tasks WHERE archived = 0))`,
[id, title, description || '', size, reward || '', expandDescription ? 1 : 0],
`INSERT INTO tasks (id, title, description, size, reward, expand_description, due_date, color, archived, position)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, (SELECT COALESCE(MAX(position), 0) + 1 FROM tasks WHERE archived = 0))`,
[id, title, description || '', size, reward || '', expandDescription ? 1 : 0, dueDate || null, color || '#6366f1'],
function(err) {
if (err) {
console.error('Error creating task:', err);
return res.status(500).json({ error: 'Failed to create task' });
}
res.json({
id,
title,
description: description || '',
size,
reward: reward || '',
completed: false,
archived: false,
expandDescription: !!expandDescription,
subtasks: []
id, title, description: description || '', size, reward: reward || '',
completed: false, archived: false, expandDescription: !!expandDescription,
dueDate: dueDate || null, color: color || '#6366f1', subtasks: []
});
}
);
});
// Update a task
app.put('/api/tasks/:id', (req, res) => {
const { id } = req.params;
const { title, description, size, reward, completed, expandDescription, subtasks } = req.body;
const { title, description, size, reward, completed, expandDescription, dueDate, color, subtasks } = req.body;
db.run(
`UPDATE tasks
SET title = ?, description = ?, size = ?, reward = ?, completed = ?, expand_description = ?, subtasks = ?, updated_at = CURRENT_TIMESTAMP
SET title = ?, description = ?, size = ?, reward = ?, completed = ?, expand_description = ?, due_date = ?, color = ?, subtasks = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?`,
[title, description || '', size, reward || '', completed ? 1 : 0, expandDescription ? 1 : 0, JSON.stringify(subtasks || []), id],
[title, description || '', size, reward || '', completed ? 1 : 0, expandDescription ? 1 : 0, dueDate || null, color || '#6366f1', JSON.stringify(subtasks || []), id],
function(err) {
if (err) {
console.error('Error updating task:', err);
@@ -130,27 +118,20 @@ app.put('/api/tasks/:id', (req, res) => {
);
});
// Archive a task
app.put('/api/tasks/:id/archive', (req, res) => {
const { id } = req.params;
db.run(
`UPDATE tasks SET archived = 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?`,
[id],
function(err) {
if (err) return res.status(500).json({ error: 'Failed to archive task' });
if (this.changes === 0) return res.status(404).json({ error: 'Task not found' });
res.json({ success: true });
}
);
db.run(`UPDATE tasks SET archived = 1, updated_at = CURRENT_TIMESTAMP WHERE id = ?`, [id], function(err) {
if (err) return res.status(500).json({ error: 'Failed to archive task' });
if (this.changes === 0) return res.status(404).json({ error: 'Task not found' });
res.json({ success: true });
});
});
// Unarchive (restore) a task
app.put('/api/tasks/:id/unarchive', (req, res) => {
const { id } = req.params;
db.run(
`UPDATE tasks SET archived = 0, position = (SELECT COALESCE(MAX(position), 0) + 1 FROM tasks WHERE archived = 0), updated_at = CURRENT_TIMESTAMP WHERE id = ?`,
[id],
function(err) {
[id], function(err) {
if (err) return res.status(500).json({ error: 'Failed to unarchive task' });
if (this.changes === 0) return res.status(404).json({ error: 'Task not found' });
res.json({ success: true });
@@ -158,7 +139,6 @@ app.put('/api/tasks/:id/unarchive', (req, res) => {
);
});
// Delete a task
app.delete('/api/tasks/:id', (req, res) => {
const { id } = req.params;
db.run('DELETE FROM tasks WHERE id = ?', [id], function(err) {
@@ -168,29 +148,19 @@ app.delete('/api/tasks/:id', (req, res) => {
});
});
// Reorder tasks
app.post('/api/tasks/reorder', (req, res) => {
const taskIds = req.body;
if (!Array.isArray(taskIds)) return res.status(400).json({ error: 'Invalid task order data' });
const promises = taskIds.map((id, index) => {
return new Promise((resolve, reject) => {
db.run('UPDATE tasks SET position = ? WHERE id = ?', [index, id], (err) => {
if (err) reject(err);
else resolve();
});
});
});
const promises = taskIds.map((id, index) =>
new Promise((resolve, reject) => {
db.run('UPDATE tasks SET position = ? WHERE id = ?', [index, id], (err) => err ? reject(err) : resolve());
})
);
Promise.all(promises)
.then(() => res.json({ success: true }))
.catch(err => {
console.error('Error reordering tasks:', err);
res.status(500).json({ error: 'Failed to reorder tasks' });
});
.catch(err => { console.error('Error reordering tasks:', err); res.status(500).json({ error: 'Failed to reorder tasks' }); });
});
// Serve the main HTML file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../public/index.html'));
});