Deploy to production #37
			
				
			
		
		
		
	| 
						 | 
					@ -0,0 +1,22 @@
 | 
				
			||||||
 | 
					import { ActionIcon } from "@mantine/core";
 | 
				
			||||||
 | 
					import { IconTrash } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import { useChoosesStore } from "../../lib/zustand/use-chooses-store";
 | 
				
			||||||
 | 
					import { IBid } from "../../system/type";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IDeleteRowActionProps {
 | 
				
			||||||
 | 
					  onClick?: () => void;
 | 
				
			||||||
 | 
					  data: IBid
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function DeleteRowAction({ data,onClick }: IDeleteRowActionProps) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const {chooses} = useChoosesStore()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <ActionIcon disabled={!chooses.some(item => item.id === data.id)} onClick={onClick} size={"sm"} color="red">
 | 
				
			||||||
 | 
					      <IconTrash size={14} />
 | 
				
			||||||
 | 
					    </ActionIcon>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -6,8 +6,16 @@ import { Socket } from "socket.io-client";
 | 
				
			||||||
import { getImagesWorking } from "../../apis/bid";
 | 
					import { getImagesWorking } from "../../apis/bid";
 | 
				
			||||||
import { useStatusToolStore } from "../../lib/zustand/use-status-tool-store";
 | 
					import { useStatusToolStore } from "../../lib/zustand/use-status-tool-store";
 | 
				
			||||||
import { IBid, IWebBid } from "../../system/type";
 | 
					import { IBid, IWebBid } from "../../system/type";
 | 
				
			||||||
import { cn, extractDomainSmart, findNearestClosingChild, isTimeReached, stringToColor, subtractSeconds } from "../../utils";
 | 
					import {
 | 
				
			||||||
 | 
					  cn,
 | 
				
			||||||
 | 
					  extractDomainSmart,
 | 
				
			||||||
 | 
					  findNearestClosingChild,
 | 
				
			||||||
 | 
					  isTimeReached,
 | 
				
			||||||
 | 
					  stringToColor,
 | 
				
			||||||
 | 
					  subtractSeconds,
 | 
				
			||||||
 | 
					} from "../../utils";
 | 
				
			||||||
import ShowImageModal from "./show-image-modal";
 | 
					import ShowImageModal from "./show-image-modal";
 | 
				
			||||||
 | 
					import { IconExternalLink, IconImageInPicture } from "@tabler/icons-react";
 | 
				
			||||||
export interface IWorkingPageProps {
 | 
					export interface IWorkingPageProps {
 | 
				
			||||||
  data: (IBid | IWebBid) & { type: string };
 | 
					  data: (IBid | IWebBid) & { type: string };
 | 
				
			||||||
  socket: Socket;
 | 
					  socket: Socket;
 | 
				
			||||||
| 
						 | 
					@ -110,9 +118,8 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
  }, []);
 | 
					  }, []);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (!isIBid(data)) {
 | 
				
			||||||
  if(!isIBid(data)){
 | 
					    console.log(data);
 | 
				
			||||||
    console.log(data)
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
| 
						 | 
					@ -144,20 +151,24 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
            <Text className="text-xs tracking-wide">{`Current price: $${data.current_price}`}</Text>
 | 
					            <Text className="text-xs tracking-wide">{`Current price: $${data.current_price}`}</Text>
 | 
				
			||||||
          )}
 | 
					          )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          <Text className="text-sm italic opacity-80">
 | 
					          <Text className="text-sm italic opacity-80">
 | 
				
			||||||
            {moment(lastUpdate).format("HH:mm:ss DD/MM/YYYY")}
 | 
					            {moment(lastUpdate).format("HH:mm:ss DD/MM/YYYY")}
 | 
				
			||||||
          </Text>
 | 
					          </Text>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          {!isIBid(data) && (
 | 
				
			||||||
          {!isIBid(data) && <Tooltip label={'Time to tracking'}><Text>{`TT: ${moment(subtractSeconds(findNearestClosingChild(data)?.close_time || '', data.early_tracking_seconds)).format(
 | 
					            <Tooltip label={"Time to tracking"}>
 | 
				
			||||||
                  "HH:mm:ss DD/MM/YYYY"
 | 
					              <Text>{`TT: ${moment(
 | 
				
			||||||
                )}`}</Text></Tooltip>}
 | 
					                subtractSeconds(
 | 
				
			||||||
 | 
					                  findNearestClosingChild(data)?.close_time || "",
 | 
				
			||||||
 | 
					                  data.early_tracking_seconds
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					              ).format("HH:mm:ss DD/MM/YYYY")}`}</Text>
 | 
				
			||||||
 | 
					            </Tooltip>
 | 
				
			||||||
 | 
					          )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <Box className="flex items-center gap-3">
 | 
					          <Box className="flex items-center gap-3">
 | 
				
			||||||
            {isIBid(data) && (
 | 
					            {isIBid(data) && (
 | 
				
			||||||
              <Tooltip label={'Close time'}>
 | 
					              <Tooltip label={"Close time"}>
 | 
				
			||||||
                <Text
 | 
					                <Text
 | 
				
			||||||
                  style={{ fontSize: "12px" }}
 | 
					                  style={{ fontSize: "12px" }}
 | 
				
			||||||
                  className="tracking-wide"
 | 
					                  className="tracking-wide"
 | 
				
			||||||
| 
						 | 
					@ -174,7 +185,7 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
                  data.web_bid?.early_tracking_seconds || 0
 | 
					                  data.web_bid?.early_tracking_seconds || 0
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
              ) && (
 | 
					              ) && (
 | 
				
			||||||
                <Tooltip label={'Time to tracking'}>
 | 
					                <Tooltip label={"Time to tracking"}>
 | 
				
			||||||
                  <Text
 | 
					                  <Text
 | 
				
			||||||
                    style={{ fontSize: "12px" }}
 | 
					                    style={{ fontSize: "12px" }}
 | 
				
			||||||
                    className="tracking-wide"
 | 
					                    className="tracking-wide"
 | 
				
			||||||
| 
						 | 
					@ -189,6 +200,7 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
          </Box>
 | 
					          </Box>
 | 
				
			||||||
          <Box className="flex items-center gap-4">
 | 
					          <Box className="flex items-center gap-4">
 | 
				
			||||||
            <Button
 | 
					            <Button
 | 
				
			||||||
 | 
					             rightSection={<IconImageInPicture size={14}/>}
 | 
				
			||||||
              size="xs"
 | 
					              size="xs"
 | 
				
			||||||
              color="green"
 | 
					              color="green"
 | 
				
			||||||
              onClick={open}
 | 
					              onClick={open}
 | 
				
			||||||
| 
						 | 
					@ -197,6 +209,7 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
              Show
 | 
					              Show
 | 
				
			||||||
            </Button>
 | 
					            </Button>
 | 
				
			||||||
            <Button
 | 
					            <Button
 | 
				
			||||||
 | 
					              rightSection={<IconExternalLink size={14} />}
 | 
				
			||||||
              target="_blank"
 | 
					              target="_blank"
 | 
				
			||||||
              component="a"
 | 
					              component="a"
 | 
				
			||||||
              size="xs"
 | 
					              size="xs"
 | 
				
			||||||
| 
						 | 
					@ -218,11 +231,15 @@ export default function WorkingPage({ data, socket }: IWorkingPageProps) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <Badge
 | 
					          <Badge
 | 
				
			||||||
            color={stringToColor(
 | 
					            color={stringToColor(
 | 
				
			||||||
              isIBid(data) ? extractDomainSmart(data.web_bid.origin_url) : extractDomainSmart(data.origin_url)
 | 
					              isIBid(data)
 | 
				
			||||||
 | 
					                ? extractDomainSmart(data.web_bid.origin_url)
 | 
				
			||||||
 | 
					                : extractDomainSmart(data.origin_url)
 | 
				
			||||||
            )}
 | 
					            )}
 | 
				
			||||||
            size="xs"
 | 
					            size="xs"
 | 
				
			||||||
          >
 | 
					          >
 | 
				
			||||||
            {isIBid(data) ? extractDomainSmart(data.web_bid.origin_url) : extractDomainSmart(data.origin_url)}
 | 
					            {isIBid(data)
 | 
				
			||||||
 | 
					              ? extractDomainSmart(data.web_bid.origin_url)
 | 
				
			||||||
 | 
					              : extractDomainSmart(data.origin_url)}
 | 
				
			||||||
          </Badge>
 | 
					          </Badge>
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
      </Box>
 | 
					      </Box>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,222 +1,278 @@
 | 
				
			||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
					/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
				
			||||||
import { Box, Button, ComboboxItem, Dialog, Select, SelectProps, Text, TextInput, TextInputProps } from '@mantine/core';
 | 
					import {
 | 
				
			||||||
import { useForm } from '@mantine/form';
 | 
					  Box,
 | 
				
			||||||
import { useDisclosure } from '@mantine/hooks';
 | 
					  Button,
 | 
				
			||||||
import { IconSearch, IconX } from '@tabler/icons-react';
 | 
					  ComboboxItem,
 | 
				
			||||||
import { ReactNode, useCallback, useEffect, useImperativeHandle, useMemo, useState } from 'react';
 | 
					  Dialog,
 | 
				
			||||||
import { IActionData, ITableFilter, TRefTableActionFn } from './type';
 | 
					  Select,
 | 
				
			||||||
import { searchKey } from './ultils';
 | 
					  SelectProps,
 | 
				
			||||||
 | 
					  Text,
 | 
				
			||||||
 | 
					  TextInput,
 | 
				
			||||||
 | 
					  TextInputProps,
 | 
				
			||||||
 | 
					} from "@mantine/core";
 | 
				
			||||||
 | 
					import { useForm } from "@mantine/form";
 | 
				
			||||||
 | 
					import { useDisclosure } from "@mantine/hooks";
 | 
				
			||||||
 | 
					import { IconSearch, IconX } from "@tabler/icons-react";
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  ReactNode,
 | 
				
			||||||
 | 
					  useCallback,
 | 
				
			||||||
 | 
					  useEffect,
 | 
				
			||||||
 | 
					  useImperativeHandle,
 | 
				
			||||||
 | 
					  useMemo,
 | 
				
			||||||
 | 
					  useState,
 | 
				
			||||||
 | 
					} from "react";
 | 
				
			||||||
 | 
					import { IActionData, ITableFilter, TRefTableActionFn } from "./type";
 | 
				
			||||||
 | 
					import { searchKey } from "./ultils";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface ITableActionsProps<R extends Record<string, string | number>> {
 | 
					export interface ITableActionsProps<R extends Record<string, string | number>> {
 | 
				
			||||||
    actions?: IActionData[];
 | 
					  actions?: IActionData[];
 | 
				
			||||||
    chooses?: R[];
 | 
					  chooses?: R[];
 | 
				
			||||||
    showSearch?: boolean;
 | 
					  showSearch?: boolean;
 | 
				
			||||||
    loading?: boolean;
 | 
					  loading?: boolean;
 | 
				
			||||||
    showAction?: boolean;
 | 
					  showAction?: boolean;
 | 
				
			||||||
    initFilter?: ITableFilter<R>[];
 | 
					  initFilter?: ITableFilter<R>[];
 | 
				
			||||||
    searchOptions?: {
 | 
					  searchOptions?: {
 | 
				
			||||||
        props?: TextInputProps;
 | 
					    props?: TextInputProps;
 | 
				
			||||||
        render?: () => ReactNode;
 | 
					    render?: () => ReactNode;
 | 
				
			||||||
    };
 | 
					  };
 | 
				
			||||||
    refAction?: TRefTableActionFn;
 | 
					  refAction?: TRefTableActionFn;
 | 
				
			||||||
    selectProps?: SelectProps;
 | 
					  selectProps?: SelectProps;
 | 
				
			||||||
    onSearch?: (data: ITableFilter<R>[]) => void;
 | 
					  leftActionSession?: ReactNode;
 | 
				
			||||||
    renderComfirm?: (data: IActionData) => ReactNode;
 | 
					  onSearch?: (data: ITableFilter<R>[]) => void;
 | 
				
			||||||
    onCloseComfirm?: () => void;
 | 
					  renderComfirm?: (data: IActionData) => ReactNode;
 | 
				
			||||||
 | 
					  onCloseComfirm?: () => void;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function TableActions<R extends Record<string, string | number>>({
 | 
					export default function TableActions<
 | 
				
			||||||
    showSearch = true,
 | 
					  R extends Record<string, string | number>
 | 
				
			||||||
    showAction = true,
 | 
					>({
 | 
				
			||||||
    loading,
 | 
					  showSearch = true,
 | 
				
			||||||
    searchOptions,
 | 
					  showAction = true,
 | 
				
			||||||
    initFilter,
 | 
					  loading,
 | 
				
			||||||
    selectProps,
 | 
					  searchOptions,
 | 
				
			||||||
    actions,
 | 
					  initFilter,
 | 
				
			||||||
    chooses,
 | 
					  selectProps,
 | 
				
			||||||
    refAction,
 | 
					  actions,
 | 
				
			||||||
    onSearch,
 | 
					  chooses,
 | 
				
			||||||
    renderComfirm,
 | 
					  refAction,
 | 
				
			||||||
    onCloseComfirm,
 | 
					  onSearch,
 | 
				
			||||||
 | 
					  renderComfirm,
 | 
				
			||||||
 | 
					  leftActionSession,
 | 
				
			||||||
 | 
					  onCloseComfirm,
 | 
				
			||||||
}: ITableActionsProps<R>) {
 | 
					}: ITableActionsProps<R>) {
 | 
				
			||||||
    const [opened, { toggle, close }] = useDisclosure(false);
 | 
					  const [opened, { toggle, close }] = useDisclosure(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [action, setAction] = useState<IActionData | null>(null);
 | 
					  const [action, setAction] = useState<IActionData | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [isLoading, setIsLoading] = useState(loading || false);
 | 
					  const [isLoading, setIsLoading] = useState(loading || false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const [selectValue, setSelectValue] = useState<string | null>(null);
 | 
					  const [selectValue, setSelectValue] = useState<string | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const form = useForm<{ [searchKey]: string }>({
 | 
					  const form = useForm<{ [searchKey]: string }>({
 | 
				
			||||||
        initialValues: {
 | 
					    initialValues: {
 | 
				
			||||||
            [searchKey]: '',
 | 
					      [searchKey]: "",
 | 
				
			||||||
        },
 | 
					    },
 | 
				
			||||||
    });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleSubmit = (data: { [searchKey]: string }) => {
 | 
					  const handleSubmit = (data: { [searchKey]: string }) => {
 | 
				
			||||||
        const filter = { type: data[searchKey].trim(), key: searchKey } as ITableFilter<R>;
 | 
					    const filter = {
 | 
				
			||||||
 | 
					      type: data[searchKey].trim(),
 | 
				
			||||||
 | 
					      key: searchKey,
 | 
				
			||||||
 | 
					    } as ITableFilter<R>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (onSearch) {
 | 
					    if (onSearch) {
 | 
				
			||||||
            onSearch(data[searchKey]?.length ? [filter] : []);
 | 
					      onSearch(data[searchKey]?.length ? [filter] : []);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    form.reset();
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleClear = () => {
 | 
				
			||||||
 | 
					    form.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (onSearch) {
 | 
				
			||||||
 | 
					      onSearch([]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleChangeAction = (value: string | null, _option: ComboboxItem) => {
 | 
				
			||||||
 | 
					    setSelectValue(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!actions) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const action = actions.find((action) => String(action.key) === value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!action) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setAction(action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (action.comfirmAction) {
 | 
				
			||||||
 | 
					      toggle();
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      handleCallBack(action.callback);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleCallBack = useCallback(
 | 
				
			||||||
 | 
					    async (callback: (chooses: R[]) => void) => {
 | 
				
			||||||
 | 
					      if (callback.constructor.name === "AsyncFunction") {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					          setIsLoading(true);
 | 
				
			||||||
 | 
					          await callback((chooses || []) as R[]);
 | 
				
			||||||
 | 
					        } finally {
 | 
				
			||||||
 | 
					          setIsLoading(false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        callback((chooses || []) as R[]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        form.reset();
 | 
					      handleClose();
 | 
				
			||||||
    };
 | 
					    },
 | 
				
			||||||
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
 | 
					    [chooses]
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleClear = () => {
 | 
					  const actionDataMemo = useMemo(() => {
 | 
				
			||||||
        form.reset();
 | 
					    const newActions = actions?.reduce((prev, cur) => {
 | 
				
			||||||
 | 
					      prev.push({
 | 
				
			||||||
 | 
					        value: String(cur.key),
 | 
				
			||||||
 | 
					        label: cur.title,
 | 
				
			||||||
 | 
					        disabled: cur?.disabled ? cur.disabled(chooses || []) : false,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      return prev;
 | 
				
			||||||
 | 
					    }, [] as { value: string; label: string; disabled: boolean }[]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (onSearch) {
 | 
					    return newActions;
 | 
				
			||||||
            onSearch([]);
 | 
					  }, [actions, chooses]);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleChangeAction = (value: string | null, _option: ComboboxItem) => {
 | 
					  const handleClose = () => {
 | 
				
			||||||
        setSelectValue(value);
 | 
					    close();
 | 
				
			||||||
 | 
					    setAction(null);
 | 
				
			||||||
 | 
					    setSelectValue(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!actions) return;
 | 
					    if (onCloseComfirm) {
 | 
				
			||||||
 | 
					      onCloseComfirm();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const action = actions.find((action) => String(action.key) === value);
 | 
					  const handleClearAction = () => {
 | 
				
			||||||
 | 
					    setAction(null);
 | 
				
			||||||
 | 
					    setSelectValue(null);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!action) return;
 | 
					  const comfirmViewMemo = useMemo(() => {
 | 
				
			||||||
 | 
					    if (!action || !action.comfirmAction) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        setAction(action);
 | 
					    return renderComfirm ? (
 | 
				
			||||||
 | 
					      renderComfirm(action)
 | 
				
			||||||
        if (action.comfirmAction) {
 | 
					    ) : (
 | 
				
			||||||
            toggle();
 | 
					      <Dialog
 | 
				
			||||||
        } else {
 | 
					        opened={opened}
 | 
				
			||||||
            handleCallBack(action.callback);
 | 
					        withCloseButton
 | 
				
			||||||
        }
 | 
					        onClose={handleClose}
 | 
				
			||||||
    };
 | 
					        size="lg"
 | 
				
			||||||
 | 
					        radius="md"
 | 
				
			||||||
    const handleCallBack = useCallback(
 | 
					      >
 | 
				
			||||||
        async (callback: (chooses: R[]) => void) => {
 | 
					        <Text size="sm" mb="xs" fw={500}>
 | 
				
			||||||
            if (callback.constructor.name === 'AsyncFunction') {
 | 
					          {action?.comfirmOption && action?.comfirmOption(action)?.title
 | 
				
			||||||
                try {
 | 
					            ? action.comfirmOption(action).title
 | 
				
			||||||
                    setIsLoading(true);
 | 
					            : "Are you sure to execute this action"}
 | 
				
			||||||
                    await callback((chooses || []) as R[]);
 | 
					        </Text>
 | 
				
			||||||
                } finally {
 | 
					        <div className="flex items-center justify-end w-full gap-3">
 | 
				
			||||||
                    setIsLoading(false);
 | 
					          <Button
 | 
				
			||||||
                }
 | 
					            size="xs"
 | 
				
			||||||
            } else {
 | 
					            disabled={isLoading}
 | 
				
			||||||
                callback((chooses || []) as R[]);
 | 
					            onClick={() => handleCallBack(action.callback)}
 | 
				
			||||||
            }
 | 
					          >
 | 
				
			||||||
 | 
					            Ok
 | 
				
			||||||
            handleClose();
 | 
					          </Button>
 | 
				
			||||||
        },
 | 
					          <Button
 | 
				
			||||||
        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					            size="xs"
 | 
				
			||||||
        [chooses],
 | 
					            disabled={isLoading}
 | 
				
			||||||
 | 
					            color="red"
 | 
				
			||||||
 | 
					            onClick={handleClose}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            Close
 | 
				
			||||||
 | 
					          </Button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </Dialog>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
 | 
					  }, [action, opened, close, renderComfirm]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const actionDataMemo = useMemo(() => {
 | 
					  useEffect(() => {
 | 
				
			||||||
        const newActions = actions?.reduce((prev, cur) => {
 | 
					    if (!initFilter) return;
 | 
				
			||||||
            prev.push({ value: String(cur.key), label: cur.title, disabled: cur?.disabled ? cur.disabled(chooses || []) : false });
 | 
					 | 
				
			||||||
            return prev;
 | 
					 | 
				
			||||||
        }, [] as { value: string; label: string; disabled: boolean }[]);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return newActions;
 | 
					    const params = initFilter.reduce((prev, cur) => {
 | 
				
			||||||
    }, [actions, chooses]);
 | 
					      if (cur.key === searchKey) {
 | 
				
			||||||
 | 
					        prev[cur.key] = cur.type;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return prev;
 | 
				
			||||||
 | 
					    }, {} as Record<string, string | number>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleClose = () => {
 | 
					    form.setValues(params);
 | 
				
			||||||
        close();
 | 
					    // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
				
			||||||
        setAction(null);
 | 
					  }, [initFilter]);
 | 
				
			||||||
        setSelectValue(null);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (onCloseComfirm) {
 | 
					  useEffect(() => {
 | 
				
			||||||
            onCloseComfirm();
 | 
					    setIsLoading(!!loading);
 | 
				
			||||||
        }
 | 
					  }, [loading]);
 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const handleClearAction = () => {
 | 
					  useImperativeHandle(
 | 
				
			||||||
        setAction(null);
 | 
					    refAction,
 | 
				
			||||||
        setSelectValue(null);
 | 
					    () => {
 | 
				
			||||||
    };
 | 
					      return {
 | 
				
			||||||
 | 
					        setAction,
 | 
				
			||||||
 | 
					        clearAction: handleClearAction,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    []
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const comfirmViewMemo = useMemo(() => {
 | 
					  return (
 | 
				
			||||||
        if (!action || !action.comfirmAction) return;
 | 
					    <Box className="flex justify-between items-center">
 | 
				
			||||||
 | 
					      {showSearch && searchOptions?.render ? (
 | 
				
			||||||
        return renderComfirm ? (
 | 
					        searchOptions.render()
 | 
				
			||||||
            renderComfirm(action)
 | 
					      ) : (
 | 
				
			||||||
        ) : (
 | 
					        <form onSubmit={form.onSubmit(handleSubmit)}>
 | 
				
			||||||
            <Dialog opened={opened} withCloseButton onClose={handleClose} size="lg" radius="md">
 | 
					          <TextInput
 | 
				
			||||||
                <Text size="sm" mb="xs" fw={500}>
 | 
					            {...form.getInputProps(searchKey)}
 | 
				
			||||||
                    {action?.comfirmOption && action?.comfirmOption(action)?.title ? action.comfirmOption(action).title : 'Are you sure to execute this action'}
 | 
					            className="min-w-[260px]"
 | 
				
			||||||
                </Text>
 | 
					            leftSection={<IconSearch size={"14px"} />}
 | 
				
			||||||
                <div className="flex items-center justify-end w-full gap-3">
 | 
					            rightSection={
 | 
				
			||||||
                    <Button size="xs" disabled={isLoading} onClick={() => handleCallBack(action.callback)}>
 | 
					              form.getValues()[searchKey].length ? (
 | 
				
			||||||
                        Ok
 | 
					                <IconX
 | 
				
			||||||
                    </Button>
 | 
					                  onClick={handleClear}
 | 
				
			||||||
                    <Button size="xs" disabled={isLoading} color="red" onClick={handleClose}>
 | 
					                  className="cursor-pointer hover:text-red-400 select-none"
 | 
				
			||||||
                        Close
 | 
					                  size={"14px"}
 | 
				
			||||||
                    </Button>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </Dialog>
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }, [action, opened, close, renderComfirm]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    useEffect(() => {
 | 
					 | 
				
			||||||
        if (!initFilter) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const params = initFilter.reduce((prev, cur) => {
 | 
					 | 
				
			||||||
            if (cur.key === searchKey) {
 | 
					 | 
				
			||||||
                prev[cur.key] = cur.type;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return prev;
 | 
					 | 
				
			||||||
        }, {} as Record<string, string | number>);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        form.setValues(params);
 | 
					 | 
				
			||||||
        // eslint-disable-next-line react-hooks/exhaustive-deps
 | 
					 | 
				
			||||||
    }, [initFilter]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    useEffect(() => {
 | 
					 | 
				
			||||||
        setIsLoading(!!loading);
 | 
					 | 
				
			||||||
    }, [loading]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    useImperativeHandle(
 | 
					 | 
				
			||||||
        refAction,
 | 
					 | 
				
			||||||
        () => {
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
                setAction,
 | 
					 | 
				
			||||||
                clearAction: handleClearAction,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        [],
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        <Box className="flex justify-between items-center">
 | 
					 | 
				
			||||||
            {showSearch && searchOptions?.render ? (
 | 
					 | 
				
			||||||
                searchOptions.render()
 | 
					 | 
				
			||||||
            ) : (
 | 
					 | 
				
			||||||
                <form onSubmit={form.onSubmit(handleSubmit)}>
 | 
					 | 
				
			||||||
                    <TextInput
 | 
					 | 
				
			||||||
                        {...form.getInputProps(searchKey)}
 | 
					 | 
				
			||||||
                        className="min-w-[260px]"
 | 
					 | 
				
			||||||
                        leftSection={<IconSearch size={'14px'} />}
 | 
					 | 
				
			||||||
                        rightSection={
 | 
					 | 
				
			||||||
                            form.getValues()[searchKey].length ? <IconX onClick={handleClear} className="cursor-pointer hover:text-red-400 select-none" size={'14px'} /> : undefined
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        placeholder="Search by keyword"
 | 
					 | 
				
			||||||
                        size="xs"
 | 
					 | 
				
			||||||
                        label={'Search'}
 | 
					 | 
				
			||||||
                        {...searchOptions?.props}
 | 
					 | 
				
			||||||
                    />
 | 
					 | 
				
			||||||
                </form>
 | 
					 | 
				
			||||||
            )}
 | 
					 | 
				
			||||||
            {showAction && (
 | 
					 | 
				
			||||||
                <Select
 | 
					 | 
				
			||||||
                    size="xs"
 | 
					 | 
				
			||||||
                    value={selectValue}
 | 
					 | 
				
			||||||
                    onChange={handleChangeAction}
 | 
					 | 
				
			||||||
                    label="Actions"
 | 
					 | 
				
			||||||
                    placeholder="Pick value"
 | 
					 | 
				
			||||||
                    defaultChecked={false}
 | 
					 | 
				
			||||||
                    data={actionDataMemo}
 | 
					 | 
				
			||||||
                    {...selectProps}
 | 
					 | 
				
			||||||
                />
 | 
					                />
 | 
				
			||||||
            )}
 | 
					              ) : undefined
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            placeholder="Search by keyword"
 | 
				
			||||||
 | 
					            size="xs"
 | 
				
			||||||
 | 
					            label={"Search"}
 | 
				
			||||||
 | 
					            {...searchOptions?.props}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
 | 
					        </form>
 | 
				
			||||||
 | 
					      )}
 | 
				
			||||||
 | 
					      {showAction && (
 | 
				
			||||||
 | 
					        <Box className="flex items-end gap-4">
 | 
				
			||||||
 | 
					          {leftActionSession}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {comfirmViewMemo}
 | 
					          <Select
 | 
				
			||||||
 | 
					            size="xs"
 | 
				
			||||||
 | 
					            value={selectValue}
 | 
				
			||||||
 | 
					            onChange={handleChangeAction}
 | 
				
			||||||
 | 
					            label="Actions"
 | 
				
			||||||
 | 
					            placeholder="Pick value"
 | 
				
			||||||
 | 
					            defaultChecked={false}
 | 
				
			||||||
 | 
					            data={actionDataMemo}
 | 
				
			||||||
 | 
					            {...selectProps}
 | 
				
			||||||
 | 
					          />
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
    );
 | 
					      )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {comfirmViewMemo}
 | 
				
			||||||
 | 
					    </Box>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,18 @@
 | 
				
			||||||
 | 
					// stores/useChooseStore.ts
 | 
				
			||||||
 | 
					import { create } from "zustand";
 | 
				
			||||||
 | 
					import { IBid } from "../../system/type";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface ChoosesStore {
 | 
				
			||||||
 | 
					  chooses: IBid[];
 | 
				
			||||||
 | 
					  setChooses: (items: IBid[]) => void;
 | 
				
			||||||
 | 
					  addChoose: (item: IBid) => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const useChoosesStore = create<ChoosesStore>((set) => ({
 | 
				
			||||||
 | 
					  chooses: [],
 | 
				
			||||||
 | 
					  setChooses: (items) => set({ chooses: items }),
 | 
				
			||||||
 | 
					  addChoose: (item) =>
 | 
				
			||||||
 | 
					    set((state) => ({
 | 
				
			||||||
 | 
					      chooses: [...state.chooses, item],
 | 
				
			||||||
 | 
					    })),
 | 
				
			||||||
 | 
					}));
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,13 @@
 | 
				
			||||||
import { ActionIcon, Anchor, Badge, Box, Menu, Text, Tooltip } from "@mantine/core";
 | 
					import {
 | 
				
			||||||
 | 
					  ActionIcon,
 | 
				
			||||||
 | 
					  Anchor,
 | 
				
			||||||
 | 
					  Badge,
 | 
				
			||||||
 | 
					  Box,
 | 
				
			||||||
 | 
					  Button,
 | 
				
			||||||
 | 
					  Menu,
 | 
				
			||||||
 | 
					  Text,
 | 
				
			||||||
 | 
					  Tooltip,
 | 
				
			||||||
 | 
					} from "@mantine/core";
 | 
				
			||||||
import { useDisclosure } from "@mantine/hooks";
 | 
					import { useDisclosure } from "@mantine/hooks";
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  IconAd,
 | 
					  IconAd,
 | 
				
			||||||
| 
						 | 
					@ -7,7 +16,7 @@ import {
 | 
				
			||||||
  IconHammer,
 | 
					  IconHammer,
 | 
				
			||||||
  IconHistory,
 | 
					  IconHistory,
 | 
				
			||||||
  IconMenu,
 | 
					  IconMenu,
 | 
				
			||||||
  IconTrash
 | 
					  IconPlus
 | 
				
			||||||
} from "@tabler/icons-react";
 | 
					} from "@tabler/icons-react";
 | 
				
			||||||
import _ from "lodash";
 | 
					import _ from "lodash";
 | 
				
			||||||
import { useMemo, useRef, useState } from "react";
 | 
					import { useMemo, useRef, useState } from "react";
 | 
				
			||||||
| 
						 | 
					@ -18,9 +27,11 @@ import {
 | 
				
			||||||
  ShowHistoriesBidPicklesApiModal,
 | 
					  ShowHistoriesBidPicklesApiModal,
 | 
				
			||||||
  ShowHistoriesModal,
 | 
					  ShowHistoriesModal,
 | 
				
			||||||
} from "../components/bid";
 | 
					} from "../components/bid";
 | 
				
			||||||
 | 
					import DeleteRowAction from "../components/bid/delete-row-action";
 | 
				
			||||||
import constants, { haveHistories } from "../constant";
 | 
					import constants, { haveHistories } from "../constant";
 | 
				
			||||||
import Table from "../lib/table/table";
 | 
					import Table from "../lib/table/table";
 | 
				
			||||||
import { IColumn, TRefTableFn } from "../lib/table/type";
 | 
					import { IColumn, TRefTableFn } from "../lib/table/type";
 | 
				
			||||||
 | 
					import { useChoosesStore } from "../lib/zustand/use-chooses-store";
 | 
				
			||||||
import { useConfirmStore } from "../lib/zustand/use-confirm";
 | 
					import { useConfirmStore } from "../lib/zustand/use-confirm";
 | 
				
			||||||
import { mappingStatusColors } from "../system/constants";
 | 
					import { mappingStatusColors } from "../system/constants";
 | 
				
			||||||
import { IBid } from "../system/type";
 | 
					import { IBid } from "../system/type";
 | 
				
			||||||
| 
						 | 
					@ -31,6 +42,8 @@ export default function Bids() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [clickData, setClickData] = useState<IBid | null>(null);
 | 
					  const [clickData, setClickData] = useState<IBid | null>(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const {setChooses} = useChoosesStore()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { setConfirm } = useConfirmStore();
 | 
					  const { setConfirm } = useConfirmStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [openedHistories, historiesModel] = useDisclosure(false);
 | 
					  const [openedHistories, historiesModel] = useDisclosure(false);
 | 
				
			||||||
| 
						 | 
					@ -52,9 +65,16 @@ export default function Bids() {
 | 
				
			||||||
      title: "Name",
 | 
					      title: "Name",
 | 
				
			||||||
      typeFilter: "text",
 | 
					      typeFilter: "text",
 | 
				
			||||||
      renderRow(row) {
 | 
					      renderRow(row) {
 | 
				
			||||||
        
 | 
					        return (
 | 
				
			||||||
 | 
					          <Anchor
 | 
				
			||||||
        return <Anchor className="text-[14px]"  href={row.url} size="sm" style={{color: 'inherit'}}>{row.name}</Anchor>
 | 
					            className="text-[14px]"
 | 
				
			||||||
 | 
					            href={row.url}
 | 
				
			||||||
 | 
					            size="sm"
 | 
				
			||||||
 | 
					            style={{ color: "inherit" }}
 | 
				
			||||||
 | 
					          >
 | 
				
			||||||
 | 
					            {row.name}
 | 
				
			||||||
 | 
					          </Anchor>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -157,7 +177,7 @@ export default function Bids() {
 | 
				
			||||||
  const handleDelete = (bid: IBid) => {
 | 
					  const handleDelete = (bid: IBid) => {
 | 
				
			||||||
    setConfirm({
 | 
					    setConfirm({
 | 
				
			||||||
      title: "Delete ?",
 | 
					      title: "Delete ?",
 | 
				
			||||||
      message: "This bid will be delete",
 | 
					      message: `This bid will be delete: ${bid.name || bid.model}`,
 | 
				
			||||||
      handleOk: async () => {
 | 
					      handleOk: async () => {
 | 
				
			||||||
        await deleteBid(bid);
 | 
					        await deleteBid(bid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -192,7 +212,7 @@ export default function Bids() {
 | 
				
			||||||
  const table = useMemo(() => {
 | 
					  const table = useMemo(() => {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <Table
 | 
					      <Table
 | 
				
			||||||
        
 | 
					        onChooses={setChooses}
 | 
				
			||||||
        tableChildProps={{
 | 
					        tableChildProps={{
 | 
				
			||||||
          trbody: {
 | 
					          trbody: {
 | 
				
			||||||
            className: "cursor-pointer",
 | 
					            className: "cursor-pointer",
 | 
				
			||||||
| 
						 | 
					@ -200,13 +220,13 @@ export default function Bids() {
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
        actionsOptions={{
 | 
					        actionsOptions={{
 | 
				
			||||||
          actions: [
 | 
					          actions: [
 | 
				
			||||||
            {
 | 
					            // {
 | 
				
			||||||
              key: "add",
 | 
					            //   key: "add",
 | 
				
			||||||
              title: "Add",
 | 
					            //   title: "Add",
 | 
				
			||||||
              callback: () => {
 | 
					            //   callback: () => {
 | 
				
			||||||
                bidModal.open();
 | 
					            //     bidModal.open();
 | 
				
			||||||
              },
 | 
					            //   },
 | 
				
			||||||
            },
 | 
					            // },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              key: "delete",
 | 
					              key: "delete",
 | 
				
			||||||
              title: "Delete",
 | 
					              title: "Delete",
 | 
				
			||||||
| 
						 | 
					@ -228,6 +248,9 @@ export default function Bids() {
 | 
				
			||||||
              disabled: (data) => data.length <= 0,
 | 
					              disabled: (data) => data.length <= 0,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
 | 
					          leftActionSession: (
 | 
				
			||||||
 | 
					            <Button onClick={bidModal.open} size="xs" rightSection={<IconPlus size={14}/>}>Add</Button>
 | 
				
			||||||
 | 
					          )
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
        refTableFn={refTableFn}
 | 
					        refTableFn={refTableFn}
 | 
				
			||||||
        striped
 | 
					        striped
 | 
				
			||||||
| 
						 | 
					@ -257,84 +280,88 @@ export default function Bids() {
 | 
				
			||||||
          title: <Box className="w-full text-center">Action</Box>,
 | 
					          title: <Box className="w-full text-center">Action</Box>,
 | 
				
			||||||
          body: (row) => {
 | 
					          body: (row) => {
 | 
				
			||||||
            return (
 | 
					            return (
 | 
				
			||||||
              <Menu shadow="md" width={200}>
 | 
					              <Box className="flex items-center gap-2">
 | 
				
			||||||
                <Menu.Target>
 | 
					                <Menu shadow="md" width={200}>
 | 
				
			||||||
                  <Box
 | 
					                  <Menu.Target>
 | 
				
			||||||
                    onClick={(e) => e.stopPropagation()}
 | 
					                    <Box
 | 
				
			||||||
                    className="flex w-full items-center justify-center"
 | 
					                      onClick={(e) => e.stopPropagation()}
 | 
				
			||||||
                  >
 | 
					                      className="flex w-full items-center justify-center"
 | 
				
			||||||
                    <ActionIcon size="sm" variant="light">
 | 
					                    >
 | 
				
			||||||
                      <IconMenu size={14} />
 | 
					                      <ActionIcon size="sm" variant="light">
 | 
				
			||||||
                    </ActionIcon>
 | 
					                        <IconMenu size={14} />
 | 
				
			||||||
                  </Box>
 | 
					                      </ActionIcon>
 | 
				
			||||||
                </Menu.Target>
 | 
					                    </Box>
 | 
				
			||||||
 | 
					                  </Menu.Target>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                <Menu.Dropdown onClick={(e) => e.stopPropagation()}>
 | 
					                  <Menu.Dropdown onClick={(e) => e.stopPropagation()}>
 | 
				
			||||||
                  <Menu.Item
 | 
					 | 
				
			||||||
                    onClick={() => {
 | 
					 | 
				
			||||||
                      setClickData(row);
 | 
					 | 
				
			||||||
                      bidModal.open();
 | 
					 | 
				
			||||||
                    }}
 | 
					 | 
				
			||||||
                    leftSection={<IconEdit size={14} />}
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    Edit
 | 
					 | 
				
			||||||
                  </Menu.Item>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                  <Menu.Item
 | 
					 | 
				
			||||||
                    onClick={() => {
 | 
					 | 
				
			||||||
                      setClickData(row);
 | 
					 | 
				
			||||||
                      historiesModel.open();
 | 
					 | 
				
			||||||
                    }}
 | 
					 | 
				
			||||||
                    leftSection={<IconHistory size={14} />}
 | 
					 | 
				
			||||||
                  >
 | 
					 | 
				
			||||||
                    Histories
 | 
					 | 
				
			||||||
                  </Menu.Item>
 | 
					 | 
				
			||||||
                  {haveHistories.includes(row?.web_bid.origin_url) && (
 | 
					 | 
				
			||||||
                    <Menu.Item
 | 
					                    <Menu.Item
 | 
				
			||||||
                      onClick={() => {
 | 
					                      onClick={() => {
 | 
				
			||||||
                        setClickData(row);
 | 
					                        setClickData(row);
 | 
				
			||||||
                        switch (row.web_bid.origin_url) {
 | 
					                        bidModal.open();
 | 
				
			||||||
                          case constants.grays: {
 | 
					 | 
				
			||||||
                            historiesGraysApiModel.open();
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                          case constants.pickles: {
 | 
					 | 
				
			||||||
                            historiesPicklesApiModel.open();
 | 
					 | 
				
			||||||
                            break;
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                          default: {
 | 
					 | 
				
			||||||
                            historiesGraysApiModel.open();
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                      }}
 | 
					                      }}
 | 
				
			||||||
                      leftSection={<IconHammer size={14} />}
 | 
					                      leftSection={<IconEdit size={14} />}
 | 
				
			||||||
                    >
 | 
					                    >
 | 
				
			||||||
                      Bids
 | 
					                      Edit
 | 
				
			||||||
                    </Menu.Item>
 | 
					                    </Menu.Item>
 | 
				
			||||||
                  )}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  <Menu.Item
 | 
					                    <Menu.Item
 | 
				
			||||||
                    disabled={row.status === "win-bid"}
 | 
					                      onClick={() => {
 | 
				
			||||||
                    onClick={() => handleToggleBid(row)}
 | 
					                        setClickData(row);
 | 
				
			||||||
                    leftSection={
 | 
					                        historiesModel.open();
 | 
				
			||||||
                      row.status === "biding" ? (
 | 
					                      }}
 | 
				
			||||||
                        <IconAdOff size={14} />
 | 
					                      leftSection={<IconHistory size={14} />}
 | 
				
			||||||
                      ) : (
 | 
					                    >
 | 
				
			||||||
                        <IconAd size={14} />
 | 
					                      Histories
 | 
				
			||||||
                      )
 | 
					                    </Menu.Item>
 | 
				
			||||||
                    }
 | 
					                    {haveHistories.includes(row?.web_bid.origin_url) && (
 | 
				
			||||||
                  >
 | 
					                      <Menu.Item
 | 
				
			||||||
                    {row.status === "biding" ? "Disable" : "Enable"}
 | 
					                        onClick={() => {
 | 
				
			||||||
                  </Menu.Item>
 | 
					                          setClickData(row);
 | 
				
			||||||
 | 
					                          switch (row.web_bid.origin_url) {
 | 
				
			||||||
 | 
					                            case constants.grays: {
 | 
				
			||||||
 | 
					                              historiesGraysApiModel.open();
 | 
				
			||||||
 | 
					                              break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            case constants.pickles: {
 | 
				
			||||||
 | 
					                              historiesPicklesApiModel.open();
 | 
				
			||||||
 | 
					                              break;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            default: {
 | 
				
			||||||
 | 
					                              historiesGraysApiModel.open();
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                          }
 | 
				
			||||||
 | 
					                        }}
 | 
				
			||||||
 | 
					                        leftSection={<IconHammer size={14} />}
 | 
				
			||||||
 | 
					                      >
 | 
				
			||||||
 | 
					                        Bids
 | 
				
			||||||
 | 
					                      </Menu.Item>
 | 
				
			||||||
 | 
					                    )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                  <Menu.Item
 | 
					                    <Menu.Item
 | 
				
			||||||
                    onClick={() => handleDelete(row)}
 | 
					                      disabled={row.status === "win-bid"}
 | 
				
			||||||
                    leftSection={<IconTrash color="red" size={14} />}
 | 
					                      onClick={() => handleToggleBid(row)}
 | 
				
			||||||
                  >
 | 
					                      leftSection={
 | 
				
			||||||
                    Delete
 | 
					                        row.status === "biding" ? (
 | 
				
			||||||
                  </Menu.Item>
 | 
					                          <IconAdOff size={14} />
 | 
				
			||||||
                </Menu.Dropdown>
 | 
					                        ) : (
 | 
				
			||||||
              </Menu>
 | 
					                          <IconAd size={14} />
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      {row.status === "biding" ? "Disable" : "Enable"}
 | 
				
			||||||
 | 
					                    </Menu.Item>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    {/* <Menu.Item
 | 
				
			||||||
 | 
					                      onClick={() => handleDelete(row)}
 | 
				
			||||||
 | 
					                      leftSection={<IconTrash color="red" size={14} />}
 | 
				
			||||||
 | 
					                    >
 | 
				
			||||||
 | 
					                      Delete
 | 
				
			||||||
 | 
					                    </Menu.Item> */}
 | 
				
			||||||
 | 
					                  </Menu.Dropdown>
 | 
				
			||||||
 | 
					                </Menu>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                <DeleteRowAction data={row} onClick={() => handleDelete(row)} />
 | 
				
			||||||
 | 
					              </Box>
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,12 +419,6 @@ const trackingLoginStatus = async () => {
 | 
				
			||||||
            login_status,
 | 
					            login_status,
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          console.log(
 | 
					 | 
				
			||||||
            "%cindex.js:422 ehehehehehe",
 | 
					 | 
				
			||||||
            "color: #007acc;",
 | 
					 | 
				
			||||||
            "ehehehehehe"
 | 
					 | 
				
			||||||
          );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          // Set time to update login sau 1 phút
 | 
					          // Set time to update login sau 1 phút
 | 
				
			||||||
          const now = new Date();
 | 
					          const now = new Date();
 | 
				
			||||||
          const oneMinuteLater = new Date(now.getTime() + 60 * 1000);
 | 
					          const oneMinuteLater = new Date(now.getTime() + 60 * 1000);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue