| @@ -1,9 +1,9 @@ | |||
| "use client"; | |||
| 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 React, { useCallback, useEffect, useMemo, useState } from "react"; | |||
| import React, { ForwardedRef, useCallback, useEffect, useMemo, useState } from "react"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import { Criterion } from "../SearchBox"; | |||
| import { isEmpty, sortBy, uniqBy, upperFirst } from "lodash"; | |||
| @@ -26,12 +26,10 @@ import { | |||
| SubmitHandler, | |||
| useForm, | |||
| } 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 { GridRowSelectionModel } from "@mui/x-data-grid"; | |||
| import { TablePagination } from "@mui/material"; | |||
| import Swal from "sweetalert2"; | |||
| type Props = { | |||
| filterArgs?: Record<string, any>; | |||
| @@ -92,14 +90,34 @@ const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSear | |||
| const pagedRows = useMemo(() => { | |||
| const start = (pagingController.pageNum - 1) * 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 | |||
| @@ -156,7 +174,8 @@ useEffect(() =>{ | |||
| try { | |||
| const data = await fetchDoSearch("", "", "", "", "","",""); | |||
| setSearchAllDos(data); | |||
| setHasSearched(false); | |||
| setHasSearched(false); | |||
| } | |||
| catch (error) { | |||
| console.error("Error: ", error); | |||
| @@ -273,9 +292,10 @@ useEffect(() =>{ | |||
| ); | |||
| //SEARCH FUNCTION | |||
| const handleSearch = useCallback(async (query: SearchBoxInputs) => { | |||
| try { | |||
| setCurrentSearchParams(query); | |||
| let orderStartDate = query.orderDate; | |||
| let orderEndDate = query.orderDateTo; | |||
| let estArrStartDate = query.estimatedArrivalDate; | |||
| @@ -313,22 +333,92 @@ useEffect(() =>{ | |||
| estArrEndDate | |||
| ); | |||
| console.log("Search parameters:", { | |||
| code: query.code, | |||
| shopName: query.shopName, | |||
| status: query.status, | |||
| orderStartDate, | |||
| orderEndDate, | |||
| estArrStartDate, | |||
| estArrEndDate | |||
| }); | |||
| setSearchAllDos(data); | |||
| setHasSearched(true); | |||
| setHasResults(data.length > 0); | |||
| } catch (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 ( | |||
| <> | |||
| <FormProvider {...formProps}> | |||
| @@ -359,18 +449,21 @@ useEffect(() =>{ | |||
| > | |||
| {t("Create")} | |||
| </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> | |||
| </Grid> | |||
| </Grid> | |||
| <SearchBox | |||
| criteria={searchCriteria} | |||
| @@ -378,6 +471,7 @@ useEffect(() =>{ | |||
| onReset={onReset} | |||
| /> | |||
| <StyledDataGrid | |||
| rows={pagedRows} | |||
| columns={columns} | |||
| @@ -410,6 +504,7 @@ useEffect(() =>{ | |||
| ); | |||
| }; | |||
| const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => { | |||
| return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>; | |||
| }; | |||