411 lines
11 KiB
TypeScript
411 lines
11 KiB
TypeScript
import { ActionIcon, Badge, Box, Menu, Text, Tooltip } from "@mantine/core";
|
|
import { useDisclosure } from "@mantine/hooks";
|
|
import {
|
|
IconAd,
|
|
IconAdOff,
|
|
IconEdit,
|
|
IconHammer,
|
|
IconHistory,
|
|
IconMenu,
|
|
IconTrash,
|
|
} from "@tabler/icons-react";
|
|
import _ from "lodash";
|
|
import { useMemo, useRef, useState } from "react";
|
|
import { deleteBid, deletesBid, getBids, toggleBid } from "../apis/bid";
|
|
import {
|
|
BidModal,
|
|
ShowHistoriesBidGraysApiModal,
|
|
ShowHistoriesBidPicklesApiModal,
|
|
ShowHistoriesModal,
|
|
} from "../components/bid";
|
|
import Table from "../lib/table/table";
|
|
import { IColumn, TRefTableFn } from "../lib/table/type";
|
|
import { useConfirmStore } from "../lib/zustand/use-confirm";
|
|
import { mappingStatusColors } from "../system/constants";
|
|
import { IBid } from "../system/type";
|
|
import { formatTime } from "../utils";
|
|
import constants, { haveHistories } from "../constant";
|
|
|
|
export default function Bids() {
|
|
const refTableFn: TRefTableFn<IBid> = useRef({});
|
|
|
|
const [clickData, setClickData] = useState<IBid | null>(null);
|
|
|
|
const { setConfirm } = useConfirmStore();
|
|
|
|
const [openedHistories, historiesModel] = useDisclosure(false);
|
|
const [openedHistoriesGraysApi, historiesGraysApiModel] =
|
|
useDisclosure(false);
|
|
|
|
const [openedHistoriesPicklesApi, historiesPicklesApiModel] =
|
|
useDisclosure(false);
|
|
const [openedBid, bidModal] = useDisclosure(false);
|
|
|
|
const columns: IColumn<IBid>[] = [
|
|
{
|
|
key: "id",
|
|
title: "ID",
|
|
typeFilter: "number",
|
|
},
|
|
{
|
|
key: "name",
|
|
title: "Name",
|
|
typeFilter: "text",
|
|
},
|
|
{
|
|
key: "web_bid",
|
|
title: "Web",
|
|
typeFilter: "text",
|
|
renderRow(row) {
|
|
return <span>{row.web_bid.origin_url}</span>;
|
|
},
|
|
},
|
|
{
|
|
key: "lot_id",
|
|
title: "Lot ID",
|
|
typeFilter: "text",
|
|
},
|
|
{
|
|
key: "model",
|
|
title: "Model",
|
|
typeFilter: "text",
|
|
},
|
|
|
|
{
|
|
key: "plus_price",
|
|
title: "Plus price",
|
|
typeFilter: "number",
|
|
},
|
|
{
|
|
key: "max_price",
|
|
title: "Max price",
|
|
typeFilter: "number",
|
|
},
|
|
{
|
|
key: "current_price",
|
|
title: "Current price",
|
|
typeFilter: "number",
|
|
},
|
|
{
|
|
key: "reserve_price",
|
|
title: "Reserve price",
|
|
typeFilter: "number",
|
|
},
|
|
{
|
|
key: "histories",
|
|
title: "Current bid",
|
|
typeFilter: "none",
|
|
renderRow(row) {
|
|
const bidPrice = _.maxBy(row.histories, "price");
|
|
|
|
return <Text>{bidPrice ? bidPrice.price : "None"}</Text>;
|
|
},
|
|
},
|
|
{
|
|
key: "start_bid_time",
|
|
title: "Start bid",
|
|
typeFilter: "text",
|
|
renderRow(row) {
|
|
return (
|
|
<Tooltip hidden={!row.start_bid_time} label={row.start_bid_time}>
|
|
<Text size="sm">
|
|
{row.start_bid_time
|
|
? formatTime(row.start_bid_time, "HH:mm:ss DD/MM/YYYY")
|
|
: "None"}
|
|
</Text>
|
|
</Tooltip>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
key: "close_time",
|
|
title: "Close time",
|
|
typeFilter: "text",
|
|
renderRow(row) {
|
|
return (
|
|
<Tooltip hidden={!row.close_time} label={row.close_time}>
|
|
<Text size="sm">
|
|
{row.close_time
|
|
? formatTime(row.close_time, "HH:mm:ss DD/MM/YYYY")
|
|
: "None"}
|
|
</Text>
|
|
</Tooltip>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
key: "status",
|
|
title: "Status",
|
|
typeFilter: "text",
|
|
renderRow(row) {
|
|
return (
|
|
<Box className="flex items-center justify-center">
|
|
<Badge color={mappingStatusColors[row.status]} size="sm">
|
|
{row.status}
|
|
</Badge>
|
|
</Box>
|
|
);
|
|
},
|
|
},
|
|
];
|
|
|
|
const handleDelete = (bid: IBid) => {
|
|
setConfirm({
|
|
title: "Delete ?",
|
|
message: "This bid will be delete",
|
|
handleOk: async () => {
|
|
await deleteBid(bid);
|
|
|
|
if (refTableFn.current?.fetchData) {
|
|
refTableFn.current.fetchData();
|
|
}
|
|
},
|
|
});
|
|
};
|
|
|
|
const handleToggleBid = async (bid: IBid) => {
|
|
const isEnable =
|
|
bid.status === "biding" ? true : bid.status === "out-bid" ? false : true;
|
|
|
|
setConfirm({
|
|
title: (isEnable ? "Disable " : "Enable ") + "ID: " + bid.id,
|
|
message: "This bid will be " + (isEnable ? "disable " : "enable "),
|
|
handleOk: async () => {
|
|
await toggleBid(bid);
|
|
|
|
if (refTableFn.current?.fetchData) {
|
|
refTableFn.current.fetchData();
|
|
}
|
|
},
|
|
okButton: {
|
|
value: isEnable ? "Disable " : "Enable ",
|
|
color: isEnable ? "red" : "blue",
|
|
},
|
|
});
|
|
};
|
|
|
|
const table = useMemo(() => {
|
|
return (
|
|
<Table
|
|
onClickRow={(row) => {
|
|
window.open(row.url, "_blank");
|
|
}}
|
|
tableChildProps={{
|
|
trbody: {
|
|
className: "cursor-pointer",
|
|
},
|
|
}}
|
|
actionsOptions={{
|
|
actions: [
|
|
{
|
|
key: "add",
|
|
title: "Add",
|
|
callback: () => {
|
|
bidModal.open();
|
|
},
|
|
},
|
|
{
|
|
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,
|
|
},
|
|
],
|
|
}}
|
|
refTableFn={refTableFn}
|
|
striped
|
|
showLoading={true}
|
|
highlightOnHover
|
|
styleDefaultHead={{
|
|
justifyContent: "flex-start",
|
|
width: "fit-content",
|
|
}}
|
|
options={{
|
|
query: getBids,
|
|
pathToData: "data.data",
|
|
keyOptions: {
|
|
last_page: "lastPage",
|
|
per_page: "perPage",
|
|
from: "from",
|
|
to: "to",
|
|
total: "total",
|
|
},
|
|
}}
|
|
rows={[]}
|
|
withColumnBorders
|
|
showChooses={true}
|
|
withTableBorder
|
|
columns={columns}
|
|
actions={{
|
|
title: <Box className="w-full text-center">Action</Box>,
|
|
body: (row) => {
|
|
return (
|
|
<Menu shadow="md" width={200}>
|
|
<Menu.Target>
|
|
<Box
|
|
onClick={(e) => e.stopPropagation()}
|
|
className="flex w-full items-center justify-center"
|
|
>
|
|
<ActionIcon size="sm" variant="light">
|
|
<IconMenu size={14} />
|
|
</ActionIcon>
|
|
</Box>
|
|
</Menu.Target>
|
|
|
|
<Menu.Dropdown onClick={(e) => e.stopPropagation()}>
|
|
<Menu.Item
|
|
onClick={() => {
|
|
setClickData(row);
|
|
bidModal.open();
|
|
}}
|
|
leftSection={<IconEdit size={14} />}
|
|
>
|
|
Edit
|
|
</Menu.Item>
|
|
|
|
<Menu.Item
|
|
onClick={() => {
|
|
setClickData(row);
|
|
historiesModel.open();
|
|
}}
|
|
leftSection={<IconHistory size={14} />}
|
|
>
|
|
Histories
|
|
</Menu.Item>
|
|
{haveHistories.includes(row?.web_bid.origin_url) && (
|
|
<Menu.Item
|
|
onClick={() => {
|
|
setClickData(row);
|
|
switch (row.web_bid.origin_url) {
|
|
case constants.grays: {
|
|
historiesGraysApiModel.open();
|
|
break;
|
|
}
|
|
case constants.pickles: {
|
|
historiesPicklesApiModel.open();
|
|
break;
|
|
}
|
|
default: {
|
|
historiesGraysApiModel.open();
|
|
}
|
|
}
|
|
}}
|
|
leftSection={<IconHammer size={14} />}
|
|
>
|
|
Bids
|
|
</Menu.Item>
|
|
)}
|
|
|
|
<Menu.Item
|
|
disabled={row.status === "win-bid"}
|
|
onClick={() => handleToggleBid(row)}
|
|
leftSection={
|
|
row.status === "biding" ? (
|
|
<IconAdOff size={14} />
|
|
) : (
|
|
<IconAd size={14} />
|
|
)
|
|
}
|
|
>
|
|
{row.status === "biding" ? "Disable" : "Enable"}
|
|
</Menu.Item>
|
|
|
|
<Menu.Item
|
|
onClick={() => handleDelete(row)}
|
|
leftSection={<IconTrash color="red" size={14} />}
|
|
>
|
|
Delete
|
|
</Menu.Item>
|
|
</Menu.Dropdown>
|
|
</Menu>
|
|
);
|
|
},
|
|
}}
|
|
rowKey="id"
|
|
/>
|
|
);
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, []);
|
|
|
|
return (
|
|
<Box>
|
|
{table}
|
|
<ShowHistoriesModal
|
|
opened={openedHistories}
|
|
onClose={() => {
|
|
historiesModel.close();
|
|
setClickData(null);
|
|
}}
|
|
data={clickData}
|
|
/>
|
|
<BidModal
|
|
onUpdated={() => {
|
|
if (refTableFn.current?.fetchData) {
|
|
refTableFn.current.fetchData();
|
|
}
|
|
|
|
setClickData(null);
|
|
}}
|
|
opened={openedBid}
|
|
onClose={() => {
|
|
bidModal.close();
|
|
|
|
setClickData(null);
|
|
}}
|
|
data={clickData}
|
|
/>
|
|
{/* Grays */}
|
|
{openedHistoriesGraysApi && (
|
|
<ShowHistoriesBidGraysApiModal
|
|
onUpdated={() => {
|
|
if (refTableFn.current?.fetchData) {
|
|
refTableFn.current.fetchData();
|
|
}
|
|
|
|
setClickData(null);
|
|
}}
|
|
opened={openedHistoriesGraysApi}
|
|
onClose={() => {
|
|
historiesGraysApiModel.close();
|
|
|
|
setClickData(null);
|
|
}}
|
|
data={clickData}
|
|
/>
|
|
)}
|
|
|
|
{openedHistoriesPicklesApi && (
|
|
<ShowHistoriesBidPicklesApiModal
|
|
onUpdated={() => {
|
|
if (refTableFn.current?.fetchData) {
|
|
refTableFn.current.fetchData();
|
|
}
|
|
|
|
setClickData(null);
|
|
}}
|
|
opened={true}
|
|
onClose={() => {
|
|
historiesPicklesApiModel.close();
|
|
setClickData(null);
|
|
}}
|
|
data={clickData}
|
|
/>
|
|
)}
|
|
</Box>
|
|
);
|
|
}
|