temp image upload
This commit is contained in:
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 ?
|
||||||
|
|||||||
Reference in New Issue
Block a user