From f26becad1dfa72c62b6ecec491be025644426d67 Mon Sep 17 00:00:00 2001 From: paul Date: Tue, 2 Sep 2025 17:23:07 +0200 Subject: [PATCH] fix: resolve feedback validation issues from GitHub issue #16 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fixed 400 Bad Request error when submitting feedback with name/email required - Updated backend validation to properly handle empty/undefined name/email fields - Modified frontend components to send undefined instead of empty strings when fields are not provided - Fixed thumbnail display issue in moderation view by using correct admin API endpoints - Updated FeedbackModerationPanel and EventFeedbackPage to display thumbnails correctly The issue was caused by the validation logic treating empty strings differently than undefined values. Frontend components now properly send undefined when name/email are not provided, and the backend validation correctly handles both cases. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- backend/src/utils/feedbackValidation.js | 6 +++--- .../admin/FeedbackModerationPanel.tsx | 21 ++++++++++++++----- .../src/components/gallery/PhotoComments.tsx | 4 ++-- .../src/components/gallery/PhotoFavorites.tsx | 4 ++-- .../src/components/gallery/PhotoLikes.tsx | 4 ++-- .../src/components/gallery/PhotoRating.tsx | 4 ++-- .../src/pages/admin/EventFeedbackPage.tsx | 16 +++++++++----- 7 files changed, 38 insertions(+), 21 deletions(-) diff --git a/backend/src/utils/feedbackValidation.js b/backend/src/utils/feedbackValidation.js index 1af1794..2c7dbdb 100644 --- a/backend/src/utils/feedbackValidation.js +++ b/backend/src/utils/feedbackValidation.js @@ -233,11 +233,11 @@ async function validateGuestRequirements(settings, guestData) { errors.push('Name is required'); } - // Check for email - handle both undefined and empty strings + // Check for email - handle both undefined and empty strings const email = guestData.guest_email; if (!email || (typeof email === 'string' && email.trim().length === 0)) { - errors.push('Valid email is required'); - } else if (email && !validator.isEmail(email.trim())) { + errors.push('Email is required'); + } else if (email && typeof email === 'string' && !validator.isEmail(email.trim())) { errors.push('Valid email is required'); } diff --git a/frontend/src/components/admin/FeedbackModerationPanel.tsx b/frontend/src/components/admin/FeedbackModerationPanel.tsx index 34dbb03..fc1eea2 100644 --- a/frontend/src/components/admin/FeedbackModerationPanel.tsx +++ b/frontend/src/components/admin/FeedbackModerationPanel.tsx @@ -126,11 +126,22 @@ export const FeedbackModerationPanel: React.FC = ( )} -

{item.comment}

- {item.photo_filename && ( -

- {t('feedback.onPhoto', 'On photo')}: {item.photo_filename} -

+

{item.comment_text || item.comment}

+ {item.photo_id && ( +
+ {item.filename { + // Hide image if thumbnail fails to load + (e.target as HTMLImageElement).style.display = 'none'; + }} + /> +

+ {t('feedback.onPhoto', 'On photo')}: {item.filename || item.photo_filename || `#${item.photo_id}`} +

+
)} diff --git a/frontend/src/components/gallery/PhotoComments.tsx b/frontend/src/components/gallery/PhotoComments.tsx index 995638f..0895d4f 100644 --- a/frontend/src/components/gallery/PhotoComments.tsx +++ b/frontend/src/components/gallery/PhotoComments.tsx @@ -103,8 +103,8 @@ export const PhotoComments: React.FC = ({ submitCommentMutation.mutate({ comment_text: commentText.trim(), - guest_name: guestName.trim(), - guest_email: guestEmail.trim() + guest_name: guestName.trim() || undefined, + guest_email: guestEmail.trim() || undefined }); }; diff --git a/frontend/src/components/gallery/PhotoFavorites.tsx b/frontend/src/components/gallery/PhotoFavorites.tsx index 5a00c6f..1d1b511 100644 --- a/frontend/src/components/gallery/PhotoFavorites.tsx +++ b/frontend/src/components/gallery/PhotoFavorites.tsx @@ -36,8 +36,8 @@ export const PhotoFavorites: React.FC = ({ mutationFn: (data: { guest_name?: string; guest_email?: string } = {}) => feedbackService.submitFeedback(gallerySlug, photoId, { feedback_type: 'favorite', - guest_name: data.guest_name, - guest_email: data.guest_email + guest_name: data.guest_name || undefined, + guest_email: data.guest_email || undefined }), onMutate: async () => { setIsSubmitting(true); diff --git a/frontend/src/components/gallery/PhotoLikes.tsx b/frontend/src/components/gallery/PhotoLikes.tsx index 1837ac7..4f4c5dc 100644 --- a/frontend/src/components/gallery/PhotoLikes.tsx +++ b/frontend/src/components/gallery/PhotoLikes.tsx @@ -36,8 +36,8 @@ export const PhotoLikes: React.FC = ({ mutationFn: (data: { guest_name?: string; guest_email?: string } = {}) => feedbackService.submitFeedback(gallerySlug, photoId, { feedback_type: 'like', - guest_name: data.guest_name, - guest_email: data.guest_email + guest_name: data.guest_name || undefined, + guest_email: data.guest_email || undefined }), onMutate: async () => { setIsSubmitting(true); diff --git a/frontend/src/components/gallery/PhotoRating.tsx b/frontend/src/components/gallery/PhotoRating.tsx index acd1307..b247962 100644 --- a/frontend/src/components/gallery/PhotoRating.tsx +++ b/frontend/src/components/gallery/PhotoRating.tsx @@ -42,8 +42,8 @@ export const PhotoRating: React.FC = ({ feedbackService.submitFeedback(gallerySlug, photoId, { feedback_type: 'rating', rating: data.rating, - guest_name: data.guest_name, - guest_email: data.guest_email + guest_name: data.guest_name || undefined, + guest_email: data.guest_email || undefined }), onMutate: async (data) => { setIsSubmitting(true); diff --git a/frontend/src/pages/admin/EventFeedbackPage.tsx b/frontend/src/pages/admin/EventFeedbackPage.tsx index 36780c8..a53e4ae 100644 --- a/frontend/src/pages/admin/EventFeedbackPage.tsx +++ b/frontend/src/pages/admin/EventFeedbackPage.tsx @@ -250,11 +250,17 @@ export const EventFeedbackPage: React.FC = () => { {feedbackData?.feedback?.map((item: PhotoFeedback) => (
- {item.filename} + {item.photo_id && ( + {item.filename { + // Hide image if thumbnail fails to load + (e.target as HTMLImageElement).style.display = 'none'; + }} + /> + )}