| @@ -9,10 +9,20 @@ import useJwt from 'auth/jwt/coreUseJwt'; | |||||
| export const hostname = 'localhost'; | export const hostname = 'localhost'; | ||||
| const hostPort = '8090'; | const hostPort = '8090'; | ||||
| export const hostPath = `http://${hostname}:${hostPort}`; | export const hostPath = `http://${hostname}:${hostPort}`; | ||||
| //export const apiPath = `http://192.168.0.112:8090/api`; | |||||
| export const apiPath = window.location.href.match("localhost:3000")?`${hostPath}/api`:(window.location.href.match(":3000")? "http://"+window.location.hostname+":8090/api":`/api`); | export const apiPath = window.location.href.match("localhost:3000")?`${hostPath}/api`:(window.location.href.match(":3000")? "http://"+window.location.hostname+":8090/api":`/api`); | ||||
| export const paymentPath = window.location.href.match("localhost:3000")?`${hostPath}/payment`:`/payment`; | export const paymentPath = window.location.href.match("localhost:3000")?`${hostPath}/payment`:`/payment`; | ||||
| /** | |||||
| * Testing: | |||||
| * Domain: apigw-isit.staging-eid.gov.hk | |||||
| * URL: hk.gov.iamsmart.testapp:// | |||||
| * | |||||
| * Production | |||||
| * Domain: apigw.iamsmart.gov.hk | |||||
| * URL: hk.gov.iamsmart:// | |||||
| */ | |||||
| export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; | export const iAmSmartPath = `https://apigw-isit.staging-eid.gov.hk`; | ||||
| export const iAmSmartAppPath = `hk.gov.iamsmart.testapp://`; | |||||
| export const clientId = "cf61fa7c121e4869966f69c8694b1cd2"; | export const clientId = "cf61fa7c121e4869966f69c8694b1cd2"; | ||||
| export const iAmSmartCallbackPath = () => { | export const iAmSmartCallbackPath = () => { | ||||
| @@ -3,7 +3,8 @@ import { | |||||
| Grid, | Grid, | ||||
| Typography, | Typography, | ||||
| Stack, | Stack, | ||||
| Box | |||||
| Box, | |||||
| Button | |||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import * as UrlUtils from "utils/ApiPathConst"; | import * as UrlUtils from "utils/ApiPathConst"; | ||||
| import * as React from "react"; | import * as React from "react"; | ||||
| @@ -36,15 +37,24 @@ const Index = () => { | |||||
| const [record, setRecord] = React.useState(); | const [record, setRecord] = React.useState(); | ||||
| const [itemList, setItemList] = React.useState([]); | const [itemList, setItemList] = React.useState([]); | ||||
| const [onReady, setOnReady] = React.useState(false); | const [onReady, setOnReady] = React.useState(false); | ||||
| const [detailsOrder, setDetailsOrder] = React.useState(2); | |||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| loadForm(); | loadForm(); | ||||
| window.addEventListener('resize', handleResize); | |||||
| }, []); | }, []); | ||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| setOnReady(true); | setOnReady(true); | ||||
| }, [record]); | }, [record]); | ||||
| const handleResize = () => { | |||||
| setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); | |||||
| } | |||||
| const doPrint = () => { | |||||
| window.print(); | |||||
| }; | |||||
| const loadForm = () => { | const loadForm = () => { | ||||
| if (params.id > 0) { | if (params.id > 0) { | ||||
| @@ -69,41 +79,48 @@ const Index = () => { | |||||
| <LoadingComponent /> | <LoadingComponent /> | ||||
| : | : | ||||
| ( | ( | ||||
| <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | |||||
| <Grid item xs={12} width="100%"> | |||||
| <div style={BackgroundHead} width="100%"> | |||||
| <Stack direction="row" height='70px'> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>Payment Details</Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| {/*row 1*/} | |||||
| <Grid item xs={12} md={12} sx={{ textAlign: "center" }}> | |||||
| <Grid container justifyContent="center" spacing={2} sx={{ p: 2 }} alignitems="stretch" > | |||||
| <Grid item xs={12} md={5} sx={{ pt: 1, pb: 2 }} style={{ height: '100%' }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <DataGrid | |||||
| recordList={itemList} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid item xs={12} md={5} sx={{ pt: 2 }} style={{ height: '100%' }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <PaymentDetails | |||||
| formData={record} | |||||
| style={{ | |||||
| display: "flex", | |||||
| height: "100%", | |||||
| flex: 1 | |||||
| }} | |||||
| /> | |||||
| </Box> | |||||
| <div> | |||||
| <style> | |||||
| {`@media print {.printHidden{display: none;} .printOrder{order:-1 !important;}`} | |||||
| </style> | |||||
| <Grid container className="printheight" sx={{ minHeight: '80%', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | |||||
| <Grid className="printHidden" item xs={12} width="100%"> | |||||
| <div style={BackgroundHead} width="100%"> | |||||
| <Stack direction="row" height='70px'> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>Payment Details</Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| {/*row 1*/} | |||||
| <Grid item xs={12} md={12} sx={{textAlign: "center" }}> | |||||
| <Button className="printHidden" variant="outlined" sx={{mt:2}} onClick={doPrint}> | |||||
| <Typography variant="h5">Print</Typography> | |||||
| </Button> | |||||
| <Grid container justifyContent="center" spacing={2} sx={{ p: 2 }} alignitems="stretch" > | |||||
| <Grid item xs={12} md={5} sx={{ pt: 1, pb: 2 }} style={{ height: '100%', order: 1 }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <DataGrid | |||||
| recordList={itemList} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid className="printOrder" item xs={12} md={5} sx={{ pt: 2 }} style={{ height: '100%', order: detailsOrder }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <PaymentDetails | |||||
| formData={record} | |||||
| style={{ | |||||
| display: "flex", | |||||
| height: "100%", | |||||
| flex: 1 | |||||
| }} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | |||||
| {/*row 2*/} | |||||
| </Grid > | |||||
| {/*row 2*/} | |||||
| </Grid > | |||||
| </div> | |||||
| ) | ) | ||||
| @@ -3,7 +3,8 @@ import { | |||||
| Grid, | Grid, | ||||
| Typography, | Typography, | ||||
| Stack, | Stack, | ||||
| Box | |||||
| Box, | |||||
| Button | |||||
| } from '@mui/material'; | } from '@mui/material'; | ||||
| import * as UrlUtils from "utils/ApiPathConst"; | import * as UrlUtils from "utils/ApiPathConst"; | ||||
| import * as React from "react"; | import * as React from "react"; | ||||
| @@ -36,15 +37,26 @@ const Index = () => { | |||||
| const [record, setRecord] = React.useState(); | const [record, setRecord] = React.useState(); | ||||
| const [itemList, setItemList] = React.useState([]); | const [itemList, setItemList] = React.useState([]); | ||||
| const [onReady, setOnReady] = React.useState(false); | const [onReady, setOnReady] = React.useState(false); | ||||
| const [detailsOrder, setDetailsOrder] = React.useState(2); | |||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| loadForm(); | loadForm(); | ||||
| window.addEventListener('resize', handleResize) | |||||
| }, []); | }, []); | ||||
| React.useEffect(() => { | React.useEffect(() => { | ||||
| setOnReady(true); | setOnReady(true); | ||||
| }, [record]); | }, [record]); | ||||
| const handleResize = () => { | |||||
| setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); | |||||
| } | |||||
| const doPrint = () => { | |||||
| window.print(); | |||||
| }; | |||||
| const loadForm = () => { | const loadForm = () => { | ||||
| if (params.id > 0) { | if (params.id > 0) { | ||||
| @@ -69,41 +81,49 @@ const Index = () => { | |||||
| <LoadingComponent /> | <LoadingComponent /> | ||||
| : | : | ||||
| ( | ( | ||||
| <Grid container sx={{ minHeight: '110vh', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | |||||
| <Grid item xs={12} width="100%"> | |||||
| <div style={BackgroundHead} width="100%"> | |||||
| <Stack direction="row" height='70px'> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>付款詳情</Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| {/*row 1*/} | |||||
| <Grid item xs={12} md={12} sx={{ textAlign: "center" }}> | |||||
| <Grid container justifyContent="center" spacing={2} sx={{ p: 2 }} alignitems="stretch" > | |||||
| <Grid item xs={12} md={5} sx={{ pt: 1, pb: 2 }} style={{ height: '100%' }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <DataGrid | |||||
| recordList={itemList} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid item xs={12} md={5} sx={{ pt: 2 }} style={{ height: '100%' }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <PaymentDetails | |||||
| formData={record} | |||||
| style={{ | |||||
| display: "flex", | |||||
| height: "100%", | |||||
| flex: 1 | |||||
| }} | |||||
| /> | |||||
| </Box> | |||||
| <div> | |||||
| <style> | |||||
| {`@media print {.printHidden{display: none;} .printOrder{order:-1 !important;}`} | |||||
| </style> | |||||
| <Grid container className="printheight" sx={{ minHeight: '80%', backgroundColor: '#fff' }} direction="column" justifyContent="flex-start" alignItems="center" > | |||||
| <Grid className="printHidden" item xs={12} width="100%"> | |||||
| <div style={BackgroundHead} width="100%"> | |||||
| <Stack direction="row" height='70px'> | |||||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ pt: 2 }}>付款詳情</Typography> | |||||
| </Stack> | |||||
| </div> | |||||
| </Grid> | |||||
| {/*row 1*/} | |||||
| <Grid item xs={12} md={12} spacing={2} sx={{ textAlign: "center" }}> | |||||
| <Button className="printHidden" variant="outlined" sx={{ mt:2 }} onClick={doPrint}> | |||||
| <Typography variant="h5">Print</Typography> | |||||
| </Button> | |||||
| <Grid container justifyContent="center" spacing={2} sx={{ p: 2 }} alignitems="stretch" > | |||||
| <Grid item xs={12} md={5} sx={{ pt: 1, pb: 2 }} style={{ height: '100%', order: 1 }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <DataGrid | |||||
| recordList={itemList} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| <Grid item className="printOrder" xs={12} md={5} sx={{ pt: 2 }} style={{ height: '100%', order: detailsOrder }}> | |||||
| <Box xs={12} md={12} sx={{ p: 4, border: '3px solid #eee', borderRadius: '10px' }} > | |||||
| <PaymentDetails | |||||
| formData={record} | |||||
| style={{ | |||||
| display: "flex", | |||||
| height: "100%", | |||||
| flex: 1 | |||||
| }} | |||||
| /> | |||||
| </Box> | |||||
| </Grid> | |||||
| </Grid> | </Grid> | ||||
| </Grid> | </Grid> | ||||
| </Grid> | |||||
| {/*row 2*/} | |||||
| </Grid > | |||||
| {/*row 2*/} | |||||
| </Grid > | |||||
| </div> | |||||
| ) | ) | ||||
| @@ -9,7 +9,7 @@ import Typography from '@mui/material/Typography'; | |||||
| import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; | import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; | ||||
| import banner from 'assets/images/bg_ml.jpg'; | import banner from 'assets/images/bg_ml.jpg'; | ||||
| import { Stack } from '../../../node_modules/@mui/material/index'; | import { Stack } from '../../../node_modules/@mui/material/index'; | ||||
| import { iAmSmartPath, clientId, getBowserType , iAmSmartCallbackPath} from 'auth/utils' | |||||
| import { iAmSmartPath, iAmSmartAppPath, clientId, getBowserType, isAppBowser, iAmSmartCallbackPath} from 'auth/utils' | |||||
| import * as React from 'react'; | import * as React from 'react'; | ||||
| @@ -25,6 +25,14 @@ const RegisterCustom = () => { | |||||
| } | } | ||||
| const getQRWithIAmSmart = () => { | const getQRWithIAmSmart = () => { | ||||
| if ((isAppBowser())) { | |||||
| openApp(); | |||||
| } else { | |||||
| openQR(); | |||||
| } | |||||
| } | |||||
| const openQR =()=>{ | |||||
| let callbackUrl = "https://"+iAmSmartCallbackPath()+"/iamsmart/registrycallback"; | let callbackUrl = "https://"+iAmSmartCallbackPath()+"/iamsmart/registrycallback"; | ||||
| let url = iAmSmartPath + "/api/v1/auth/getQR" | let url = iAmSmartPath + "/api/v1/auth/getQR" | ||||
| + "?clientID=" + clientId | + "?clientID=" + clientId | ||||
| @@ -38,6 +46,22 @@ const RegisterCustom = () => { | |||||
| window.location.assign(url); | window.location.assign(url); | ||||
| } | } | ||||
| const openApp = () => { | |||||
| setTimeout(function () { | |||||
| openQR(); | |||||
| }, 1000); | |||||
| let callbackUrl = "https://" + iAmSmartCallbackPath() + "/iamsmart/registrycallback"; | |||||
| let url = iAmSmartAppPath + "auth" | |||||
| + "?clientID=" + clientId | |||||
| + "&responseType=code" | |||||
| + "&source=" + getBowserType() | |||||
| + "&redirectURI=" + encodeURIComponent(callbackUrl) | |||||
| + "&scope=" + encodeURIComponent("eidapi_auth eidapi_profiles") | |||||
| + "&lang=zh-HK"//en-US, zh-HK, or zh-CN | |||||
| //+"&state=" | |||||
| + "&brokerPage=false" | |||||
| window.location=url; | |||||
| } | |||||
| return ( | return ( | ||||
| <Stack justifyContent="center" sx={{ minHeight: '100vh', bgcolor: 'backgroundColor.default' }}> | <Stack justifyContent="center" sx={{ minHeight: '100vh', bgcolor: 'backgroundColor.default' }}> | ||||
| @@ -66,7 +90,7 @@ const RegisterCustom = () => { | |||||
| <Grid container > | <Grid container > | ||||
| <Grid item xs={12} md={6} sx={{ borderRight: 1, borderColor: 'grey.500' }}> | <Grid item xs={12} md={6} sx={{ borderRight: 1, borderColor: 'grey.500' }}> | ||||
| <Typography mb={4} variant="h3">個人用戶</Typography> | <Typography mb={4} variant="h3">個人用戶</Typography> | ||||
| <Button variant="outlined" onClick={registerWithIAmSmart} startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}><Typography variant="h5">以「智方便」繼續</Typography></Button> | |||||
| <Button variant="outlined" color="iAmSmart" onClick={registerWithIAmSmart} startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}><Typography variant="h5">以「智方便」繼續</Typography></Button> | |||||
| <Box mt={4} ml={2} mr={2} bgcolor="grey.100" p={1.5} > | <Box mt={4} ml={2} mr={2} bgcolor="grey.100" p={1.5} > | ||||
| <Typography textAlign='justify' variant="body1" display="block" gutterBottom> | <Typography textAlign='justify' variant="body1" display="block" gutterBottom> | ||||
| @@ -6,7 +6,7 @@ import React, { | |||||
| import { Link as RouterLink } from 'react-router-dom'; | import { Link as RouterLink } from 'react-router-dom'; | ||||
| import { useNavigate } from 'react-router-dom'; | import { useNavigate } from 'react-router-dom'; | ||||
| import { useForm, } from 'react-hook-form' | import { useForm, } from 'react-hook-form' | ||||
| import { iAmSmartPath, clientId, getBowserType, isAppBowser, iAmSmartCallbackPath } from 'auth/utils' | |||||
| import { iAmSmartPath, iAmSmartAppPath, clientId, getBowserType, isAppBowser, iAmSmartCallbackPath } from 'auth/utils' | |||||
| // material-ui | // material-ui | ||||
| import { | import { | ||||
| @@ -195,7 +195,7 @@ const AuthLoginCustom = () => { | |||||
| openQR(); | openQR(); | ||||
| }, 1000); | }, 1000); | ||||
| let callbackUrl = "https://" + iAmSmartCallbackPath() + "/iamsmart/authcallback"; | let callbackUrl = "https://" + iAmSmartCallbackPath() + "/iamsmart/authcallback"; | ||||
| let url = "hk.gov.iamsmart.testapp://" + "auth" | |||||
| let url = iAmSmartAppPath + "auth" | |||||
| + "?clientID=" + clientId | + "?clientID=" + clientId | ||||
| + "&responseType=code" | + "&responseType=code" | ||||
| + "&source=" + getBowserType() | + "&source=" + getBowserType() | ||||
| @@ -55,10 +55,10 @@ const Index = () => { | |||||
| }, | }, | ||||
| onFail: ()=>{ | onFail: ()=>{ | ||||
| window.location.assign("/iamsmart/loginFall"); | |||||
| window.location.assign("/login"); | |||||
| }, | }, | ||||
| onError:()=>{ | onError:()=>{ | ||||
| window.location.assign("/iamsmart/loginFall"); | |||||
| window.location.assign("/login"); | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -55,10 +55,10 @@ const Index = () => { | |||||
| }, | }, | ||||
| onFail: ()=>{ | onFail: ()=>{ | ||||
| window.location.assign("/iamsmart/loginFall"); | |||||
| window.location.assign("/login"); | |||||
| }, | }, | ||||
| onError:()=>{ | onError:()=>{ | ||||
| window.location.assign("/iamsmart/loginFall"); | |||||
| window.location.assign("/login"); | |||||
| } | } | ||||
| }); | }); | ||||
| } | } | ||||