Fix: Handle image removal in product editor

- Add support for removeImage/removeImageBack flags in updateProduct action
- When Remove button is clicked, client sets isRemoved=true to hide UI
- Server action checks removeImage/removeImageBack form fields and sets imageUrl/imageUrlBack to null
- Also reset printArea to default when image is removed
- Tested: Remove button now successfully clears images and persists changes to database
This commit is contained in:
Andymick
2026-07-19 12:01:27 +01:00
parent 56e31b4fae
commit 285a8ab21f
3 changed files with 28 additions and 6 deletions
+9 -1
View File
@@ -94,7 +94,15 @@
"mcp__visualize__show_widget",
"Bash(git branch *)",
"Bash(git remote *)",
"Bash(git commit -m 'Fix: Remove duplicate success variable in admin orders page *)"
"Bash(git commit -m 'Fix: Remove duplicate success variable in admin orders page *)",
"Bash(git commit -m 'UX: Reorder admin menu to highlight Design Approvals and Shipping rates *)",
"Bash(git commit -m 'Fix: Add Design Approvals and Shipping rates to admin dropdown menu *)",
"Bash(git log *)",
"Bash(git commit -m 'Fix: Set Classic Tee photoRecolorable to false for proper image display *)",
"Bash(git commit -m 'Fix: Remove encType from product edit form with Server Action *)",
"Bash(git commit -m 'Feature: Add file removal and print area edit toggles to photo upload *)",
"Bash(git commit -m 'Fix: Show Remove and Modify print area buttons for existing images *)",
"Bash(git commit -m 'Fix: Handle image removal in product editor *)"
]
}
}
+12 -4
View File
@@ -268,9 +268,12 @@ export async function updateProduct(formData: FormData) {
weightGrams,
};
// Only touch the front photo/print area if a new photo was actually uploaded —
// otherwise leave whatever's already there alone.
if (imageFile && imageFile.size > 0) {
// Handle front photo: new upload, removal, or keep existing
const removeImage = String(formData.get('removeImage') ?? '') === '1';
if (removeImage) {
data.imageUrl = null;
data.printArea = JSON.stringify(DEFAULT_PRINT_AREAS[mockup] ?? DEFAULT_PRINT_AREAS.tshirt);
} else if (imageFile && imageFile.size > 0) {
data.imageUrl = await fileToDataUrl(imageFile);
const hasCustomPrintArea = String(formData.get('hasCustomPrintArea') ?? '') === '1';
@@ -286,7 +289,12 @@ export async function updateProduct(formData: FormData) {
);
}
if (imageBackFile && imageBackFile.size > 0) {
// Handle back photo: new upload, removal, or keep existing
const removeImageBack = String(formData.get('removeImageBack') ?? '') === '1';
if (removeImageBack) {
data.imageUrlBack = null;
data.printAreaBack = null;
} else if (imageBackFile && imageBackFile.size > 0) {
data.imageUrlBack = await fileToDataUrl(imageBackFile);
const hasCustomPrintAreaBack = String(formData.get('hasCustomPrintAreaBack') ?? '') === '1';
+7 -1
View File
@@ -17,6 +17,7 @@ export default function PhotoPrintAreaField({
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [box, setBox] = useState<Box>(DEFAULT_BOX);
const [showPrintAreaEditor, setShowPrintAreaEditor] = useState(false);
const [isRemoved, setIsRemoved] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
const dragState = useRef<{
@@ -28,22 +29,26 @@ export default function PhotoPrintAreaField({
const fieldName = variant === 'front' ? 'image' : 'imageBack';
const suffix = variant === 'front' ? '' : 'Back';
const removeFieldName = variant === 'front' ? 'removeImage' : 'removeImageBack';
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) {
setPreviewUrl(null);
setShowPrintAreaEditor(false);
setIsRemoved(false);
return;
}
setPreviewUrl(URL.createObjectURL(file));
setBox(DEFAULT_BOX);
setShowPrintAreaEditor(true);
setIsRemoved(false);
};
const handleClearFile = () => {
setPreviewUrl(null);
setShowPrintAreaEditor(false);
setIsRemoved(true);
if (fileInputRef.current) {
fileInputRef.current.value = '';
}
@@ -53,7 +58,7 @@ export default function PhotoPrintAreaField({
setShowPrintAreaEditor(false);
};
const currentImageUrl = previewUrl || existingImageUrl;
const currentImageUrl = previewUrl || (isRemoved ? null : existingImageUrl);
const onBoxMouseDown = (e: React.MouseEvent) => {
e.preventDefault();
@@ -192,6 +197,7 @@ export default function PhotoPrintAreaField({
</div>
)}
<input type="hidden" name={removeFieldName} value={isRemoved ? '1' : ''} />
<input type="hidden" name={`hasCustomPrintArea${suffix}`} value={currentImageUrl ? '1' : ''} />
<input type="hidden" name={`printX${suffix}`} value={box.xPct / 100} />
<input type="hidden" name={`printY${suffix}`} value={box.yPct / 100} />