122 lines
3.6 KiB
TypeScript
122 lines
3.6 KiB
TypeScript
![]() |
import VerticalSpacer from "@saleor/apps/components/VerticalSpacer";
|
||
|
import { inputTypeMessages } from "@saleor/attributes/components/AttributeDetails/messages";
|
||
|
import { AttributeValueEditDialogFormData } from "@saleor/attributes/utils/data";
|
||
|
import { ColorPicker } from "@saleor/components/ColorPicker";
|
||
|
import FileUploadField from "@saleor/components/FileUploadField";
|
||
|
import { RadioGroupField } from "@saleor/components/RadioGroupField";
|
||
|
import { useFileUploadMutation } from "@saleor/files/mutations";
|
||
|
import { UseFormResult } from "@saleor/hooks/useForm";
|
||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||
|
import { errorMessages } from "@saleor/intl";
|
||
|
import React, { useState } from "react";
|
||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||
|
|
||
|
import { swatchFieldMessages } from "./messages";
|
||
|
import { useStyles } from "./styles";
|
||
|
|
||
|
type AttributeSwatchFieldProps<T> = Pick<
|
||
|
UseFormResult<T>,
|
||
|
"setError" | "set" | "errors" | "clearErrors" | "data"
|
||
|
>;
|
||
|
|
||
|
type SwatchType = "picker" | "image";
|
||
|
|
||
|
const AttributeSwatchField: React.FC<AttributeSwatchFieldProps<
|
||
|
AttributeValueEditDialogFormData
|
||
|
>> = ({ set, ...props }) => {
|
||
|
const { data } = props;
|
||
|
const notify = useNotifier();
|
||
|
const intl = useIntl();
|
||
|
const { formatMessage } = useIntl();
|
||
|
const classes = useStyles();
|
||
|
const [processing, setProcessing] = useState(false);
|
||
|
const [uploadFile] = useFileUploadMutation({});
|
||
|
const [type, setType] = useState<SwatchType>(
|
||
|
data.fileUrl ? "image" : "picker"
|
||
|
);
|
||
|
|
||
|
const handleColorChange = (hex: string) =>
|
||
|
set({ value: hex, fileUrl: undefined, contentType: undefined });
|
||
|
|
||
|
const handleFileUpload = async (file: File) => {
|
||
|
setProcessing(true);
|
||
|
|
||
|
const {
|
||
|
data: { fileUpload }
|
||
|
} = await uploadFile({ variables: { file } });
|
||
|
|
||
|
if (fileUpload.errors?.length) {
|
||
|
notify({
|
||
|
status: "error",
|
||
|
title: intl.formatMessage(errorMessages.imgageUploadErrorTitle),
|
||
|
text: intl.formatMessage(errorMessages.imageUploadErrorText)
|
||
|
});
|
||
|
} else {
|
||
|
set({
|
||
|
fileUrl: fileUpload.uploadedFile.url,
|
||
|
contentType: fileUpload.uploadedFile.contentType,
|
||
|
value: undefined
|
||
|
});
|
||
|
}
|
||
|
|
||
|
setProcessing(false);
|
||
|
};
|
||
|
|
||
|
const handleFileDelete = () =>
|
||
|
set({
|
||
|
fileUrl: undefined,
|
||
|
contentType: undefined,
|
||
|
value: undefined
|
||
|
});
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
<VerticalSpacer spacing={2} />
|
||
|
<RadioGroupField
|
||
|
choices={[
|
||
|
{
|
||
|
label: formatMessage(swatchFieldMessages.picker),
|
||
|
value: "picker"
|
||
|
},
|
||
|
{
|
||
|
label: formatMessage(swatchFieldMessages.image),
|
||
|
value: "image"
|
||
|
}
|
||
|
]}
|
||
|
variant="inline"
|
||
|
label={<FormattedMessage {...inputTypeMessages.swatch} />}
|
||
|
name="swatch"
|
||
|
value={type}
|
||
|
onChange={event => setType(event.target.value)}
|
||
|
data-test="swatch-radio"
|
||
|
/>
|
||
|
{type === "image" ? (
|
||
|
<>
|
||
|
<FileUploadField
|
||
|
disabled={processing}
|
||
|
loading={processing}
|
||
|
file={{ label: null, value: null, file: null }}
|
||
|
onFileUpload={handleFileUpload}
|
||
|
onFileDelete={handleFileDelete}
|
||
|
inputProps={{
|
||
|
accept: "image/*"
|
||
|
}}
|
||
|
/>
|
||
|
|
||
|
{data.fileUrl && (
|
||
|
<div
|
||
|
className={classes.filePreview}
|
||
|
style={{ backgroundImage: `url(${data.fileUrl})` }}
|
||
|
/>
|
||
|
)}
|
||
|
</>
|
||
|
) : (
|
||
|
<ColorPicker {...props} onColorChange={handleColorChange} />
|
||
|
)}
|
||
|
</>
|
||
|
);
|
||
|
};
|
||
|
|
||
|
AttributeSwatchField.displayName = "AttributeSwatchField";
|
||
|
export default AttributeSwatchField;
|