Project-Image-Uploader/backend/src/routes/reorder.js
matthias.lotz 7564525c7e feat: implement drag-and-drop reordering infrastructure
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
2025-11-03 21:06:39 +01:00

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;