feat: upload image on product

This commit is contained in:
2024-05-26 09:27:54 +03:00
parent 1e40e79be1
commit f54d41691c
2 changed files with 57 additions and 14 deletions

View File

@@ -1,6 +1,6 @@
import {Dropzone, DropzoneProps, FileWithPath} from "@mantine/dropzone";
import {FC, useState} from "react";
import {Button, Fieldset, Flex, Group, Image, rem, Text} from "@mantine/core";
import {Button, Fieldset, Flex, Group, Image, Loader, rem, Text} from "@mantine/core";
import {IconPhoto, IconUpload, IconX} from "@tabler/icons-react";
import {omit} from "lodash";
import {BaseFormInputProps} from "../../types/utils.ts";
@@ -20,8 +20,7 @@ const ImageDropzone: FC<Props> = (props: Props) => {
!(typeof props.imageUrlInputProps?.value === 'string' &&
props.imageUrlInputProps.value.trim() !== '')
);
console.log(props.imageUrlInputProps);
console.log(showDropzone);
const [isLoading, setIsLoading] = useState(false);
const restProps = omit(props, ['imageUrl', 'productId', 'imageUrlInputProps']);
const onDrop = (files: FileWithPath[]) => {
if (!props.productId || !props.imageUrlInputProps) return;
@@ -31,6 +30,7 @@ const ImageDropzone: FC<Props> = (props: Props) => {
}
const file = files[0];
// TODO check if file is image
setIsLoading(true);
ProductService.uploadProductImage({
productId: props.productId,
formData: {
@@ -38,19 +38,37 @@ const ImageDropzone: FC<Props> = (props: Props) => {
}
}).then(({ok, message, imageUrl}) => {
notifications.guess(ok, {message});
setIsLoading(false);
if (!ok || !imageUrl) {
setShowDropzone(true);
return;
}
props.imageUrlInputProps?.onChange(imageUrl);
setShowDropzone(false);
}).catch(error => {
notifications.error({message: error.toString()});
setShowDropzone(true);
setIsLoading(false);
});
}
const getBody = () => {
return props.imageUrlInputProps?.value && showDropzone ? (
return props.imageUrlInputProps?.value && !showDropzone ? (
<Image src={props.imageUrlInputProps.value}/>
) : (
<Dropzone
{...restProps}
accept={["image/png",
"image/jpeg",
"image/gif",
"image/bmp",
"image/tiff",
"image/x-icon",
"image/webp",
"image/svg+xml",
"image/heic"]}
multiple={false}
onDrop={onDrop}
@@ -75,25 +93,30 @@ const ImageDropzone: FC<Props> = (props: Props) => {
/>
</Dropzone.Idle>
<div>
<div style={{textAlign: "center"}}>
<Text size="xl" inline>
Drag images here or click to select files
</Text>
<Text size="sm" c="dimmed" inline mt={7}>
Attach as many files as you like, each file should not exceed 5mb
Перенесите изображение или нажмите чтоб выбрать файл
</Text>
</div>
</Group>
</Dropzone>
);
}
return (
<Flex gap={rem(10)} direction={"column"}>
<Fieldset legend={'Изображение'}>
{getBody()}
<Flex
gap={rem(10)}
direction={"column"}
>
<Fieldset
legend={'Изображение'}>
<Flex justify={"center"}>
{isLoading ? <Loader/> : getBody()}
</Flex>
</Fieldset>
{!showDropzone &&
<Button variant={"default"}>Заменить изображение {}</Button>
<Button onClick={() => setShowDropzone(true)} variant={"default"}>Заменить изображение {}</Button>
}
</Flex>
)

View File

@@ -25,3 +25,23 @@ export const getPluralForm = (amount: number, one: string, twoFour: string, many
return many;
}
};
type KeysOf<T> = (keyof T)[];
// Универсальная функция для получения ключей интерфейса
export function getKeys<T extends object>(): KeysOf<T> {
return Object.keys({} as T) as KeysOf<T>;
}
export const IMAGE_MIME_TYPES = [
"image/png",
"image/jpeg",
"image/gif",
"image/bmp",
"image/tiff",
"image/x-icon",
"image/webp",
"image/svg+xml",
"image/heic"
];