staging #6
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
VITE_BASE_URL = 'http://localhost:4000/api/v1/admin/'
 | 
			
		||||
VITE_SOCKET_URL = 'http://localhost:4000'
 | 
			
		||||
| 
						 | 
				
			
			@ -1,10 +1,10 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Badge, Box, Button, Modal, ModalProps, PasswordInput, Text, TextInput, Tooltip } from '@mantine/core';
 | 
			
		||||
import { Badge, Box, Button, LoadingOverlay, Modal, ModalProps, PasswordInput, Text, TextInput, Tooltip } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import { useDisclosure } from '@mantine/hooks';
 | 
			
		||||
import { IconPlus } from '@tabler/icons-react';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { useEffect, useRef } from 'react';
 | 
			
		||||
import { useEffect, useRef, useState } from 'react';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import { createAdmin, updateAdmin } from '../../apis/admin';
 | 
			
		||||
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +40,8 @@ export default function AdminModal({ data, onUpdated, ...props }: IAdminModelPro
 | 
			
		|||
        validate: zodResolver(data ? updateSchema : createSchema),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const [opened, { open, close }] = useDisclosure(false);
 | 
			
		||||
 | 
			
		||||
    const { deletePermission, setPermissions, permissions, basePermission } = usePermissionStore();
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +56,9 @@ export default function AdminModal({ data, onUpdated, ...props }: IAdminModelPro
 | 
			
		|||
                title: 'Update ?',
 | 
			
		||||
                message: `This account will be update`,
 | 
			
		||||
                handleOk: async () => {
 | 
			
		||||
                    setLoading(true);
 | 
			
		||||
                    const result = await updateAdmin(values);
 | 
			
		||||
                    setLoading(false);
 | 
			
		||||
 | 
			
		||||
                    if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +76,10 @@ export default function AdminModal({ data, onUpdated, ...props }: IAdminModelPro
 | 
			
		|||
        } else {
 | 
			
		||||
            const { confirmPassword, ...newValues } = values;
 | 
			
		||||
 | 
			
		||||
            setLoading(true);
 | 
			
		||||
 | 
			
		||||
            const result = await createAdmin(newValues as Omit<IAdmin, 'id' | 'created_at' | 'updated_at' | 'is_system_account'>);
 | 
			
		||||
            setLoading(false);
 | 
			
		||||
 | 
			
		||||
            if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +117,7 @@ export default function AdminModal({ data, onUpdated, ...props }: IAdminModelPro
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal
 | 
			
		||||
            className="relative"
 | 
			
		||||
            classNames={{
 | 
			
		||||
                header: '!flex !item-center !justify-center w-full',
 | 
			
		||||
            }}
 | 
			
		||||
| 
						 | 
				
			
			@ -160,6 +168,8 @@ export default function AdminModal({ data, onUpdated, ...props }: IAdminModelPro
 | 
			
		|||
            </form>
 | 
			
		||||
 | 
			
		||||
            <PermissionDrawer opened={opened} onClose={close} />
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Button, Modal, ModalProps, PasswordInput } from '@mantine/core';
 | 
			
		||||
import { Button, LoadingOverlay, Modal, ModalProps, PasswordInput } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import { useEffect } from 'react';
 | 
			
		||||
import { useEffect, useState } from 'react';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import { grantNewPasswordAdmin } from '../../apis/admin';
 | 
			
		||||
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +26,8 @@ export default function GrantNewPasswordModal({ data, onUpdated, ...props }: IAd
 | 
			
		|||
        validate: zodResolver(schema),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const { setConfirm } = useConfirmStore();
 | 
			
		||||
 | 
			
		||||
    const handleSubmit = async (values: typeof form.values) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,10 +36,12 @@ export default function GrantNewPasswordModal({ data, onUpdated, ...props }: IAd
 | 
			
		|||
                title: 'Update ?',
 | 
			
		||||
                message: `This account will be update`,
 | 
			
		||||
                handleOk: async () => {
 | 
			
		||||
                    setLoading(true);
 | 
			
		||||
                    const result = await grantNewPasswordAdmin({
 | 
			
		||||
                        id: data.id,
 | 
			
		||||
                        password: values.password,
 | 
			
		||||
                    });
 | 
			
		||||
                    setLoading(false);
 | 
			
		||||
 | 
			
		||||
                    if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +77,7 @@ export default function GrantNewPasswordModal({ data, onUpdated, ...props }: IAd
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal
 | 
			
		||||
            className="relative"
 | 
			
		||||
            classNames={{
 | 
			
		||||
                header: '!flex !item-center !justify-center w-full',
 | 
			
		||||
            }}
 | 
			
		||||
| 
						 | 
				
			
			@ -89,6 +94,8 @@ export default function GrantNewPasswordModal({ data, onUpdated, ...props }: IAd
 | 
			
		|||
                    {'Grant'}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </form>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Button, Modal, ModalProps, NumberInput, TextInput } from '@mantine/core';
 | 
			
		||||
import { Button, LoadingOverlay, Modal, ModalProps, NumberInput, TextInput } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { useEffect, useRef } from 'react';
 | 
			
		||||
import { useEffect, useRef, useState } from 'react';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import { createBid, updateBid } from '../../apis/bid';
 | 
			
		||||
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
			
		||||
| 
						 | 
				
			
			@ -28,13 +28,17 @@ export default function BidModal({ data, onUpdated, ...props }: IBidModelProps)
 | 
			
		|||
 | 
			
		||||
    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;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +56,11 @@ export default function BidModal({ data, onUpdated, ...props }: IBidModelProps)
 | 
			
		|||
        } 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();
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +90,7 @@ export default function BidModal({ data, onUpdated, ...props }: IBidModelProps)
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal
 | 
			
		||||
            className="relative"
 | 
			
		||||
            classNames={{
 | 
			
		||||
                header: '!flex !item-center !justify-center w-full',
 | 
			
		||||
            }}
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +110,8 @@ export default function BidModal({ data, onUpdated, ...props }: IBidModelProps)
 | 
			
		|||
                    {data ? 'Update' : 'Create'}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </form>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,5 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Modal, ModalProps, Table } from '@mantine/core';
 | 
			
		||||
import { LoadingOverlay, Modal, ModalProps, Table } from '@mantine/core';
 | 
			
		||||
import { useCallback, useEffect, useMemo, useState } from 'react';
 | 
			
		||||
import { getDetailBidHistories } from '../../apis/bid-histories';
 | 
			
		||||
import { extractNumber } from '../../lib/table/ultils';
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,8 @@ export interface IShowHistoriesBidGraysApiModalProps extends ModalProps {
 | 
			
		|||
export default function ShowHistoriesBidGraysApiModal({ data, onUpdated, ...props }: IShowHistoriesBidGraysApiModalProps) {
 | 
			
		||||
    const [histories, setHistories] = useState<Record<string, string>[]>([]);
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const rows = useMemo(() => {
 | 
			
		||||
        return histories.map((element) => (
 | 
			
		||||
            <Table.Tr key={element.LotId}>
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +35,9 @@ export default function ShowHistoriesBidGraysApiModal({ data, onUpdated, ...prop
 | 
			
		|||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        setLoading(true);
 | 
			
		||||
        const response = await getDetailBidHistories(data?.lot_id);
 | 
			
		||||
        setLoading(false);
 | 
			
		||||
 | 
			
		||||
        if (response.data && response.data) {
 | 
			
		||||
            setHistories(response.data);
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +49,7 @@ export default function ShowHistoriesBidGraysApiModal({ data, onUpdated, ...prop
 | 
			
		|||
    }, [handleCallApi]);
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal {...props} size="xl" title={<span className="text-xl font-bold">BIDDING HISTORY</span>} centered>
 | 
			
		||||
        <Modal className="relative" {...props} size="xl" title={<span className="text-xl font-bold">BIDDING HISTORY</span>} centered>
 | 
			
		||||
            <Table striped highlightOnHover withTableBorder withColumnBorders>
 | 
			
		||||
                <Table.Thead>
 | 
			
		||||
                    <Table.Tr>
 | 
			
		||||
| 
						 | 
				
			
			@ -68,6 +72,8 @@ export default function ShowHistoriesBidGraysApiModal({ data, onUpdated, ...prop
 | 
			
		|||
                    )}
 | 
			
		||||
                </Table.Tbody>
 | 
			
		||||
            </Table>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
import { Avatar, Button, Menu, Modal, PasswordInput } from '@mantine/core';
 | 
			
		||||
import { Avatar, Button, LoadingOverlay, Menu, Modal, PasswordInput } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import { useDisclosure } from '@mantine/hooks';
 | 
			
		||||
import { IconLogout, IconSettings, IconUser } from '@tabler/icons-react';
 | 
			
		||||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import { z } from 'zod';
 | 
			
		|||
import { changePassword, logout } from '../apis/auth';
 | 
			
		||||
import { useConfirmStore } from '../lib/zustand/use-confirm';
 | 
			
		||||
import Links from '../system/links';
 | 
			
		||||
import { useState } from 'react';
 | 
			
		||||
 | 
			
		||||
const schema = z
 | 
			
		||||
    .object({
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +25,8 @@ export default function UserMenu() {
 | 
			
		|||
 | 
			
		||||
    const { setConfirm } = useConfirmStore();
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const navigate = useNavigate();
 | 
			
		||||
    const form = useForm({
 | 
			
		||||
        initialValues: {
 | 
			
		||||
| 
						 | 
				
			
			@ -59,11 +62,14 @@ export default function UserMenu() {
 | 
			
		|||
            message: 'This account will change password !',
 | 
			
		||||
            okButton: { value: 'Sure' },
 | 
			
		||||
            handleOk: async () => {
 | 
			
		||||
                setLoading(true);
 | 
			
		||||
                const data = await changePassword({
 | 
			
		||||
                    newPassword: values.newPassword,
 | 
			
		||||
                    password: values.currentPassword,
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                setLoading(false);
 | 
			
		||||
 | 
			
		||||
                if (data && data.data) {
 | 
			
		||||
                    navigate(Links.LOGIN);
 | 
			
		||||
                    close();
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +101,7 @@ export default function UserMenu() {
 | 
			
		|||
                </Menu.Dropdown>
 | 
			
		||||
            </Menu>
 | 
			
		||||
 | 
			
		||||
            <Modal opened={opened} onClose={close} title="Change password" centered>
 | 
			
		||||
            <Modal className="relative" opened={opened} onClose={close} title="Change password" centered>
 | 
			
		||||
                <form onSubmit={form.onSubmit(handleSubmit)} className="flex flex-col gap-2.5">
 | 
			
		||||
                    <PasswordInput size="sm" label="Current password" {...form.getInputProps('currentPassword')} />
 | 
			
		||||
                    <PasswordInput size="sm" label="New password" {...form.getInputProps('newPassword')} />
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +110,8 @@ export default function UserMenu() {
 | 
			
		|||
                        Change
 | 
			
		||||
                    </Button>
 | 
			
		||||
                </form>
 | 
			
		||||
 | 
			
		||||
                <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
            </Modal>
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Button, Modal, ModalProps, PasswordInput, TextInput } from '@mantine/core';
 | 
			
		||||
import { Button, LoadingOverlay, Modal, ModalProps, PasswordInput, TextInput } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { useEffect, useRef } from 'react';
 | 
			
		||||
import { useEffect, useRef, useState } from 'react';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import { updateWebBid } from '../../apis/web-bid';
 | 
			
		||||
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,8 @@ export default function WebAccountModal({ data, onUpdated, ...props }: IWebBidMo
 | 
			
		|||
        validate: zodResolver(schema),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const prevData = useRef<IWebBid | null>(data);
 | 
			
		||||
 | 
			
		||||
    const { setConfirm } = useConfirmStore();
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +34,9 @@ export default function WebAccountModal({ data, onUpdated, ...props }: IWebBidMo
 | 
			
		|||
                title: 'Update ?',
 | 
			
		||||
                message: `This account will be update`,
 | 
			
		||||
                handleOk: async () => {
 | 
			
		||||
                    setLoading(true);
 | 
			
		||||
                    const result = await updateWebBid(values);
 | 
			
		||||
                    setLoading(false);
 | 
			
		||||
 | 
			
		||||
                    if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +52,9 @@ export default function WebAccountModal({ data, onUpdated, ...props }: IWebBidMo
 | 
			
		|||
                },
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            setLoading(true);
 | 
			
		||||
            const result = await updateWebBid(values);
 | 
			
		||||
            setLoading(false);
 | 
			
		||||
 | 
			
		||||
            if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +85,7 @@ export default function WebAccountModal({ data, onUpdated, ...props }: IWebBidMo
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal
 | 
			
		||||
            className="relative"
 | 
			
		||||
            classNames={{
 | 
			
		||||
                header: '!flex !item-center !justify-center w-full',
 | 
			
		||||
            }}
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +102,8 @@ export default function WebAccountModal({ data, onUpdated, ...props }: IWebBidMo
 | 
			
		|||
                    {data ? 'Update' : 'Create'}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </form>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
			
		||||
import { Button, Modal, ModalProps, TextInput } from '@mantine/core';
 | 
			
		||||
import { Button, LoadingOverlay, Modal, ModalProps, TextInput } from '@mantine/core';
 | 
			
		||||
import { useForm, zodResolver } from '@mantine/form';
 | 
			
		||||
import _ from 'lodash';
 | 
			
		||||
import { useEffect, useRef } from 'react';
 | 
			
		||||
import { useEffect, useRef, useState } from 'react';
 | 
			
		||||
import { z } from 'zod';
 | 
			
		||||
import { createWebBid, updateWebBid } from '../../apis/web-bid';
 | 
			
		||||
import { useConfirmStore } from '../../lib/zustand/use-confirm';
 | 
			
		||||
| 
						 | 
				
			
			@ -22,6 +22,8 @@ export default function WebBidModal({ data, onUpdated, ...props }: IWebBidModelP
 | 
			
		|||
        validate: zodResolver(z.object(schema)),
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const [loading, setLoading] = useState(false);
 | 
			
		||||
 | 
			
		||||
    const prevData = useRef<IWebBid | null>(data);
 | 
			
		||||
 | 
			
		||||
    const { setConfirm } = useConfirmStore();
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +34,9 @@ export default function WebBidModal({ data, onUpdated, ...props }: IWebBidModelP
 | 
			
		|||
                title: 'Update ?',
 | 
			
		||||
                message: `This web will be update`,
 | 
			
		||||
                handleOk: async () => {
 | 
			
		||||
                    setLoading(true);
 | 
			
		||||
                    const result = await updateWebBid(values);
 | 
			
		||||
                    setLoading(false);
 | 
			
		||||
 | 
			
		||||
                    if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +54,9 @@ export default function WebBidModal({ data, onUpdated, ...props }: IWebBidModelP
 | 
			
		|||
        } else {
 | 
			
		||||
            const { url, origin_url } = values;
 | 
			
		||||
 | 
			
		||||
            setLoading(true);
 | 
			
		||||
            const result = await createWebBid({ url, origin_url } as IWebBid);
 | 
			
		||||
            setLoading(false);
 | 
			
		||||
 | 
			
		||||
            if (!result) return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +94,7 @@ export default function WebBidModal({ data, onUpdated, ...props }: IWebBidModelP
 | 
			
		|||
 | 
			
		||||
    return (
 | 
			
		||||
        <Modal
 | 
			
		||||
            className="relative"
 | 
			
		||||
            classNames={{
 | 
			
		||||
                header: '!flex !item-center !justify-center w-full',
 | 
			
		||||
            }}
 | 
			
		||||
| 
						 | 
				
			
			@ -104,6 +111,8 @@ export default function WebBidModal({ data, onUpdated, ...props }: IWebBidModelP
 | 
			
		|||
                    {data ? 'Update' : 'Create'}
 | 
			
		||||
                </Button>
 | 
			
		||||
            </form>
 | 
			
		||||
 | 
			
		||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
			
		||||
        </Modal>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
DB_HOST=127.0.0.1
 | 
			
		||||
# DB_HOST=127.0.0.1
 | 
			
		||||
DB_USERNAME=root
 | 
			
		||||
DB_PASSWORD=123
 | 
			
		||||
 | 
			
		||||
ENVIRONMENT='dev'
 | 
			
		||||
 | 
			
		||||
DB_PORT=3306
 | 
			
		||||
DB_NAME=auto-bids
 | 
			
		||||
 | 
			
		||||
PORT = 4000
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
APP_PATH = 'http://localhost:4000'
 | 
			
		||||
 | 
			
		||||
CORS = "http://localhost:5173, http://localhost:3000"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
SECRET_KEY = "kgmwljwekqiq25232mdmsgnekwhlwekmglkwjqjwqw"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# DEV GROUP 
 | 
			
		||||
TELEGRAM_BOT_TOKEN = "7963294152:AAE8b9AbsyLYzpeJbUMIcelVWlCBN5mLJ2o"
 | 
			
		||||
CHAT_ID = "-1002593407119"
 | 
			
		||||
 | 
			
		||||
# Bid histories GROUP
 | 
			
		||||
# TELEGRAM_BOT_TOKEN = "7533631751:AAEfE7Ei015U1sSsYPSAYwbYXWFl5D7y_18"
 | 
			
		||||
# CHAT_ID = "-1002535794248"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2,6 +2,11 @@ import { MigrationInterface, QueryRunner } from 'typeorm';
 | 
			
		|||
 | 
			
		||||
export class CreateAdminTable1742778498009 implements MigrationInterface {
 | 
			
		||||
  public async up(queryRunner: QueryRunner): Promise<void> {
 | 
			
		||||
    // {
 | 
			
		||||
    //     'username': 'admin',
 | 
			
		||||
    //     'password': 'Admin@123'
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    await queryRunner.query(`
 | 
			
		||||
            INSERT INTO admins (email, username, password, is_system_account) VALUES 
 | 
			
		||||
            ('admin@gmail.com', 'admin', '$2b$10$eF7K4Msw32e5ZC2cU78KgOqxMJygQcPDt5xXZP29inBBIV9KEsoyO', 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,9 @@ export default class Admin extends Timestamp {
 | 
			
		|||
  @Column({ type: 'boolean', default: false })
 | 
			
		||||
  is_system_account: boolean;
 | 
			
		||||
 | 
			
		||||
  @ManyToMany(() => Permission, (permission) => permission.admins)
 | 
			
		||||
  @ManyToMany(() => Permission, (permission) => permission.admins, {
 | 
			
		||||
    cascade: true,
 | 
			
		||||
    onDelete: 'CASCADE',
 | 
			
		||||
  })
 | 
			
		||||
  permissions: Permission[];
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
ENVIRONMENT = 'prod'
 | 
			
		||||
SOCKET_URL = 'http://localhost:4000'
 | 
			
		||||
BASE_URL = 'http://localhost:4000/api/v1/'
 | 
			
		||||
| 
						 | 
				
			
			@ -40,9 +40,6 @@ lerna-debug.log*
 | 
			
		|||
 | 
			
		||||
# dotenv environment variable files
 | 
			
		||||
.env
 | 
			
		||||
.env.development.local
 | 
			
		||||
.env.test.local
 | 
			
		||||
.env.production.local
 | 
			
		||||
.env.local
 | 
			
		||||
 | 
			
		||||
# temp directory
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,19 +5,32 @@ import StealthPlugin from 'puppeteer-extra-plugin-stealth';
 | 
			
		|||
 | 
			
		||||
puppeteer.use(StealthPlugin());
 | 
			
		||||
const browser = await puppeteer.launch({
 | 
			
		||||
    headless: process.env.ENVIRONMENT === 'prod' ? true : false,
 | 
			
		||||
    headless: process.env.ENVIRONMENT === 'prod' ? 'new' : false,
 | 
			
		||||
    // userDataDir: CONSTANTS.PROFILE_PATH, // Thư mục lưu profile
 | 
			
		||||
    timeout: 60000,
 | 
			
		||||
    args: [
 | 
			
		||||
        '--no-sandbox',
 | 
			
		||||
        '--disable-setuid-sandbox',
 | 
			
		||||
        '--disable-backgrounding-occluded-windows',
 | 
			
		||||
        '--disable-renderer-backgrounding',
 | 
			
		||||
        '--disable-ipc-flooding-protection',
 | 
			
		||||
        '--disable-features=CalculateNativeWinOcclusion,AudioServiceOutOfProcess',
 | 
			
		||||
        '--disable-background-timer-throttling',
 | 
			
		||||
        '--disable-dev-shm-usage',
 | 
			
		||||
        '--disable-gpu',
 | 
			
		||||
        '--disable-software-rasterizer',
 | 
			
		||||
        '--disable-background-networking',
 | 
			
		||||
        '--disable-sync',
 | 
			
		||||
        '--mute-audio',
 | 
			
		||||
        '--no-first-run',
 | 
			
		||||
        '--no-default-browser-check',
 | 
			
		||||
        '--ignore-certificate-errors',
 | 
			
		||||
        '--start-maximized',
 | 
			
		||||
        '--disable-site-isolation-trials', // Tắt sandbox riêng cho từng site
 | 
			
		||||
        '--memory-pressure-off', // Tắt cơ chế bảo vệ bộ nhớ
 | 
			
		||||
        '--disk-cache-size=0', // Không dùng cache để giảm bộ nhớ
 | 
			
		||||
        '--enable-low-end-device-mode', // Kích hoạt chế độ tiết kiệm RAM
 | 
			
		||||
        '--disable-best-effort-tasks', // Tắt tác vụ không quan trọng
 | 
			
		||||
        '--disable-accelerated-2d-canvas', // Không dùng GPU để vẽ canvas
 | 
			
		||||
        '--disable-threaded-animation', // Giảm animation chạy trên nhiều thread
 | 
			
		||||
        '--disable-threaded-scrolling', // Tắt cuộn trang đa luồng
 | 
			
		||||
        '--disable-logging', // Tắt log debug
 | 
			
		||||
        '--blink-settings=imagesEnabled=false', // Không tải hình ảnh
 | 
			
		||||
    ],
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue