527 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			527 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
import _ from "lodash";
 | 
						|
import { outBid, pushPrice, updateBid } from "../../system/apis/bid.js";
 | 
						|
import { sendMessage } from "../../system/apis/notification.js";
 | 
						|
import { createOutBidLog } from "../../system/apis/out-bid-log.js";
 | 
						|
import configs from "../../system/config.js";
 | 
						|
import CONSTANTS from "../../system/constants.js";
 | 
						|
import {
 | 
						|
  convertAETtoUTC,
 | 
						|
  isTimeReached,
 | 
						|
  removeFalsyValues,
 | 
						|
  takeSnapshot,
 | 
						|
} from "../../system/utils.js";
 | 
						|
import { ProductBid } from "../product-bid.js";
 | 
						|
 | 
						|
export class LangtonsProductBid extends ProductBid {
 | 
						|
  constructor({ ...prev }) {
 | 
						|
    super(prev);
 | 
						|
  }
 | 
						|
 | 
						|
  // Hàm lấy thời gian kết thúc từ trang web
 | 
						|
  async getCloseTime() {
 | 
						|
    try {
 | 
						|
      // Kiểm tra xem có context của trang web không, nếu không thì trả về null
 | 
						|
      if (!this.page_context) return null;
 | 
						|
 | 
						|
      await this.page_context.waitForSelector(".site-timezone", {
 | 
						|
        timeout: 2000,
 | 
						|
      });
 | 
						|
      const time = await this.page_context.evaluate(() => {
 | 
						|
        const el = document.querySelector(".site-timezone");
 | 
						|
        return el ? el.innerText : null;
 | 
						|
      });
 | 
						|
 | 
						|
      return time ? convertAETtoUTC(time) : null;
 | 
						|
 | 
						|
      // return new Date(Date.now() + 6 * 60 * 1000).toUTCString();
 | 
						|
    } catch (error) {
 | 
						|
      // Nếu có lỗi xảy ra trong quá trình lấy thời gian, trả về null
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  async waitForApiResponse(timeout = 15000) {
 | 
						|
    if (!this.page_context) {
 | 
						|
      console.error(`❌ [${this.id}] Error: page_context is undefined.`);
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
 | 
						|
    return new Promise((resolve) => {
 | 
						|
      const onResponse = async (response) => {
 | 
						|
        try {
 | 
						|
          if (
 | 
						|
            !response ||
 | 
						|
            !response
 | 
						|
              .request()
 | 
						|
              .url()
 | 
						|
              .includes(configs.WEB_CONFIGS.LANGTONS.API_CALL_TO_TRACKING)
 | 
						|
          ) {
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          clearTimeout(timer); // Hủy timeout nếu có phản hồi
 | 
						|
          this.page_context.off("response", onResponse); // Gỡ bỏ listener
 | 
						|
 | 
						|
          const data = await response.json();
 | 
						|
          resolve(data);
 | 
						|
        } catch (error) {
 | 
						|
          console.error(
 | 
						|
            `❌ [${this.id}] Error while parsing response:`,
 | 
						|
            error?.message
 | 
						|
          );
 | 
						|
          resolve(null);
 | 
						|
        }
 | 
						|
      };
 | 
						|
 | 
						|
      const timer = setTimeout(async () => {
 | 
						|
        console.log(
 | 
						|
          `⏳ [${this.id}] Timeout: No response received within ${
 | 
						|
            timeout / 1000
 | 
						|
          }s`
 | 
						|
        );
 | 
						|
        this.page_context?.off("response", onResponse); // Gỡ bỏ listener khi timeout
 | 
						|
 | 
						|
        try {
 | 
						|
          if (!this.page_context.isClosed()) {
 | 
						|
            await this.page_context.reload({ waitUntil: "networkidle0" });
 | 
						|
            console.log(`🔁 [${this.id}] Reload page in waitForApiResponse`);
 | 
						|
          } else {
 | 
						|
            console.log(`⚠️ [${this.id}] Cannot reload, page already closed.`);
 | 
						|
          }
 | 
						|
        } catch (error) {
 | 
						|
          console.error(
 | 
						|
            `❌ [${this.id}] Error reloading page:`,
 | 
						|
            error?.message
 | 
						|
          );
 | 
						|
        }
 | 
						|
 | 
						|
        console.log(`🔁 [${this.id}] Reload page in waitForApiResponse`);
 | 
						|
        resolve(null);
 | 
						|
      }, timeout);
 | 
						|
 | 
						|
      this.page_context.on("response", onResponse);
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  async getName() {
 | 
						|
    try {
 | 
						|
      if (!this.page_context) return null;
 | 
						|
 | 
						|
      await this.page_context.waitForSelector(".product-name", {
 | 
						|
        timeout: 3000,
 | 
						|
      });
 | 
						|
 | 
						|
      return await this.page_context.evaluate(() => {
 | 
						|
        const el = document.querySelector(".product-name");
 | 
						|
        return el ? el.innerText : null;
 | 
						|
      });
 | 
						|
    } catch (error) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  async handleUpdateBid({
 | 
						|
    lot_id,
 | 
						|
    close_time,
 | 
						|
    name,
 | 
						|
    current_price,
 | 
						|
    reserve_price,
 | 
						|
    model,
 | 
						|
  }) {
 | 
						|
    const response = await updateBid(this.id, {
 | 
						|
      lot_id,
 | 
						|
      close_time,
 | 
						|
      name,
 | 
						|
      current_price,
 | 
						|
      reserve_price: Number(reserve_price) || 0,
 | 
						|
      model,
 | 
						|
    });
 | 
						|
 | 
						|
    if (response) {
 | 
						|
      this.lot_id = response.lot_id;
 | 
						|
      this.close_time = response.close_time;
 | 
						|
      this.start_bid_time = response.start_bid_time;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  update = async () => {
 | 
						|
    if (!this.page_context) return;
 | 
						|
 | 
						|
    console.log(`🔄 [${this.id}] Call update for ID: ${this.id}`);
 | 
						|
 | 
						|
    // 📌 Lấy thời gian kết thúc đấu giá từ giao diện
 | 
						|
    const close_time = await this.getCloseTime();
 | 
						|
    console.log(`⏳ [${this.id}] Retrieved close time: ${close_time}`);
 | 
						|
 | 
						|
    // 📌 Lấy tên sản phẩm hoặc thông tin liên quan
 | 
						|
    const name = await this.getName();
 | 
						|
    console.log(`📌 [${this.id}] Retrieved name: ${name}`);
 | 
						|
 | 
						|
    // 📌 Chờ phản hồi API từ trang, tối đa 10 giây
 | 
						|
    const result = await this.waitForApiResponse();
 | 
						|
 | 
						|
    // 📌 Nếu không có dữ liệu trả về thì dừng
 | 
						|
    if (!result) {
 | 
						|
      console.log(`⚠️ [${this.id}] No valid data received, skipping update.`);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // 📌 Loại bỏ các giá trị không hợp lệ và bổ sung thông tin cần thiết
 | 
						|
    const data = removeFalsyValues(
 | 
						|
      {
 | 
						|
        model: result?.pid || null,
 | 
						|
        lot_id: result?.lotId || null,
 | 
						|
        reserve_price: result.lotData?.minimumBid || null,
 | 
						|
        current_price: result.lotData?.currentMaxBid || null,
 | 
						|
        close_time: close_time ? String(close_time) : null,
 | 
						|
        // close_time: close_time && !this.close_time ? String(close_time) : null,
 | 
						|
        name,
 | 
						|
      },
 | 
						|
      // [],
 | 
						|
      ["close_time"]
 | 
						|
    );
 | 
						|
 | 
						|
    console.log(`🚀 [${this.id}] Processed data ready for update`);
 | 
						|
 | 
						|
    // 📌 Gửi dữ liệu cập nhật lên hệ thống
 | 
						|
    await this.handleUpdateBid(data);
 | 
						|
 | 
						|
    console.log("✅ Update successful!");
 | 
						|
 | 
						|
    return { ...response, name, close_time };
 | 
						|
  };
 | 
						|
 | 
						|
  async getContinueShopButton() {
 | 
						|
    try {
 | 
						|
      if (!this.page_context) return null;
 | 
						|
 | 
						|
      await this.page_context.waitForSelector(
 | 
						|
        ".btn.btn-block.btn-primary.error.continue-shopping",
 | 
						|
        { timeout: 3000 }
 | 
						|
      );
 | 
						|
 | 
						|
      return await this.page_context.evaluate(() => {
 | 
						|
        const el = document.querySelector(
 | 
						|
          ".btn.btn-block.btn-primary.error.continue-shopping"
 | 
						|
        );
 | 
						|
 | 
						|
        return el;
 | 
						|
      });
 | 
						|
    } catch (error) {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  async handlePlaceBid() {
 | 
						|
    if (!this.page_context) {
 | 
						|
      console.log(
 | 
						|
        `⚠️ [${this.id}] No page context found, aborting bid process.`
 | 
						|
      );
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    const page = this.page_context;
 | 
						|
 | 
						|
    if (global[`IS_PLACE_BID-${this.id}`]) {
 | 
						|
      console.log(`⚠️ [${this.id}] Bid is already in progress, skipping.`);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    try {
 | 
						|
      console.log(`🔄 [${this.id}] Starting bid process...`);
 | 
						|
      global[`IS_PLACE_BID-${this.id}`] = true;
 | 
						|
 | 
						|
      const continueShopBtn = await this.getContinueShopButton();
 | 
						|
      if (continueShopBtn) {
 | 
						|
        console.log(
 | 
						|
          `⚠️ [${this.id}] Outbid detected, calling outBid function.`
 | 
						|
        );
 | 
						|
        await outBid(this.id);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // Kiểm tra nếu giá hiện tại lớn hơn giá tối đa cộng thêm giá cộng thêm
 | 
						|
      if (this.current_price > this.max_price + this.plus_price) {
 | 
						|
        console.log(`⚠️ [${this.id}] Outbid bid`); // Ghi log cảnh báo nếu giá hiện tại vượt quá mức tối đa cho phép
 | 
						|
        return; // Dừng hàm nếu giá đã vượt qua giới hạn
 | 
						|
      }
 | 
						|
 | 
						|
      // Kiểm tra thời gian bid
 | 
						|
      if (this.start_bid_time && !isTimeReached(this.start_bid_time)) {
 | 
						|
        console.log(
 | 
						|
          `⏳ [${this.id}] Not yet time to bid. Skipping Product: ${
 | 
						|
            this.name || "None"
 | 
						|
          }`
 | 
						|
        );
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      // Đợi phản hồi từ API
 | 
						|
      const response = await this.waitForApiResponse();
 | 
						|
 | 
						|
      // Kiểm tra nếu phản hồi không tồn tại hoặc nếu giá đấu của người dùng bằng với giá tối đa hiện tại
 | 
						|
      if (
 | 
						|
        !response ||
 | 
						|
        (response?.lotData?.myBid &&
 | 
						|
          response.lotData.myBid == this.max_price) ||
 | 
						|
        response?.lotData?.minimumBid > this.max_price
 | 
						|
      ) {
 | 
						|
        console.log(
 | 
						|
          `⚠️ [${this.id}] No response or myBid equals max_price:`,
 | 
						|
          response
 | 
						|
        ); // Ghi log nếu không có phản hồi hoặc giá đấu của người dùng bằng giá tối đa
 | 
						|
        return; // Nếu không có phản hồi hoặc giá đấu bằng giá tối đa thì dừng hàm
 | 
						|
      }
 | 
						|
 | 
						|
      // Kiểm tra nếu dữ liệu trong response có tồn tại và trạng thái đấu giá (bidStatus) không phải là 'None'
 | 
						|
      if (
 | 
						|
        response.lotData &&
 | 
						|
        response.lotData?.bidStatus !== "None" &&
 | 
						|
        this.max_price == response?.lotData.myBid
 | 
						|
      ) {
 | 
						|
        console.log(
 | 
						|
          `✔️ [${this.id}] Bid status is not 'None'. Current bid status:`,
 | 
						|
          response.lotData?.bidStatus
 | 
						|
        ); // Ghi log nếu trạng thái đấu giá không phải 'None'
 | 
						|
        return; // Nếu trạng thái đấu giá không phải là 'None', dừng hàm
 | 
						|
      }
 | 
						|
 | 
						|
      const bidHistoriesItem = _.maxBy(this.histories, "price");
 | 
						|
      console.log(`📜 [${this.id}] Current bid history:`, this.histories);
 | 
						|
 | 
						|
      if (
 | 
						|
        bidHistoriesItem &&
 | 
						|
        bidHistoriesItem?.price === this.current_price &&
 | 
						|
        this.max_price == response?.lotData.myBid
 | 
						|
      ) {
 | 
						|
        console.log(
 | 
						|
          `🔄 [${this.id}] You have already bid on this item! (Bid Price: ${bidHistoriesItem.price})`
 | 
						|
        );
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      console.log(
 | 
						|
        `💰 [${this.id}] Placing a bid with amount: ${this.reserve_price}`
 | 
						|
      );
 | 
						|
 | 
						|
      // 📌 Làm rỗng ô input trước khi nhập giá đấu
 | 
						|
      await page.evaluate(() => {
 | 
						|
        document.querySelector("#place-bid").value = "";
 | 
						|
      });
 | 
						|
 | 
						|
      console.log(`📝 [${this.id}] Cleared bid input field.`);
 | 
						|
 | 
						|
      // 📌 Nhập giá đấu vào ô input
 | 
						|
      await page.type("#place-bid", String(this.max_price), { delay: 800 });
 | 
						|
      console.log(`✅ [${this.id}] Entered bid amount: ${this.max_price}`);
 | 
						|
 | 
						|
      // 📌 Lấy giá trị thực tế từ ô input sau khi nhập
 | 
						|
      const bidValue = await page.evaluate(
 | 
						|
        () => document.querySelector("#place-bid").value
 | 
						|
      );
 | 
						|
      console.log(`🔍 Entered bid value: ${bidValue}`);
 | 
						|
 | 
						|
      // 📌 Kiểm tra nếu giá trị nhập vào không khớp với giá trị mong muốn
 | 
						|
      if (!bidValue || bidValue !== String(this.max_price)) {
 | 
						|
        console.log(`❌ Incorrect bid amount! Received: ${bidValue}`);
 | 
						|
        return; // Dừng thực hiện nếu giá trị nhập sai
 | 
						|
      }
 | 
						|
 | 
						|
      // 📌 Nhấn nút "Place Bid"
 | 
						|
      await page.click(
 | 
						|
        ".place-bid-submit .btn.btn-primary.btn-block.place-bid-btn",
 | 
						|
        { delay: 5000 }
 | 
						|
      );
 | 
						|
      console.log(`🖱️ [${this.id}] Clicked "Place Bid" button.`);
 | 
						|
 | 
						|
      console.log(`📩 [${this.id}] Bid submitted, waiting for navigation...`);
 | 
						|
 | 
						|
      // 📌 Chờ trang load lại để cập nhật trạng thái đấu giá
 | 
						|
      await page.waitForNavigation({
 | 
						|
        timeout: 8000,
 | 
						|
        waitUntil: "domcontentloaded",
 | 
						|
      });
 | 
						|
 | 
						|
      console.log(`🔄 [${this.id}] Page reloaded, checking bid status...`);
 | 
						|
 | 
						|
      const { lotData } = await this.waitForApiResponse();
 | 
						|
      console.log(`📡 [${this.id}] API Response received:`, lotData);
 | 
						|
 | 
						|
      // 📌 Kiểm tra trạng thái đấu giá từ API
 | 
						|
      if (lotData?.myBid == this.max_price) {
 | 
						|
        console.log(`📸 [${this.id}] Taking bid success snapshot...`);
 | 
						|
        await takeSnapshot(
 | 
						|
          page,
 | 
						|
          this,
 | 
						|
          "bid-success",
 | 
						|
          CONSTANTS.TYPE_IMAGE.SUCCESS
 | 
						|
        );
 | 
						|
 | 
						|
        sendMessage(this);
 | 
						|
 | 
						|
        console.log(`✅ [${this.id}] Bid placed successfully!`);
 | 
						|
        return;
 | 
						|
      }
 | 
						|
 | 
						|
      console.log(
 | 
						|
        `⚠️ [${this.id}] Bid action completed, but status is still "None".`
 | 
						|
      );
 | 
						|
    } catch (error) {
 | 
						|
      console.log(`🚨 [${this.id}] Error placing bid: ${error.message}`);
 | 
						|
    } finally {
 | 
						|
      console.log(`🔚 [${this.id}] Resetting bid flag.`);
 | 
						|
      global[`IS_PLACE_BID-${this.id}`] = false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  async handleCreateLogsOnServer(data) {
 | 
						|
    const values = data.map((item) => {
 | 
						|
      return {
 | 
						|
        model: item.pid,
 | 
						|
        lot_id: item.lotId,
 | 
						|
        out_price: item.lotData.minimumBid || 0,
 | 
						|
        raw_data: JSON.stringify(item),
 | 
						|
      };
 | 
						|
    });
 | 
						|
 | 
						|
    await createOutBidLog(values);
 | 
						|
  }
 | 
						|
 | 
						|
  async gotoLink() {
 | 
						|
    const page = this.page_context;
 | 
						|
 | 
						|
    if (page.isClosed()) {
 | 
						|
      console.error(`❌ [${this.id}] Page has been closed, cannot navigate.`);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    console.log(`🔄 [${this.id}] Starting the bidding process...`);
 | 
						|
 | 
						|
    try {
 | 
						|
      console.log(`🌐 [${this.id}] Navigating to: ${this.url} ...`);
 | 
						|
      await page.goto(this.url, { waitUntil: "networkidle2" });
 | 
						|
      console.log(`✅ [${this.id}] Successfully navigated to: ${this.url}`);
 | 
						|
 | 
						|
      console.log(`🖥️ [${this.id}] Bringing tab to the foreground...`);
 | 
						|
      await page.bringToFront();
 | 
						|
 | 
						|
      console.log(`🛠️ [${this.id}] Setting custom user agent...`);
 | 
						|
      await page.setUserAgent(
 | 
						|
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
 | 
						|
      );
 | 
						|
 | 
						|
      console.log(`🎯 [${this.id}] Listening for API responses...`);
 | 
						|
 | 
						|
      // // 🔥 Xóa tất cả event chặn request trước khi thêm mới
 | 
						|
      // page.removeAllListeners('request');
 | 
						|
 | 
						|
      // await page.setRequestInterception(true);
 | 
						|
 | 
						|
      // page.on('request', (request) => {
 | 
						|
      //     if (request.url().includes(configs.WEB_CONFIGS.LANGTONS.API_CALL_TO_TRACKING)) {
 | 
						|
      //         console.log('🚀 Fake response cho request:', request.url());
 | 
						|
 | 
						|
      //         const fakeData = fs.readFileSync('./data/fake-out-lot-langtons.json', 'utf8');
 | 
						|
 | 
						|
      //         request.respond({
 | 
						|
      //             status: 200,
 | 
						|
      //             contentType: 'application/json',
 | 
						|
      //             body: fakeData,
 | 
						|
      //         });
 | 
						|
      //     } else {
 | 
						|
      //         try {
 | 
						|
      //             request.continue(); // ⚠️ Chỉ tiếp tục nếu request chưa bị chặn
 | 
						|
      //         } catch (error) {
 | 
						|
      //             console.error('⚠️ Lỗi khi tiếp tục request:', error.message);
 | 
						|
      //         }
 | 
						|
      //     }
 | 
						|
      // });
 | 
						|
 | 
						|
      const onResponse = async (response) => {
 | 
						|
        const url = response?.request()?.url();
 | 
						|
        if (
 | 
						|
          !url ||
 | 
						|
          !url.includes(configs.WEB_CONFIGS.LANGTONS.API_CALL_TO_TRACKING)
 | 
						|
        ) {
 | 
						|
          return;
 | 
						|
        }
 | 
						|
 | 
						|
        try {
 | 
						|
          const { lotData, ...prev } = await response.json();
 | 
						|
          console.log(`📜 [${this.id}] Received lotData:`, lotData);
 | 
						|
 | 
						|
          if (!lotData || lotData.lotId !== this.lot_id) {
 | 
						|
            console.log(
 | 
						|
              `⚠️ [${this.id}] Ignored response for lotId: ${lotData?.lotId}`
 | 
						|
            );
 | 
						|
 | 
						|
            if (!this.page_context.isClosed()) {
 | 
						|
              await this.page_context.reload({ waitUntil: "networkidle0" });
 | 
						|
            }
 | 
						|
 | 
						|
            console.log(`🔁 [${this.id}] Reload page in gotoLink`);
 | 
						|
            return;
 | 
						|
          }
 | 
						|
 | 
						|
          console.log(`🔍 [${this.id}] Checking bid status...`);
 | 
						|
 | 
						|
          if (["Outbid"].includes(lotData?.bidStatus)) {
 | 
						|
            console.log(
 | 
						|
              `⚠️ [${this.id}] Outbid detected, attempting to place a new bid...`
 | 
						|
            );
 | 
						|
 | 
						|
            this.handleCreateLogsOnServer([{ lotData, ...prev }]);
 | 
						|
          } else if (["Winning"].includes(lotData?.bidStatus)) {
 | 
						|
            const bidHistoriesItem = _.maxBy(this.histories, "price");
 | 
						|
 | 
						|
            if (
 | 
						|
              !bidHistoriesItem ||
 | 
						|
              bidHistoriesItem?.price != lotData?.currentMaxBid
 | 
						|
            ) {
 | 
						|
              pushPrice({
 | 
						|
                bid_id: this.id,
 | 
						|
                price: lotData?.currentMaxBid,
 | 
						|
              });
 | 
						|
            }
 | 
						|
          }
 | 
						|
 | 
						|
          if (
 | 
						|
            lotData.myBid &&
 | 
						|
            this.max_price &&
 | 
						|
            this.max_price != lotData.myBid
 | 
						|
          ) {
 | 
						|
            this.handlePlaceBid();
 | 
						|
          }
 | 
						|
        } catch (error) {
 | 
						|
          console.error(`🚨 [${this.id}] Error parsing API response:`, error);
 | 
						|
        }
 | 
						|
      };
 | 
						|
 | 
						|
      console.log(`🔄 [${this.id}] Removing previous response listeners...`);
 | 
						|
      this.page_context.off("response", onResponse);
 | 
						|
 | 
						|
      console.log(`📡 [${this.id}] Attaching new response listener...`);
 | 
						|
      this.page_context.on("response", onResponse);
 | 
						|
 | 
						|
      console.log(`✅ [${this.id}] Navigation setup complete.`);
 | 
						|
    } catch (error) {
 | 
						|
      console.error(`❌ [${this.id}] Error during navigation:`, error);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  action = async () => {
 | 
						|
    try {
 | 
						|
      const page = this.page_context;
 | 
						|
 | 
						|
      // 📌 Kiểm tra nếu trang chưa tải đúng URL thì điều hướng đến URL mục tiêu
 | 
						|
      if (!page.url() || !page.url().includes(this.url)) {
 | 
						|
        console.log(`🔄 [${this.id}] Navigating to target URL: ${this.url}`);
 | 
						|
        await this.gotoLink();
 | 
						|
      }
 | 
						|
 | 
						|
      await this.handlePlaceBid();
 | 
						|
    } catch (error) {
 | 
						|
      console.error(`🚨 [${this.id}] Error navigating the page: ${error}`);
 | 
						|
    }
 | 
						|
  };
 | 
						|
}
 |