feat: rediseño de TaskItem, añade completar y lista 24h
Co-authored-by: aider (openrouter/openai/gpt-5) <aider@aider.chat>webui
parent
2446427b5f
commit
06c4a0619d
@ -0,0 +1,102 @@
|
||||
import type { RequestHandler } from './$types';
|
||||
import { getDb } from '$lib/server/db';
|
||||
|
||||
export const POST: RequestHandler = async (event) => {
|
||||
const userId = event.locals.userId ?? null;
|
||||
if (!userId) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
const idStr = event.params.id || '';
|
||||
const taskId = parseInt(idStr, 10);
|
||||
if (!Number.isFinite(taskId) || taskId <= 0) {
|
||||
return new Response('Bad Request', { status: 400 });
|
||||
}
|
||||
|
||||
const db = await getDb();
|
||||
|
||||
const task = db.prepare(`
|
||||
SELECT id, description, due_date, group_id, COALESCE(completed, 0) AS completed, completed_at, display_code
|
||||
FROM tasks
|
||||
WHERE id = ?
|
||||
`).get(taskId) as any;
|
||||
|
||||
if (!task) {
|
||||
return new Response(JSON.stringify({ status: 'not_found' }), {
|
||||
status: 404,
|
||||
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
|
||||
});
|
||||
}
|
||||
|
||||
// Gating:
|
||||
// - Si tiene group_id: grupo allowed y miembro activo
|
||||
// - Si NO tiene group_id: debe estar asignada al usuario
|
||||
const groupId: string | null = task.group_id ? String(task.group_id) : null;
|
||||
if (groupId) {
|
||||
const allowed = db
|
||||
.prepare(`SELECT 1 FROM allowed_groups WHERE group_id = ? AND status = 'allowed' LIMIT 1`)
|
||||
.get(groupId);
|
||||
const active = db
|
||||
.prepare(`SELECT 1 FROM group_members WHERE group_id = ? AND user_id = ? AND is_active = 1 LIMIT 1`)
|
||||
.get(groupId, userId);
|
||||
if (!allowed || !active) {
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
} else {
|
||||
const isAssigned = db
|
||||
.prepare(`SELECT 1 FROM task_assignments WHERE task_id = ? AND user_id = ? LIMIT 1`)
|
||||
.get(taskId, userId);
|
||||
if (!isAssigned) {
|
||||
return new Response('Forbidden', { status: 403 });
|
||||
}
|
||||
}
|
||||
|
||||
if (Number(task.completed) !== 0 || task.completed_at) {
|
||||
const body = {
|
||||
status: 'already',
|
||||
task: {
|
||||
id: Number(task.id),
|
||||
description: String(task.description || ''),
|
||||
due_date: task.due_date ? String(task.due_date) : null,
|
||||
display_code: task.display_code != null ? Number(task.display_code) : null,
|
||||
completed: 1,
|
||||
completed_at: task.completed_at ? String(task.completed_at) : null
|
||||
}
|
||||
};
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
|
||||
});
|
||||
}
|
||||
|
||||
db.prepare(`
|
||||
UPDATE tasks
|
||||
SET completed = 1,
|
||||
completed_at = strftime('%Y-%m-%d %H:%M:%f', 'now'),
|
||||
completed_by = ?
|
||||
WHERE id = ?
|
||||
`).run(userId, taskId);
|
||||
|
||||
const updated = db.prepare(`
|
||||
SELECT id, description, due_date, display_code, COALESCE(completed, 0) AS completed, completed_at
|
||||
FROM tasks
|
||||
WHERE id = ?
|
||||
`).get(taskId) as any;
|
||||
|
||||
const body = {
|
||||
status: 'updated',
|
||||
task: {
|
||||
id: Number(updated.id),
|
||||
description: String(updated.description || ''),
|
||||
due_date: updated.due_date ? String(updated.due_date) : null,
|
||||
display_code: updated.display_code != null ? Number(updated.display_code) : null,
|
||||
completed: Number(updated.completed || 0),
|
||||
completed_at: updated.completed_at ? String(updated.completed_at) : null
|
||||
}
|
||||
};
|
||||
|
||||
return new Response(JSON.stringify(body), {
|
||||
status: 200,
|
||||
headers: { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' }
|
||||
});
|
||||
};
|
||||
Loading…
Reference in New Issue