Procházet zdrojové kódy

[rough scheduling] update search page

create_edit_user
jason.lam před 3 měsíci
rodič
revize
e22318c9f8
10 změnil soubory, kde provedl 396 přidání a 0 odebrání
  1. +48
    -0
      src/app/(main)/scheduling/detail/page.tsx
  2. +11
    -0
      src/app/(main)/scheduling/page.tsx
  3. +48
    -0
      src/app/(main)/scheduling/rough/page.tsx
  4. +2
    -0
      src/components/Breadcrumb/Breadcrumb.tsx
  5. +17
    -0
      src/components/NavigationContent/NavigationContent.tsx
  6. +194
    -0
      src/components/RoughSchedule/RoughSchedileSearchView.tsx
  7. +40
    -0
      src/components/RoughSchedule/RoughScheduleLoading.tsx
  8. +19
    -0
      src/components/RoughSchedule/RoughScheduleWrapper.tsx
  9. +1
    -0
      src/components/RoughSchedule/index.ts
  10. +16
    -0
      src/components/SearchBox/SearchBox.tsx

+ 48
- 0
src/app/(main)/scheduling/detail/page.tsx Zobrazit soubor

@@ -0,0 +1,48 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import ItemsSearch from "@/components/ItemsSearch";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { Metadata } from "next";
import Link from "next/link";
import { Suspense } from "react";

export const metadata: Metadata = {
title: "Detail Scheduling",
};

const detailScheduling: React.FC = async () => {
const project = TypeEnum.PRODUCT
const { t } = await getServerI18n(project);
// preloadClaims();

return (
<>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("Detail Scheduling")}
</Typography>
{/* <Button
variant="contained"
startIcon={<Add />}
LinkComponent={Link}
href="product/create"
>
{t("Create product")}
</Button> */}
</Stack>
<Suspense fallback={<ItemsSearch.Loading />}>
<ItemsSearch />
</Suspense>
</>
);
};

export default detailScheduling;

+ 11
- 0
src/app/(main)/scheduling/page.tsx Zobrazit soubor

@@ -0,0 +1,11 @@
import { Metadata } from "next";

export const metadata: Metadata = {
title: "Scheduling",
};

const Scheduling: React.FC = async () => {
return null;
};

export default Scheduling;

+ 48
- 0
src/app/(main)/scheduling/rough/page.tsx Zobrazit soubor

@@ -0,0 +1,48 @@
import { TypeEnum } from "@/app/utils/typeEnum";
import RoughSchedule from "@/components/RoughSchedule";
import { getServerI18n } from "@/i18n";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { Metadata } from "next";
import Link from "next/link";
import { Suspense } from "react";

export const metadata: Metadata = {
title: "Rough Scheduling",
};

const roughScheduling: React.FC = async () => {
const project = TypeEnum.PRODUCT
const { t } = await getServerI18n(project);
// preloadClaims();

return (
<>
<Stack
direction="row"
justifyContent="space-between"
flexWrap="wrap"
rowGap={2}
>
<Typography variant="h4" marginInlineEnd={2}>
{t("Rough Scheduling")}
</Typography>
{/* <Button
variant="contained"
startIcon={<Add />}
LinkComponent={Link}
href="product/create"
>
{t("Create product")}
</Button> */}
</Stack>
<Suspense fallback={<RoughSchedule.Loading />}>
<RoughSchedule />
</Suspense>
</>
);
};

export default roughScheduling;

+ 2
- 0
src/components/Breadcrumb/Breadcrumb.tsx Zobrazit soubor

@@ -14,6 +14,8 @@ const pathToLabelMap: { [path: string]: string } = {
"/tasks/create": "Create Task Template",
"/settings/qcItem": "Qc Item",
"/settings/rss": "Rough Schedule Setting",
"/scheduling/rough": "Rough Scheduling",
"/scheduling/detail": "Detail Scheduling",
};

