| @@ -1,4 +1,4 @@ | |||||
| import ImportTesting from "@/components/ImportTesting"; | |||||
| import M18ImportTesting from "@/components/M18ImportTesting"; | |||||
| import { getServerI18n } from "@/i18n"; | import { getServerI18n } from "@/i18n"; | ||||
| import { Stack } from "@mui/material"; | import { Stack } from "@mui/material"; | ||||
| import { Metadata } from "next"; | import { Metadata } from "next"; | ||||
| @@ -8,8 +8,8 @@ export const metadata: Metadata = { | |||||
| title: "Import Testing" | title: "Import Testing" | ||||
| } | } | ||||
| const ImportTestingPage: React.FC = async () => { | |||||
| const { t } = await getServerI18n("importTesting"); | |||||
| const M18ImportTestingPage: React.FC = async () => { | |||||
| const { t } = await getServerI18n("m18ImportTesting"); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -20,11 +20,11 @@ const ImportTestingPage: React.FC = async () => { | |||||
| rowGap={2} | rowGap={2} | ||||
| > | > | ||||
| </Stack> | </Stack> | ||||
| <Suspense fallback={<ImportTesting.Loading />}> | |||||
| <ImportTesting /> | |||||
| <Suspense fallback={<M18ImportTesting.Loading />}> | |||||
| <M18ImportTesting /> | |||||
| </Suspense> | </Suspense> | ||||
| </> | </> | ||||
| ) | ) | ||||
| } | } | ||||
| export default ImportTestingPage; | |||||
| export default M18ImportTestingPage; | |||||
| @@ -1,21 +0,0 @@ | |||||
| "use server"; | |||||
| import { serverFetchWithNoContent } from '@/app/utils/fetchUtil'; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| export interface ImportPoForm { | |||||
| dateFrom: string, | |||||
| dateTo: string, | |||||
| } | |||||
| export interface ImportTestingForm { | |||||
| po: ImportPoForm | |||||
| } | |||||
| export const testImportPo = async (data: ImportPoForm) => { | |||||
| return serverFetchWithNoContent(`${BASE_API_URL}/m18/po`, { | |||||
| method: "POST", | |||||
| body: JSON.stringify(data), | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }) | |||||
| } | |||||
| @@ -0,0 +1,49 @@ | |||||
| "use server"; | |||||
| import { serverFetchWithNoContent } from '@/app/utils/fetchUtil'; | |||||
| import { BASE_API_URL } from "@/config/api"; | |||||
| export interface M18ImportPoForm { | |||||
| modifiedDateFrom: string, | |||||
| modifiedDateTo: string, | |||||
| } | |||||
| export interface M18ImportPqForm { | |||||
| modifiedDateFrom: string, | |||||
| modifiedDateTo: string, | |||||
| } | |||||
| export interface M18ImportMasterDataForm { | |||||
| modifiedDateFrom: string, | |||||
| modifiedDateTo: string, | |||||
| } | |||||
| export interface M18ImportTestingForm { | |||||
| po: M18ImportPoForm, | |||||
| pq: M18ImportPqForm, | |||||
| masterData: M18ImportMasterDataForm, | |||||
| } | |||||
| export const testM18ImportPo = async (data: M18ImportPoForm) => { | |||||
| return serverFetchWithNoContent(`${BASE_API_URL}/m18/po`, { | |||||
| method: "POST", | |||||
| body: JSON.stringify(data), | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }) | |||||
| } | |||||
| export const testM18ImportPq = async (data: M18ImportPqForm) => { | |||||
| return serverFetchWithNoContent(`${BASE_API_URL}/m18/pq`, { | |||||
| method: "POST", | |||||
| body: JSON.stringify(data), | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }) | |||||
| } | |||||
| export const testM18ImportMasterData = async (data: M18ImportMasterDataForm) => { | |||||
| return serverFetchWithNoContent(`${BASE_API_URL}/m18/master-data`, { | |||||
| method: "POST", | |||||
| body: JSON.stringify(data), | |||||
| headers: { "Content-Type": "application/json" }, | |||||
| }) | |||||
| } | |||||
| @@ -1,67 +0,0 @@ | |||||
| "use client" | |||||
| import { ImportTestingForm, testImportPo } from "@/app/api/settings/importTesting/actions"; | |||||
| import { Card, CardContent, Grid, Stack, Typography } from "@mui/material"; | |||||
| import React, { BaseSyntheticEvent, FormEvent, useCallback, useState } from "react"; | |||||
| import { FormProvider, SubmitErrorHandler, useForm } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import ImportPo from "./ImportPo"; | |||||
| import { ImportPoForm } from "@/app/api/settings/importTesting/actions"; | |||||
| interface Props { | |||||
| } | |||||
| const ImportTesting: React.FC<Props> = ({ | |||||
| }) => { | |||||
| const { t } = useTranslation() | |||||
| const [isLoading, setIsLoading] = useState(false) | |||||
| const formProps = useForm<ImportTestingForm>() | |||||
| const onSubmit = useCallback(async (data: ImportTestingForm, event?: BaseSyntheticEvent) => { | |||||
| const buttonId = (event?.nativeEvent as SubmitEvent).submitter?.id | |||||
| console.log(data.po) | |||||
| switch (buttonId) { | |||||
| case "importPo": | |||||
| setIsLoading(() => true) | |||||
| const response = await testImportPo(data.po) | |||||
| console.log(response) | |||||
| if (response) { | |||||
| setIsLoading(() => false) | |||||
| } | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| }, []) | |||||
| const onSubmitError = useCallback<SubmitErrorHandler<ImportTestingForm>>( | |||||
| (errors) => { | |||||
| console.log(errors) | |||||
| }, | |||||
| [], | |||||
| ); | |||||
| return ( | |||||
| <Card> | |||||
| <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | |||||
| <Typography variant="overline">{t("Status: ")}{isLoading ? t("Importing...") : t("Ready to import")}</Typography> | |||||
| <FormProvider {...formProps}> | |||||
| <Stack | |||||
| spacing={2} | |||||
| component={"form"} | |||||
| onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)} | |||||
| > | |||||
| <Grid container> | |||||
| <ImportPo /> | |||||
| </Grid> | |||||
| </Stack> | |||||
| </FormProvider> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ) | |||||
| } | |||||
| export default ImportTesting; | |||||
| @@ -1,17 +0,0 @@ | |||||
| import React from "react"; | |||||
| import GeneralLoading from "../General/GeneralLoading" | |||||
| import ImportTesting from "./ImportTesting"; | |||||
| interface SubComponents { | |||||
| Loading: typeof GeneralLoading; | |||||
| } | |||||
| const ImportTestingWrapper: React.FC & SubComponents = async () => { | |||||
| return <ImportTesting/> | |||||
| } | |||||
| ImportTestingWrapper.Loading = GeneralLoading; | |||||
| export default ImportTestingWrapper | |||||
| @@ -1 +0,0 @@ | |||||
| export { default } from './ImportTestingWrapper' | |||||
| @@ -0,0 +1,126 @@ | |||||
| "use client" | |||||
| import { M18ImportTestingForm, M18ImportMasterDataForm } from "@/app/api/settings/m18ImportTesting/actions"; | |||||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; | |||||
| import { Check } from "@mui/icons-material"; | |||||
| import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; | |||||
| import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; | |||||
| import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||||
| import dayjs, { Dayjs } from "dayjs"; | |||||
| import React, { useCallback, useState } from "react"; | |||||
| import { Controller, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| interface Props { | |||||
| } | |||||
| const M18ImportMasterData: React.FC<Props> = ({ | |||||
| }) => { | |||||
| const { t } = useTranslation() | |||||
| const [isLoading, setIsLoading] = useState(false) | |||||
| const { | |||||
| control, | |||||
| formState: { errors }, | |||||
| watch | |||||
| } = useFormContext<M18ImportTestingForm>() | |||||
| const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { | |||||
| const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null | |||||
| onChange(formattedValue) | |||||
| }, []) | |||||
| return ( | |||||
| <Card sx={{ width: '100%' }}> | |||||
| <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | |||||
| <Grid container> | |||||
| <Grid container> | |||||
| <Typography variant="overline">{t("Import Master Data")}</Typography> | |||||
| </Grid> | |||||
| <Grid item xs={8}> | |||||
| <LocalizationProvider | |||||
| dateAdapter={AdapterDayjs} | |||||
| // TODO: Should maybe use a custom adapterLocale here to support YYYY-MM-DD | |||||
| adapterLocale="zh-hk" | |||||
| > | |||||
| <Box display="flex"> | |||||
| <Controller | |||||
| control={control} | |||||
| name="masterData.modifiedDateFrom" | |||||
| // rules={{ | |||||
| // // required: "Please input the date From!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | |||||
| <DateTimePicker | |||||
| label={t("Modified Date From")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | |||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| error: !!error, | |||||
| helperText: error ? error.message : null | |||||
| } | |||||
| }} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| <Box | |||||
| display="flex" | |||||
| alignItems="center" | |||||
| justifyContent="center" | |||||
| marginInline={2} | |||||
| > | |||||
| {"-"} | |||||
| </Box> | |||||
| <Controller | |||||
| control={control} | |||||
| name="masterData.modifiedDateTo" | |||||
| // rules={{ | |||||
| // // required: "Please input the date to!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", | |||||
| // isFuture: (value) => | |||||
| // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | |||||
| <DateTimePicker | |||||
| label={t("Modified Date To")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | |||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| error: !!error, | |||||
| helperText: error ? error.message : null | |||||
| } | |||||
| }} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| </Box> | |||||
| </LocalizationProvider> | |||||
| </Grid> | |||||
| </Grid> | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||||
| <Button | |||||
| name="m18ImportMasterData" | |||||
| id="m18ImportMasterData" | |||||
| variant="contained" | |||||
| startIcon={<Check />} | |||||
| type="submit" | |||||
| > | |||||
| {t("Import Master Data")} | |||||
| </Button> | |||||
| </Stack> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ) | |||||
| } | |||||
| export default M18ImportMasterData; | |||||
| @@ -1,6 +1,5 @@ | |||||
| "use client" | "use client" | ||||
| import { ImportTestingForm } from "@/app/api/settings/importTesting/actions"; | |||||
| import { ImportPoForm } from "@/app/api/settings/importTesting/actions"; | |||||
| import { M18ImportTestingForm, M18ImportPoForm } from "@/app/api/settings/m18ImportTesting/actions"; | |||||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; | import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; | ||||
| import { Check } from "@mui/icons-material"; | import { Check } from "@mui/icons-material"; | ||||
| import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; | import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; | ||||
| @@ -14,7 +13,7 @@ import { useTranslation } from "react-i18next"; | |||||
| interface Props { | interface Props { | ||||
| } | } | ||||
| const ImportPo: React.FC<Props> = ({ | |||||
| const M18ImportPo: React.FC<Props> = ({ | |||||
| }) => { | }) => { | ||||
| const { t } = useTranslation() | const { t } = useTranslation() | ||||
| @@ -23,7 +22,7 @@ const ImportPo: React.FC<Props> = ({ | |||||
| control, | control, | ||||
| formState: { errors }, | formState: { errors }, | ||||
| watch | watch | ||||
| } = useFormContext<ImportTestingForm>() | |||||
| } = useFormContext<M18ImportTestingForm>() | |||||
| const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { | const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { | ||||
| const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null | const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null | ||||
| @@ -37,7 +36,7 @@ const ImportPo: React.FC<Props> = ({ | |||||
| <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | ||||
| <Grid container> | <Grid container> | ||||
| <Grid container> | <Grid container> | ||||
| <Typography variant="overline">{t("Import PO")}</Typography> | |||||
| <Typography variant="overline">{t("Import Purchase Order")}</Typography> | |||||
| </Grid> | </Grid> | ||||
| <Grid item xs={8}> | <Grid item xs={8}> | ||||
| <LocalizationProvider | <LocalizationProvider | ||||
| @@ -48,17 +47,17 @@ const ImportPo: React.FC<Props> = ({ | |||||
| <Box display="flex"> | <Box display="flex"> | ||||
| <Controller | <Controller | ||||
| control={control} | control={control} | ||||
| name="po.dateFrom" | |||||
| rules={{ | |||||
| required: "Please input the date From!", | |||||
| validate: { | |||||
| isValid: (value) => | |||||
| value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" | |||||
| }, | |||||
| }} | |||||
| name="po.modifiedDateFrom" | |||||
| // rules={{ | |||||
| // required: "Please input the date From!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | render={({ field, fieldState: { error } }) => ( | ||||
| <DateTimePicker | <DateTimePicker | ||||
| label={t("Import Po From")} | |||||
| label={t("Modified Date From *")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | ||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | ||||
| slotProps={{ | slotProps={{ | ||||
| @@ -80,19 +79,19 @@ const ImportPo: React.FC<Props> = ({ | |||||
| </Box> | </Box> | ||||
| <Controller | <Controller | ||||
| control={control} | control={control} | ||||
| name="po.dateTo" | |||||
| rules={{ | |||||
| required: "Please input the date to!", | |||||
| validate: { | |||||
| isValid: (value) => | |||||
| value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", | |||||
| isFuture: (value) => | |||||
| dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", | |||||
| }, | |||||
| }} | |||||
| name="po.modifiedDateTo" | |||||
| // rules={{ | |||||
| // required: "Please input the date to!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", | |||||
| // isFuture: (value) => | |||||
| // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | render={({ field, fieldState: { error } }) => ( | ||||
| <DateTimePicker | <DateTimePicker | ||||
| label={t("Import Po To")} | |||||
| label={t("Modified Date To *")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | ||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | ||||
| slotProps={{ | slotProps={{ | ||||
| @@ -110,8 +109,8 @@ const ImportPo: React.FC<Props> = ({ | |||||
| </Grid> | </Grid> | ||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
| <Button | <Button | ||||
| name="importPo" | |||||
| id="importPo" | |||||
| name="m18ImportPo" | |||||
| id="m18ImportPo" | |||||
| variant="contained" | variant="contained" | ||||
| startIcon={<Check />} | startIcon={<Check />} | ||||
| type="submit" | type="submit" | ||||
| @@ -124,4 +123,4 @@ const ImportPo: React.FC<Props> = ({ | |||||
| ) | ) | ||||
| } | } | ||||
| export default ImportPo; | |||||
| export default M18ImportPo; | |||||
| @@ -0,0 +1,126 @@ | |||||
| "use client" | |||||
| import { M18ImportTestingForm, M18ImportPqForm } from "@/app/api/settings/m18ImportTesting/actions"; | |||||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT, OUTPUT_TIME_FORMAT, dateTimeStringToDayjs } from "@/app/utils/formatUtil"; | |||||
| import { Check } from "@mui/icons-material"; | |||||
| import { Box, Button, Card, CardContent, FormControl, Grid, Stack, Typography } from "@mui/material"; | |||||
| import { DatePicker, DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers"; | |||||
| import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; | |||||
| import dayjs, { Dayjs } from "dayjs"; | |||||
| import React, { useCallback, useState } from "react"; | |||||
| import { Controller, useFormContext } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| interface Props { | |||||
| } | |||||
| const M18ImportPq: React.FC<Props> = ({ | |||||
| }) => { | |||||
| const { t } = useTranslation() | |||||
| const [isLoading, setIsLoading] = useState(false) | |||||
| const { | |||||
| control, | |||||
| formState: { errors }, | |||||
| watch | |||||
| } = useFormContext<M18ImportTestingForm>() | |||||
| const handleDateTimePickerOnChange = useCallback((value: Dayjs | null, onChange: (value: any) => void) => { | |||||
| const formattedValue = value ? value.format(`${INPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`) : null | |||||
| onChange(formattedValue) | |||||
| }, []) | |||||
| return ( | |||||
| <Card sx={{ width: '100%' }}> | |||||
| <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | |||||
| <Grid container> | |||||
| <Grid container> | |||||
| <Typography variant="overline">{t("Import Purchase Quotation")}</Typography> | |||||
| </Grid> | |||||
| <Grid item xs={8}> | |||||
| <LocalizationProvider | |||||
| dateAdapter={AdapterDayjs} | |||||
| // TODO: Should maybe use a custom adapterLocale here to support YYYY-MM-DD | |||||
| adapterLocale="zh-hk" | |||||
| > | |||||
| <Box display="flex"> | |||||
| <Controller | |||||
| control={control} | |||||
| name="pq.modifiedDateFrom" | |||||
| // rules={{ | |||||
| // // required: "Please input the date From!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time" | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | |||||
| <DateTimePicker | |||||
| label={t("Modified Date From")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | |||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| error: !!error, | |||||
| helperText: error ? error.message : null | |||||
| } | |||||
| }} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| <Box | |||||
| display="flex" | |||||
| alignItems="center" | |||||
| justifyContent="center" | |||||
| marginInline={2} | |||||
| > | |||||
| {"-"} | |||||
| </Box> | |||||
| <Controller | |||||
| control={control} | |||||
| name="pq.modifiedDateTo" | |||||
| // rules={{ | |||||
| // // required: "Please input the date to!", | |||||
| // validate: { | |||||
| // isValid: (value) => | |||||
| // value && dateTimeStringToDayjs(value).isValid() ? true : "Invalid date-time", | |||||
| // isFuture: (value) => | |||||
| // dateTimeStringToDayjs(value).isAfter(watch("po.dateFrom")) || "Date must be in the future", | |||||
| // }, | |||||
| // }} | |||||
| render={({ field, fieldState: { error } }) => ( | |||||
| <DateTimePicker | |||||
| label={t("Modified Date To")} | |||||
| format={`${OUTPUT_DATE_FORMAT} ${OUTPUT_TIME_FORMAT}`} | |||||
| onChange={(newValue: Dayjs | null) => (handleDateTimePickerOnChange(newValue, field.onChange))} | |||||
| slotProps={{ | |||||
| textField: { | |||||
| error: !!error, | |||||
| helperText: error ? error.message : null | |||||
| } | |||||
| }} | |||||
| /> | |||||
| )} | |||||
| /> | |||||
| </Box> | |||||
| </LocalizationProvider> | |||||
| </Grid> | |||||
| </Grid> | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | |||||
| <Button | |||||
| name="m18ImportPq" | |||||
| id="m18ImportPq" | |||||
| variant="contained" | |||||
| startIcon={<Check />} | |||||
| type="submit" | |||||
| > | |||||
| {t("Import Pq")} | |||||
| </Button> | |||||
| </Stack> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ) | |||||
| } | |||||
| export default M18ImportPq; | |||||
| @@ -0,0 +1,143 @@ | |||||
| "use client" | |||||
| import { M18ImportTestingForm, testM18ImportPo, M18ImportPoForm, testM18ImportPq, testM18ImportMasterData } from "@/app/api/settings/m18ImportTesting/actions"; | |||||
| import { Card, CardContent, Grid, Stack, Typography } from "@mui/material"; | |||||
| import React, { BaseSyntheticEvent, FormEvent, useCallback, useState } from "react"; | |||||
| import { FormProvider, SubmitErrorHandler, useForm } from "react-hook-form"; | |||||
| import { useTranslation } from "react-i18next"; | |||||
| import M18ImportPo from "./M18ImportPo"; | |||||
| import M18ImportPq from "./M18ImportPq"; | |||||
| import { dateTimeStringToDayjs } from "@/app/utils/formatUtil"; | |||||
| import M18ImportMasterData from "./M18ImportMasterData"; | |||||
| interface Props { | |||||
| } | |||||
| const M18ImportTesting: React.FC<Props> = ({ | |||||
| }) => { | |||||
| const { t } = useTranslation() | |||||
| const [isLoading, setIsLoading] = useState(false) | |||||
| const formProps = useForm<M18ImportTestingForm>() | |||||
| const onSubmit = useCallback(async (data: M18ImportTestingForm, event?: BaseSyntheticEvent) => { | |||||
| console.log(isLoading) | |||||
| if (isLoading) { | |||||
| return; | |||||
| } | |||||
| const buttonId = (event?.nativeEvent as SubmitEvent).submitter?.id | |||||
| console.log(data) | |||||
| console.log(buttonId) | |||||
| switch (buttonId) { | |||||
| case "m18ImportMasterData": | |||||
| const mdDateFrom = data.masterData.modifiedDateFrom | |||||
| const mdDateTo = data.masterData.modifiedDateTo | |||||
| if (!(!!mdDateFrom && dateTimeStringToDayjs(mdDateFrom).isValid())) { | |||||
| formProps.setError("masterData.modifiedDateFrom", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (!(!!mdDateTo && dateTimeStringToDayjs(mdDateTo).isValid())) { | |||||
| formProps.setError("masterData.modifiedDateTo", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (formProps.formState.errors.masterData) { | |||||
| return; | |||||
| } | |||||
| setIsLoading(() => true) | |||||
| const mdResponse = await testM18ImportMasterData(data.masterData) | |||||
| console.log(mdResponse) | |||||
| if (mdResponse) { | |||||
| setIsLoading(() => false) | |||||
| } | |||||
| break; | |||||
| case "m18ImportPo": | |||||
| const poDateFrom = data.po.modifiedDateFrom | |||||
| const poDateTo = data.po.modifiedDateTo | |||||
| if (!(poDateFrom && dateTimeStringToDayjs(poDateFrom).isValid())) { | |||||
| formProps.setError("po.modifiedDateFrom", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (!(poDateTo && dateTimeStringToDayjs(poDateTo).isValid())) { | |||||
| formProps.setError("po.modifiedDateTo", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (formProps.formState.errors.po) { | |||||
| return; | |||||
| } | |||||
| setIsLoading(() => true) | |||||
| const poResponse = await testM18ImportMasterData(data.po) | |||||
| console.log(poResponse) | |||||
| if (poResponse) { | |||||
| setIsLoading(() => false) | |||||
| } | |||||
| break; | |||||
| case "m18ImportPq": | |||||
| const pqDateFrom = data.pq.modifiedDateFrom | |||||
| const pqDateTo = data.pq.modifiedDateTo | |||||
| if (!(!!pqDateFrom && dateTimeStringToDayjs(pqDateFrom).isValid())) { | |||||
| formProps.setError("pq.modifiedDateFrom", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (!(!!pqDateTo && dateTimeStringToDayjs(pqDateTo).isValid())) { | |||||
| formProps.setError("pq.modifiedDateTo", { message: "Invalid DateTime Format" }) | |||||
| } | |||||
| if (formProps.formState.errors.pq) { | |||||
| return; | |||||
| } | |||||
| setIsLoading(() => true) | |||||
| const pqResponse = await testM18ImportPq(data.pq) | |||||
| console.log(pqResponse) | |||||
| if (pqResponse) { | |||||
| setIsLoading(() => false) | |||||
| } | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| }, []) | |||||
| // const onSubmitError = useCallback<SubmitErrorHandler<M18ImportTestingForm>>( | |||||
| // (errors) => { | |||||
| // console.log(errors) | |||||
| // }, | |||||
| // [], | |||||
| // ); | |||||
| return ( | |||||
| <Card> | |||||
| <CardContent sx={{ display: "flex", flexDirection: "column", gap: 1 }}> | |||||
| <Typography variant="overline">{t("Status: ")}{isLoading ? t("Importing...") : t("Ready to import")}</Typography> | |||||
| <FormProvider {...formProps}> | |||||
| <Stack | |||||
| spacing={2} | |||||
| component={"form"} | |||||
| onSubmit={formProps.handleSubmit(onSubmit)} | |||||
| > | |||||
| <Grid container columnGap={2} rowGap={2}> | |||||
| <Grid item xs={12}> | |||||
| <M18ImportMasterData /> | |||||
| </Grid> | |||||
| <Grid item xs={12}> | |||||
| <M18ImportPo /> | |||||
| </Grid> | |||||
| <Grid item xs={12}> | |||||
| <M18ImportPq /> | |||||
| </Grid> | |||||
| </Grid> | |||||
| </Stack> | |||||
| </FormProvider> | |||||
| </CardContent> | |||||
| </Card> | |||||
| ) | |||||
| } | |||||
| export default M18ImportTesting; | |||||
| @@ -0,0 +1,17 @@ | |||||
| import React from "react"; | |||||
| import GeneralLoading from "../General/GeneralLoading" | |||||
| import M18ImportTesting from "./M18ImportTesting"; | |||||
| interface SubComponents { | |||||
| Loading: typeof GeneralLoading; | |||||
| } | |||||
| const M18ImportTestingWrapper: React.FC & SubComponents = async () => { | |||||
| return <M18ImportTesting/> | |||||
| } | |||||
| M18ImportTestingWrapper.Loading = GeneralLoading; | |||||
| export default M18ImportTestingWrapper | |||||
| @@ -0,0 +1 @@ | |||||
| export { default } from './M18ImportTestingWrapper' | |||||
| @@ -266,7 +266,7 @@ const NavigationContent: React.FC = () => { | |||||
| { | { | ||||
| icon: <RequestQuote />, | icon: <RequestQuote />, | ||||
| label: "Import Testing", | label: "Import Testing", | ||||
| path: "/settings/importTesting", | |||||
| path: "/settings/m18ImportTesting", | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||