118 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
						|
import { Button, LoadingOverlay, Modal, ModalProps, NumberInput, TextInput } from '@mantine/core';
 | 
						|
import { useForm, zodResolver } from '@mantine/form';
 | 
						|
import _ from 'lodash';
 | 
						|
import { useEffect, useRef, useState } from 'react';
 | 
						|
import { z } from 'zod';
 | 
						|
import { createBid, updateBid } from '../../apis/bid';
 | 
						|
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
						|
import { IBid } from '../../system/type';
 | 
						|
export interface IBidModelProps extends ModalProps {
 | 
						|
    data: IBid | null;
 | 
						|
    onUpdated?: () => void;
 | 
						|
}
 | 
						|
 | 
						|
const schema = {
 | 
						|
    url: z.string({ message: 'Url is required' }).url('Invalid url format'),
 | 
						|
    max_price: z.number({ message: 'Max price is required' }).min(1, 'Max price must be at least 1'),
 | 
						|
    plus_price: z.number().min(0, 'Plus price must be at least 1').optional(),
 | 
						|
    quantity: z.number().min(1, 'Quantity must be at least 1').optional(),
 | 
						|
};
 | 
						|
 | 
						|
export default function BidModal({ data, onUpdated, ...props }: IBidModelProps) {
 | 
						|
    const form = useForm({
 | 
						|
        validate: zodResolver(z.object(schema)),
 | 
						|
    });
 | 
						|
 | 
						|
    const prevData = useRef<IBid | null>(data);
 | 
						|
 | 
						|
    const { setConfirm } = useConfirmStore();
 | 
						|
 | 
						|
    const [loading, setLoading] = useState(false);
 | 
						|
 | 
						|
    const handleSubmit = async (values: typeof form.values) => {
 | 
						|
        if (data) {
 | 
						|
            setConfirm({
 | 
						|
                title: 'Update ?',
 | 
						|
                message: `This product will be update`,
 | 
						|
                handleOk: async () => {
 | 
						|
                    setLoading(true);
 | 
						|
                    const result = await updateBid(values);
 | 
						|
                    setLoading(false);
 | 
						|
 | 
						|
                    if (!result) return;
 | 
						|
 | 
						|
                    props.onClose();
 | 
						|
 | 
						|
                    if (onUpdated) {
 | 
						|
                        onUpdated();
 | 
						|
                    }
 | 
						|
                },
 | 
						|
                okButton: {
 | 
						|
                    color: 'blue',
 | 
						|
                    value: 'Update',
 | 
						|
                },
 | 
						|
            });
 | 
						|
        } else {
 | 
						|
            const { url, max_price, plus_price } = values;
 | 
						|
 | 
						|
            setLoading(true);
 | 
						|
            const result = await createBid({ url, max_price, plus_price } as IBid);
 | 
						|
 | 
						|
            setLoading(false);
 | 
						|
 | 
						|
            if (!result) return;
 | 
						|
 | 
						|
            props.onClose();
 | 
						|
 | 
						|
            if (onUpdated) {
 | 
						|
                onUpdated();
 | 
						|
            }
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    useEffect(() => {
 | 
						|
        form.reset();
 | 
						|
        if (!data) return;
 | 
						|
 | 
						|
        form.setValues(data);
 | 
						|
 | 
						|
        prevData.current = data;
 | 
						|
        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
						|
    }, [data]);
 | 
						|
 | 
						|
    useEffect(() => {
 | 
						|
        if (!props.opened) {
 | 
						|
            form.reset();
 | 
						|
        }
 | 
						|
        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
						|
    }, [props.opened]);
 | 
						|
 | 
						|
    return (
 | 
						|
        <Modal
 | 
						|
            className="relative"
 | 
						|
            classNames={{
 | 
						|
                header: '!flex !item-center !justify-center w-full',
 | 
						|
            }}
 | 
						|
            {...props}
 | 
						|
            size={'xl'}
 | 
						|
            title={<span className="text-xl font-bold">Bid</span>}
 | 
						|
            centered
 | 
						|
        >
 | 
						|
            <form onSubmit={form.onSubmit(handleSubmit)} className="grid grid-cols-2 gap-2.5">
 | 
						|
                {data && data.name && <TextInput className="col-span-2" readOnly={!!data} size="sm" label="Name" value={data.name} />}
 | 
						|
                <TextInput className="col-span-2" readOnly={!!data} size="sm" label="Url" {...form.getInputProps('url')} />
 | 
						|
                <NumberInput className="col-span-2" size="sm" label="Max price" {...form.getInputProps('max_price')} />
 | 
						|
                <NumberInput size="sm" label="Plus price" {...form.getInputProps('plus_price')} />
 | 
						|
                <NumberInput size="sm" label="Quantity" {...form.getInputProps('quantity')} />
 | 
						|
 | 
						|
                <Button disabled={_.isEqual(form.getValues(), prevData.current)} className="col-span-2" type="submit" fullWidth size="sm" mt="md">
 | 
						|
                    {data ? 'Update' : 'Create'}
 | 
						|
                </Button>
 | 
						|
            </form>
 | 
						|
 | 
						|
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
						|
        </Modal>
 | 
						|
    );
 | 
						|
}
 |