Repository navigation
Expand file tree
/
Copy pathtaskController.js
More file actions
152 lines (130 loc) · 3.88 KB
/
Copy pathtaskController.js
File metadata and controls
152 lines (130 loc) · 3.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// controllers/taskController.js
const pool = require('../config/db');
// GET all tasks for logged-in user with pagination + metadata + filtering + sorting
const getTasks = async (req, res, next) => {
try {
const userId = req.user.userId;
// Query parameters
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const completed = req.query.completed;
// Sorting parameters
const sort = req.query.sort || 'id';
const order = req.query.order === 'desc' ? 'DESC' : 'ASC';
const offset = (page - 1) * limit;
// Allowed fields for sorting (security)
const allowedSortFields = ['id', 'title', 'completed'];
const sortField = allowedSortFields.includes(sort) ? sort : 'id';
// Build filtering condition
let filterQuery = 'WHERE user_id = $1';
let queryParams = [userId];
if (completed !== undefined) {
filterQuery += ' AND completed = $2';
queryParams.push(completed === 'true');
}
// 1️⃣ Get total number of tasks (with filter applied)
const countQuery = `SELECT COUNT(*) FROM tasks ${filterQuery}`;
const countResult = await pool.query(countQuery, queryParams);
const totalTasks = parseInt(countResult.rows[0].count);
const totalPages = Math.ceil(totalTasks / limit);
// 2️⃣ Add pagination parameters
queryParams.push(limit);
queryParams.push(offset);
// 3️⃣ Fetch tasks with sorting
const result = await pool.query(
`SELECT * FROM tasks
${filterQuery}
ORDER BY ${sortField} ${order}
LIMIT $${queryParams.length - 1}
OFFSET $${queryParams.length}`,
queryParams
);
res.status(200).json({
status: 'success',
page,
limit,
totalTasks,
totalPages,
hasNextPage: page < totalPages,
hasPreviousPage: page > 1,
sort: sortField,
order: order.toLowerCase(),
data: result.rows
});
} catch (err) {
next(err);
}
};
// CREATE task for logged-in user
// Note: title validation is handled by validateMiddleware + createTaskSchema
const createTask = async (req, res, next) => {
try {
const { title } = req.body;
const userId = req.user.userId;
const result = await pool.query(
'INSERT INTO tasks (title, user_id) VALUES ($1, $2) RETURNING *',
[title, userId]
);
res.status(201).json({
status: 'success',
data: result.rows[0]
});
} catch (err) {
next(err);
}
};
// UPDATE task (only if it belongs to logged-in user)
const updateTask = async (req, res, next) => {
try {
const taskId = parseInt(req.params.id);
const { title, completed } = req.body;
const userId = req.user.userId;
const result = await pool.query(
`UPDATE tasks
SET title = COALESCE($1, title),
completed = COALESCE($2, completed)
WHERE id = $3 AND user_id = $4
RETURNING *`,
[title, completed, taskId, userId]
);
if (result.rows.length === 0) {
const error = new Error('Task not found or not authorized');
error.statusCode = 404;
return next(error);
}
res.status(200).json({
status: 'success',
data: result.rows[0]
});
} catch (err) {
next(err);
}
};
// DELETE task (only if it belongs to logged-in user)
const deleteTask = async (req, res, next) => {
try {
const taskId = parseInt(req.params.id);
const userId = req.user.userId;
const result = await pool.query(
'DELETE FROM tasks WHERE id = $1 AND user_id = $2 RETURNING *',
[taskId, userId]
);
if (result.rows.length === 0) {
const error = new Error('Task not found or not authorized');
error.statusCode = 404;
return next(error);
}
res.status(200).json({
status: 'success',
data: result.rows[0]
});
} catch (err) {
next(err);
}
};
module.exports = {
getTasks,
createTask,
updateTask,
deleteTask
};