Phase 1 (Backend API): ✅ GroupRepository.updateImageOrder() with SQL transactions ✅ PUT /api/groups/:groupId/reorder API route with validation ✅ Manual testing: Reordering verified working (group qion_-lT1) ✅ Error handling: Invalid IDs, missing groups, empty arrays Phase 2 (Frontend DnD): ✅ @dnd-kit/core packages installed ✅ ReorderService.js for API communication ✅ useReordering.js custom hook with optimistic updates ✅ ImageGalleryCard.js extended with drag handles & sortable ✅ ImageGallery.js with DndContext and SortableContext ✅ CSS styles for drag states, handles, touch-friendly mobile Next: Integration with ModerationGroupImagesPage
100 lines
3.0 KiB
JavaScript
100 lines
3.0 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const GroupRepository = require('../repositories/GroupRepository');
|
|
|
|
/**
|
|
* PUT /api/groups/:groupId/reorder
|
|
* Reorder images within a group
|
|
*
|
|
* Request Body:
|
|
* {
|
|
* "imageIds": [123, 456, 789] // Array of image IDs in new order
|
|
* }
|
|
*
|
|
* Response:
|
|
* {
|
|
* "success": true,
|
|
* "message": "Image order updated successfully",
|
|
* "data": {
|
|
* "groupId": "abc123",
|
|
* "updatedImages": 3,
|
|
* "newOrder": [123, 456, 789]
|
|
* }
|
|
* }
|
|
*/
|
|
router.put('/:groupId/reorder', async (req, res) => {
|
|
try {
|
|
const { groupId } = req.params;
|
|
const { imageIds } = req.body;
|
|
|
|
// Input validation
|
|
if (!groupId) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'Group ID is required'
|
|
});
|
|
}
|
|
|
|
if (!imageIds || !Array.isArray(imageIds) || imageIds.length === 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: 'imageIds array is required and cannot be empty'
|
|
});
|
|
}
|
|
|
|
// Validate that all imageIds are numbers
|
|
const invalidIds = imageIds.filter(id => !Number.isInteger(id) || id <= 0);
|
|
if (invalidIds.length > 0) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: `Invalid image IDs: ${invalidIds.join(', ')}. Image IDs must be positive integers`
|
|
});
|
|
}
|
|
|
|
// Log the reordering operation
|
|
console.log(`[REORDER] Group ${groupId}: Reordering ${imageIds.length} images`);
|
|
console.log(`[REORDER] New order: ${imageIds.join(' → ')}`);
|
|
|
|
// Execute the reordering
|
|
const result = await GroupRepository.updateImageOrder(groupId, imageIds);
|
|
|
|
// Success response
|
|
res.status(200).json({
|
|
success: true,
|
|
message: 'Image order updated successfully',
|
|
data: result
|
|
});
|
|
|
|
// Log success
|
|
console.log(`[REORDER] Success: Updated ${result.updatedImages} images in group ${groupId}`);
|
|
|
|
} catch (error) {
|
|
console.error(`[REORDER] Error reordering images in group ${req.params.groupId}:`, error.message);
|
|
|
|
// Handle specific error types
|
|
if (error.message.includes('not found')) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
message: error.message
|
|
});
|
|
}
|
|
|
|
if (error.message.includes('Invalid image IDs') ||
|
|
error.message.includes('Missing image IDs') ||
|
|
error.message.includes('is required')) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
message: error.message
|
|
});
|
|
}
|
|
|
|
// Generic server error
|
|
res.status(500).json({
|
|
success: false,
|
|
message: 'Internal server error during image reordering',
|
|
error: process.env.NODE_ENV === 'development' ? error.message : undefined
|
|
});
|
|
}
|
|
});
|
|
|
|
module.exports = router; |