| @@ -74,62 +74,62 @@ function Header(props) { | |||
| isGLDLoggedIn() ? | |||
| <div id="adminContent"> | |||
| <li> | |||
| <Link className="dashboard" to='/dashboard'>Dashboard</Link> | |||
| <Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>Dashboard</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="application" to='/application/search'>Application</Link> | |||
| <Link className="application" to='/application/search'><Typography variant={"headerTitle1"} sx={{ml:2}}>Application</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="proof" to='/proof/search'>Proof</Link> | |||
| <Link className="proof" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ml:2}}>Proof</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="payment" to='/dashboard'>Payment</Link> | |||
| <Link className="payment" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>Payment</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="client" >Client<KeyboardArrowDownIcon /></Link> | |||
| <Link className="client" ><Typography variant={"headerTitle1"} sx={{ml:2}}>Client</Typography><KeyboardArrowDownIcon /></Link> | |||
| <ul className='dropdown'> | |||
| <li> | |||
| <Link className="userSearchview" to='/userSearchview'>Users (GLD)</Link> | |||
| <Link className="userSearchview" to='/userSearchview'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (GLD)</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="indUser" to='/indUser'>Users (Individual)</Link> | |||
| <Link className="indUser" to='/indUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (Individual)</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="orgUser" to='/orgUser'>Users (Organization)</Link> | |||
| <Link className="orgUser" to='/orgUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>Users (Organization)</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="org" to='/org'>Organization</Link> | |||
| <Link className="org" to='/org'><Typography variant={"headerTitle1"} sx={{ml:2}}>Organization</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="usergroupSearchview" to='/usergroupSearchview'>User Group</Link> | |||
| <Link className="usergroupSearchview" to='/usergroupSearchview'><Typography variant={"headerTitle1"} sx={{ml:2}}>User Group</Typography></Link> | |||
| </li> | |||
| </ul> | |||
| </li> | |||
| <li> | |||
| <Link className="logout" onClick={handleLogout}>Logout</Link> | |||
| <Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ml:2}}>Logout</Typography></Link> | |||
| </li> | |||
| </div> | |||
| : | |||
| <div id="individualUserContent"> | |||
| <li> | |||
| <Link className="dashboard" to='/dashboard'>主頁</Link> | |||
| <Link className="dashboard" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>主頁</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="myDocumet" to='/publicNotice'>我的公共啟事</Link> | |||
| <Link className="myDocumet" to='/publicNotice'><Typography variant={"headerTitle1"} sx={{ml:2}}>我的公共啟事</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="documentRecord" to='/proof/search'>校對記錄</Link> | |||
| <Link className="documentRecord" to='/proof/search'><Typography variant={"headerTitle1"} sx={{ml:2}}>校對記錄</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="paymentRecord" to='/dashboard'>付款記錄</Link> | |||
| <Link className="paymentRecord" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>付款記錄</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="userSetting" to='/dashboard'>設定<KeyboardArrowDownIcon /></Link> | |||
| <Link className="userSetting" to='/dashboard'><Typography variant={"headerTitle1"} sx={{ml:2}}>設定</Typography><KeyboardArrowDownIcon /></Link> | |||
| {isPrimaryLoggedIn() ? | |||
| <ul className='dropdown'> | |||
| <li> | |||
| <Link className="manageOrgUser" to='setting/manageUser'>公司/機構用戶記錄</Link> | |||
| <Link className="manageOrgUser" to='setting/manageUser'><Typography variant={"headerTitle1"} sx={{ml:2}}>公司/機構用戶記錄</Typography></Link> | |||
| </li> | |||
| </ul> | |||
| : | |||
| @@ -137,7 +137,7 @@ function Header(props) { | |||
| } | |||
| </li> | |||
| <li> | |||
| <Link className="logout" onClick={handleLogout}>登出</Link> | |||
| <Link className="logout" onClick={handleLogout}><Typography variant={"headerTitle1"} sx={{ml:2}}>登出</Typography></Link> | |||
| </li> | |||
| </div> | |||
| ); | |||
| @@ -145,10 +145,10 @@ function Header(props) { | |||
| const logoutContent = ( | |||
| <div> | |||
| <li> | |||
| <Link className="login" to='/login'>登入</Link> | |||
| <Link className="login" to='/login'><Typography variant={"headerTitle1"} sx={{ml:2}}>登入</Typography></Link> | |||
| </li> | |||
| <li> | |||
| <Link className="register" to='/register'>申請</Link> | |||
| <Link className="register" to='/register'><Typography variant={"headerTitle1"} sx={{ml:2}}>申請</Typography></Link> | |||
| </li> | |||
| </div> | |||
| ); | |||
| @@ -64,9 +64,9 @@ const Index = () => { | |||
| }, [paymentData]); | |||
| const loadForm = () => { | |||
| const timeoutdatetime = "2023-10-26T09:04:30Z[UTC]" | |||
| const convertedDateString = timeoutdatetime.replace("[UTC]", ""); | |||
| setFpsmerchanttimeoutdatetime(convertedDateString) | |||
| // const timeoutdatetime = "2023-10-26T09:04:30Z[UTC]" | |||
| // const convertedDateString = timeoutdatetime.replace("[UTC]", ""); | |||
| // setFpsmerchanttimeoutdatetime(convertedDateString) | |||
| HttpUtils.post({ | |||
| url: paymentPath+loadPaymentUrl+(paymentData.type=="PPS"?"pps":"creditcard"), | |||
| @@ -40,6 +40,7 @@ const Index = () => { | |||
| const [responeData, setResponeDataData] = React.useState({}); | |||
| const [fpsTransctionData, setFpsTransctionData] = React.useState({}); | |||
| const [fpsmerchanttimeoutdatetime, setFpsmerchanttimeoutdatetime] = React.useState(""); | |||
| const [timeDownCount, setTimeDownCount] = React.useState(0); | |||
| // const [fpsqrcodeurl, setFpsqrcodeurl] = React.useState(""); | |||
| // const pasgPath = 'https://fps.payapps.hkicl.com.hk'; //PRD | |||
| @@ -185,6 +186,8 @@ const Index = () => { | |||
| console.log(time) | |||
| console.log(timeOutDate) | |||
| console.log(currentTime) | |||
| console.log(timeOutDate.getTime()-currentTime.getTime()) | |||
| setTimeDownCount(timeOutDate.getTime()-currentTime.getTime()) | |||
| getPaymentStatus(); | |||
| if (timeOutDate.getTime()<currentTime.getTime()){ | |||
| console.log("stop"); | |||
| @@ -239,9 +242,11 @@ const Index = () => { | |||
| <br /> | |||
| <img src={fpsTransctionData.fpsqrcodeimgbase64} alt="QR Code"/> | |||
| <br /> | |||
| 二維碼有效期限10分鐘 | |||
| 二維碼有效期限3分鐘 | |||
| <br /> | |||
| 請在規定時間內完成付款流程 | |||
| <br /> | |||
| {"剩餘時間:"+timeDownCount} | |||
| </Typography> | |||
| <Typography variant="h3" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | |||
| @@ -33,27 +33,44 @@ const MultiPaymentWindow = (props) => { | |||
| const windowTitle = "請選擇付款方式"; | |||
| const [content, setContent] = useState(); | |||
| const [loadtTransactionData, setLoadtTransactionData] = useState({}); | |||
| const [loadAvailableMethodData, setLoadAvailableMethodData] = useState([]); | |||
| const [paymentMethod, setPaymentMethod] = useState(""); | |||
| const [transactionData, setTransactionData] = useState([]); | |||
| const [transactionData, setTransactionData] = useState({}); | |||
| const [availableMethodData, setAvailableMethodData] = useState([]); | |||
| const [onReady, setOnReady] = useState(false); | |||
| useEffect(() => { | |||
| console.log(props.availableMethods) | |||
| console.log(props.transactionData) | |||
| if(props.availableMethods.length > 0){ | |||
| setAvailableMethodData(props.availableMethods) | |||
| setTransactionData(props.transactionData) | |||
| if(Object.keys(props.transactionData).length > 0){ | |||
| setLoadtTransactionData(props.transactionData) | |||
| } | |||
| }, [props.transactionData]); | |||
| useEffect(() => { | |||
| console.log(availableMethodData) | |||
| console.log(transactionData) | |||
| if(availableMethodData.length > 0){ | |||
| console.log(props.availableMethods) | |||
| if(props.availableMethods.length > 0){ | |||
| setLoadAvailableMethodData(props.availableMethods) | |||
| } | |||
| }, [props.availableMethods]); | |||
| useEffect(() => { | |||
| if(loadAvailableMethodData.length > 0){ | |||
| setAvailableMethodData(loadAvailableMethodData) | |||
| } | |||
| }, [loadAvailableMethodData]); | |||
| useEffect(() => { | |||
| if(Object.keys(loadtTransactionData).length > 0){ | |||
| setTransactionData(loadtTransactionData) | |||
| } | |||
| }, [loadtTransactionData]); | |||
| useEffect(() => { | |||
| if(availableMethodData.length > 0 && Object.keys(transactionData).length > 0){ | |||
| setOnReady(true) | |||
| } | |||
| }, [availableMethodData]); | |||
| }, [availableMethodData,transactionData]); | |||
| useEffect(() => { | |||
| console.log(paymentMethod) | |||
| @@ -44,8 +44,8 @@ const AuthWrapper = ({ children }) => ( | |||
| alignItems="center" | |||
| spacing={2}> | |||
| <Grid item xs={12} md={8} lg={8} xl={9} sx={{ ml: 4, mt: 3 ,display: { xs: 'none', sm: 'block' }}}> | |||
| <Typography style={{textAlign: "center",fontFamily: "微軟正黑體",fontSize: "1.6rem"}}>香港特別行政區政府</Typography> | |||
| <Typography style={{textAlign: "center",fontFamily: "微軟正黑體",fontSize: "1.6rem",fontWeight:"bold"}}>憲報</Typography> | |||
| <Typography style={{textAlign: "center",fontFamily: "微軟正黑體",fontSize: "1.8rem"}}>香港特別行政區政府</Typography> | |||
| <Typography style={{textAlign: "center",fontFamily: "微軟正黑體",fontSize: "1.8rem",fontWeight:"bold"}}>憲報</Typography> | |||
| </Grid> | |||
| <Grid | |||
| item | |||
| @@ -1,183 +1,185 @@ | |||
| // import { Link } from 'react-router-dom'; | |||
| import React,{useState} from 'react'; | |||
| // material-ui | |||
| import { | |||
| Stepper, | |||
| Step, | |||
| StepButton, | |||
| // Grid, | |||
| Stack, | |||
| Typography, | |||
| Button, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| import { lazy } from 'react'; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/BusCustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // import CustomFormWizard from './auth-forms/BusCustomFormWizard'; | |||
| // import AuthWrapper from './AuthWrapperCustom'; | |||
| // ================================|| REGISTER ||================================ // | |||
| const stepStyle = { | |||
| width:"40%", | |||
| boxShadow: 2, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "warning.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "warning.main" | |||
| } | |||
| // import { Link } from 'react-router-dom'; | |||
| import React, { useState } from 'react'; | |||
| // material-ui | |||
| import { | |||
| Stepper, | |||
| Step, | |||
| StepButton, | |||
| // Grid, | |||
| Stack, | |||
| Typography, | |||
| Button, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| import { lazy } from 'react'; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/BusCustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // import CustomFormWizard from './auth-forms/BusCustomFormWizard'; | |||
| // import AuthWrapper from './AuthWrapperCustom'; | |||
| // ================================|| REGISTER ||================================ // | |||
| const stepStyle = { | |||
| width: "40%", | |||
| boxShadow: 2, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "warning.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "secondary.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "secondary.main" | |||
| } | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "warning.main" | |||
| } | |||
| }, | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "secondary.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "secondary.main" | |||
| } | |||
| } | |||
| const steps = ['個人資料', '預覽', '完成提交']; | |||
| } | |||
| const steps = ['個人資料', '預覽', '完成提交']; | |||
| const BusRegister = () => { | |||
| const [activeStep, setActiveStep] = useState(0); | |||
| const [completed, setCompleted] = useState([false]); | |||
| const [updateValid, setUpdateValid] = useState(false); | |||
| const BusRegister = () => { | |||
| const [activeStep, setActiveStep] = useState(0); | |||
| const [completed, setCompleted] = useState([false]); | |||
| const [updateValid, setUpdateValid] = useState(false); | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| const completedSteps = () => { | |||
| return Object.keys(completed).length; | |||
| }; | |||
| const completedSteps = () => { | |||
| return Object.keys(completed).length; | |||
| }; | |||
| const isLastStep = () => { | |||
| return activeStep === totalSteps() - 1; | |||
| }; | |||
| const isLastStep = () => { | |||
| return activeStep === totalSteps() - 1; | |||
| }; | |||
| const allStepsCompleted = () => { | |||
| return completedSteps() === totalSteps(); | |||
| }; | |||
| const allStepsCompleted = () => { | |||
| return completedSteps() === totalSteps(); | |||
| }; | |||
| const handleNext = () => { | |||
| const newActiveStep = | |||
| const handleNext = () => { | |||
| const newActiveStep = | |||
| isLastStep() && !allStepsCompleted() | |||
| ? // It's the last step, but not all steps have been completed, | |||
| // find the first step that has been completed | |||
| steps.findIndex((step, i) => !(i in completed)) | |||
| : activeStep + 1; | |||
| setActiveStep(newActiveStep); | |||
| scrollToTop(); | |||
| }; | |||
| const handleBack = () => { | |||
| scrollToTop(); | |||
| setActiveStep((prevActiveStep) => prevActiveStep - 1); | |||
| }; | |||
| const scrollToTop = () => { | |||
| window.scrollTo(0,0); | |||
| }; | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| }; | |||
| return( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%',fontSize: '2rem',paddingTop: '65px'}} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| { | |||
| index < 2 ? | |||
| (<StepButton | |||
| // onClick={handleStep(index)} | |||
| > | |||
| {label} | |||
| </StepButton>) : | |||
| (<StepButton | |||
| sx={activeStep === 2 ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } : allStepsCompleted() ? { "& .MuiSvgIcon-root": { color: "secondary.main", fontSize: "2rem" } } : { color: "rgba(0, 0, 0, 0.38)" }} | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| {label} | |||
| </StepButton>) | |||
| } | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| {allStepsCompleted() ? ( | |||
| <React.Fragment> | |||
| <Typography sx={{ mt: 2, mb: 1 }}> | |||
| All steps completed - you're finished | |||
| </Typography> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| <Button onClick={handleReset}>Reset</Button> | |||
| </Stack> | |||
| </React.Fragment> | |||
| ) : ( | |||
| <React.Fragment> | |||
| <AuthWrapper> | |||
| <CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| { activeStep === totalSteps() - 1 ? ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={true} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| ? // It's the last step, but not all steps have been completed, | |||
| // find the first step that has been completed | |||
| steps.findIndex((step, i) => !(i in completed)) | |||
| : activeStep + 1; | |||
| setActiveStep(newActiveStep); | |||
| scrollToTop(); | |||
| }; | |||
| const handleBack = () => { | |||
| scrollToTop(); | |||
| setActiveStep((prevActiveStep) => prevActiveStep - 1); | |||
| }; | |||
| const scrollToTop = () => { | |||
| window.scrollTo(0, 0); | |||
| }; | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| }; | |||
| return ( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%', fontSize: '2rem', paddingTop: '65px', bgcolor: 'backgroundColor.default' }} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| { | |||
| index < 2 ? | |||
| (<StepButton | |||
| // onClick={handleStep(index)} | |||
| > | |||
| 返回 | |||
| </Button> | |||
| ):( | |||
| <Button | |||
| color="inherit" | |||
| disabled={activeStep === 0} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton>) : | |||
| (<StepButton | |||
| sx={activeStep === 2 ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } : allStepsCompleted() ? { "& .MuiSvgIcon-root": { color: "secondary.main", fontSize: "2rem" } } : { color: "rgba(0, 0, 0, 0.38)" }} | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| 返回 | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton>) | |||
| } | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| {allStepsCompleted() ? ( | |||
| <React.Fragment> | |||
| <Typography variant="h4" sx={{ mt: 2, mb: 1 }}> | |||
| All steps completed - you're finished | |||
| </Typography> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| <Button variant="h5" onClick={handleReset}>Reset</Button> | |||
| </Stack> | |||
| </React.Fragment> | |||
| ) : ( | |||
| <React.Fragment> | |||
| <AuthWrapper> | |||
| <CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| {activeStep === totalSteps() - 1 ? ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={true} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| variant="h5" | |||
| > | |||
| <Typography variant="h5">返回</Typography> | |||
| </Button> | |||
| ) : ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={activeStep === 0} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| variant="h5" | |||
| > | |||
| <Typography variant="h5">返回</Typography> | |||
| </Button> | |||
| ) | |||
| } | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| {activeStep === totalSteps() - 2 ? | |||
| ( | |||
| <Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">提交</Typography> | |||
| </Button> | |||
| ) | |||
| } | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| {activeStep === totalSteps() - 2 ? | |||
| ) : (activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| 提交 | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">提交</Typography> | |||
| </Button> | |||
| ) : ( activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| 提交 | |||
| </Button> | |||
| ): | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| 繼續 | |||
| </Button> | |||
| ) | |||
| ) : | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">繼續</Typography> | |||
| </Button> | |||
| ) | |||
| )} | |||
| {/* {activeStep !== steps.length && | |||
| {/* {activeStep !== steps.length && | |||
| (completed[activeStep] ? ( | |||
| <Typography variant="caption" sx={{ display: 'inline-block' }}> | |||
| Step {activeStep + 1} already completed | |||
| @@ -189,12 +191,12 @@ | |||
| : 'Complete Step'} | |||
| </Button> | |||
| ))} */} | |||
| </Stack> | |||
| </React.Fragment> | |||
| )} | |||
| </Stack > | |||
| // </AuthWrapper> | |||
| ); | |||
| }; | |||
| export default BusRegister; | |||
| </Stack> | |||
| </React.Fragment> | |||
| )} | |||
| </Stack > | |||
| // </AuthWrapper> | |||
| ); | |||
| }; | |||
| export default BusRegister; | |||
| @@ -1,182 +1,182 @@ | |||
| // import { Link } from 'react-router-dom'; | |||
| import React,{useState | |||
| // ,useEffect | |||
| } from 'react'; | |||
| // import { Link } from 'react-router-dom'; | |||
| import React, { | |||
| useState | |||
| // ,useEffect | |||
| } from 'react'; | |||
| // material-ui | |||
| import { | |||
| Stepper, | |||
| Step, | |||
| StepButton, | |||
| // Grid, | |||
| Stack, | |||
| Typography, | |||
| Button, | |||
| // material-ui | |||
| import { | |||
| Stepper, | |||
| Step, | |||
| StepButton, | |||
| // Grid, | |||
| Stack, | |||
| Typography, | |||
| Button, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| import { lazy } from 'react'; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/CustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // ================================|| REGISTER ||================================ // | |||
| const stepStyle = { | |||
| width:"40%", | |||
| boxShadow: 1, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "warning.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "warning.main" | |||
| } | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| import { lazy } from 'react'; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/CustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // ================================|| REGISTER ||================================ // | |||
| const stepStyle = { | |||
| width: "40%", | |||
| boxShadow: 1, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "warning.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "warning.main" | |||
| } | |||
| }, | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "secondary.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { | |||
| color: "secondary.main", | |||
| fontSize: "2rem", | |||
| }, | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "secondary.main" | |||
| } | |||
| "& .MuiStepConnector-line": { | |||
| borderColor: "secondary.main" | |||
| } | |||
| } | |||
| const steps = ['個人資料', '預覽', '完成提交']; | |||
| } | |||
| const steps = ['個人資料', '預覽', '完成提交']; | |||
| const Register = () => { | |||
| const [activeStep, setActiveStep] = useState(0); | |||
| const [completed, setCompleted] = useState([false]); | |||
| const [updateValid, setUpdateValid] = useState(false); | |||
| const Register = () => { | |||
| const [activeStep, setActiveStep] = useState(0); | |||
| const [completed, setCompleted] = useState([false]); | |||
| const [updateValid, setUpdateValid] = useState(false); | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| const completedSteps = () => { | |||
| return Object.keys(completed).length; | |||
| }; | |||
| const completedSteps = () => { | |||
| return Object.keys(completed).length; | |||
| }; | |||
| const isLastStep = () => { | |||
| return activeStep === totalSteps() - 1; | |||
| }; | |||
| const isLastStep = () => { | |||
| return activeStep === totalSteps() - 1; | |||
| }; | |||
| const allStepsCompleted = () => { | |||
| return completedSteps() === totalSteps(); | |||
| }; | |||
| const allStepsCompleted = () => { | |||
| return completedSteps() === totalSteps(); | |||
| }; | |||
| const handleNext = () => { | |||
| const newActiveStep = | |||
| const handleNext = () => { | |||
| const newActiveStep = | |||
| isLastStep() && !allStepsCompleted() | |||
| ? // It's the last step, but not all steps have been completed, | |||
| // find the first step that has been completed | |||
| steps.findIndex((step, i) => !(i in completed)) | |||
| : activeStep + 1; | |||
| setActiveStep(newActiveStep); | |||
| scrollToTop(); | |||
| }; | |||
| const handleBack = () => { | |||
| scrollToTop(); | |||
| setActiveStep((prevActiveStep) => prevActiveStep - 1); | |||
| }; | |||
| ? // It's the last step, but not all steps have been completed, | |||
| // find the first step that has been completed | |||
| steps.findIndex((step, i) => !(i in completed)) | |||
| : activeStep + 1; | |||
| setActiveStep(newActiveStep); | |||
| scrollToTop(); | |||
| }; | |||
| const scrollToTop = () => { | |||
| window.scrollTo(0,0); | |||
| }; | |||
| const handleBack = () => { | |||
| scrollToTop(); | |||
| setActiveStep((prevActiveStep) => prevActiveStep - 1); | |||
| }; | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| }; | |||
| const scrollToTop = () => { | |||
| window.scrollTo(0, 0); | |||
| }; | |||
| return( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%',fontSize: '2rem',paddingTop: '65px'}} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| { | |||
| index < 2 ? | |||
| (<StepButton | |||
| // onClick={handleStep(index)} | |||
| > | |||
| {label} | |||
| </StepButton>) : | |||
| (<StepButton | |||
| sx={activeStep === 2 ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } : allStepsCompleted() ? { "& .MuiSvgIcon-root": { color: "secondary.main", fontSize: "2rem" } } : { color: "rgba(0, 0, 0, 0.38)" }} | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| {label} | |||
| </StepButton>) | |||
| } | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| }; | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| {allStepsCompleted() ? ( | |||
| <React.Fragment> | |||
| <Typography sx={{ mt: 2, mb: 1 }}> | |||
| All steps completed - you're finished | |||
| </Typography> | |||
| <Stack direction="row" sx={{ pt: 2 }}> | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| <Button onClick={handleReset}>Reset</Button> | |||
| </Stack> | |||
| </React.Fragment> | |||
| ) : ( | |||
| <React.Fragment> | |||
| <AuthWrapper> | |||
| <CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| { activeStep === 2|| activeStep === 0? ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={true} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| return ( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%', fontSize: '2rem', paddingTop: '65px', bgcolor: 'backgroundColor.default' }} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| { | |||
| index < 2 ? | |||
| (<StepButton | |||
| // onClick={handleStep(index)} | |||
| > | |||
| 返回 | |||
| </Button> | |||
| ):( | |||
| <Button | |||
| color="inherit" | |||
| disabled={activeStep === 0} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton>) : | |||
| (<StepButton | |||
| sx={activeStep === 2 ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } : allStepsCompleted() ? { "& .MuiSvgIcon-root": { color: "secondary.main", fontSize: "2rem" } } : { color: "rgba(0, 0, 0, 0.38)" }} | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| 返回 | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton>) | |||
| } | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| {allStepsCompleted() ? ( | |||
| <React.Fragment> | |||
| <Typography variant="h4" sx={{ mt: 2, mb: 1 }}> | |||
| All steps completed - you're finished | |||
| </Typography> | |||
| <Stack direction="row" sx={{ pt: 2 }}> | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| <Button onClick={handleReset}><Typography variant="h5">Reset</Typography></Button> | |||
| </Stack> | |||
| </React.Fragment> | |||
| ) : ( | |||
| <React.Fragment> | |||
| <AuthWrapper> | |||
| <CustomFormWizard setUpdateValid={setUpdateValid} step={activeStep} /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| <Stack direction="row" sx={{ pb: 2 }}> | |||
| {activeStep === 2 || activeStep === 0 ? ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={true} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| > | |||
| <Typography variant="h5">返回</Typography> | |||
| </Button> | |||
| ) : ( | |||
| <Button | |||
| color="inherit" | |||
| disabled={activeStep === 0} | |||
| onClick={handleBack} | |||
| sx={{ mr: 1 }} | |||
| > | |||
| <Typography variant="h5">返回</Typography> | |||
| </Button> | |||
| ) | |||
| } | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| {activeStep === totalSteps() - 2 ? | |||
| ( | |||
| <Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">提交</Typography> | |||
| </Button> | |||
| ) | |||
| } | |||
| <Stack sx={{ flex: '1 1 auto' }} /> | |||
| {activeStep === totalSteps() - 2 ? | |||
| ) : (activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">提交</Typography> | |||
| </Button> | |||
| ) : | |||
| ( | |||
| <Button variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| 提交 | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5">繼續</Typography> | |||
| </Button> | |||
| ) : ( activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| 提交 | |||
| </Button> | |||
| ): | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| 繼續 | |||
| </Button> | |||
| ) | |||
| ) | |||
| )} | |||
| {/* {activeStep !== steps.length && | |||
| {/* {activeStep !== steps.length && | |||
| (completed[activeStep] ? ( | |||
| <Typography variant="caption" sx={{ display: 'inline-block' }}> | |||
| Step {activeStep + 1} already completed | |||
| @@ -188,12 +188,12 @@ | |||
| : 'Complete Step'} | |||
| </Button> | |||
| ))} */} | |||
| </Stack> | |||
| </React.Fragment> | |||
| )} | |||
| </Stack > | |||
| // </AuthWrapper> | |||
| ); | |||
| }; | |||
| </Stack> | |||
| </React.Fragment> | |||
| )} | |||
| </Stack > | |||
| // </AuthWrapper> | |||
| ); | |||
| }; | |||
| export default Register; | |||
| export default Register; | |||
| @@ -7,14 +7,11 @@ import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; | |||
| import banner from 'assets/images/bg_ml.jpg'; | |||
| import { Stack } from '../../../node_modules/@mui/material/index'; | |||
| // ================================|| LOGIN ||================================ // | |||
| const RegisterCustom = () => ( | |||
| <Stack justifyContent="center" sx={{ minHeight: '100vh' }}> | |||
| <Stack justifyContent="center" sx={{ minHeight: '100vh', bgcolor: 'backgroundColor.default' }}> | |||
| <img src={banner} alt="banner" width="100%" height="200px"/> | |||
| <center> | |||
| <Card | |||
| @@ -24,8 +21,10 @@ const RegisterCustom = () => ( | |||
| '& > *': { | |||
| flexGrow: 1, | |||
| flexBasis: '50%' | |||
| } | |||
| }, | |||
| backgroundColor: "secondary" | |||
| }} | |||
| > | |||
| <Box alignItems="center"> | |||
| <Grid container> | |||
| @@ -38,7 +37,7 @@ const RegisterCustom = () => ( | |||
| <Grid container > | |||
| <Grid item xs={12} md={6} sx={{ borderRight: 1 , borderColor: 'grey.500' }}> | |||
| <Typography mb={4} variant="h3">個人用戶</Typography> | |||
| <Button variant="outlined" startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}>以「智方便」繼續</Button> | |||
| <Button variant="outlined" 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} > | |||
| <Typography textAlign='justify' variant="body1" display="block" gutterBottom> | |||
| @@ -50,7 +49,7 @@ const RegisterCustom = () => ( | |||
| <Typography m={5}>或</Typography> | |||
| <Button href="/registerFrom" variant="contained">申請個人用戶</Button> | |||
| <Button href="/registerFrom" variant="contained"><Typography variant="h5">申請個人用戶</Typography></Button> | |||
| <Typography ml={4} mr={4} mt={4} variant="body1" display="block" sx={{fontWeight: 'bold'}} gutterBottom> | |||
| 需上載身份證明文件數碼檔案以進行網上申請。 | |||
| @@ -59,7 +58,7 @@ const RegisterCustom = () => ( | |||
| </Grid> | |||
| <Grid item xs={12} md={6} sx={{ borderLeft: 1 ,borderColor: 'grey.500' }}> | |||
| <Typography mb={4} variant="h3">機構/公司用戶</Typography> | |||
| <Button href="/registerFromOrganization" variant="contained">申請機構/公司用戶</Button> | |||
| <Button href="/registerFromOrganization" variant="contained" sx={{mt:0.5}}><Typography variant="h5">申請機構/公司用戶</Typography></Button> | |||
| <Typography ml={4} mr={4} mt={4} variant="body1" display="block" sx={{fontWeight: 'bold'}} gutterBottom> | |||
| 需上載以下任何一份證明文件以進行網上申請。 | |||
| <br/>如:商業登記證;專業執業證書 | |||
| @@ -4,8 +4,8 @@ import React, { | |||
| lazy | |||
| } from 'react'; | |||
| import { Link as RouterLink } from 'react-router-dom'; | |||
| import {useNavigate} from 'react-router-dom'; | |||
| import {useForm,} from 'react-hook-form' | |||
| import { useNavigate } from 'react-router-dom'; | |||
| import { useForm, } from 'react-hook-form' | |||
| // material-ui | |||
| import { | |||
| @@ -26,7 +26,7 @@ import { | |||
| // third party | |||
| import * as yup from 'yup'; | |||
| import { useFormik,FormikProvider } from 'formik'; | |||
| import { useFormik, FormikProvider } from 'formik'; | |||
| // project import | |||
| //import FirebaseSocial from './FirebaseSocial'; | |||
| @@ -38,8 +38,8 @@ const PasswordAlertDialog = Loadable(lazy(() => import('./PasswordAlertDialog')) | |||
| import { EyeOutlined, EyeInvisibleOutlined } from '@ant-design/icons'; | |||
| // import axios from "axios"; | |||
| import iAmSmartICon from 'assets/images/icons/icon_iAmSmart.png'; | |||
| import {useDispatch} from "react-redux"; | |||
| import {handleLogin} from "auth/index"; | |||
| import { useDispatch } from "react-redux"; | |||
| import { handleLogin } from "auth/index"; | |||
| import useJwt from "../../../auth/jwt/useJwt"; | |||
| import { handleLogoutFunction } from 'auth/index'; | |||
| // ============================|| FIREBASE - LOGIN ||============================ // | |||
| @@ -64,11 +64,11 @@ const AuthLoginCustom = () => { | |||
| }; | |||
| const tryLogin = () => { | |||
| if(isValid){ | |||
| dispatch(handleLogoutFunction()); | |||
| if (isValid) { | |||
| dispatch(handleLogoutFunction()); | |||
| // setSumitting(true) | |||
| useJwt | |||
| .login({username: values.username, password: values.password}) | |||
| .login({ username: values.username, password: values.password }) | |||
| .then((response) => { | |||
| console.log(response) | |||
| const userData = { | |||
| @@ -82,7 +82,7 @@ const AuthLoginCustom = () => { | |||
| creditor: response.data.creditor, | |||
| //avatar: require('src/assets/images/users/avatar-3.png').default, | |||
| } | |||
| const data = {...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken} | |||
| const data = { ...userData, accessToken: response.data.accessToken, refreshToken: response.data.refreshToken } | |||
| // setSuccess(true) | |||
| dispatch(handleLogin(data)) | |||
| navigate('/dashboard'); | |||
| @@ -96,42 +96,41 @@ const AuthLoginCustom = () => { | |||
| setErrorMassage(error.response.data.error) | |||
| setOpen(true) | |||
| }); | |||
| }else{ | |||
| } else { | |||
| setOpen(true) | |||
| } | |||
| } | |||
| const formik = useFormik({ | |||
| initialValues:({ | |||
| username: '', | |||
| password: '', | |||
| submit: null | |||
| initialValues: ({ | |||
| username: '', | |||
| password: '', | |||
| submit: null | |||
| }), | |||
| validationSchema:yup.object().shape({ | |||
| // username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱'), | |||
| username: yup.string().required('請輸入用戶名稱'), | |||
| password: yup.string().min(8,'請輸入最少8位密碼').required('請輸入密碼') | |||
| .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') | |||
| .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') | |||
| .matches(/^(?=.*[0-9])/, '請包括最少1個數字') | |||
| .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), | |||
| validationSchema: yup.object().shape({ | |||
| // username: yup.string().min(6,'用戶名稱最少6位').required('請輸入用戶名稱'), | |||
| username: yup.string().required('請輸入用戶名稱'), | |||
| password: yup.string().min(8, '請輸入最少8位密碼').required('請輸入密碼') | |||
| .matches(/^(?=.*[a-z])/, '請包括最少1個小寫字母') | |||
| .matches(/^(?=.*[A-Z])/, '請包括最少1個大寫字母') | |||
| .matches(/^(?=.*[0-9])/, '請包括最少1個數字') | |||
| .matches(/^(?=.*[!@#%&])/, '請包括最少1個特殊字符'), | |||
| }), | |||
| }); | |||
| const checkDataField = (data)=> { | |||
| if (data.username !==""&& | |||
| data.password !==""&& | |||
| handlePassword(data.password) | |||
| // &&handle6Digi(data.username) | |||
| ) | |||
| { | |||
| setisValid(true) | |||
| setIsButtonDisabled(false); | |||
| return isValid | |||
| }else{ | |||
| setisValid(false) | |||
| setIsButtonDisabled(true); | |||
| return isValid | |||
| const checkDataField = (data) => { | |||
| if (data.username !== "" && | |||
| data.password !== "" && | |||
| handlePassword(data.password) | |||
| // &&handle6Digi(data.username) | |||
| ) { | |||
| setisValid(true) | |||
| setIsButtonDisabled(false); | |||
| return isValid | |||
| } else { | |||
| setisValid(false) | |||
| setIsButtonDisabled(true); | |||
| return isValid | |||
| } | |||
| }; | |||
| @@ -143,17 +142,17 @@ const AuthLoginCustom = () => { | |||
| var numbers = /[0-9]/g; | |||
| var symbol = /^(?=.*[!@#%&])/; | |||
| if (!new_pass.match(lowerCase)) { | |||
| return false; | |||
| return false; | |||
| } else if (!new_pass.match(upperCase)) { | |||
| return false; | |||
| return false; | |||
| } else if (!new_pass.match(numbers)) { | |||
| return false; | |||
| return false; | |||
| } else if (!new_pass.match(symbol)) { | |||
| return false; | |||
| return false; | |||
| } else if (new_pass.length < 8) { | |||
| return false; | |||
| } else { | |||
| return true; | |||
| return true; | |||
| } | |||
| } | |||
| @@ -162,123 +161,123 @@ const AuthLoginCustom = () => { | |||
| }; | |||
| const { values } = formik | |||
| useEffect(() => { | |||
| checkDataField(values) | |||
| }, [values]) | |||
| useEffect(() => { | |||
| checkDataField(values) | |||
| }, [values]) | |||
| const {handleSubmit} = useForm({}) | |||
| const { handleSubmit } = useForm({}) | |||
| return ( | |||
| <FormikProvider value={formik}> | |||
| <form onSubmit={handleSubmit(tryLogin)}> | |||
| <Grid container spacing={3}> | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="email-login">用戶登入名稱</InputLabel> | |||
| <OutlinedInput | |||
| id="username" | |||
| name="username" | |||
| onChange={formik.handleChange} | |||
| placeholder="" | |||
| fullWidth | |||
| value={formik.values.username} | |||
| error={Boolean(formik.touched.username && formik.errors.username)} | |||
| onBlur={formik.handleBlur} | |||
| inputProps={{ | |||
| maxLength: 50, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| } | |||
| }, | |||
| <FormikProvider value={formik}> | |||
| <form onSubmit={handleSubmit(tryLogin)}> | |||
| <Grid container spacing={3}> | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="email-login"><Typography variant="h5">用戶登入名稱</Typography></InputLabel> | |||
| <OutlinedInput | |||
| id="username" | |||
| name="username" | |||
| onChange={formik.handleChange} | |||
| placeholder="" | |||
| fullWidth | |||
| value={formik.values.username} | |||
| error={Boolean(formik.touched.username && formik.errors.username)} | |||
| onBlur={formik.handleBlur} | |||
| inputProps={{ | |||
| maxLength: 50, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| } | |||
| }, | |||
| }} | |||
| /> | |||
| {formik.touched.username && formik.errors.username && ( | |||
| <FormHelperText error id="standard-weight-helper-text-username-login"> | |||
| {formik.errors.username} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="password-login">密碼</InputLabel> | |||
| <OutlinedInput | |||
| fullWidth | |||
| id="password-login" | |||
| type={showPassword ? 'text' : 'password'} | |||
| name="password" | |||
| value={formik.values.password} | |||
| onChange={formik.handleChange} | |||
| onBlur={formik.handleBlur} | |||
| error={Boolean(formik.touched.password && formik.errors.password)} | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| > | |||
| {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| } | |||
| placeholder="" | |||
| /> | |||
| {formik.touched.password && formik.errors.password && ( | |||
| <FormHelperText error id="standard-weight-helper-text-password-login"> | |||
| {formik.errors.password} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| </Grid> | |||
| /> | |||
| {formik.touched.username && formik.errors.username && ( | |||
| <FormHelperText error id="standard-weight-helper-text-username-login"> | |||
| {formik.errors.username} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="password-login"><Typography variant="h5">密碼</Typography></InputLabel> | |||
| <OutlinedInput | |||
| fullWidth | |||
| id="password-login" | |||
| type={showPassword ? 'text' : 'password'} | |||
| name="password" | |||
| value={formik.values.password} | |||
| onChange={formik.handleChange} | |||
| onBlur={formik.handleBlur} | |||
| error={Boolean(formik.touched.password && formik.errors.password)} | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| > | |||
| {showPassword ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||
| </IconButton> | |||
| </InputAdornment> | |||
| } | |||
| placeholder="" | |||
| /> | |||
| {formik.touched.password && formik.errors.password && ( | |||
| <FormHelperText error id="standard-weight-helper-text-password-login"> | |||
| {formik.errors.password} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <AnimateButton> | |||
| <Button disableElevation disabled={isButtonDisabled} | |||
| fullWidth size="large" type="submit" variant="contained" color="primary" | |||
| sx={{ | |||
| "&.Mui-disabled": { | |||
| background: "#bbdefb", | |||
| color: "#fff", | |||
| border: "2px solid", | |||
| borderColor: "#e7e7e7" | |||
| } | |||
| }}> | |||
| 登錄 | |||
| </Button> | |||
| </AnimateButton> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Link variant="h6" component={RouterLink} to="" color="primary"> | |||
| <Typography align="center"> | |||
| <Grid item xs={12}> | |||
| <AnimateButton> | |||
| <Button disableElevation disabled={isButtonDisabled} | |||
| fullWidth size="large" type="submit" variant="contained" color="primary" | |||
| sx={{ | |||
| "&.Mui-disabled": { | |||
| background: "#bbdefb", | |||
| color: "#fff", | |||
| border: "2px solid", | |||
| borderColor: "#e7e7e7" | |||
| } | |||
| }}> | |||
| <Typography variant="h5">登錄</Typography> | |||
| </Button> | |||
| </AnimateButton> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Link component={RouterLink} to="" color="primary"> | |||
| <Typography align="center" variant="h6"> | |||
| 忘記密碼? | |||
| </Typography> | |||
| </Link> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Button fullWidth size="large" variant="outlined" startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}>智方便登入</Button> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Link href="#">了解更多智方便</Link> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Button fullWidth size="large" variant="outlined" href="/register" >建立/重新啟動帳戶</Button> | |||
| </Stack> | |||
| </Grid> | |||
| </Typography> | |||
| </Link> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Button fullWidth size="large" variant="outlined" startIcon={<img src={iAmSmartICon} alt="iAM Smart" width="30" />}><Typography variant="h5">智方便登入</Typography></Button> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Link href="#"><Typography align="center" variant="h6">了解更多智方便</Typography></Link> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" spacing={2}> | |||
| <Button fullWidth size="large" variant="outlined" href="/register" ><Typography variant="h5">建立/重新啟動帳戶</Typography></Button> | |||
| </Stack> | |||
| </Grid> | |||
| <PasswordAlertDialog open={open} handleClose={handleClose} errorMassage={errorMassage}/> | |||
| </form> | |||
| </FormikProvider> | |||
| </Grid> | |||
| <PasswordAlertDialog open={open} handleClose={handleClose} errorMassage={errorMassage} /> | |||
| </form> | |||
| </FormikProvider> | |||
| ); | |||
| }; | |||
| @@ -6,17 +6,18 @@ import { | |||
| // GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| // import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import {useEffect} from "react"; | |||
| import { useEffect } from "react"; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| Box, | |||
| Stack | |||
| Stack, | |||
| Typography | |||
| } from '@mui/material'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function PreviewUploadFileTable({recordList,}) { | |||
| export default function PreviewUploadFileTable({ recordList, }) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel] = React.useState({}); | |||
| // const theme = useTheme(); | |||
| @@ -30,8 +31,10 @@ export default function PreviewUploadFileTable({recordList,}) { | |||
| function NoRowsOverlay() { | |||
| return ( | |||
| <Stack height="100%" alignItems="center" justifyContent="center"> | |||
| 沒有上傳檔案 | |||
| {/* <pre>(rows={[]})</pre> */} | |||
| <Typography variant="h6"> | |||
| 沒有上傳檔案 | |||
| </Typography> | |||
| {/* <pre>(rows={[]})</pre> */} | |||
| </Stack> | |||
| ); | |||
| } | |||
| @@ -71,17 +74,17 @@ export default function PreviewUploadFileTable({recordList,}) { | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| headerName: '檔案名稱', | |||
| headerName: <Typography variant="h6">檔案名稱</Typography>, | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'size', | |||
| field: 'size', | |||
| headerName: '檔案大小', | |||
| headerName: <Typography variant="h6">檔案大小</Typography>, | |||
| valueGetter: (params) => { | |||
| // console.log(params) | |||
| return Math.ceil(params.value/1024)+" KB"; | |||
| }, | |||
| return Math.ceil(params.value / 1024) + " KB"; | |||
| }, | |||
| flex: 1, | |||
| }, | |||
| ]; | |||
| @@ -92,7 +95,7 @@ export default function PreviewUploadFileTable({recordList,}) { | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| sx={{border:1}} | |||
| sx={{ border: 1 }} | |||
| rowModesModel={rowModesModel} | |||
| disablePagination | |||
| components={{ NoRowsOverlay, }} | |||
| @@ -6,19 +6,20 @@ import { | |||
| GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import {useEffect} from "react"; | |||
| import { useEffect } from "react"; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| Box, | |||
| Stack | |||
| Stack, | |||
| Typography | |||
| } from '@mui/material'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UploadFileTable({recordList, setUpdateRows,}) { | |||
| export default function UploadFileTable({ recordList, setUpdateRows, }) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel,setRowModesModel] = React.useState({}); | |||
| const [rowModesModel, setRowModesModel] = React.useState({}); | |||
| // const theme = useTheme(); | |||
| // const navigate = useNavigate() | |||
| @@ -31,8 +32,10 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { | |||
| function NoRowsOverlay() { | |||
| return ( | |||
| <Stack height="100%" alignItems="center" justifyContent="center"> | |||
| 沒有上傳檔案 | |||
| {/* <pre>(rows={[]})</pre> */} | |||
| <Typography variant="h6"> | |||
| 沒有上傳檔案 | |||
| </Typography> | |||
| {/* <pre>(rows={[]})</pre> */} | |||
| </Stack> | |||
| ); | |||
| } | |||
| @@ -58,11 +61,11 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({id}) => { | |||
| getActions: ({ id }) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon/>} | |||
| icon={<RemoveCircleOutlineIcon />} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| @@ -73,17 +76,17 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| headerName: '檔案名稱', | |||
| headerName: <Typography variant="h6">檔案名稱</Typography>, | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'size', | |||
| field: 'size', | |||
| headerName: '檔案大小', | |||
| headerName: <Typography variant="h6">檔案大小</Typography>, | |||
| valueGetter: (params) => { | |||
| // console.log(params) | |||
| return Math.ceil(params.value/1024)+" KB"; | |||
| }, | |||
| return Math.ceil(params.value / 1024) + " KB"; | |||
| }, | |||
| flex: 1, | |||
| }, | |||
| ]; | |||
| @@ -94,7 +97,7 @@ export default function UploadFileTable({recordList, setUpdateRows,}) { | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| sx={{border:1}} | |||
| sx={{ border: 1 }} | |||
| rowModesModel={rowModesModel} | |||
| disablePagination | |||
| components={{ NoRowsOverlay, }} | |||
| @@ -83,6 +83,9 @@ const Palette = (mode) => { | |||
| dark: '#b0671e', | |||
| contrastText: '#fff', | |||
| }, | |||
| backgroundColor: { | |||
| default: '#F2F2F2' | |||
| } | |||
| } | |||
| }); | |||
| }; | |||
| @@ -9,30 +9,35 @@ const Typography = (fontFamily) => ({ | |||
| fontWeightBold: 600, | |||
| h1: { | |||
| fontWeight: 600, | |||
| fontSize: '2.375rem', | |||
| fontSize: '2.5rem', | |||
| lineHeight: 1.21 | |||
| }, | |||
| h2: { | |||
| fontWeight: 600, | |||
| fontSize: '1.875rem', | |||
| fontSize: '2.375rem', | |||
| lineHeight: 1.27 | |||
| }, | |||
| h3: { | |||
| fontWeight: 600, | |||
| fontSize: '1.5rem', | |||
| fontSize: '1.875rem', | |||
| lineHeight: 1.33 | |||
| }, | |||
| h4: { | |||
| fontWeight: 600, | |||
| fontSize: '1.25rem', | |||
| fontSize: '1.5rem', | |||
| lineHeight: 1.4 | |||
| }, | |||
| h5: { | |||
| fontWeight: 600, | |||
| fontSize: '1rem', | |||
| lineHeight: 1.5 | |||
| fontSize: '1.275rem', | |||
| lineHeight: 1.66 | |||
| }, | |||
| h6: { | |||
| fontWeight: 600, | |||
| fontSize: '1.1rem', | |||
| lineHeight: 1.57 | |||
| }, | |||
| h7: { | |||
| fontWeight: 400, | |||
| fontSize: '0.875rem', | |||
| lineHeight: 1.57 | |||
| @@ -43,23 +48,39 @@ const Typography = (fontFamily) => ({ | |||
| lineHeight: 1.66 | |||
| }, | |||
| body1: { | |||
| fontSize: '0.875rem', | |||
| fontSize: '1.1rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1.57 | |||
| }, | |||
| body2: { | |||
| fontSize: '0.75rem', | |||
| fontSize: '1.2rem', | |||
| lineHeight: 1.66 | |||
| }, | |||
| subtitle1: { | |||
| fontSize: '0.875rem', | |||
| fontSize: '1rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1.57 | |||
| }, | |||
| subtitle2: { | |||
| fontSize: '0.75rem', | |||
| fontSize: '0.8rem', | |||
| fontWeight: 500, | |||
| lineHeight: 1.66 | |||
| }, | |||
| headerTitle1: { | |||
| fontSize: '1.5rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1.66 | |||
| }, | |||
| errorMessage1: { | |||
| fontSize: '1rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1 | |||
| }, | |||
| step1: { | |||
| fontSize: '1.4rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1 | |||
| }, | |||
| overline: { | |||
| lineHeight: 1.66 | |||
| }, | |||
| @@ -68,4 +89,4 @@ const Typography = (fontFamily) => ({ | |||
| } | |||
| }); | |||
| export default Typography; | |||
| export default Typography; | |||