|
|
@@ -0,0 +1,212 @@ |
|
|
|
"use client"; |
|
|
|
|
|
|
|
import { PoResult } from "@/app/api/po"; |
|
|
|
import { useCallback, useEffect, useMemo, useState } from "react"; |
|
|
|
import { useTranslation } from "react-i18next"; |
|
|
|
import { useRouter, useSearchParams } from "next/navigation"; |
|
|
|
import SearchBox, { Criterion } from "../SearchBox"; |
|
|
|
import SearchResults, { Column } from "../SearchResults"; |
|
|
|
import { EditNote } from "@mui/icons-material"; |
|
|
|
import { Button, Grid, Tab, Tabs, TabsProps, Typography } from "@mui/material"; |
|
|
|
import QrModal from "../PoDetail/QrModal"; |
|
|
|
import { WarehouseResult } from "@/app/api/warehouse"; |
|
|
|
import NotificationIcon from "@mui/icons-material/NotificationImportant"; |
|
|
|
import { useSession } from "next-auth/react"; |
|
|
|
import { defaultPagingController } from "../SearchResults/SearchResults"; |
|
|
|
import { fetchPoListClient, testing } from "@/app/api/po/actions"; |
|
|
|
import dayjs from "dayjs"; |
|
|
|
import { OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; |
|
|
|
import arraySupport from "dayjs/plugin/arraySupport"; |
|
|
|
dayjs.extend(arraySupport); |
|
|
|
|
|
|
|
type Props = { |
|
|
|
po: PoResult[]; |
|
|
|
warehouse: WarehouseResult[]; |
|
|
|
totalCount: number; |
|
|
|
}; |
|
|
|
type SearchQuery = Partial<Omit<PoResult, "id">>; |
|
|
|
type SearchParamNames = keyof SearchQuery; |
|
|
|
|
|
|
|
// cal offset (pageSize) |
|
|
|
// cal limit (pageSize) |
|
|
|
const PoSearch: React.FC<Props> = ({ |
|
|
|
po, |
|
|
|
warehouse, |
|
|
|
totalCount: initTotalCount, |
|
|
|
}) => { |
|
|
|
const [filteredPo, setFilteredPo] = useState<PoResult[]>(po); |
|
|
|
const [filterArgs, setFilterArgs] = useState<Record<string, any>>({}); |
|
|
|
const { t } = useTranslation("purchaseOrder"); |
|
|
|
const router = useRouter(); |
|
|
|
const [pagingController, setPagingController] = useState( |
|
|
|
defaultPagingController |
|
|
|
); |
|
|
|
const [totalCount, setTotalCount] = useState(initTotalCount); |
|
|
|
const searchCriteria: Criterion<SearchParamNames>[] = useMemo(() => { |
|
|
|
var searchCriteria: Criterion<SearchParamNames>[] = [ |
|
|
|
{ label: t("Code"), paramName: "code", type: "text" }, |
|
|
|
{ |
|
|
|
label: t("Status"), |
|
|
|
paramName: "status", |
|
|
|
type: "select-labelled", |
|
|
|
options: [ |
|
|
|
{label: t(`pending`), value: `pending`}, |
|
|
|
{label: t(`receiving`), value: `receiving`}, |
|
|
|
{label: t(`completed`), value: `completed`}, |
|
|
|
] |
|
|
|
}, |
|
|
|
{ |
|
|
|
label: t("Escalated"), |
|
|
|
paramName: "escalated", |
|
|
|
type: "select", |
|
|
|
options: [t("Escalated"), t("NotEscalated")], |
|
|
|
}, |
|
|
|
]; |
|
|
|
return searchCriteria; |
|
|
|
}, [t, po]); |
|
|
|
|
|
|
|
const onDetailClick = useCallback( |
|
|
|
(po: PoResult) => { |
|
|
|
router.push(`/po/edit?id=${po.id}`); |
|
|
|
}, |
|
|
|
[router] |
|
|
|
); |
|
|
|
|
|
|
|
const onDeleteClick = useCallback((po: PoResult) => {}, [router]); |
|
|
|
|
|
|
|
const columns = useMemo<Column<PoResult>[]>( |
|
|
|
() => [ |
|
|
|
{ |
|
|
|
name: "id", |
|
|
|
label: t("Details"), |
|
|
|
onClick: onDetailClick, |
|
|
|
buttonIcon: <EditNote />, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "code", |
|
|
|
label: t("Code"), |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "orderDate", |
|
|
|
label: t("OrderDate"), |
|
|
|
renderCell: (params) => { |
|
|
|
return dayjs(params.orderDate) |
|
|
|
// .add(-1, "month") |
|
|
|
.format(OUTPUT_DATE_FORMAT); |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "supplier", |
|
|
|
label: t("Supplier"), |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "status", |
|
|
|
label: t("Status"), |
|
|
|
renderCell: (params) => { |
|
|
|
return t(`${params.status.toLowerCase()}`); |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
name: "escalated", |
|
|
|
label: t("Escalated"), |
|
|
|
renderCell: (params) => { |
|
|
|
console.log(params.escalated) |
|
|
|
return params.escalated ? ( |
|
|
|
<NotificationIcon color="warning" /> |
|
|
|
) : undefined; |
|
|
|
}, |
|
|
|
}, |
|
|
|
], |
|
|
|
[filteredPo] |
|
|
|
); |
|
|
|
|
|
|
|
const onReset = useCallback(() => { |
|
|
|
setFilteredPo(po); |
|
|
|
}, [po]); |
|
|
|
|
|
|
|
const [isOpenScanner, setOpenScanner] = useState(false); |
|
|
|
const onOpenScanner = useCallback(() => { |
|
|
|
setOpenScanner(true); |
|
|
|
}, []); |
|
|
|
|
|
|
|
const onCloseScanner = useCallback(() => { |
|
|
|
setOpenScanner(false); |
|
|
|
}, []); |
|
|
|
|
|
|
|
const newPageFetch = useCallback( |
|
|
|
async ( |
|
|
|
pagingController: Record<string, number>, |
|
|
|
filterArgs: Record<string, number> |
|
|
|
) => { |
|
|
|
console.log(pagingController); |
|
|
|
console.log(filterArgs); |
|
|
|
const params = { |
|
|
|
...pagingController, |
|
|
|
...filterArgs, |
|
|
|
}; |
|
|
|
const res = await fetchPoListClient(params); |
|
|
|
// const res = await testing(params); |
|
|
|
if (res) { |
|
|
|
console.log(res); |
|
|
|
setFilteredPo(res.records); |
|
|
|
setTotalCount(res.total); |
|
|
|
} |
|
|
|
}, |
|
|
|
[fetchPoListClient] |
|
|
|
); |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
newPageFetch(pagingController, filterArgs); |
|
|
|
}, [newPageFetch, pagingController, filterArgs]); |
|
|
|
return ( |
|
|
|
<> |
|
|
|
<Grid container> |
|
|
|
<Grid item xs={8}> |
|
|
|
<Typography variant="h4" marginInlineEnd={2}> |
|
|
|
{t("Purchase Order")} |
|
|
|
</Typography> |
|
|
|
</Grid> |
|
|
|
<Grid item xs={4} display="flex" justifyContent="end" alignItems="end"> |
|
|
|
<QrModal |
|
|
|
open={isOpenScanner} |
|
|
|
onClose={onCloseScanner} |
|
|
|
warehouse={warehouse} |
|
|
|
/> |
|
|
|
<Button onClick={onOpenScanner}>{t("bind")}</Button> |
|
|
|
</Grid> |
|
|
|
</Grid> |
|
|
|
<> |
|
|
|
<SearchBox |
|
|
|
criteria={searchCriteria} |
|
|
|
onSearch={(query) => { |
|
|
|
console.log(query) |
|
|
|
setFilterArgs({ |
|
|
|
code: query.code, |
|
|
|
status: query.status === "All" ? "" : query.status, |
|
|
|
escalated: query.escalated === 'All' ? undefined : query.escalated === t("Escalated") |
|
|
|
}); |
|
|
|
// setFilteredPo((prev) => |
|
|
|
// po.filter((p) => { |
|
|
|
// return ( |
|
|
|
// p.code.toLowerCase().includes(query.code.toLowerCase()) && |
|
|
|
// (query.status === "All" || t(`${p.status.toLowerCase()}`) === query.status) && |
|
|
|
// (query.escalated === "All" || (p.escalated === Boolean((query.escalated) === t("Escalated")))) |
|
|
|
// ) |
|
|
|
// }) |
|
|
|
// ); |
|
|
|
}} |
|
|
|
onReset={onReset} |
|
|
|
/> |
|
|
|
<SearchResults<PoResult> |
|
|
|
items={filteredPo} |
|
|
|
columns={columns} |
|
|
|
pagingController={pagingController} |
|
|
|
setPagingController={setPagingController} |
|
|
|
totalCount={totalCount} |
|
|
|
isAutoPaging={false} |
|
|
|
/> |
|
|
|
</> |
|
|
|
</> |
|
|
|
); |
|
|
|
}; |
|
|
|
export default PoSearch; |