@@ -227,7 +227,9 @@ export const handleRefreshTokenFunction = () => { | |||||
}) | }) | ||||
.catch((refreshError) => { | .catch((refreshError) => { | ||||
console.log('Failed to refresh token'); | console.log('Failed to refresh token'); | ||||
console.log(refreshError) | |||||
if (refreshError != undefined){ | |||||
console.log(refreshError) | |||||
} | |||||
// token = null | // token = null | ||||
isRefresh = false; | isRefresh = false; | ||||
}); | }); | ||||
@@ -35,7 +35,9 @@ const RefreshTokenProvider = ({ children }) => { | |||||
}) | }) | ||||
.catch((refreshError) => { | .catch((refreshError) => { | ||||
console.log('Failed to refresh token'); | console.log('Failed to refresh token'); | ||||
console.log(refreshError) | |||||
if (refreshError != undefined){ | |||||
console.log(refreshError) | |||||
} | |||||
token.current = null | token.current = null | ||||
isRefresh.current = false; | isRefresh.current = false; | ||||
}); | }); | ||||
@@ -21,6 +21,7 @@ const SysSettingProvider = ({ children }) => { | |||||
// console.log(responseData) | // console.log(responseData) | ||||
setSysSetting(responseData); | setSysSetting(responseData); | ||||
localStorage.setItem('sysEnv', responseData.sysEnv) | localStorage.setItem('sysEnv', responseData.sysEnv) | ||||
localStorage.setItem('paymentSuspention', responseData.suspensionMode) | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -25,11 +25,12 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
// const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); | // const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); | ||||
const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); | const [minDate, setMinDate] = React.useState(searchCriteria.dateFrom); | ||||
const [maxDate] = React.useState(searchCriteria.dateFrom); | |||||
// const [status, setStatus] = React.useState(ComboData.paymentStatus[0]); | |||||
const [maxDate,setMaxDate] = React.useState(searchCriteria.dateFrom); | |||||
const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); | const [fromDateValue, setFromDateValue] = React.useState("dd / mm / yyyy"); | ||||
const [toDateValue, setToDateValue] = React.useState("dd / mm / yyyy"); | |||||
// const [status, setStatus] = React.useState(ComboData.paymentStatus[0]); | |||||
const { | |||||
const { | |||||
// register, | // register, | ||||
handleSubmit, | handleSubmit, | ||||
} = useForm() | } = useForm() | ||||
@@ -37,19 +38,27 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setFromDateValue(minDate); | setFromDateValue(minDate); | ||||
}, [minDate]); | }, [minDate]); | ||||
React.useEffect(() => { | |||||
setToDateValue(maxDate); | |||||
}, [maxDate]); | |||||
const onSubmit = () => { | const onSubmit = () => { | ||||
let sentDateFrom = ""; | let sentDateFrom = ""; | ||||
let sentDateTo = ""; | |||||
if (fromDateValue != "dd / mm / yyyy") { | if (fromDateValue != "dd / mm / yyyy") { | ||||
sentDateFrom = DateUtils.dateValue(fromDateValue) | sentDateFrom = DateUtils.dateValue(fromDateValue) | ||||
} | } | ||||
if (toDateValue != "dd / mm / yyyy") { | |||||
sentDateTo = DateUtils.dateValue(toDateValue) | |||||
} | |||||
const temp = { | const temp = { | ||||
// code: data.code, | // code: data.code, | ||||
// transNo: data.transNo, | // transNo: data.transNo, | ||||
dateFrom: sentDateFrom, | dateFrom: sentDateFrom, | ||||
// dateTo: data.dateTo, | |||||
dateTo: sentDateTo, | |||||
// status : (status?.type && status?.type != 'all') ? status?.type : "", | // status : (status?.type && status?.type != 'all') ? status?.type : "", | ||||
}; | }; | ||||
applySearch(temp); | applySearch(temp); | ||||
@@ -57,16 +66,20 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
const generateHandler = () => { | const generateHandler = () => { | ||||
let sentDateFrom = ""; | let sentDateFrom = ""; | ||||
let sentDateTo = ""; | |||||
if (fromDateValue != "dd / mm / yyyy") { | if (fromDateValue != "dd / mm / yyyy") { | ||||
sentDateFrom = DateUtils.dateValue(fromDateValue) | sentDateFrom = DateUtils.dateValue(fromDateValue) | ||||
} | } | ||||
if (toDateValue != "dd / mm / yyyy") { | |||||
sentDateTo = DateUtils.dateValue(toDateValue) | |||||
} | |||||
// const dateTo = getValues("dateTo") | // const dateTo = getValues("dateTo") | ||||
const temp = { | const temp = { | ||||
// code: data.code, | // code: data.code, | ||||
// transNo: data.transNo, | // transNo: data.transNo, | ||||
dateFrom: sentDateFrom, | dateFrom: sentDateFrom, | ||||
dateTo: "", | |||||
dateTo: sentDateTo, | |||||
// status : (status?.type && status?.type != 'all') ? status?.type : "", | // status : (status?.type && status?.type != 'all') ? status?.type : "", | ||||
}; | }; | ||||
generateXML(temp); | generateXML(temp); | ||||
@@ -90,8 +103,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
{/*row 2*/} | {/*row 2*/} | ||||
<Grid container display="flex" alignItems={"center"}> | <Grid container display="flex" alignItems={"center"}> | ||||
<Grid item xs={9} s={6} md={4} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||||
<Grid item xs={9} s={6} md={4} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | <LocalizationProvider dateAdapter={AdapterDayjs}> | ||||
<DemoItem components={['DatePicker']}> | <DemoItem components={['DatePicker']}> | ||||
<DatePicker | <DatePicker | ||||
@@ -104,7 +116,7 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
// }, | // }, | ||||
}} | }} | ||||
format="DD/MM/YYYY" | format="DD/MM/YYYY" | ||||
label="Credit Date" | |||||
label="From Date" | |||||
value={minDate === null ? null : dayjs(minDate)} | value={minDate === null ? null : dayjs(minDate)} | ||||
maxDate={maxDate === null ? null : dayjs(maxDate)} | maxDate={maxDate === null ? null : dayjs(maxDate)} | ||||
onChange={(newValue) => { | onChange={(newValue) => { | ||||
@@ -119,21 +131,30 @@ const SearchPublicNoticeForm = ({ applySearch, generateXML, searchCriteria, onGr | |||||
</Grid> | </Grid> | ||||
<Grid item xs={9} s={6} md={4} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | <Grid item xs={9} s={6} md={4} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | ||||
{/* <TextField | |||||
fullWidth | |||||
InputLabelProps={{ | |||||
shrink: true | |||||
}} | |||||
{...register("dateTo")} | |||||
InputProps={{ inputProps: { min: minDate } }} | |||||
onChange={(newValue) => { | |||||
setMaxDate(DateUtils.dateValue(newValue)); | |||||
}} | |||||
id="dateTo" | |||||
type="date" | |||||
label="To" | |||||
defaultValue={searchCriteria.dateTo} | |||||
/> */} | |||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | |||||
<DemoItem components={['DatePicker']}> | |||||
<DatePicker | |||||
id="dateTo" | |||||
// onError={(newError) => setReceiptFromError(newError)} | |||||
slotProps={{ | |||||
field: { readOnly: true, }, | |||||
// textField: { | |||||
// helperText: receiptFromErrorMessage, | |||||
// }, | |||||
}} | |||||
format="DD/MM/YYYY" | |||||
label="To Date" | |||||
value={maxDate === null ? null : dayjs(maxDate)} | |||||
minDate={minDate === null ? null : dayjs(minDate)} | |||||
onChange={(newValue) => { | |||||
// console.log(newValue) | |||||
if(newValue!=null){ | |||||
setMaxDate(newValue); | |||||
} | |||||
}} | |||||
/> | |||||
</DemoItem > | |||||
</LocalizationProvider> | |||||
</Grid> | </Grid> | ||||
{/* <Grid item xs={9} s={6} md={4} lg={3}> | {/* <Grid item xs={9} s={6} md={4} lg={3}> | ||||
@@ -2,7 +2,9 @@ | |||||
import { | import { | ||||
Grid, | Grid, | ||||
Typography, | Typography, | ||||
Stack | |||||
Stack, | |||||
Button, | |||||
Dialog, DialogTitle, DialogContent, DialogActions, | |||||
} from '@mui/material'; | } from '@mui/material'; | ||||
import MainCard from "components/MainCard"; | import MainCard from "components/MainCard"; | ||||
import {GEN_GFMIS_XML} from "utils/ApiPathConst"; | import {GEN_GFMIS_XML} from "utils/ApiPathConst"; | ||||
@@ -10,6 +12,12 @@ import * as React from "react"; | |||||
import * as HttpUtils from "utils/HttpUtils"; | import * as HttpUtils from "utils/HttpUtils"; | ||||
import * as DateUtils from "utils/DateUtils"; | import * as DateUtils from "utils/DateUtils"; | ||||
import {DatePicker} from "@mui/x-date-pickers/DatePicker"; | |||||
import dayjs from "dayjs"; | |||||
import {DemoItem} from "@mui/x-date-pickers/internals/demo"; | |||||
import {LocalizationProvider} from "@mui/x-date-pickers/LocalizationProvider"; | |||||
import {AdapterDayjs} from "@mui/x-date-pickers/AdapterDayjs"; | |||||
import Loadable from 'components/Loadable'; | import Loadable from 'components/Loadable'; | ||||
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | ||||
const SearchForm = Loadable(React.lazy(() => import('./SearchForm'))); | const SearchForm = Loadable(React.lazy(() => import('./SearchForm'))); | ||||
@@ -31,24 +39,41 @@ const BackgroundHead = { | |||||
const Index = () => { | const Index = () => { | ||||
const [searchCriteria, setSearchCriteria] = React.useState({ | const [searchCriteria, setSearchCriteria] = React.useState({ | ||||
dateFrom: DateUtils.dateValue(new Date()), | |||||
// dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), | |||||
dateTo: DateUtils.dateValue(new Date()), | |||||
dateFrom: DateUtils.dateValue(new Date().setDate(new Date().getDate()-14)), | |||||
}); | }); | ||||
const [onReady, setOnReady] = React.useState(false); | const [onReady, setOnReady] = React.useState(false); | ||||
const [onGridReady, setGridOnReady] = React.useState(false); | const [onGridReady, setGridOnReady] = React.useState(false); | ||||
const [isPopUp, setIsPopUp] = React.useState(false); | |||||
const [downloadInput, setDownloadInput] = React.useState(); | |||||
const [inputDate, setInputDate] = React.useState(searchCriteria.dateTo); | |||||
const [inputDateValue, setInputDateValue] = React.useState("dd / mm / yyyy"); | |||||
React.useEffect(() => { | |||||
setInputDateValue(inputDate); | |||||
}, [inputDate]); | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
setOnReady(true); | setOnReady(true); | ||||
}, [searchCriteria]); | }, [searchCriteria]); | ||||
function downloadXML(input) { | |||||
function downloadXML() { | |||||
// console.log(input) | // console.log(input) | ||||
setIsPopUp(false) | |||||
let sentDateFrom = ""; | |||||
if (inputDateValue != "dd / mm / yyyy") { | |||||
sentDateFrom = DateUtils.dateValue(inputDateValue) | |||||
} | |||||
HttpUtils.get({ | HttpUtils.get({ | ||||
url: GEN_GFMIS_XML + "/today", | url: GEN_GFMIS_XML + "/today", | ||||
params:{ | params:{ | ||||
// dateTo: input.dateTo, | |||||
dateFrom: input.dateFrom, | |||||
dateTo: downloadInput.dateTo, | |||||
dateFrom: downloadInput.dateFrom, | |||||
inputDate: sentDateFrom | |||||
}, | }, | ||||
onSuccess: (responseData) => { | onSuccess: (responseData) => { | ||||
// console.log(responseData) | // console.log(responseData) | ||||
@@ -100,6 +125,7 @@ const Index = () => { | |||||
function applySearch(input) { | function applySearch(input) { | ||||
setGridOnReady(true) | setGridOnReady(true) | ||||
setSearchCriteria(input); | setSearchCriteria(input); | ||||
setInputDate(input.dateFrom) | |||||
} | } | ||||
function applyGridOnReady(input) { | function applyGridOnReady(input) { | ||||
@@ -107,7 +133,8 @@ const Index = () => { | |||||
} | } | ||||
function generateXML(input) { | function generateXML(input) { | ||||
downloadXML(input); | |||||
setDownloadInput(input); | |||||
setIsPopUp(true) | |||||
} | } | ||||
return ( | return ( | ||||
@@ -147,6 +174,50 @@ const Index = () => { | |||||
/> | /> | ||||
</MainCard> | </MainCard> | ||||
</Grid> | </Grid> | ||||
<Dialog | |||||
open={isPopUp} | |||||
onClose={() => setIsPopUp(false)} | |||||
PaperProps={{ | |||||
sx: { | |||||
minWidth: '40vw', | |||||
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, | |||||
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } | |||||
} | |||||
}} | |||||
> | |||||
<DialogTitle> Bank Statement Collection Date </DialogTitle> | |||||
<DialogContent style={{ display: 'flex', }}> | |||||
<LocalizationProvider dateAdapter={AdapterDayjs}> | |||||
<DemoItem components={['DatePicker']}> | |||||
<DatePicker | |||||
id="dateFrom" | |||||
// onError={(newError) => setReceiptFromError(newError)} | |||||
slotProps={{ | |||||
field: { readOnly: true, }, | |||||
// textField: { | |||||
// helperText: receiptFromErrorMessage, | |||||
// }, | |||||
}} | |||||
format="DD/MM/YYYY" | |||||
// label="Credit Date" | |||||
value={inputDate === null ? null : dayjs(inputDate)} | |||||
maxDate={searchCriteria.dateTo === null ? null : dayjs(searchCriteria.dateTo)} | |||||
minDate={searchCriteria.dateFrom === null ? null : dayjs(searchCriteria.dateFrom)} | |||||
onChange={(newValue) => { | |||||
// console.log(newValue) | |||||
if(newValue!=null){ | |||||
setInputDate(newValue); | |||||
} | |||||
}} | |||||
/> | |||||
</DemoItem > | |||||
</LocalizationProvider> | |||||
</DialogContent> | |||||
<DialogActions> | |||||
<Button onClick={() => setIsPopUp(false)}><Typography variant="h5">Cancel</Typography></Button> | |||||
<Button onClick={() => downloadXML()}><Typography variant="h5">Confirm</Typography></Button> | |||||
</DialogActions> | |||||
</Dialog> | |||||
</Grid> | </Grid> | ||||
); | ); | ||||
}; | }; | ||||
@@ -13,6 +13,7 @@ import { useParams } from "react-router-dom"; | |||||
import { useNavigate } from "react-router-dom"; | import { useNavigate } from "react-router-dom"; | ||||
import * as DateUtils from "utils/DateUtils" | import * as DateUtils from "utils/DateUtils" | ||||
import * as FormatUtils from "utils/FormatUtils"; | import * as FormatUtils from "utils/FormatUtils"; | ||||
import { checkPaymentSuspention } from "utils/Utils"; | |||||
import Loadable from 'components/Loadable'; | import Loadable from 'components/Loadable'; | ||||
const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | ||||
@@ -150,7 +151,6 @@ const Index = () => { | |||||
<Typography variant="h4" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}> | <Typography variant="h4" sx={{ textAlign: "left", ml: 4, mr: 4, mt: 4, borderBottom: "1px solid black" }}> | ||||
<FormattedMessage id="proofPaymentHeader_online" /> | <FormattedMessage id="proofPaymentHeader_online" /> | ||||
</Typography> | </Typography> | ||||
<Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | ||||
<div dangerouslySetInnerHTML={{ | <div dangerouslySetInnerHTML={{ | ||||
__html: intl.formatMessage( | __html: intl.formatMessage( | ||||
@@ -174,36 +174,46 @@ const Index = () => { | |||||
) | ) | ||||
}} /> | }} /> | ||||
<br /> | <br /> | ||||
{checkPaymentSuspention()? | |||||
<div> | |||||
<Typography style={{ textAlign: "flex-start" }}> | |||||
<div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessage" }) }} /> | |||||
</Typography> | |||||
<br /> | |||||
</div>:null | |||||
} | |||||
</Typography> | </Typography> | ||||
<Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}> | |||||
<ThemeProvider theme={PNSPS_BUTTON_THEME}> | |||||
<Button | |||||
component="span" | |||||
variant="contained" | |||||
// sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }} | |||||
sx={{mr: 4 }} | |||||
onClick={() => { setIsPopUp(true) }} | |||||
> | |||||
<FormattedMessage id="payInstantly" /> | |||||
</Button> | |||||
</ThemeProvider> | |||||
{!checkPaymentSuspention()? | |||||
<Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}> | |||||
<ThemeProvider theme={PNSPS_BUTTON_THEME}> | |||||
<Button | |||||
component="span" | |||||
variant="contained" | |||||
// sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }} | |||||
sx={{mr: 4 }} | |||||
onClick={() => { setIsPopUp(true) }} | |||||
> | |||||
<FormattedMessage id="payInstantly" /> | |||||
</Button> | |||||
</ThemeProvider> | |||||
<FormattedMessage id="or" /> | |||||
<FormattedMessage id="or" /> | |||||
<ThemeProvider theme={PNSPS_BUTTON_THEME}> | |||||
<Button | |||||
component="span" | |||||
variant="contained" | |||||
sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }} | |||||
onClick={() => { | |||||
navigate("/publicNotice"); | |||||
}} | |||||
> | |||||
<FormattedMessage id="payLater" /> | |||||
</Button> | |||||
</ThemeProvider> | |||||
</Typography> | |||||
<ThemeProvider theme={PNSPS_BUTTON_THEME}> | |||||
<Button | |||||
component="span" | |||||
variant="contained" | |||||
sx={{ ml: { sm: 4, md: 4, lg: 4 }, mr: 4, mt: { xs: 2, sm: 2 }, mb: { xs: 2, sm: 2 } }} | |||||
onClick={() => { | |||||
navigate("/publicNotice"); | |||||
}} | |||||
> | |||||
<FormattedMessage id="payLater" /> | |||||
</Button> | |||||
</ThemeProvider> | |||||
</Typography>:null | |||||
} | |||||
<Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | <Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | ||||
<div dangerouslySetInnerHTML={{ | <div dangerouslySetInnerHTML={{ | ||||
@@ -258,47 +258,43 @@ const ApplicationDetailCard = ({ formData, }) => { | |||||
<Grid item xs={12} md={5} lg={5} sx={{ mb: 1, }}> | <Grid item xs={12} md={5} lg={5} sx={{ mb: 1, }}> | ||||
<Grid container alignItems={"center"}> | <Grid container alignItems={"center"}> | ||||
{ | |||||
data.creditor == true ? | |||||
<> | |||||
<Grid item xs={12} md={12} lg={12} | |||||
sx={{ display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5" display="inline"> | |||||
<FormattedMessage id="commentDeadline" />: | |||||
</Typography> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5">  | |||||
{locale === 'en' ? | |||||
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||||
: | |||||
`${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}` | |||||
} | |||||
</Typography> | |||||
</Grid> | |||||
{data.creditor == true ? | |||||
<> | |||||
<Grid item xs={12} md={12} lg={12} | |||||
sx={{ display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5" display="inline"> | |||||
<FormattedMessage id="commentDeadline" />: | |||||
</Typography> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5">  | |||||
{locale === 'en' ? | |||||
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||||
: | |||||
`${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}` | |||||
} | |||||
</Typography> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12} | |||||
sx={{ display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5" display="inline"> | |||||
<FormattedMessage id="paymentDeadline" />: | |||||
</Typography> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5">  | |||||
{locale === 'en' ? | |||||
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||||
: | |||||
`${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}` | |||||
} | |||||
</Typography> | |||||
</Grid> | |||||
</> | |||||
<Grid item xs={12} md={12} lg={12} | |||||
sx={{ display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5" display="inline"> | |||||
<FormattedMessage id="paymentDeadline" />: | |||||
</Typography> | |||||
</Grid> | |||||
<Grid item xs={12} md={12} lg={12} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> | |||||
<Typography variant="h5">  | |||||
{locale === 'en' ? | |||||
`${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||||
: | |||||
`${DateUtils.dateFormat(data?.proofPaymentDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "上午")?.replace("pm", "下午")}${intl.formatMessage({ id: 'before' })}` | |||||
} | |||||
</Typography> | |||||
</Grid> | |||||
</> | |||||
: | : | ||||
<></> | |||||
} | |||||
<></> | |||||
} | |||||
<Grid item xs={12} sm={3} md={3} lg={3} | <Grid item xs={12} sm={3} md={3} lg={3} | ||||
sx={{ mb: 1, display: 'flex', alignItems: 'center' }}> | sx={{ mb: 1, display: 'flex', alignItems: 'center' }}> | ||||
<Typography> | <Typography> | ||||
@@ -28,7 +28,8 @@ import { ThemeProvider } from "@emotion/react"; | |||||
import { FormattedMessage, useIntl } from "react-intl"; | import { FormattedMessage, useIntl } from "react-intl"; | ||||
import { | import { | ||||
isDummyLoggedIn, | isDummyLoggedIn, | ||||
checkIsOnlyOnlinePaymentByIssueDate | |||||
checkIsOnlyOnlinePaymentByIssueDate, | |||||
checkPaymentSuspention | |||||
} from "utils/Utils" | } from "utils/Utils" | ||||
const UploadFileTable = Loadable(React.lazy(() => import('./UploadFileTable'))); | const UploadFileTable = Loadable(React.lazy(() => import('./UploadFileTable'))); | ||||
@@ -320,8 +321,6 @@ const FormPanel = ({ formData }) => { | |||||
<FormControlLabel value={false} control={<Radio />} label={intl.formatMessage({ id: 'proofWithError' })} /> | <FormControlLabel value={false} control={<Radio />} label={intl.formatMessage({ id: 'proofWithError' })} /> | ||||
</RadioGroup> | </RadioGroup> | ||||
</Grid> | </Grid> | ||||
{ | { | ||||
actionValue && formData.creditor == false ? | actionValue && formData.creditor == false ? | ||||
isDummyLoggedIn() ? | isDummyLoggedIn() ? | ||||
@@ -436,6 +435,11 @@ const FormPanel = ({ formData }) => { | |||||
</td> | </td> | ||||
<td style={tabelStyle}> | <td style={tabelStyle}> | ||||
<FormattedMessage id="payOnline" /> | <FormattedMessage id="payOnline" /> | ||||
{checkPaymentSuspention()? | |||||
<Typography style={{ padding: '16px' }}> | |||||
<div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessage" }) }} /> | |||||
</Typography>:null | |||||
} | |||||
<br /><a href="#payOnlineDetails" color='#fff' onClick={() => { | <br /><a href="#payOnlineDetails" color='#fff' onClick={() => { | ||||
setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payOnline" })) | setWarningTitle(intl.formatMessage({ id: "paymentMeans" }) + ": " + intl.formatMessage({ id: "payOnline" })) | ||||
setWarningText( | setWarningText( | ||||
@@ -661,8 +665,6 @@ const FormPanel = ({ formData }) => { | |||||
</Stack> | </Stack> | ||||
</Grid> | </Grid> | ||||
} | } | ||||
<Grid item xs={12} md={12} textAlign="left"> | <Grid item xs={12} md={12} textAlign="left"> | ||||
<ThemeProvider theme={PNSPS_BUTTON_THEME}> | <ThemeProvider theme={PNSPS_BUTTON_THEME}> | ||||
<Button | <Button | ||||
@@ -676,7 +678,6 @@ const FormPanel = ({ formData }) => { | |||||
</Button> | </Button> | ||||
</ThemeProvider> | </ThemeProvider> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
) | ) | ||||
@@ -10,7 +10,7 @@ import { GET_SYS_PARAMS } from "utils/ApiPathConst"; | |||||
// ==============================|| DASHBOARD - DEFAULT ||============================== // | // ==============================|| DASHBOARD - DEFAULT ||============================== // | ||||
const Table = ({onRowClick, searchCriteria}) => { | |||||
const Table = ({onRowClick, searchCriteria, refreshTrigger}) => { | |||||
const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); | const [_searchCriteria, set_searchCriteria] = React.useState(searchCriteria); | ||||
React.useEffect(() => { | React.useEffect(() => { | ||||
@@ -70,7 +70,7 @@ const Table = ({onRowClick, searchCriteria}) => { | |||||
doLoad={React.useMemo(() => ({ | doLoad={React.useMemo(() => ({ | ||||
url:GET_SYS_PARAMS, | url:GET_SYS_PARAMS, | ||||
params:_searchCriteria | params:_searchCriteria | ||||
}), [_searchCriteria])} | |||||
}), [_searchCriteria, refreshTrigger])} | |||||
/> | /> | ||||
{/* </Box> */} | {/* </Box> */} | ||||
</div> | </div> | ||||
@@ -3,11 +3,13 @@ import { | |||||
Grid, | Grid, | ||||
Typography, | Typography, | ||||
Stack, | Stack, | ||||
Button, | |||||
Dialog, DialogTitle, DialogContent, DialogActions, | |||||
// Box, | // Box, | ||||
} from '@mui/material'; | } from '@mui/material'; | ||||
import * as React from "react"; | import * as React from "react"; | ||||
import { GET_SYS_PARAMS } from "utils/ApiPathConst"; | |||||
import { GET_SYS_PARAMS, GET_PAYMENT_SUSPENSION_MODE, UPDATE_PAYMENT_SUSPENSION_MODE } from "utils/ApiPathConst"; | |||||
import Loadable from 'components/Loadable'; | import Loadable from 'components/Loadable'; | ||||
import MainCard from "components/MainCard"; | import MainCard from "components/MainCard"; | ||||
@@ -36,11 +38,24 @@ const SystemSetting = () => { | |||||
const [searchCriteria, setSearchCriteria] = React.useState({}); | const [searchCriteria, setSearchCriteria] = React.useState({}); | ||||
const [selectedItem, setSelectedItem] = React.useState({}); | const [selectedItem, setSelectedItem] = React.useState({}); | ||||
const [reloadTime, setReloadTime] = React.useState(new Date()) | const [reloadTime, setReloadTime] = React.useState(new Date()) | ||||
const [isPopUp, setIsPopUp] = React.useState(false); | |||||
const [refreshTrigger, setRefreshTrigger] = React.useState(0); | |||||
const [suspensionMode, setSuspensionMode] = React.useState(); | |||||
const [onReady, setOnReady] = React.useState(false); | |||||
const forceRefresh = () => { | |||||
setRefreshTrigger(prev => prev + 1); | |||||
}; | |||||
React.useEffect(()=>{ | React.useEffect(()=>{ | ||||
setSearchCriteria({}) | setSearchCriteria({}) | ||||
loadPaymentSuspension() | |||||
}, []); | }, []); | ||||
React.useEffect(() => { | |||||
setOnReady(true); | |||||
}, [suspensionMode]); | |||||
const onRowClick = (param) => { | const onRowClick = (param) => { | ||||
setSelectedItem(param.row); | setSelectedItem(param.row); | ||||
} | } | ||||
@@ -60,6 +75,29 @@ const SystemSetting = () => { | |||||
onSuccess: () => { | onSuccess: () => { | ||||
notifyActionSuccess(); | notifyActionSuccess(); | ||||
setReloadTime(new Date()); | setReloadTime(new Date()); | ||||
// forceRefresh() | |||||
} | |||||
}); | |||||
} | |||||
const loadPaymentSuspension = () => { | |||||
HttpUtils.get({ | |||||
url: GET_PAYMENT_SUSPENSION_MODE, | |||||
onSuccess: (responseData) => { | |||||
setSuspensionMode(responseData) | |||||
} | |||||
}); | |||||
} | |||||
const onPaymentSuspension = () => { | |||||
setIsPopUp(false); | |||||
HttpUtils.post({ | |||||
url: UPDATE_PAYMENT_SUSPENSION_MODE, | |||||
onSuccess: (responseData) => { | |||||
setSuspensionMode(responseData) | |||||
notifyActionSuccess(); | |||||
setReloadTime(new Date()); | |||||
forceRefresh() | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
@@ -90,13 +128,14 @@ const SystemSetting = () => { | |||||
<Table | <Table | ||||
searchCriteria={searchCriteria} | searchCriteria={searchCriteria} | ||||
onRowClick={onRowClick} | onRowClick={onRowClick} | ||||
refreshTrigger={refreshTrigger} | |||||
/> | /> | ||||
</MainCard> | </MainCard> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={12} sm={4} md={4} lg={4}> | <Grid item xs={12} sm={4} md={4} lg={4}> | ||||
<Grid container> | |||||
<Grid container spacing> | |||||
<Grid item xs={12} md={12}> | <Grid item xs={12} md={12}> | ||||
<MainCard elevation={0} | <MainCard elevation={0} | ||||
border={false} | border={false} | ||||
@@ -110,9 +149,48 @@ const SystemSetting = () => { | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={12} sm={4} md={4} lg={4}> | |||||
{onReady? | |||||
<Grid container mb={2}> | |||||
<Grid item xs={12} md={12}> | |||||
<Button | |||||
variant="contained" | |||||
color="red" | |||||
onClick={()=>{ | |||||
setIsPopUp(true); | |||||
}} | |||||
> | |||||
{suspensionMode?"Cancel Payment Suspension Mode":"Enable Payment Suspension Mode"} | |||||
</Button> | |||||
</Grid> | |||||
</Grid>:null | |||||
} | |||||
</Grid> | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
{/*col 2*/} | {/*col 2*/} | ||||
<div> | |||||
<Dialog | |||||
open={isPopUp} | |||||
onClose={() => setIsPopUp(false)} | |||||
PaperProps={{ | |||||
sx: { | |||||
minWidth: '40vw', | |||||
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, | |||||
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } | |||||
} | |||||
}} | |||||
> | |||||
<DialogTitle>Payment Suspension Mode</DialogTitle> | |||||
<DialogContent style={{ display: 'flex', }}> | |||||
<Typography variant="h5" style={{ padding: '16px' }}>{suspensionMode?"Cancel payment suspension mode?":"Enable payment suspension mode?"}</Typography> | |||||
</DialogContent> | |||||
<DialogActions> | |||||
<Button onClick={() => setIsPopUp(false)}><Typography variant="h5">Cancel</Typography></Button> | |||||
<Button onClick={() => onPaymentSuspension()}><Typography variant="h5">Confirm</Typography></Button> | |||||
</DialogActions> | |||||
</Dialog> | |||||
</div> | |||||
</> | </> | ||||
</Grid> | </Grid> | ||||
); | ); | ||||
@@ -2,11 +2,12 @@ import PropTypes from 'prop-types'; | |||||
import { Box, Grid, Typography } from '@mui/material'; | import { Box, Grid, Typography } from '@mui/material'; | ||||
// import { Stack } from '@mui/material'; | // import { Stack } from '@mui/material'; | ||||
import Loadable from 'components/Loadable'; | import Loadable from 'components/Loadable'; | ||||
import { lazy } from 'react'; | |||||
import { lazy, useContext } from 'react'; | |||||
import { FormattedMessage, useIntl } from "react-intl"; | import { FormattedMessage, useIntl } from "react-intl"; | ||||
import { checkSysEnv } from "utils/Utils"; | |||||
import { checkSysEnv, checkPaymentSuspention } from "utils/Utils"; | |||||
import backbroundImg from 'assets/images/bg_ml.jpg'; | import backbroundImg from 'assets/images/bg_ml.jpg'; | ||||
import 'assets/style/loginStyles.css'; | import 'assets/style/loginStyles.css'; | ||||
import { SysContext } from "components/SysSettingProvider" | |||||
const AuthCard = Loadable(lazy(() => import('./AuthCardCustom'))); | const AuthCard = Loadable(lazy(() => import('./AuthCardCustom'))); | ||||
@@ -20,6 +21,7 @@ const BackgroundHead = { | |||||
const AuthWrapper = ({ children }) => { | const AuthWrapper = ({ children }) => { | ||||
// Move useIntl inside component | // Move useIntl inside component | ||||
const intl = useIntl(); | const intl = useIntl(); | ||||
const { sysSetting } = useContext(SysContext); | |||||
return ( | return ( | ||||
<Box sx={{ minHeight: '87vh' }}> | <Box sx={{ minHeight: '87vh' }}> | ||||
@@ -41,9 +43,15 @@ const AuthWrapper = ({ children }) => { | |||||
sx={{ minHeight: { md: 'calc(87vh)' } }} | sx={{ minHeight: { md: 'calc(87vh)' } }} | ||||
> | > | ||||
<Grid item xs={12} sx={{ ml: 4,}}> | <Grid item xs={12} sx={{ ml: 4,}}> | ||||
{checkPaymentSuspention()? | |||||
<Typography style={{ textAlign: "flex-start" }}> | |||||
<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessage" }) }} /> | |||||
</Typography> | |||||
: | |||||
<Typography style={{ textAlign: "flex-start" }}> | <Typography style={{ textAlign: "flex-start" }}> | ||||
<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "homePageHeaderMessage" }) }} /> | <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "homePageHeaderMessage" }) }} /> | ||||
</Typography> | </Typography> | ||||
} | |||||
</Grid> | </Grid> | ||||
<Grid container direction="column" | <Grid container direction="column" | ||||
justifyContent="flex-start" | justifyContent="flex-start" | ||||
@@ -73,18 +81,20 @@ const AuthWrapper = ({ children }) => { | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
<Grid item xs={12} md={4} lg={4} xl={4}> | |||||
<Grid | |||||
container | |||||
justifyContent="center" | |||||
alignItems="center" | |||||
sx={{ minHeight: { xs: 'calc(90vh - 134px)', md: 'calc(90vh - 112px)' }, }} | |||||
> | |||||
<Grid item xs={12} md={11} lg={11} xl={11}> | |||||
<AuthCard>{children}</AuthCard> | |||||
{sysSetting?.publicLogin? | |||||
<Grid item xs={12} md={4} lg={4} xl={4}> | |||||
<Grid | |||||
container | |||||
justifyContent="center" | |||||
alignItems="center" | |||||
sx={{ minHeight: { xs: 'calc(90vh - 134px)', md: 'calc(90vh - 112px)' }, }} | |||||
> | |||||
<Grid item xs={12} md={11} lg={11} xl={11}> | |||||
<AuthCard>{children}</AuthCard> | |||||
</Grid> | |||||
</Grid> | </Grid> | ||||
</Grid> | |||||
</Grid> | |||||
</Grid>:null | |||||
} | |||||
</Grid> | </Grid> | ||||
</div> | </div> | ||||
</Box> | </Box> | ||||
@@ -6,7 +6,8 @@ import { | |||||
Typography, | Typography, | ||||
Stack, | Stack, | ||||
Button, | Button, | ||||
Box | |||||
Box, | |||||
Dialog, DialogTitle, DialogContent, DialogActions, | |||||
} from '@mui/material'; | } from '@mui/material'; | ||||
import { isORGLoggedIn, } from "utils/Utils"; | import { isORGLoggedIn, } from "utils/Utils"; | ||||
import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | ||||
@@ -17,6 +18,7 @@ import Loadable from 'components/Loadable'; | |||||
import * as HttpUtils from "utils/HttpUtils"; | import * as HttpUtils from "utils/HttpUtils"; | ||||
import * as UrlUtils from "utils/ApiPathConst"; | import * as UrlUtils from "utils/ApiPathConst"; | ||||
import * as DateUtils from "utils/DateUtils"; | import * as DateUtils from "utils/DateUtils"; | ||||
import { checkPaymentSuspention } from "utils/Utils"; | |||||
const Message = Loadable(React.lazy(() => import('./Message'))); | const Message = Loadable(React.lazy(() => import('./Message'))); | ||||
const Notice = Loadable(React.lazy(() => import('./Notice'))); | const Notice = Loadable(React.lazy(() => import('./Notice'))); | ||||
@@ -49,10 +51,13 @@ const DashboardDefault = () => { | |||||
const [isLoading, setLoding] = useState(true); | const [isLoading, setLoding] = useState(true); | ||||
const [itemList, setItemList] = React.useState([]); | const [itemList, setItemList] = React.useState([]); | ||||
const [listData, setListData] = React.useState([]); | const [listData, setListData] = React.useState([]); | ||||
const [paymentSuspention, setPaymentSuspention] = useState(false); | |||||
const [isPopUp, setIsPopUp] = React.useState(false); | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
loadMessageData() | loadMessageData() | ||||
loadNoticeData() | loadNoticeData() | ||||
checkPaymentSuspention()?setPaymentSuspention(true):setPaymentSuspention(false) | |||||
localStorage.setItem('searchCriteria',"") | localStorage.setItem('searchCriteria',"") | ||||
}, []); | }, []); | ||||
@@ -70,6 +75,14 @@ const DashboardDefault = () => { | |||||
} | } | ||||
} | } | ||||
React.useEffect(() => { | |||||
// console.log(messageOnReady) | |||||
// console.log(onNoticeReady) | |||||
if(paymentSuspention){ | |||||
setIsPopUp(true); | |||||
} | |||||
}, [paymentSuspention]); | |||||
React.useEffect(() => { | React.useEffect(() => { | ||||
// console.log(messageOnReady) | // console.log(messageOnReady) | ||||
// console.log(onNoticeReady) | // console.log(onNoticeReady) | ||||
@@ -214,6 +227,33 @@ const DashboardDefault = () => { | |||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
</Grid> | </Grid> | ||||
<div> | |||||
<Dialog | |||||
open={isPopUp} | |||||
onClose={() => setIsPopUp(false)} | |||||
PaperProps={{ | |||||
sx: { | |||||
minWidth: '40vw', | |||||
maxWidth: { xs: '90vw', s: '90vw', m: '70vw', lg: '70vw' }, | |||||
maxHeight: { xs: '90vh', s: '70vh', m: '70vh', lg: '60vh' } | |||||
} | |||||
}} | |||||
> | |||||
<DialogTitle> | |||||
<Typography variant="h5"> | |||||
<FormattedMessage id="systemNotice" /> | |||||
</Typography> | |||||
</DialogTitle> | |||||
<DialogContent style={{ display: 'flex', }}> | |||||
<Typography variant="h5" style={{ padding: '16px' }}> | |||||
<div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessage" }) }} /> | |||||
</Typography> | |||||
</DialogContent> | |||||
<DialogActions> | |||||
<Button onClick={() => setIsPopUp(false)}><Typography variant="h5"><FormattedMessage id="ok" /></Typography></Button> | |||||
</DialogActions> | |||||
</Dialog> | |||||
</div> | |||||
</Grid> | </Grid> | ||||
); | ); | ||||
}; | }; | ||||
@@ -21,6 +21,7 @@ | |||||
"gazetteLength": "Length", | "gazetteLength": "Length", | ||||
"gazetteSampleName": "Gazette Supplement No. 6", | "gazetteSampleName": "Gazette Supplement No. 6", | ||||
"reason": "Reason", | "reason": "Reason", | ||||
"systemNotice": "System Notice", | |||||
"payInstantly": "Pay now", | "payInstantly": "Pay now", | ||||
"payLater": "Pay later", | "payLater": "Pay later", | ||||
@@ -21,6 +21,7 @@ | |||||
"gazetteLength": "长度", | "gazetteLength": "长度", | ||||
"gazetteSampleName": "宪报第6号副刊公共启事", | "gazetteSampleName": "宪报第6号副刊公共启事", | ||||
"reason": "原因", | "reason": "原因", | ||||
"systemNotice": "系统公告", | |||||
"payInstantly": "即时付款", | "payInstantly": "即时付款", | ||||
"payLater": "稍后付款", | "payLater": "稍后付款", | ||||
@@ -21,6 +21,7 @@ | |||||
"gazetteLength": "長度", | "gazetteLength": "長度", | ||||
"gazetteSampleName": "憲報第6號副刊公共啟事", | "gazetteSampleName": "憲報第6號副刊公共啟事", | ||||
"reason": "原因", | "reason": "原因", | ||||
"systemNotice": "系統公告", | |||||
"payInstantly": "即時付款", | "payInstantly": "即時付款", | ||||
"payLater": "稍後付款", | "payLater": "稍後付款", | ||||
@@ -9,6 +9,8 @@ export const CHANGE_PASSWORD_PATH = "/user/change-password" | |||||
export const GET_SYS_PARAMS = apiPath+'/settings'; | export const GET_SYS_PARAMS = apiPath+'/settings'; | ||||
export const PRIVACY_POLICY_PATH = apiPath+'/privacyPolicy'; | export const PRIVACY_POLICY_PATH = apiPath+'/privacyPolicy'; | ||||
export const UPDATE_PAYMENT_SUSPENSION_MODE = apiPath+'/settings/update-payment-suspension'; | |||||
export const GET_PAYMENT_SUSPENSION_MODE = apiPath+'/settings/get-payment-suspension'; | |||||
export const I_AM_SMART_PATH = apiPath+'/smart/call/iAmSmart'; | export const I_AM_SMART_PATH = apiPath+'/smart/call/iAmSmart'; | ||||
export const I_AM_SMART_APP_PATH = apiPath+'/smart/call/app/iAmSmart'; | export const I_AM_SMART_APP_PATH = apiPath+'/smart/call/app/iAmSmart'; | ||||
@@ -111,6 +111,12 @@ export const checkSysEnv = () =>{ | |||||
return localStorage.getItem('sysEnv') | return localStorage.getItem('sysEnv') | ||||
} | } | ||||
} | } | ||||
export const checkPaymentSuspention = () =>{ | |||||
if (localStorage.getItem('paymentSuspention') != null){ | |||||
// console.log(localStorage.getItem('sysEnv')) | |||||
return localStorage.getItem('paymentSuspention') | |||||
} | |||||
} | |||||
/** | /** | ||||
** This function is used for demo purpose route navigation | ** This function is used for demo purpose route navigation | ||||
** In real app you won't need this function because your app will navigate to same route for each users regardless of ability | ** In real app you won't need this function because your app will navigate to same route for each users regardless of ability | ||||