FPSMS-frontend
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 

307 рядки
9.3 KiB

  1. "use client";
  2. import React, { useCallback, useEffect, useMemo, useState } from "react";
  3. import SearchBox, { Criterion } from "../SearchBox";
  4. import { ItemsResult } from "@/app/api/settings/item";
  5. import SearchResults, { Column } from "../SearchResults";
  6. import { EditNote } from "@mui/icons-material";
  7. import { useRouter, useSearchParams } from "next/navigation";
  8. import { GridDeleteIcon } from "@mui/x-data-grid";
  9. import { TypeEnum } from "@/app/utils/typeEnum";
  10. import axios from "axios";
  11. import { BASE_API_URL, NEXT_PUBLIC_API_URL } from "@/config/api";
  12. import { useTranslation } from "react-i18next";
  13. import axiosInstance from "@/app/(main)/axios/axiosInstance";
  14. import Qs from "qs";
  15. import EditableSearchResults from "@/components/SearchResults/EditableSearchResults"; // Make sure to import Qs
  16. import {
  17. ProdScheduleResult,
  18. ProdScheduleResultByPage,
  19. SearchProdSchedule,
  20. fetchProdSchedules,
  21. testDetailedSchedule,
  22. testRoughSchedule,
  23. } from "@/app/api/scheduling/actions";
  24. import { arrayToDateString, decimalFormatter } from "@/app/utils/formatUtil";
  25. import { isEqual, uniqBy } from "lodash";
  26. import dayjs from "dayjs";
  27. import { defaultPagingController } from "../SearchResults/SearchResults";
  28. import { ScheduleType } from "@/app/api/scheduling";
  29. import { Button, Stack } from "@mui/material";
  30. // type RecordStructure ={
  31. // id: number,
  32. // schedulePeriod: string,
  33. // scheduleAt: string
  34. // };
  35. type Props = {
  36. type: ScheduleType;
  37. // initProdSchedules: ProdScheduleResultByPage;
  38. defaultInputs: SearchProdSchedule;
  39. };
  40. type SearchQuery = Partial<
  41. Omit<SearchProdSchedule, "id" | "types" | "pageSize" | "pageNum">
  42. >;
  43. type SearchParamNames = keyof SearchQuery;
  44. const RSOverview: React.FC<Props> = ({ type, defaultInputs }) => {
  45. const [filteredSchedules, setFilteredSchedules] = useState<
  46. ProdScheduleResult[]
  47. >([]);
  48. const { t } = useTranslation("schedule");
  49. const router = useRouter();
  50. // const [filterObj, setFilterObj] = useState({});
  51. // const [tempSelectedValue, setTempSelectedValue] = useState({});
  52. const [pagingController, setPagingController] = useState(
  53. defaultPagingController,
  54. );
  55. const [totalCount, setTotalCount] = useState(0);
  56. const [inputs, setInputs] = useState(defaultInputs);
  57. const searchCriteria: Criterion<SearchParamNames>[] = useMemo(() => {
  58. const searchCriteria: Criterion<SearchParamNames>[] = [
  59. {
  60. label: t("Schedule Period"),
  61. label2: t("Schedule Period To"),
  62. paramName: "schedulePeriod",
  63. type: "dateRange",
  64. },
  65. { label: t("Scheduled At"), paramName: "scheduleAt", type: "date" },
  66. {
  67. label: t("Product Count"),
  68. paramName: "totalEstProdCount",
  69. type: "text",
  70. },
  71. ];
  72. return searchCriteria;
  73. }, [t]);
  74. // const onDetailClick = useCallback(
  75. // (item: ItemsResult) => {
  76. // router.push(`/settings/items/edit?id=${item.id}`);
  77. // },
  78. // [router]
  79. // );
  80. // const onDeleteClick = useCallback(
  81. // (item: ItemsResult) => { },
  82. // [router]
  83. // );
  84. const onDetailClick = (record: ProdScheduleResult) => {
  85. console.log("[debug] record", record);
  86. router.push(`/scheduling/rough/edit?id=${record.id}`);
  87. };
  88. const columns = useMemo<Column<ProdScheduleResult>[]>(
  89. () => [
  90. {
  91. name: "id",
  92. label: t("Details"),
  93. onClick: (record) => onDetailClick(record),
  94. buttonIcon: <EditNote />,
  95. },
  96. {
  97. name: "schedulePeriod",
  98. label: t("Demand Forecast Period"),
  99. renderCell: (params) => {
  100. return `${arrayToDateString(
  101. params.schedulePeriod,
  102. )} - ${arrayToDateString(params.schedulePeriodTo)}`;
  103. },
  104. },
  105. {
  106. name: "scheduleAt",
  107. label: t("Schedule At"),
  108. renderCell: (params) => {
  109. return arrayToDateString(params.scheduleAt);
  110. },
  111. },
  112. {
  113. name: "totalEstProdCount",
  114. label: t("Product Count(s)"),
  115. headerAlign: "right",
  116. align: "right",
  117. renderCell: (params) => {
  118. return decimalFormatter.format(params.totalEstProdCount);
  119. },
  120. },
  121. // {
  122. // name: "action",
  123. // label: t(""),
  124. // buttonIcon: <GridDeleteIcon />,
  125. // onClick: onDeleteClick,
  126. // },
  127. ],
  128. [filteredSchedules],
  129. );
  130. // useEffect(() => {
  131. // refetchData(filterObj);
  132. // }, [filterObj, pagingController.pageNum, pagingController.pageSize]);
  133. const refetchData = useCallback(
  134. async (
  135. query: Record<SearchParamNames, string> | SearchProdSchedule,
  136. actionType: "reset" | "search" | "paging",
  137. ) => {
  138. // console.log(query)
  139. const params: SearchProdSchedule = {
  140. scheduleAt: dayjs(query?.scheduleAt).isValid()
  141. ? query?.scheduleAt
  142. : undefined,
  143. schedulePeriod: dayjs(query?.schedulePeriod).isValid()
  144. ? query?.schedulePeriod
  145. : undefined,
  146. schedulePeriodTo: dayjs(query?.schedulePeriodTo).isValid()
  147. ? query?.schedulePeriodTo
  148. : undefined,
  149. totalEstProdCount: query?.totalEstProdCount
  150. ? Number(query?.totalEstProdCount)
  151. : undefined,
  152. types: ["rough"],
  153. pageNum: pagingController.pageNum - 1,
  154. pageSize: pagingController.pageSize,
  155. };
  156. const response = await fetchProdSchedules(params);
  157. // console.log(response)
  158. if (response) {
  159. setTotalCount(response.total);
  160. switch (actionType) {
  161. case "reset":
  162. case "search":
  163. setFilteredSchedules(() => response.records);
  164. break;
  165. case "paging":
  166. setFilteredSchedules((fs) =>
  167. uniqBy([...fs, ...response.records], "id"),
  168. );
  169. break;
  170. }
  171. }
  172. },
  173. [pagingController, setPagingController],
  174. );
  175. useEffect(() => {
  176. refetchData(inputs, "paging");
  177. }, [pagingController]);
  178. // const refetchData = async (filterObj: SearchQuery) => {
  179. // const authHeader = axiosInstance.defaults.headers['Authorization'];
  180. // if (!authHeader) {
  181. // return; // Exit the function if the token is not set
  182. // }
  183. // const params ={
  184. // pageNum: pagingController.pageNum,
  185. // pageSize: pagingController.pageSize,
  186. // ...filterObj,
  187. // ...tempSelectedValue,
  188. // }
  189. // try {
  190. // // const response = await axiosInstance.get<ItemsResult[]>(`${NEXT_PUBLIC_API_URL}/items/getRecordByPage`, {
  191. // // params,
  192. // // paramsSerializer: (params) => {
  193. // // return Qs.stringify(params, { arrayFormat: 'repeat' });
  194. // // },
  195. // // });
  196. // //setFilteredSchedules(response.data.records);
  197. // // setFilteredSchedules([
  198. // // {
  199. // // id: 1,
  200. // // scheduledPeriod: "2025-05-11 to 2025-05-17",
  201. // // scheduledAt: "2025-05-07",
  202. // // productCount: 13,
  203. // // },
  204. // // {
  205. // // id: 2,
  206. // // scheduledPeriod: "2025-05-18 to 2025-05-24",
  207. // // scheduledAt: "2025-05-14",
  208. // // productCount: 15,
  209. // // },
  210. // // {
  211. // // id: 3,
  212. // // scheduledPeriod: "2025-05-25 to 2025-05-31",
  213. // // scheduledAt: "2025-05-21",
  214. // // productCount: 13,
  215. // // },
  216. // // ])
  217. // setPagingController({
  218. // ...pagingController,
  219. // // totalCount: response.data.total
  220. // })
  221. // // return response; // Return the data from the response
  222. // } catch (error) {
  223. // console.error('Error fetching items:', error);
  224. // throw error; // Rethrow the error for further handling
  225. // }
  226. // };
  227. const onReset = useCallback(() => {
  228. // setFilteredSchedules(items ?? []);
  229. // setFilterObj({});
  230. // setTempSelectedValue({});
  231. refetchData(defaultInputs, "reset");
  232. }, []);
  233. const testRoughScheduleClick = useCallback(async () => {
  234. const response = await testRoughSchedule()
  235. if (response) {
  236. refetchData(inputs, "paging");
  237. }
  238. }, []);
  239. return (
  240. <>
  241. <Stack
  242. direction="row"
  243. justifyContent="flex-end"
  244. flexWrap="wrap"
  245. rowGap={2}
  246. >
  247. <Button
  248. variant="contained"
  249. onClick={testRoughScheduleClick}
  250. >
  251. {t("Test Rough Schedule")}
  252. </Button>
  253. </Stack>
  254. <SearchBox
  255. criteria={searchCriteria}
  256. onSearch={(query) => {
  257. // resetPagingController()
  258. setInputs(() => ({
  259. scheduleAt: query?.scheduleAt,
  260. schedulePeriod: query?.schedulePeriod,
  261. schedulePeriodTo: query?.schedulePeriodTo,
  262. totalEstProdCount: Number(query?.totalEstProdCount),
  263. }));
  264. refetchData(query, "search");
  265. // setFilterObj({
  266. // ...query
  267. // })
  268. }}
  269. onReset={onReset}
  270. />
  271. <SearchResults<ProdScheduleResult>
  272. items={filteredSchedules}
  273. columns={columns}
  274. setPagingController={setPagingController}
  275. pagingController={pagingController}
  276. totalCount={totalCount}
  277. // isAutoPaging={false}
  278. />
  279. </>
  280. );
  281. };
  282. export default RSOverview;