@feardread/fear 2.0.1 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/controllers/crud/crud.js +265 -175
- package/controllers/review.js +7 -6
- package/models/review.js +5 -2
- package/package.json +1 -1
- package/routes/review.js +2 -2
package/controllers/crud/crud.js
CHANGED
|
@@ -12,6 +12,41 @@ const isValidObjectId = (id) => {
|
|
|
12
12
|
return mongoose.Types.ObjectId.isValid(id) && /^[0-9a-fA-F]{24}$/.test(id);
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Sanitizes update data by removing undefined values
|
|
17
|
+
* @param {Object} data - Data object to sanitize
|
|
18
|
+
* @returns {Object} Sanitized data object
|
|
19
|
+
*/
|
|
20
|
+
const sanitizeUpdateData = (data) => {
|
|
21
|
+
const sanitized = { ...data };
|
|
22
|
+
Object.keys(sanitized).forEach(key => {
|
|
23
|
+
if (sanitized[key] === undefined) {
|
|
24
|
+
delete sanitized[key];
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return sanitized;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Processes image data for upload
|
|
32
|
+
* @param {string|Array} images - Images to process
|
|
33
|
+
* @returns {Promise<Array>} Promise resolving to uploaded image URLs
|
|
34
|
+
*/
|
|
35
|
+
const processImages = (images) => {
|
|
36
|
+
if (!images) return Promise.resolve(null);
|
|
37
|
+
|
|
38
|
+
const imageArray = Array.isArray(images)
|
|
39
|
+
? images
|
|
40
|
+
: images.split(',').map(item => item.trim());
|
|
41
|
+
|
|
42
|
+
return cloud.uploadImages(imageArray)
|
|
43
|
+
.then(imageLinks => imageLinks || null)
|
|
44
|
+
.catch(error => {
|
|
45
|
+
console.error('Error uploading images:', error);
|
|
46
|
+
return null;
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
|
|
15
50
|
/**
|
|
16
51
|
* Get all documents for requested Model
|
|
17
52
|
* @param {mongoose.Model} Model - Mongoose model
|
|
@@ -19,34 +54,27 @@ const isValidObjectId = (id) => {
|
|
|
19
54
|
* @param {Object} res - Express response object
|
|
20
55
|
* @returns {Promise<void>}
|
|
21
56
|
*/
|
|
22
|
-
exports.all = tryCatch(
|
|
57
|
+
exports.all = tryCatch((Model, req, res) => {
|
|
23
58
|
const { sort = 'category', order = 'asc', populate = 'true' } = req.query;
|
|
24
|
-
|
|
25
59
|
const sortOrder = order === 'desc' ? -1 : 1;
|
|
60
|
+
|
|
26
61
|
let query = Model.find().sort({ [sort]: sortOrder });
|
|
27
62
|
|
|
28
|
-
|
|
29
|
-
if (populate !== 'false') {
|
|
30
|
-
query = query.populate();
|
|
31
|
-
}
|
|
63
|
+
if (populate !== 'false') query = query.populate();
|
|
32
64
|
|
|
33
|
-
|
|
65
|
+
return query
|
|
66
|
+
.exec()
|
|
67
|
+
.then(result => {
|
|
68
|
+
if (!result || result.length === 0) {
|
|
69
|
+
return res.status(200).json({result: [],success: true,message: "No documents found",count: 0});
|
|
70
|
+
}
|
|
34
71
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
count: 0
|
|
72
|
+
return res.status(200).json({result,success: true,message: `Found ${result.length} documents`,count: result.length});
|
|
73
|
+
})
|
|
74
|
+
.catch(error => {
|
|
75
|
+
console.error('Error fetching documents:', error);
|
|
76
|
+
return res.status(500).json({result: null,success: false});
|
|
41
77
|
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return res.status(200).json({
|
|
45
|
-
result,
|
|
46
|
-
success: true,
|
|
47
|
-
message: `Found ${result.length} documents`,
|
|
48
|
-
count: result.length
|
|
49
|
-
});
|
|
50
78
|
});
|
|
51
79
|
|
|
52
80
|
/**
|
|
@@ -56,31 +84,43 @@ exports.all = tryCatch(async (Model, req, res) => {
|
|
|
56
84
|
* @param {Object} res - Express response object
|
|
57
85
|
* @returns {Promise<void>}
|
|
58
86
|
*/
|
|
59
|
-
exports.read = tryCatch(
|
|
87
|
+
exports.read = tryCatch((Model, req, res) => {
|
|
60
88
|
const { id } = req.params;
|
|
61
89
|
|
|
62
90
|
if (!id || !isValidObjectId(id)) {
|
|
63
|
-
return
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
91
|
+
return Promise.resolve(
|
|
92
|
+
res.status(400).json({
|
|
93
|
+
result: null,
|
|
94
|
+
success: false,
|
|
95
|
+
message: "Invalid or missing document ID"
|
|
96
|
+
})
|
|
97
|
+
);
|
|
68
98
|
}
|
|
69
|
-
const result = await Model.findById(id).exec();
|
|
70
99
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
result
|
|
74
|
-
|
|
75
|
-
|
|
100
|
+
return Model.findById(id).exec()
|
|
101
|
+
.then(result => {
|
|
102
|
+
if (!result) {
|
|
103
|
+
return res.status(404).json({
|
|
104
|
+
result: null,
|
|
105
|
+
success: false,
|
|
106
|
+
message: `Document with ID ${id} not found`
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return res.status(200).json({
|
|
111
|
+
result,
|
|
112
|
+
success: true,
|
|
113
|
+
message: "Document found successfully"
|
|
114
|
+
});
|
|
115
|
+
})
|
|
116
|
+
.catch(error => {
|
|
117
|
+
console.error('Error reading document:', error);
|
|
118
|
+
return res.status(500).json({
|
|
119
|
+
result: null,
|
|
120
|
+
success: false,
|
|
121
|
+
message: "Error reading document"
|
|
122
|
+
});
|
|
76
123
|
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return res.status(200).json({
|
|
80
|
-
result,
|
|
81
|
-
success: true,
|
|
82
|
-
message: "Document found successfully"
|
|
83
|
-
});
|
|
84
124
|
});
|
|
85
125
|
|
|
86
126
|
/**
|
|
@@ -90,27 +130,36 @@ exports.read = tryCatch(async (Model, req, res) => {
|
|
|
90
130
|
* @param {Object} res - Express response object
|
|
91
131
|
* @returns {Promise<void>}
|
|
92
132
|
*/
|
|
93
|
-
exports.create = tryCatch(
|
|
133
|
+
exports.create = tryCatch((Model, req, res) => {
|
|
94
134
|
const documentData = { ...req.body };
|
|
95
|
-
// Handle image uploads if present
|
|
96
|
-
if (documentData.images) {
|
|
97
|
-
|
|
98
|
-
documentData.images.split(',').map(item => item.trim());
|
|
99
|
-
|
|
100
|
-
const imageLinks = await cloud.uploadImages(documentData.images);
|
|
101
|
-
|
|
102
|
-
if ( imageLinks ) documentData.images = imageLinks;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
console.log('Creating document:', documentData);
|
|
106
135
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
136
|
+
return processImages(documentData.images)
|
|
137
|
+
.then(imageLinks => {
|
|
138
|
+
if (imageLinks) {
|
|
139
|
+
documentData.images = imageLinks;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log('Creating document:', documentData);
|
|
143
|
+
const document = new Model(documentData);
|
|
144
|
+
|
|
145
|
+
return document.save();
|
|
146
|
+
})
|
|
147
|
+
.then(result => {
|
|
148
|
+
return res.status(201).json({
|
|
149
|
+
result,
|
|
150
|
+
success: true,
|
|
151
|
+
message: `Document created successfully in ${Model.modelName} collection`
|
|
152
|
+
});
|
|
153
|
+
})
|
|
154
|
+
.catch(error => {
|
|
155
|
+
console.error('Error creating document:', error);
|
|
156
|
+
return res.status(500).json({
|
|
157
|
+
result: null,
|
|
158
|
+
success: false,
|
|
159
|
+
message: "Error creating document",
|
|
160
|
+
error: error.message
|
|
161
|
+
});
|
|
162
|
+
});
|
|
114
163
|
});
|
|
115
164
|
|
|
116
165
|
/**
|
|
@@ -120,60 +169,71 @@ exports.create = tryCatch(async (Model, req, res) => {
|
|
|
120
169
|
* @param {Object} res - Express response object
|
|
121
170
|
* @returns {Promise<void>}
|
|
122
171
|
*/
|
|
123
|
-
exports.update = tryCatch(
|
|
172
|
+
exports.update = tryCatch((Model, req, res) => {
|
|
124
173
|
const { id } = req.params;
|
|
125
174
|
|
|
126
175
|
if (!id) {
|
|
127
|
-
return
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
176
|
+
return Promise.resolve(
|
|
177
|
+
res.status(400).json({
|
|
178
|
+
result: null,
|
|
179
|
+
success: false,
|
|
180
|
+
message: "Document ID is required"
|
|
181
|
+
})
|
|
182
|
+
);
|
|
132
183
|
}
|
|
133
184
|
|
|
134
185
|
if (!isValidObjectId(id)) {
|
|
135
|
-
return
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const updateData = { ...req.body };
|
|
143
|
-
|
|
144
|
-
// Remove undefined values
|
|
145
|
-
Object.keys(updateData).forEach(key => {
|
|
146
|
-
if (updateData[key] === undefined) {
|
|
147
|
-
delete updateData[key];
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
// Handle image uploads if present
|
|
152
|
-
if (updateData.images && Array.isArray(updateData.images) && updateData.images.length > 0) {
|
|
153
|
-
const uploadedImages = await cloud.uploadImages(updateData.images);
|
|
154
|
-
updateData.images = uploadedImages;
|
|
186
|
+
return Promise.resolve(
|
|
187
|
+
res.status(400).json({
|
|
188
|
+
result: null,
|
|
189
|
+
success: false,
|
|
190
|
+
message: "Invalid document ID format"
|
|
191
|
+
})
|
|
192
|
+
);
|
|
155
193
|
}
|
|
156
194
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
updateData
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
195
|
+
const updateData = sanitizeUpdateData(req.body);
|
|
196
|
+
|
|
197
|
+
const imagePromise = (updateData.images && Array.isArray(updateData.images) && updateData.images.length > 0)
|
|
198
|
+
? processImages(updateData.images)
|
|
199
|
+
: Promise.resolve(null);
|
|
200
|
+
|
|
201
|
+
return imagePromise
|
|
202
|
+
.then(uploadedImages => {
|
|
203
|
+
if (uploadedImages) {
|
|
204
|
+
updateData.images = uploadedImages;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return Model.findByIdAndUpdate(
|
|
208
|
+
id,
|
|
209
|
+
updateData,
|
|
210
|
+
{ new: true, runValidators: true }
|
|
211
|
+
).exec();
|
|
212
|
+
})
|
|
213
|
+
.then(result => {
|
|
214
|
+
if (!result) {
|
|
215
|
+
return res.status(404).json({
|
|
216
|
+
result: null,
|
|
217
|
+
success: false,
|
|
218
|
+
message: `Document with ID ${id} not found`
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
return res.status(200).json({
|
|
223
|
+
result,
|
|
224
|
+
success: true,
|
|
225
|
+
message: `Document updated successfully with ID: ${id}`
|
|
226
|
+
});
|
|
227
|
+
})
|
|
228
|
+
.catch(error => {
|
|
229
|
+
console.error('Error updating document:', error);
|
|
230
|
+
return res.status(500).json({
|
|
231
|
+
result: null,
|
|
232
|
+
success: false,
|
|
233
|
+
message: "Error updating document",
|
|
234
|
+
error: error.message
|
|
235
|
+
});
|
|
169
236
|
});
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
return res.status(200).json({
|
|
173
|
-
result,
|
|
174
|
-
success: true,
|
|
175
|
-
message: `Document updated successfully with ID: ${id}`
|
|
176
|
-
});
|
|
177
237
|
});
|
|
178
238
|
|
|
179
239
|
/**
|
|
@@ -183,47 +243,60 @@ exports.update = tryCatch(async (Model, req, res) => {
|
|
|
183
243
|
* @param {Object} res - Express response object
|
|
184
244
|
* @returns {Promise<void>}
|
|
185
245
|
*/
|
|
186
|
-
exports.delete = tryCatch(
|
|
246
|
+
exports.delete = tryCatch((Model, req, res) => {
|
|
187
247
|
const { id } = req.params;
|
|
188
248
|
|
|
189
249
|
if (!id) {
|
|
190
|
-
return
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
250
|
+
return Promise.resolve(
|
|
251
|
+
res.status(400).json({
|
|
252
|
+
result: null,
|
|
253
|
+
success: false,
|
|
254
|
+
message: "Document ID is required"
|
|
255
|
+
})
|
|
256
|
+
);
|
|
195
257
|
}
|
|
196
258
|
|
|
197
259
|
if (!isValidObjectId(id)) {
|
|
198
|
-
return
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
260
|
+
return Promise.resolve(
|
|
261
|
+
res.status(400).json({
|
|
262
|
+
result: null,
|
|
263
|
+
success: false,
|
|
264
|
+
message: "Invalid document ID format"
|
|
265
|
+
})
|
|
266
|
+
);
|
|
203
267
|
}
|
|
204
268
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
269
|
+
return Model.findByIdAndDelete(id)
|
|
270
|
+
.exec()
|
|
271
|
+
.then(result => {
|
|
272
|
+
if (!result) {
|
|
273
|
+
return res.status(404).json({ result: null, success: false });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Clean up associated images if they exist
|
|
277
|
+
if (result.images && Array.isArray(result.images) && result.images.length > 0) {
|
|
278
|
+
console.log('Document had images that should be cleaned up:', result.images);
|
|
279
|
+
// Uncomment when cloud.deleteImages is available:
|
|
280
|
+
// return cloud.deleteImages(result.images)
|
|
281
|
+
// .then(() => result)
|
|
282
|
+
// .catch(err => {
|
|
283
|
+
// console.error('Error deleting images:', err);
|
|
284
|
+
// return result;
|
|
285
|
+
// });
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
return result;
|
|
289
|
+
})
|
|
290
|
+
.then(result => {
|
|
291
|
+
return res.status(200)
|
|
292
|
+
.json({ result, success: true,
|
|
293
|
+
message: `Document deleted successfully with ID: ${id}`
|
|
294
|
+
});
|
|
295
|
+
})
|
|
296
|
+
.catch(error => {
|
|
297
|
+
console.error('Error deleting document:', error);
|
|
298
|
+
return res.status(500).json({ result: error, success: false });
|
|
212
299
|
});
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// TODO: Clean up associated images if they exist
|
|
216
|
-
if (result.images && Array.isArray(result.images) && result.images.length > 0) {
|
|
217
|
-
console.log('Document had images that should be cleaned up:', result.images);
|
|
218
|
-
// Uncomment when cloud.deleteImages is available:
|
|
219
|
-
// await cloud.deleteImages(result.images);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
return res.status(200).json({
|
|
223
|
-
result,
|
|
224
|
-
success: true,
|
|
225
|
-
message: `Document deleted successfully with ID: ${id}`
|
|
226
|
-
});
|
|
227
300
|
});
|
|
228
301
|
|
|
229
302
|
/**
|
|
@@ -233,7 +306,7 @@ exports.delete = tryCatch(async (Model, req, res) => {
|
|
|
233
306
|
* @param {Object} res - Express response object
|
|
234
307
|
* @returns {Promise<void>}
|
|
235
308
|
*/
|
|
236
|
-
exports.list = tryCatch(
|
|
309
|
+
exports.list = tryCatch((Model, req, res) => {
|
|
237
310
|
const page = Math.max(1, parseInt(req.query.page) || 1);
|
|
238
311
|
const limit = Math.min(100, Math.max(1, parseInt(req.query.items) || 10));
|
|
239
312
|
const skip = (page - 1) * limit;
|
|
@@ -241,35 +314,44 @@ exports.list = tryCatch(async (Model, req, res) => {
|
|
|
241
314
|
|
|
242
315
|
const sortOrder = order === 'asc' ? 1 : -1;
|
|
243
316
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
])
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
317
|
+
const findQuery = Model.find()
|
|
318
|
+
.skip(skip)
|
|
319
|
+
.limit(limit)
|
|
320
|
+
.sort({ [sort]: sortOrder })
|
|
321
|
+
.populate(populate !== 'false' ? undefined : null)
|
|
322
|
+
.exec();
|
|
323
|
+
|
|
324
|
+
const countQuery = Model.countDocuments().exec();
|
|
325
|
+
|
|
326
|
+
return Promise.all([findQuery, countQuery])
|
|
327
|
+
.then(([result, count]) => {
|
|
328
|
+
const totalPages = Math.ceil(count / limit);
|
|
329
|
+
const pagination = {
|
|
330
|
+
currentPage: page,
|
|
331
|
+
totalPages,
|
|
332
|
+
totalItems: count,
|
|
333
|
+
itemsPerPage: limit,
|
|
334
|
+
hasNextPage: page < totalPages,
|
|
335
|
+
hasPrevPage: page > 1
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
return res.status(200).json({
|
|
339
|
+
result,
|
|
340
|
+
success: true,
|
|
341
|
+
pagination,
|
|
342
|
+
message: count > 0
|
|
343
|
+
? `Found ${result.length} of ${count} documents`
|
|
344
|
+
: "Collection is empty"
|
|
345
|
+
});
|
|
346
|
+
})
|
|
347
|
+
.catch(error => {
|
|
348
|
+
console.error('Error listing documents:', error);
|
|
349
|
+
return res.status(500).json({
|
|
350
|
+
result: null,
|
|
351
|
+
success: false,
|
|
352
|
+
message: "Error listing documents"
|
|
353
|
+
});
|
|
354
|
+
});
|
|
273
355
|
});
|
|
274
356
|
|
|
275
357
|
/**
|
|
@@ -279,7 +361,7 @@ exports.list = tryCatch(async (Model, req, res) => {
|
|
|
279
361
|
* @param {Object} res - Express response object
|
|
280
362
|
* @returns {Promise<void>}
|
|
281
363
|
*/
|
|
282
|
-
exports.search = tryCatch(
|
|
364
|
+
exports.search = tryCatch((Model, req, res) => {
|
|
283
365
|
console.log('CRUD search query:', req.query);
|
|
284
366
|
|
|
285
367
|
const {
|
|
@@ -294,7 +376,6 @@ exports.search = tryCatch(async (Model, req, res) => {
|
|
|
294
376
|
limit = 24
|
|
295
377
|
} = req.query;
|
|
296
378
|
|
|
297
|
-
// Build query object
|
|
298
379
|
const queryObj = {
|
|
299
380
|
page: parseInt(page),
|
|
300
381
|
limit: parseInt(limit)
|
|
@@ -325,19 +406,28 @@ exports.search = tryCatch(async (Model, req, res) => {
|
|
|
325
406
|
defaultSort: sortOptions[sortBy] || sortOptions.popularity
|
|
326
407
|
});
|
|
327
408
|
|
|
328
|
-
|
|
409
|
+
return searchApi
|
|
329
410
|
.search(['_id', 'id', 'price', 'name', 'description', 'brand', 'tags'])
|
|
330
411
|
.filter()
|
|
331
412
|
.sort()
|
|
332
413
|
.selectFields('-__v,-updatedAt')
|
|
333
414
|
.populate('reviews')
|
|
334
415
|
.paginate(parseInt(limit), 50)
|
|
335
|
-
.execute()
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
416
|
+
.execute()
|
|
417
|
+
.then(result => {
|
|
418
|
+
return res.status(200).json({
|
|
419
|
+
success: true,
|
|
420
|
+
...result
|
|
421
|
+
});
|
|
422
|
+
})
|
|
423
|
+
.catch(error => {
|
|
424
|
+
console.error('Error searching documents:', error);
|
|
425
|
+
return res.status(500).json({
|
|
426
|
+
success: false,
|
|
427
|
+
message: "Error searching documents",
|
|
428
|
+
error: error.message
|
|
429
|
+
});
|
|
430
|
+
});
|
|
341
431
|
});
|
|
342
432
|
|
|
343
433
|
/**
|
package/controllers/review.js
CHANGED
|
@@ -8,9 +8,9 @@ const Product = require("../models/product");
|
|
|
8
8
|
* @param {Object} res - Express response object
|
|
9
9
|
*/
|
|
10
10
|
exports.review = tryCatch(async (req, res) => {
|
|
11
|
-
const { rating, comment } = req.body;
|
|
12
|
-
const productId = req.params.
|
|
13
|
-
const userId = req.user._id;
|
|
11
|
+
const { username, email, rating, comment } = req.body;
|
|
12
|
+
const productId = req.params.productId || req.body.productId;
|
|
13
|
+
//const userId = req.user._id;
|
|
14
14
|
|
|
15
15
|
// Validate required fields
|
|
16
16
|
if (!rating || rating < 1 || rating > 5) {
|
|
@@ -42,8 +42,9 @@ exports.review = tryCatch(async (req, res) => {
|
|
|
42
42
|
);
|
|
43
43
|
|
|
44
44
|
const reviewData = {
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
productId: productId,
|
|
46
|
+
username,
|
|
47
|
+
email,
|
|
47
48
|
rating: Number(rating),
|
|
48
49
|
comment: comment.trim(),
|
|
49
50
|
createdAt: new Date()
|
|
@@ -74,7 +75,7 @@ exports.review = tryCatch(async (req, res) => {
|
|
|
74
75
|
if (existingReviewIndex !== -1) {
|
|
75
76
|
// Update existing review in Review collection
|
|
76
77
|
await Review.findOneAndUpdate(
|
|
77
|
-
{
|
|
78
|
+
{ username, productId },
|
|
78
79
|
reviewData,
|
|
79
80
|
{ upsert: true, new: true }
|
|
80
81
|
);
|
package/models/review.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
const mongoose = require("mongoose");
|
|
2
2
|
|
|
3
3
|
const reviewSchema = new mongoose.Schema({
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
productId: { type: mongoose.Schema.Types.ObjectId, ref:"Product", required:true },
|
|
5
|
+
username: { type: String, required: true },
|
|
6
|
+
email: { type: String, required: false, unique: true, lowercase: true, trim: true,
|
|
7
|
+
match: [/^\S+@\S+\.\S+$/, 'Please enter a valid email']
|
|
8
|
+
},
|
|
6
9
|
rating: { type:Number, required:true, min:1, max:5 },
|
|
7
10
|
comment: { type:String, required:true },
|
|
8
11
|
createdAt: { type:Date, default:Date.now }
|
package/package.json
CHANGED
package/routes/review.js
CHANGED
|
@@ -5,7 +5,7 @@ module.exports = (fear) => {
|
|
|
5
5
|
|
|
6
6
|
router.post("/new", Review.review)
|
|
7
7
|
.get("/rating", Review.rating)
|
|
8
|
-
.get("/product/:
|
|
9
|
-
|
|
8
|
+
.get("/by-product/:productId", Review.getProductReviews);
|
|
9
|
+
router.get("/by-product", Review.getProductReviews);
|
|
10
10
|
return router;
|
|
11
11
|
};
|