const Breadcrumb = () => {


+ 17
- 0
src/components/NavigationContent/NavigationContent.tsx Zobrazit soubor

@@ -166,6 +166,23 @@ const NavigationContent: React.FC = () => {
},
],
},
{
icon: <RequestQuote />,
label: "Scheduling",
path: "",
children: [
{
icon: <RequestQuote />,
label: "Rough Scheduling",
path: "/scheduling/rough",
},
{
icon: <RequestQuote />,
label: "Detail Scheduling",
path: "/scheduling/detail",
},
],
},
{
icon: <RequestQuote />,
label: "Settings",


+ 194
- 0
src/components/RoughSchedule/RoughSchedileSearchView.tsx Zobrazit soubor

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

import React, {useCallback, useEffect, useMemo, useState} from "react";
import SearchBox, { Criterion } from "../SearchBox";
import { ItemsResult} from "@/app/api/settings/item";
import SearchResults, { Column } from "../SearchResults";
import { EditNote } from "@mui/icons-material";
import { useRouter, useSearchParams } from "next/navigation";
import { GridDeleteIcon } from "@mui/x-data-grid";
import { TypeEnum } from "@/app/utils/typeEnum";
import axios from "axios";
import {BASE_API_URL, NEXT_PUBLIC_API_URL} from "@/config/api";
import { useTranslation } from "react-i18next";
import axiosInstance from "@/app/(main)/axios/axiosInstance";
import Qs from 'qs';
import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs

type RecordStructure ={
id: number,
schedulePeriod: string,
scheduleAt: string
};

type Props = {
records: RecordStructure[];
};

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

const RSOverview: React.FC<Props> = ({ records }) => {
const [filteredItems, setFilteredItems] = useState<Object[]>(records ?? []);
const { t } = useTranslation("items");
const router = useRouter();
const [filterObj, setFilterObj] = useState({});
const [tempSelectedValue, setTempSelectedValue] = useState({});
const [pagingController, setPagingController] = useState({
pageNum: 1,
pageSize: 10,
totalCount: 0,
})

const [mode, redirPath] = useMemo(() => {
// var typeId = TypeEnum.CONSUMABLE_ID
var title = "";
var mode = "Search";
var redirPath = "";
title = "Product";
redirPath = "/scheduling/rough";
return [mode, redirPath];
}, []);

const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
() => {
var searchCriteria: Criterion<SearchParamNames>[] = [
{ label: t("Schedule Period"), paramName: "schedulePeriod", type: "dateRange" },
{ label: t("Scheduled At"), paramName: "scheduleAt", type: "date" },
{ label: t("Product Count"), paramName: "productCount", type: "input" },
]
return searchCriteria
},
[t, records]
);

// const onDetailClick = useCallback(
// (item: ItemsResult) => {
// router.push(`/settings/items/edit?id=${item.id}`);
// },
// [router]
// );

const onDeleteClick = useCallback(
(item: ItemsResult) => {},
[router]
);

const columns = useMemo<Column<ItemsResult>[]>(
() => [
{
name: "id",
label: t("Details"),
onClick: ()=>{},
buttonIcon: <EditNote />,
},
{
name: "scheduledPeriod",
label: "Rough Schedule Period",
},
{
name: "scheduledAt",
label: t("Scheduled At"),
},
{
name: "productCount",
label: t("Product Count(s)"),
},
// {
// name: "action",
// label: t(""),
// buttonIcon: <GridDeleteIcon />,
// onClick: onDeleteClick,
// },
],
[filteredItems]
);

useEffect(() => {
refetchData(filterObj);

}, [filterObj, pagingController.pageNum, pagingController.pageSize]);

const refetchData = async (filterObj: SearchQuery) => {

const authHeader = axiosInstance.defaults.headers['Authorization'];
if (!authHeader) {
return; // Exit the function if the token is not set
}

const params ={
pageNum: pagingController.pageNum,
pageSize: pagingController.pageSize,
...filterObj,
...tempSelectedValue,
}

try {
const response = await axiosInstance.get<ItemsResult[]>(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, {
params,
paramsSerializer: (params) => {
return Qs.stringify(params, { arrayFormat: 'repeat' });
},
});
//setFilteredItems(response.data.records);
setFilteredItems([
{
id: 1,
scheduledPeriod: "2025-05-11 to 2025-05-17",
scheduledAt: "2025-05-07",
productCount: 13,
},
{
id: 2,
scheduledPeriod: "2025-05-18 to 2025-05-24",
scheduledAt: "2025-05-14",
productCount: 15,
},
{
id: 3,
scheduledPeriod: "2025-05-25 to 2025-05-31",
scheduledAt: "2025-05-21",
productCount: 13,
},
])
setPagingController({
...pagingController,
totalCount: response.data.total
})
return response; // Return the data from the response
} catch (error) {
console.error('Error fetching items:', error);
throw error; // Rethrow the error for further handling
}
};

const onReset = useCallback(() => {
//setFilteredItems(items ?? []);
setFilterObj({});
setTempSelectedValue({});
refetchData();
}, [records]);

return (
<>
<SearchBox
criteria={searchCriteria}
onSearch={(query) => {
setFilterObj({
...query
})
}}
onReset={onReset}
/>
<SearchResults<ItemsResult>
items={filteredItems}
columns={columns}
setPagingController={setPagingController}
pagingController={pagingController}
isAutoPaging={false}
/>
</>
);
};

