Deploy to staging #57
			
				
			
		
		
		
	| 
						 | 
					@ -17,11 +17,13 @@ export default function DeleteRowAction({
 | 
				
			||||||
    setConfirm({
 | 
					    setConfirm({
 | 
				
			||||||
      handleOk: async () => {
 | 
					      handleOk: async () => {
 | 
				
			||||||
        const result = await deletesBid(chooses);
 | 
					        const result = await deletesBid(chooses);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        console.log({ result });
 | 
				
			||||||
        if (!result) return;
 | 
					        if (!result) return;
 | 
				
			||||||
        onDeleted?.();
 | 
					        onDeleted?.();
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      title: 'Delete',
 | 
					      title: "Delete",
 | 
				
			||||||
      message: `This action will remove ${chooses.length} products.`
 | 
					      message: `This action will remove ${chooses.length} products.`,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,2 @@
 | 
				
			||||||
export { default as ShowHistoriesModal } from './show-histories-modal';
 | 
					export { default as ShowHistoriesModal } from "./show-histories-modal";
 | 
				
			||||||
export { default as ShowHistoriesBidGraysApiModal } from './show-histories-bid-grays-api-modal';
 | 
					export { default as BidModal } from "./bid-modal";
 | 
				
			||||||
export { default as ShowHistoriesBidPicklesApiModal } from './show-histories-bid-pickles-api-modal';
 | 
					 | 
				
			||||||
export { default as BidModal } from './bid-modal';
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,71 @@
 | 
				
			||||||
 | 
					/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Table from "../../../lib/table/table";
 | 
				
			||||||
 | 
					import { IColumn } from "../../../lib/table/type";
 | 
				
			||||||
 | 
					import { formatTime } from "../../../utils";
 | 
				
			||||||
 | 
					export interface IGraysHistoriesViewProps {
 | 
				
			||||||
 | 
					  histories: Record<string, string>[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function AllbidsHistoriesView({
 | 
				
			||||||
 | 
					  histories,
 | 
				
			||||||
 | 
					}: IGraysHistoriesViewProps) {
 | 
				
			||||||
 | 
					  type BidHistoryEntry = {
 | 
				
			||||||
 | 
					    row_id: number;
 | 
				
			||||||
 | 
					    date: string; // ISO datetime string
 | 
				
			||||||
 | 
					    amount: number; // Số tiền đặt giá
 | 
				
			||||||
 | 
					    proxyamount: number; // Giá proxy tối đa
 | 
				
			||||||
 | 
					    bidQty: number; // Số lượng
 | 
				
			||||||
 | 
					    flashBuy: boolean; // Mua ngay
 | 
				
			||||||
 | 
					    proxyBid: boolean; // Có phải đấu giá tự động
 | 
				
			||||||
 | 
					    instantBid: boolean; // Đặt giá ngay
 | 
				
			||||||
 | 
					    userName: string; // Tên người dùng
 | 
				
			||||||
 | 
					    bidBidderID: number; // ID người đặt giá
 | 
				
			||||||
 | 
					    $$hashKey?: string; // Khóa nội bộ Angular (không cần thiết, có thể bỏ hoặc để optional)
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const columns: IColumn<BidHistoryEntry>[] = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Username",
 | 
				
			||||||
 | 
					      key: "userName",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Amount",
 | 
				
			||||||
 | 
					      key: "amount",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Proxy amount",
 | 
				
			||||||
 | 
					      key: "proxyamount",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bid Qty",
 | 
				
			||||||
 | 
					      key: "bidQty",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bid at",
 | 
				
			||||||
 | 
					      key: "date",
 | 
				
			||||||
 | 
					      renderRow(row) {
 | 
				
			||||||
 | 
					        return <span>{formatTime(row.date)}</span>;
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Table
 | 
				
			||||||
 | 
					      striped
 | 
				
			||||||
 | 
					      highlightOnHover
 | 
				
			||||||
 | 
					      withTableBorder
 | 
				
			||||||
 | 
					      withColumnBorders
 | 
				
			||||||
 | 
					      styleDefaultHead={{
 | 
				
			||||||
 | 
					        justifyContent: "flex-start",
 | 
				
			||||||
 | 
					        width: "fit-content",
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      showFilter={false}
 | 
				
			||||||
 | 
					      showActions={false}
 | 
				
			||||||
 | 
					      showChooses={false}
 | 
				
			||||||
 | 
					      columns={columns}
 | 
				
			||||||
 | 
					      rowKey="row_id"
 | 
				
			||||||
 | 
					      rows={histories as unknown as BidHistoryEntry[]}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
				
			||||||
 | 
					import { useMemo } from "react";
 | 
				
			||||||
 | 
					import { extractNumber, formatTime } from "../../../utils";
 | 
				
			||||||
 | 
					import Table from "../../../lib/table/table";
 | 
				
			||||||
 | 
					import { IColumn } from "../../../lib/table/type";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGraysHistoriesViewProps {
 | 
				
			||||||
 | 
					  histories: Record<string, string>[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function GraysHistoriesView({
 | 
				
			||||||
 | 
					  histories,
 | 
				
			||||||
 | 
					}: IGraysHistoriesViewProps) {
 | 
				
			||||||
 | 
					  type BidHistoryEntry = {
 | 
				
			||||||
 | 
					    row_id: number;
 | 
				
			||||||
 | 
					    Price: string;
 | 
				
			||||||
 | 
					    Quantity: number;
 | 
				
			||||||
 | 
					    WinningQuantity: number;
 | 
				
			||||||
 | 
					    UserShortAddress: string;
 | 
				
			||||||
 | 
					    UserInitials: string;
 | 
				
			||||||
 | 
					    OriginalDate: string;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const columns: IColumn<BidHistoryEntry>[] = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bidding Details",
 | 
				
			||||||
 | 
					      key: "UserInitials",
 | 
				
			||||||
 | 
					      renderRow(row) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					          <span>{`${row["UserInitials"]} - ${row["UserShortAddress"]}`}</span>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bid Time",
 | 
				
			||||||
 | 
					      key: "OriginalDate",
 | 
				
			||||||
 | 
					      renderRow(row) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					          <span>
 | 
				
			||||||
 | 
					            {formatTime(
 | 
				
			||||||
 | 
					              new Date(extractNumber(row["OriginalDate"]) || 0).toUTCString(),
 | 
				
			||||||
 | 
					              "HH:mm:ss DD/MM/YYYY"
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					          </span>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bid Price",
 | 
				
			||||||
 | 
					      key: "Price",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bid Qty",
 | 
				
			||||||
 | 
					      key: "Quantity",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Win Qty",
 | 
				
			||||||
 | 
					      key: "WinningQuantity",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Table
 | 
				
			||||||
 | 
					      striped
 | 
				
			||||||
 | 
					      highlightOnHover
 | 
				
			||||||
 | 
					      withTableBorder
 | 
				
			||||||
 | 
					      withColumnBorders
 | 
				
			||||||
 | 
					      styleDefaultHead={{
 | 
				
			||||||
 | 
					        justifyContent: "flex-start",
 | 
				
			||||||
 | 
					        width: "fit-content",
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      showFilter={false}
 | 
				
			||||||
 | 
					      showActions={false}
 | 
				
			||||||
 | 
					      showChooses={false}
 | 
				
			||||||
 | 
					      columns={columns}
 | 
				
			||||||
 | 
					      rowKey="row_id"
 | 
				
			||||||
 | 
					      rows={histories as unknown as BidHistoryEntry[]}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,79 @@
 | 
				
			||||||
 | 
					/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
				
			||||||
 | 
					import { useMemo } from "react";
 | 
				
			||||||
 | 
					import { formatTime } from "../../../utils";
 | 
				
			||||||
 | 
					import { IColumn } from "../../../lib/table/type";
 | 
				
			||||||
 | 
					import Table from "../../../lib/table/table";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IGraysHistoriesViewProps {
 | 
				
			||||||
 | 
					  histories: Record<string, string>[];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function PicklesHistoriesView({
 | 
				
			||||||
 | 
					  histories,
 | 
				
			||||||
 | 
					}: IGraysHistoriesViewProps) {
 | 
				
			||||||
 | 
					  // const rows = useMemo(() => {
 | 
				
			||||||
 | 
					  //   return histories.map((element, index) => (
 | 
				
			||||||
 | 
					  //     <Table.Tr key={index}>
 | 
				
			||||||
 | 
					  //       <Table.Td>{element["bidderAnonName"]}</Table.Td>
 | 
				
			||||||
 | 
					  //       <Table.Td>{element["actualBid"]}</Table.Td>
 | 
				
			||||||
 | 
					  //       <Table.Td>
 | 
				
			||||||
 | 
					  //         {formatTime(
 | 
				
			||||||
 | 
					  //           new Date(element["bidTimeInMilliSeconds"]).toUTCString(),
 | 
				
			||||||
 | 
					  //           "HH:mm:ss DD/MM/YYYY"
 | 
				
			||||||
 | 
					  //         )}
 | 
				
			||||||
 | 
					  //       </Table.Td>
 | 
				
			||||||
 | 
					  //     </Table.Tr>
 | 
				
			||||||
 | 
					  //   ));
 | 
				
			||||||
 | 
					  // }, [histories]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  type BidHistoryEntry = {
 | 
				
			||||||
 | 
					    row_id: number;
 | 
				
			||||||
 | 
					    bidderAnonName: string;
 | 
				
			||||||
 | 
					    actualBid: number;
 | 
				
			||||||
 | 
					    bidTimeInMilliSeconds: number;
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const columns: IColumn<BidHistoryEntry>[] = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Bidder name",
 | 
				
			||||||
 | 
					      key: "bidderAnonName",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Actual bid",
 | 
				
			||||||
 | 
					      key: "actualBid",
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      title: "Time",
 | 
				
			||||||
 | 
					      key: "bidTimeInMilliSeconds",
 | 
				
			||||||
 | 
					      renderRow(row) {
 | 
				
			||||||
 | 
					        return (
 | 
				
			||||||
 | 
					          <span>
 | 
				
			||||||
 | 
					            {formatTime(
 | 
				
			||||||
 | 
					              new Date(row["bidTimeInMilliSeconds"]).toUTCString(),
 | 
				
			||||||
 | 
					              "HH:mm:ss DD/MM/YYYY"
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					          </span>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Table
 | 
				
			||||||
 | 
					      striped
 | 
				
			||||||
 | 
					      highlightOnHover
 | 
				
			||||||
 | 
					      withTableBorder
 | 
				
			||||||
 | 
					      withColumnBorders
 | 
				
			||||||
 | 
					      styleDefaultHead={{
 | 
				
			||||||
 | 
					        justifyContent: "flex-start",
 | 
				
			||||||
 | 
					        width: "fit-content",
 | 
				
			||||||
 | 
					      }}
 | 
				
			||||||
 | 
					      showFilter={false}
 | 
				
			||||||
 | 
					      showActions={false}
 | 
				
			||||||
 | 
					      showChooses={false}
 | 
				
			||||||
 | 
					      columns={columns}
 | 
				
			||||||
 | 
					      rowKey="row_id"
 | 
				
			||||||
 | 
					      rows={histories as unknown as BidHistoryEntry[]}
 | 
				
			||||||
 | 
					    />
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,81 @@
 | 
				
			||||||
 | 
					/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
				
			||||||
 | 
					import { LoadingOverlay, Modal, ModalProps } from "@mantine/core";
 | 
				
			||||||
 | 
					import { useCallback, useEffect, useMemo, useState } from "react";
 | 
				
			||||||
 | 
					import { getDetailBidHistories } from "../../../apis/bid-histories";
 | 
				
			||||||
 | 
					import { IBid } from "../../../system/type";
 | 
				
			||||||
 | 
					import GraysHistoriesView from "./grays-histories-view";
 | 
				
			||||||
 | 
					import constants from "../../../constant";
 | 
				
			||||||
 | 
					import PicklesHistoriesView from "./pickles-histories-view";
 | 
				
			||||||
 | 
					import AllbidsHistoriesView from "./allbids-histories-view";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface IShowHistoriesApiModalProps extends ModalProps {
 | 
				
			||||||
 | 
					  data: IBid | null;
 | 
				
			||||||
 | 
					  onUpdated?: () => void;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function ShowHistoriesApiModal({
 | 
				
			||||||
 | 
					  data,
 | 
				
			||||||
 | 
					  onUpdated,
 | 
				
			||||||
 | 
					  ...props
 | 
				
			||||||
 | 
					}: IShowHistoriesApiModalProps) {
 | 
				
			||||||
 | 
					  const [histories, setHistories] = useState<Record<string, string>[]>([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const [loading, setLoading] = useState(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleCallApi = useCallback(async () => {
 | 
				
			||||||
 | 
					    if (!data?.lot_id) {
 | 
				
			||||||
 | 
					      setHistories([]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setLoading(true);
 | 
				
			||||||
 | 
					    const response = await getDetailBidHistories(data?.lot_id);
 | 
				
			||||||
 | 
					    setLoading(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.data && response.data) {
 | 
				
			||||||
 | 
					      const values = (response.data as Record<string, string>[]).map(
 | 
				
			||||||
 | 
					        (item, index) => {
 | 
				
			||||||
 | 
					          return {
 | 
				
			||||||
 | 
					            ...item,
 | 
				
			||||||
 | 
					            row_id: String(index),
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      setHistories(values);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [data]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  useEffect(() => {
 | 
				
			||||||
 | 
					    handleCallApi();
 | 
				
			||||||
 | 
					  }, [handleCallApi]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const generateView = useMemo(() => {
 | 
				
			||||||
 | 
					    switch (data?.web_bid.origin_url) {
 | 
				
			||||||
 | 
					      case constants.grays:
 | 
				
			||||||
 | 
					        return <GraysHistoriesView histories={histories} />;
 | 
				
			||||||
 | 
					      case constants.pickles:
 | 
				
			||||||
 | 
					        return <PicklesHistoriesView histories={histories} />;
 | 
				
			||||||
 | 
					      case constants.allbids:
 | 
				
			||||||
 | 
					        return <AllbidsHistoriesView histories={histories} />;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }, [data?.web_bid.origin_url, histories]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return (
 | 
				
			||||||
 | 
					    <Modal
 | 
				
			||||||
 | 
					      className="relative"
 | 
				
			||||||
 | 
					      {...props}
 | 
				
			||||||
 | 
					      size="xl"
 | 
				
			||||||
 | 
					      title={<span className="text-xl font-bold">BIDDING HISTORY</span>}
 | 
				
			||||||
 | 
					      centered
 | 
				
			||||||
 | 
					    >
 | 
				
			||||||
 | 
					      {generateView}
 | 
				
			||||||
 | 
					      <LoadingOverlay
 | 
				
			||||||
 | 
					        visible={loading}
 | 
				
			||||||
 | 
					        zIndex={1000}
 | 
				
			||||||
 | 
					        overlayProps={{ blur: 2 }}
 | 
				
			||||||
 | 
					      />
 | 
				
			||||||
 | 
					    </Modal>
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,78 +0,0 @@
 | 
				
			||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
 | 
					 | 
				
			||||||
import { LoadingOverlay, Modal, ModalProps, Table } from '@mantine/core';
 | 
					 | 
				
			||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
 | 
					 | 
				
			||||||
import { getDetailBidHistories } from '../../apis/bid-histories';
 | 
					 | 
				
			||||||
import { IBid } from '../../system/type';
 | 
					 | 
				
			||||||
import { extractNumber, formatTime } from '../../utils';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface IShowHistoriesBidGraysApiModalProps extends ModalProps {
 | 
					 | 
				
			||||||
    data: IBid | null;
 | 
					 | 
				
			||||||
    onUpdated?: () => void;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
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, index) => (
 | 
					 | 
				
			||||||
            <Table.Tr key={index}>
 | 
					 | 
				
			||||||
                <Table.Td>{`${element['UserInitials']} - ${element['UserShortAddress']}`}</Table.Td>
 | 
					 | 
				
			||||||
                <Table.Td>{formatTime(new Date(extractNumber(element['OriginalDate']) || 0).toUTCString(), 'HH:mm:ss DD/MM/YYYY')}</Table.Td>
 | 
					 | 
				
			||||||
                <Table.Td>{`AU $${element['Price']}`}</Table.Td>
 | 
					 | 
				
			||||||
                <Table.Td>{`${element['Quantity']}`}</Table.Td>
 | 
					 | 
				
			||||||
                <Table.Td>{`${element['WinningQuantity']}`}</Table.Td>
 | 
					 | 
				
			||||||
            </Table.Tr>
 | 
					 | 
				
			||||||
        ));
 | 
					 | 
				
			||||||
    }, [histories]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const handleCallApi = useCallback(async () => {
 | 
					 | 
				
			||||||
        if (!data?.lot_id) {
 | 
					 | 
				
			||||||
            setHistories([]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setLoading(true);
 | 
					 | 
				
			||||||
        const response = await getDetailBidHistories(data?.lot_id);
 | 
					 | 
				
			||||||
        setLoading(false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (response.data && response.data) {
 | 
					 | 
				
			||||||
            setHistories(response.data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }, [data]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    useEffect(() => {
 | 
					 | 
				
			||||||
        handleCallApi();
 | 
					 | 
				
			||||||
    }, [handleCallApi]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return (
 | 
					 | 
				
			||||||
        <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>
 | 
					 | 
				
			||||||
                        <Table.Th>Bidding Details</Table.Th>
 | 
					 | 
				
			||||||
                        <Table.Th>Bid Time</Table.Th>
 | 
					 | 
				
			||||||
                        <Table.Th>Bid Price</Table.Th>
 | 
					 | 
				
			||||||
                        <Table.Th>Bid Qty</Table.Th>
 | 
					 | 
				
			||||||
                        <Table.Th>Win Qty</Table.Th>
 | 
					 | 
				
			||||||
                    </Table.Tr>
 | 
					 | 
				
			||||||
                </Table.Thead>
 | 
					 | 
				
			||||||
                <Table.Tbody>
 | 
					 | 
				
			||||||
                    {histories.length <= 0 ? (
 | 
					 | 
				
			||||||
                        <Table.Tr>
 | 
					 | 
				
			||||||
                            <Table.Td colSpan={5} className="text-center">
 | 
					 | 
				
			||||||
                                None
 | 
					 | 
				
			||||||
                            </Table.Td>
 | 
					 | 
				
			||||||
                        </Table.Tr>
 | 
					 | 
				
			||||||
                    ) : (
 | 
					 | 
				
			||||||
                        rows
 | 
					 | 
				
			||||||
                    )}
 | 
					 | 
				
			||||||
                </Table.Tbody>
 | 
					 | 
				
			||||||
            </Table>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            <LoadingOverlay visible={loading} zIndex={1000} overlayProps={{ blur: 2 }} />
 | 
					 | 
				
			||||||
        </Modal>
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,8 +1,13 @@
 | 
				
			||||||
 const constants = {
 | 
					const constants = {
 | 
				
			||||||
    grays: 'https://www.grays.com',
 | 
					  grays: "https://www.grays.com",
 | 
				
			||||||
    pickles:'https://www.pickles.com.au'
 | 
					  pickles: "https://www.pickles.com.au",
 | 
				
			||||||
}
 | 
					  allbids: "https://www.allbids.com.au",
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const haveHistories = [constants.grays, constants.pickles]
 | 
					export const haveHistories = [
 | 
				
			||||||
 | 
					  constants.grays,
 | 
				
			||||||
 | 
					  constants.pickles,
 | 
				
			||||||
 | 
					  constants.allbids,
 | 
				
			||||||
 | 
					];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default constants
 | 
					export default constants;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,22 +21,18 @@ import {
 | 
				
			||||||
} 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";
 | 
				
			||||||
import { deleteBid, deletesBid, getBids, toggleBid } from "../apis/bid";
 | 
					import { deleteBid, getBids, toggleBid } from "../apis/bid";
 | 
				
			||||||
import {
 | 
					import { BidModal, ShowHistoriesModal } from "../components/bid";
 | 
				
			||||||
  BidModal,
 | 
					import DeleteRowAction from "../components/bid/delete-row-action";
 | 
				
			||||||
  ShowHistoriesBidGraysApiModal,
 | 
					import { haveHistories } from "../constant";
 | 
				
			||||||
  ShowHistoriesBidPicklesApiModal,
 | 
					 | 
				
			||||||
  ShowHistoriesModal,
 | 
					 | 
				
			||||||
} from "../components/bid";
 | 
					 | 
				
			||||||
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";
 | 
				
			||||||
import { extractDomainSmart, formatTime } from "../utils";
 | 
					import { extractDomainSmart, formatTime } from "../utils";
 | 
				
			||||||
import DeleteRowAction from "../components/bid/delete-row-action";
 | 
					import ShowHistoriesApiModal from "../components/bid/show-histories-api/show-histories-api-modal";
 | 
				
			||||||
import { useChoosesStore } from "../lib/zustand/use-chooses-store";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function Bids() {
 | 
					export default function Bids() {
 | 
				
			||||||
  const refTableFn: TRefTableFn<IBid> = useRef({});
 | 
					  const refTableFn: TRefTableFn<IBid> = useRef({});
 | 
				
			||||||
| 
						 | 
					@ -47,12 +43,9 @@ export default function Bids() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const { setChooses } = useChoosesStore();
 | 
					  const { setChooses } = useChoosesStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [openedHistories, historiesModel] = useDisclosure(false);
 | 
					  const [openedHistories, historiesModal] = useDisclosure(false);
 | 
				
			||||||
  const [openedHistoriesGraysApi, historiesGraysApiModel] =
 | 
					 | 
				
			||||||
    useDisclosure(false);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const [openedHistoriesPicklesApi, historiesPicklesApiModel] =
 | 
					  const [openedHistoriesView, openedHistoriesViewModal] = useDisclosure(false);
 | 
				
			||||||
    useDisclosure(false);
 | 
					 | 
				
			||||||
  const [openedBid, bidModal] = useDisclosure(false);
 | 
					  const [openedBid, bidModal] = useDisclosure(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const columns: IColumn<IBid>[] = [
 | 
					  const columns: IColumn<IBid>[] = [
 | 
				
			||||||
| 
						 | 
					@ -84,7 +77,9 @@ export default function Bids() {
 | 
				
			||||||
      title: "Web",
 | 
					      title: "Web",
 | 
				
			||||||
      typeFilter: "none",
 | 
					      typeFilter: "none",
 | 
				
			||||||
      renderRow(row) {
 | 
					      renderRow(row) {
 | 
				
			||||||
        return <span>{extractDomainSmart(row.web_bid.origin_url)}</span>;
 | 
					        return (
 | 
				
			||||||
 | 
					          <span>{extractDomainSmart(row.web_bid?.origin_url) || "None"}</span>
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
| 
						 | 
					@ -238,28 +233,6 @@ export default function Bids() {
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
        actionsOptions={{
 | 
					        actionsOptions={{
 | 
				
			||||||
          showMainAction: false,
 | 
					          showMainAction: false,
 | 
				
			||||||
          actions: [
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
              key: "delete",
 | 
					 | 
				
			||||||
              title: "Delete",
 | 
					 | 
				
			||||||
              callback: (data) => {
 | 
					 | 
				
			||||||
                if (!data.length) return;
 | 
					 | 
				
			||||||
                setConfirm({
 | 
					 | 
				
			||||||
                  title: "Delete",
 | 
					 | 
				
			||||||
                  message: `${data.length} will be delete`,
 | 
					 | 
				
			||||||
                  handleOk: async () => {
 | 
					 | 
				
			||||||
                    const result = await deletesBid(data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (!result) return;
 | 
					 | 
				
			||||||
                    if (refTableFn.current.fetchData) {
 | 
					 | 
				
			||||||
                      refTableFn.current.fetchData();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                  },
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
              },
 | 
					 | 
				
			||||||
              disabled: (data) => data.length <= 0,
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
          ],
 | 
					 | 
				
			||||||
          leftActionSession: (
 | 
					          leftActionSession: (
 | 
				
			||||||
            <Box className="flex items-end gap-2">
 | 
					            <Box className="flex items-end gap-2">
 | 
				
			||||||
              <Button
 | 
					              <Button
 | 
				
			||||||
| 
						 | 
					@ -270,7 +243,11 @@ export default function Bids() {
 | 
				
			||||||
                Add
 | 
					                Add
 | 
				
			||||||
              </Button>
 | 
					              </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <DeleteRowAction onDeleted={refTableFn.current?.fetchData} />
 | 
					              <DeleteRowAction
 | 
				
			||||||
 | 
					                onDeleted={() => {
 | 
				
			||||||
 | 
					                  refTableFn.current?.fetchData?.();
 | 
				
			||||||
 | 
					                }}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
            </Box>
 | 
					            </Box>
 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
| 
						 | 
					@ -329,29 +306,17 @@ export default function Bids() {
 | 
				
			||||||
                    <Menu.Item
 | 
					                    <Menu.Item
 | 
				
			||||||
                      onClick={() => {
 | 
					                      onClick={() => {
 | 
				
			||||||
                        setClickData(row);
 | 
					                        setClickData(row);
 | 
				
			||||||
                        historiesModel.open();
 | 
					                        historiesModal.open();
 | 
				
			||||||
                      }}
 | 
					                      }}
 | 
				
			||||||
                      leftSection={<IconHistory size={14} />}
 | 
					                      leftSection={<IconHistory size={14} />}
 | 
				
			||||||
                    >
 | 
					                    >
 | 
				
			||||||
                      Histories
 | 
					                      Histories
 | 
				
			||||||
                    </Menu.Item>
 | 
					                    </Menu.Item>
 | 
				
			||||||
                    {haveHistories.includes(row?.web_bid.origin_url) && (
 | 
					                    {haveHistories.includes(row?.web_bid?.origin_url) && (
 | 
				
			||||||
                      <Menu.Item
 | 
					                      <Menu.Item
 | 
				
			||||||
                        onClick={() => {
 | 
					                        onClick={() => {
 | 
				
			||||||
                          setClickData(row);
 | 
					                          setClickData(row);
 | 
				
			||||||
                          switch (row.web_bid.origin_url) {
 | 
					                          openedHistoriesViewModal.open();
 | 
				
			||||||
                            case constants.grays: {
 | 
					 | 
				
			||||||
                              historiesGraysApiModel.open();
 | 
					 | 
				
			||||||
                              break;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            case constants.pickles: {
 | 
					 | 
				
			||||||
                              historiesPicklesApiModel.open();
 | 
					 | 
				
			||||||
                              break;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            default: {
 | 
					 | 
				
			||||||
                              historiesGraysApiModel.open();
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                          }
 | 
					 | 
				
			||||||
                        }}
 | 
					                        }}
 | 
				
			||||||
                        leftSection={<IconHammer size={14} />}
 | 
					                        leftSection={<IconHammer size={14} />}
 | 
				
			||||||
                      >
 | 
					                      >
 | 
				
			||||||
| 
						 | 
					@ -405,7 +370,7 @@ export default function Bids() {
 | 
				
			||||||
      <ShowHistoriesModal
 | 
					      <ShowHistoriesModal
 | 
				
			||||||
        opened={openedHistories}
 | 
					        opened={openedHistories}
 | 
				
			||||||
        onClose={() => {
 | 
					        onClose={() => {
 | 
				
			||||||
          historiesModel.close();
 | 
					          historiesModal.close();
 | 
				
			||||||
          setClickData(null);
 | 
					          setClickData(null);
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
        data={clickData}
 | 
					        data={clickData}
 | 
				
			||||||
| 
						 | 
					@ -426,28 +391,9 @@ export default function Bids() {
 | 
				
			||||||
        }}
 | 
					        }}
 | 
				
			||||||
        data={clickData}
 | 
					        data={clickData}
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
      {/* Grays */}
 | 
					 | 
				
			||||||
      {openedHistoriesGraysApi && (
 | 
					 | 
				
			||||||
        <ShowHistoriesBidGraysApiModal
 | 
					 | 
				
			||||||
          onUpdated={() => {
 | 
					 | 
				
			||||||
            if (refTableFn.current?.fetchData) {
 | 
					 | 
				
			||||||
              refTableFn.current.fetchData();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            setClickData(null);
 | 
					      {openedHistoriesView && (
 | 
				
			||||||
          }}
 | 
					        <ShowHistoriesApiModal
 | 
				
			||||||
          opened={openedHistoriesGraysApi}
 | 
					 | 
				
			||||||
          onClose={() => {
 | 
					 | 
				
			||||||
            historiesGraysApiModel.close();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            setClickData(null);
 | 
					 | 
				
			||||||
          }}
 | 
					 | 
				
			||||||
          data={clickData}
 | 
					 | 
				
			||||||
        />
 | 
					 | 
				
			||||||
      )}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      {openedHistoriesPicklesApi && (
 | 
					 | 
				
			||||||
        <ShowHistoriesBidPicklesApiModal
 | 
					 | 
				
			||||||
          onUpdated={() => {
 | 
					          onUpdated={() => {
 | 
				
			||||||
            if (refTableFn.current?.fetchData) {
 | 
					            if (refTableFn.current?.fetchData) {
 | 
				
			||||||
              refTableFn.current.fetchData();
 | 
					              refTableFn.current.fetchData();
 | 
				
			||||||
| 
						 | 
					@ -457,7 +403,7 @@ export default function Bids() {
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
          opened={true}
 | 
					          opened={true}
 | 
				
			||||||
          onClose={() => {
 | 
					          onClose={() => {
 | 
				
			||||||
            historiesPicklesApiModel.close();
 | 
					            openedHistoriesViewModal.close();
 | 
				
			||||||
            setClickData(null);
 | 
					            setClickData(null);
 | 
				
			||||||
          }}
 | 
					          }}
 | 
				
			||||||
          data={clickData}
 | 
					          data={clickData}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1 @@
 | 
				
			||||||
{"createdAt":1747812172479}
 | 
					{"createdAt":1747970028717}
 | 
				
			||||||
| 
						 | 
					@ -26,7 +26,6 @@
 | 
				
			||||||
        "axios": "^1.8.3",
 | 
					        "axios": "^1.8.3",
 | 
				
			||||||
        "bcrypt": "^5.1.1",
 | 
					        "bcrypt": "^5.1.1",
 | 
				
			||||||
        "bull": "^4.16.5",
 | 
					        "bull": "^4.16.5",
 | 
				
			||||||
        "cheerio": "^1.0.0",
 | 
					 | 
				
			||||||
        "class-transformer": "^0.5.1",
 | 
					        "class-transformer": "^0.5.1",
 | 
				
			||||||
        "class-validator": "^0.14.1",
 | 
					        "class-validator": "^0.14.1",
 | 
				
			||||||
        "cookie": "^1.0.2",
 | 
					        "cookie": "^1.0.2",
 | 
				
			||||||
| 
						 | 
					@ -4661,7 +4660,8 @@
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
 | 
					      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
 | 
				
			||||||
      "license": "ISC"
 | 
					      "license": "ISC",
 | 
				
			||||||
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/brace-expansion": {
 | 
					    "node_modules/brace-expansion": {
 | 
				
			||||||
      "version": "2.0.1",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
| 
						 | 
					@ -4968,36 +4968,12 @@
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "license": "MIT"
 | 
					      "license": "MIT"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/cheerio": {
 | 
					 | 
				
			||||||
      "version": "1.0.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "cheerio-select": "^2.1.0",
 | 
					 | 
				
			||||||
        "dom-serializer": "^2.0.0",
 | 
					 | 
				
			||||||
        "domhandler": "^5.0.3",
 | 
					 | 
				
			||||||
        "domutils": "^3.1.0",
 | 
					 | 
				
			||||||
        "encoding-sniffer": "^0.2.0",
 | 
					 | 
				
			||||||
        "htmlparser2": "^9.1.0",
 | 
					 | 
				
			||||||
        "parse5": "^7.1.2",
 | 
					 | 
				
			||||||
        "parse5-htmlparser2-tree-adapter": "^7.0.0",
 | 
					 | 
				
			||||||
        "parse5-parser-stream": "^7.1.2",
 | 
					 | 
				
			||||||
        "undici": "^6.19.5",
 | 
					 | 
				
			||||||
        "whatwg-mimetype": "^4.0.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=18.17"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/cheerio-select": {
 | 
					    "node_modules/cheerio-select": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
 | 
					      "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "boolbase": "^1.0.0",
 | 
					        "boolbase": "^1.0.0",
 | 
				
			||||||
        "css-select": "^5.1.0",
 | 
					        "css-select": "^5.1.0",
 | 
				
			||||||
| 
						 | 
					@ -5582,6 +5558,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
 | 
					      "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "boolbase": "^1.0.0",
 | 
					        "boolbase": "^1.0.0",
 | 
				
			||||||
        "css-what": "^6.1.0",
 | 
					        "css-what": "^6.1.0",
 | 
				
			||||||
| 
						 | 
					@ -5598,6 +5575,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
 | 
					      "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
        "node": ">= 6"
 | 
					        "node": ">= 6"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -5873,6 +5851,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
 | 
					      "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "domelementtype": "^2.3.0",
 | 
					        "domelementtype": "^2.3.0",
 | 
				
			||||||
        "domhandler": "^5.0.2",
 | 
					        "domhandler": "^5.0.2",
 | 
				
			||||||
| 
						 | 
					@ -5892,13 +5871,15 @@
 | 
				
			||||||
          "url": "https://github.com/sponsors/fb55"
 | 
					          "url": "https://github.com/sponsors/fb55"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "license": "BSD-2-Clause"
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/domhandler": {
 | 
					    "node_modules/domhandler": {
 | 
				
			||||||
      "version": "5.0.3",
 | 
					      "version": "5.0.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
 | 
				
			||||||
      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
 | 
					      "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "domelementtype": "^2.3.0"
 | 
					        "domelementtype": "^2.3.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -5914,6 +5895,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
 | 
				
			||||||
      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
 | 
					      "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "dom-serializer": "^2.0.0",
 | 
					        "dom-serializer": "^2.0.0",
 | 
				
			||||||
        "domelementtype": "^2.3.0",
 | 
					        "domelementtype": "^2.3.0",
 | 
				
			||||||
| 
						 | 
					@ -6100,31 +6082,6 @@
 | 
				
			||||||
        "node": ">=8.10.0"
 | 
					        "node": ">=8.10.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/encoding-sniffer": {
 | 
					 | 
				
			||||||
      "version": "0.2.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "iconv-lite": "^0.6.3",
 | 
					 | 
				
			||||||
        "whatwg-encoding": "^3.1.1"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/encoding-sniffer/node_modules/iconv-lite": {
 | 
					 | 
				
			||||||
      "version": "0.6.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "safer-buffer": ">= 2.1.2 < 3.0.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=0.10.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/encoding/node_modules/iconv-lite": {
 | 
					    "node_modules/encoding/node_modules/iconv-lite": {
 | 
				
			||||||
      "version": "0.6.3",
 | 
					      "version": "0.6.3",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
 | 
				
			||||||
| 
						 | 
					@ -6211,6 +6168,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
 | 
					      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
        "node": ">=0.12"
 | 
					        "node": ">=0.12"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -7844,6 +7802,7 @@
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "domelementtype": "^2.3.0",
 | 
					        "domelementtype": "^2.3.0",
 | 
				
			||||||
        "domhandler": "^5.0.3",
 | 
					        "domhandler": "^5.0.3",
 | 
				
			||||||
| 
						 | 
					@ -10921,6 +10880,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
 | 
					      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "boolbase": "^1.0.0"
 | 
					        "boolbase": "^1.0.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -11224,6 +11184,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
 | 
					      "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "entities": "^6.0.0"
 | 
					        "entities": "^6.0.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -11236,6 +11197,7 @@
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
 | 
					      "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
 | 
				
			||||||
      "license": "MIT",
 | 
					      "license": "MIT",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "domhandler": "^5.0.3",
 | 
					        "domhandler": "^5.0.3",
 | 
				
			||||||
        "parse5": "^7.0.0"
 | 
					        "parse5": "^7.0.0"
 | 
				
			||||||
| 
						 | 
					@ -11244,23 +11206,12 @@
 | 
				
			||||||
        "url": "https://github.com/inikulin/parse5?sponsor=1"
 | 
					        "url": "https://github.com/inikulin/parse5?sponsor=1"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/parse5-parser-stream": {
 | 
					 | 
				
			||||||
      "version": "7.1.2",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "parse5": "^7.0.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "funding": {
 | 
					 | 
				
			||||||
        "url": "https://github.com/inikulin/parse5?sponsor=1"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/parse5/node_modules/entities": {
 | 
					    "node_modules/parse5/node_modules/entities": {
 | 
				
			||||||
      "version": "6.0.0",
 | 
					      "version": "6.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.0.tgz",
 | 
				
			||||||
      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
 | 
					      "integrity": "sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==",
 | 
				
			||||||
      "license": "BSD-2-Clause",
 | 
					      "license": "BSD-2-Clause",
 | 
				
			||||||
 | 
					      "optional": true,
 | 
				
			||||||
      "engines": {
 | 
					      "engines": {
 | 
				
			||||||
        "node": ">=0.12"
 | 
					        "node": ">=0.12"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
| 
						 | 
					@ -14245,15 +14196,6 @@
 | 
				
			||||||
        "node": ">=8"
 | 
					        "node": ">=8"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/undici": {
 | 
					 | 
				
			||||||
      "version": "6.21.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=18.17"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/undici-types": {
 | 
					    "node_modules/undici-types": {
 | 
				
			||||||
      "version": "6.19.8",
 | 
					      "version": "6.19.8",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
 | 
				
			||||||
| 
						 | 
					@ -14726,39 +14668,6 @@
 | 
				
			||||||
        "url": "https://opencollective.com/webpack"
 | 
					        "url": "https://opencollective.com/webpack"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/whatwg-encoding": {
 | 
					 | 
				
			||||||
      "version": "3.1.1",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "iconv-lite": "0.6.3"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=18"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/whatwg-encoding/node_modules/iconv-lite": {
 | 
					 | 
				
			||||||
      "version": "0.6.3",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "dependencies": {
 | 
					 | 
				
			||||||
        "safer-buffer": ">= 2.1.2 < 3.0.0"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=0.10.0"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/whatwg-mimetype": {
 | 
					 | 
				
			||||||
      "version": "4.0.0",
 | 
					 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
 | 
					 | 
				
			||||||
      "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
 | 
					 | 
				
			||||||
      "license": "MIT",
 | 
					 | 
				
			||||||
      "engines": {
 | 
					 | 
				
			||||||
        "node": ">=18"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "node_modules/whatwg-url": {
 | 
					    "node_modules/whatwg-url": {
 | 
				
			||||||
      "version": "5.0.0",
 | 
					      "version": "5.0.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,7 +42,6 @@
 | 
				
			||||||
    "axios": "^1.8.3",
 | 
					    "axios": "^1.8.3",
 | 
				
			||||||
    "bcrypt": "^5.1.1",
 | 
					    "bcrypt": "^5.1.1",
 | 
				
			||||||
    "bull": "^4.16.5",
 | 
					    "bull": "^4.16.5",
 | 
				
			||||||
    "cheerio": "^1.0.0",
 | 
					 | 
				
			||||||
    "class-transformer": "^0.5.1",
 | 
					    "class-transformer": "^0.5.1",
 | 
				
			||||||
    "class-validator": "^0.14.1",
 | 
					    "class-validator": "^0.14.1",
 | 
				
			||||||
    "cookie": "^1.0.2",
 | 
					    "cookie": "^1.0.2",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,59 +1,51 @@
 | 
				
			||||||
import { Injectable } from '@nestjs/common';
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
import axios from 'axios';
 | 
					import axios from 'axios';
 | 
				
			||||||
import AppResponse from 'src/response/app-response';
 | 
					import AppResponse from 'src/response/app-response';
 | 
				
			||||||
import { Bid } from '../entities/bid.entity';
 | 
					import { Bid } from '../entities/bid.entity';
 | 
				
			||||||
import { BidsService } from '../services/bids.service';
 | 
					import { BidsService } from '../services/bids.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export class GraysApi {
 | 
					export class AllBidsApi {
 | 
				
			||||||
 | 
					  constructor(private readonly bidsService: BidsService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(private readonly bidsService: BidsService){}
 | 
					  async getHistoriesBid(lot_id: Bid['lot_id']) {
 | 
				
			||||||
 | 
					    const bid = await this.bidsService.bidsRepo.findOne({
 | 
				
			||||||
 | 
					      where: { lot_id },
 | 
				
			||||||
  async getHistoriesBid(lot_id: Bid['lot_id']) {
 | 
					      relations: { web_bid: true },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const bid= await this.bidsService.bidsRepo.findOne({where: {lot_id, }, relations: {web_bid: true}})
 | 
					    try {
 | 
				
			||||||
 | 
					      switch (bid.web_bid.origin_url) {
 | 
				
			||||||
 | 
					        // GRAYS
 | 
				
			||||||
    try {
 | 
					        case 'https://www.grays.com': {
 | 
				
			||||||
 | 
					          const response = await axios({
 | 
				
			||||||
      switch(bid.web_bid.origin_url){
 | 
					            url: `https://www.grays.com/api/LotInfo/GetBiddingHistory?lotId=${lot_id}¤cyCode=AUD`,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
        // GRAYS
 | 
					
 | 
				
			||||||
        case 'https://www.grays.com': {
 | 
					          if (response.data && response.data?.Bids) {
 | 
				
			||||||
          const response = await axios({
 | 
					            return AppResponse.toResponse(response.data.Bids);
 | 
				
			||||||
            url: `https://www.grays.com/api/LotInfo/GetBiddingHistory?lotId=${lot_id}¤cyCode=AUD`,
 | 
					          }
 | 
				
			||||||
          });
 | 
					
 | 
				
			||||||
    
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
          if (response.data && response.data?.Bids) {
 | 
					        }
 | 
				
			||||||
            return AppResponse.toResponse(response.data.Bids);
 | 
					
 | 
				
			||||||
          }
 | 
					        // PICKLES
 | 
				
			||||||
 | 
					        case 'https://www.pickles.com.au': {
 | 
				
			||||||
          return AppResponse.toResponse([])
 | 
					          const response = await axios({
 | 
				
			||||||
        }
 | 
					            url: `https://www.pickles.com.au/PWR-Web/services/api/bidHistoryService/bidHistory?item=${lot_id}`,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
        // PICKLES
 | 
					
 | 
				
			||||||
        case 'https://www.pickles.com.au': {
 | 
					          if (response.data) {
 | 
				
			||||||
          
 | 
					            return AppResponse.toResponse(response.data.Bids);
 | 
				
			||||||
          const response = await axios({
 | 
					          }
 | 
				
			||||||
            url: `https://www.pickles.com.au/PWR-Web/services/api/bidHistoryService/bidHistory?item=${lot_id}`,
 | 
					
 | 
				
			||||||
          });
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
    
 | 
					        }
 | 
				
			||||||
          if (response.data) {
 | 
					        default:
 | 
				
			||||||
            return AppResponse.toResponse(response.data.Bids);
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
          }
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
          return AppResponse.toResponse([])
 | 
					      return AppResponse.toResponse([]);
 | 
				
			||||||
        }
 | 
					    }
 | 
				
			||||||
        default: 
 | 
					  }
 | 
				
			||||||
          return AppResponse.toResponse([])
 | 
					}
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
      return AppResponse.toResponse([]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,62 @@
 | 
				
			||||||
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
 | 
					import axios from 'axios';
 | 
				
			||||||
 | 
					import AppResponse from 'src/response/app-response';
 | 
				
			||||||
 | 
					import { Bid } from '../entities/bid.entity';
 | 
				
			||||||
 | 
					import { BidsService } from '../services/bids.service';
 | 
				
			||||||
 | 
					import * as _ from 'lodash';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class AuctionHistoresApi {
 | 
				
			||||||
 | 
					  constructor(private readonly bidsService: BidsService) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getHistoriesBid(lot_id: Bid['lot_id']) {
 | 
				
			||||||
 | 
					    const bid = await this.bidsService.bidsRepo.findOne({
 | 
				
			||||||
 | 
					      where: { lot_id },
 | 
				
			||||||
 | 
					      relations: { web_bid: true, metadata: true },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      switch (bid.web_bid.origin_url) {
 | 
				
			||||||
 | 
					        // GRAYS
 | 
				
			||||||
 | 
					        case 'https://www.grays.com': {
 | 
				
			||||||
 | 
					          const response = await axios({
 | 
				
			||||||
 | 
					            url: `https://www.grays.com/api/LotInfo/GetBiddingHistory?lotId=${lot_id}¤cyCode=AUD`,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (response.data && response.data?.Bids) {
 | 
				
			||||||
 | 
					            return AppResponse.toResponse(response.data.Bids);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // PICKLES
 | 
				
			||||||
 | 
					        case 'https://www.pickles.com.au': {
 | 
				
			||||||
 | 
					          const response = await axios({
 | 
				
			||||||
 | 
					            url: `https://www.pickles.com.au/PWR-Web/services/api/bidHistoryService/bidHistory?item=${lot_id}`,
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (response.data) {
 | 
				
			||||||
 | 
					            return AppResponse.toResponse(response.data.Bids);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // ALLBIDS
 | 
				
			||||||
 | 
					        case 'https://www.allbids.com.au': {
 | 
				
			||||||
 | 
					          const data = bid.metadata.find(
 | 
				
			||||||
 | 
					            (meta) => meta.key_name === 'competor_histories',
 | 
				
			||||||
 | 
					          )?.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          const sorted = _.orderBy(data, ['amount'], ['desc']);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          return AppResponse.toResponse(sorted || []);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					          return AppResponse.toResponse([]);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      return AppResponse.toResponse([]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,7 @@ import { TypeOrmModule } from '@nestjs/typeorm';
 | 
				
			||||||
import { AdminsModule } from '../admins/admins.module';
 | 
					import { AdminsModule } from '../admins/admins.module';
 | 
				
			||||||
import { NotificationModule } from '../notification/notification.module';
 | 
					import { NotificationModule } from '../notification/notification.module';
 | 
				
			||||||
import { BotTelegramApi } from './apis/bot-telegram.api';
 | 
					import { BotTelegramApi } from './apis/bot-telegram.api';
 | 
				
			||||||
import { GraysApi } from './apis/grays.api';
 | 
					import { AuctionHistoresApi } from './apis/auction-histories.api';
 | 
				
			||||||
import { AdminBidHistoriesController } from './controllers/admin/admin-bid-histories.controller';
 | 
					import { AdminBidHistoriesController } from './controllers/admin/admin-bid-histories.controller';
 | 
				
			||||||
import { AdminBidsController } from './controllers/admin/admin-bids.controller';
 | 
					import { AdminBidsController } from './controllers/admin/admin-bids.controller';
 | 
				
			||||||
import { AdminOutBidLogsController } from './controllers/admin/admin-out-bid-logs.controller';
 | 
					import { AdminOutBidLogsController } from './controllers/admin/admin-out-bid-logs.controller';
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,8 @@ import { TasksService } from './services/tasks.servise';
 | 
				
			||||||
import { ConfigsService } from './services/configs.service';
 | 
					import { ConfigsService } from './services/configs.service';
 | 
				
			||||||
import { Config } from './entities/configs.entity';
 | 
					import { Config } from './entities/configs.entity';
 | 
				
			||||||
import { AdminConfigsController } from './controllers/admin/admin-configs.controller';
 | 
					import { AdminConfigsController } from './controllers/admin/admin-configs.controller';
 | 
				
			||||||
 | 
					import { BidMetadatasService } from './services/bid-metadatas.service';
 | 
				
			||||||
 | 
					import { BidMetadata } from './entities/bid-metadata.entity';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Module({
 | 
					@Module({
 | 
				
			||||||
  imports: [
 | 
					  imports: [
 | 
				
			||||||
| 
						 | 
					@ -41,6 +43,7 @@ import { AdminConfigsController } from './controllers/admin/admin-configs.contro
 | 
				
			||||||
      WebBid,
 | 
					      WebBid,
 | 
				
			||||||
      SendMessageHistory,
 | 
					      SendMessageHistory,
 | 
				
			||||||
      Config,
 | 
					      Config,
 | 
				
			||||||
 | 
					      BidMetadata,
 | 
				
			||||||
    ]),
 | 
					    ]),
 | 
				
			||||||
    // AuthModule,
 | 
					    // AuthModule,
 | 
				
			||||||
    AdminsModule,
 | 
					    AdminsModule,
 | 
				
			||||||
| 
						 | 
					@ -66,12 +69,13 @@ import { AdminConfigsController } from './controllers/admin/admin-configs.contro
 | 
				
			||||||
    OutBidLogsService,
 | 
					    OutBidLogsService,
 | 
				
			||||||
    WebBidsService,
 | 
					    WebBidsService,
 | 
				
			||||||
    BotTelegramApi,
 | 
					    BotTelegramApi,
 | 
				
			||||||
    GraysApi,
 | 
					    AuctionHistoresApi,
 | 
				
			||||||
    SendMessageHistoriesService,
 | 
					    SendMessageHistoriesService,
 | 
				
			||||||
    ImapService,
 | 
					    ImapService,
 | 
				
			||||||
    DashboardService,
 | 
					    DashboardService,
 | 
				
			||||||
    TasksService,
 | 
					    TasksService,
 | 
				
			||||||
    ConfigsService,
 | 
					    ConfigsService,
 | 
				
			||||||
 | 
					    BidMetadatasService,
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  exports: [
 | 
					  exports: [
 | 
				
			||||||
    BotTelegramApi,
 | 
					    BotTelegramApi,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,13 +4,13 @@ import { CreateBidDto } from '../../dto/bid/create-bid.dto';
 | 
				
			||||||
import { BidHistoriesService } from '../../services/bid-histories.service';
 | 
					import { BidHistoriesService } from '../../services/bid-histories.service';
 | 
				
			||||||
import { CreateBidHistoryDto } from '../../dto/bid-history/create-bid-history.dto';
 | 
					import { CreateBidHistoryDto } from '../../dto/bid-history/create-bid-history.dto';
 | 
				
			||||||
import { Bid } from '../../entities/bid.entity';
 | 
					import { Bid } from '../../entities/bid.entity';
 | 
				
			||||||
import { GraysApi } from '../../apis/grays.api';
 | 
					import { AuctionHistoresApi } from '../../apis/auction-histories.api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Controller('admin/bid-histories')
 | 
					@Controller('admin/bid-histories')
 | 
				
			||||||
export class AdminBidHistoriesController {
 | 
					export class AdminBidHistoriesController {
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private readonly bidHistoriesService: BidHistoriesService,
 | 
					    private readonly bidHistoriesService: BidHistoriesService,
 | 
				
			||||||
    private readonly graysApi: GraysApi,
 | 
					    private readonly auctionHistoresApi: AuctionHistoresApi,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Post()
 | 
					  @Post()
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,6 @@ export class AdminBidHistoriesController {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Get('detail/:lot_id')
 | 
					  @Get('detail/:lot_id')
 | 
				
			||||||
  async getBidHistories(@Param('lot_id') lot_id: Bid['lot_id']) {
 | 
					  async getBidHistories(@Param('lot_id') lot_id: Bid['lot_id']) {
 | 
				
			||||||
    return await this.graysApi.getHistoriesBid(lot_id);
 | 
					    return await this.auctionHistoresApi.getHistoriesBid(lot_id);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
import { IsNumber, IsOptional, IsString } from 'class-validator';
 | 
					import { IsNumber, IsObject, IsOptional, IsString } from 'class-validator';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class ClientUpdateBidDto {
 | 
					export class ClientUpdateBidDto {
 | 
				
			||||||
  @IsString()
 | 
					  @IsString()
 | 
				
			||||||
| 
						 | 
					@ -24,4 +24,8 @@ export class ClientUpdateBidDto {
 | 
				
			||||||
  @IsNumber()
 | 
					  @IsNumber()
 | 
				
			||||||
  @IsOptional()
 | 
					  @IsOptional()
 | 
				
			||||||
  reserve_price: number;
 | 
					  reserve_price: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @IsObject()
 | 
				
			||||||
 | 
					  @IsOptional()
 | 
				
			||||||
 | 
					  metadata: Record<string, any>;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,25 @@
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  Column,
 | 
				
			||||||
 | 
					  Entity,
 | 
				
			||||||
 | 
					  ManyToOne,
 | 
				
			||||||
 | 
					  PrimaryGeneratedColumn,
 | 
				
			||||||
 | 
					  Unique,
 | 
				
			||||||
 | 
					} from 'typeorm';
 | 
				
			||||||
 | 
					import { Bid } from './bid.entity';
 | 
				
			||||||
 | 
					import { Timestamp } from './timestamp';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Entity('bid_metadata')
 | 
				
			||||||
 | 
					@Unique(['key_name', 'bid'])
 | 
				
			||||||
 | 
					export class BidMetadata extends Timestamp {
 | 
				
			||||||
 | 
					  @PrimaryGeneratedColumn('increment')
 | 
				
			||||||
 | 
					  id: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Column()
 | 
				
			||||||
 | 
					  key_name: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Column({ type: 'json' })
 | 
				
			||||||
 | 
					  value: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @ManyToOne(() => Bid, (bid) => bid.metadata, { onDelete: 'CASCADE' })
 | 
				
			||||||
 | 
					  bid: Bid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ import { Timestamp } from './timestamp';
 | 
				
			||||||
import { BidHistory } from './bid-history.entity';
 | 
					import { BidHistory } from './bid-history.entity';
 | 
				
			||||||
import { WebBid } from './wed-bid.entity';
 | 
					import { WebBid } from './wed-bid.entity';
 | 
				
			||||||
import { SendMessageHistory } from './send-message-histories.entity';
 | 
					import { SendMessageHistory } from './send-message-histories.entity';
 | 
				
			||||||
 | 
					import { BidMetadata } from './bid-metadata.entity';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Entity('bids')
 | 
					@Entity('bids')
 | 
				
			||||||
export class Bid extends Timestamp {
 | 
					export class Bid extends Timestamp {
 | 
				
			||||||
| 
						 | 
					@ -69,4 +70,7 @@ export class Bid extends Timestamp {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @ManyToOne(() => WebBid, (web) => web.children, { onDelete: 'CASCADE' })
 | 
					  @ManyToOne(() => WebBid, (web) => web.children, { onDelete: 'CASCADE' })
 | 
				
			||||||
  web_bid: WebBid;
 | 
					  web_bid: WebBid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @OneToMany(() => BidMetadata, (metadata) => metadata.bid)
 | 
				
			||||||
 | 
					  metadata: BidMetadata[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,44 @@
 | 
				
			||||||
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
 | 
					import { InjectRepository } from '@nestjs/typeorm';
 | 
				
			||||||
 | 
					import { Repository } from 'typeorm';
 | 
				
			||||||
 | 
					import { BidMetadata } from '../entities/bid-metadata.entity';
 | 
				
			||||||
 | 
					import { Bid } from '../entities/bid.entity';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Injectable()
 | 
				
			||||||
 | 
					export class BidMetadatasService {
 | 
				
			||||||
 | 
					  constructor(
 | 
				
			||||||
 | 
					    @InjectRepository(BidMetadata)
 | 
				
			||||||
 | 
					    readonly bidMetadataRepo: Repository<BidMetadata>,
 | 
				
			||||||
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async upsert(data: Record<string, any>, bid: Bid) {
 | 
				
			||||||
 | 
					    const existingMetadata = await this.bidMetadataRepo.find({
 | 
				
			||||||
 | 
					      where: { bid: { id: bid.id } },
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const existingMap = new Map(
 | 
				
			||||||
 | 
					      existingMetadata.map((item) => [item.key_name, item]),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const toSave: BidMetadata[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const [key, value] of Object.entries(data)) {
 | 
				
			||||||
 | 
					      const existing = existingMap.get(key);
 | 
				
			||||||
 | 
					      if (existing) {
 | 
				
			||||||
 | 
					        existing.value = value;
 | 
				
			||||||
 | 
					        toSave.push(existing);
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        toSave.push(
 | 
				
			||||||
 | 
					          this.bidMetadataRepo.create({
 | 
				
			||||||
 | 
					            key_name: key,
 | 
				
			||||||
 | 
					            value,
 | 
				
			||||||
 | 
					            bid: { id: bid.id },
 | 
				
			||||||
 | 
					          }),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await this.bidMetadataRepo.save(toSave);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -32,6 +32,7 @@ import { ImageCompressionPipe } from '../pipes/image-compression-pipe';
 | 
				
			||||||
import { Constant } from '../utils/constant';
 | 
					import { Constant } from '../utils/constant';
 | 
				
			||||||
import { Event } from '../utils/events';
 | 
					import { Event } from '../utils/events';
 | 
				
			||||||
import { WebBidsService } from './web-bids.service';
 | 
					import { WebBidsService } from './web-bids.service';
 | 
				
			||||||
 | 
					import { BidMetadatasService } from './bid-metadatas.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
export class BidsService {
 | 
					export class BidsService {
 | 
				
			||||||
| 
						 | 
					@ -41,8 +42,9 @@ export class BidsService {
 | 
				
			||||||
    @InjectRepository(BidHistory)
 | 
					    @InjectRepository(BidHistory)
 | 
				
			||||||
    readonly bidHistoriesRepo: Repository<BidHistory>,
 | 
					    readonly bidHistoriesRepo: Repository<BidHistory>,
 | 
				
			||||||
    private readonly webBidsService: WebBidsService,
 | 
					    private readonly webBidsService: WebBidsService,
 | 
				
			||||||
    private eventEmitter: EventEmitter2,
 | 
					    private readonly eventEmitter: EventEmitter2,
 | 
				
			||||||
    private notificationService: NotificationService,
 | 
					    private readonly notificationService: NotificationService,
 | 
				
			||||||
 | 
					    private readonly bidMetadatasService: BidMetadatasService,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async index(query: PaginateQuery) {
 | 
					  async index(query: PaginateQuery) {
 | 
				
			||||||
| 
						 | 
					@ -208,12 +210,12 @@ export class BidsService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async clientUpdate(
 | 
					  async clientUpdate(
 | 
				
			||||||
    id: Bid['id'],
 | 
					    id: Bid['id'],
 | 
				
			||||||
    { close_time, model, ...data }: ClientUpdateBidDto, // Nhận dữ liệu cập nhật
 | 
					    { close_time, model, metadata, ...data }: ClientUpdateBidDto, // Nhận dữ liệu cập nhật
 | 
				
			||||||
  ) {
 | 
					  ) {
 | 
				
			||||||
    // Tìm kiếm phiên đấu giá trong database theo id
 | 
					    // Tìm kiếm phiên đấu giá trong database theo id
 | 
				
			||||||
    const bid = await this.bidsRepo.findOne({
 | 
					    const bid = await this.bidsRepo.findOne({
 | 
				
			||||||
      where: { id },
 | 
					      where: { id },
 | 
				
			||||||
      relations: { histories: true, web_bid: true },
 | 
					      relations: { histories: true, web_bid: true, metadata: true },
 | 
				
			||||||
      order: {
 | 
					      order: {
 | 
				
			||||||
        histories: {
 | 
					        histories: {
 | 
				
			||||||
          price: 'DESC',
 | 
					          price: 'DESC',
 | 
				
			||||||
| 
						 | 
					@ -288,6 +290,10 @@ export class BidsService {
 | 
				
			||||||
      updated_at: new Date(), // Cập nhật timestamp
 | 
					      updated_at: new Date(), // Cập nhật timestamp
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (metadata) {
 | 
				
			||||||
 | 
					      await this.bidMetadatasService.upsert(metadata, bid);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Phát sự kiện cập nhật toàn bộ danh sách đấu giá
 | 
					    // Phát sự kiện cập nhật toàn bộ danh sách đấu giá
 | 
				
			||||||
    this.emitAllBidEvent();
 | 
					    this.emitAllBidEvent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@ import { Queue } from 'bull';
 | 
				
			||||||
export class MailsService {
 | 
					export class MailsService {
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    private readonly mailerService: MailerService,
 | 
					    private readonly mailerService: MailerService,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @InjectQueue('mail-queue') private mailQueue: Queue,
 | 
					    @InjectQueue('mail-queue') private mailQueue: Queue,
 | 
				
			||||||
  ) {}
 | 
					  ) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +53,8 @@ export class MailsService {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  generateProductTableHTML(products: ScrapItem[]): string {
 | 
					  generateProductTableHTML(products: ScrapItem[]): string {
 | 
				
			||||||
 | 
					    const from = process.env.MAIL_USER || 'no-reply@example.com';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!products.length) {
 | 
					    if (!products.length) {
 | 
				
			||||||
      return `
 | 
					      return `
 | 
				
			||||||
    <!DOCTYPE html>
 | 
					    <!DOCTYPE html>
 | 
				
			||||||
| 
						 | 
					@ -64,6 +67,7 @@ export class MailsService {
 | 
				
			||||||
    <body style="font-family: sans-serif; background: #f8f9fa; padding: 20px;">
 | 
					    <body style="font-family: sans-serif; background: #f8f9fa; padding: 20px;">
 | 
				
			||||||
      <h2 style="text-align: center; color: #333;">Product Listing</h2>
 | 
					      <h2 style="text-align: center; color: #333;">Product Listing</h2>
 | 
				
			||||||
      <p style="text-align: center; color: #666;">No matching products found for your keywords today.</p>
 | 
					      <p style="text-align: center; color: #666;">No matching products found for your keywords today.</p>
 | 
				
			||||||
 | 
					      <p style="text-align: center; color: #999; font-size: 12px; margin-top: 40px;">From: ${from}</p>
 | 
				
			||||||
    </body>
 | 
					    </body>
 | 
				
			||||||
    </html>
 | 
					    </html>
 | 
				
			||||||
    `;
 | 
					    `;
 | 
				
			||||||
| 
						 | 
					@ -109,6 +113,7 @@ export class MailsService {
 | 
				
			||||||
        </tbody>
 | 
					        </tbody>
 | 
				
			||||||
      </table>
 | 
					      </table>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					    <p style="text-align: center; color: #999; font-size: 12px; margin-top: 40px;">From: ${from}</p>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
  </html>
 | 
					  </html>
 | 
				
			||||||
  `;
 | 
					  `;
 | 
				
			||||||
| 
						 | 
					@ -122,6 +127,7 @@ export class MailsService {
 | 
				
			||||||
    const max = `$${bid.max_price}`;
 | 
					    const max = `$${bid.max_price}`;
 | 
				
			||||||
    const submitted = `$${bid.max_price}`;
 | 
					    const submitted = `$${bid.max_price}`;
 | 
				
			||||||
    const nextBid = bid.max_price + bid.plus_price;
 | 
					    const nextBid = bid.max_price + bid.plus_price;
 | 
				
			||||||
 | 
					    const from = process.env.MAIL_USER || 'no-reply@example.com';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const cardStyle = `
 | 
					    const cardStyle = `
 | 
				
			||||||
    max-width: 600px; 
 | 
					    max-width: 600px; 
 | 
				
			||||||
| 
						 | 
					@ -146,15 +152,16 @@ export class MailsService {
 | 
				
			||||||
    switch (bid.status) {
 | 
					    switch (bid.status) {
 | 
				
			||||||
      case 'biding':
 | 
					      case 'biding':
 | 
				
			||||||
        return `
 | 
					        return `
 | 
				
			||||||
        <div style="${cardStyle}">
 | 
					      <div style="${cardStyle}">
 | 
				
			||||||
          <h2 style="${headerStyle('#2c7a7b')}">✅ Auto Bid Started</h2>
 | 
					        <h2 style="${headerStyle('#2c7a7b')}">✅ Auto Bid Started</h2>
 | 
				
			||||||
          ${renderRow('Title', title)}
 | 
					        ${renderRow('Title', title)}
 | 
				
			||||||
          ${renderRow('Max', max)}
 | 
					        ${renderRow('Max', max)}
 | 
				
			||||||
          ${renderRow('End time', endTime)}
 | 
					        ${renderRow('End time', endTime)}
 | 
				
			||||||
          ${renderRow('Competitor', competitor)}
 | 
					        ${renderRow('Competitor', competitor)}
 | 
				
			||||||
          ${renderRow('Bid submitted', submitted)}
 | 
					        ${renderRow('Bid submitted', submitted)}
 | 
				
			||||||
        </div>
 | 
					        ${renderRow('From', from)}
 | 
				
			||||||
      `;
 | 
					      </div>
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case 'out-bid': {
 | 
					      case 'out-bid': {
 | 
				
			||||||
        const overLimit = bid.current_price >= nextBid;
 | 
					        const overLimit = bid.current_price >= nextBid;
 | 
				
			||||||
| 
						 | 
					@ -163,59 +170,64 @@ export class MailsService {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (isTimeReached(bid.close_time)) {
 | 
					        if (isTimeReached(bid.close_time)) {
 | 
				
			||||||
          return `
 | 
					          return `
 | 
				
			||||||
          <div style="${cardStyle}">
 | 
					        <div style="${cardStyle}">
 | 
				
			||||||
            <h2 style="${headerStyle('#718096')}">⏳ Auction Ended</h2>
 | 
					          <h2 style="${headerStyle('#718096')}">⏳ Auction Ended</h2>
 | 
				
			||||||
            ${renderRow('Title', title)}
 | 
					          ${renderRow('Title', title)}
 | 
				
			||||||
            ${renderRow('End time', endTime)}
 | 
					          ${renderRow('End time', endTime)}
 | 
				
			||||||
            ${renderRow('Final price', competitor)}
 | 
					          ${renderRow('Final price', competitor)}
 | 
				
			||||||
          </div>
 | 
					          ${renderRow('From', from)}
 | 
				
			||||||
        `;
 | 
					        </div>
 | 
				
			||||||
 | 
					      `;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (overLimit || belowReserve) {
 | 
					        if (overLimit || belowReserve) {
 | 
				
			||||||
          return `
 | 
					          return `
 | 
				
			||||||
          <div style="${cardStyle}">
 | 
					 | 
				
			||||||
            <h2 style="${headerStyle('#dd6b20')}">⚠️ Outbid (${timeExtended})</h2>
 | 
					 | 
				
			||||||
            ${renderRow('Title', title)}
 | 
					 | 
				
			||||||
            ${renderRow('Competitor', competitor)}
 | 
					 | 
				
			||||||
            ${renderRow('Max', max)}
 | 
					 | 
				
			||||||
            ${renderRow('Next bid at', `$${nextBid}`)}
 | 
					 | 
				
			||||||
            ${renderRow('End time', endTime)}
 | 
					 | 
				
			||||||
            <p style="color:#c05621; font-weight: 600;">⚠️ Current bid exceeds your max bid.</p>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
        `;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return `
 | 
					 | 
				
			||||||
        <div style="${cardStyle}">
 | 
					        <div style="${cardStyle}">
 | 
				
			||||||
          <h2 style="${headerStyle('#e53e3e')}">🛑 Auction Canceled (${timeExtended})</h2>
 | 
					          <h2 style="${headerStyle('#dd6b20')}">⚠️ Outbid (${timeExtended})</h2>
 | 
				
			||||||
          ${renderRow('Title', title)}
 | 
					          ${renderRow('Title', title)}
 | 
				
			||||||
          ${renderRow('Competitor', competitor)}
 | 
					          ${renderRow('Competitor', competitor)}
 | 
				
			||||||
          ${renderRow('Max', max)}
 | 
					          ${renderRow('Max', max)}
 | 
				
			||||||
          ${renderRow('Next bid at', `$${nextBid}`)}
 | 
					          ${renderRow('Next bid at', `$${nextBid}`)}
 | 
				
			||||||
          ${renderRow('End time', endTime)}
 | 
					          ${renderRow('End time', endTime)}
 | 
				
			||||||
          <p style="color:#9b2c2c; font-weight: 600;">🛑 Auction has been canceled.</p>
 | 
					          ${renderRow('From', from)}
 | 
				
			||||||
 | 
					          <p style="color:#c05621; font-weight: 600;">⚠️ Current bid exceeds your max bid.</p>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      `;
 | 
					      `;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return `
 | 
				
			||||||
 | 
					      <div style="${cardStyle}">
 | 
				
			||||||
 | 
					        <h2 style="${headerStyle('#e53e3e')}">🛑 Auction Canceled (${timeExtended})</h2>
 | 
				
			||||||
 | 
					        ${renderRow('Title', title)}
 | 
				
			||||||
 | 
					        ${renderRow('Competitor', competitor)}
 | 
				
			||||||
 | 
					        ${renderRow('Max', max)}
 | 
				
			||||||
 | 
					        ${renderRow('Next bid at', `$${nextBid}`)}
 | 
				
			||||||
 | 
					        ${renderRow('End time', endTime)}
 | 
				
			||||||
 | 
					        ${renderRow('From', from)}
 | 
				
			||||||
 | 
					        <p style="color:#9b2c2c; font-weight: 600;">🛑 Auction has been canceled.</p>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      case 'win-bid':
 | 
					      case 'win-bid':
 | 
				
			||||||
        return `
 | 
					        return `
 | 
				
			||||||
        <div style="${cardStyle}">
 | 
					      <div style="${cardStyle}">
 | 
				
			||||||
          <h2 style="${headerStyle('#2b6cb0')}">🎉 You Won!</h2>
 | 
					        <h2 style="${headerStyle('#2b6cb0')}">🎉 You Won!</h2>
 | 
				
			||||||
          ${renderRow('Title', title)}
 | 
					        ${renderRow('Title', title)}
 | 
				
			||||||
          ${renderRow('Price won', `$${bid.current_price}`)}
 | 
					        ${renderRow('Price won', `$${bid.current_price}`)}
 | 
				
			||||||
          ${renderRow('Max', max)}
 | 
					        ${renderRow('Max', max)}
 | 
				
			||||||
        </div>
 | 
					        ${renderRow('From', from)}
 | 
				
			||||||
      `;
 | 
					      </div>
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      default:
 | 
					      default:
 | 
				
			||||||
        return `
 | 
					        return `
 | 
				
			||||||
        <div style="${cardStyle}">
 | 
					      <div style="${cardStyle}">
 | 
				
			||||||
          <h2 style="${headerStyle('#718096')}">❓ Unknown Status</h2>
 | 
					        <h2 style="${headerStyle('#718096')}">❓ Unknown Status</h2>
 | 
				
			||||||
          ${renderRow('Title', title)}
 | 
					        ${renderRow('Title', title)}
 | 
				
			||||||
        </div>
 | 
					        ${renderRow('From', from)}
 | 
				
			||||||
      `;
 | 
					      </div>
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,6 +239,7 @@ export class MailsService {
 | 
				
			||||||
    const max = `$${bid.max_price}`;
 | 
					    const max = `$${bid.max_price}`;
 | 
				
			||||||
    const submitted = `$${bid.max_price}`;
 | 
					    const submitted = `$${bid.max_price}`;
 | 
				
			||||||
    const maxReached = bid.max_price <= bid.max_price;
 | 
					    const maxReached = bid.max_price <= bid.max_price;
 | 
				
			||||||
 | 
					    const from = process.env.MAIL_USER || 'no-reply@example.com';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return `
 | 
					    return `
 | 
				
			||||||
  <!DOCTYPE html>
 | 
					  <!DOCTYPE html>
 | 
				
			||||||
| 
						 | 
					@ -300,6 +313,10 @@ export class MailsService {
 | 
				
			||||||
            <th>End Time</th>
 | 
					            <th>End Time</th>
 | 
				
			||||||
            <td>${endTime}</td>
 | 
					            <td>${endTime}</td>
 | 
				
			||||||
          </tr>
 | 
					          </tr>
 | 
				
			||||||
 | 
					          <tr>
 | 
				
			||||||
 | 
					            <th>From</th>
 | 
				
			||||||
 | 
					            <td>${from}</td>
 | 
				
			||||||
 | 
					          </tr>
 | 
				
			||||||
        </tbody>
 | 
					        </tbody>
 | 
				
			||||||
      </table>
 | 
					      </table>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,6 @@ import { Injectable, Logger } from '@nestjs/common';
 | 
				
			||||||
import { Cron } from '@nestjs/schedule';
 | 
					import { Cron } from '@nestjs/schedule';
 | 
				
			||||||
import * as moment from 'moment';
 | 
					import * as moment from 'moment';
 | 
				
			||||||
import { Between } from 'typeorm';
 | 
					import { Between } from 'typeorm';
 | 
				
			||||||
import { ScrapConfigsService } from './scrap-config.service';
 | 
					 | 
				
			||||||
import { ScrapItemsService } from './scrap-item-config.service';
 | 
					import { ScrapItemsService } from './scrap-item-config.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable()
 | 
					@Injectable()
 | 
				
			||||||
| 
						 | 
					@ -87,7 +86,7 @@ export class TasksService {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @Cron('0 2 * * *')
 | 
					  @Cron('58 5 * * *')
 | 
				
			||||||
  async handleScraps() {
 | 
					  async handleScraps() {
 | 
				
			||||||
    const processName = 'scrape-data-keyword';
 | 
					    const processName = 'scrape-data-keyword';
 | 
				
			||||||
    await this.runProcessAndSendReport(processName);
 | 
					    await this.runProcessAndSendReport(processName);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,6 +59,48 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async getHistoriesData() {
 | 
				
			||||||
 | 
					    if (!this.page_context) return;
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      // Chờ cho Angular load (có thể tùy chỉnh thời gian nếu cần)
 | 
				
			||||||
 | 
					      await this.page_context.waitForFunction(
 | 
				
			||||||
 | 
					        () => window.angular !== undefined
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const historiesData = await this.page_context.evaluate(() => {
 | 
				
			||||||
 | 
					        let data = null;
 | 
				
			||||||
 | 
					        const elements = document.querySelectorAll(".ng-scope");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (let i = 0; i < elements.length; i++) {
 | 
				
			||||||
 | 
					          try {
 | 
				
			||||||
 | 
					            const scope = angular.element(elements[i]).scope();
 | 
				
			||||||
 | 
					            if (scope?.bidHistory) {
 | 
				
			||||||
 | 
					              data = scope.bidHistory;
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // Thử lấy từ $parent nếu không thấy
 | 
				
			||||||
 | 
					            if (scope?.$parent?.bidHistory) {
 | 
				
			||||||
 | 
					              data = scope.$parent.bidHistory;
 | 
				
			||||||
 | 
					              break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          } catch (e) {
 | 
				
			||||||
 | 
					            // Angular element có thể lỗi nếu phần tử không hợp lệ
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return data;
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      return historiesData;
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      console.log(
 | 
				
			||||||
 | 
					        `[${this.id}] Error in waitForApiResponse: ${error?.message}`
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async handleUpdateBid({
 | 
					  async handleUpdateBid({
 | 
				
			||||||
    lot_id,
 | 
					    lot_id,
 | 
				
			||||||
    close_time,
 | 
					    close_time,
 | 
				
			||||||
| 
						 | 
					@ -66,6 +108,7 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
    current_price,
 | 
					    current_price,
 | 
				
			||||||
    reserve_price,
 | 
					    reserve_price,
 | 
				
			||||||
    model,
 | 
					    model,
 | 
				
			||||||
 | 
					    metadata,
 | 
				
			||||||
  }) {
 | 
					  }) {
 | 
				
			||||||
    const response = await updateBid(this.id, {
 | 
					    const response = await updateBid(this.id, {
 | 
				
			||||||
      lot_id,
 | 
					      lot_id,
 | 
				
			||||||
| 
						 | 
					@ -74,6 +117,7 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
      current_price,
 | 
					      current_price,
 | 
				
			||||||
      reserve_price: Number(reserve_price) || 0,
 | 
					      reserve_price: Number(reserve_price) || 0,
 | 
				
			||||||
      model,
 | 
					      model,
 | 
				
			||||||
 | 
					      metadata,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response) {
 | 
					    if (response) {
 | 
				
			||||||
| 
						 | 
					@ -122,6 +166,8 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
    // 📌 Chờ phản hồi API từ trang, tối đa 10 giây
 | 
					    // 📌 Chờ phản hồi API từ trang, tối đa 10 giây
 | 
				
			||||||
    const result = await this.waitForApiResponse();
 | 
					    const result = await this.waitForApiResponse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const historiesData = await this.getHistoriesData();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // 📌 Nếu không có dữ liệu trả về thì dừng
 | 
					    // 📌 Nếu không có dữ liệu trả về thì dừng
 | 
				
			||||||
    if (!result) {
 | 
					    if (!result) {
 | 
				
			||||||
      console.log(`⚠️ [${this.id}] No valid data received, skipping update.`);
 | 
					      console.log(`⚠️ [${this.id}] No valid data received, skipping update.`);
 | 
				
			||||||
| 
						 | 
					@ -140,6 +186,9 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
          : null,
 | 
					          : null,
 | 
				
			||||||
        // close_time: close_time && !this.close_time ? String(close_time) : null, // test
 | 
					        // close_time: close_time && !this.close_time ? String(close_time) : null, // test
 | 
				
			||||||
        name: result?.aucTitle || null,
 | 
					        name: result?.aucTitle || null,
 | 
				
			||||||
 | 
					        metadata: {
 | 
				
			||||||
 | 
					          competor_histories: historiesData,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      ["close_time"]
 | 
					      ["close_time"]
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
| 
						 | 
					@ -233,12 +282,10 @@ export class AllbidsProductBid extends ProductBid {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const data = await this.submitBid();
 | 
					      const data = await this.submitBid();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log({ data });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      await this.page_context.reload({ waitUntil: "networkidle0" });
 | 
					      await this.page_context.reload({ waitUntil: "networkidle0" });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const { aucUserMaxBid } = await this.waitForApiResponse();
 | 
					      const { aucUserMaxBid } = await this.waitForApiResponse();
 | 
				
			||||||
      console.log(`📡 [${this.id}] API Response received:`, lotData);
 | 
					      console.log(`📡 [${this.id}] API Response received:`, { aucUserMaxBid });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // 📌 Kiểm tra trạng thái đấu giá từ API
 | 
					      // 📌 Kiểm tra trạng thái đấu giá từ API
 | 
				
			||||||
      if (aucUserMaxBid == this.max_price) {
 | 
					      if (aucUserMaxBid == this.max_price) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue