feat: product images upload and display
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
import { FC } from "react";
|
||||
import { DropzoneProps, FileWithPath } from "@mantine/dropzone";
|
||||
import ImageDropzone from "@/components/ui/ImageDropzone/ImageDropzone";
|
||||
import { uploadProductImage } from "@/lib/client";
|
||||
import { notifications } from "@/lib/notifications";
|
||||
import BaseFormInputProps from "@/utils/baseFormInputProps";
|
||||
import useImageDropzone from "./useImageDropzone";
|
||||
@ -31,30 +32,31 @@ const ProductImageDropzone: FC<Props> = ({
|
||||
|
||||
setIsLoading(true);
|
||||
|
||||
// TODO SEND REQUEST
|
||||
uploadProductImage({
|
||||
path: {
|
||||
productId,
|
||||
},
|
||||
body: {
|
||||
upload_file: file,
|
||||
},
|
||||
})
|
||||
.then(({ data }) => {
|
||||
notifications.success({ message: data?.message });
|
||||
setIsLoading(false);
|
||||
|
||||
// ProductService.uploadProductImage({
|
||||
// productId,
|
||||
// formData: {
|
||||
// upload_file: file,
|
||||
// },
|
||||
// })
|
||||
// .then(({ ok, message, imageUrl }) => {
|
||||
// notifications.guess(ok, { message });
|
||||
// setIsLoading(false);
|
||||
//
|
||||
// if (!ok || !imageUrl) {
|
||||
// setShowDropzone(true);
|
||||
// return;
|
||||
// }
|
||||
// imageUrlInputProps?.onChange(imageUrl);
|
||||
// setShowDropzone(false);
|
||||
// })
|
||||
// .catch(error => {
|
||||
// notifications.error({ message: error.toString() });
|
||||
// setShowDropzone(true);
|
||||
// setIsLoading(false);
|
||||
// });
|
||||
if (!data?.imageUrl) {
|
||||
setShowDropzone(true);
|
||||
return;
|
||||
}
|
||||
imageUrlInputProps?.onChange(data?.imageUrl);
|
||||
setShowDropzone(false);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
notifications.error({ message: err.toString() });
|
||||
setShowDropzone(true);
|
||||
setIsLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@ -107,12 +107,12 @@ const ProductView: FC<Props> = ({ dealProduct }) => {
|
||||
<Stack
|
||||
flex={2}
|
||||
gap={"sm"}>
|
||||
{!dealProduct.product && (
|
||||
{dealProduct.product?.imageUrl && (
|
||||
<Image
|
||||
flex={1}
|
||||
radius={"md"}
|
||||
fit={"cover"}
|
||||
// src={dealProduct.product.imageUrl}
|
||||
src={dealProduct.product.imageUrl}
|
||||
/>
|
||||
)}
|
||||
<Title order={3}>{dealProduct.product.name}</Title>
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { Fieldset, Flex, Stack, TagsInput, TextInput } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { ContextModalProps } from "@mantine/modals";
|
||||
@ -14,6 +15,9 @@ import BaseFormModal, {
|
||||
CreateEditFormProps,
|
||||
} from "@/modals/base/BaseFormModal/BaseFormModal";
|
||||
import ProductImageDropzone from "@/modules/dealModularEditorTabs/FulfillmentBase/desktop/components/ProductImageDropzone/ProductImageDropzone";
|
||||
import ProductEditorSegmentedControl, {
|
||||
ProductEditorTab,
|
||||
} from "@/modules/dealModularEditorTabs/FulfillmentBase/shared/modals/ProductEditorModal/components/ProductEditorSegmentedControl";
|
||||
import BaseFormInputProps from "@/utils/baseFormInputProps";
|
||||
|
||||
type Props = CreateEditFormProps<
|
||||
@ -35,6 +39,9 @@ const ProductEditorModal = ({
|
||||
id,
|
||||
innerProps,
|
||||
}: ContextModalProps<Props>) => {
|
||||
const [editorTab, setEditorTab] = useState<ProductEditorTab>(
|
||||
ProductEditorTab.CHARACTERISTICS
|
||||
);
|
||||
const isEditing = "entity" in innerProps;
|
||||
|
||||
const initialValues: ProductForm = isEditing
|
||||
@ -63,94 +70,108 @@ const ProductEditorModal = ({
|
||||
},
|
||||
});
|
||||
|
||||
const characteristicsTab = (
|
||||
<>
|
||||
<Fieldset legend={"Основные характеристики"}>
|
||||
<Stack gap={"xs"}>
|
||||
<TextInput
|
||||
placeholder={"Введите название товара"}
|
||||
label={"Название товара"}
|
||||
{...form.getInputProps("name")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите артикул"}
|
||||
label={"Артикул"}
|
||||
{...form.getInputProps("article")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите складской артикул"}
|
||||
label={"Складской артикул"}
|
||||
{...form.getInputProps("factoryArticle")}
|
||||
/>
|
||||
<BarcodeTemplateSelect
|
||||
placeholder={"Выберите шаблон штрихкода"}
|
||||
label={"Шаблон штрихкода"}
|
||||
{...form.getInputProps("barcodeTemplate")}
|
||||
onChange={template => {
|
||||
form.setFieldValue("barcodeTemplate", template);
|
||||
form.setFieldValue(
|
||||
"barcodeTemplateId",
|
||||
template?.id
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<TagsInput
|
||||
placeholder={
|
||||
!form.values.barcodes?.length
|
||||
? "Добавьте штрихкоды к товару"
|
||||
: ""
|
||||
}
|
||||
label={"Штрихкоды"}
|
||||
{...form.getInputProps("barcodes")}
|
||||
/>
|
||||
</Stack>
|
||||
</Fieldset>
|
||||
<Fieldset legend={"Дополнительные характеристики"}>
|
||||
<Stack gap={"xs"}>
|
||||
<TextInput
|
||||
placeholder={"Введите бренд"}
|
||||
label={"Бренд"}
|
||||
{...form.getInputProps("brand")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите состав"}
|
||||
label={"Состав"}
|
||||
{...form.getInputProps("composition")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите цвет"}
|
||||
label={"Цвет"}
|
||||
{...form.getInputProps("color")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите размер"}
|
||||
label={"Размер"}
|
||||
{...form.getInputProps("size")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите доп. информацию"}
|
||||
label={"Доп. информация"}
|
||||
{...form.getInputProps("additionalInfo")}
|
||||
/>
|
||||
</Stack>
|
||||
</Fieldset>
|
||||
</>
|
||||
);
|
||||
|
||||
const imageTab = isEditing && (
|
||||
<ProductImageDropzone
|
||||
imageUrlInputProps={
|
||||
form.getInputProps("imageUrl") as BaseFormInputProps<string>
|
||||
}
|
||||
productId={innerProps.entity.id}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<BaseFormModal
|
||||
{...innerProps}
|
||||
form={form}
|
||||
closeOnSubmit
|
||||
actionsEnabled={editorTab === ProductEditorTab.CHARACTERISTICS}
|
||||
onClose={() => context.closeContextModal(id)}>
|
||||
<Flex
|
||||
gap={"xs"}
|
||||
direction={"column"}>
|
||||
<Fieldset legend={"Основные характеристики"}>
|
||||
<Stack gap={"xs"}>
|
||||
<TextInput
|
||||
placeholder={"Введите название товара"}
|
||||
label={"Название товара"}
|
||||
{...form.getInputProps("name")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите артикул"}
|
||||
label={"Артикул"}
|
||||
{...form.getInputProps("article")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите складской артикул"}
|
||||
label={"Складской артикул"}
|
||||
{...form.getInputProps("factoryArticle")}
|
||||
/>
|
||||
<BarcodeTemplateSelect
|
||||
placeholder={"Выберите шаблон штрихкода"}
|
||||
label={"Шаблон штрихкода"}
|
||||
{...form.getInputProps("barcodeTemplate")}
|
||||
onChange={template => {
|
||||
form.setFieldValue("barcodeTemplate", template);
|
||||
form.setFieldValue(
|
||||
"barcodeTemplateId",
|
||||
template?.id
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<TagsInput
|
||||
placeholder={
|
||||
!form.values.barcodes?.length
|
||||
? "Добавьте штрихкоды к товару"
|
||||
: ""
|
||||
}
|
||||
label={"Штрихкоды"}
|
||||
{...form.getInputProps("barcodes")}
|
||||
/>
|
||||
</Stack>
|
||||
</Fieldset>
|
||||
<Fieldset legend={"Дополнительные характеристики"}>
|
||||
<Stack gap={"xs"}>
|
||||
<TextInput
|
||||
placeholder={"Введите бренд"}
|
||||
label={"Бренд"}
|
||||
{...form.getInputProps("brand")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите состав"}
|
||||
label={"Состав"}
|
||||
{...form.getInputProps("composition")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите цвет"}
|
||||
label={"Цвет"}
|
||||
{...form.getInputProps("color")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите размер"}
|
||||
label={"Размер"}
|
||||
{...form.getInputProps("size")}
|
||||
/>
|
||||
<TextInput
|
||||
placeholder={"Введите доп. информацию"}
|
||||
label={"Доп. информация"}
|
||||
{...form.getInputProps("additionalInfo")}
|
||||
/>
|
||||
</Stack>
|
||||
</Fieldset>
|
||||
{isEditing && (
|
||||
<ProductImageDropzone
|
||||
imageUrlInputProps={
|
||||
form.getInputProps(
|
||||
"imageUrl"
|
||||
) as BaseFormInputProps<string>
|
||||
}
|
||||
productId={innerProps.entity.id}
|
||||
<ProductEditorSegmentedControl
|
||||
value={editorTab}
|
||||
onChange={setEditorTab}
|
||||
/>
|
||||
)}
|
||||
{editorTab === ProductEditorTab.CHARACTERISTICS
|
||||
? characteristicsTab
|
||||
: imageTab}
|
||||
</Flex>
|
||||
</BaseFormModal>
|
||||
);
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
import { FC } from "react";
|
||||
import BaseSegmentedControl, {
|
||||
BaseSegmentedControlProps,
|
||||
} from "@/components/ui/BaseSegmentedControl/BaseSegmentedControl";
|
||||
|
||||
export enum ProductEditorTab {
|
||||
CHARACTERISTICS,
|
||||
IMAGES,
|
||||
}
|
||||
|
||||
type Props = Omit<BaseSegmentedControlProps<ProductEditorTab>, "data">;
|
||||
|
||||
const data = [
|
||||
{
|
||||
label: "Характеристики",
|
||||
value: ProductEditorTab.CHARACTERISTICS,
|
||||
},
|
||||
{
|
||||
label: "Изображение",
|
||||
value: ProductEditorTab.IMAGES,
|
||||
},
|
||||
];
|
||||
|
||||
const ProductEditorSegmentedControl: FC<Props> = props => (
|
||||
<BaseSegmentedControl
|
||||
data={data}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export default ProductEditorSegmentedControl;
|
||||
Reference in New Issue
Block a user