瀏覽代碼

add delivery order

production_process
cyril.tsui 2 月之前
父節點
當前提交
a85b1f9b32
共有 12 個檔案被更改,包括 196 行新增2 行删除
  1. +0
    -0
      src/app/(main)/do/edit/page.tsx
  2. +33
    -0
      src/app/(main)/do/page.tsx
  3. +0
    -0
      src/app/api/do/actions.tsx
  4. +21
    -0
      src/app/api/do/index.tsx
  5. +1
    -0
      src/components/Breadcrumb/Breadcrumb.tsx
  6. +0
    -0
      src/components/DoSave/DoSaveWrapper.tsx
  7. +1
    -0
      src/components/DoSave/index.ts
  8. +115
    -0
      src/components/DoSearch/DoSearch.tsx
  9. +22
    -0
      src/components/DoSearch/DoSearchWrapper.tsx
  10. +1
    -0
      src/components/DoSearch/index.ts
  11. +1
    -1
      src/components/NavigationContent/NavigationContent.tsx
  12. +1
    -1
      src/components/SearchBox/SearchBox.tsx

+ 0
- 0
src/app/(main)/do/edit/page.tsx 查看文件


+ 33
- 0
src/app/(main)/do/page.tsx 查看文件

@@ -0,0 +1,33 @@
import DoSearch from "@/components/DoSearch";
import { getServerI18n } from "@/i18n"
import { Stack, Typography } from "@mui/material";
import { Metadata } from "next";
import { Suspense } from "react";

export const metadata: Metadata = {
title: "Delivery Order"
}

const DeliveryOrder: React.FC = async () => {
const { t } = await getServerI18n("do");

return (
<>
<Stack
direction="row"
justifyContent={"space-between"}
flexWrap={"wrap"}
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("Delivery Order")}
</Typography>
</Stack>
<Suspense fallback={<DoSearch.Loading />}>
<DoSearch />
</Suspense>
</>
)
}

export default DeliveryOrder;

+ 0
- 0
src/app/api/do/actions.tsx 查看文件


+ 21
- 0
src/app/api/do/index.tsx 查看文件

@@ -0,0 +1,21 @@
import { serverFetchJson } from "@/app/utils/fetchUtil";
import { BASE_API_URL } from "@/config/api";
import { cache } from "react";

export interface DoResult {
id: number,
code: string,
orderDate: string,
status: string,
shopName: string,
}

export const preloadDo = () => {
fetchDoList();
}

export const fetchDoList = cache(async () => {
return serverFetchJson<DoResult[]>(`${BASE_API_URL}/do/list`, {
next: { tags: ["doList"] }
})
})

+ 1
- 0
src/components/Breadcrumb/Breadcrumb.tsx 查看文件

@@ -20,6 +20,7 @@ const pathToLabelMap: { [path: string]: string } = {
"/scheduling/detail/edit": "FG Production Schedule",
"/inventory": "Inventory",
"/settings/importTesting": "Import Testing",
"/do": "Delivery Order",
};

const Breadcrumb = () => {


+ 0
- 0
src/components/DoSave/DoSaveWrapper.tsx 查看文件


+ 1
- 0
src/components/DoSave/index.ts 查看文件

@@ -0,0 +1 @@
export default from "./DoSaveWrapper"

+ 115
- 0
src/components/DoSearch/DoSearch.tsx 查看文件

@@ -0,0 +1,115 @@
"use client";

import { DoResult } from "@/app/api/do"
import { useRouter } from "next/navigation";
import { useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { Criterion } from "../SearchBox";
import { isEmpty, sortBy, uniqBy, upperFirst } from "lodash";
import { Column } from "../SearchResults";
import { arrayToDateString, arrayToDayjs } from "@/app/utils/formatUtil";
import SearchBox from "../SearchBox/SearchBox";
import SearchResults from "../SearchResults/SearchResults";
import { EditNote } from "@mui/icons-material";

type Props = {
dos: DoResult[]
}

type SearchQuery = Partial<Omit<DoResult, "id">>;
type SearchParamNames = keyof SearchQuery;

const DoSearch: React.FC<Props> = ({
dos
}) => {

const [filteredDos, setFilteredDos] = useState<DoResult[]>(dos);
const { t } = useTranslation("do");
const router = useRouter();

const searchCriteria: Criterion<SearchParamNames>[] = 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 onReset = useCallback(() => {
setFilteredDos(dos)
}, [dos])

const onDetailClick = useCallback(
(doResult: DoResult) => {
router.push(`/do/edit?id=${doResult.id}`);
},
[router]
);


const columns = useMemo<Column<DoResult>[]>(() => [
{
name: "id",
label: t("Details"),
onClick: onDetailClick,
buttonIcon: <EditNote />,
},
{
name: "code",
label: t("Code")
},
{
name: "shopName",
label: t("Shop Name")
},
{
name: "orderDate",
label: t("Order Date"),
renderCell: (params) => {
return params.orderDate ? arrayToDateString(params.orderDate) : "N/A"
},
},
{
name: "status",
label: t("Status"),
renderCell: (params) => {
return t(upperFirst(params.status))
},
},
], [t])

return (
<>
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
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}
/>
<SearchResults<DoResult> items={filteredDos} columns={columns} pagingController={{
pageNum: 0,
pageSize: 0,
totalCount: 0,
}} />
</>
)
}

export default DoSearch;

+ 22
- 0
src/components/DoSearch/DoSearchWrapper.tsx 查看文件

@@ -0,0 +1,22 @@
import React from "react";
import GeneralLoading from "../General/GeneralLoading"
import { fetchDoList } from "@/app/api/do";
import DoSearch from "./DoSearch";

interface SubComponents {
Loading: typeof GeneralLoading;
}

const DoSearchWrapper: React.FC & SubComponents = async () => {

const [
dos
] = await Promise.all([
fetchDoList()
]);
return <DoSearch dos={dos}/>
}

DoSearchWrapper.Loading = GeneralLoading;

export default DoSearchWrapper;

+ 1
- 0
src/components/DoSearch/index.ts 查看文件

@@ -0,0 +1 @@
export { default } from "./DoSearchWrapper"

+ 1
- 1
src/components/NavigationContent/NavigationContent.tsx 查看文件

@@ -128,7 +128,7 @@ const NavigationContent: React.FC = () => {
{
icon: <RequestQuote />,
label: "Delivery Order",
path: "",
path: "/do",
},
],
},


+ 1
- 1
src/components/SearchBox/SearchBox.tsx 查看文件

@@ -210,7 +210,7 @@ function SearchBox<T extends string>({
{c.type === "autocomplete" && (
<Autocomplete
groupBy={
c.options.every((option) => option.group)
c.options.filter((option) => option.group !== "All").length > 0 && c.options.every((option) => option.group)
? (option) => (option.group && option.group.trim() !== '' ? option.group : 'Ungrouped')
: undefined
}


Loading…
取消
儲存