export default RSOverview;

+ 40
- 0
src/components/RoughSchedule/RoughScheduleLoading.tsx Zobrazit soubor

@@ -0,0 +1,40 @@
import Card from "@mui/material/Card";
import CardContent from "@mui/material/CardContent";
import Skeleton from "@mui/material/Skeleton";
import Stack from "@mui/material/Stack";
import React from "react";

// Can make this nicer
export const RoughScheduleLoading: React.FC = () => {
return (
<>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton variant="rounded" height={60} />
<Skeleton
variant="rounded"
height={50}
width={100}
sx={{ alignSelf: "flex-end" }}
/>
</Stack>
</CardContent>
</Card>
<Card>
<CardContent>
<Stack spacing={2}>
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
<Skeleton variant="rounded" height={40} />
</Stack>
</CardContent>
</Card>
</>
);
};

export default RoughScheduleLoading;

+ 19
- 0
src/components/RoughSchedule/RoughScheduleWrapper.tsx Zobrazit soubor

@@ -0,0 +1,19 @@
import { fetchAllItems, } from "@/app/api/settings/item";
import {RoughScheduleLoading} from "./RoughScheduleLoading";
import RSOverview from "./RoughSchedileSearchView";

interface SubComponents {
Loading: typeof RoughScheduleLoading;
}

const RoughScheduleWrapper: ({}: {}) => Promise<JSX.Element> = async ({
// type,
}) => {
// console.log(type)
var result = await fetchAllItems()
return <RSOverview records={result} />;
};

RoughScheduleWrapper.Loading = RoughScheduleLoading;

export default RoughScheduleWrapper;

+ 1
- 0
src/components/RoughSchedule/index.ts Zobrazit soubor

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

+ 16
- 0
src/components/SearchBox/SearchBox.tsx Zobrazit soubor

@@ -196,6 +196,22 @@ function SearchBox<T extends string>({
</Box>
</LocalizationProvider>
)}
{c.type === "date" && (
<LocalizationProvider
dateAdapter={AdapterDayjs}
// TODO: Should maybe use a custom adapterLocale here to support YYYY-MM-DD
adapterLocale="zh-hk"
>
<Box display="flex">
<FormControl fullWidth>
<DatePicker
label={c.label}
onChange={makeDateChangeHandler(c.paramName)}
/>
</FormControl>
</Box>
</LocalizationProvider>
)}
</Grid>
);
})}


Načítá se…
Zrušit
Uložit