import { Product } from "@medusajs/medusa" import { useAdminCreateProductOption, useAdminDeleteProductOption, useAdminUpdateProductOption, } from "medusa-react" import { useEffect, useMemo } from "react" import { useFieldArray, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import useNotification from "../../../hooks/use-notification" import FormValidator from "../../../utils/form-validator" import Button from "../../fundamentals/button" import PlusIcon from "../../fundamentals/icons/plus-icon" import TrashIcon from "../../fundamentals/icons/trash-icon" import InputField from "../../molecules/input" import Modal from "../../molecules/modal" import { useOptionsContext } from "./options-provider" type Props = { product: Product open: boolean onClose: () => void } type Option = { id: string | null title: string } type OptionsForm = { options: Option[] } const OptionsModal = ({ product, open, onClose }: Props) => { const { mutate: update, isLoading: updating } = useAdminUpdateProductOption( product.id ) const { mutate: create, isLoading: creating } = useAdminCreateProductOption( product.id ) const { mutate: del, isLoading: deleting } = useAdminDeleteProductOption( product.id ) const { t } = useTranslation() const { refetch } = useOptionsContext() const { control, register, reset, handleSubmit, formState: { isDirty, errors }, } = useForm({ defaultValues: getDefaultValues(product), }) const { fields, remove, append } = useFieldArray({ name: "options", control, shouldUnregister: true, }) const notification = useNotification() useEffect(() => { reset(getDefaultValues(product)) }, [product]) const handleClose = () => { reset(getDefaultValues(product)) onClose() } const handleAddAnOption = () => { append({ title: "", id: null }) } const isSubmitting = useMemo(() => { return updating || creating || deleting }, [updating, creating, deleting]) const onSubmit = handleSubmit((data) => { const errors: string[] = [] const toCreate: Option[] = [] const toUpdate: Option[] = [] const toDelete: Option[] = product.options.filter( (o) => data.options.find((d) => d.id === o.id) === undefined ) data.options.forEach((option) => { if (option.id) { toUpdate.push(option) } else { toCreate.push(option) } }) toCreate.forEach((option) => { create( { title: option.title, }, { onError: () => { errors.push(`create ${option.title}`) }, onSuccess: () => { refetch() }, } ) }) toUpdate.forEach((option) => { update( { option_id: option.id!, title: option.title, }, { onError: () => { errors.push(`update ${option.title}`) }, onSuccess: () => { refetch() }, } ) }) toDelete.forEach((option) => { del(option.id!, { onError: () => { errors.push(`delete ${option.title}`) }, onSuccess: () => { refetch() }, }) }) if (errors.length === toCreate.length + toUpdate.length + toDelete.length) { notification( t("product-variants-section-error", "Error"), t( "product-variants-section-failed-to-update-product-options", "Failed to update product options" ), "error" ) return } if (errors.length > 0) { notification( "Warning", "Failed to; " + errors.join(", ") + ".", "warning" ) } refetch() notification( t("product-variants-section-success", "Success"), t( "product-variants-section-successfully-updated-product-options", "Successfully updated product options" ), "success" ) handleClose() }) return (

{t("product-variants-section-edit-options", "Edit Options")}

{t("product-variants-section-product-options", "Product options")}

{t("product-variants-section-option-title", "Option title")}

{fields.map((field, index) => { return (
) })}
) } const getDefaultValues = (product: Product) => { return { options: product.options.map((option) => ({ title: option.title, id: option.id, })), } } export default OptionsModal