diff --git a/src/app/(main)/do/page.tsx b/src/app/(main)/do/page.tsx
index 3ec9163..d58862d 100644
--- a/src/app/(main)/do/page.tsx
+++ b/src/app/(main)/do/page.tsx
@@ -19,9 +19,6 @@ const DeliveryOrder: React.FC = async () => {
flexWrap={"wrap"}
rowGap={2}
>
-
- {t("Delivery Order")}
-
}>
diff --git a/src/app/api/do/actions.tsx b/src/app/api/do/actions.tsx
index e69de29..96f1717 100644
--- a/src/app/api/do/actions.tsx
+++ b/src/app/api/do/actions.tsx
@@ -0,0 +1,14 @@
+"use server";
+import { BASE_API_URL } from "@/config/api";
+// import { ServerFetchError, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
+import { revalidateTag } from "next/cache";
+import { cache } from "react";
+import { serverFetchJson } from "@/app/utils/fetchUtil";
+import { QcItemResult } from "../settings/qcItem";
+import { RecordsRes } from "../utils";
+import { DoResult } from ".";
+import { GridRowId, GridRowSelectionModel } from "@mui/x-data-grid";
+
+export interface CreateConsoDoInput {
+ ids: GridRowSelectionModel
+}
diff --git a/src/app/api/do/index.tsx b/src/app/api/do/index.tsx
index 31494a8..624558c 100644
--- a/src/app/api/do/index.tsx
+++ b/src/app/api/do/index.tsx
@@ -6,6 +6,7 @@ export interface DoResult {
id: number,
code: string,
orderDate: string,
+ estimatedArrivalDate: string,
status: string,
shopName: string,
}
diff --git a/src/components/DoDetail/DoDetail.tsx b/src/components/DoDetail/DoDetail.tsx
new file mode 100644
index 0000000..7ea87e2
--- /dev/null
+++ b/src/components/DoDetail/DoDetail.tsx
@@ -0,0 +1,3 @@
+"use client"
+
+// const doDetail =
\ No newline at end of file
diff --git a/src/components/DoSearch/DoSearch.tsx b/src/components/DoSearch/DoSearch.tsx
index 8230620..db94c5b 100644
--- a/src/components/DoSearch/DoSearch.tsx
+++ b/src/components/DoSearch/DoSearch.tsx
@@ -1,6 +1,6 @@
"use client";
-import { DoResult } from "@/app/api/do"
+import { DoResult } from "@/app/api/do";
import { useRouter } from "next/navigation";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
@@ -11,105 +11,289 @@ import { arrayToDateString, arrayToDayjs } from "@/app/utils/formatUtil";
import SearchBox from "../SearchBox/SearchBox";
import SearchResults from "../SearchResults/SearchResults";
import { EditNote } from "@mui/icons-material";
+import InputDataGrid from "../InputDataGrid";
+import { CreateConsoDoInput } from "@/app/api/do/actions";
+import { TableRow } from "../InputDataGrid/InputDataGrid";
+import { FooterPropsOverrides, GridColDef, GridRowModel, GridToolbarContainer, useGridApiRef } from "@mui/x-data-grid";
+import {
+ FormProvider,
+ SubmitErrorHandler,
+ SubmitHandler,
+ useForm,
+} from "react-hook-form";
+import { Box, Button, Grid, Stack, Typography } from "@mui/material";
+import StyledDataGrid from "../StyledDataGrid";
+import { GridRowSelectionModel } from "@mui/x-data-grid";
type Props = {
- dos: DoResult[]
-}
+ dos: DoResult[];
+};
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
+// put all this into a new component
+// ConsoDoForm
+type EntryError =
+ | {
+ [field in keyof DoResult]?: string;
+ }
+ | undefined;
+type DoRow = TableRow, EntryError>;
-const DoSearch: React.FC = ({
- dos
-}) => {
+const DoSearch: React.FC = ({ dos }) => {
+ const apiRef = useGridApiRef();
- const [filteredDos, setFilteredDos] = useState(dos);
- const { t } = useTranslation("do");
- const router = useRouter();
+ const formProps = useForm({
+ defaultValues: {},
+ });
+ const errors = formProps.formState.errors;
- const searchCriteria: Criterion[] = useMemo(() => [
- { label: t("Code"), paramName: "code", type: "text" },
-
- { label: t("Order Date From"), label2: t("Order Date To"), paramName: "orderDate", type: "dateRange" },
- { label: t("Shop Name"), paramName: "shopName", type: "text" },
- {
- label: t("Status"), paramName: "status", type: "autocomplete", options: sortBy(
- uniqBy(dos.map((_do) => ({ value: _do.status, label: t(upperFirst(_do.status)) })), "value"),
- "label")
- },
- ], [t, dos])
+ const tttt = [
+ {
+ id: 1,
+ code: "string",
+ orderDate: "2025-01-01",
+ estimatedArrivalDate: "2025-01-01",
+ status: "string",
+ shopName: "string",
+ },
+ {
+ id: 2,
+ code: "string1",
+ orderDate: "2025-01-01",
+ estimatedArrivalDate: "2025-01-01",
+ status: "string",
+ shopName: "string",
+ },
+ {
+ id: 3,
+ code: "string2",
+ orderDate: "2025-01-01",
+ estimatedArrivalDate: "2025-01-01",
+ status: "string",
+ shopName: "string",
+ },
+ ]
+// const [filteredDos, setFilteredDos] = useState(dos);
+ const [filteredDos, setFilteredDos] = useState(tttt);
+ const { t } = useTranslation("do");
+ const router = useRouter();
+ const [rowSelectionModel, setRowSelectionModel] = useState([])
- const onReset = useCallback(() => {
- setFilteredDos(dos)
- }, [dos])
+ const searchCriteria: Criterion[] = useMemo(
+ () => [
+ { label: t("Code"), paramName: "code", type: "text" },
- const onDetailClick = useCallback(
- (doResult: DoResult) => {
- router.push(`/do/edit?id=${doResult.id}`);
- },
- [router]
- );
+ {
+ label: t("Order Date From"),
+ label2: t("Order Date To"),
+ paramName: "orderDate",
+ type: "dateRange",
+ },
+ { label: t("Shop Name"), paramName: "shopName", type: "text" },
+ {
+ label: t("Status"),
+ paramName: "status",
+ type: "autocomplete",
+ options: sortBy(
+ uniqBy(
+ dos.map((_do) => ({
+ value: _do.status,
+ label: t(upperFirst(_do.status)),
+ })),
+ "value"
+ ),
+ "label"
+ ),
+ },
+ ],
+ [t, dos]
+ );
+ const onReset = useCallback(() => {
+ setFilteredDos(dos);
+ }, [dos]);
- const columns = useMemo[]>(() => [
- {
- name: "id",
- label: t("Details"),
- onClick: onDetailClick,
- buttonIcon: ,
- },
- {
- name: "code",
- label: t("Code")
- },
- {
- name: "shopName",
- label: t("Shop Name")
+ const onDetailClick = useCallback(
+ (doResult: DoResult) => {
+ router.push(`/do/edit?id=${doResult.id}`);
+ },
+ [router]
+ );
+
+ const validationTest = useCallback(
+ (
+ newRow: GridRowModel
+ // rowModel: GridRowSelectionModel
+ ): EntryError => {
+ const error: EntryError = {};
+ console.log(newRow);
+ // if (!newRow.lowerLimit) {
+ // error["lowerLimit"] = "lower limit cannot be null"
+ // }
+ // if (newRow.lowerLimit && newRow.upperLimit && newRow.lowerLimit > newRow.upperLimit) {
+ // error["lowerLimit"] = "lower limit should not be greater than upper limit"
+ // error["upperLimit"] = "lower limit should not be greater than upper limit"
+ // }
+ return Object.keys(error).length > 0 ? error : undefined;
+ },
+ []
+ );
+
+ const columns = useMemo(
+ () => [
+ // {
+ // name: "id",
+ // label: t("Details"),
+ // onClick: onDetailClick,
+ // buttonIcon: ,
+ // },
+ {
+ field: "code",
+ headerName: "code",
+ flex: 1,
+ },
+ {
+ field: "shopName",
+ headerName: t("Shop Name"),
+ flex: 1,
+ },
+ {
+ field: "orderDate",
+ headerName: t("Order Date"),
+ flex: 1,
+ renderCell: (params) => {
+ return params.row.orderDate
+ ? arrayToDateString(params.row.orderDate)
+ : "N/A";
},
- {
- name: "orderDate",
- label: t("Order Date"),
- renderCell: (params) => {
- return params.orderDate ? arrayToDateString(params.orderDate) : "N/A"
- },
+ },
+ {
+ field: "estimatedArrivalDate",
+ headerName: t("Estimated Arrival"),
+ flex: 1,
+ renderCell: (params) => {
+ return params.row.estimatedArrivalDate
+ ? arrayToDateString(params.row.estimatedArrivalDate)
+ : "N/A";
},
- {
- name: "status",
- label: t("Status"),
- renderCell: (params) => {
- return t(upperFirst(params.status))
- },
+ },
+ {
+ field: "status",
+ headerName: t("Status"),
+ flex: 1,
+ renderCell: (params) => {
+ return t(upperFirst(params.row.status));
},
- ], [t])
-
- return (
- <>
- {
- setFilteredDos(
- dos.filter(
- (_do) => {
- const doOrderDateStr = arrayToDayjs(_do.orderDate)
+ },
+ ],
+ [t, arrayToDateString]
+ );
- return _do.code.toLowerCase().includes(query.code.toLowerCase())
- && _do.shopName.toLowerCase().includes(query.shopName.toLowerCase())
- && (query.status == "All" || _do.status.toLowerCase().includes(query.status.toLowerCase()))
- && (isEmpty(query.orderDate) || doOrderDateStr.isSame(query.orderDate) || doOrderDateStr.isAfter(query.orderDate))
- && (isEmpty(query.orderDateTo) || doOrderDateStr.isSame(query.orderDateTo) || doOrderDateStr.isBefore(query.orderDateTo))
- }
- )
- )
- }}
- onReset={onReset}
- />
- items={filteredDos} columns={columns} pagingController={{
- pageNum: 0,
- pageSize: 0,
- totalCount: 0,
- }} />
- >
- )
-}
+ const onSubmit = useCallback>(
+ async (data, event) => {
+ let hasErrors = false;
+ console.log(errors);
+ console.log(data);
+ },
+ []
+ );
+ const onSubmitError = useCallback>(
+ (errors) => {},
+ []
+ );
+ return (
+ <>
+
+
+
+
+
+ {t("Delivery Order")}
+
+
+
+ }
+ type="submit"
+ >
+ {t("Create")}
+
+
+
+ {
+ setFilteredDos(
+ dos.filter((_do) => {
+ const doOrderDateStr = arrayToDayjs(_do.orderDate);
+ return (
+ _do.code.toLowerCase().includes(query.code.toLowerCase()) &&
+ _do.shopName
+ .toLowerCase()
+ .includes(query.shopName.toLowerCase()) &&
+ (query.status == "All" ||
+ _do.status
+ .toLowerCase()
+ .includes(query.status.toLowerCase())) &&
+ (isEmpty(query.orderDate) ||
+ doOrderDateStr.isSame(query.orderDate) ||
+ doOrderDateStr.isAfter(query.orderDate)) &&
+ (isEmpty(query.orderDateTo) ||
+ doOrderDateStr.isSame(query.orderDateTo) ||
+ doOrderDateStr.isBefore(query.orderDateTo))
+ );
+ })
+ );
+ }}
+ onReset={onReset}
+ />
+ {
+ setRowSelectionModel(newRowSelectionModel);
+ formProps.setValue("ids", newRowSelectionModel)
+ }}
+ slots={{
+ footer: FooterToolbar,
+ noRowsOverlay: NoRowsOverlay,
+ }}
+ />
+
+
+ >
+ );
+};
-export default DoSearch;
\ No newline at end of file
+const FooterToolbar: React.FC = ({ child }) => {
+ return {child};
+};
+const NoRowsOverlay: React.FC = () => {
+ const { t } = useTranslation("home");
+ return (
+
+ {t("Add some entries!")}
+
+ );
+};
+export default DoSearch;
diff --git a/src/components/PoSearch/PoSearch.tsx b/src/components/PoSearch/PoSearch.tsx
index 816c0fb..67db55c 100644
--- a/src/components/PoSearch/PoSearch.tsx
+++ b/src/components/PoSearch/PoSearch.tsx
@@ -48,8 +48,12 @@ const PoSearch: React.FC = ({
{
label: t("Status"),
paramName: "status",
- type: "select",
- options: [t(`pending`), t(`receiving`), t(`completed`)],
+ type: "select-labelled",
+ options: [
+ {label: t(`pending`), value: `pending`},
+ {label: t(`receiving`), value: `receiving`},
+ {label: t(`completed`), value: `completed`},
+ ]
},
{
label: t("Escalated"),
@@ -87,7 +91,7 @@ const PoSearch: React.FC = ({
label: t("OrderDate"),
renderCell: (params) => {
return dayjs(params.orderDate)
- .add(-1, "month")
+ // .add(-1, "month")
.format(OUTPUT_DATE_FORMAT);
},
},
@@ -106,21 +110,12 @@ const PoSearch: React.FC = ({
name: "escalated",
label: t("Escalated"),
renderCell: (params) => {
+ console.log(params.escalated)
return params.escalated ? (
) : undefined;
},
},
- // {
- // name: "name",
- // label: t("Name"),
- // },
- // {
- // name: "action",
- // label: t(""),
- // buttonIcon: ,
- // onClick: onDeleteClick,
- // },
],
[filteredPo]
);
@@ -144,6 +139,7 @@ const PoSearch: React.FC = ({
filterArgs: Record
) => {
console.log(pagingController);
+ console.log(filterArgs);
const params = {
...pagingController,
...filterArgs,
@@ -152,16 +148,16 @@ const PoSearch: React.FC = ({
// const res = await testing(params);
if (res) {
console.log(res);
- // setFilteredPo(res.records);
- // setTotalCount(res.total);
+ setFilteredPo(res.records);
+ setTotalCount(res.total);
}
},
[fetchPoListClient, pagingController]
);
- // useEffect(() => {
- // newPageFetch(pagingController, filterArgs);
- // }, [newPageFetch, pagingController, filterArgs]);
+ useEffect(() => {
+ newPageFetch(pagingController, filterArgs);
+ }, [newPageFetch, pagingController, filterArgs]);
return (
<>
@@ -183,26 +179,31 @@ const PoSearch: React.FC = ({
{
- // setFilterArgs({ ...query });
- 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"))))
- )
- })
- );
+ 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}
/>
items={filteredPo}
columns={columns}
- // pagingController={pagingController}
- // setPagingController={setPagingController}
- // totalCount={totalCount}
- // isAutoPaging={false}
+ pagingController={pagingController}
+ setPagingController={setPagingController}
+ totalCount={totalCount}
+ isAutoPaging={false}
/>
>
>
diff --git a/src/components/PoSearch/PoSearchWrapper.tsx b/src/components/PoSearch/PoSearchWrapper.tsx
index b244da3..4505f2d 100644
--- a/src/components/PoSearch/PoSearchWrapper.tsx
+++ b/src/components/PoSearch/PoSearchWrapper.tsx
@@ -32,11 +32,11 @@ const PoSearchWrapper: React.FC & SubComponents = async (
po,
warehouse,
] = await Promise.all([
- // fetchPoList({
- // "pageNum": 1,
- // "pageSize": 10,
- // }),
- fetchPoList(),
+ fetchPoList({
+ "pageNum": 1,
+ "pageSize": 10,
+ }),
+ // fetchPoList(),
fetchWarehouseList(),
]);
const fixPoDate = po.records.map((p) => {
diff --git a/src/components/SearchBox/SearchBox.tsx b/src/components/SearchBox/SearchBox.tsx
index 7cb767c..34281e5 100644
--- a/src/components/SearchBox/SearchBox.tsx
+++ b/src/components/SearchBox/SearchBox.tsx
@@ -34,6 +34,11 @@ interface BaseCriterion {
handleSelectionChange?: (selectedOptions: T[]) => void;
}
+interface OptionWithLabel {
+ label: string,
+ value: any,
+}
+
interface TextCriterion extends BaseCriterion {
type: "text";
}
@@ -43,6 +48,11 @@ interface SelectCriterion extends BaseCriterion {
options: string[];
}
+interface SelectWithLabelCriterion extends BaseCriterion {
+ type: "select-labelled";
+ options: OptionWithLabel[];
+}
+
interface MultiSelectCriterion extends BaseCriterion {
type: "multi-select";
options: T[];
@@ -75,6 +85,7 @@ interface DateCriterion extends BaseCriterion {
export type Criterion =
| TextCriterion
| SelectCriterion
+ | SelectWithLabelCriterion
| DateRangeCriterion
| DateCriterion
| MultiSelectCriterion
@@ -102,7 +113,7 @@ function SearchBox({
(acc, c) => {
return {
...acc,
- [c.paramName]: (c.type === "select" || (c.type === "autocomplete" && !Boolean(c.multiple)) ? "All"
+ [c.paramName]: (c.type === "select" || c.type === "select-labelled" || (c.type === "autocomplete" && !Boolean(c.multiple)) ? "All"
: (c.type === "autocomplete" && Boolean(c.multiple)) ? [defaultAll.value]: "")
};
},
@@ -200,13 +211,30 @@ function SearchBox({
>
{c.options.map((option) => (
-