bid-tool/auto-bid-admin/src/components/dashboard/working-page.tsx

239 lines
7.4 KiB
TypeScript

import { Badge, Box, Button, Image, Text, Tooltip } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import moment from "moment";
import { useEffect, useState } from "react";
import { Socket } from "socket.io-client";
import { getImagesWorking } from "../../apis/bid";
import { useStatusToolStore } from "../../lib/zustand/use-status-tool-store";
import { IBid, IWebBid } from "../../system/type";
import { cn, extractDomainSmart, findNearestClosingChild, isTimeReached, stringToColor, subtractSeconds } from "../../utils";
import ShowImageModal from "./show-image-modal";
export interface IWorkingPageProps {
data: (IBid | IWebBid) & { type: string };
socket: Socket;
}
export default function WorkingPage({ data, socket }: IWorkingPageProps) {
const fallbackSrc =
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRGh5WFH8TOIfRKxUrIgJZoDCs1yvQ4hIcppw&s";
const [opened, { open, close }] = useDisclosure(false);
const [imageSrc, setImageSrc] = useState<string | null>(null);
const [lastUpdate, setLastUpdate] = useState<Date | null>(null);
const [payloadLoginStatus, setPayloadLoginStatus] = useState<{
data: IWebBid;
login_status: boolean;
} | null>(null);
const { statusTool } = useStatusToolStore();
function isIBid(obj: IBid | IWebBid): obj is IBid {
return "name" in obj;
}
const renderUrl = (
{ type, id }: (IBid | IWebBid) & { type: string },
name: string
) => {
return `${import.meta.env.VITE_BASE_URL}bids/status-working/${type
.replace("_", "-")
.toLowerCase()}/${id}/${name}`;
};
const extractTime = (filename: string) => {
return Number(filename.split("-")[0]) || 0;
};
const statusLabel = () => {
if (
statusTool &&
statusTool === "online" &&
payloadLoginStatus?.login_status
) {
return "logined";
}
return !statusTool || statusTool !== "online" ? "Unknown" : "logout";
};
useEffect(() => {
const updateImage = ({
type,
id,
filename,
}: {
type: string;
filename: string;
id: IBid["id"];
}) => {
if (type == data.type && id == data.id) {
setLastUpdate(new Date(extractTime(filename)));
setImageSrc(renderUrl(data, filename));
}
};
socket.on("working", updateImage);
return () => {
socket.off("working", updateImage);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [socket, data.id, data.type]);
useEffect(() => {
const onLoginStatus = (data: { data: IWebBid; login_status: boolean }) => {
setPayloadLoginStatus(data);
};
const origin_url = isIBid(data) ? data.web_bid.origin_url : data.origin_url;
socket.on(`login-status.${origin_url}`, onLoginStatus);
return () => {
socket.off(`login-status.${origin_url}`, onLoginStatus);
};
}, [data, socket]);
useEffect(() => {
(async () => {
const result = await getImagesWorking(data);
if (!result || !result.data) return;
const filename = result.data[0];
setImageSrc(renderUrl(data, filename));
setLastUpdate(new Date(extractTime(filename)));
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
if(!isIBid(data)){
console.log(data)
}
return (
<>
<Box
className={cn("rounded-md overflow-hidden relative shadow-lg", {
["border border-green-800"]: payloadLoginStatus?.login_status,
["border border-red-800"]: !payloadLoginStatus?.login_status,
})}
>
<Image
radius="md"
h={300}
style={{
objectFit: "cover",
}}
fallbackSrc={fallbackSrc}
src={imageSrc}
/>
<Box className="absolute bg-black/60 inset-0 flex items-center justify-center text-white font-bold flex-col gap-2 p-4 rounded-lg transition duration-300 hover:bg-opacity-70">
<Text className="text-lg tracking-wide text-center font-bold">
{isIBid(data) ? data.name : "Tracking page"}
</Text>
{isIBid(data) && (
<Text className="text-xs tracking-wide">{`Max price: $${data.max_price}`}</Text>
)}
{isIBid(data) && (
<Text className="text-xs tracking-wide">{`Current price: $${data.current_price}`}</Text>
)}
<Text className="text-sm italic opacity-80">
{moment(lastUpdate).format("HH:mm:ss DD/MM/YYYY")}
</Text>
{!isIBid(data) && <Tooltip label={'Time to tracking'}><Text>{`TT: ${moment(subtractSeconds(findNearestClosingChild(data)?.close_time || '', data.early_tracking_seconds)).format(
"HH:mm:ss DD/MM/YYYY"
)}`}</Text></Tooltip>}
<Box className="flex items-center gap-3">
{isIBid(data) && (
<Tooltip label={'Close time'}>
<Text
style={{ fontSize: "12px" }}
className="tracking-wide"
>{`CLT: ${moment(data.close_time).format(
"HH:mm:ss DD/MM/YYYY"
)}`}</Text>
</Tooltip>
)}
{isIBid(data) &&
data.close_time &&
!isTimeReached(
subtractSeconds(
data.close_time,
data.web_bid?.early_tracking_seconds || 0
)
) && (
<Tooltip label={'Time to tracking'}>
<Text
style={{ fontSize: "12px" }}
className="tracking-wide"
>{`TT: ${moment(
subtractSeconds(
data.close_time,
data.web_bid?.early_tracking_seconds || 0
)
).format("HH:mm:ss DD/MM/YYYY")}`}</Text>
</Tooltip>
)}
</Box>
<Box className="flex items-center gap-4">
<Button
size="xs"
color="green"
onClick={open}
className="bg-white text-black px-4 py-2 rounded-md shadow-md hover:bg-gray-200 transition"
>
Show
</Button>
<Button
target="_blank"
component="a"
size="xs"
href={data.url || "/"}
className="bg-white text-black px-4 py-2 rounded-md shadow-md hover:bg-gray-200 transition"
>
Link
</Button>
</Box>
</Box>
<Box className="absolute top-2.5 left-2.5 flex items-center gap-2">
<Badge
color={payloadLoginStatus?.login_status ? "green" : "red"}
size="xs"
>
{statusLabel()}
</Badge>
<Badge
color={stringToColor(
isIBid(data) ? extractDomainSmart(data.web_bid.origin_url) : extractDomainSmart(data.origin_url)
)}
size="xs"
>
{isIBid(data) ? extractDomainSmart(data.web_bid.origin_url) : extractDomainSmart(data.origin_url)}
</Badge>
</Box>
</Box>
<ShowImageModal
src={imageSrc || fallbackSrc}
fallbackSrc={fallbackSrc}
opened={opened}
onClose={close}
/>
</>
);
}