Files
GearBox/.planning/debug/crop-preview-edit-state.md
Jean-Luc Makiola ba13fa8ded
Some checks failed
CI / ci (push) Failing after 20s
CI / deploy (push) Has been skipped
CI / e2e (push) Has been skipped
docs: update roadmap, config, and UAT state
2026-04-13 13:56:56 +02:00

3.5 KiB

status, trigger, created, updated
status trigger created updated
diagnosed 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 2026-04-13T12:30:00Z 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: []