medusa-variant-images-updated
Version:
A variant images plugin for Medusa V2.
204 lines (203 loc) • 8.39 kB
JavaScript
import { jsx, jsxs } from "react/jsx-runtime";
import { useState, useEffect, useCallback } from "react";
import { useForm } from "react-hook-form";
import { FocusModal, Button } from "@medusajs/ui";
import { nestedForm } from "./utils/nestedForm.js";
import VariantsImagesMediaForm from "./VariantsImagesMediaForm.js";
import { prepareImages } from "./utils/images.js";
import { fetchBackend } from "./utils/util.js";
const VariantsImagesModal = ({ variant, open, onClose, product, type, settings, notify }) => {
const [isUpdating, setIsUpdating] = useState(false);
const [imageArr, setImageArr] = useState([]);
const [deletedImages, setDeletedImages] = useState([]);
const [variants, setVariants] = useState(variant);
const form = useForm({
defaultValues: { media: { images: [] } }
});
const { handleSubmit, reset, setValue, formState: { isDirty } } = form;
useEffect(() => {
const fetchImages = async () => {
const res = await fetchBackend(`/admin/variant-images?variant_id=${variant.id}`);
const images = ((res == null ? void 0 : res.data) || []).map((img) => ({
...img,
info: {
selected: type === "thumbnail" ? img.type === "thumbnail" : false,
selectedNumber: -1
}
}));
setImageArr(images);
setValue("media.images", images);
setDeletedImages([]);
};
if (open) fetchImages();
}, [variant.id, open, setValue, type]);
useEffect(() => {
reset({ media: { images: imageArr } });
}, [imageArr, reset]);
useEffect(() => {
var _a, _b;
if ((_a = settings.baseOptionUpload) == null ? void 0 : _a.enabled) {
const _variants = (_b = product.variants) == null ? void 0 : _b.filter(
(v) => {
var _a2, _b2, _c, _d;
return ((_b2 = (_a2 = v.options) == null ? void 0 : _a2.find((o) => o.option_id === settings.baseOptionUpload.option)) == null ? void 0 : _b2.value) === ((_d = (_c = variant.options) == null ? void 0 : _c.find((o) => o.option_id === settings.baseOptionUpload.option)) == null ? void 0 : _d.value);
}
);
if (_variants == null ? void 0 : _variants.length) setVariants(_variants);
}
}, [settings.baseOptionUpload, product, variant]);
const handleDeleteImage = useCallback((image) => {
if (typeof image.id === "number" && Number.isInteger(image.id)) {
setDeletedImages((prev) => [...prev, image]);
}
}, []);
const handleBatchDelete = (images) => {
setDeletedImages((prev) => [
...prev,
...images.filter((img) => typeof img.id === "number" && Number.isInteger(img.id))
]);
};
const handleThumbnailSelect = (image) => {
};
const onSubmit = handleSubmit(async (data) => {
var _a, _b, _c, _d, _e, _f;
setIsUpdating(true);
try {
for (const img of deletedImages) {
if (typeof img.id === "number" && Number.isInteger(img.id)) {
await fetchBackend(`/admin/variant-images/${img.id}`, { method: "DELETE" });
}
}
let imagesToSave = data.media.images;
const originalImagesMap = /* @__PURE__ */ new Map();
for (const img of imagesToSave) {
originalImagesMap.set(img.url, img);
}
const uploadedImages = (await prepareImages(imagesToSave)).map((img) => {
var _a2;
return {
...img,
info: ((_a2 = originalImagesMap.get(img.url)) == null ? void 0 : _a2.info) ?? { selected: false, selectedNumber: -1 }
};
});
let updatedVariantList;
if (((_a = settings.baseOptionUpload) == null ? void 0 : _a.enabled) && Array.isArray(variants)) {
updatedVariantList = await fetchBackend(`/admin/products/${product.id}/variants?order=title`).then((res) => res == null ? void 0 : res.variants);
}
if (((_b = settings.baseOptionUpload) == null ? void 0 : _b.enabled) && settings.baseOptionUpload.option && Array.isArray(product.variants)) {
const baseOptionId = settings.baseOptionUpload.option;
const currentValue = (_d = (_c = variant.options) == null ? void 0 : _c.find((o) => o.option_id === baseOptionId)) == null ? void 0 : _d.value;
await fetchBackend("/admin/variant-images-batch", {
method: "POST",
body: {
product_id: product.id,
option_id: baseOptionId,
option_value: currentValue,
images: uploadedImages.map((img) => ({
url: img.url,
type: img.type || "media"
}))
}
});
} else {
const newImageArr = [];
if (type === "thumbnail") {
const selected = uploadedImages.find((img) => {
var _a2;
return (_a2 = img.info) == null ? void 0 : _a2.selected;
});
for (const img of uploadedImages) {
const { id, ...imgData } = img;
const payload = {
variant_id: variant.id,
url: imgData.url,
type: selected && imgData.url === selected.url ? "thumbnail" : "media"
};
if (typeof id === "number" && Number.isInteger(id)) {
await fetchBackend(`/admin/variant-images/${id}`, {
method: "POST",
body: payload
});
newImageArr.push({ ...img, id, info: img.info });
} else {
const newImage = await fetchBackend("/admin/variant-images", {
method: "POST",
body: payload
});
newImageArr.push({ ...newImage, info: ((_e = originalImagesMap.get(img.url)) == null ? void 0 : _e.info) ?? { selected: false, selectedNumber: -1 } });
}
}
} else {
for (const img of uploadedImages) {
const { id, ...imgData } = img;
let typeToSave = img.type;
if (!typeToSave) typeToSave = "media";
const payload = {
variant_id: variant.id,
url: imgData.url,
type: typeToSave
// 'media' or 'thumbnail'
};
if (typeof id === "number" && Number.isInteger(id)) {
await fetchBackend(`/admin/variant-images/${id}`, {
method: "POST",
body: payload
});
newImageArr.push({ ...img, id, info: img.info });
} else {
const newImage = await fetchBackend("/admin/variant-images", {
method: "POST",
body: payload
});
newImageArr.push({ ...newImage, info: ((_f = originalImagesMap.get(img.url)) == null ? void 0 : _f.info) ?? { selected: false, selectedNumber: -1 } });
}
}
}
setImageArr(newImageArr);
}
notify("Images updated!");
onClose(updatedVariantList ? { ...product, variants: updatedVariantList } : void 0);
setTimeout(() => {
window.location.reload();
}, 100);
} catch (e) {
notify.error("Error", { description: "Failed to update images." });
} finally {
setIsUpdating(false);
}
});
const onReset = () => {
reset({ media: { images: imageArr } });
onClose();
setTimeout(() => {
window.location.reload();
}, 100);
};
return /* @__PURE__ */ jsx(FocusModal, { open, onOpenChange: onReset, modal: true, children: /* @__PURE__ */ jsxs(FocusModal.Content, { "aria-describedby": void 0, children: [
/* @__PURE__ */ jsx(FocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx("h2", { className: "sr-only", children: "Variant Images" }) }),
/* @__PURE__ */ jsx(FocusModal.Header, { children: /* @__PURE__ */ jsx(
Button,
{
variant: "primary",
type: "submit",
disabled: !isDirty,
isLoading: isUpdating,
form: "variant-images-form",
children: "Save and close"
}
) }),
/* @__PURE__ */ jsx(FocusModal.Body, { children: /* @__PURE__ */ jsx("form", { onSubmit, id: "variant-images-form", className: "h-full w-full", children: /* @__PURE__ */ jsx(
VariantsImagesMediaForm,
{
form: nestedForm(form, "media"),
type,
onDeleteImage: handleDeleteImage,
onBatchDelete: handleBatchDelete,
onThumbnailSelect: handleThumbnailSelect
}
) }) })
] }) });
};
export {
VariantsImagesModal as default
};