| @@ -1,9 +1,9 @@ | |||||
| "use client"; | "use client"; | ||||
| import { DoResult } from "@/app/api/do"; | import { DoResult } from "@/app/api/do"; | ||||
| import { DoSearchAll, fetchDoSearch } from "@/app/api/do/actions"; | |||||
| import { DoSearchAll, fetchDoSearch, releaseDo } from "@/app/api/do/actions"; | |||||
| import { useRouter } from "next/navigation"; | import { useRouter } from "next/navigation"; | ||||
| import React, { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import React, { ForwardedRef, useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { Criterion } from "../SearchBox"; | import { Criterion } from "../SearchBox"; | ||||
| import { isEmpty, sortBy, uniqBy, upperFirst } from "lodash"; | import { isEmpty, sortBy, uniqBy, upperFirst } from "lodash"; | ||||
| @@ -26,12 +26,10 @@ import { | |||||
| SubmitHandler, | SubmitHandler, | ||||
| useForm, | useForm, | ||||
| } from "react-hook-form"; | } from "react-hook-form"; | ||||
| import { Box, Button, Grid, Stack, Typography } from "@mui/material"; | |||||
| import { Box, Button, Grid, Stack, Typography, TablePagination } from "@mui/material"; | |||||
| import StyledDataGrid from "../StyledDataGrid"; | import StyledDataGrid from "../StyledDataGrid"; | ||||
| import { GridRowSelectionModel } from "@mui/x-data-grid"; | import { GridRowSelectionModel } from "@mui/x-data-grid"; | ||||
| import { TablePagination } from "@mui/material"; | |||||
| import Swal from "sweetalert2"; | |||||
| type Props = { | type Props = { | ||||
| filterArgs?: Record<string, any>; | filterArgs?: Record<string, any>; | ||||
| @@ -92,14 +90,34 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||||
| const pagedRows = useMemo(() => { | const pagedRows = useMemo(() => { | ||||
| const start = (pagingController.pageNum - 1) * pagingController.pageSize; | const start = (pagingController.pageNum - 1) * pagingController.pageSize; | ||||
| return searchAllDos.slice(start, start + pagingController.pageSize); | return searchAllDos.slice(start, start + pagingController.pageSize); | ||||
| }, [searchAllDos, pagingController]); | |||||
| }, [searchAllDos, pagingController]); | |||||
| const [currentSearchParams, setCurrentSearchParams] = useState<SearchBoxInputs>({ | |||||
| code: "", | |||||
| status: "", | |||||
| estimatedArrivalDate: "", | |||||
| orderDate: "", | |||||
| supplierName: "", | |||||
| shopName: "", | |||||
| deliveryOrderLines: "", | |||||
| codeTo: "", | |||||
| statusTo: "", | |||||
| estimatedArrivalDateTo: "", | |||||
| orderDateTo: "", | |||||
| supplierNameTo: "", | |||||
| shopNameTo: "", | |||||
| deliveryOrderLinesTo: "" | |||||
| }); | |||||
| useEffect(() =>{ | |||||
| setPagingController(p => ({ | |||||
| ...p, | |||||
| pageNum: 1, | |||||
| })); | |||||
| }, [searchAllDos]); | |||||
| const [hasSearched, setHasSearched] = useState(false); | |||||
| const [hasResults, setHasResults] = useState(false); | |||||
| useEffect(() =>{ | |||||
| setPagingController(p => ({ | |||||
| ...p, | |||||
| pageNum: 1, | |||||
| })); | |||||
| }, [searchAllDos]); | |||||
| //INITIALIZATION | //INITIALIZATION | ||||
| @@ -156,7 +174,8 @@ useEffect(() =>{ | |||||
| try { | try { | ||||
| const data = await fetchDoSearch("", "", "", "", "","",""); | const data = await fetchDoSearch("", "", "", "", "","",""); | ||||
| setSearchAllDos(data); | setSearchAllDos(data); | ||||
| setHasSearched(false); | |||||
| setHasSearched(false); | |||||
| } | } | ||||
| catch (error) { | catch (error) { | ||||
| console.error("Error: ", error); | console.error("Error: ", error); | ||||
| @@ -273,9 +292,10 @@ useEffect(() =>{ | |||||
| ); | ); | ||||
| //SEARCH FUNCTION | //SEARCH FUNCTION | ||||
| const handleSearch = useCallback(async (query: SearchBoxInputs) => { | const handleSearch = useCallback(async (query: SearchBoxInputs) => { | ||||
| try { | try { | ||||
| setCurrentSearchParams(query); | |||||
| let orderStartDate = query.orderDate; | let orderStartDate = query.orderDate; | ||||
| let orderEndDate = query.orderDateTo; | let orderEndDate = query.orderDateTo; | ||||
| let estArrStartDate = query.estimatedArrivalDate; | let estArrStartDate = query.estimatedArrivalDate; | ||||
| @@ -313,22 +333,92 @@ useEffect(() =>{ | |||||
| estArrEndDate | estArrEndDate | ||||
| ); | ); | ||||
| console.log("Search parameters:", { | |||||
| code: query.code, | |||||
| shopName: query.shopName, | |||||
| status: query.status, | |||||
| orderStartDate, | |||||
| orderEndDate, | |||||
| estArrStartDate, | |||||
| estArrEndDate | |||||
| }); | |||||
| setSearchAllDos(data); | setSearchAllDos(data); | ||||
| setHasSearched(true); | |||||
| setHasResults(data.length > 0); | |||||
| } catch (error) { | } catch (error) { | ||||
| console.error("Error: ", error); | console.error("Error: ", error); | ||||
| } | } | ||||
| }, []); | }, []); | ||||
| const handleBatchRelease = useCallback(async () => { | |||||
| const query = currentSearchParams; | |||||
| let orderStartDate = query.orderDate; | |||||
| let orderEndDate = query.orderDateTo; | |||||
| let estArrStartDate = query.estimatedArrivalDate; | |||||
| let estArrEndDate = query.estimatedArrivalDateTo; | |||||
| const time = "T00:00:00"; | |||||
| if(orderStartDate != ""){ | |||||
| orderStartDate = query.orderDate + time; | |||||
| } | |||||
| if(orderEndDate != ""){ | |||||
| orderEndDate = query.orderDateTo + time; | |||||
| } | |||||
| if(estArrStartDate != ""){ | |||||
| estArrStartDate = query.estimatedArrivalDate + time; | |||||
| } | |||||
| if(estArrEndDate != ""){ | |||||
| estArrEndDate = query.estimatedArrivalDateTo + time; | |||||
| } | |||||
| let status = ""; | |||||
| if(query.status == "All"){ | |||||
| status = ""; | |||||
| } | |||||
| else{ | |||||
| status = query.status; | |||||
| } | |||||
| const batchReleaseData = await fetchDoSearch( | |||||
| query.code || "", | |||||
| query.shopName || "", | |||||
| status, | |||||
| orderStartDate, | |||||
| orderEndDate, | |||||
| estArrStartDate, | |||||
| estArrEndDate | |||||
| ); | |||||
| const extractedIds = batchReleaseData.map(item => item.id); | |||||
| const extractedIdsCount = batchReleaseData.map(item => item.id).length; | |||||
| const extractedItemsCount = batchReleaseData.flatMap(item => item.deliveryOrderLines).length; | |||||
| console.log("Batch Release Data:", batchReleaseData); | |||||
| console.log("Query:", query); | |||||
| console.log("IDs: " + extractedIds); | |||||
| console.log("Total Shops: " + extractedIdsCount); | |||||
| console.log("Total Items: " + extractedItemsCount); | |||||
| const result = await Swal.fire( | |||||
| { | |||||
| icon: "info", | |||||
| title: "Batch Release", | |||||
| html: `<p>Selected Shop(s): ` + extractedIdsCount.toString() + `</p> | |||||
| <p>Selected Item(s): ` + extractedItemsCount.toString() + `</p>`, | |||||
| showCancelButton: true, | |||||
| confirmButtonText: "Confirm", | |||||
| cancelButtonText: "Cancel", | |||||
| confirmButtonColor: "#3085d6", | |||||
| cancelButtonColor: "#d33" | |||||
| }); | |||||
| if (result.isConfirmed) { | |||||
| await Promise.all(extractedIds.map((id) => releaseDo({ id }))); | |||||
| Swal.fire({ | |||||
| position: "bottom-end", | |||||
| icon: "success", | |||||
| text: "Batch release completed successfully.", | |||||
| showConfirmButton: false, | |||||
| timer: 1500 | |||||
| }); | |||||
| } | |||||
| }, [currentSearchParams]); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| <FormProvider {...formProps}> | <FormProvider {...formProps}> | ||||
| @@ -359,18 +449,21 @@ useEffect(() =>{ | |||||
| > | > | ||||
| {t("Create")} | {t("Create")} | ||||
| </Button> | </Button> | ||||
| <Button | |||||
| name="direct_release" | |||||
| variant="contained" | |||||
| type="submit" | |||||
| > | |||||
| {t("Direct Release")} | |||||
| </Button> | |||||
| {hasSearched && hasResults && ( | |||||
| <Button | |||||
| name="batch_release" | |||||
| variant="contained" | |||||
| onClick={handleBatchRelease} | |||||
| > | |||||
| {t("Batch Release")} | |||||
| </Button> | |||||
| )} | |||||
| </Stack> | </Stack> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| <SearchBox | <SearchBox | ||||
| criteria={searchCriteria} | criteria={searchCriteria} | ||||
| @@ -378,6 +471,7 @@ useEffect(() =>{ | |||||
| onReset={onReset} | onReset={onReset} | ||||
| /> | /> | ||||
| <StyledDataGrid | <StyledDataGrid | ||||
| rows={pagedRows} | rows={pagedRows} | ||||
| columns={columns} | columns={columns} | ||||
| @@ -410,6 +504,7 @@ useEffect(() =>{ | |||||
| ); | ); | ||||
| }; | }; | ||||
| const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | ||||
| return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | ||||
| }; | }; | ||||