|
|
@@ -1,15 +1,14 @@ |
|
|
"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 { useRouter } from "next/navigation"; |
|
|
import { useRouter } from "next/navigation"; |
|
|
import { useCallback, useMemo, useState } from "react"; |
|
|
|
|
|
|
|
|
import React, { 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"; |
|
|
import { Column } from "../SearchResults"; |
|
|
|
|
|
import { arrayToDateString, arrayToDayjs } from "@/app/utils/formatUtil"; |
|
|
import { arrayToDateString, arrayToDayjs } from "@/app/utils/formatUtil"; |
|
|
import SearchBox from "../SearchBox/SearchBox"; |
|
|
import SearchBox from "../SearchBox/SearchBox"; |
|
|
import SearchResults from "../SearchResults/SearchResults"; |
|
|
|
|
|
import { EditNote } from "@mui/icons-material"; |
|
|
import { EditNote } from "@mui/icons-material"; |
|
|
import InputDataGrid from "../InputDataGrid"; |
|
|
import InputDataGrid from "../InputDataGrid"; |
|
|
import { CreateConsoDoInput } from "@/app/api/do/actions"; |
|
|
import { CreateConsoDoInput } from "@/app/api/do/actions"; |
|
|
@@ -26,17 +25,22 @@ import { |
|
|
SubmitErrorHandler, |
|
|
SubmitErrorHandler, |
|
|
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 } 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"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Props = { |
|
|
type Props = { |
|
|
dos: DoResult[]; |
|
|
|
|
|
|
|
|
filterArgs?: Record<string, any>; |
|
|
|
|
|
searchQuery?: Record<string, any>; |
|
|
|
|
|
onDeliveryOrderSearch: () => void; |
|
|
}; |
|
|
}; |
|
|
|
|
|
type SearchBoxInputs = Record<"code" | "status" | "estimatedArrivalDate" | "orderDate" | "supplierName" | "shopName" | "deliveryOrderLines" | "codeTo" | "statusTo" | "estimatedArrivalDateTo" | "orderDateTo" | "supplierNameTo" | "shopNameTo" | "deliveryOrderLinesTo" , string>; |
|
|
|
|
|
type SearchParamNames = keyof SearchBoxInputs; |
|
|
|
|
|
|
|
|
type SearchQuery = Partial<Omit<DoResult, "id">>; |
|
|
|
|
|
type SearchParamNames = keyof SearchQuery; |
|
|
|
|
|
// put all this into a new component |
|
|
// put all this into a new component |
|
|
// ConsoDoForm |
|
|
// ConsoDoForm |
|
|
type EntryError = |
|
|
type EntryError = |
|
|
@@ -46,7 +50,8 @@ type EntryError = |
|
|
| undefined; |
|
|
| undefined; |
|
|
type DoRow = TableRow<Partial<DoResult>, EntryError>; |
|
|
type DoRow = TableRow<Partial<DoResult>, EntryError>; |
|
|
|
|
|
|
|
|
const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const DoSearch: React.FC<Props> = ({filterArgs, searchQuery, onDeliveryOrderSearch}) => { |
|
|
const apiRef = useGridApiRef(); |
|
|
const apiRef = useGridApiRef(); |
|
|
|
|
|
|
|
|
const formProps = useForm<CreateConsoDoInput>({ |
|
|
const formProps = useForm<CreateConsoDoInput>({ |
|
|
@@ -54,39 +59,66 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
}); |
|
|
}); |
|
|
const errors = formProps.formState.errors; |
|
|
const errors = formProps.formState.errors; |
|
|
|
|
|
|
|
|
const tttt = [ |
|
|
|
|
|
{ |
|
|
|
|
|
id: 1, |
|
|
|
|
|
code: "string", |
|
|
|
|
|
orderDate: "2025-01-01", |
|
|
|
|
|
estimatedArrivalDate: "2025-01-01", |
|
|
|
|
|
status: "string", |
|
|
|
|
|
shopName: "string", |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
id: 2, |
|
|
|
|
|
code: "string1", |
|
|
|
|
|
orderDate: "2025-01-01", |
|
|
|
|
|
estimatedArrivalDate: "2025-01-01", |
|
|
|
|
|
status: "string", |
|
|
|
|
|
shopName: "string", |
|
|
|
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
id: 3, |
|
|
|
|
|
code: "string2", |
|
|
|
|
|
orderDate: "2025-01-01", |
|
|
|
|
|
estimatedArrivalDate: "2025-01-01", |
|
|
|
|
|
status: "string", |
|
|
|
|
|
shopName: "string", |
|
|
|
|
|
}, |
|
|
|
|
|
]; |
|
|
|
|
|
// const [filteredDos, setFilteredDos] = useState<DoResult[]>(dos); |
|
|
|
|
|
const [filteredDos, setFilteredDos] = useState<DoResult[]>(tttt); |
|
|
|
|
|
|
|
|
|
|
|
const { t } = useTranslation("do"); |
|
|
const { t } = useTranslation("do"); |
|
|
const router = useRouter(); |
|
|
const router = useRouter(); |
|
|
const [rowSelectionModel, setRowSelectionModel] = |
|
|
const [rowSelectionModel, setRowSelectionModel] = |
|
|
useState<GridRowSelectionModel>([]); |
|
|
useState<GridRowSelectionModel>([]); |
|
|
|
|
|
|
|
|
|
|
|
const [searchAllDos, setSearchAllDos] = useState<DoSearchAll[]>([]); |
|
|
|
|
|
|
|
|
|
|
|
const [pagingController, setPagingController] = useState({ |
|
|
|
|
|
pageNum: 1, |
|
|
|
|
|
pageSize: 10, |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
const handlePageChange = useCallback((event: unknown, newPage: number) => { |
|
|
|
|
|
const newPagingController = { |
|
|
|
|
|
...pagingController, |
|
|
|
|
|
pageNum: newPage + 1, |
|
|
|
|
|
}; |
|
|
|
|
|
setPagingController(newPagingController); |
|
|
|
|
|
},[pagingController]); |
|
|
|
|
|
|
|
|
|
|
|
const handlePageSizeChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => { |
|
|
|
|
|
const newPageSize = parseInt(event.target.value, 10); |
|
|
|
|
|
const newPagingController = { |
|
|
|
|
|
pageNum: 1, |
|
|
|
|
|
pageSize: newPageSize, |
|
|
|
|
|
}; |
|
|
|
|
|
setPagingController(newPagingController); |
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
|
|
|
const pagedRows = useMemo(() => { |
|
|
|
|
|
const start = (pagingController.pageNum - 1) * pagingController.pageSize; |
|
|
|
|
|
return searchAllDos.slice(start, start + pagingController.pageSize); |
|
|
|
|
|
}, [searchAllDos, pagingController]); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() =>{ |
|
|
|
|
|
setPagingController(p => ({ |
|
|
|
|
|
...p, |
|
|
|
|
|
pageNum: 1, |
|
|
|
|
|
})); |
|
|
|
|
|
}, [searchAllDos]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//INITIALIZATION |
|
|
|
|
|
useEffect(() => { |
|
|
|
|
|
const loadItems = async () => { |
|
|
|
|
|
try{ |
|
|
|
|
|
const itemsData = await fetchDoSearch("","","","","","",""); |
|
|
|
|
|
setSearchAllDos(itemsData); |
|
|
|
|
|
} |
|
|
|
|
|
catch (error){ |
|
|
|
|
|
console.error("Loading Error: ", error); |
|
|
|
|
|
setSearchAllDos([]); |
|
|
|
|
|
}; |
|
|
|
|
|
}; |
|
|
|
|
|
loadItems(); |
|
|
|
|
|
console.log("success"); |
|
|
|
|
|
},[]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const searchCriteria: Criterion<SearchParamNames>[] = useMemo( |
|
|
const searchCriteria: Criterion<SearchParamNames>[] = useMemo( |
|
|
() => [ |
|
|
() => [ |
|
|
{ label: t("Code"), paramName: "code", type: "text" }, |
|
|
{ label: t("Code"), paramName: "code", type: "text" }, |
|
|
@@ -98,28 +130,39 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
type: "dateRange", |
|
|
type: "dateRange", |
|
|
}, |
|
|
}, |
|
|
{ label: t("Shop Name"), paramName: "shopName", type: "text" }, |
|
|
{ label: t("Shop Name"), paramName: "shopName", type: "text" }, |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
label: t("Estimated Arrival From"), |
|
|
|
|
|
label2: t("Estimated Arrival To"), |
|
|
|
|
|
paramName: "estimatedArrivalDate", |
|
|
|
|
|
type: "dateRange", |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
{ |
|
|
{ |
|
|
label: t("Status"), |
|
|
label: t("Status"), |
|
|
paramName: "status", |
|
|
paramName: "status", |
|
|
type: "autocomplete", |
|
|
type: "autocomplete", |
|
|
options: sortBy( |
|
|
|
|
|
uniqBy( |
|
|
|
|
|
dos.map((_do) => ({ |
|
|
|
|
|
value: _do.status, |
|
|
|
|
|
label: t(upperFirst(_do.status)), |
|
|
|
|
|
})), |
|
|
|
|
|
"value", |
|
|
|
|
|
), |
|
|
|
|
|
"label", |
|
|
|
|
|
), |
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
options:[ |
|
|
|
|
|
{label: t('Pending'), value: 'pending'}, |
|
|
|
|
|
{label: t('Receiving'), value: 'receiving'}, |
|
|
|
|
|
{label: t('Completed'), value: 'completed'} |
|
|
|
|
|
] |
|
|
|
|
|
} |
|
|
], |
|
|
], |
|
|
[t, dos], |
|
|
|
|
|
|
|
|
[t], |
|
|
); |
|
|
); |
|
|
|
|
|
|
|
|
const onReset = useCallback(() => { |
|
|
|
|
|
setFilteredDos(dos); |
|
|
|
|
|
}, [dos]); |
|
|
|
|
|
|
|
|
const onReset = useCallback(async () => { |
|
|
|
|
|
try { |
|
|
|
|
|
const data = await fetchDoSearch("", "", "", "", "","",""); |
|
|
|
|
|
setSearchAllDos(data); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
catch (error) { |
|
|
|
|
|
console.error("Error: ", error); |
|
|
|
|
|
setSearchAllDos([]); |
|
|
|
|
|
} |
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
const onDetailClick = useCallback( |
|
|
const onDetailClick = useCallback( |
|
|
(doResult: DoResult) => { |
|
|
(doResult: DoResult) => { |
|
|
@@ -155,7 +198,6 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
// onClick: onDetailClick, |
|
|
// onClick: onDetailClick, |
|
|
// buttonIcon: <EditNote />, |
|
|
// buttonIcon: <EditNote />, |
|
|
// }, |
|
|
// }, |
|
|
|
|
|
|
|
|
{ |
|
|
{ |
|
|
field: "id", |
|
|
field: "id", |
|
|
headerName: t("Details"), |
|
|
headerName: t("Details"), |
|
|
@@ -174,13 +216,18 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
{ |
|
|
{ |
|
|
field: "code", |
|
|
field: "code", |
|
|
headerName: t("code"), |
|
|
headerName: t("code"), |
|
|
flex: 1, |
|
|
|
|
|
|
|
|
flex: 1.5, |
|
|
}, |
|
|
}, |
|
|
{ |
|
|
{ |
|
|
field: "shopName", |
|
|
field: "shopName", |
|
|
headerName: t("Shop Name"), |
|
|
headerName: t("Shop Name"), |
|
|
flex: 1, |
|
|
flex: 1, |
|
|
}, |
|
|
}, |
|
|
|
|
|
{ |
|
|
|
|
|
field: "supplierName", |
|
|
|
|
|
headerName: t("Supplier Name"), |
|
|
|
|
|
flex: 1, |
|
|
|
|
|
}, |
|
|
{ |
|
|
{ |
|
|
field: "orderDate", |
|
|
field: "orderDate", |
|
|
headerName: t("Order Date"), |
|
|
headerName: t("Order Date"), |
|
|
@@ -217,7 +264,6 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
async (data, event) => { |
|
|
async (data, event) => { |
|
|
const hasErrors = false; |
|
|
const hasErrors = false; |
|
|
console.log(errors); |
|
|
console.log(errors); |
|
|
console.log(data); |
|
|
|
|
|
}, |
|
|
}, |
|
|
[], |
|
|
[], |
|
|
); |
|
|
); |
|
|
@@ -225,6 +271,64 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
(errors) => {}, |
|
|
(errors) => {}, |
|
|
[], |
|
|
[], |
|
|
); |
|
|
); |
|
|
|
|
|
//SEARCH FUNCTION |
|
|
|
|
|
const handleSearch = useCallback(async (query: SearchBoxInputs) => { |
|
|
|
|
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
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 data = await fetchDoSearch( |
|
|
|
|
|
query.code || "", |
|
|
|
|
|
query.shopName || "", |
|
|
|
|
|
status, |
|
|
|
|
|
orderStartDate, |
|
|
|
|
|
orderEndDate, |
|
|
|
|
|
estArrStartDate, |
|
|
|
|
|
estArrEndDate |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
console.log("Search parameters:", { |
|
|
|
|
|
code: query.code, |
|
|
|
|
|
shopName: query.shopName, |
|
|
|
|
|
status: query.status, |
|
|
|
|
|
orderStartDate, |
|
|
|
|
|
orderEndDate, |
|
|
|
|
|
estArrStartDate, |
|
|
|
|
|
estArrEndDate |
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
setSearchAllDos(data); |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("Error: ", error); |
|
|
|
|
|
} |
|
|
|
|
|
}, []); |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<> |
|
|
<> |
|
|
<FormProvider {...formProps}> |
|
|
<FormProvider {...formProps}> |
|
|
@@ -246,6 +350,7 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
justifyContent="end" |
|
|
justifyContent="end" |
|
|
alignItems="end" |
|
|
alignItems="end" |
|
|
> |
|
|
> |
|
|
|
|
|
<Stack spacing={2} direction="row"> |
|
|
<Button |
|
|
<Button |
|
|
name="submit" |
|
|
name="submit" |
|
|
variant="contained" |
|
|
variant="contained" |
|
|
@@ -254,39 +359,29 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
> |
|
|
> |
|
|
{t("Create")} |
|
|
{t("Create")} |
|
|
</Button> |
|
|
</Button> |
|
|
|
|
|
<Button |
|
|
|
|
|
name="direct_release" |
|
|
|
|
|
variant="contained" |
|
|
|
|
|
type="submit" |
|
|
|
|
|
> |
|
|
|
|
|
{t("Direct Release")} |
|
|
|
|
|
</Button> |
|
|
|
|
|
</Stack> |
|
|
|
|
|
|
|
|
</Grid> |
|
|
</Grid> |
|
|
</Grid> |
|
|
</Grid> |
|
|
|
|
|
|
|
|
<SearchBox |
|
|
<SearchBox |
|
|
criteria={searchCriteria} |
|
|
criteria={searchCriteria} |
|
|
onSearch={(query) => { |
|
|
|
|
|
setFilteredDos( |
|
|
|
|
|
dos.filter((_do) => { |
|
|
|
|
|
const doOrderDateStr = arrayToDayjs(_do.orderDate); |
|
|
|
|
|
return ( |
|
|
|
|
|
_do.code.toLowerCase().includes(query.code.toLowerCase()) && |
|
|
|
|
|
_do.shopName |
|
|
|
|
|
.toLowerCase() |
|
|
|
|
|
.includes(query.shopName.toLowerCase()) && |
|
|
|
|
|
(query.status == "All" || |
|
|
|
|
|
_do.status |
|
|
|
|
|
.toLowerCase() |
|
|
|
|
|
.includes(query.status.toLowerCase())) && |
|
|
|
|
|
(isEmpty(query.orderDate) || |
|
|
|
|
|
doOrderDateStr.isSame(query.orderDate) || |
|
|
|
|
|
doOrderDateStr.isAfter(query.orderDate)) && |
|
|
|
|
|
(isEmpty(query.orderDateTo) || |
|
|
|
|
|
doOrderDateStr.isSame(query.orderDateTo) || |
|
|
|
|
|
doOrderDateStr.isBefore(query.orderDateTo)) |
|
|
|
|
|
); |
|
|
|
|
|
}), |
|
|
|
|
|
); |
|
|
|
|
|
}} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onSearch={handleSearch} |
|
|
|
|
|
|
|
|
onReset={onReset} |
|
|
onReset={onReset} |
|
|
/> |
|
|
/> |
|
|
<StyledDataGrid |
|
|
<StyledDataGrid |
|
|
checkboxSelection={true} |
|
|
|
|
|
rows={filteredDos} |
|
|
|
|
|
|
|
|
rows={pagedRows} |
|
|
columns={columns} |
|
|
columns={columns} |
|
|
|
|
|
checkboxSelection |
|
|
rowSelectionModel={rowSelectionModel} |
|
|
rowSelectionModel={rowSelectionModel} |
|
|
onRowSelectionModelChange={(newRowSelectionModel) => { |
|
|
onRowSelectionModelChange={(newRowSelectionModel) => { |
|
|
setRowSelectionModel(newRowSelectionModel); |
|
|
setRowSelectionModel(newRowSelectionModel); |
|
|
@@ -297,7 +392,19 @@ const DoSearch: React.FC<Props> = ({ dos }) => { |
|
|
noRowsOverlay: NoRowsOverlay, |
|
|
noRowsOverlay: NoRowsOverlay, |
|
|
}} |
|
|
}} |
|
|
/> |
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
<TablePagination |
|
|
|
|
|
component="div" |
|
|
|
|
|
count={searchAllDos.length} |
|
|
|
|
|
page={(pagingController.pageNum - 1)} |
|
|
|
|
|
rowsPerPage={pagingController.pageSize} |
|
|
|
|
|
onPageChange={handlePageChange} |
|
|
|
|
|
onRowsPerPageChange={handlePageSizeChange} |
|
|
|
|
|
rowsPerPageOptions={[10, 25, 50]} |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
</Stack> |
|
|
</Stack> |
|
|
|
|
|
|
|
|
</FormProvider> |
|
|
</FormProvider> |
|
|
</> |
|
|
</> |
|
|
); |
|
|
); |
|
|
@@ -319,4 +426,5 @@ const NoRowsOverlay: React.FC = () => { |
|
|
</Box> |
|
|
</Box> |
|
|
); |
|
|
); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
export default DoSearch; |
|
|
export default DoSearch; |