fix: resolve feedback validation issues from GitHub issue #16
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -126,11 +126,22 @@ export const FeedbackModerationPanel: React.FC<FeedbackModerationPanelProps> = (
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="mt-1 text-sm text-neutral-700">{item.comment}</p>
|
||||
{item.photo_filename && (
|
||||
<p className="mt-1 text-xs text-neutral-500">
|
||||
{t('feedback.onPhoto', 'On photo')}: {item.photo_filename}
|
||||
</p>
|
||||
<p className="mt-1 text-sm text-neutral-700">{item.comment_text || item.comment}</p>
|
||||
{item.photo_id && (
|
||||
<div className="mt-2 flex items-center gap-2">
|
||||
<img
|
||||
src={`/api/admin/photos/${eventId}/thumbnail/${item.photo_id}`}
|
||||
alt={item.filename || 'Photo'}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
onError={(e) => {
|
||||
// Hide image if thumbnail fails to load
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
<p className="text-xs text-neutral-500">
|
||||
{t('feedback.onPhoto', 'On photo')}: {item.filename || item.photo_filename || `#${item.photo_id}`}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -103,8 +103,8 @@ export const PhotoComments: React.FC<PhotoCommentsProps> = ({
|
||||
|
||||
submitCommentMutation.mutate({
|
||||
comment_text: commentText.trim(),
|
||||
guest_name: guestName.trim(),
|
||||
guest_email: guestEmail.trim()
|
||||
guest_name: guestName.trim() || undefined,
|
||||
guest_email: guestEmail.trim() || undefined
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ export const PhotoFavorites: React.FC<PhotoFavoritesProps> = ({
|
||||
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);
|
||||
|
||||
@@ -36,8 +36,8 @@ export const PhotoLikes: React.FC<PhotoLikesProps> = ({
|
||||
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);
|
||||
|
||||
@@ -42,8 +42,8 @@ export const PhotoRating: React.FC<PhotoRatingProps> = ({
|
||||
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);
|
||||
|
||||
@@ -250,11 +250,17 @@ export const EventFeedbackPage: React.FC = () => {
|
||||
{feedbackData?.feedback?.map((item: PhotoFeedback) => (
|
||||
<Card key={item.id} className="overflow-hidden">
|
||||
<div className="p-4 flex items-start gap-4">
|
||||
<img
|
||||
src={`/thumbnails/${item.path}`}
|
||||
alt={item.filename}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
/>
|
||||
{item.photo_id && (
|
||||
<img
|
||||
src={`/api/admin/photos/${eventId}/thumbnail/${item.photo_id}`}
|
||||
alt={item.filename || 'Photo'}
|
||||
className="w-16 h-16 object-cover rounded"
|
||||
onError={(e) => {
|
||||
// Hide image if thumbnail fails to load
|
||||
(e.target as HTMLImageElement).style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div className="flex-1">
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user