temp image upload

This commit is contained in:
2024-05-25 11:35:24 +03:00
parent f41999dfbc
commit 1e40e79be1
4 changed files with 105 additions and 49 deletions

View File

@@ -14,5 +14,6 @@ export type ProductCreateRequest = {
composition?: (string | null); composition?: (string | null);
size?: (string | null); size?: (string | null);
additionalInfo?: (string | null); additionalInfo?: (string | null);
imageUrl?: (string | null);
}; };

View File

@@ -14,6 +14,7 @@ export type ProductSchema = {
composition?: (string | null); composition?: (string | null);
size?: (string | null); size?: (string | null);
additionalInfo?: (string | null); additionalInfo?: (string | null);
imageUrl?: (string | null);
id: number; id: number;
}; };

View File

@@ -1,53 +1,101 @@
import {Dropzone, DropzoneProps} from "@mantine/dropzone"; import {Dropzone, DropzoneProps, FileWithPath} from "@mantine/dropzone";
import {FC} from "react"; import {FC, useState} from "react";
import {Group, rem, Text} from "@mantine/core"; import {Button, Fieldset, Flex, Group, Image, 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 {notifications} from "../../shared/lib/notifications.ts";
import {ProductService} from "../../client";
type RestProps = { interface RestProps {
imageUrl?: string; imageUrlInputProps?: BaseFormInputProps<string>;
}; productId?: number;
const ALL_PROPERTIES = Object.keys(colDefProperties) as (keyof ColDef)[]; }
type Props = DropzoneProps & RestProps; type Props = Omit<DropzoneProps, 'onDrop'> & RestProps;
const ImageDropzone: FC<Props> = (props: Props) => { const ImageDropzone: FC<Props> = (props: Props) => {
const restProps = omit() const [showDropzone, setShowDropzone] = useState(
return ( !(typeof props.imageUrlInputProps?.value === 'string' &&
<Dropzone props.imageUrlInputProps.value.trim() !== '')
{...props} );
> console.log(props.imageUrlInputProps);
<Group justify="center" gap="xl" style={{pointerEvents: 'none'}}> console.log(showDropzone);
<Dropzone.Accept> const restProps = omit(props, ['imageUrl', 'productId', 'imageUrlInputProps']);
<IconUpload const onDrop = (files: FileWithPath[]) => {
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)'}} if (!props.productId || !props.imageUrlInputProps) return;
stroke={1.5} if (files.length > 1) {
/> notifications.error({message: "Прикрепите одно изображение"});
</Dropzone.Accept> return;
<Dropzone.Reject> }
<IconX const file = files[0];
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-red-6)'}} // TODO check if file is image
stroke={1.5} ProductService.uploadProductImage({
/> productId: props.productId,
</Dropzone.Reject> formData: {
<Dropzone.Idle> upload_file: file
<IconPhoto }
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-dimmed)'}} }).then(({ok, message, imageUrl}) => {
stroke={1.5} notifications.guess(ok, {message});
/> if (!ok || !imageUrl) {
</Dropzone.Idle> return;
}
props.imageUrlInputProps?.onChange(imageUrl);
setShowDropzone(false);
});
}
const getBody = () => {
return props.imageUrlInputProps?.value && showDropzone ? (
<Image src={props.imageUrlInputProps.value}/>
) : (
<Dropzone
{...restProps}
multiple={false}
onDrop={onDrop}
<div> >
<Text size="xl" inline> <Group justify="center" gap="xl" style={{pointerEvents: 'none'}}>
Drag images here or click to select files <Dropzone.Accept>
</Text> <IconUpload
<Text size="sm" c="dimmed" inline mt={7}> style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)'}}
Attach as many files as you like, each file should not exceed 5mb stroke={1.5}
</Text> />
</div> </Dropzone.Accept>
</Group> <Dropzone.Reject>
</Dropzone> <IconX
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-red-6)'}}
stroke={1.5}
/>
</Dropzone.Reject>
<Dropzone.Idle>
<IconPhoto
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-dimmed)'}}
stroke={1.5}
/>
</Dropzone.Idle>
<div>
<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()}
</Fieldset>
{!showDropzone &&
<Button variant={"default"}>Заменить изображение {}</Button>
}
</Flex>
) )
} }

View File

@@ -5,6 +5,7 @@ import {BaseProduct, CreateProductRequest} from "../../types.ts";
import {ProductSchema} from "../../../../client"; import {ProductSchema} from "../../../../client";
import BarcodeTemplateSelect from "../../../../components/Selects/BarcodeTemplateSelect/BarcodeTemplateSelect.tsx"; import BarcodeTemplateSelect from "../../../../components/Selects/BarcodeTemplateSelect/BarcodeTemplateSelect.tsx";
import ImageDropzone from "../../../../components/ImageDropzone/ImageDropzone.tsx"; import ImageDropzone from "../../../../components/ImageDropzone/ImageDropzone.tsx";
import {BaseFormInputProps} from "../../../../types/utils.ts";
type CreateProps = { type CreateProps = {
clientId: number; clientId: number;
@@ -25,12 +26,13 @@ const CreateProductModal = ({
}: ContextModalProps<Props>) => { }: ContextModalProps<Props>) => {
const isEditProps = 'product' in innerProps; const isEditProps = 'product' in innerProps;
const isCreatingProps = 'clientId' in innerProps; const isCreatingProps = 'clientId' in innerProps;
const initialValues = isEditProps ? innerProps.product : { const initialValues: Omit<ProductSchema, 'id'> = isEditProps ? innerProps.product : {
name: '', name: '',
article: '', article: '',
barcodes: [] barcodes: [],
clientId: innerProps.clientId
}; };
const form = useForm({ const form = useForm<Omit<ProductSchema, 'id'>>({
initialValues: initialValues, initialValues: initialValues,
validate: { validate: {
name: (name) => name.trim() !== '' ? null : "Необходимо ввести название товара", name: (name) => name.trim() !== '' ? null : "Необходимо ввести название товара",
@@ -99,11 +101,15 @@ const CreateProductModal = ({
label={"Доп. информация"} label={"Доп. информация"}
{...form.getInputProps('additionalInfo')} /> {...form.getInputProps('additionalInfo')} />
</Fieldset> </Fieldset>
<Fieldset legend={"Изображение"}>
<ImageDropzone onDrop={(data) => { {isEditProps &&
}}/> // <Fieldset legend={"Изображение"}>
</Fieldset> <ImageDropzone
imageUrlInputProps={form.getInputProps('imageUrl') as BaseFormInputProps<string>}
productId={innerProps.product.id}
/>
// </Fieldset>
}
<Flex justify={"flex-end"} mt={rem(5)} gap={rem(10)}> <Flex justify={"flex-end"} mt={rem(5)} gap={rem(10)}>
<Button onClick={() => onCancelClick()} variant={"subtle"}>Отменить</Button> <Button onClick={() => onCancelClick()} variant={"subtle"}>Отменить</Button>
{isEditProps ? {isEditProps ?