temp image upload
This commit is contained in:
@@ -14,5 +14,6 @@ export type ProductCreateRequest = {
|
||||
composition?: (string | null);
|
||||
size?: (string | null);
|
||||
additionalInfo?: (string | null);
|
||||
imageUrl?: (string | null);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export type ProductSchema = {
|
||||
composition?: (string | null);
|
||||
size?: (string | null);
|
||||
additionalInfo?: (string | null);
|
||||
imageUrl?: (string | null);
|
||||
id: number;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,53 +1,101 @@
|
||||
import {Dropzone, DropzoneProps} from "@mantine/dropzone";
|
||||
import {FC} from "react";
|
||||
import {Group, rem, Text} from "@mantine/core";
|
||||
import {Dropzone, DropzoneProps, FileWithPath} from "@mantine/dropzone";
|
||||
import {FC, useState} from "react";
|
||||
import {Button, Fieldset, Flex, Group, Image, rem, Text} from "@mantine/core";
|
||||
import {IconPhoto, IconUpload, IconX} from "@tabler/icons-react";
|
||||
import {omit} from "lodash";
|
||||
import {BaseFormInputProps} from "../../types/utils.ts";
|
||||
import {notifications} from "../../shared/lib/notifications.ts";
|
||||
import {ProductService} from "../../client";
|
||||
|
||||
type RestProps = {
|
||||
imageUrl?: string;
|
||||
};
|
||||
const ALL_PROPERTIES = Object.keys(colDefProperties) as (keyof ColDef)[];
|
||||
interface RestProps {
|
||||
imageUrlInputProps?: BaseFormInputProps<string>;
|
||||
productId?: number;
|
||||
}
|
||||
|
||||
|
||||
type Props = DropzoneProps & RestProps;
|
||||
type Props = Omit<DropzoneProps, 'onDrop'> & RestProps;
|
||||
|
||||
const ImageDropzone: FC<Props> = (props: Props) => {
|
||||
const restProps = omit()
|
||||
return (
|
||||
<Dropzone
|
||||
{...props}
|
||||
>
|
||||
<Group justify="center" gap="xl" style={{pointerEvents: 'none'}}>
|
||||
<Dropzone.Accept>
|
||||
<IconUpload
|
||||
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)'}}
|
||||
stroke={1.5}
|
||||
/>
|
||||
</Dropzone.Accept>
|
||||
<Dropzone.Reject>
|
||||
<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>
|
||||
const [showDropzone, setShowDropzone] = useState(
|
||||
!(typeof props.imageUrlInputProps?.value === 'string' &&
|
||||
props.imageUrlInputProps.value.trim() !== '')
|
||||
);
|
||||
console.log(props.imageUrlInputProps);
|
||||
console.log(showDropzone);
|
||||
const restProps = omit(props, ['imageUrl', 'productId', 'imageUrlInputProps']);
|
||||
const onDrop = (files: FileWithPath[]) => {
|
||||
if (!props.productId || !props.imageUrlInputProps) return;
|
||||
if (files.length > 1) {
|
||||
notifications.error({message: "Прикрепите одно изображение"});
|
||||
return;
|
||||
}
|
||||
const file = files[0];
|
||||
// TODO check if file is image
|
||||
ProductService.uploadProductImage({
|
||||
productId: props.productId,
|
||||
formData: {
|
||||
upload_file: file
|
||||
}
|
||||
}).then(({ok, message, imageUrl}) => {
|
||||
notifications.guess(ok, {message});
|
||||
if (!ok || !imageUrl) {
|
||||
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>
|
||||
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>
|
||||
>
|
||||
<Group justify="center" gap="xl" style={{pointerEvents: 'none'}}>
|
||||
<Dropzone.Accept>
|
||||
<IconUpload
|
||||
style={{width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)'}}
|
||||
stroke={1.5}
|
||||
/>
|
||||
</Dropzone.Accept>
|
||||
<Dropzone.Reject>
|
||||
<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 BarcodeTemplateSelect from "../../../../components/Selects/BarcodeTemplateSelect/BarcodeTemplateSelect.tsx";
|
||||
import ImageDropzone from "../../../../components/ImageDropzone/ImageDropzone.tsx";
|
||||
import {BaseFormInputProps} from "../../../../types/utils.ts";
|
||||
|
||||
type CreateProps = {
|
||||
clientId: number;
|
||||
@@ -25,12 +26,13 @@ const CreateProductModal = ({
|
||||
}: ContextModalProps<Props>) => {
|
||||
const isEditProps = 'product' in innerProps;
|
||||
const isCreatingProps = 'clientId' in innerProps;
|
||||
const initialValues = isEditProps ? innerProps.product : {
|
||||
const initialValues: Omit<ProductSchema, 'id'> = isEditProps ? innerProps.product : {
|
||||
name: '',
|
||||
article: '',
|
||||
barcodes: []
|
||||
barcodes: [],
|
||||
clientId: innerProps.clientId
|
||||
};
|
||||
const form = useForm({
|
||||
const form = useForm<Omit<ProductSchema, 'id'>>({
|
||||
initialValues: initialValues,
|
||||
validate: {
|
||||
name: (name) => name.trim() !== '' ? null : "Необходимо ввести название товара",
|
||||
@@ -99,11 +101,15 @@ const CreateProductModal = ({
|
||||
label={"Доп. информация"}
|
||||
{...form.getInputProps('additionalInfo')} />
|
||||
</Fieldset>
|
||||
<Fieldset legend={"Изображение"}>
|
||||
|
||||
<ImageDropzone onDrop={(data) => {
|
||||
}}/>
|
||||
</Fieldset>
|
||||
{isEditProps &&
|
||||
// <Fieldset legend={"Изображение"}>
|
||||
<ImageDropzone
|
||||
imageUrlInputProps={form.getInputProps('imageUrl') as BaseFormInputProps<string>}
|
||||
productId={innerProps.product.id}
|
||||
/>
|
||||
// </Fieldset>
|
||||
}
|
||||
<Flex justify={"flex-end"} mt={rem(5)} gap={rem(10)}>
|
||||
<Button onClick={() => onCancelClick()} variant={"subtle"}>Отменить</Button>
|
||||
{isEditProps ?
|
||||
|
||||
Reference in New Issue
Block a user