FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

257 lines
8.5 KiB

  1. "use client";
  2. import { InventoryLotLineResult, InventoryResult } from "@/app/api/inventory";
  3. import { useTranslation } from "react-i18next";
  4. import SearchBox, { Criterion } from "../SearchBox";
  5. import { useCallback, useEffect, useMemo, useState } from "react";
  6. import { isEqual, orderBy, uniq, uniqBy } from "lodash";
  7. import SearchResults, { Column } from "../SearchResults";
  8. import { CheckCircleOutline, DoDisturb } from "@mui/icons-material";
  9. import InventoryTable from "./InventoryTable";
  10. import { defaultPagingController } from "../SearchResults/SearchResults";
  11. import InventoryLotLineTable from "./InventoryLotLineTable";
  12. import { SearchInventory, SearchInventoryLotLine, fetchInventories, fetchInventoryLotLines } from "@/app/api/inventory/actions";
  13. interface Props {
  14. inventories: InventoryResult[];
  15. }
  16. type SearchQuery = Partial<
  17. Omit<
  18. InventoryResult,
  19. | "id"
  20. | "qty"
  21. | "uomCode"
  22. | "uomUdfudesc"
  23. | "germPerSmallestUnit"
  24. | "qtyPerSmallestUnit"
  25. | "itemSmallestUnit"
  26. | "price"
  27. | "description"
  28. | "category"
  29. >
  30. >;
  31. type SearchParamNames = keyof SearchQuery;
  32. const InventorySearch: React.FC<Props> = ({ inventories }) => {
  33. const { t } = useTranslation(["inventory", "common"]);
  34. // Inventory
  35. const [filteredInventories, setFilteredInventories] = useState<InventoryResult[]>([]);
  36. const [inventoriesPagingController, setInventoriesPagingController] = useState(defaultPagingController)
  37. const [inventoriesTotalCount, setInventoriesTotalCount] = useState(0)
  38. const [selectedInventory, setSelectedInventory] = useState<InventoryResult | null>(null)
  39. // Inventory Lot Line
  40. const [filteredInventoryLotLines, setFilteredInventoryLotLines] = useState<InventoryLotLineResult[]>([]);
  41. const [inventoryLotLinesPagingController, setInventoryLotLinesPagingController] = useState(defaultPagingController)
  42. const [inventoryLotLinesTotalCount, setInventoryLotLinesTotalCount] = useState(0)
  43. const defaultInputs = useMemo(() => ({
  44. itemId: "",
  45. itemCode: "",
  46. itemName: "",
  47. itemType: "",
  48. onHandQty: "",
  49. onHoldQty: "",
  50. unavailableQty: "",
  51. availableQty: "",
  52. currencyName: "",
  53. status: "",
  54. baseUom: "",
  55. }), [])
  56. const [inputs, setInputs] = useState<Record<SearchParamNames, string>>(defaultInputs);
  57. const searchCriteria: Criterion<SearchParamNames>[] = useMemo(
  58. () => [
  59. { label: t("Code"), paramName: "itemCode", type: "text" },
  60. { label: t("Name"), paramName: "itemName", type: "text" },
  61. {
  62. label: t("Type"),
  63. paramName: "itemType",
  64. type: "select",
  65. options: uniq(inventories.map((i) => i.itemType)),
  66. },
  67. // {
  68. // label: t("Status"),
  69. // paramName: "status",
  70. // type: "select",
  71. // options: uniq(inventories.map((i) => i.status)),
  72. // },
  73. ],
  74. [t],
  75. );
  76. // Inventory
  77. const refetchInventoryData = useCallback(async (
  78. query: Record<SearchParamNames, string>,
  79. actionType: "reset" | "search" | "paging" | "init",
  80. pagingController: typeof defaultPagingController,
  81. ) => {
  82. console.log("%c Action Type 1.", "color:red", actionType)
  83. // Avoid loading data again
  84. if (actionType === "paging" && pagingController === defaultPagingController) {
  85. return
  86. }
  87. console.log("%c Action Type 2.", "color:blue", actionType)
  88. const params: SearchInventory = {
  89. code: query?.itemCode ?? '',
  90. name: query?.itemName ?? '',
  91. type: query?.itemType.toLowerCase() === "all" ? '' : query?.itemType ?? '',
  92. pageNum: pagingController.pageNum - 1,
  93. pageSize: pagingController.pageSize
  94. }
  95. const response = await fetchInventories(params)
  96. if (response) {
  97. setInventoriesTotalCount(response.total);
  98. switch (actionType) {
  99. case "init":
  100. case "reset":
  101. case "search":
  102. setFilteredInventories(() => response.records);
  103. break;
  104. case "paging":
  105. setFilteredInventories((fi) =>
  106. // orderBy(
  107. uniqBy([...fi, ...response.records], "id")
  108. // , ["id"], ["desc"])
  109. );
  110. }
  111. }
  112. }, [])
  113. useEffect(() => {
  114. refetchInventoryData(defaultInputs, "init", defaultPagingController)
  115. }, [])
  116. useEffect(() => {
  117. // if (!isEqual(inventoriesPagingController, defaultPagingController)) {
  118. refetchInventoryData(inputs, "paging", inventoriesPagingController)
  119. // }
  120. }, [inventoriesPagingController])
  121. // Inventory Lot Line
  122. const refetchInventoryLotLineData = useCallback(async (
  123. itemId: number | null,
  124. actionType: "reset" | "search" | "paging",
  125. pagingController: typeof defaultPagingController,
  126. ) => {
  127. if (!itemId) {
  128. setSelectedInventory(null)
  129. setInventoryLotLinesTotalCount(0);
  130. setFilteredInventoryLotLines([])
  131. return
  132. }
  133. // Avoid loading data again
  134. if (actionType === "paging" && pagingController === defaultPagingController) {
  135. return
  136. }
  137. const params: SearchInventoryLotLine = {
  138. itemId: itemId,
  139. pageNum: pagingController.pageNum - 1,
  140. pageSize: pagingController.pageSize
  141. }
  142. const response = await fetchInventoryLotLines(params)
  143. if (response) {
  144. setInventoryLotLinesTotalCount(response.total);
  145. switch (actionType) {
  146. case "reset":
  147. case "search":
  148. setFilteredInventoryLotLines(() => response.records);
  149. break;
  150. case "paging":
  151. setFilteredInventoryLotLines((fi) =>
  152. // orderBy(
  153. uniqBy([...fi, ...response.records], "id"),
  154. // ["id"], ["desc"])
  155. );
  156. }
  157. }
  158. }, [])
  159. useEffect(() => {
  160. // if (!isEqual(inventoryLotLinesPagingController, defaultPagingController)) {
  161. refetchInventoryLotLineData(selectedInventory?.itemId ?? null, "paging", inventoryLotLinesPagingController)
  162. // }
  163. }, [inventoryLotLinesPagingController])
  164. // Reset
  165. const onReset = useCallback(() => {
  166. refetchInventoryData(defaultInputs, "reset", defaultPagingController);
  167. refetchInventoryLotLineData(null, "reset", defaultPagingController);
  168. // setFilteredInventories(inventories);
  169. setInputs(() => defaultInputs)
  170. setInventoriesPagingController(() => defaultPagingController)
  171. setInventoryLotLinesPagingController(() => defaultPagingController)
  172. }, []);
  173. // Click Row
  174. const onInventoryRowClick = useCallback((item: InventoryResult) => {
  175. refetchInventoryLotLineData(item.itemId, "search", defaultPagingController)
  176. setSelectedInventory(item)
  177. setInventoryLotLinesPagingController(() => defaultPagingController)
  178. }, [])
  179. // On Search
  180. const onSearch = useCallback((query: Record<SearchParamNames, string>) => {
  181. refetchInventoryData(query, "search", defaultPagingController)
  182. refetchInventoryLotLineData(null, "search", defaultPagingController);
  183. setInputs(() => query)
  184. setInventoriesPagingController(() => defaultPagingController)
  185. setInventoryLotLinesPagingController(() => defaultPagingController)
  186. }, [refetchInventoryData])
  187. console.log("", "color: #666", inventoriesPagingController)
  188. return (
  189. <>
  190. <SearchBox
  191. criteria={searchCriteria}
  192. onSearch={(query) => {
  193. onSearch(query)
  194. // console.log(query)
  195. // console.log(inventories)
  196. // setInputs(() => query)
  197. // refetchInventoryData(query, "search", defaultPagingController)
  198. // setFilteredInventories(
  199. // inventories.filter(
  200. // (i) =>
  201. // i.itemCode.toLowerCase().includes(query.itemCode.toLowerCase()) &&
  202. // i.itemName.toLowerCase().includes(query.itemName.toLowerCase()) &&
  203. // (query.itemType == "All" ||
  204. // i.itemType.toLowerCase().includes(query.itemType.toLowerCase())) &&
  205. // (query.status == "All" ||
  206. // i.status.toLowerCase().includes(query.status.toLowerCase())),
  207. // ),
  208. // );
  209. }}
  210. onReset={onReset}
  211. />
  212. <InventoryTable
  213. inventories={filteredInventories}
  214. pagingController={inventoriesPagingController}
  215. setPagingController={setInventoriesPagingController}
  216. totalCount={inventoriesTotalCount}
  217. onRowClick={onInventoryRowClick}
  218. />
  219. <InventoryLotLineTable
  220. inventoryLotLines={filteredInventoryLotLines}
  221. pagingController={inventoryLotLinesPagingController}
  222. setPagingController={setInventoryLotLinesPagingController}
  223. totalCount={inventoryLotLinesTotalCount}
  224. inventory={selectedInventory}
  225. />
  226. </>
  227. );
  228. };
  229. export default InventorySearch;