- CatalogSearchOverlay: replace handleAddStub with real openAddToCollection/openAddToThread routing based on catalogSearchMode - ConfirmDialog + __root.tsx: swap t() for Trans component on deleteItemMessage, deleteCandidateMessage, pickWinnerMessage — fixes <bold> rendering as literal text - Biome format pass: fix 23 lint/format errors across scripts, services, tests - Planning: mark all UAT and verification gaps resolved for phases 07, 11, 16, 20, 21, 22, 24, 32, 34; close debug sessions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
3.5 KiB
Markdown
56 lines
3.5 KiB
Markdown
---
|
|
status: resolved
|
|
trigger: "crop editor opens on upload correctly, but after cropping the cropped image isn't shown in the edit state always — after clicking save it is shown correctly"
|
|
created: 2026-04-13T12:30:00Z
|
|
updated: 2026-04-13T12:35:00Z
|
|
---
|
|
|
|
## Current Focus
|
|
|
|
hypothesis: GearImage in ImageUpload receives no crop props after cropping — crop values are sent to server via onCropChange but never stored locally or passed to the preview GearImage
|
|
test: trace data flow from ImageCropEditor.onSave through ImageUpload to GearImage rendering
|
|
expecting: GearImage in ImageUpload has no cropZoom/cropX/cropY props
|
|
next_action: return diagnosis
|
|
|
|
## Symptoms
|
|
|
|
expected: After cropping in the crop editor, the image preview in edit mode should immediately reflect the crop
|
|
actual: Cropped image not shown in edit state after cropping; shows correctly only after Save
|
|
errors: None
|
|
reproduction: Upload image to item -> crop editor opens -> adjust crop -> close editor -> preview shows uncropped image -> Save item -> page re-renders with crop applied
|
|
started: Since Phase 29 implementation
|
|
|
|
## Eliminated
|
|
|
|
(none needed — root cause found on first hypothesis)
|
|
|
|
## Evidence
|
|
|
|
- timestamp: 2026-04-13T12:32:00Z
|
|
checked: ImageUpload.tsx lines 83-95 — ImageCropEditor onSave handler
|
|
found: onSave calls onCropChange(result) then setShowCropEditor(false). The crop values are passed up to the parent but NOT stored in any local state within ImageUpload.
|
|
implication: After crop editor closes, ImageUpload has no memory of what crop was applied.
|
|
|
|
- timestamp: 2026-04-13T12:33:00Z
|
|
checked: ImageUpload.tsx lines 109-114 — GearImage rendering after crop editor closes
|
|
found: GearImage is rendered with only src, alt, and dominantColor props. NO cropZoom, cropX, or cropY props are passed. The component never receives crop values.
|
|
implication: GearImage renders uncropped because it literally has no crop data to apply.
|
|
|
|
- timestamp: 2026-04-13T12:34:00Z
|
|
checked: $itemId.tsx lines 277-294 — onCropChange callback in item detail page
|
|
found: onCropChange triggers updateItem.mutate() which sends crop values to the server immediately. This is a fire-and-forget mutation — it does NOT update local state or the React Query cache synchronously.
|
|
implication: Crop values reach the server, but the local component tree has no access to them until the query is invalidated/refetched.
|
|
|
|
- timestamp: 2026-04-13T12:34:30Z
|
|
checked: $itemId.tsx lines 326-335 — GearImage in non-edit view mode
|
|
found: Non-edit view reads cropZoom, cropX, cropY from item (React Query cache data). After Save, the mutation invalidates the query, item refetches with crop values, and GearImage renders correctly.
|
|
implication: Confirms the "works after save" behavior — the query refetch provides the crop data.
|
|
|
|
## Resolution
|
|
|
|
root_cause: ImageUpload component does not track crop values locally after the crop editor closes. When the crop editor's onSave fires, the crop values are forwarded to the parent ($itemId.tsx) which sends them to the server via updateItem.mutate(), but no local state is updated. The GearImage rendered inside ImageUpload receives zero crop-related props (cropZoom, cropX, cropY are never passed). So the preview always shows the uncropped/default image. After the user clicks Save on the item form, the React Query cache is invalidated, the item refetches with server-side crop values, and the page re-renders in view mode with the correct crop applied.
|
|
|
|
fix: (not applied — diagnosis only)
|
|
verification: (not applied — diagnosis only)
|
|
files_changed: []
|