saleor-dashboard/src/attributes/views/AttributeCreate/AttributeCreate.tsx

191 lines
5.7 KiB
TypeScript
Raw Normal View History

import { ProductErrorFragment } from "@saleor/fragments/types/ProductErrorFragment";
2019-08-09 10:17:04 +00:00
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { getStringOrPlaceholder } from "@saleor/misc";
2020-03-24 14:05:26 +00:00
import { ReorderEvent } from "@saleor/types";
import { ProductErrorCode } from "@saleor/types/globalTypes";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
2019-08-09 10:17:04 +00:00
import {
add,
isSelected,
move,
remove,
updateAtIndex
} from "@saleor/utils/lists";
import React from "react";
import { useIntl } from "react-intl";
import slugify from "slugify";
2019-08-09 10:17:04 +00:00
import AttributePage from "../../components/AttributePage";
import AttributeValueDeleteDialog from "../../components/AttributeValueDeleteDialog";
import AttributeValueEditDialog, {
AttributeValueEditDialogFormData
} from "../../components/AttributeValueEditDialog";
import { useAttributeCreateMutation } from "../../mutations";
2019-08-09 10:17:04 +00:00
import {
attributeAddUrl,
AttributeAddUrlDialog,
2019-08-09 10:17:04 +00:00
AttributeAddUrlQueryParams,
attributeListUrl,
attributeUrl
2019-08-09 10:17:04 +00:00
} from "../../urls";
interface AttributeDetailsProps {
params: AttributeAddUrlQueryParams;
}
2020-03-24 14:05:26 +00:00
const attributeValueAlreadyExistsError: ProductErrorFragment = {
__typename: "ProductError",
code: ProductErrorCode.ALREADY_EXISTS,
field: "name"
};
2019-08-09 10:17:04 +00:00
function areValuesEqual(
a: AttributeValueEditDialogFormData,
b: AttributeValueEditDialogFormData
) {
return a.name === b.name;
}
const AttributeDetails: React.FC<AttributeDetailsProps> = ({ params }) => {
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
2019-08-09 10:17:04 +00:00
const [values, setValues] = React.useState<
AttributeValueEditDialogFormData[]
>([]);
2020-03-24 14:05:26 +00:00
const [valueErrors, setValueErrors] = React.useState<ProductErrorFragment[]>(
[]
);
2019-08-09 10:17:04 +00:00
const [attributeCreate, attributeCreateOpts] = useAttributeCreateMutation({
onCompleted: data => {
if (data.attributeCreate.errors.length === 0) {
notify({
status: "success",
text: intl.formatMessage({
defaultMessage: "Successfully created attribute"
})
});
navigate(attributeUrl(data.attributeCreate.attribute.id));
}
}
});
2019-08-09 10:17:04 +00:00
const id = params.id ? parseInt(params.id, 0) : undefined;
2019-12-06 14:58:28 +00:00
const [openModal, closeModal] = createDialogActionHandlers<
AttributeAddUrlDialog,
AttributeAddUrlQueryParams
>(navigate, attributeAddUrl, params);
2019-08-09 10:17:04 +00:00
2020-03-24 14:05:26 +00:00
React.useEffect(() => setValueErrors([]), [params.action]);
2019-08-09 10:17:04 +00:00
const handleValueDelete = () => {
setValues(remove(values[params.id], values, areValuesEqual));
closeModal();
};
const handleValueUpdate = (input: AttributeValueEditDialogFormData) => {
if (isSelected(input, values, areValuesEqual)) {
2020-03-24 14:05:26 +00:00
setValueErrors([attributeValueAlreadyExistsError]);
2019-08-09 10:17:04 +00:00
} else {
setValues(updateAtIndex(input, values, id));
closeModal();
}
};
const handleValueCreate = (input: AttributeValueEditDialogFormData) => {
if (isSelected(input, values, areValuesEqual)) {
2020-03-24 14:05:26 +00:00
setValueErrors([attributeValueAlreadyExistsError]);
2019-08-09 10:17:04 +00:00
} else {
setValues(add(input, values));
closeModal();
}
};
const handleValueReorder = ({ newIndex, oldIndex }: ReorderEvent) =>
setValues(move(values[oldIndex], values, areValuesEqual, newIndex));
return (
<>
<AttributePage
attribute={null}
disabled={attributeCreateOpts.loading}
errors={attributeCreateOpts.data?.attributeCreate.errors || []}
onBack={() => navigate(attributeListUrl())}
onDelete={undefined}
onSubmit={input =>
attributeCreate({
variables: {
input: {
...input,
storefrontSearchPosition: parseInt(
input.storefrontSearchPosition,
0
),
values: values.map(value => ({
name: value.name
}))
}
2019-12-06 17:11:46 +00:00
}
})
}
onValueAdd={() => openModal("add-value")}
onValueDelete={id =>
openModal("remove-value", {
id
})
}
onValueReorder={handleValueReorder}
onValueUpdate={id =>
openModal("edit-value", {
id
})
}
saveButtonBarState={attributeCreateOpts.status}
values={values.map((value, valueIndex) => ({
__typename: "AttributeValue" as "AttributeValue",
id: valueIndex.toString(),
slug: slugify(value.name).toLowerCase(),
sortOrder: valueIndex,
type: null,
value: null,
...value
}))}
/>
<AttributeValueEditDialog
attributeValue={null}
confirmButtonState="default"
disabled={false}
errors={valueErrors}
open={params.action === "add-value"}
onClose={closeModal}
onSubmit={handleValueCreate}
/>
{values.length > 0 && (
<>
<AttributeValueDeleteDialog
attributeName={undefined}
open={params.action === "remove-value"}
name={getStringOrPlaceholder(values[id].name)}
confirmButtonState="default"
onClose={closeModal}
onConfirm={handleValueDelete}
2019-12-06 17:11:46 +00:00
/>
<AttributeValueEditDialog
attributeValue={values[params.id]}
2019-12-06 17:11:46 +00:00
confirmButtonState="default"
disabled={false}
errors={valueErrors}
open={params.action === "edit-value"}
2019-12-06 17:11:46 +00:00
onClose={closeModal}
onSubmit={handleValueUpdate}
2019-12-06 17:11:46 +00:00
/>
</>
)}
</>
2019-08-09 10:17:04 +00:00
);
};
AttributeDetails.displayName = "AttributeDetails";
export default AttributeDetails;