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

View File

@@ -24,4 +24,24 @@ export const getPluralForm = (amount: number, one: string, twoFour: string, many
default: default:
return 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"
];