77f07e9329
Fixes two bugs reported on #292 after 3.27.0-beta.0 shipped: 1. Masonry grid showed no visual feedback after liking a photo. MasonryGalleryLayout's Like button had no liked-state plumbing — the Heart icon was a static <Heart> regardless of whether the user had liked the photo. 2. PhotoLightbox (fullscreen view) silently failed to like photos in guest identity mode. submitLike() and submitRating() never called ensureIdentity() before firing the API request, so the first interaction from a fresh session hit a 401 from the server instead of opening the name prompt. Root causes: 1. MasonryGalleryLayout was missing the 'liked' state pattern that GridGalleryLayout already uses (likedPhotoIds Set in the parent, passed down as a `liked` prop, updated via onLikeSuccess callback). The bug was invisible in simple mode (no personal state) but surfaced immediately in guest mode where each guest expects to see confirmation of their own action. 2. PhotoLightbox's submit handlers were written before the guest identity context existed and only checked the legacy require_name_email flag. They were never updated when guest mode landed. Also fixed: z-index conflict where the GuestNamePromptModal (z-50) was sitting at the same level as PhotoLightbox (z-50), so when the prompt opened over the lightbox, the fullscreen image intercepted pointer events and the modal's Continue button was unclickable. Bumped both guest modals to z-[60]. Changes: - MasonryGalleryLayout.tsx - MasonryPhotoProps gains `liked?: boolean` + `onLikeSuccess?: () => void`. - Like button: red bg + filled white Heart icon when liked; aria-label toggles between "Like photo"/"Unlike photo"; aria-pressed mirrors state. - onClick wires onLikeSuccess() for optimistic UI in both guest-mode and simple-mode branches plus the FeedbackIdentityModal onSubmit path. - Parent layout holds `likedPhotoIds: Set<number>` and passes it to each MasonryPhoto (matches the GridGalleryLayout pattern). - PhotoLightbox.tsx - Consumes useGuestIdentityOptional(); new `isGuestMode` flag. - submitLike() and submitRating() get a guest-mode branch that calls ensureIdentity() first and submits without body guest_name/email (server reads from the verified token). - Optimistic UI updates happen after successful submit in guest mode. - GuestNamePromptModal.tsx, GuestRecoveryModal.tsx - z-50 → z-[60] so they render above PhotoLightbox. Verified end-to-end against local Docker with Playwright MCP on event 168 (Masonry Columns Test layout): - Fresh session, click Like in Masonry grid → name prompt opens, register, feedback persists with guest_id, Heart button turns red with aria-pressed and "Unlike photo" label. Subsequent likes on other photos also show red state. DB confirms feedback rows. - Fresh session, open photo in lightbox BEFORE registering → click Like, the name prompt correctly opens on top of the lightbox, register, feedback persists. Rate 4 stars → works, average 4.0 (1) displayed in lightbox, ★ badge appears on toggle-feedback button, grid cell shows "1 likes" + "Rating: 4.0" indicators after closing lightbox. - Backend DB: gallery_guests row created, photo_feedback rows have correct guest_id, server reads name from verified token (body values ignored). Out of scope (documented in audit, not reported by the user, no regression from guest mode): Mosaic/Carousel/Timeline have partial optimistic-UI issues unrelated to this report; they pre-date guest mode and behave the same in simple mode. Leaving alone per scope discipline.