| @@ -2,7 +2,7 @@ | |||
| <path d="M1.63954 13.3644L3.95187 11.052L3.95428 11.0496H8.30453L6.5736 12.7806L6.12669 13.2275L4.35415 15L4.57368 15.2201L14.5039 25.1498L24.6537 15L22.8805 13.2275L22.7557 13.102L20.7033 11.0496H25.0535L25.0559 11.052L26.8683 12.8644L29.0039 15L14.5039 29.5L0.00390625 15L1.63954 13.3644ZM14.5039 0.5L22.8823 8.87842H18.5321L14.5039 4.85024L10.4757 8.87842H6.12548L14.5039 0.5Z" fill="#096DD9"/> | |||
| <path d="M4.35477 15.0002L6.12731 13.2276L6.57422 12.7807L4.84389 11.0498H3.9549L3.95249 11.0522L1.64016 13.3645L3.85961 15.5731L4.35477 15.0002Z" fill="url(#paint0_linear_112102_1824)"/> | |||
| <path d="M22.8814 13.2276L24.6545 15.0002L24.479 15.1757L24.4796 15.1763L26.8691 12.8646L25.0568 11.0522L25.0544 11.0498H24.8783L22.7565 13.1022L22.8814 13.2276Z" fill="url(#paint1_linear_112102_1824)"/> | |||
| <path d="M3.9497 11.0498L3.95211 11.0522L6.12693 13.2276L14.5041 21.6043L25.0586 11.0498H3.9497Z" fill="#1890FF"/> | |||
| <path d="M3.9497 11.0498L3.95211 11.0522L6.12693 13.2276L14.5041 21.6043L25.0586 11.0498H3.9497Z" fill="#0C489E"/> | |||
| <defs> | |||
| <linearGradient id="paint0_linear_112102_1824" x1="5.62978" y1="11.5889" x2="2.57161" y2="14.6471" gradientUnits="userSpaceOnUse"> | |||
| <stop stop-color="#023B95"/> | |||
| @@ -2,6 +2,47 @@ | |||
| <html lang="en"> | |||
| <head> | |||
| <meta charset="utf-8" /> | |||
| <!-- Preload critical Public Sans webfont files and declare @font-face so the browser | |||
| uses the custom font immediately on page render, eliminating the flash of the | |||
| default/fallback font (FOIT/FOUT). --> | |||
| <link rel="preload" as="font" href="%PUBLIC_URL%/public-sans-latin-400-normal.woff2" type="font/woff2" crossorigin="anonymous" /> | |||
| <link rel="preload" as="font" href="%PUBLIC_URL%/public-sans-latin-500-normal.woff2" type="font/woff2" crossorigin="anonymous" /> | |||
| <link rel="preload" as="font" href="%PUBLIC_URL%/public-sans-latin-600-normal.woff2" type="font/woff2" crossorigin="anonymous" /> | |||
| <link rel="preload" as="font" href="%PUBLIC_URL%/public-sans-latin-700-normal.woff2" type="font/woff2" crossorigin="anonymous" /> | |||
| <style> | |||
| @font-face { | |||
| font-family: 'Public Sans'; | |||
| font-style: normal; | |||
| font-display: swap; | |||
| font-weight: 400; | |||
| src: url(%PUBLIC_URL%/public-sans-latin-400-normal.woff2) format('woff2'); | |||
| unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; | |||
| } | |||
| @font-face { | |||
| font-family: 'Public Sans'; | |||
| font-style: normal; | |||
| font-display: swap; | |||
| font-weight: 500; | |||
| src: url(%PUBLIC_URL%/public-sans-latin-500-normal.woff2) format('woff2'); | |||
| unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; | |||
| } | |||
| @font-face { | |||
| font-family: 'Public Sans'; | |||
| font-style: normal; | |||
| font-display: swap; | |||
| font-weight: 600; | |||
| src: url(%PUBLIC_URL%/public-sans-latin-600-normal.woff2) format('woff2'); | |||
| unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; | |||
| } | |||
| @font-face { | |||
| font-family: 'Public Sans'; | |||
| font-style: normal; | |||
| font-display: swap; | |||
| font-weight: 700; | |||
| src: url(%PUBLIC_URL%/public-sans-latin-700-normal.woff2) format('woff2'); | |||
| unicode-range: U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD; | |||
| } | |||
| </style> | |||
| <link rel="icon" type="image/png" sizes="32x32" href="%PUBLIC_URL%/favicon-32x32.png"> | |||
| <link rel="icon" type="image/png" sizes="16x16" href="%PUBLIC_URL%/favicon-16x16.png"> | |||
| <link rel="mask-icon" href="%PUBLIC_URL%/safari-pinned-tab.svg" color="#5bbad5"> | |||
| @@ -1,19 +1,20 @@ | |||
| /* Self-hosted fonts (bundled via @fontsource; no Google Fonts CDN — CSP-friendly). */ | |||
| /* All @fontsource v5 packages already use font-display: swap by default. */ | |||
| /* Public Sans — MUI theme (`themeConst.js`), charts, config */ | |||
| @import "@fontsource/public-sans/400.css"; | |||
| @import "@fontsource/public-sans/500.css"; | |||
| @import "@fontsource/public-sans/600.css"; | |||
| @import "@fontsource/public-sans/700.css"; | |||
| @import url("@fontsource/public-sans/400.css"); | |||
| @import url("@fontsource/public-sans/500.css"); | |||
| @import url("@fontsource/public-sans/600.css"); | |||
| @import url("@fontsource/public-sans/700.css"); | |||
| /* Noto Sans HK — `styles.css` / navbar (Latin + Hong Kong glyphs) */ | |||
| @import "@fontsource/noto-sans-hk/latin-400.css"; | |||
| @import "@fontsource/noto-sans-hk/chinese-hongkong-400.css"; | |||
| @import "@fontsource/noto-sans-hk/latin-600.css"; | |||
| @import "@fontsource/noto-sans-hk/chinese-hongkong-600.css"; | |||
| /* Noto Sans HK — navbar (Latin + Hong Kong glyphs) */ | |||
| @import url("@fontsource/noto-sans-hk/latin-400.css"); | |||
| @import url("@fontsource/noto-sans-hk/chinese-hongkong-400.css"); | |||
| @import url("@fontsource/noto-sans-hk/latin-600.css"); | |||
| @import url("@fontsource/noto-sans-hk/chinese-hongkong-600.css"); | |||
| /* Noto Sans SC — fallback for simplified Chinese */ | |||
| @import "@fontsource/noto-sans-sc/latin-400.css"; | |||
| @import "@fontsource/noto-sans-sc/chinese-simplified-400.css"; | |||
| @import "@fontsource/noto-sans-sc/latin-600.css"; | |||
| @import "@fontsource/noto-sans-sc/chinese-simplified-600.css"; | |||
| @import url("@fontsource/noto-sans-sc/latin-400.css"); | |||
| @import url("@fontsource/noto-sans-sc/chinese-simplified-400.css"); | |||
| @import url("@fontsource/noto-sans-sc/latin-600.css"); | |||
| @import url("@fontsource/noto-sans-sc/chinese-simplified-600.css"); | |||
| @@ -11,7 +11,7 @@ | |||
| top: 0px; | |||
| width: 100%; | |||
| z-index: 9999; | |||
| border-bottom: 3px solid #0C489E; | |||
| border-bottom: 3px solid #0c489e; | |||
| min-height: 77px; | |||
| } | |||
| @@ -112,7 +112,7 @@ | |||
| #navbar div li a:hover, | |||
| #navbar div li button.navTrigger:hover{ | |||
| color: #0C489E; | |||
| color: #1565C0; | |||
| } | |||
| #navbar div li a:hover::after, | |||
| @@ -122,7 +122,7 @@ | |||
| content: ""; | |||
| width: 80%; | |||
| height: 3px; | |||
| background:#0C489E; | |||
| background:#1565C0; | |||
| position: absolute; | |||
| bottom: -5px; | |||
| left: 20px; | |||
| @@ -166,7 +166,7 @@ | |||
| #navbar a:focus-visible, | |||
| #navbar button.navTrigger:focus-visible{ | |||
| outline: 3px solid #0C489E; | |||
| outline: 3px solid #0c489e; | |||
| outline-offset: 2px; | |||
| border-radius: 10px; | |||
| } | |||
| @@ -234,7 +234,7 @@ | |||
| text-decoration: none; | |||
| font-size: 1.1rem; | |||
| font-weight: 600; | |||
| color: #0C489E; | |||
| color: #0c489e; | |||
| transition: 0.3s ease-in-out; | |||
| text-align: center; | |||
| } | |||
| @@ -242,7 +242,7 @@ | |||
| text-decoration: none; | |||
| font-size: 1.1rem; | |||
| font-weight: 600; | |||
| color: #0C489E; | |||
| color: #0c489e; | |||
| transition: 0.3s ease-in-out; | |||
| text-align: center; | |||
| } | |||
| @@ -284,7 +284,7 @@ | |||
| transition: 0.3s ease-in-out; | |||
| } | |||
| #sidebar li a:hover{ | |||
| color: #0C489E; | |||
| color: #0c489e; | |||
| } | |||
| #sidebar div li ul{ | |||
| background: white; | |||
| @@ -344,12 +344,12 @@ | |||
| /* Hover / focus */ | |||
| #sidebar li > a:hover, | |||
| #sidebar li > button.navTrigger:hover{ | |||
| color: #0C489E; | |||
| color: #0c489e; | |||
| } | |||
| #sidebar li > a:focus-visible, | |||
| #sidebar li > button.navTrigger:focus-visible{ | |||
| outline: 3px solid #0C489E; | |||
| outline: 3px solid #0c489e; | |||
| outline-offset: 2px; | |||
| border-radius: 10px; | |||
| } | |||
| @@ -72,7 +72,7 @@ a:active { | |||
| [role="link"], | |||
| [tabindex]:not([tabindex="-1"]) | |||
| ):focus-visible { | |||
| outline: 3px solid #0C489E; | |||
| outline: 3px solid #0c489e; | |||
| outline-offset: 2px; | |||
| border-radius: 4px; | |||
| } | |||
| @@ -95,9 +95,9 @@ a:active { | |||
| /* ===== MUI DataGrid keyboard focus (WCAG 2.4.7 / 2.4.11) ===== */ | |||
| .MuiDataGrid-columnHeader:focus-visible, | |||
| .MuiDataGrid-cell:focus-visible { | |||
| outline: 3px solid #0C489E; | |||
| outline: 3px solid #0c489e; | |||
| outline-offset: -2px; | |||
| box-shadow: 0 0 0 3px rgba(12, 72, 158, 0.25); | |||
| box-shadow: 0 0 0 3px rgba(25, 118, 210, 0.25); | |||
| } | |||
| /* Contained buttons only */ | |||
| @@ -122,7 +122,7 @@ a:active { | |||
| /* ===== Outlined button focus ===== */ | |||
| .MuiButton-outlined:focus-visible { | |||
| outline: 3px solid #0C489E; | |||
| outline: 3px solid #0c489e; | |||
| outline-offset: 2px; | |||
| } | |||
| @@ -34,7 +34,7 @@ const LogoSection = ({ sx, to }) => { | |||
| ...sx, | |||
| /* ✅ WCAG 2.4.7 focus indicator */ | |||
| '&:focus-visible': { | |||
| outline: '3px solid #0C489E', | |||
| outline: '3px solid #0c489e', | |||
| outlineOffset: '2px', | |||
| borderRadius: '6px' | |||
| } | |||
| @@ -42,7 +42,7 @@ const LogoSection = ({ sx, to }) => { | |||
| > | |||
| <Stack direction="column" justifyContent="center" alignItems="center" > | |||
| <Logo /> | |||
| <span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="systemTitle">PNSPS</span> | |||
| <span style={{ color: checkSysEnv()!=''?'red':'#0c489e'}} id="systemTitle">PNSPS</span> | |||
| </Stack> | |||
| </ButtonBase> | |||
| @@ -0,0 +1,27 @@ | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import { IconButton } from '@mui/material'; | |||
| import { useIntl } from 'react-intl'; | |||
| import { handleActionKeyDown } from 'utils/CommonFunction'; | |||
| export default function FileDeleteButton({ onDelete, icon: IconComponent = RemoveCircleOutlineIcon, color = 'error' }) { | |||
| const intl = useIntl(); | |||
| const label = intl.formatMessage({ id: 'ariaDeleteFile' }); | |||
| const handleDelete = (event) => { | |||
| onDelete(event); | |||
| }; | |||
| return ( | |||
| <IconButton | |||
| size="small" | |||
| color={color} | |||
| tabIndex={0} | |||
| aria-label={label} | |||
| title={label} | |||
| onClick={handleDelete} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleDelete)} | |||
| > | |||
| <IconComponent fontSize="small" /> | |||
| </IconButton> | |||
| ); | |||
| } | |||
| @@ -11,6 +11,8 @@ import { FiDataGrid } from './FiDataGrid'; | |||
| import {useTheme} from "@emotion/react"; | |||
| import {useMediaQuery} from "@mui/material"; | |||
| import {useIntl} from "react-intl"; | |||
| import { createDeleteFileColumn } from 'utils/fileListColumns'; | |||
| import { CONTAINED_PRIMARY_BLUE } from "themes/colorConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function FileList({ refType, refId, allowDelete, sx, dateHideable,lang, ...props }) { | |||
| @@ -94,11 +96,10 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<Icon.Download />} | |||
| icon={<Icon.Download sx={{ color: CONTAINED_PRIMARY_BLUE }} />} | |||
| label="Download" | |||
| className="textPrimary" | |||
| onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)} | |||
| color="primary" | |||
| disabled={onDownload} | |||
| />] | |||
| }, | |||
| @@ -143,11 +144,10 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<Icon.Download />} | |||
| icon={<Icon.Download sx={{ color: CONTAINED_PRIMARY_BLUE }} />} | |||
| label="Download" | |||
| className="textPrimary" | |||
| onClick={onDownloadClick(params.id, params.row.skey, params.row.filename)} | |||
| color="primary" | |||
| disabled={onDownload} | |||
| />] | |||
| }, | |||
| @@ -175,24 +175,10 @@ export default function FileList({ refType, refId, allowDelete, sx, dateHideable | |||
| if (allowDelete) { | |||
| columns.push({ | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: 'Delete', | |||
| width: 100, | |||
| cellClassName: 'actions', | |||
| getActions: (params) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<Icon.Delete />} | |||
| label="Delete" | |||
| className="textPrimary" | |||
| onClick={onDeleteClick(params.id, params.row.skey, params.row.filename)} | |||
| color="primary" | |||
| />] | |||
| }, | |||
| }); | |||
| columns.push(createDeleteFileColumn( | |||
| (id, row) => onDeleteClick(id, row.skey, row.filename), | |||
| { icon: Icon.Delete, color: 'primary', width: 100 } | |||
| )); | |||
| } | |||
| return ( | |||
| @@ -30,7 +30,7 @@ const LogoSection = ({ sx, to }) => { | |||
| /* WCAG 2.4.7 – visible keyboard focus */ | |||
| '&:focus-visible': { | |||
| outline: '3px solid #0C489E', | |||
| outline: '3px solid #0c489e', | |||
| outlineOffset: '2px', | |||
| borderRadius: '6px' | |||
| } | |||
| @@ -0,0 +1,55 @@ | |||
| import { Box, useTheme } from '@mui/material'; | |||
| /** Darker green for completed register steps (matches PAY button hover). */ | |||
| export const REGISTER_STEP_COMPLETED_COLOR = '#488F52'; | |||
| export const registerStepStyle = { | |||
| width: { lg: '40%', md: '70%', xs: '100%' }, | |||
| boxShadow: 1, | |||
| backgroundColor: '#FFFFFF', | |||
| padding: 2, | |||
| '& .MuiStepLabel-label': { color: '#424242' }, | |||
| '& .MuiStepConnector-line': { borderColor: '#9E9E9E' }, | |||
| '& .MuiStepConnector-root.Mui-completed .MuiStepConnector-line': { | |||
| borderColor: REGISTER_STEP_COMPLETED_COLOR, | |||
| }, | |||
| '& .MuiStepConnector-root.Mui-active .MuiStepConnector-line': { | |||
| borderColor: 'warning.main', | |||
| }, | |||
| }; | |||
| const RegisterStepIcon = ({ active, completed, className, icon }) => { | |||
| const theme = useTheme(); | |||
| let circleColor = '#757575'; | |||
| let textColor = '#FFFFFF'; | |||
| if (completed) { | |||
| circleColor = REGISTER_STEP_COMPLETED_COLOR; | |||
| } else if (active) { | |||
| circleColor = theme.palette.warning.main; | |||
| textColor = '#1A1A1A'; | |||
| } | |||
| return ( | |||
| <Box | |||
| className={className} | |||
| sx={{ | |||
| width: '2rem', | |||
| height: '2rem', | |||
| borderRadius: '50%', | |||
| backgroundColor: circleColor, | |||
| display: 'flex', | |||
| alignItems: 'center', | |||
| justifyContent: 'center', | |||
| color: textColor, | |||
| fontSize: '1rem', | |||
| fontWeight: 600, | |||
| lineHeight: 1, | |||
| }} | |||
| > | |||
| {icon} | |||
| </Box> | |||
| ); | |||
| }; | |||
| export default RegisterStepIcon; | |||
| @@ -25,7 +25,7 @@ export function IAmSmartButton({ label, onClickFun, fullWidth }) { | |||
| return ( | |||
| <Button onClick={()=>doOnClick()} sx={{textTransform: 'none'}} color="iAmSmart" fullWidth={fullWidth} size="large" variant="outlined" startIcon={<img src={iAmSmartICon} alt={intl.formatMessage({ id: 'iAmSmartAlt' })} width="30" />}> | |||
| <Typography variant="h5"> | |||
| <Typography component="span" variant="h5"> | |||
| {_label} | |||
| </Typography> | |||
| </Button> | |||
| @@ -58,7 +58,10 @@ root.render( | |||
| <ReduxProvider store={store}> | |||
| <SysSettingProvider> | |||
| <I18nProvider> | |||
| <BrowserRouter basename="/"> | |||
| <BrowserRouter | |||
| basename="/" | |||
| future={{ v7_startTransition: true, v7_relativeSplatPath: true }} | |||
| > | |||
| <RefreshTokenProvider> | |||
| <AutoLogoutProvider> | |||
| <GreyWrapper> | |||
| @@ -64,7 +64,8 @@ const LocaleSelector = () => { | |||
| }} | |||
| aria-label={intl.formatMessage({id: 'openLanguage'})} | |||
| ref={anchorRef} | |||
| aria-controls={open ? 'profile-grow' : undefined} | |||
| aria-controls={open ? 'locale-selector-menu' : undefined} | |||
| aria-expanded={open} | |||
| aria-haspopup="true" | |||
| onClick={handleToggle} | |||
| > | |||
| @@ -103,6 +104,7 @@ const LocaleSelector = () => { | |||
| > | |||
| <ClickAwayListener onClickAway={handleClose}> | |||
| <List | |||
| id="locale-selector-menu" | |||
| component="nav" | |||
| > | |||
| <ListItem disablePadding> | |||
| @@ -77,7 +77,7 @@ const Notification = () => { | |||
| /* ✅ WCAG 2.4.7 focus indicator */ | |||
| '&:focus-visible': { | |||
| outline: '3px solid #0C489E', | |||
| outline: '3px solid #0c489e', | |||
| outlineOffset: '2px', | |||
| borderRadius: '6px' | |||
| } | |||
| @@ -516,6 +516,20 @@ function Header(props) { | |||
| {isGranted("MAINTAIN_SETTING") ? ( | |||
| <> | |||
| <li> | |||
| <Link className="systemSetting" to="/setting/hkidKeyMigration"> | |||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | |||
| HKID Key Migration | |||
| </Typography> | |||
| </Link> | |||
| </li> | |||
| <li> | |||
| <Link className="systemSetting" to="/setting/userPiiEncryption"> | |||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | |||
| User PII Encryption | |||
| </Typography> | |||
| </Link> | |||
| </li> | |||
| <li> | |||
| <Link className="systemSetting" to="/setting/sys"> | |||
| <Typography style={{ opacity: 0.9 }} variant={"pnspsHeaderTitle"} sx={{ ml: 2, mt: 1, mb: 1 }}> | |||
| @@ -775,7 +789,7 @@ function Header(props) { | |||
| <Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" sx={{ textAlign: "center", width: "300px" }}> | |||
| <Box sx={{ mr: 2, mt: 1, display: { md: "none" } }}> | |||
| <MobileLogo /> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0C489E" }} id="mobileTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0c489e" }} id="mobileTitle"> | |||
| PNSPS | |||
| </span> | |||
| </Box> | |||
| @@ -794,7 +808,7 @@ function Header(props) { | |||
| <Stack id="sidebar" direction="column" justifyContent="center" alignItems="center" onClick={handleDrawerToggle} sx={{ textAlign: "center" }}> | |||
| <Box sx={{ mr: 2, mt: 1, display: { md: "none" } }}> | |||
| <MobileLogo /> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0C489E" }} id="mobileTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0c489e" }} id="mobileTitle"> | |||
| PNSPS | |||
| </span> | |||
| </Box> | |||
| @@ -826,13 +840,13 @@ function Header(props) { | |||
| onClick={handleDrawerToggle} | |||
| sx={{ mr: 2, display: { md: "none" } }} | |||
| > | |||
| <MenuIcon style={{ color: "#0C489E" }} /> | |||
| <MenuIcon style={{ color: "#0c489e" }} /> | |||
| </IconButton> | |||
| <Box sx={{ flexGrow: 1, mr: 2, display: { sm: "block", md: "none" } }}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" width="100%"> | |||
| <MobileLogo /> | |||
| <Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0C489E" }} id="mobileTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0c489e" }} id="mobileTitle"> | |||
| PNSPS | |||
| </span> | |||
| </Stack> | |||
| @@ -848,7 +862,7 @@ function Header(props) { | |||
| <Stack direction="row" justifyContent="flex-start" alignItems="center"> | |||
| <Logo /> | |||
| <Stack justifyContent="flex-start" alignItems="center"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "#B00020" : "#0C489E" }} id="systemTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "#B00020" : "#0c489e" }} id="systemTitle"> | |||
| <FormattedMessage id="PNSPS" /> | |||
| </span> | |||
| </Stack> | |||
| @@ -863,14 +877,14 @@ function Header(props) { | |||
| onClick={handleDrawerToggle} | |||
| sx={{ mr: 2, display: { md: "none" } }} | |||
| > | |||
| <MenuIcon style={{ color: "#0C489E" }} /> | |||
| <MenuIcon style={{ color: "#0c489e" }} /> | |||
| </IconButton> | |||
| <Box sx={{ flexGrow: 1, mr: 2, display: { sm: "block", md: "none" } }}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" width="100%"> | |||
| <MobileLogo /> | |||
| <Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0C489E" }} id="mobileTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#000" }} id="mobileTitle"> | |||
| <FormattedMessage id="PNSPS" /> | |||
| </span> | |||
| </Stack> | |||
| @@ -946,14 +960,14 @@ function Header(props) { | |||
| onClick={handleDrawerToggle} | |||
| sx={{ mr: 2, display: { md: "none" } }} | |||
| > | |||
| <MenuIcon style={{ color: "#0C489E" }} /> | |||
| <MenuIcon style={{ color: "#0c489e" }} /> | |||
| </IconButton> | |||
| <Box sx={{ flexGrow: 1, mr: 2, display: { sm: "block", md: "none" } }}> | |||
| <Stack direction="row" justifyContent="space-between" alignItems="center" width="100%"> | |||
| <MobileLogo /> | |||
| <Stack justifyContent="flex-start" alignItems="flex-start" width="100%" ml={2}> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0C489E" }} id="mobileTitle"> | |||
| <span style={{ color: checkSysEnv() !== "" ? "red" : "#0c489e" }} id="mobileTitle"> | |||
| <FormattedMessage id="PNSPS" /> | |||
| </span> | |||
| </Stack> | |||
| @@ -67,7 +67,7 @@ const MainLayout = () => { | |||
| {/* <Breadcrumbs navigation={navigation} title /> */} | |||
| <Outlet /> | |||
| </Box> | |||
| <Box sx={{borderTop: "3px solid #0C489E"}}> | |||
| <Box sx={{borderTop: "3px solid #0c489e"}}> | |||
| <Footer/> | |||
| </Box> | |||
| </Box> | |||
| @@ -72,7 +72,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Announcement</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Announcement</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -75,7 +75,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography component="h1" ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}><FormattedMessage id="announcement" /></Typography> | |||
| <Typography component="h1" ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}><FormattedMessage id="announcement" /></Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -61,7 +61,7 @@ const AuditLogPage = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Audit Log</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Audit Log</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -68,7 +68,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| Create Demand Note | |||
| </Typography> | |||
| </Stack> | |||
| @@ -68,7 +68,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| Export for GDN (Non Creditor) | |||
| </Typography> | |||
| </Stack> | |||
| @@ -27,6 +27,7 @@ import { PNSPS_BUTTON_THEME } from "themes/buttonConst"; | |||
| import { ThemeProvider } from "@emotion/react"; | |||
| import { isGrantedAny } from "auth/utils"; | |||
| import { useIntl } from "react-intl"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function SearchDemandNote({ applySearch, searchCriteria, applyGridOnReady }) { | |||
| @@ -334,6 +335,7 @@ export default function SearchDemandNote({ applySearch, searchCriteria, applyGri | |||
| <Button | |||
| component="span" | |||
| variant="contained" | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| > | |||
| Attach DN | |||
| </Button> | |||
| @@ -93,7 +93,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| Demand Note | |||
| </Typography> | |||
| </Stack> | |||
| @@ -208,7 +208,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| GFMIS Generate XML | |||
| </Typography> | |||
| </Stack> | |||
| @@ -87,7 +87,7 @@ const JVMDefault = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="space-between" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| System Background Status | |||
| </Typography> | |||
| </Stack> | |||
| @@ -18,6 +18,7 @@ const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/Loa | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import { FormattedMessage } from "react-intl"; | |||
| import usePageTitle from 'components/usePageTitle'; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from 'themes/colorConst'; | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| @@ -91,8 +92,8 @@ const Index = () => { | |||
| {record?.subject} | |||
| </Typography> | |||
| <Typography sx={{p:1}} align="justify">{DateUtils.datetimeStr(record?.sentDate)}</Typography> | |||
| <Typography variant="body1" sx={{ p:4, textAlign: "left" }} align="justify" backgroundColor="#f8f8f8"> | |||
| <div dangerouslySetInnerHTML={{__html: record?.content}}></div> | |||
| <Typography component="div" variant="body1" sx={{ p: 4, textAlign: "left", bgcolor: "#f8f8f8" }} align="justify"> | |||
| <div dangerouslySetInnerHTML={{ __html: record?.content }} /> | |||
| </Typography> | |||
| <Typography component="h3" variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "center" }}> | |||
| @@ -100,7 +101,7 @@ const Index = () => { | |||
| component="span" | |||
| variant="contained" | |||
| size="large" | |||
| sx={{ m: 4 }} | |||
| sx={{ m: 4, ...PRIMARY_CONTAINED_BUTTON_SX }} | |||
| onClick={() => { | |||
| navigate(-1); | |||
| }} | |||
| @@ -72,7 +72,7 @@ const OrganizationSearchPage = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>View Organisation</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>View Organisation</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -4,6 +4,7 @@ import { | |||
| } from '@mui/material'; | |||
| import { | |||
| isORGLoggedIn, | |||
| formatPaymentParticularsLength, | |||
| } from "utils/Utils"; | |||
| import * as React from 'react'; | |||
| import * as FormatUtils from "utils/FormatUtils" | |||
| @@ -48,7 +49,7 @@ export default function SearchPublicNoticeTable({ recordList }) { | |||
| {isORGLoggedIn()&¶ms.row.careOf!=null&¶ms.row.careOf!=""?<>{params.row.careOf}<br /></>:null} | |||
| App No: {appNo}<br/> | |||
| Issue Date: {DateUtils.dateValue(params.row.issueDate)}<br/> | |||
| Length: {params.row.length+ " cm"}</div> | |||
| Length: {formatPaymentParticularsLength(params.row)}</div> | |||
| }, | |||
| }, | |||
| { | |||
| @@ -3,24 +3,33 @@ import { | |||
| Grid, | |||
| Typography, | |||
| FormLabel, | |||
| Button | |||
| Button, | |||
| Dialog, | |||
| DialogTitle, | |||
| DialogContent, | |||
| DialogActions, | |||
| Box | |||
| } from '@mui/material'; | |||
| import * as React from "react"; | |||
| import * as FormatUtils from "utils/FormatUtils"; | |||
| import * as PaymentStatus from "utils/statusUtils/PaymentStatus"; | |||
| import * as DateUtils from "utils/DateUtils"; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import { PAYMENT_MARK_AS_PAID } from "utils/ApiPathConst"; | |||
| import Loadable from 'components/Loadable'; | |||
| const MainCard = Loadable(React.lazy(() => import('components/MainCard'))); | |||
| const LoadingComponent = Loadable(React.lazy(() => import('pages/extra-pages/LoadingComponent'))); | |||
| import DownloadIcon from '@mui/icons-material/Download'; | |||
| import {useIntl} from "react-intl"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| const PaymentDetails = ({ formData, doPrint, onDownload, onRefresh }) => { | |||
| const intl = useIntl(); | |||
| const [data, setData] = React.useState({}); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| const [confirmOpen, setConfirmOpen] = React.useState(false); | |||
| const [markingPaid, setMarkingPaid] = React.useState(false); | |||
| // const { locale } = intl; | |||
| React.useEffect(() => { | |||
| @@ -40,9 +49,29 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| if("01" == paymentmethod) return "PPS"; | |||
| if("02" == paymentmethod || "03" == paymentmethod) return "Credit Card"; | |||
| if("04" == paymentmethod) return "FPS"; | |||
| if (data.payMethod === "04,BCFP,FPS") return "FPS"; | |||
| return paymentmethod; | |||
| } | |||
| const showMarkAsPaid = data.status === "REJT" && getPaymentMethod() === "FPS"; | |||
| const handleMarkAsPaid = () => { | |||
| setMarkingPaid(true); | |||
| HttpUtils.post({ | |||
| url: PAYMENT_MARK_AS_PAID + "/" + data.id, | |||
| onSuccess: () => { | |||
| setConfirmOpen(false); | |||
| setMarkingPaid(false); | |||
| if (onRefresh) { | |||
| onRefresh(); | |||
| } | |||
| }, | |||
| onError: () => { | |||
| setMarkingPaid(false); | |||
| } | |||
| }); | |||
| }; | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent /> | |||
| @@ -51,9 +80,21 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <Typography variant="h5" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||
| Payment Details | |||
| </Typography> | |||
| <Box sx={{ display: "flex", alignItems: "center", justifyContent: "space-between", mb: 2, borderBottom: "1px solid black" }}> | |||
| <Typography variant="h5" sx={{ textAlign: "left" }}> | |||
| Payment Details | |||
| </Typography> | |||
| {showMarkAsPaid && ( | |||
| <Button | |||
| className="printHidden" | |||
| variant="contained" | |||
| color="primary" | |||
| onClick={() => setConfirmOpen(true)} | |||
| > | |||
| Mark as Paid | |||
| </Button> | |||
| )} | |||
| </Box> | |||
| <form> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12} > | |||
| @@ -116,7 +157,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| <Grid container > | |||
| <Grid item xs={6} md={6} sx={{ml:-5, textAlign: "right" }}> | |||
| <FormLabel sx={{ color: "#000000" }}> | |||
| EGIS Reference No.: | |||
| Payment Reference No.: | |||
| </FormLabel> | |||
| </Grid> | |||
| <Grid item xs={6} md={5} sx={{ml:5, textAlign: "left" }}> | |||
| @@ -164,7 +205,7 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| Payment Receipt: | |||
| </FormLabel> | |||
| </Grid> | |||
| <Grid xs={6} md={5} sx={{ml:5,textAlign: "left" }}> | |||
| <Grid item xs={6} md={5} sx={{ml:5,textAlign: "left" }}> | |||
| <Button className="printHidden" variant="contained" disabled={onDownload} sx={{ mt:2 }} onClick={doPrint}> | |||
| <DownloadIcon/> | |||
| <Typography sx={{fontSize: "16px"}}>Download</Typography> | |||
| @@ -176,6 +217,25 @@ const PaymentDetails = ({ formData,doPrint,onDownload }) => { | |||
| } | |||
| </Grid> | |||
| </form> | |||
| <Dialog | |||
| open={confirmOpen} | |||
| onClose={() => !markingPaid && setConfirmOpen(false)} | |||
| > | |||
| <DialogTitle>Confirm</DialogTitle> | |||
| <DialogContent> | |||
| <Typography variant="h5" sx={{ padding: '16px' }}> | |||
| {`Are you sure to mark as paid for Payment No. ${data.transNo || data.payload?.transactionid} ?`} | |||
| </Typography> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button onClick={() => setConfirmOpen(false)} disabled={markingPaid}> | |||
| <Typography variant="h5">Cancel</Typography> | |||
| </Button> | |||
| <Button onClick={handleMarkAsPaid} disabled={markingPaid}> | |||
| <Typography variant="h5">Confirm</Typography> | |||
| </Button> | |||
| </DialogActions> | |||
| </Dialog> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| @@ -35,6 +35,9 @@ const Index = () => { | |||
| const params = useParams(); | |||
| const navigate = useNavigate() | |||
| const [responeData, setResponeData] = React.useState({}); | |||
| const [transactionData, setTransactionData] = React.useState({}); | |||
| const [record, setRecord] = React.useState(); | |||
| const [itemList, setItemList] = React.useState([]); | |||
| const [onReady, setOnReady] = React.useState(false); | |||
| @@ -47,8 +50,16 @@ const Index = () => { | |||
| }, []); | |||
| React.useEffect(() => { | |||
| setOnReady(true); | |||
| }, [record]); | |||
| if (Object.keys(responeData).length > 0) { | |||
| setTransactionData(responeData); | |||
| } | |||
| }, [responeData]); | |||
| React.useEffect(() => { | |||
| if (Object.keys(transactionData).length > 0) { | |||
| setOnReady(true); | |||
| } | |||
| }, [transactionData]); | |||
| // const handleResize = () => { | |||
| // setDetailsOrder(window.innerWidth > 1023 ? 2 : -1); | |||
| @@ -70,17 +81,40 @@ const Index = () => { | |||
| const loadForm = () => { | |||
| if (params.id > 0) { | |||
| HttpUtils.get({ | |||
| url: UrlUtils.PAYMENT_LOAD + "/" + params.id, | |||
| onSuccess: (responseData) => { | |||
| if (!responseData.data?.id) { | |||
| navigate("/paymentPage/search"); | |||
| } | |||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||
| setItemList(responseData.paymentItemList) | |||
| setRecord(responseData.data); | |||
| if (responseData.data.status == null || responseData.data.status == "INPR") { | |||
| HttpUtils.post({ | |||
| url: UrlUtils.PAYMENT_RETRY_STATUS_API, | |||
| params: { | |||
| "paymentId": params.id | |||
| }, | |||
| onSuccess: function (responseData2) { | |||
| responseData2.data["transDateStr"] = responseData2.data.transDateTime; | |||
| responseData2.data["transTimeStr"] = DateUtils.dateFormat(responseData2.data.transDateTime, "HH:mm:ss"); | |||
| setResponeData(responseData2.transactionData); | |||
| setItemList(responseData2.paymentItemList); | |||
| setRecord(responseData2.data); | |||
| }, | |||
| onError: function () { | |||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||
| setResponeData(responseData); | |||
| setItemList(responseData.paymentItemList); | |||
| setRecord(responseData.data); | |||
| } | |||
| }); | |||
| } else { | |||
| responseData.data["transDateStr"] = responseData.data.transDateTime; | |||
| responseData.data["transTimeStr"] = DateUtils.dateFormat(responseData.data.transDateTime, "HH:mm:ss"); | |||
| setResponeData(responseData); | |||
| setItemList(responseData.paymentItemList); | |||
| setRecord(responseData.data); | |||
| } | |||
| } | |||
| }); | |||
| } | |||
| @@ -125,6 +159,7 @@ const Index = () => { | |||
| formData={record} | |||
| doPrint={doPrint} | |||
| onDownload={onDownload} | |||
| onRefresh={loadForm} | |||
| style={{ | |||
| display: "flex", | |||
| height: "100%", | |||
| @@ -4,6 +4,7 @@ import { | |||
| } from '@mui/material'; | |||
| import { | |||
| isORGLoggedIn, | |||
| formatPaymentParticularsLength, | |||
| } from "utils/Utils"; | |||
| import * as React from 'react'; | |||
| import * as FormatUtils from "utils/FormatUtils" | |||
| @@ -75,7 +76,7 @@ export default function SearchPublicNoticeTable({ recordList }) { | |||
| {isORGLoggedIn()&¶ms.row.careOf!=null&¶ms.row.careOf!=""?<>{params.row.careOf}<br /></>:null} | |||
| <FormattedMessage id="applicationId"/>: {appNo}<br/> | |||
| <FormattedMessage id="gazetteDate"/>: {locale === 'en' ? DateUtils.dateValue(params.row.issueDate) : DateUtils.dateStr_Cht(params.row.issueDate)}<br/> | |||
| <FormattedMessage id="gazetteLength"/>: {params.row.length+ " cm"}</div> | |||
| <FormattedMessage id="gazetteLength"/>: {formatPaymentParticularsLength(params.row, intl)}</div> | |||
| }, | |||
| }, | |||
| { | |||
| @@ -21,6 +21,7 @@ import ForwardIcon from '@mui/icons-material/Forward'; | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import {FormattedMessage,useIntl} from "react-intl"; | |||
| import usePageTitle from "components/usePageTitle"; | |||
| import { toReceiptLanguage } from "utils/Utils"; | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: '100%', | |||
| @@ -76,10 +77,8 @@ const Index = () => { | |||
| const doPrint = () => { | |||
| // window.print(); | |||
| setOnDownload(true) | |||
| const local = locale | |||
| // console.log(local) | |||
| HttpUtils.fileDownload({ | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+params.id+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+params.id+"/"+toReceiptLanguage(locale), | |||
| onResponse:()=>{ | |||
| setOnDownload(false) | |||
| }, | |||
| @@ -24,6 +24,7 @@ const DataGrid = Loadable(React.lazy(() => import('../Details_Public/DataGrid')) | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import {FormattedMessage,useIntl} from "react-intl"; | |||
| import { toReceiptLanguage } from "utils/Utils"; | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: '100%', | |||
| @@ -162,10 +163,8 @@ const AckPage = () => { | |||
| const doPrint = () => { | |||
| // window.print(); | |||
| setOnDownload(true) | |||
| const local = locale | |||
| HttpUtils.fileDownload({ | |||
| // url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+localStorage.getItem("paymentId")+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+paymentData.id+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+paymentData.id+"/"+toReceiptLanguage(locale), | |||
| onResponse:()=>{ | |||
| setOnDownload(false) | |||
| }, | |||
| @@ -485,11 +485,17 @@ const Index = () => { | |||
| component="span" | |||
| variant="contained" | |||
| size="large" | |||
| color="error" | |||
| onClick={()=>{ | |||
| cancelPayment(); | |||
| }} | |||
| sx={{ m: 4 }} | |||
| sx={{ | |||
| m: 4, | |||
| backgroundColor: (theme) => theme.palette.error.darker, | |||
| color: (theme) => theme.palette.error.contrastText, | |||
| '&:hover': { | |||
| backgroundColor: (theme) => theme.palette.error.dark, | |||
| }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="payCancel"/> | |||
| </Button> | |||
| @@ -24,6 +24,7 @@ const DataGrid = Loadable(React.lazy(() => import('../Details_Public/DataGrid')) | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import {FormattedMessage,useIntl} from "react-intl"; | |||
| import { toReceiptLanguage } from "utils/Utils"; | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: '100%', | |||
| @@ -152,9 +153,8 @@ const Fpscallback = () => { | |||
| const params = new URLSearchParams(window.location.search); | |||
| // window.print(); | |||
| setOnDownload(true) | |||
| const local = locale | |||
| HttpUtils.fileDownload({ | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+params.get("PAYMENT_ID")+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+params.get("PAYMENT_ID")+"/"+toReceiptLanguage(locale), | |||
| onResponse:()=>{ | |||
| setOnDownload(false) | |||
| }, | |||
| @@ -32,6 +32,7 @@ import UnionPayIcon from "assets/images/icons/unionpay.svg"; | |||
| import PpsIcon from "assets/images/icons/ppshk.svg"; | |||
| import FpsIcon from "assets/images/icons/fps.svg"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX, PAY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| import * as HttpUtils from "utils/HttpUtils" | |||
| import * as UrlUtils from "utils/ApiPathConst" | |||
| @@ -442,7 +443,7 @@ const MultiPaymentWindow = (props) => { | |||
| </FormikProvider> | |||
| <Stack direction="row" justifyContent="space-around"> | |||
| <DialogActions> | |||
| <Button variant="contained" onClick={closeHandle()} autoFocus > | |||
| <Button variant="contained" onClick={closeHandle()} autoFocus sx={PRIMARY_CONTAINED_BUTTON_SX}> | |||
| <FormattedMessage id="cancel"/> | |||
| </Button> | |||
| </DialogActions> | |||
| @@ -451,7 +452,7 @@ const MultiPaymentWindow = (props) => { | |||
| props.onPayment? | |||
| <LoadingComponent disableText={true} alignItems="flex-start"/> | |||
| : | |||
| <Button variant="contained" color="success" onClick={confirmPaymentHandle()} disabled={paymentMethod === "" || isLimit || isPPSLimit}> | |||
| <Button variant="contained" onClick={confirmPaymentHandle()} disabled={paymentMethod === "" || isLimit || isPPSLimit} sx={PAY_CONTAINED_BUTTON_SX}> | |||
| <FormattedMessage id="pay"/> | |||
| </Button> | |||
| } | |||
| @@ -21,6 +21,7 @@ const DataGrid = Loadable(React.lazy(() => import('./Details_Public/DataGrid'))) | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import {FormattedMessage,useIntl} from "react-intl"; | |||
| import { toReceiptLanguage } from "utils/Utils"; | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: '100%', | |||
| @@ -159,11 +160,8 @@ const Index = () => { | |||
| const doPrint = () => { | |||
| // window.print(); | |||
| setOnDownload(true) | |||
| const local = locale | |||
| console.log(local) | |||
| HttpUtils.fileDownload({ | |||
| // url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+localStorage.getItem("paymentId")+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+paymentData.id+"/"+local, | |||
| url: UrlUtils.GEN_PAYMENT_RECEIPT+"/"+paymentData.id+"/"+toReceiptLanguage(locale), | |||
| onResponse:()=>{ | |||
| setOnDownload(false) | |||
| }, | |||
| @@ -87,7 +87,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||
| }, | |||
| { | |||
| field: 'actions', | |||
| headerName: 'Transaction No.', | |||
| headerName: 'Payment No.', | |||
| flex: 1, | |||
| minWidth: 200, | |||
| cellClassName: 'actions', | |||
| @@ -95,6 +95,12 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||
| return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | |||
| }, | |||
| }, | |||
| { | |||
| field: 'egisRefNo', | |||
| headerName: 'Payment Reference No.', | |||
| flex: 1, | |||
| minWidth: 200, | |||
| }, | |||
| { | |||
| field: 'payMethod', | |||
| headerName: 'Payment Method', | |||
| @@ -107,7 +113,7 @@ export default function SearchPaymentTable({ searchCriteria, applyGridOnReady, a | |||
| { | |||
| id: 'transDateTime', | |||
| field: 'transDateTime', | |||
| headerName: 'Transaction Date', | |||
| headerName: 'Payment Date', | |||
| flex: 1, | |||
| minWidth: 150, | |||
| @@ -71,7 +71,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| Online Payment Record | |||
| </Typography> | |||
| </Stack> | |||
| @@ -11,6 +11,7 @@ import { FiDataGrid } from "components/FiDataGrid"; | |||
| import {useTheme} from "@emotion/react"; | |||
| import {useIntl} from "react-intl"; | |||
| import { clickableLink } from 'utils/CommonFunction'; | |||
| import { getPaymentMethodByCode } from "auth/utils"; | |||
| import {PAYMENT_LIST} from "utils/ApiPathConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| @@ -58,6 +59,12 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea | |||
| return clickableLink('/paymentPage/details/' + params.row.id, params.row.transNo); | |||
| }, | |||
| }, | |||
| { | |||
| field: 'egisRefNo', | |||
| headerName: intl.formatMessage({id: 'paymentRefCode'}), | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| }, | |||
| { | |||
| id: 'appNos', | |||
| field: 'appNos', | |||
| @@ -69,6 +76,13 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea | |||
| return <div style={{ margin: 4 }}>{appNo}</div> | |||
| }, | |||
| }, | |||
| { | |||
| field: 'payMethod', | |||
| headerName: intl.formatMessage({id: 'paymentMethod'}), | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| renderCell: (params) => getPaymentMethodByCode(params?.value), | |||
| }, | |||
| { | |||
| id: 'transDateTime', | |||
| field: 'transDateTime', | |||
| @@ -23,6 +23,7 @@ import { | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import {ThemeProvider} from "@emotion/react"; | |||
| import {PNSPS_BUTTON_THEME} from "../../themes/buttonConst"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX, PAY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| import { | |||
| FormattedMessage, | |||
| useIntl | |||
| @@ -490,16 +491,16 @@ const Index = () => { | |||
| variant="contained" | |||
| // color="error" | |||
| onClick={() => paymentClick()} | |||
| sx={{ mt: 4 }} | |||
| sx={{ mt: 4, ...PAY_CONTAINED_BUTTON_SX }} | |||
| > | |||
| <FormattedMessage id="pay"/> | |||
| <FormattedMessage id="selectPaymentMethodBtn"/> | |||
| </Button> | |||
| <Button | |||
| component="span" | |||
| variant="contained" | |||
| // color="error" | |||
| onClick={() => { navigate("/publicNotice") }} | |||
| sx={{ mt: 4 }} | |||
| sx={{ mt: 4, ...PRIMARY_CONTAINED_BUTTON_SX }} | |||
| > | |||
| <FormattedMessage id="cancel"/> | |||
| </Button> | |||
| @@ -2,11 +2,10 @@ | |||
| import * as React from 'react'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import { useEffect } from "react"; | |||
| import { createDeleteFileColumn } from 'utils/fileListColumns'; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| @@ -17,7 +16,6 @@ import { | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UploadFileTable({ recordList, setRecordList, showPageColumn, _checkCode, _expectedCode }) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel, setRowModesModel] = React.useState({}); | |||
| const [showPage, setShowPage] = React.useState(false); | |||
| @@ -67,6 +65,8 @@ export default function UploadFileTable({ recordList, setRecordList, showPageCol | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| } | |||
| const deleteColumn = createDeleteFileColumn((id) => handleCancelClick(id)); | |||
| const handlePreviewClick = (param) => () => { | |||
| var reader = new FileReader(); | |||
| reader.onload = function () { | |||
| @@ -87,25 +87,7 @@ export default function UploadFileTable({ recordList, setRecordList, showPageCol | |||
| const columns = showPage?[ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({ id }) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon />} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="error" | |||
| />] | |||
| }, | |||
| }, | |||
| deleteColumn, | |||
| { | |||
| field: 'name', | |||
| headerName: 'File Name', | |||
| @@ -132,25 +114,7 @@ export default function UploadFileTable({ recordList, setRecordList, showPageCol | |||
| hide: true | |||
| }, | |||
| ]:[ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({ id }) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon />} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="error" | |||
| />] | |||
| }, | |||
| }, | |||
| deleteColumn, | |||
| { | |||
| field: 'name', | |||
| headerName: 'File Name', | |||
| @@ -79,7 +79,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Create Proof</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Create Proof</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -32,6 +32,37 @@ const BackgroundHead = { | |||
| backgroundPosition: 'right' | |||
| } | |||
| const contentBoxSx = { | |||
| px: { xs: 2, sm: 3, md: 5, lg: 6 }, | |||
| maxWidth: 1500, | |||
| width: '100%', | |||
| }; | |||
| const headerSx = { | |||
| textAlign: 'left', | |||
| mt: 4, | |||
| fontSize: { xs: '1.15rem', sm: '1.35rem', md: '1.5rem' }, | |||
| textDecoration: 'underline', | |||
| textDecorationThickness: '2px', | |||
| textUnderlineOffset: '4px', | |||
| }; | |||
| const bodySx = { | |||
| mt: 4, | |||
| textAlign: 'left', | |||
| fontSize: { xs: '1rem', sm: '1.1rem', md: '1.25rem' }, | |||
| lineHeight: 1.6, | |||
| }; | |||
| const payButtonSx = { | |||
| minWidth: 'unset', | |||
| px: { xs: 2, sm: 3 }, | |||
| py: 1.25, | |||
| whiteSpace: 'nowrap', | |||
| width: { xs: '100%', sm: 'auto' }, | |||
| fontSize: { xs: '1rem', sm: '1.2rem' }, | |||
| }; | |||
| import { | |||
| // useEffect, | |||
| useState | |||
| @@ -151,37 +182,19 @@ const Index = () => { | |||
| </Grid> | |||
| {/*row 1*/} | |||
| <Grid item xs={12} md={12} > | |||
| <Grid container justifyContent="flex-start" alignItems="center" > | |||
| <center> | |||
| <Grid item xs={12} md={8} > | |||
| <Grid container justifyContent="center" alignItems="center" > | |||
| <Grid item xs={12} md={11} lg={10} sx={contentBoxSx}> | |||
| {isAfter ? ( | |||
| <Typography | |||
| variant="h4" | |||
| sx={{ textAlign: "left", ml: 8, mr: 4, mt: 4, | |||
| textDecoration: "underline", | |||
| textDecorationThickness: "2px", | |||
| textUnderlineOffset: "4px" }} | |||
| > | |||
| <Typography variant="h4" sx={headerSx}> | |||
| <FormattedMessage id="proofPaymentHeader_online2" /> | |||
| </Typography> | |||
| ) : ( | |||
| <Typography | |||
| variant="h4" | |||
| sx={{ | |||
| textAlign: "left", | |||
| ml: 4, | |||
| mr: 4, | |||
| mt: 4, | |||
| textDecoration: "underline", | |||
| textDecorationThickness: "2px", | |||
| textUnderlineOffset: "4px" | |||
| }} | |||
| > | |||
| <Typography variant="h4" sx={headerSx}> | |||
| <FormattedMessage id="proofPaymentHeader_online" /> | |||
| </Typography> | |||
| )} | |||
| <Typography variant="h5" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | |||
| <Typography variant="h5" sx={bodySx}> | |||
| <div dangerouslySetInnerHTML={{ | |||
| __html: intl.formatMessage( | |||
| { | |||
| @@ -215,26 +228,39 @@ const Index = () => { | |||
| </Typography> | |||
| {!checkPaymentSuspension()? | |||
| <Typography variant="h4" sx={{ ml: 8, textAlign: "left" }}> | |||
| <Stack | |||
| direction={{ xs: 'column', sm: 'row' }} | |||
| alignItems={{ xs: 'stretch', sm: 'center' }} | |||
| sx={{ mt: 4, gap: { xs: 1.5, sm: 2 } }} | |||
| > | |||
| <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 }} | |||
| sx={payButtonSx} | |||
| onClick={() => { setIsPopUp(true) }} | |||
| > | |||
| <FormattedMessage id="payInstantly" /> | |||
| </Button> | |||
| </ThemeProvider> | |||
| <FormattedMessage id="or" /> | |||
| <Typography | |||
| component="span" | |||
| variant="h4" | |||
| sx={{ | |||
| textAlign: { xs: 'center', sm: 'left' }, | |||
| fontSize: { xs: '1rem', sm: '1.25rem' }, | |||
| my: { xs: 0.5, sm: 0 }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="or" /> | |||
| </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 } }} | |||
| sx={payButtonSx} | |||
| onClick={() => { | |||
| navigate("/publicNotice"); | |||
| }} | |||
| @@ -242,10 +268,10 @@ const Index = () => { | |||
| <FormattedMessage id="payLater" /> | |||
| </Button> | |||
| </ThemeProvider> | |||
| </Typography>:null | |||
| </Stack>:null | |||
| } | |||
| <Typography variant="h4" sx={{ ml: 8, mt: 4, mr: 8, textAlign: "left" }}> | |||
| <Typography variant="h4" sx={bodySx}> | |||
| <div dangerouslySetInnerHTML={{ | |||
| __html: intl.formatMessage( | |||
| { | |||
| @@ -258,7 +284,6 @@ const Index = () => { | |||
| </Grid> | |||
| </center> | |||
| </Grid> | |||
| </Grid> | |||
| <div> | |||
| @@ -350,7 +350,7 @@ const ApplicationDetailCard = ({ | |||
| { | |||
| formik.values.groupType == "Private Bill" | |||
| ? | |||
| <Typography variant="h5">( {data.noOfPages} page x $6,552 )</Typography> | |||
| <Typography variant="h5">( {data.noOfPages} {data.noOfPages === 1 ? 'page' : 'pages'} x $6,552 )</Typography> | |||
| : | |||
| <Typography variant="h5">( {data.length} cm x {data.colCount == 2 ? "$364 Double Column" : "$182 Single Column"} )</Typography> | |||
| } | |||
| @@ -1,19 +1,16 @@ | |||
| // material-ui | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| import * as React from 'react'; | |||
| import { useEffect } from "react"; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| Box, | |||
| Stack | |||
| } from '@mui/material'; | |||
| import {useIntl} from "react-intl"; | |||
| import { createDeleteFileColumn } from 'utils/fileListColumns'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UploadFileTable({recordList, setRecordList,}) { | |||
| @@ -52,26 +49,10 @@ export default function UploadFileTable({recordList, setRecordList,}) { | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| } | |||
| const deleteColumn = createDeleteFileColumn((id) => handleCancelClick(id)); | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({id}) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon/>} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="error" | |||
| />] | |||
| }, | |||
| }, | |||
| deleteColumn, | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| @@ -70,7 +70,7 @@ const ApplicationDetailCard = ({ formData, }) => { | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <Typography variant="h4" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||
| <Typography variant="h4" component="h2" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||
| <FormattedMessage id="publicNoticePaymentProofInfo" /> | |||
| </Typography> | |||
| <form> | |||
| @@ -262,12 +262,12 @@ const ApplicationDetailCard = ({ formData, }) => { | |||
| <> | |||
| <Grid item xs={12} md={12} lg={12} | |||
| sx={{ display: 'flex', alignItems: 'center' }}> | |||
| <Typography variant="h5" display="inline"> | |||
| <Typography variant="h5" component="span" 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">  | |||
| <Typography variant="h5" component="span">  | |||
| {locale === 'en' ? | |||
| `${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.reviseDeadline, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||
| : | |||
| @@ -278,12 +278,12 @@ const ApplicationDetailCard = ({ formData, }) => { | |||
| <Grid item xs={12} md={12} lg={12} | |||
| sx={{ display: 'flex', alignItems: 'center' }}> | |||
| <Typography variant="h5" display="inline"> | |||
| <Typography variant="h5" component="span" 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">  | |||
| <Typography variant="h5" component="span">  | |||
| {locale === 'en' ? | |||
| `${intl.formatMessage({ id: 'before' })} ${DateUtils.dateFormat(data?.expiryDate, intl.formatMessage({ id: "paymentMethodDatetimeStrFormat" }))?.replace("am", "a.m.")?.replace("pm", "p.m.")} ` | |||
| : | |||
| @@ -304,14 +304,14 @@ const ApplicationDetailCard = ({ formData, }) => { | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12} sm={9} md={9} lg={9} sx={{ mb: 1, display: 'flex', alignItems: 'center' }}> | |||
| <Typography variant="h4" style={{ color: "#0049B8", fontWeight: "bold", }}>{FormatUtils.currencyFormat(data.fee)}</Typography> | |||
| <Typography variant="h4" component="span" style={{ color: "#0049B8", fontWeight: "bold", }}>{FormatUtils.currencyFormat(data.fee)}</Typography> | |||
| </Grid> | |||
| <Grid item xs={12} md={9} lg={9} sx={{ mb: 4, display: 'flex', alignItems: 'center' }}> | |||
| { | |||
| formik.values.groupType === "Private Bill" | |||
| ? | |||
| <Typography> | |||
| <Typography variant="pnspsFormParagraph">( {data.noOfPages} {intl.formatMessage({ id: 'page' })} x $6,552 )</Typography> | |||
| <Typography variant="pnspsFormParagraph">( {data.noOfPages} {intl.formatMessage({ id: data.noOfPages === 1 ? 'page' : 'pages' })} x $6,552 )</Typography> | |||
| </Typography> | |||
| : | |||
| <Typography> | |||
| @@ -24,6 +24,7 @@ import * as DateUtils from "utils/DateUtils" | |||
| import Loadable from 'components/Loadable'; | |||
| import { notifyActionSuccess } from 'utils/CommonFunction'; | |||
| import { PNSPS_BUTTON_THEME } from "themes/buttonConst"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| import { ThemeProvider } from "@emotion/react"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import { | |||
| @@ -251,7 +252,7 @@ const FormPanel = ({ formData }) => { | |||
| border={false} | |||
| content={false}> | |||
| <Typography variant="h4" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||
| <Typography variant="h4" component="h2" sx={{ textAlign: "left", mb: 2, borderBottom: "1px solid black" }}> | |||
| <FormattedMessage id="publicNoticePaymentProofComment" /> | |||
| </Typography> | |||
| @@ -261,7 +262,7 @@ const FormPanel = ({ formData }) => { | |||
| formik.values.replyDate ? | |||
| <Grid container direction="column" sx={{ paddingLeft: 0, paddingRight: 0 }}> | |||
| <Grid item xs={12} sm={12} md={12} lg={8} textAlign="left"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="proofReplyDate" /> : | |||
| { | |||
| locale === 'en' ? | |||
| @@ -272,7 +273,7 @@ const FormPanel = ({ formData }) => { | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} textAlign="left"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="proofReply" /> : {formik.values.action ? | |||
| (<span style={{ color: 'green' }}> | |||
| <FormattedMessage id="proofErrorFree" /> | |||
| @@ -284,7 +285,7 @@ const FormPanel = ({ formData }) => { | |||
| </Typography> | |||
| </Grid> | |||
| {/* <Grid item xs={12} md={12} textAlign="left"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="proofReply" /> : | |||
| <span style={{ color: 'green' }}> | |||
| { | |||
| @@ -321,7 +322,7 @@ const FormPanel = ({ formData }) => { | |||
| isOverTime() ? | |||
| <Grid container direction="column" sx={{ paddingLeft: 0, paddingRight: 0 }} spacing={1}> | |||
| <Grid item xs={12} md={12} textAlign="left"> | |||
| <Typography variant="h5"><FormattedMessage id="MSG.proofOutOfTime" /></Typography> | |||
| <Typography variant="h5" component="span"><FormattedMessage id="MSG.proofOutOfTime" /></Typography> | |||
| </Grid> | |||
| </Grid> | |||
| : | |||
| @@ -380,7 +381,7 @@ const FormPanel = ({ formData }) => { | |||
| <li><FormattedMessage id="store" /></li> | |||
| <li><FormattedMessage id="post" /></li> | |||
| </ul> | |||
| <Typography variant="h6"> | |||
| <Typography variant="h6" component="span"> | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} /> | |||
| </Typography> | |||
| </> | |||
| @@ -534,7 +535,7 @@ const FormPanel = ({ formData }) => { | |||
| <li><FormattedMessage id="store" /></li> | |||
| <li><FormattedMessage id="post" /></li> | |||
| </ul> | |||
| <Typography variant="h6"> | |||
| <Typography variant="h6" component="span"> | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} /> | |||
| </Typography> | |||
| </> | |||
| @@ -597,13 +598,13 @@ const FormPanel = ({ formData }) => { | |||
| </Grid> | |||
| } | |||
| {/* <Grid item xs={12}> | |||
| <Typography variant="h6" height="100%" > | |||
| <Typography variant="h6" component="span" height="100%" > | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} /> | |||
| </Typography> | |||
| </Grid> */} | |||
| {!isOnlyOnlinePayment? | |||
| <Grid item xs={12}> | |||
| <Typography variant="h6" height="100%" > | |||
| <Typography variant="h6" component="span" height="100%" > | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofImportant" }) }} /> | |||
| </Typography> | |||
| </Grid>:null | |||
| @@ -617,14 +618,14 @@ const FormPanel = ({ formData }) => { | |||
| { | |||
| isOverReviseDeadline() ? | |||
| <Grid item xs={12} md={12} textAlign="left"> | |||
| <Typography variant="h5" style={{ color: "red" }}> | |||
| <Typography variant="h5" component="span" style={{ color: "red" }}> | |||
| <FormattedMessage id="MSG.overReviseDeadline" /> | |||
| </Typography> | |||
| </Grid> | |||
| : | |||
| <> | |||
| <Grid item xs={12} md={12} textAlign="left"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="requiredUploadFix" />: | |||
| </Typography> | |||
| </Grid> | |||
| @@ -632,10 +633,10 @@ const FormPanel = ({ formData }) => { | |||
| <Grid item xs={12} md={12} textAlign="left"> | |||
| <ThemeProvider theme={PNSPS_BUTTON_THEME}> | |||
| <Button | |||
| color="save" | |||
| variant="contained" | |||
| type="button" | |||
| aria-label={intl.formatMessage({ id: 'upload' })} | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| disabled={attachments.length >= (formik.values.groupType === "Private Bill" ? 2 : 1)} | |||
| onClick={() => { | |||
| if (fileInputRef.current) { | |||
| @@ -683,7 +684,7 @@ const FormPanel = ({ formData }) => { | |||
| <Grid item xs={12} sm={12} md={12} lg={12}> | |||
| <Stack direction="row" alignItems="center"> | |||
| <FormLabel sx={{ paddingRight: 2, paddingBottom: 3, textAlign: "center" }}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="sign" />: | |||
| </Typography> | |||
| </FormLabel> | |||
| @@ -718,9 +719,9 @@ const FormPanel = ({ formData }) => { | |||
| disabled={(actionValue == false && isOverReviseDeadline()) || isSubmitting} | |||
| aria-label={intl.formatMessage({ id: 'submitReply' })} | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| {isSubmitting ? <FormattedMessage id="loading" /> : <FormattedMessage id="submitReply" />} | |||
| @@ -753,7 +754,7 @@ const FormPanel = ({ formData }) => { | |||
| {warningTitle} | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Typography variant="h5" style={{ padding: '16px' }}>{warningText}</Typography> | |||
| <Typography variant="h5" component="span" style={{ padding: '16px' }}>{warningText}</Typography> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button | |||
| @@ -2,18 +2,15 @@ | |||
| import * as React from 'react'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import {useEffect} from "react"; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| Stack, useMediaQuery | |||
| } from '@mui/material'; | |||
| import {useTheme} from "@emotion/react"; | |||
| import {useIntl} from "react-intl"; | |||
| import { createDeleteFileColumn } from 'utils/fileListColumns'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UploadFileTable({recordList, setRecordList,}) { | |||
| @@ -54,26 +51,10 @@ export default function UploadFileTable({recordList, setRecordList,}) { | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| } | |||
| const deleteColumn = createDeleteFileColumn((id) => handleCancelClick(id)); | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({id}) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon/>} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="error" | |||
| />] | |||
| }, | |||
| }, | |||
| deleteColumn, | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| @@ -86,7 +86,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Proof</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Proof</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -33,6 +33,7 @@ import { ThemeProvider } from "@emotion/react"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import { useState, useEffect, useRef } from 'react'; | |||
| import { checkPaymentSuspension } from "utils/Utils"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| @@ -457,7 +458,7 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => | |||
| <li><FormattedMessage id="store" /></li> | |||
| <li><FormattedMessage id="post" /></li> | |||
| </ul> | |||
| <Typography variant="h6"> | |||
| <Typography variant="h6" component="span"> | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "proofNote" }) }} /> | |||
| </Typography> | |||
| </> | |||
| @@ -545,8 +546,9 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => | |||
| <Button | |||
| aria-label={intl.formatMessage({ id: 'uploadFileBtn' })} | |||
| component="span" | |||
| variant="outlined" | |||
| variant="contained" | |||
| size="large" | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| >{attachment ? intl.formatMessage({ id: 'uploadFileBtn' }) : intl.formatMessage({ id: 'reUpload' })}</Button> | |||
| </label> | |||
| </Grid> | |||
| @@ -627,7 +629,7 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => | |||
| "aria-label": intl.formatMessage({ id: "applyTickStr" }) | |||
| }} | |||
| /> | |||
| <Typography variant="h6" height="100%" > | |||
| <Typography variant="h6" component="span" height="100%" > | |||
| <div style={{ padding: 12, textAlign: 'justify' }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "applyTickStr" }) }} /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -650,7 +652,7 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Typography variant="h6" height="100%" > | |||
| <Typography variant="h6" component="span" height="100%" > | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "applyPublicNoticeText" }) }} /> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -676,7 +678,7 @@ const PublicNoticeApplyForm = ({ loadedData, _selections, gazetteIssueList }) => | |||
| {warningTitle} | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Typography variant="h5" style={{ padding: '16px' }}> | |||
| <Typography variant="h5" component="span" style={{ padding: '16px' }}> | |||
| {warningText} | |||
| </Typography> | |||
| </DialogContent> | |||
| @@ -749,9 +749,9 @@ const ApplicationDetailCard = ( | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end', | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| <DownloadIcon /> | |||
| @@ -40,6 +40,7 @@ import CloseIcon from '@mui/icons-material/Close'; | |||
| import EditNoteIcon from '@mui/icons-material/EditNote'; | |||
| import DownloadIcon from '@mui/icons-material/Download'; | |||
| import { PNSPS_BUTTON_THEME } from "../../../themes/buttonConst"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| import { ThemeProvider } from "@emotion/react"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| @@ -239,9 +240,9 @@ const ApplicationDetailCard = ( | |||
| startIcon={<CloseIcon />} | |||
| aria-label={intl.formatMessage({ id: 'cancelApp' })} | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="cancelApp" /> | |||
| @@ -253,7 +254,7 @@ const ApplicationDetailCard = ( | |||
| </div> | |||
| :null | |||
| } | |||
| <Typography variant="h4" sx={{ mb: 2, borderBottom: "1px solid black" }}> | |||
| <Typography variant="h4" component="h3" sx={{ mb: 2, borderBottom: "1px solid black" }}> | |||
| <FormattedMessage id="publicNoticeDetailTitle" /> | |||
| </Typography> | |||
| <form> | |||
| @@ -665,9 +666,9 @@ const ApplicationDetailCard = ( | |||
| <Button | |||
| sx={{ | |||
| ml: 3, | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| variant="contained" | |||
| onClick={onDownloadClick()} | |||
| @@ -752,30 +753,34 @@ const ApplicationDetailCard = ( | |||
| }} | |||
| > | |||
| <DialogTitle> | |||
| <Typography variant="h3" > | |||
| <Typography variant="h3" component="span"> | |||
| <FormattedMessage id="payConfirm" /> | |||
| </Typography> | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Stack direction="column" justifyContent="space-between"> | |||
| <Typography variant="h4"> | |||
| <Typography variant="h4" component="span"> | |||
| <FormattedMessage id="totalAmount" /> ($): {FormatUtils.currencyFormat(fee)} | |||
| </Typography> | |||
| </Stack> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button | |||
| variant="contained" | |||
| onClick={() => setIsPopUp(false)} | |||
| aria-label={intl.formatMessage({ id: 'close' })} | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| > | |||
| <Typography variant="pnspsFormParagraph"> | |||
| <Typography variant="pnspsFormParagraph" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="close" /> | |||
| </Typography></Button> | |||
| <Button | |||
| variant="contained" | |||
| onClick={() => doPayment()} | |||
| aria-label={intl.formatMessage({ id: 'confirm' })} | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| > | |||
| <Typography variant="pnspsFormParagraph"> | |||
| <Typography variant="pnspsFormParagraph" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="confirm" /> | |||
| </Typography></Button> | |||
| </DialogActions> | |||
| @@ -794,7 +799,7 @@ const ApplicationDetailCard = ( | |||
| }} | |||
| > | |||
| <DialogTitle></DialogTitle> | |||
| <Typography variant="h2" style={{ padding: '16px' }}><FormattedMessage id="MSG.actionFail" /></Typography> | |||
| <Typography variant="h2" component="span" style={{ padding: '16px' }}><FormattedMessage id="MSG.actionFail" /></Typography> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Stack direction="column" justifyContent="space-between"> | |||
| { | |||
| @@ -826,7 +831,7 @@ const ApplicationDetailCard = ( | |||
| }} | |||
| > | |||
| <DialogTitle></DialogTitle> | |||
| <Typography variant="h4" style={{ paddingLeft: '24px' }}><FormattedMessage id="MSG.actionFail" /></Typography> | |||
| <Typography variant="h4" component="span" style={{ paddingLeft: '24px' }}><FormattedMessage id="MSG.actionFail" /></Typography> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Stack direction="column" justifyContent="space-between"> | |||
| <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: 'MSG.paymentHolded' }, { appNo: paymentHoldedErrText }) }} /> | |||
| @@ -834,7 +839,7 @@ const ApplicationDetailCard = ( | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button onClick={() => setPaymentHoldedErr(false)} aria-label={intl.formatMessage({ id: 'close' })}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="close" /> | |||
| </Typography></Button> | |||
| </DialogActions> | |||
| @@ -34,6 +34,7 @@ import ForwardIcon from '@mui/icons-material/Forward'; | |||
| import { notifyActionSuccess } from "utils/CommonFunction"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import usePageTitle from "components/usePageTitle"; | |||
| import { PRIMARY_OUTLINED_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| Body - DEFAULT ||============================== // | |||
| const DashboardDefault = () => { | |||
| @@ -190,7 +191,7 @@ const DashboardDefault = () => { | |||
| <Button | |||
| aria-label={intl.formatMessage({ id: 'back' })} | |||
| title={intl.formatMessage({ id: 'back' })} | |||
| sx={{ ml: 0, mt: 2.5 }} style={{ border: '2px solid' }} | |||
| sx={{ ml: 0, mt: 2.5, borderWidth: '2px', ...PRIMARY_OUTLINED_BUTTON_SX }} | |||
| variant="outlined" onClick={() => { navigate("/publicNotice") }} | |||
| > | |||
| <ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} /> | |||
| @@ -15,6 +15,7 @@ import { | |||
| import {useTheme} from "@emotion/react"; | |||
| import {getStatusIntl,getModeIntl } from "utils/statusUtils/PublicNoteStatusUtils"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import { PRIMARY_TEXT_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| @@ -106,7 +107,7 @@ export default function BaseGrid({setCount, url}) { | |||
| renderHeader: renderHeaderWithAria, | |||
| cellClassName: 'actions', | |||
| renderCell: (params) => { | |||
| return <Button aria-label={intl.formatMessage({id: 'viewDetail'})} onClick={handleDetailClick(params)}> | |||
| return <Button aria-label={intl.formatMessage({id: 'viewDetail'})} onClick={handleDetailClick(params)} sx={PRIMARY_TEXT_BUTTON_SX}> | |||
| <FormattedMessage id="viewDetail"/> | |||
| </Button>; | |||
| }, | |||
| @@ -29,6 +29,7 @@ import { | |||
| import { ThemeProvider, useTheme } from "@emotion/react"; | |||
| import { PNSPS_BUTTON_THEME } from "../../../themes/buttonConst"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import { PRIMARY_TEXT_BUTTON_SX, PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function SubmittedTab({ setCount, url }) { | |||
| @@ -309,7 +310,7 @@ export default function SubmittedTab({ setCount, url }) { | |||
| renderHeader: renderHeaderWithAria, | |||
| cellClassName: 'actions', | |||
| renderCell: (params) => { | |||
| return <Button aria-label={intl.formatMessage({ id: 'viewDetail' })} onClick={handleDetailClick(params)}> | |||
| return <Button aria-label={intl.formatMessage({ id: 'viewDetail' })} onClick={handleDetailClick(params)} sx={PRIMARY_TEXT_BUTTON_SX}> | |||
| <FormattedMessage id="viewDetail" /> | |||
| </Button>; | |||
| }, | |||
| @@ -484,13 +485,13 @@ export default function SubmittedTab({ setCount, url }) { | |||
| </Stack> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button onClick={() => setIsPopUp(false)} aria-label={intl.formatMessage({ id: 'close' })}> | |||
| <Typography variant="h5"> | |||
| <Button variant="contained" onClick={() => setIsPopUp(false)} aria-label={intl.formatMessage({ id: 'close' })} sx={PRIMARY_CONTAINED_BUTTON_SX}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="close" /> | |||
| </Typography></Button> | |||
| <Button onClick={() => doPayment()} aria-label={intl.formatMessage({ id: 'confirm' })}> | |||
| <Typography variant="h5"> | |||
| <Button variant="contained" onClick={() => doPayment()} aria-label={intl.formatMessage({ id: 'confirm' })} sx={PRIMARY_CONTAINED_BUTTON_SX}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="confirm" /> | |||
| </Typography></Button> | |||
| </DialogActions> | |||
| @@ -17,6 +17,7 @@ import {getModeIntl } from "utils/statusUtils/PublicNoteStatusUtils"; | |||
| import { useTheme } from "@emotion/react"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import * as React from 'react'; | |||
| import { PRIMARY_TEXT_BUTTON_SX } from "themes/colorConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnReady, applySearch }) { | |||
| @@ -139,6 +140,7 @@ export default function SearchPublicNoticeTable({ searchCriteria, applyGridOnRea | |||
| renderCell: (params) => { | |||
| return <Button onClick={handleDetailClick(params)} | |||
| aria-label={intl.formatMessage({ id: 'viewDetail' })} | |||
| sx={PRIMARY_TEXT_BUTTON_SX} | |||
| > | |||
| <FormattedMessage id="viewDetail" /> | |||
| </Button>; | |||
| @@ -84,7 +84,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Application</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Application</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -84,7 +84,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Mark Payment</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Mark Payment</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -125,7 +125,7 @@ const Index = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| Recon Report | |||
| </Typography> | |||
| </Stack> | |||
| @@ -74,7 +74,7 @@ const ReportSearchPage = () => { | |||
| <Grid item xs={12} mb={2}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Gazette Notice Full List</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Gazette Notice Full List</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -74,7 +74,7 @@ const ReportSearchPage = () => { | |||
| <Grid item xs={12} mb={2}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>Summary of Gazette Notice</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>Summary of Gazette Notice</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -14,6 +14,7 @@ import { notifyActionError } from 'utils/CommonFunction'; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| import { PRIMARY_OUTLINED_BUTTON_SX } from 'themes/colorConst'; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| @@ -168,6 +169,7 @@ const Index = () => { | |||
| component="span" | |||
| variant="outlined" | |||
| size="large" | |||
| sx={PRIMARY_OUTLINED_BUTTON_SX} | |||
| >Import DR Excel</Button> | |||
| </label> | |||
| </Grid> | |||
| @@ -199,6 +201,7 @@ const Index = () => { | |||
| component="span" | |||
| variant="outlined" | |||
| size="large" | |||
| sx={PRIMARY_OUTLINED_BUTTON_SX} | |||
| >Import Offline Mode Application</Button> | |||
| </label> | |||
| </Grid> | |||
| @@ -0,0 +1,101 @@ | |||
| import * as React from "react"; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import * as DateUtils from "utils/DateUtils"; | |||
| import * as UrlUtils from "utils/ApiPathConst"; | |||
| import { | |||
| Grid, Typography, Button, | |||
| Stack, Box, CircularProgress, | |||
| } from '@mui/material'; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| const formatLog = (responData) => { | |||
| if (responData?.msg && !responData?.log) { | |||
| return <>{DateUtils.datetimeStr(new Date())}<br/><span style={{ color: "red" }}>Error</span><br/>{responData.msg}</>; | |||
| } | |||
| const statusColor = responData?.success ? "green" : "red"; | |||
| const statusText = responData?.success ? "Success" : "Completed with errors"; | |||
| const logText = (responData?.log || []).join("\n"); | |||
| return ( | |||
| <> | |||
| {DateUtils.datetimeStr(new Date())}<br/> | |||
| <span style={{ color: statusColor }}>{responData?.dryRun ? "Dry-run " : ""}{statusText}</span><br/> | |||
| Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||
| </> | |||
| ); | |||
| }; | |||
| const HkidKeyMigration = () => { | |||
| const [resultStr, setResultStr] = React.useState(""); | |||
| const [wait, setWait] = React.useState(false); | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: 'auto', | |||
| height: 'auto', | |||
| backgroundSize: 'contain', | |||
| backgroundRepeat: 'no-repeat', | |||
| backgroundColor: '#0C489E', | |||
| backgroundPosition: 'right' | |||
| }; | |||
| const runMigration = (dryRun) => { | |||
| setWait(true); | |||
| HttpUtils.post({ | |||
| url: `${UrlUtils.HKID_REKEY_MIGRATION}?dryRun=${dryRun}&batchSize=100`, | |||
| params: {}, | |||
| onSuccess: function (responData) { | |||
| setWait(false); | |||
| setResultStr(formatLog(responData)); | |||
| }, | |||
| onError: function () { | |||
| setWait(false); | |||
| notifyActionError("HKID re-key migration failed"); | |||
| } | |||
| }); | |||
| }; | |||
| return ( | |||
| <Grid container sx={{ minHeight: '87vh', backgroundColor: "backgroundColor.default" }} direction="column"> | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="space-between" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}> | |||
| HKID Key Migration | |||
| </Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1 }} width="98%"> | |||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||
| <Typography variant="body1" sx={{ mb: 2 }}> | |||
| Re-encrypt identification and checkDigit from the legacy key to the new key. | |||
| Ensure Tomcat has both <code>security.hkid-secret</code> and <code>security.hkid-secret-legacy</code> configured before running. | |||
| </Typography> | |||
| <Stack direction="row" spacing={2}> | |||
| <Button variant="outlined" size="large" disabled={wait} onClick={() => runMigration(true)}> | |||
| Dry Run | |||
| </Button> | |||
| <Button variant="contained" size="large" disabled={wait} onClick={() => runMigration(false)}> | |||
| Run Migration | |||
| </Button> | |||
| {wait ? <CircularProgress size={32} /> : null} | |||
| </Stack> | |||
| </Box> | |||
| </Grid> | |||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1, mb: 2 }} width="98%"> | |||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||
| <Typography variant="h4">Result:</Typography> | |||
| <Box sx={{ pl: 2, pt: 2 }}>{resultStr}</Box> | |||
| </Box> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default HkidKeyMigration; | |||
| @@ -0,0 +1,133 @@ | |||
| import * as React from "react"; | |||
| import * as HttpUtils from "utils/HttpUtils"; | |||
| import * as DateUtils from "utils/DateUtils"; | |||
| import * as UrlUtils from "utils/ApiPathConst"; | |||
| import { | |||
| Grid, Typography, Button, | |||
| Stack, Box, CircularProgress, | |||
| } from '@mui/material'; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import titleBackgroundImg from 'assets/images/dashboard/gazette-bar.png' | |||
| const formatEncryptLog = (responData) => { | |||
| if (responData?.msg && !responData?.log) { | |||
| return <>{DateUtils.datetimeStr(new Date())}<br/><span style={{ color: "red" }}>Error</span><br/>{responData.msg}</>; | |||
| } | |||
| const statusColor = responData?.success ? "green" : "red"; | |||
| const statusText = responData?.success ? "Success" : "Completed with errors"; | |||
| const logText = (responData?.log || []).join("\n"); | |||
| return ( | |||
| <> | |||
| {DateUtils.datetimeStr(new Date())}<br/> | |||
| <span style={{ color: statusColor }}>{responData?.dryRun ? "Dry-run " : ""}{statusText}</span><br/> | |||
| Total: {responData?.total ?? 0}, OK: {responData?.successCount ?? 0}, Skipped: {responData?.skipped ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||
| </> | |||
| ); | |||
| }; | |||
| const formatVerifyLog = (responData) => { | |||
| const tests = responData?.tests || []; | |||
| const logText = tests.map(t => `${t.passed ? "PASS" : "FAIL"} - ${t.name}: ${t.message}`).join("\n"); | |||
| const statusColor = responData?.success ? "green" : "red"; | |||
| return ( | |||
| <> | |||
| {DateUtils.datetimeStr(new Date())}<br/> | |||
| <span style={{ color: statusColor }}>{responData?.success ? "All tests passed" : "Some tests failed"}</span><br/> | |||
| Passed: {responData?.passed ?? 0}, Failed: {responData?.failed ?? 0}<br/> | |||
| <span style={{ whiteSpace: "pre-line" }}>{logText}</span> | |||
| </> | |||
| ); | |||
| }; | |||
| const UserPiiEncryption = () => { | |||
| const [resultStr, setResultStr] = React.useState(""); | |||
| const [wait, setWait] = React.useState(false); | |||
| const BackgroundHead = { | |||
| backgroundImage: `url(${titleBackgroundImg})`, | |||
| width: 'auto', | |||
| height: 'auto', | |||
| backgroundSize: 'contain', | |||
| backgroundRepeat: 'no-repeat', | |||
| backgroundColor: '#0C489E', | |||
| backgroundPosition: 'right' | |||
| }; | |||
| const runEncrypt = (dryRun) => { | |||
| setWait(true); | |||
| HttpUtils.post({ | |||
| url: `${UrlUtils.USER_PII_ENCRYPT_MIGRATION}?dryRun=${dryRun}&batchSize=100`, | |||
| params: {}, | |||
| onSuccess: function (responData) { | |||
| setWait(false); | |||
| setResultStr(formatEncryptLog(responData)); | |||
| }, | |||
| onError: function () { | |||
| setWait(false); | |||
| notifyActionError("User PII encryption failed"); | |||
| } | |||
| }); | |||
| }; | |||
| const runVerify = () => { | |||
| setWait(true); | |||
| HttpUtils.post({ | |||
| url: UrlUtils.USER_PII_VERIFY_MIGRATION, | |||
| params: {}, | |||
| onSuccess: function (responData) { | |||
| setWait(false); | |||
| setResultStr(formatVerifyLog(responData)); | |||
| }, | |||
| onError: function () { | |||
| setWait(false); | |||
| notifyActionError("User PII verification failed"); | |||
| } | |||
| }); | |||
| }; | |||
| return ( | |||
| <Grid container sx={{ minHeight: '87vh', backgroundColor: "backgroundColor.default" }} direction="column"> | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="space-between" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ textShadow: "0px 0px 25px #0C489E" }}> | |||
| User PII Encryption | |||
| </Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1 }} width="98%"> | |||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||
| <Typography variant="body1" sx={{ mb: 2 }}> | |||
| Encrypt enName, chName, mobileNumber, and address for existing user records, then verify data retrieval. | |||
| </Typography> | |||
| <Stack direction="row" spacing={2} flexWrap="wrap"> | |||
| <Button variant="outlined" size="large" disabled={wait} onClick={() => runEncrypt(true)}> | |||
| Dry Run Encrypt | |||
| </Button> | |||
| <Button variant="contained" size="large" disabled={wait} onClick={() => runEncrypt(false)}> | |||
| Run Encrypt | |||
| </Button> | |||
| <Button variant="contained" color="secondary" size="large" disabled={wait} onClick={runVerify}> | |||
| Verify Retrieval | |||
| </Button> | |||
| {wait ? <CircularProgress size={32} /> : null} | |||
| </Stack> | |||
| </Box> | |||
| </Grid> | |||
| <Grid item xs={12} sx={{ backgroundColor: '#ffffff', ml: 2, mt: 1, mb: 2 }} width="98%"> | |||
| <Box sx={{ borderRadius: '10px', backgroundColor: '#fff', p: 4 }}> | |||
| <Typography variant="h4">Result:</Typography> | |||
| <Box sx={{ pl: 2, pt: 2 }}>{resultStr}</Box> | |||
| </Box> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserPiiEncryption; | |||
| @@ -215,13 +215,13 @@ const Index = () => { | |||
| <Grid container spacing={4} sx={{ minHeight: {xs:"80vh", sm:"50vh", md: "50vh", lg:"70vh", xl:"50vh"} }} direction="column" justifyContent="flex-start" alignItems="center"> | |||
| {isPasswordExpiry()? | |||
| <Grid item width="70%" xs={12} md={12} lg={12} sx={{ mb: 1, mt:2 }}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="passwordExpired"/> | |||
| </Typography> | |||
| </Grid> | |||
| : | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:2 }}> | |||
| <Typography variant="h5" > | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="setNewPassword"/> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -433,14 +433,14 @@ const Index = () => { | |||
| <DialogTitle></DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Stack direction="column" justifyContent="space-between"> | |||
| <Typography variant="h5" style={{ padding: '10px' }}> | |||
| <Typography variant="h5" component="span" style={{ padding: '10px' }}> | |||
| <FormattedMessage id ="changePasswordConfirm"/> | |||
| </Typography> | |||
| </Stack> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button disabled={isChangingPassword} onClick={() => setComfirmChangeMessage(false)}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="close"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -449,7 +449,7 @@ const Index = () => { | |||
| onClick={() => goLogin(changePasswordValues)} | |||
| startIcon={isChangingPassword ? <CircularProgress color="inherit" size={18} /> : null} | |||
| > | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="confirm"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -468,13 +468,13 @@ const Index = () => { | |||
| }} | |||
| > | |||
| <DialogTitle> | |||
| <Typography variant="h5" style={{ padding: '10px' }}> | |||
| <Typography variant="h5" component="span" style={{ padding: '10px' }}> | |||
| <FormattedMessage id ="MSG.actionFail"/> | |||
| </Typography> | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Stack direction="column" justifyContent="space-between"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| { | |||
| expiryErrText | |||
| } | |||
| @@ -483,7 +483,7 @@ const Index = () => { | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button onClick={() => setExpiryErr(false)}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="close"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -498,13 +498,13 @@ const Index = () => { | |||
| <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} /> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="resetPasswordSuccess"/> | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5,}}> | |||
| <Button color="success" variant="outlined" onClick={()=>logout()}> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="backToLogin"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -242,7 +242,7 @@ const UserMaintainPage = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>{isNewRecord ? "Create GLD User" : "Maintain GLD User"}</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>{isNewRecord ? "Create GLD User" : "Maintain GLD User"}</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -17,6 +17,7 @@ import * as ComboData from "utils/ComboData"; | |||
| const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingComponent'))); | |||
| import Loadable from 'components/Loadable'; | |||
| import { notifyActiveSuccess, notifyLockSuccess, notifySaveSuccess, notifyVerifySuccess } from 'utils/CommonFunction'; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from 'themes/colorConst'; | |||
| import { useIntl } from "react-intl"; | |||
| import { PNSPS_BUTTON_THEME } from "themes/buttonConst"; | |||
| import { ThemeProvider } from "@emotion/react"; | |||
| @@ -80,7 +81,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| addressLine3: yup.string().max(40, getMaxErrStr(40)).nullable(), | |||
| emailAddress: yup.string().email(intl.formatMessage({ id: 'validEmailFormat' })).max(255).required(intl.formatMessage({ id: 'requireEmail' })), | |||
| idDocType: yup.string().max(255, getMaxErrStr(255)).required(intl.formatMessage({ id: 'requireIdDocType' })), | |||
| identification: yup.string().required(getRequiredErrStr('number')) | |||
| identification: yup.string().when('verifiedBy', { | |||
| is: (verifiedBy) => verifiedBy != null, | |||
| then: (schema) => schema.notRequired(), | |||
| otherwise: (schema) => schema.required(getRequiredErrStr('number')) | |||
| .matches(/^[aA-zZ0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | |||
| .matches(/^\S*$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpace' })}`) }) | |||
| .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredValid' })}${selectedIdDocInputType}${intl.formatMessage({ id: 'number' })}`), function (value) { | |||
| @@ -132,8 +136,12 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| break; | |||
| } | |||
| } | |||
| }) | |||
| }), | |||
| checkDigit: yup.string().max(1, getMaxErrStr(1)).nullable() | |||
| checkDigit: yup.string().when('verifiedBy', { | |||
| is: (verifiedBy) => verifiedBy != null, | |||
| then: (schema) => schema.notRequired(), | |||
| otherwise: (schema) => schema.max(1, getMaxErrStr(1)).nullable() | |||
| .matches(/^[A-Z0-9\s]+$/, { message: displayErrorMsg(`${selectedIdDocInputType}${intl.formatMessage({ id: 'noSpecialCharacter' })}`) }) | |||
| .test('checkIDCardFormat', displayErrorMsg(`${intl.formatMessage({ id: 'requiredNumberInQuote' })}`), function (value) { | |||
| // console.log(selectedIdDocInputType) | |||
| @@ -161,7 +169,8 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| return false | |||
| } | |||
| } | |||
| }), | |||
| }) | |||
| }), | |||
| tel_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })).required(intl.formatMessage({ id: 'requireDialingCode' })), | |||
| fax_countryCode: yup.string().min(3, intl.formatMessage({ id: 'require3Number' })), | |||
| phoneNumber: yup.string().min(8, intl.formatMessage({ id: 'require8Number' })).required(intl.formatMessage({ id: 'requireContactNumber' })), | |||
| @@ -185,8 +194,10 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| countryCode: values.tel_countryCode, | |||
| phoneNumber: values.phoneNumber | |||
| }, | |||
| identification: values.identification, | |||
| checkDigit: values.checkDigit, | |||
| ...(values.verifiedBy == null ? { | |||
| identification: values.identification, | |||
| checkDigit: values.checkDigit, | |||
| } : {}), | |||
| faxNo: { | |||
| countryCode: values.fax_countryCode, | |||
| faxNumber: values.faxNumber | |||
| @@ -288,7 +299,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| <Button | |||
| variant="contained" | |||
| type="submit" | |||
| color="success" | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| > | |||
| Save | |||
| </Button> | |||
| @@ -470,6 +481,11 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| </Grid> | |||
| <Grid item xs={12} sm={12} md={9} lg={6}> | |||
| {currentUserData.verifiedBy ? | |||
| <Typography variant="h5" mt={1}> | |||
| Hidden for security purpose | |||
| </Typography> | |||
| : | |||
| <Grid container> | |||
| {formik.values.idDocType === "HKID" ? | |||
| editMode ? | |||
| @@ -548,6 +564,7 @@ const UserInformationCard_Individual = ({ formData, loadDataFun }) => { | |||
| </Stack> | |||
| } | |||
| </Grid> | |||
| } | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -2,8 +2,6 @@ | |||
| import { | |||
| Grid, Button, Typography, | |||
| FormHelperText, | |||
| Stack, | |||
| IconButton | |||
| } from '@mui/material'; | |||
| import MainCard from "components/MainCard"; | |||
| import * as React from "react"; | |||
| @@ -19,10 +17,10 @@ const LoadingComponent = Loadable(lazy(() => import('../../extra-pages/LoadingCo | |||
| import Loadable from 'components/Loadable'; | |||
| import { lazy } from 'react'; | |||
| import {notifySaveSuccess,} from 'utils/CommonFunction'; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from 'themes/colorConst'; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import {PNSPS_BUTTON_THEME} from "../../../themes/buttonConst"; | |||
| import {ThemeProvider} from "@emotion/react"; | |||
| import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons'; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| @@ -33,15 +31,6 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { | |||
| const [editMode, setEditMode] = useState(false); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [errorMsg, setErrorMsg] = useState(""); | |||
| const [showId, setshowId] = useState(false); | |||
| const handleClickShowId = () => { | |||
| setshowId(!showId); | |||
| }; | |||
| const handleMouseDownId = (event) => { | |||
| event.preventDefault(); | |||
| }; | |||
| useEffect(() => { | |||
| if (Object.keys(formData).length > 0) { | |||
| @@ -166,7 +155,7 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { | |||
| aria-label={intl.formatMessage({id: 'save'})} | |||
| variant="contained" | |||
| type="submit" | |||
| color="success" | |||
| sx={PRIMARY_CONTAINED_BUTTON_SX} | |||
| disabled={formik.isSubmitting} | |||
| > | |||
| <FormattedMessage id="save" /> | |||
| @@ -251,79 +240,9 @@ const UserInformationCard_Individual_Pub = ({ formData, loadDataFun }) => { | |||
| </Grid> | |||
| <Grid item xs={12} sm={12} md={9} lg={6}> | |||
| <Grid container> | |||
| {formik.values.idDocType === "HKID" ? | |||
| // <> | |||
| // <Grid item xs={6} sm={6} md={6} lg={7.5} sx={{mr:1}}> | |||
| // {FieldUtils.initField({ | |||
| // valueName: "identification", | |||
| // disabled: true, | |||
| // form: formik, | |||
| // placeholder: intl.formatMessage({id: 'idDocNumber'}), | |||
| // inputProps: { | |||
| // maxLength: 7, | |||
| // onKeyDown: (e) => { | |||
| // if (e.key === 'Enter') { | |||
| // e.preventDefault(); | |||
| // } | |||
| // }, | |||
| // } | |||
| // })} | |||
| // </Grid> | |||
| // <Grid item xs={2} sm={2} md={2} lg={2} style={{minWidth:40}}> | |||
| // {FieldUtils.initField({ | |||
| // valueName: "checkDigit", | |||
| // disabled: true, | |||
| // form: formik, | |||
| // })} | |||
| // </Grid> | |||
| // </> | |||
| <Stack direction="row"> | |||
| <Typography variant="h5" mt={1}> | |||
| {formik.values.identification?.slice(0, 4)} | |||
| </Typography> | |||
| <Typography variant="h5"mt={1}> | |||
| {/* {showId ?formik.values.identification.slice(4):"****"}{showId ? '(' + formik.values.checkDigit + ')' :null} */} | |||
| {showId ? formik.values.identification?.slice(4) : "****"}{showId ? formik.values.checkDigit?'(' +formik.values.checkDigit+ ')': "()" : ""} | |||
| </Typography> | |||
| <IconButton | |||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||
| onClick={handleClickShowId} | |||
| onMouseDown={handleMouseDownId} | |||
| edge="end" | |||
| size="large" | |||
| > | |||
| {showId ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||
| </IconButton> | |||
| </Stack> | |||
| : | |||
| // <Grid item xs={10} sm={4} md={4} lg={10}> | |||
| // {FieldUtils.initField({ | |||
| // valueName: "identification", | |||
| // disabled: true, | |||
| // form: formik | |||
| // })} | |||
| // </Grid> | |||
| <Stack direction="row"> | |||
| <Typography variant="h5" mt={1}> | |||
| {formik.values.identification?.slice(0, 4)} | |||
| </Typography> | |||
| <Typography variant="h5"mt={1}> | |||
| {showId ?formik.values.identification?.slice(4):"****"} | |||
| </Typography> | |||
| <IconButton | |||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||
| onClick={handleClickShowId} | |||
| onMouseDown={handleMouseDownId} | |||
| edge="end" | |||
| size="large" | |||
| > | |||
| {showId ? <EyeOutlined /> : <EyeInvisibleOutlined />} | |||
| </IconButton> | |||
| </Stack> | |||
| } | |||
| </Grid> | |||
| <Typography variant="h5" mt={1}> | |||
| {formik.values.identification?.slice(0, 4)} | |||
| </Typography> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -53,7 +53,14 @@ const ManageOrgUserPage = () => { | |||
| '& .MuiDataGrid-footerContainer': { | |||
| border: 1, | |||
| borderColor: "#EEE" | |||
| } | |||
| }, | |||
| "& .MuiDataGrid-columnHeaderTitle": { | |||
| whiteSpace: "normal", | |||
| lineHeight: "normal" | |||
| }, | |||
| "& .MuiDataGrid-columnHeader": { | |||
| height: "unset !important" | |||
| }, | |||
| } | |||
| const [_searchCriteria, set_searchCriteria] = React.useState({}); | |||
| @@ -78,9 +85,9 @@ const ManageOrgUserPage = () => { | |||
| }); | |||
| } | |||
| /** DataGrid `headerName` must be a string; use `renderHeader` for styled markup. */ | |||
| const renderStyledHeader = (params) => ( | |||
| <Typography variant="h5">{params.colDef.headerName}</Typography> | |||
| /** Match /proof/search grid column header styling (inherits MuiDataGrid columnHeader color). */ | |||
| const renderHeaderWithAria = (params) => ( | |||
| <span aria-label={params.colDef.headerName}>{params.colDef.headerName}</span> | |||
| ); | |||
| function getStatus(params) { | |||
| @@ -127,7 +134,7 @@ const ManageOrgUserPage = () => { | |||
| id: 'username', | |||
| field: 'username', | |||
| headerName: intl.formatMessage({ id: 'loginName' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| @@ -135,8 +142,8 @@ const ManageOrgUserPage = () => { | |||
| { | |||
| id: 'contactPerson', | |||
| field: 'contactPerson', | |||
| headerName: intl.formatMessage({ id: 'userName' }), | |||
| renderHeader: renderStyledHeader, | |||
| headerName: intl.formatMessage({ id: 'contactPerson' }), | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| @@ -145,7 +152,7 @@ const ManageOrgUserPage = () => { | |||
| id: 'contactTel', | |||
| field: 'contactTel', | |||
| headerName: intl.formatMessage({ id: 'userContactNumber' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| valueGetter: (params) => { | |||
| @@ -157,7 +164,7 @@ const ManageOrgUserPage = () => { | |||
| id: 'emailBus', | |||
| field: 'emailBus', | |||
| headerName: intl.formatMessage({ id: 'userContactEmail' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| }, | |||
| @@ -165,7 +172,7 @@ const ManageOrgUserPage = () => { | |||
| id: 'lastLogin', | |||
| field: 'lastLogin', | |||
| headerName: intl.formatMessage({ id: 'lastLoginDate' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| valueGetter: (params) => { | |||
| @@ -176,7 +183,7 @@ const ManageOrgUserPage = () => { | |||
| id: 'lastApply', | |||
| field: 'lastApply', | |||
| headerName: intl.formatMessage({ id: 'lastSubmissionDate' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| valueGetter: () => { | |||
| @@ -186,7 +193,7 @@ const ManageOrgUserPage = () => { | |||
| { | |||
| field: 'actions', | |||
| headerName: intl.formatMessage({ id: 'status' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| cellClassName: 'actions', | |||
| @@ -199,7 +206,7 @@ const ManageOrgUserPage = () => { | |||
| field: 'primaryUser', | |||
| type: 'bool', | |||
| headerName: intl.formatMessage({ id: 'primary' }), | |||
| renderHeader: renderStyledHeader, | |||
| renderHeader: renderHeaderWithAria, | |||
| width: isMdOrLg ? 'auto' : 160, | |||
| flex: isMdOrLg ? 1 : undefined, | |||
| renderCell: (params) => { | |||
| @@ -272,7 +279,7 @@ const ManageOrgUserPage = () => { | |||
| <FormattedMessage id="confirm" /> | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| <Typography variant="h5" style={{ padding: '16px' }}>{warningText}</Typography> | |||
| <Typography variant="h5" component="span" style={{ padding: '16px' }}>{warningText}</Typography> | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button onClick={() => { | |||
| @@ -92,7 +92,7 @@ const UserSettingPage = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>View GLD User</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>View GLD User</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -64,7 +64,7 @@ const UserSearchPage_Individual = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| View Individual User | |||
| </Typography> | |||
| </Stack> | |||
| @@ -68,7 +68,7 @@ const UserSearchPage_Organization = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>View Organisation User</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>View Organisation User</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -12,7 +12,8 @@ import { | |||
| Button, StepLabel, | |||
| CircularProgress, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| import { POST_USERNAME, POST_VERIFY_CAPTCHA } from "utils/ApiPathConst"; | |||
| import RegisterStepIcon, { registerStepStyle } from 'components/RegisterStepIcon'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| @@ -21,8 +22,8 @@ import { notifyActionError } from 'utils/CommonFunction'; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/BusCustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| import axios from "axios"; | |||
| import { POST_USERNAME, POST_VERIFY_CAPTCHA } from "utils/ApiPathConst"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| // import CustomFormWizard from './auth-forms/BusCustomFormWizard'; | |||
| // import AuthWrapper from './AuthWrapperCustom'; | |||
| @@ -37,6 +38,7 @@ const BusRegister = () => { | |||
| const [base64Url, setBase64Url] = useState("") | |||
| const [checkCode, setCheckCode] = useState("") | |||
| const [isNextBusy, setIsNextBusy] = useState(false); | |||
| const [registrationComplete, setRegistrationComplete] = useState(false); | |||
| const intl = useIntl(); | |||
| const steps = [ | |||
| intl.formatMessage({id: 'personalInformation'}), | |||
| @@ -44,30 +46,6 @@ const BusRegister = () => { | |||
| intl.formatMessage({id: 'finishSubmission'}) | |||
| ]; | |||
| const stepStyle = { | |||
| width: { lg: "40%", md: "70%", xs: "100%" }, | |||
| boxShadow: 1, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| /* Inactive (default) */ | |||
| "& .MuiStepIcon-root": { color: "#757575", fontSize: "2rem" }, // darker grey | |||
| "& .MuiStepLabel-label": { color: "#424242" }, // label darker | |||
| "& .MuiStepConnector-line": { borderColor: "#9E9E9E" }, // connector darker | |||
| /* Active */ | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { color: "warning.main", fontSize: "2rem" }, | |||
| "& .MuiStepConnector-line": { borderColor: "warning.main" } | |||
| }, | |||
| /* Completed */ | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { color: "#0C489E", fontSize: "2rem" }, // use your strong blue | |||
| "& .MuiStepConnector-line": { borderColor: "#0C489E" } | |||
| } | |||
| }; | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| @@ -147,51 +125,30 @@ const BusRegister = () => { | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| setRegistrationComplete(false); | |||
| }; | |||
| const isStepCompleted = (index) => index < activeStep || registrationComplete; | |||
| return ( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%', fontSize: '2rem', paddingTop: '35px', bgcolor: 'backgroundColor.default' }} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| <Stepper activeStep={activeStep} sx={registerStepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| {index < 2 ? ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| <StepLabel | |||
| sx={{ | |||
| flexDirection: "column", | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 }, | |||
| }} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| ) : ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| sx={ | |||
| activeStep === 2 | |||
| ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } | |||
| : allStepsCompleted() | |||
| ? { "& .MuiSvgIcon-root": { color: "#0C489E", fontSize: "2rem" } } | |||
| : { color: "rgba(0,0,0,0.6)" } | |||
| } | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| <Step key={label} completed={isStepCompleted(index)} readOnly={true}> | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| > | |||
| <StepLabel | |||
| StepIconComponent={RegisterStepIcon} | |||
| sx={{ | |||
| flexDirection: "column", | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 }, | |||
| }} | |||
| > | |||
| <StepLabel | |||
| sx={{ | |||
| flexDirection: "column", | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 }, | |||
| }} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| )} | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| @@ -215,6 +172,7 @@ const BusRegister = () => { | |||
| setUsername={setUsername} | |||
| setBase64Url={setBase64Url} | |||
| setCheckCode={setCheckCode} | |||
| onRegistrationComplete={() => setRegistrationComplete(true)} | |||
| /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| @@ -249,33 +207,33 @@ const BusRegister = () => { | |||
| {activeStep === totalSteps() - 2 ? | |||
| ( | |||
| <Button | |||
| variant="outlined" | |||
| variant="contained" | |||
| disabled={isNextBusy} | |||
| onClick={handleNext} | |||
| aria-busy={isNextBusy} | |||
| sx={{ mr: 1, minWidth: 120 }} | |||
| sx={{ mr: 1, minWidth: 120, ...PRIMARY_CONTAINED_BUTTON_SX }} | |||
| > | |||
| {isNextBusy ? ( | |||
| <CircularProgress size={22} color="inherit" aria-hidden /> | |||
| ) : ( | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| )} | |||
| </Button> | |||
| ) : (activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button variant="contained" color="inherit" | |||
| disabled={true} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| </Button> | |||
| ) : | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid || isNextBusy} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button disabled={!updateValid || isNextBusy} variant="contained" onClick={handleNext} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="continue"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -128,17 +128,17 @@ const ForgotPasswordApplyForm = () => { | |||
| <Grid container spacing={2} sx={{ minHeight: '40vh' }} direction="column" justifyContent="flex-start" alignItems="center"> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}> | |||
| <InputLabel htmlFor="email-login-title"> | |||
| <Typography variant="h5" > | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="forgotPasswordSubTitle"/> | |||
| </Typography> | |||
| </InputLabel> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { md: 'none', xl: 'none', lg: 'none' } }}> | |||
| <InputLabel htmlFor="email-login-subtitle"> | |||
| <Typography variant="h6" > | |||
| <Typography variant="h6" component="span"> | |||
| <FormattedMessage id="forgotPasswordSubTitle1"/> | |||
| </Typography> | |||
| <Typography variant="h6" > | |||
| <Typography variant="h6" component="span"> | |||
| <FormattedMessage id="forgotPasswordSubTitle2"/> | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -212,7 +212,7 @@ const ForgotPasswordApplyForm = () => { | |||
| <FormattedMessage id="attention"/> | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| {/* <Typography variant="h5" style={{ padding: '16px' }}>{warningText}</Typography> */} | |||
| {/* <Typography variant="h5" component="span" style={{ padding: '16px' }}>{warningText}</Typography> */} | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button | |||
| @@ -127,17 +127,17 @@ const ForgotUsernameApplyForm = () => { | |||
| <Grid container spacing={2} sx={{ minHeight: '40vh' }} direction="column" justifyContent="flex-start" alignItems="center"> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { xs: 'none', sm: 'none', md: 'block' } }}> | |||
| <InputLabel htmlFor="email-login-title"> | |||
| <Typography variant="h5" > | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="forgotUsernameSubTitle"/> | |||
| </Typography> | |||
| </InputLabel> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} lg={12} sx={{ mb: 1, mt:5, display: { md: 'none', xl: 'none', lg: 'none' } }}> | |||
| <InputLabel htmlFor="email-login-subtitle"> | |||
| <Typography variant="h6" > | |||
| <Typography variant="h6" component="span"> | |||
| <FormattedMessage id="forgotUsernameSubTitle1"/> | |||
| </Typography> | |||
| <Typography variant="h6" > | |||
| <Typography variant="h6" component="span"> | |||
| <FormattedMessage id="forgotPasswordSubTitle2"/> | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -211,7 +211,7 @@ const ForgotUsernameApplyForm = () => { | |||
| <FormattedMessage id="attention"/> | |||
| </DialogTitle> | |||
| <DialogContent style={{ display: 'flex', }}> | |||
| {/* <Typography variant="h5" style={{ padding: '16px' }}>{warningText}</Typography> */} | |||
| {/* <Typography variant="h5"component="span" style={{ padding: '16px' }}>{warningText}</Typography> */} | |||
| </DialogContent> | |||
| <DialogActions> | |||
| <Button | |||
| @@ -13,10 +13,11 @@ import { | |||
| Stack, | |||
| Typography, | |||
| Button, | |||
| StepLabel, | |||
| CircularProgress, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| import { GET_ID, POST_VERIFY_CAPTCHA } from "utils/ApiPathConst"; | |||
| import RegisterStepIcon, { registerStepStyle } from 'components/RegisterStepIcon'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| @@ -24,32 +25,10 @@ import { lazy } from 'react'; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import axios from "axios"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/IAmSmartFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // ================================|| REGISTER ||================================ // | |||
| const stepStyle = { | |||
| width: { lg: "40%", md: "70%", xs: "100%" }, | |||
| boxShadow: 1, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| /* Inactive (default) */ | |||
| "& .MuiStepIcon-root": { color: "#757575", fontSize: "2rem" }, // darker grey | |||
| "& .MuiStepLabel-label": { color: "#424242" }, // label darker | |||
| "& .MuiStepConnector-line": { borderColor: "#9E9E9E" }, // connector darker | |||
| /* Active */ | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { color: "warning.main", fontSize: "2rem" }, | |||
| "& .MuiStepConnector-line": { borderColor: "warning.main" } | |||
| }, | |||
| /* Completed */ | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { color: "#0C489E", fontSize: "2rem" }, // use your strong blue | |||
| "& .MuiStepConnector-line": { borderColor: "#0C489E" } | |||
| } | |||
| }; | |||
| const Register = () => { | |||
| const [activeStep, setActiveStep] = useState(0); | |||
| @@ -61,6 +40,7 @@ const Register = () => { | |||
| const [checkCode, setCheckCode] = useState("") | |||
| const [idNo, setIdNo] = useState(""); | |||
| const [isNextBusy, setIsNextBusy] = useState(false); | |||
| const [registrationComplete, setRegistrationComplete] = useState(false); | |||
| const intl = useIntl(); | |||
| const steps = [ | |||
| intl.formatMessage({id: 'personalInformation'}), | |||
| @@ -152,37 +132,30 @@ const Register = () => { | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| setRegistrationComplete(false); | |||
| }; | |||
| const isStepCompleted = (index) => index < activeStep || registrationComplete; | |||
| return ( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%', fontSize: '2rem', paddingTop: '65px', bgcolor: 'backgroundColor.default' }} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| <Stepper activeStep={activeStep} sx={registerStepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| {index < 2 ? ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton> | |||
| ) : ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| sx={ | |||
| activeStep === 2 | |||
| ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } | |||
| : allStepsCompleted() | |||
| ? { "& .MuiSvgIcon-root": { color: "#0C489E", fontSize: "2rem" } } | |||
| : { color: "rgba(0,0,0,0.6)" } | |||
| } | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| <Step key={label} completed={isStepCompleted(index)} readOnly={true}> | |||
| <StepButton | |||
| aria-current={activeStep === index ? "step" : undefined} | |||
| > | |||
| <StepLabel | |||
| StepIconComponent={RegisterStepIcon} | |||
| sx={{ | |||
| flexDirection: "column", | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 }, | |||
| }} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepButton> | |||
| )} | |||
| </StepLabel> | |||
| </StepButton> | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| @@ -207,6 +180,7 @@ const Register = () => { | |||
| setIdNo={setIdNo} | |||
| setBase64Url={setBase64Url} | |||
| setCheckCode={setCheckCode} | |||
| onRegistrationComplete={() => setRegistrationComplete(true)} | |||
| /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| @@ -239,33 +213,33 @@ const Register = () => { | |||
| {activeStep === totalSteps() - 2 ? | |||
| ( | |||
| <Button | |||
| variant="outlined" | |||
| variant="contained" | |||
| disabled={isNextBusy} | |||
| onClick={handleNext} | |||
| aria-busy={isNextBusy} | |||
| sx={{ mr: 1, minWidth: 120 }} | |||
| sx={{ mr: 1, minWidth: 120, ...PRIMARY_CONTAINED_BUTTON_SX }} | |||
| > | |||
| {isNextBusy ? ( | |||
| <CircularProgress size={22} color="inherit" aria-hidden /> | |||
| ) : ( | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| )} | |||
| </Button> | |||
| ) : (activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button variant="contained" color="inherit" | |||
| disabled={true} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| </Button> | |||
| ) : | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid || isNextBusy} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button disabled={!updateValid || isNextBusy} variant="contained" onClick={handleNext} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="continue"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -15,8 +15,8 @@ import { | |||
| Button, StepLabel, | |||
| CircularProgress, | |||
| } from '@mui/material'; | |||
| import VisibilityIcon from '@mui/icons-material/Visibility'; | |||
| import { POST_USERNAME, POST_VERIFY_CAPTCHA } from "utils/ApiPathConst"; | |||
| import RegisterStepIcon, { registerStepStyle } from 'components/RegisterStepIcon'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| @@ -25,6 +25,7 @@ import { notifyActionError } from 'utils/CommonFunction'; | |||
| import axios from "axios"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| import usePageTitle from "components/usePageTitle"; | |||
| import { PRIMARY_CONTAINED_BUTTON_SX } from "themes/colorConst"; | |||
| const CustomFormWizard = Loadable(lazy(() => import('./auth-forms/CustomFormWizard'))); | |||
| const AuthWrapper = Loadable(lazy(() => import('./AuthWrapperCustom'))); | |||
| // ================================|| REGISTER ||================================ // | |||
| @@ -38,6 +39,7 @@ const Register = () => { | |||
| const [base64Url, setBase64Url] = useState("") | |||
| const [checkCode, setCheckCode] = useState("") | |||
| const [isNextBusy, setIsNextBusy] = useState(false); | |||
| const [registrationComplete, setRegistrationComplete] = useState(false); | |||
| const nextBusyRef = useRef(false); | |||
| const intl = useIntl(); | |||
| // Localized document title/meta for register flow | |||
| @@ -48,30 +50,6 @@ const Register = () => { | |||
| intl.formatMessage({id: 'finishSubmission'}) | |||
| ]; | |||
| const stepStyle = { | |||
| width: { lg: "40%", md: "70%", xs: "100%" }, | |||
| boxShadow: 1, | |||
| backgroundColor: "#FFFFFF", | |||
| padding: 2, | |||
| /* Inactive (default) */ | |||
| "& .MuiStepIcon-root": { color: "#757575", fontSize: "2rem" }, // darker grey | |||
| "& .MuiStepLabel-label": { color: "#424242" }, // label darker | |||
| "& .MuiStepConnector-line": { borderColor: "#9E9E9E" }, // connector darker | |||
| /* Active */ | |||
| "& .Mui-active": { | |||
| "&.MuiStepIcon-root": { color: "warning.main", fontSize: "2rem" }, | |||
| "& .MuiStepConnector-line": { borderColor: "warning.main" } | |||
| }, | |||
| /* Completed */ | |||
| "& .Mui-completed": { | |||
| "&.MuiStepIcon-root": { color: "#0C489E", fontSize: "2rem" }, // use your strong blue | |||
| "& .MuiStepConnector-line": { borderColor: "#0C489E" } | |||
| } | |||
| }; | |||
| const totalSteps = () => { | |||
| return steps.length; | |||
| }; | |||
| @@ -153,51 +131,30 @@ const Register = () => { | |||
| const handleReset = () => { | |||
| setActiveStep(0); | |||
| setCompleted({}); | |||
| setRegistrationComplete(false); | |||
| }; | |||
| const isStepCompleted = (index) => index < activeStep || registrationComplete; | |||
| return ( | |||
| // <AuthWrapper> | |||
| <Stack sx={{ width: '100%', fontSize: '2rem', paddingTop: '35px', bgcolor: 'backgroundColor.default' }} alignItems="center"> | |||
| <Stepper activeStep={activeStep} sx={stepStyle}> | |||
| <Stepper activeStep={activeStep} sx={registerStepStyle}> | |||
| {steps.map((label, index) => ( | |||
| <Step key={label} completed={completed[index]} readOnly={true}> | |||
| {index < 2 ? ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? 'step' : undefined} | |||
| // onClick={handleStep(index)} | |||
| <Step key={label} completed={isStepCompleted(index)} readOnly={true}> | |||
| <StepButton | |||
| aria-current={activeStep === index ? 'step' : undefined} | |||
| > | |||
| <StepLabel | |||
| StepIconComponent={RegisterStepIcon} | |||
| sx={{ | |||
| flexDirection: 'column', | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 } | |||
| }} | |||
| > | |||
| <StepLabel | |||
| sx={{ | |||
| flexDirection: 'column', | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 } | |||
| }} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| ) : ( | |||
| <StepButton | |||
| aria-current={activeStep === index ? 'step' : undefined} | |||
| sx={ | |||
| activeStep === 2 | |||
| ? { "& .MuiSvgIcon-root": { color: "warning.main", fontSize: "2rem" } } | |||
| : allStepsCompleted() | |||
| ? { "& .MuiSvgIcon-root": { color: "#0C489E", fontSize: "2rem" } } | |||
| : { color: "rgba(0,0,0,0.6)" } | |||
| } | |||
| icon={<VisibilityIcon />} | |||
| // onClick={handleStep(index)} | |||
| > | |||
| <StepLabel | |||
| sx={{ | |||
| flexDirection: 'column', | |||
| "& .MuiStepLabel-iconContainer": { paddingRight: 0 } | |||
| }} | |||
| > | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| )} | |||
| <Typography variant="step1">{label}</Typography> | |||
| </StepLabel> | |||
| </StepButton> | |||
| </Step> | |||
| ))} | |||
| </Stepper> | |||
| @@ -221,6 +178,7 @@ const Register = () => { | |||
| setUsername={setUsername} | |||
| setBase64Url={setBase64Url} | |||
| setCheckCode={setCheckCode} | |||
| onRegistrationComplete={() => setRegistrationComplete(true)} | |||
| /> | |||
| {/* <CustomFormWizard step={activeStep} /> */} | |||
| </AuthWrapper> | |||
| @@ -255,33 +213,33 @@ const Register = () => { | |||
| {activeStep === totalSteps() - 2 ? | |||
| ( | |||
| <Button | |||
| variant="outlined" | |||
| variant="contained" | |||
| disabled={isNextBusy} | |||
| onClick={handleNext} | |||
| aria-busy={isNextBusy} | |||
| sx={{ mr: 1, minWidth: 120 }} | |||
| sx={{ mr: 1, minWidth: 120, ...PRIMARY_CONTAINED_BUTTON_SX }} | |||
| > | |||
| {isNextBusy ? ( | |||
| <CircularProgress size={22} color="inherit" aria-hidden /> | |||
| ) : ( | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| )} | |||
| </Button> | |||
| ) : (activeStep === totalSteps() - 1 ? | |||
| ( | |||
| <Button variant="outlined" color="inherit" | |||
| disabled={true} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button variant="contained" color="inherit" | |||
| disabled={true} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="submit"/> | |||
| </Typography> | |||
| </Button> | |||
| ) : | |||
| ( | |||
| // <Button disabled={updateValid} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Button disabled={!updateValid || isNextBusy} variant="outlined" onClick={handleNext} sx={{ mr: 1 }}> | |||
| <Typography variant="h5"> | |||
| <Button disabled={!updateValid || isNextBusy} variant="contained" onClick={handleNext} sx={{ mr: 1, ...PRIMARY_CONTAINED_BUTTON_SX }}> | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="continue"/> | |||
| </Typography> | |||
| </Button> | |||
| @@ -142,19 +142,19 @@ const RegisterCustom = () => { | |||
| href="/registerFrom" | |||
| variant="contained" | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| border: '1px solid #0C489E', | |||
| border: '1px solid #0c489e', | |||
| boxShadow: 'none', | |||
| '&:hover': { | |||
| backgroundColor: '#093A7A', | |||
| backgroundColor: '#1565c0', | |||
| color: '#FFFFFF', | |||
| border: '1px solid #093A7A', | |||
| border: '1px solid #1565c0', | |||
| boxShadow: 'none', | |||
| }, | |||
| }} | |||
| > | |||
| <Typography variant="h5" sx={{ color: 'inherit' }}> | |||
| <Typography component="span" variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="registerNewPersonalUser" /> | |||
| </Typography> | |||
| </Button> | |||
| @@ -164,7 +164,7 @@ const RegisterCustom = () => { | |||
| </Typography> | |||
| </Grid> | |||
| <Grid item xs={12} md={6} sx={{ borderLeft: 1, borderColor: 'grey.500' }}> | |||
| <Typography mb={4} variant="h3"> | |||
| <Typography component="h2" mb={4} variant="h3"> | |||
| <FormattedMessage id="businessUser" /> | |||
| </Typography> | |||
| <Button | |||
| @@ -172,19 +172,19 @@ const RegisterCustom = () => { | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 0.5, | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| border: '1px solid #0C489E', | |||
| border: '1px solid #0c489e', | |||
| boxShadow: 'none', | |||
| '&:hover': { | |||
| backgroundColor: '#093A7A', | |||
| backgroundColor: '#1565c0', | |||
| color: '#FFFFFF', | |||
| border: '1px solid #093A7A', | |||
| border: '1px solid #1565c0', | |||
| boxShadow: 'none', | |||
| }, | |||
| }} | |||
| > | |||
| <Typography component="h2" variant="h5" sx={{ color: 'inherit' }}> | |||
| <Typography component="span" variant="h5" sx={{ color: 'inherit' }}> | |||
| <FormattedMessage id="registerNewBusinessUser" /> | |||
| </Typography> | |||
| </Button> | |||
| @@ -369,9 +369,9 @@ const AuthLoginCustom = () => { | |||
| <Button disableElevation disabled={isButtonDisabled} | |||
| fullWidth size="large" type="submit" variant="contained" color="primary" | |||
| sx={{ | |||
| backgroundColor: "#0C489E", | |||
| backgroundColor: "#0c489e", | |||
| color: "#FFFFFF", | |||
| "&:hover": { backgroundColor: "#093A7A" }, | |||
| "&:hover": { backgroundColor: "#1565c0" }, | |||
| "&.Mui-disabled": { | |||
| background: "#bbdefb", | |||
| color: "#fff", | |||
| @@ -55,7 +55,8 @@ import {PNSPS_LONG_BUTTON_THEME} from "../../../themes/buttonConst"; | |||
| import {ThemeProvider} from "@emotion/react"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| //import { Invaild } from 'utils/IconUtils'; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import { handleActionKeyDown, notifyActionError } from 'utils/CommonFunction'; | |||
| import { ADDRESS_LINE_MAX_LENGTH, isAddressLineWithinLimit, isRegisterAddressValid } from 'utils/registerValidation'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| @@ -286,7 +287,7 @@ const BusCustomFormWizard = (props) => { | |||
| (data.chCompanyName !== "" || data.enCompanyName !== "") && | |||
| data.enName !== "" && | |||
| data.chName !== "" && | |||
| data.address1 !== "" && | |||
| isRegisterAddressValid(data) && | |||
| data.email !== "" && | |||
| data.emailConfirm !== "" && | |||
| data.email === data.emailConfirm && | |||
| @@ -343,6 +344,10 @@ const BusCustomFormWizard = (props) => { | |||
| } | |||
| if (fileInputRef.current) { | |||
| fileInputRef.current.value = ''; | |||
| } | |||
| }, [updateRows]); | |||
| const handleBrNo = (brNo) => { | |||
| @@ -396,6 +401,8 @@ const BusCustomFormWizard = (props) => { | |||
| setFileListData(saveFileList) | |||
| setFileList(updatedFileList); | |||
| setUpdateRows(saveFileList); | |||
| event.target.value = ''; | |||
| }; | |||
| useEffect(() => { | |||
| @@ -494,6 +501,7 @@ const BusCustomFormWizard = (props) => { | |||
| ) => { | |||
| // console.log(response) | |||
| setCheckUpload(true) | |||
| props.onRegistrationComplete?.(); | |||
| setLoding(false); | |||
| }) | |||
| .catch(error => { | |||
| @@ -669,7 +677,17 @@ const BusCustomFormWizard = (props) => { | |||
| const syncOk = computeStep0ValidSync(values); | |||
| if (!syncOk) { | |||
| setisValid(false); | |||
| if (!isDistrictSelectionValid()) { | |||
| if (!isRegisterAddressValid(values)) { | |||
| if (values.address1 === '') { | |||
| notifyActionError(intl.formatMessage({ id: 'validateAddressLine1' })); | |||
| } else if (!isAddressLineWithinLimit(values.address1)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine1' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address2)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine2' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address3)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine3' }) + ": " })); | |||
| } | |||
| } else if (!isDistrictSelectionValid()) { | |||
| setDistrictErrStr(getRequiredErrStr("district")); | |||
| setCheckDistrict(true); | |||
| notifyActionError(intl.formatMessage({ id: 'require' }, { fieldname: intl.formatMessage({ id: 'district' }) })); | |||
| @@ -721,14 +739,14 @@ const BusCustomFormWizard = (props) => { | |||
| </Typography> | |||
| </Button> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3"component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewBusinessUser"/> | |||
| </Typography> | |||
| </div> | |||
| <Typography mt={0.25} variant="h6" sx={{ color: '#B00020' }}> | |||
| <Typography mt={0.25} variant="h6" component="span" sx={{ color: '#B00020' }}> | |||
| <FormattedMessage id="requireString"/> | |||
| </Typography> | |||
| <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourLoginInformation"/> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -748,7 +766,7 @@ const BusCustomFormWizard = (props) => { | |||
| variant="contained" | |||
| onClick={handleCheckUsername} | |||
| sx={{ ml: 2, height: "40px" }}> | |||
| <Typography variant="h6">檢查是否重覆</Typography> | |||
| <Typography variant="h6" component="span">檢查是否重覆</Typography> | |||
| </Button> */} | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -815,10 +833,13 @@ const BusCustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowPassword)} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| @@ -891,10 +912,13 @@ const BusCustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowConfirmPassword)} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| @@ -929,7 +953,7 @@ const BusCustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" /*sx={{ color: '#1A4399' }}*/> | |||
| <Typography display="inline" variant="h4" component="h2" /*sx={{ color: '#1A4399' }}*/> | |||
| <FormattedMessage id="yourBusinessInformation"/> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -1102,6 +1126,7 @@ const BusCustomFormWizard = (props) => { | |||
| onBlur={formik.handleBlur} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine1" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1120,6 +1145,7 @@ const BusCustomFormWizard = (props) => { | |||
| placeholder={intl.formatMessage({id: 'addressLine2'})} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine2" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1138,6 +1164,7 @@ const BusCustomFormWizard = (props) => { | |||
| placeholder={intl.formatMessage({id: 'addressLine3'})} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine3" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1246,7 +1273,7 @@ const BusCustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact"/> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1524,20 +1551,21 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="businessRegCertAndDoc"/> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| <Typography display="inline" variant="h6" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h6" component="span" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="pleaseUploadDoc"/> | |||
| </Typography> | |||
| {/* <Typography display="inline" variant="h6" sx={{ fontSize: 12,color: 'primary.primary'}}>如: 香港身份證; 護照; 中國內地身份證等</Typography> */} | |||
| {/* <Typography display="inline" variant="h6" component="span" sx={{ fontSize: 12,color: 'primary.primary'}}>如: 香港身份證; 護照; 中國內地身份證等</Typography> */} | |||
| <Stack mt={1} direction="row" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| <ThemeProvider theme={PNSPS_LONG_BUTTON_THEME}> | |||
| <Button | |||
| variant="contained" | |||
| sx={{ height: '40px' }} | |||
| type="button" | |||
| tabIndex={0} | |||
| onClick={() => { | |||
| if (fileInputRef.current) { | |||
| fileInputRef.current.click(); | |||
| @@ -1565,7 +1593,7 @@ const BusCustomFormWizard = (props) => { | |||
| style={{ display: 'none' }} | |||
| /> | |||
| </ThemeProvider> | |||
| {/* <Typography display="inline" variant="h6" sx={{ fontSize: 12, color: 'primary.primary'}}></Typography> */} | |||
| {/* <Typography display="inline" variant="h6" component="span" sx={{ fontSize: 12, color: 'primary.primary'}}></Typography> */} | |||
| </Stack> | |||
| {fileList != null && props.step === 0 ? | |||
| <UploadFileTable key="uploadTable" recordList={fileListData} setUpdateRows={setUpdateRows} /> : null} | |||
| @@ -1581,7 +1609,7 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="termsAndCondition"/> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1589,7 +1617,7 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography variant="h6" height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0C489E" }}> | |||
| <Typography variant="h6" height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0c489e" }}> | |||
| <div style={{padding: 12}} dangerouslySetInnerHTML={{__html: intl.formatMessage({id: "termsAndCon"})}} /> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -1642,7 +1670,7 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid item xs={12} lg={12}> | |||
| <Grid container> | |||
| <Stack direction="column"> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="verify"/> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1651,7 +1679,14 @@ const BusCustomFormWizard = (props) => { | |||
| <img src={captchaImg} alt="" /> | |||
| </Grid> | |||
| <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}> | |||
| <IconButton aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} size="large" onClick={() => { onCaptchaChange() }}> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} | |||
| size="large" | |||
| onClick={() => { onCaptchaChange() }} | |||
| onKeyDown={(event) => handleActionKeyDown(event, () => onCaptchaChange())} | |||
| > | |||
| <LoopIcon fontSize="inherit" /> | |||
| </IconButton> | |||
| </Grid> | |||
| @@ -1689,9 +1724,9 @@ const BusCustomFormWizard = (props) => { | |||
| onClick={playCaptchaAudio} | |||
| aria-label={intl.formatMessage({ id: "captchaPlayAudio" })} | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| @@ -1709,12 +1744,12 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid item xs={12}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3"component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewBusinessUser"/> | |||
| </Typography> | |||
| </div> | |||
| {/* <Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#B00020'}}>註有*的項目必須輸入資料</Typography> */} | |||
| <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}> | |||
| {/* <Typography mt={0.25} variant="h6" component="span" sx={{ fontSize: 12,color: '#B00020'}}>註有*的項目必須輸入資料</Typography> */} | |||
| <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourLoginInformation"/> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -1736,7 +1771,7 @@ const BusCustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" /*sx={{ color: '#1A4399' }}*/> | |||
| <Typography display="inline" variant="h4" component="h2" /*sx={{ color: '#1A4399' }}*/> | |||
| <FormattedMessage id="yourBusinessInformation"/> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -1837,7 +1872,7 @@ const BusCustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact"/> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1886,8 +1921,8 @@ const BusCustomFormWizard = (props) => { | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="userIdDoc"/> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="businessRegCertAndDoc"/> | |||
| </Typography> | |||
| {fileList != null && props.step === 1 ? | |||
| <PreviewUploadFileTable key="previewTable" recordList={fileListData} /> : null} | |||
| @@ -1909,10 +1944,10 @@ const BusCustomFormWizard = (props) => { | |||
| // SUCCESS page | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerSubmitted"/> | |||
| </Typography> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="emailSent"/> | |||
| </Typography> | |||
| <Button variant="outlined" component={Link} to="/login" > | |||
| @@ -1925,7 +1960,7 @@ const BusCustomFormWizard = (props) => { | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */} | |||
| <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerFail" /> | |||
| </Typography> | |||
| <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="pnspsFormHeader"> | |||
| @@ -47,7 +47,8 @@ import { FormattedMessage, useIntl } from "react-intl"; | |||
| import { Link } from 'react-router-dom'; | |||
| import { PNSPS_LONG_BUTTON_THEME } from "../../../themes/buttonConst"; | |||
| import * as HttpUtils from "../../../utils/HttpUtils"; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import { handleActionKeyDown, notifyActionError } from 'utils/CommonFunction'; | |||
| import { ADDRESS_LINE_MAX_LENGTH, isAddressLineWithinLimit, isRegisterAddressValid } from 'utils/registerValidation'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| const CustomFormWizard = (props) => { | |||
| @@ -377,7 +378,7 @@ const CustomFormWizard = (props) => { | |||
| selectedIdDocType.type !== "" && | |||
| data.idNo !== "" && | |||
| handleName(data.enName, data.chName) && | |||
| data.address1 !== "" && | |||
| isRegisterAddressValid(data) && | |||
| data.email !== "" && | |||
| data.emailConfirm !== "" && | |||
| data.email == data.emailConfirm && | |||
| @@ -432,6 +433,10 @@ const CustomFormWizard = (props) => { | |||
| } | |||
| if (fileInputRef.current) { | |||
| fileInputRef.current.value = ''; | |||
| } | |||
| }, [updateRows]); | |||
| const handleFileUpload = (event) => { | |||
| @@ -473,6 +478,8 @@ const CustomFormWizard = (props) => { | |||
| setFileListData(saveFileList) | |||
| setFileList(updatedFileList); | |||
| setUpdateRows(saveFileList); | |||
| event.target.value = ''; | |||
| }; | |||
| useEffect(() => { | |||
| @@ -586,6 +593,7 @@ const CustomFormWizard = (props) => { | |||
| ) => { | |||
| // console.log(response) | |||
| setCheckUpload(true) | |||
| props.onRegistrationComplete?.(); | |||
| setLoding(false); | |||
| }) | |||
| .catch(error => { | |||
| @@ -890,7 +898,17 @@ const CustomFormWizard = (props) => { | |||
| const syncOk = computeStep0ValidSync(values); | |||
| if (!syncOk) { | |||
| setisValid(false); | |||
| if (!isDistrictSelectionValid()) { | |||
| if (!isRegisterAddressValid(values)) { | |||
| if (values.address1 === '') { | |||
| notifyActionError(intl.formatMessage({ id: 'validateAddressLine1' })); | |||
| } else if (!isAddressLineWithinLimit(values.address1)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine1' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address2)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine2' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address3)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine3' }) + ": " })); | |||
| } | |||
| } else if (!isDistrictSelectionValid()) { | |||
| setDistrictErrStr(getRequiredErrStr("district")); | |||
| setCheckDistrict(true); | |||
| notifyActionError(intl.formatMessage({ id: 'require' }, { fieldname: intl.formatMessage({ id: 'district' }) })); | |||
| @@ -942,14 +960,14 @@ const CustomFormWizard = (props) => { | |||
| </Typography> | |||
| </Button> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewPersonalUser" /> | |||
| </Typography> | |||
| </div> | |||
| <Typography mt={0.25} variant="h6" sx={{ color: '#B00020' }}> | |||
| <Typography mt={0.25} variant="h6" component="span" sx={{ color: '#B00020' }}> | |||
| <FormattedMessage id="requireString" /> | |||
| </Typography> | |||
| <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourLoginInformation" /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -966,7 +984,7 @@ const CustomFormWizard = (props) => { | |||
| {/* variant="contained"*/} | |||
| {/* onClick={handleCheckUsername}*/} | |||
| {/* sx={{ ml: 2, height: "40px" }}>*/} | |||
| {/* <Typography variant="h6">檢查是否重覆</Typography>*/} | |||
| {/* <Typography variant="h6" component="span">檢查是否重覆</Typography>*/} | |||
| {/*</Button> **/} | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -1033,10 +1051,13 @@ const CustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowPassword)} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| @@ -1109,10 +1130,13 @@ const CustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowConfirmPassword)} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| size="large" | |||
| @@ -1147,7 +1171,7 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourPersonalInformation" /> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -1161,7 +1185,7 @@ const CustomFormWizard = (props) => { | |||
| <InputLabel htmlFor="idDocType-signup"> | |||
| <Typography variant="pnspsFormHeader"> | |||
| <FormattedMessage id="userIdDoc" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| <span style={{ color: '#131313' }}>*</span> | |||
| </Typography> | |||
| </InputLabel> | |||
| {/* {formik.touched.enName && formik.errors.enName && ( | |||
| @@ -1462,6 +1486,7 @@ const CustomFormWizard = (props) => { | |||
| onBlur={formik.handleBlur} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine1" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1480,6 +1505,7 @@ const CustomFormWizard = (props) => { | |||
| placeholder={intl.formatMessage({ id: 'addressLine2' })} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine2" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1498,6 +1524,7 @@ const CustomFormWizard = (props) => { | |||
| placeholder={intl.formatMessage({ id: 'addressLine3' })} | |||
| inputProps={{ | |||
| "aria-label": intl.formatMessage({ id: "addressLine3" }), | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -1607,7 +1634,7 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact" /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1851,7 +1878,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="userIdDoc" /> | |||
| <span style={{ color: '#B00020' }}>*</span></Typography> | |||
| <Typography display="inline" variant="subtitle1" sx={{ color: 'primary.primary' }}> | |||
| @@ -1866,6 +1893,7 @@ const CustomFormWizard = (props) => { | |||
| variant="contained" | |||
| sx={{ height: '40px' }} | |||
| type="button" | |||
| tabIndex={0} | |||
| onClick={() => { | |||
| if (fileInputRef.current) { | |||
| fileInputRef.current.click(); | |||
| @@ -1909,7 +1937,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="termsAndCondition" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1917,7 +1945,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography variant="h6" height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0C489E" }}> | |||
| <Typography height="100%" sx={{ textAlign: "left", /*overflow: "scroll",*/ borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0c489e" }}> | |||
| <div style={{padding: 12}} dangerouslySetInnerHTML={{__html: intl.formatMessage({id: "termsAndCon"})}} /> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -1970,7 +1998,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} lg={12}> | |||
| <Grid container> | |||
| <Stack direction="column"> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="verify" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1979,7 +2007,14 @@ const CustomFormWizard = (props) => { | |||
| <img src={captchaImg} alt="" /> | |||
| </Grid> | |||
| <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}> | |||
| <IconButton aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} size="large" onClick={() => { onCaptchaChange() }}> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} | |||
| size="large" | |||
| onClick={() => { onCaptchaChange() }} | |||
| onKeyDown={(event) => handleActionKeyDown(event, () => onCaptchaChange())} | |||
| > | |||
| <LoopIcon fontSize="inherit" /> | |||
| </IconButton> | |||
| </Grid> | |||
| @@ -2017,9 +2052,9 @@ const CustomFormWizard = (props) => { | |||
| onClick={playCaptchaAudio} | |||
| aria-label={intl.formatMessage({ id: "captchaPlayAudio" })} | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| @@ -2037,12 +2072,12 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewPersonalUser" /> | |||
| </Typography> | |||
| </div> | |||
| {/* <Typography mt={0.25} variant="h6" sx={{ fontSize: 12,color: '#B00020'}}>註有*的項目必須輸入資料</Typography> */} | |||
| <Typography mt={0.25} variant="h4" sx={{ color: 'primary.primary' }}> | |||
| {/* <Typography mt={0.25} variant="h6" component="span" sx={{ fontSize: 12,color: '#B00020'}}>註有*的項目必須輸入資料</Typography> */} | |||
| <Typography mt={0.25} variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourLoginInformation" /> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -2064,7 +2099,7 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourPersonalInformation" /> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -2107,8 +2142,11 @@ const CustomFormWizard = (props) => { | |||
| </Typography> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||
| onClick={handleClickShowId} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowId)} | |||
| onMouseDown={handleMouseDownId} | |||
| edge="end" | |||
| size="medium" | |||
| @@ -2180,7 +2218,7 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact" /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -2221,7 +2259,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="userIdDoc" /> | |||
| </Typography> | |||
| {fileList != null && props.step === 1 ? | |||
| @@ -2244,10 +2282,10 @@ const CustomFormWizard = (props) => { | |||
| // SUCCESS page | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerSubmitted" /> | |||
| </Typography> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="emailSent" /> | |||
| </Typography> | |||
| <Button variant="outlined" component={Link} to="/login" ><Typography variant="pnspsFormHeader"> | |||
| @@ -2259,7 +2297,7 @@ const CustomFormWizard = (props) => { | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */} | |||
| <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerFail" /> | |||
| </Typography> | |||
| <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="pnspsFormHeader"> | |||
| @@ -40,7 +40,8 @@ import LoopIcon from '@mui/icons-material/Loop'; | |||
| import { useTheme } from '@mui/material/styles'; | |||
| import { useLocation } from "react-router-dom"; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import { notifyActionError } from 'utils/CommonFunction'; | |||
| import { handleActionKeyDown, notifyActionError } from 'utils/CommonFunction'; | |||
| import { ADDRESS_LINE_MAX_LENGTH, isAddressLineWithinLimit, isRegisterAddressValid, splitAddressIntoLines } from 'utils/registerValidation'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| @@ -199,20 +200,22 @@ const CustomFormWizard = (props) => { | |||
| "phoneCountryCode": rd?.mobileNumber?.CountryCode ?? "", | |||
| }; | |||
| if (rd?.postalAddress) { | |||
| if (rd?.postalAddress?.EngPremisesAddress) { | |||
| data["address1"] = getAddressEng(rd?.postalAddress?.EngPremisesAddress); | |||
| } else if (rd.postalAddress.ChiPremisesAddress) { | |||
| data["address1"] = getAddressChi(rd?.postalAddress?.ChiPremisesAddress); | |||
| } | |||
| } else if (rd?.residentialAddress) { | |||
| if (rd?.residentialAddress?.EngPremisesAddress) { | |||
| data["address1"] = getAddressEng(rd?.residentialAddress?.EngPremisesAddress); | |||
| } else if (rd?.residentialAddress?.ChiPremisesAddress) { | |||
| data["address1"] = getAddressChi(rd?.residentialAddress?.ChiPremisesAddress); | |||
| } | |||
| let fullAddress = ''; | |||
| if (rd?.postalAddress?.EngPremisesAddress) { | |||
| fullAddress = getAddressEng(rd.postalAddress.EngPremisesAddress); | |||
| } else if (rd?.postalAddress?.ChiPremisesAddress) { | |||
| fullAddress = getAddressChi(rd.postalAddress.ChiPremisesAddress); | |||
| } else if (rd?.residentialAddress?.EngPremisesAddress) { | |||
| fullAddress = getAddressEng(rd.residentialAddress.EngPremisesAddress); | |||
| } else if (rd?.residentialAddress?.ChiPremisesAddress) { | |||
| fullAddress = getAddressChi(rd.residentialAddress.ChiPremisesAddress); | |||
| } | |||
| const { address1, address2, address3 } = splitAddressIntoLines(fullAddress); | |||
| data["address1"] = address1; | |||
| data["address2"] = address2; | |||
| data["address3"] = address3; | |||
| setIAmSmartData(data); | |||
| } | |||
| @@ -300,6 +303,8 @@ const CustomFormWizard = (props) => { | |||
| formik.setFieldValue("phone", iAmSmartData.phone ?? ""); | |||
| formik.setFieldValue("phoneCountryCode", iAmSmartData.phoneCountryCode ?? ""); | |||
| formik.setFieldValue("address1", iAmSmartData.address1 ?? ""); | |||
| formik.setFieldValue("address2", iAmSmartData.address2 ?? ""); | |||
| formik.setFieldValue("address3", iAmSmartData.address3 ?? ""); | |||
| props.setIdNo(iAmSmartData.idNo ?? ""); | |||
| setLodingData(false) | |||
| } | |||
| @@ -321,7 +326,7 @@ const CustomFormWizard = (props) => { | |||
| /** All step-0 checks except duplicate-email result from /checkE1 (see checkEmail state). */ | |||
| const computeStep0ValidSync = (data) => ( | |||
| data.address1 !== "" && | |||
| isRegisterAddressValid(data) && | |||
| data.email !== "" && | |||
| data.emailConfirm !== "" && | |||
| data.email == data.emailConfirm && | |||
| @@ -431,6 +436,7 @@ const CustomFormWizard = (props) => { | |||
| .then((response) => { | |||
| console.log(response) | |||
| setCheckUpload(true) | |||
| props.onRegistrationComplete?.(); | |||
| setLoding(false); | |||
| }) | |||
| .catch(error => { | |||
| @@ -509,7 +515,17 @@ const CustomFormWizard = (props) => { | |||
| const syncOk = computeStep0ValidSync(values); | |||
| if (!syncOk) { | |||
| setisValid(false); | |||
| if (!isDistrictSelectionValid()) { | |||
| if (!isRegisterAddressValid(values)) { | |||
| if (values.address1 === '') { | |||
| notifyActionError(intl.formatMessage({ id: 'validateAddressLine1' })); | |||
| } else if (!isAddressLineWithinLimit(values.address1)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine1' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address2)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine2' }) + ": " })); | |||
| } else if (!isAddressLineWithinLimit(values.address3)) { | |||
| notifyActionError(intl.formatMessage({ id: 'noMoreThenNWords' }, { num: ADDRESS_LINE_MAX_LENGTH, fieldname: intl.formatMessage({ id: 'addressLine3' }) + ": " })); | |||
| } | |||
| } else if (!isDistrictSelectionValid()) { | |||
| setDistrictErrStr(getRequiredErrStr("district")); | |||
| setCheckDistrict(true); | |||
| notifyActionError(intl.formatMessage({ id: 'require' }, { fieldname: intl.formatMessage({ id: 'district' }) })); | |||
| @@ -550,15 +566,15 @@ const CustomFormWizard = (props) => { | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewPersonalUser" /> | |||
| </Typography> | |||
| </div> | |||
| <Typography mt={0.25} variant="h6" sx={{ color: '#B00020' }}> | |||
| <Typography mt={0.25} variant="h6" component="span" sx={{ color: '#B00020' }}> | |||
| <FormattedMessage id="requireString" />。 | |||
| </Typography> | |||
| <Stack mt={1} direction="row" style={{ alignItems: "center" }}><img src={iAmSmartICon} alt="iAM Smart" width="25" /><Typography mt={0.25} variant="h6" >: <FormattedMessage id="MSG.providedByIAmSmart" /></Typography></Stack> | |||
| <Stack mt={1} direction="row" style={{ alignItems: "center" }}><img src={iAmSmartICon} alt="iAM Smart" width="25" /><Typography mt={0.25} variant="h6" component="span" >: <FormattedMessage id="MSG.providedByIAmSmart" /></Typography></Stack> | |||
| </Stack> | |||
| </Grid> | |||
| @@ -566,7 +582,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid container spacing={1}> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourPersonalInformation" /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -575,17 +591,20 @@ const CustomFormWizard = (props) => { | |||
| <Grid container sx={{ mb: 1 }}> | |||
| <InputLabel htmlFor="idDocType-signup"> | |||
| <Typography variant="h5" sx={{ mr: 1 }}> | |||
| <Typography variant="h5" component="span" sx={{ mr: 1 }}> | |||
| <FormattedMessage id="HKIDcard" />: {iAmSmartData.idNo ? <img src={iAmSmartICon} alt="iAM Smart" width="25" /> : <></>} | |||
| {/* {iAmSmartData.idNo + "(" + iAmSmartData.checkDigit + ")"} */} | |||
| </Typography> | |||
| <Stack direction="row"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| {iAmSmartData?.idNo?.slice(0, 4)}{showId ? iAmSmartData?.idNo?.slice(4) : "****"}{showId ? '(' + iAmSmartData.checkDigit + ')' : null} | |||
| </Typography> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||
| onClick={handleClickShowId} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowId)} | |||
| onMouseDown={handleMouseDownId} | |||
| edge="end" | |||
| size="medium" | |||
| @@ -600,7 +619,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="enName-signup"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="userEnglishName" />: {iAmSmartData.enName}{iAmSmartData.enName ? <img src={iAmSmartICon} alt="iAM Smart" width="25" /> : <></>} | |||
| </Typography> | |||
| @@ -610,7 +629,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="chName-signup"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| {intl.formatMessage({ id: 'userChineseName' })}: {iAmSmartData.chName}{iAmSmartData.chName ? <img src={iAmSmartICon} alt="iAM Smart" width="25" /> : <></>} | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -619,7 +638,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="address1-signup"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="formAddress" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| @@ -638,6 +657,7 @@ const CustomFormWizard = (props) => { | |||
| placeholder={intl.formatMessage({ id: 'addressLine1' })} | |||
| onBlur={formik.handleBlur} | |||
| inputProps={{ | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -659,6 +679,7 @@ const CustomFormWizard = (props) => { | |||
| onChange={formik.handleChange} | |||
| placeholder={intl.formatMessage({ id: 'addressLine2' })} | |||
| inputProps={{ | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -681,6 +702,7 @@ const CustomFormWizard = (props) => { | |||
| onChange={formik.handleChange} | |||
| placeholder={intl.formatMessage({ id: 'addressLine3' })} | |||
| inputProps={{ | |||
| maxLength: ADDRESS_LINE_MAX_LENGTH, | |||
| onKeyDown: (e) => { | |||
| if (e.key === 'Enter') { | |||
| e.preventDefault(); | |||
| @@ -772,7 +794,7 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact" /> | |||
| </Typography> | |||
| </Stack> | |||
| @@ -782,7 +804,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}> | |||
| <InputLabel htmlFor="email-login"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="userContactEmail" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| @@ -828,7 +850,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} > | |||
| <InputLabel htmlFor="emailConfirm-login"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="confirmEmail" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -877,7 +899,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Stack direction="column" spacing={1} sx={{ mr: { md: 1 }, mb: 1 }}> | |||
| <InputLabel htmlFor="phone-signup"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="userContactNumber" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| @@ -956,7 +978,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="column"> | |||
| <InputLabel htmlFor="fax-signup"> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="userFaxNumber" /> | |||
| </Typography> | |||
| </InputLabel> | |||
| @@ -1023,7 +1045,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="termsAndCondition" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1031,7 +1053,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12}> | |||
| <Typography variant="h5" sx={{ textAlign: "left", borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0C489E" }}> | |||
| <Typography sx={{ textAlign: "left", borderRadius: "inherit", borderStyle: "solid", borderWidth: "1px", borderColor: "#0c489e" }}> | |||
| <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "termsAndCon" }) }} /> | |||
| </Typography> | |||
| @@ -1049,7 +1071,7 @@ const CustomFormWizard = (props) => { | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="iConfirm" /> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -1066,7 +1088,7 @@ const CustomFormWizard = (props) => { | |||
| size="small" | |||
| /> | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| <FormattedMessage id="rejectTerms" /> | |||
| </Typography> | |||
| </Grid> | |||
| @@ -1080,7 +1102,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} lg={12}> | |||
| <Grid container> | |||
| <Stack direction="column"> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="verify" /> | |||
| <span style={{ color: '#B00020' }}>*</span> | |||
| </Typography> | |||
| @@ -1089,7 +1111,14 @@ const CustomFormWizard = (props) => { | |||
| <img src={captchaImg} alt="" /> | |||
| </Grid> | |||
| <Grid item xs={1} lg={1} style={{ "border": "0px solid black" }}> | |||
| <IconButton aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} size="large" onClick={() => { onCaptchaChange() }}> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaRefreshCaptcha' })} | |||
| size="large" | |||
| onClick={() => { onCaptchaChange() }} | |||
| onKeyDown={(event) => handleActionKeyDown(event, () => onCaptchaChange())} | |||
| > | |||
| <LoopIcon fontSize="inherit" /> | |||
| </IconButton> | |||
| </Grid> | |||
| @@ -1123,9 +1152,9 @@ const CustomFormWizard = (props) => { | |||
| onClick={playCaptchaAudio} | |||
| aria-label={intl.formatMessage({ id: "captchaPlayAudio" })} | |||
| sx={{ | |||
| backgroundColor: '#0C489E', | |||
| backgroundColor: '#0c489e', | |||
| color: '#FFFFFF', | |||
| '&:hover': { backgroundColor: '#093A7A' }, | |||
| '&:hover': { backgroundColor: '#1565c0' }, | |||
| }} | |||
| > | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| @@ -1143,7 +1172,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid item xs={12} md={12}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <div style={{ borderBottom: "3px solid #1A4399", width: "100%", margin_right: "15px" }}> | |||
| <Typography display="inline" variant="h3" sx={{ color: '#1A4399' }}> | |||
| <Typography display="inline" variant="h3" component="h1" sx={{ color: '#1A4399' }}> | |||
| <FormattedMessage id="becomeNewPersonalUser" /> | |||
| </Typography> | |||
| </div> | |||
| @@ -1153,7 +1182,7 @@ const CustomFormWizard = (props) => { | |||
| <Grid container spacing={2}> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourPersonalInformation" /> | |||
| </Typography> | |||
| {/* <Typography component={Link} to="/login" variant="body1" sx={{ textDecoration: 'none' }} color="primary"> | |||
| @@ -1163,20 +1192,23 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} md={12} > | |||
| <Stack direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]} sx={{ mr: 1 }}> | |||
| <Typography variant="h5" component="h2" color={theme.palette.grey[600]} sx={{ mr: 1 }}> | |||
| <FormattedMessage id="userIdDoc" /> | |||
| </Typography> | |||
| <Typography variant="h5" name="preview-idDocType-1"> | |||
| <Typography variant="h5" component="span" name="preview-idDocType-1"> | |||
| {formik?.values?.idNo?.slice(0, 4)} | |||
| {/* {formik.values.idNo + "(" + formik.values.checkDigit + ")"} */} | |||
| </Typography> | |||
| <Typography variant="h5" name="preview-idDocType-2"> | |||
| <Typography variant="h5" component="span" name="preview-idDocType-2"> | |||
| {showComId ? formik?.values?.idNo?.slice(4) : "****"}{showComId ? '(' + formik.values.checkDigit + ')' : null} | |||
| {/* {formik.values.idNo + "(" + formik.values.checkDigit + ")"} */} | |||
| </Typography> | |||
| <IconButton | |||
| role="button" | |||
| tabIndex={0} | |||
| aria-label={intl.formatMessage({ id: 'ariaToggleIdVisibility' })} | |||
| onClick={handleClickShowComId} | |||
| onKeyDown={(event) => handleActionKeyDown(event, handleClickShowComId)} | |||
| onMouseDown={handleMouseDownComId} | |||
| edge="end" | |||
| size="medium" | |||
| @@ -1187,10 +1219,10 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="userEnglishName" />: | |||
| </Typography> | |||
| <Typography variant="h5" id="preview-enName-signup"> | |||
| <Typography variant="h5" component="span" id="preview-enName-signup"> | |||
| {formik.values.enName} | |||
| </Typography> | |||
| {iAmSmartData.enName ? <img src={iAmSmartICon} alt="iAM Smart" width="25" /> : <></>} | |||
| @@ -1198,48 +1230,48 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="userChineseName" />: | |||
| </Typography> | |||
| <Typography variant="h5" id="preview-chName-signup"> | |||
| <Typography variant="h5" component="span" id="preview-chName-signup"> | |||
| {formik.values.chName} | |||
| </Typography> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Stack spacing={1} direction="column"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="formAddress" />: | |||
| </Typography> | |||
| <Stack spacing={1} direction="column"> | |||
| <Typography variant="h5" id="preview-address1-signup"> | |||
| <Typography variant="h5" component="span" id="preview-address1-signup"> | |||
| {formik.values.address1} | |||
| </Typography> | |||
| {formik.values.address2 != null ? | |||
| <Typography variant="h5" id="preview-address2-signup"> | |||
| <Typography variant="h5" component="span" id="preview-address2-signup"> | |||
| {formik.values.address2} | |||
| </Typography> | |||
| : null} | |||
| {formik.values.address3 != null ? | |||
| <Typography variant="h5" id="preview-address3-signup"> | |||
| <Typography variant="h5" component="span" id="preview-address3-signup"> | |||
| {formik.values.address3} | |||
| </Typography> | |||
| : null} | |||
| {selectedAddress5.type === "hongKong" ? | |||
| <Stack direction="column"> | |||
| {/* <Typography variant="h5" color={theme.palette.grey[600]} id="preview-address4-signup"> | |||
| {/* <Typography variant="h5" component="span" color={theme.palette.grey[600]} id="preview-address4-signup"> | |||
| <FormattedMessage id="region" />: | |||
| </Typography> */} | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| {!selectedAddress4 ? "" : intl.formatMessage({ id: selectedAddress4.type })} | |||
| </Typography> | |||
| </Stack> | |||
| : null} | |||
| <Stack direction="column"> | |||
| {/* <Typography variant="h5" color={theme.palette.grey[600]} id="preview-address5-signup"> | |||
| {/* <Typography variant="h5" component="span" color={theme.palette.grey[600]} id="preview-address5-signup"> | |||
| <FormattedMessage id="regionOrCountry" />: | |||
| </Typography> */} | |||
| <Typography variant="h5"> | |||
| <Typography variant="h5" component="span"> | |||
| {intl.formatMessage({ id: selectedAddress5.type })} | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1248,27 +1280,27 @@ const CustomFormWizard = (props) => { | |||
| </Grid> | |||
| <Grid item xs={12} mt={1} mb={1}> | |||
| <Stack direction="column" justifyContent="space-between" alignItems="baseline" sx={{ mb: { xs: -0.5, sm: 0.5 } }}> | |||
| <Typography display="inline" variant="h4" sx={{ color: 'primary.primary' }}> | |||
| <Typography display="inline" variant="h4" component="h2" sx={{ color: 'primary.primary' }}> | |||
| <FormattedMessage id="yourContact" /> | |||
| </Typography> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12} md={12}> | |||
| <Stack spacing={1} direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="userContactEmail" />: | |||
| </Typography> | |||
| <Typography variant="h5" id="preview-email-signup"> | |||
| <Typography variant="h5" component="span" id="preview-email-signup"> | |||
| {formik.values.email} | |||
| </Typography> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="userContactNumber" />: | |||
| </Typography> | |||
| <Typography variant="h5" id="preview-phone-signup"> | |||
| <Typography variant="h5" component="span" id="preview-phone-signup"> | |||
| +{formik.values.phoneCountryCode} {formik.values.phone} | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1276,10 +1308,10 @@ const CustomFormWizard = (props) => { | |||
| {formik.values.faxCountryCode != "" && formik.values.fax != "" ? | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} direction="row"> | |||
| <Typography variant="h5" color={theme.palette.grey[600]}> | |||
| <Typography variant="h5" component="span" color={theme.palette.grey[600]}> | |||
| <FormattedMessage id="userFaxNumber" />: | |||
| </Typography> | |||
| <Typography variant="h5" id="preview-fax-signup"> | |||
| <Typography variant="h5" component="span" id="preview-fax-signup"> | |||
| +{formik.values.faxCountryCode} {formik.values.fax} | |||
| </Typography> | |||
| </Stack> | |||
| @@ -1299,13 +1331,13 @@ const CustomFormWizard = (props) => { | |||
| // SUCCESS page | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| <CheckCircleOutlineIcon color="success" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerSubmitted" /> | |||
| </Typography> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="emailSent" /> | |||
| </Typography> | |||
| <Button variant="outlined" component={Link} to="/login" ><Typography variant="h5"> | |||
| <Button variant="outlined" component={Link} to="/login" ><Typography variant="h5" component="span"> | |||
| <FormattedMessage id="backToLogin" /> | |||
| </Typography></Button> | |||
| </Stack> | |||
| @@ -1314,10 +1346,10 @@ const CustomFormWizard = (props) => { | |||
| <Stack mt={1} direction="column" justifyContent="flex-start" alignItems="center" spacing={2}> | |||
| {/* <Button disabled={true} hidden={true} variant="contained" type="submit" sx={{ fontSize: 12,height:'25px'}}>Submit</Button> */} | |||
| <CancelOutlinedIcon color="error" sx={{ width: "200px", height: "200px" }} /> | |||
| <Typography display="inline" variant="h4"> | |||
| <Typography display="inline" variant="h4" component="span"> | |||
| <FormattedMessage id="registerFail" /> | |||
| </Typography> | |||
| <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="h5"> | |||
| <Button color="error" variant="outlined" component={Link} to="/login" ><Typography variant="h5" component="span"> | |||
| <FormattedMessage id="backToLogin" /> | |||
| </Typography></Button> | |||
| </Stack> | |||
| @@ -1,116 +1,88 @@ | |||
| // material-ui | |||
| import RemoveCircleOutlineIcon from '@mui/icons-material/RemoveCircleOutline'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| GridRowModes | |||
| } from "@mui/x-data-grid"; | |||
| import * as React from 'react'; | |||
| import { useEffect } from "react"; | |||
| // import {useNavigate} from "react-router-dom"; | |||
| // import { useTheme } from '@mui/material/styles'; | |||
| import { | |||
| Box, | |||
| Stack, | |||
| Table, | |||
| TableBody, | |||
| TableCell, | |||
| TableHead, | |||
| TableRow, | |||
| Typography | |||
| } from '@mui/material'; | |||
| import { FormattedMessage, useIntl } from "react-intl"; | |||
| import FileDeleteButton from 'components/FileDeleteButton'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UploadFileTable({ recordList, setUpdateRows, }) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel, setRowModesModel] = React.useState({}); | |||
| // const theme = useTheme(); | |||
| const intl = useIntl(); | |||
| // const navigate = useNavigate() | |||
| useEffect(() => { | |||
| setRows(recordList); | |||
| // console.log(disableDelete); | |||
| }, [recordList]); | |||
| function NoRowsOverlay() { | |||
| const handleCancelClick = (id) => { | |||
| setRows((prevRows) => { | |||
| const newRows = prevRows.filter((row) => row.id !== id); | |||
| setUpdateRows(newRows); | |||
| return newRows; | |||
| }); | |||
| }; | |||
| const formatFileSize = (size) => `${Math.ceil(size / 1024)} KB`; | |||
| if (rows.length === 0) { | |||
| return ( | |||
| <Stack height="100%" alignItems="center" justifyContent="center"> | |||
| <Box | |||
| sx={{ | |||
| height: '200px', | |||
| width: '100%', | |||
| border: 1, | |||
| borderColor: 'divider', | |||
| display: 'flex', | |||
| alignItems: 'center', | |||
| justifyContent: 'center', | |||
| }} | |||
| > | |||
| <Typography variant="h6"> | |||
| <FormattedMessage id="noFile"/> | |||
| </Typography> | |||
| {/* <pre>(rows={[]})</pre> */} | |||
| </Stack> | |||
| </Box> | |||
| ); | |||
| } | |||
| const handleCancelClick = (id) => () => { | |||
| setRowModesModel({ | |||
| ...rowModesModel, | |||
| [id]: { mode: GridRowModes.View, ignoreModifications: true }, | |||
| }); | |||
| // console.log("Starting Delete") | |||
| // const editedRow = rows.find((row) => row.id === id); | |||
| // console.log(editedRow) | |||
| // console.log(editedRow.isNew) | |||
| setUpdateRows(rows.filter((row) => row.id !== id)); | |||
| setRows(rows.filter((row) => row.id !== id)); | |||
| } | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: '', | |||
| width: 30, | |||
| cellClassName: 'actions', | |||
| // hide:true, | |||
| getActions: ({ id }) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<RemoveCircleOutlineIcon />} | |||
| label="delete" | |||
| className="textPrimary" | |||
| onClick={handleCancelClick(id)} | |||
| color="error" | |||
| />] | |||
| }, | |||
| }, | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| headerName: intl.formatMessage({ id: 'fileName' }), | |||
| flex: 4, | |||
| }, | |||
| { | |||
| id: 'size', | |||
| field: 'size', | |||
| headerName: intl.formatMessage({ id: 'fileSize' }), | |||
| valueGetter: (params) => { | |||
| // console.log(params) | |||
| return Math.ceil(params.value / 1024) + " KB"; | |||
| }, | |||
| flex: 2, | |||
| }, | |||
| ]; | |||
| return ( | |||
| <Box style={{ height: '200px', width: '100%' }}> | |||
| <DataGrid | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| sx={{ border: 1 }} | |||
| rowModesModel={rowModesModel} | |||
| disablePagination | |||
| components={{ NoRowsOverlay, }} | |||
| // hideFooterPagination={true} | |||
| disableSelectionOnClick | |||
| disableColumnMenu | |||
| disableColumnSelector | |||
| hideFooter | |||
| getRowHeight={()=>"auto"} | |||
| /> | |||
| <Box sx={{ height: '200px', width: '100%', border: 1, borderColor: 'divider', overflow: 'auto' }}> | |||
| <Table size="small" aria-label={intl.formatMessage({ id: 'fileName' })}> | |||
| <TableHead> | |||
| <TableRow> | |||
| <TableCell padding="checkbox" sx={{ width: 48 }} /> | |||
| <TableCell>{intl.formatMessage({ id: 'fileName' })}</TableCell> | |||
| <TableCell align="right">{intl.formatMessage({ id: 'fileSize' })}</TableCell> | |||
| </TableRow> | |||
| </TableHead> | |||
| <TableBody> | |||
| {rows.map((row) => ( | |||
| <TableRow key={row.id}> | |||
| <TableCell padding="checkbox"> | |||
| <FileDeleteButton onDelete={() => handleCancelClick(row.id)} /> | |||
| </TableCell> | |||
| <TableCell> | |||
| <Stack direction="row" alignItems="center"> | |||
| <Typography variant="body2">{row.name}</Typography> | |||
| </Stack> | |||
| </TableCell> | |||
| <TableCell align="right"> | |||
| <Typography variant="body2">{formatFileSize(row.size)}</Typography> | |||
| </TableCell> | |||
| </TableRow> | |||
| ))} | |||
| </TableBody> | |||
| </Table> | |||
| </Box> | |||
| ); | |||
| } | |||
| @@ -68,7 +68,7 @@ const ComponentColor = () => ( | |||
| <ColorBox bgcolor="primary.200" data={{ label: 'Blue-3', color: '#91d5ff' }} title="primary[200]" dark /> | |||
| <ColorBox bgcolor="primary.light" data={{ label: 'Blue-4', color: '#69c0ff' }} title="primary.light" dark /> | |||
| <ColorBox bgcolor="primary.400" data={{ label: 'Blue-5', color: '#40a9ff' }} title="primary[400]" /> | |||
| <ColorBox bgcolor="primary.main" data={{ label: 'Blue-6', color: '#1890ff' }} title="primary.main" main /> | |||
| <ColorBox bgcolor="primary.main" data={{ label: 'Blue-6', color: '#0c489e' }} title="primary.main" main /> | |||
| <ColorBox bgcolor="primary.dark" data={{ label: 'Blue-7', color: '#096dd9' }} title="primary.dark" /> | |||
| <ColorBox bgcolor="primary.700" data={{ label: 'Blue-8', color: '#0050b3' }} title="primary[700]" /> | |||
| <ColorBox bgcolor="primary.darker" data={{ label: 'Blue-9', color: '#003a8c' }} title="primary.darker" /> | |||
| @@ -45,7 +45,7 @@ const DashboardDefault = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| {getWelcomeMsg()}, {userData.fullenName} | |||
| </Typography> | |||
| </Stack> | |||
| @@ -32,9 +32,15 @@ const SearchDemandNoteForm = (props) => { | |||
| listData.map((item, index) => { | |||
| list.push( | |||
| <Stack key={item.id != null ? item.id : `announce-${index}`} direction="column"> | |||
| <Typography variant='h4' align="justify"><b>{locale === 'en' ?item.subjectEng:locale === 'zh-HK' ?item.subjectCht:item.subjectChs}</b></Typography> | |||
| <Typography align="justify">{DateUtils.dateValue(item.announceDate)}</Typography> | |||
| <Typography sx={{pt: 1}} align="justify">{locale === 'en' ?item.contentEng:locale === 'zh-HK' ?item.contentCht:item.contentChs}</Typography> | |||
| <Typography component="h3" variant="h5" align="justify"> | |||
| {locale === 'en' ? item.subjectEng : locale === 'zh-HK' ? item.subjectCht : item.subjectChs} | |||
| </Typography> | |||
| <Typography component="span" variant="subtitle2" sx={{ color: '#000' }} align="justify"> | |||
| {DateUtils.dateValue(item.announceDate)} | |||
| </Typography> | |||
| <Typography component="span" variant="h6" sx={{ pt: 1, fontWeight: 400 }} align="justify"> | |||
| {locale === 'en' ? item.contentEng : locale === 'zh-HK' ? item.contentCht : item.contentChs} | |||
| </Typography> | |||
| <Divider sx={{ pt: 1 }} /> | |||
| </Stack> | |||
| ) | |||
| @@ -100,22 +100,35 @@ const DashboardDefault = () => { | |||
| p: 2, | |||
| justifyContent: "flex-start", | |||
| textTransform: "none", | |||
| fontSize: "inherit", | |||
| fontWeight: "inherit", | |||
| // text always readable | |||
| color: "#1A1A1A", | |||
| // unread gets subtle highlight | |||
| backgroundColor: item.readTime ? "transparent" : "#F5F7FA", | |||
| fontWeight: item.readTime ? 400 : 600, | |||
| "&:hover": { | |||
| backgroundColor: "#EEF2F7", | |||
| }, | |||
| }} | |||
| > | |||
| <Stack direction="column" > | |||
| <Typography variant='string' align="justify"><b>{item.subject}</b></Typography> | |||
| <Typography align="justify">{DateUtils.datetimeStr(item.sentDate)}</Typography> | |||
| <Stack direction="column"> | |||
| <Typography | |||
| component="h3" | |||
| variant="h6" | |||
| align="justify" | |||
| sx={(theme) => ({ | |||
| ...theme.typography.h6, | |||
| fontWeight: item.readTime ? 400 : 600, | |||
| })} | |||
| > | |||
| {item.subject} | |||
| </Typography> | |||
| <Typography component="span" variant="subtitle2" sx={{ color: '#000' }} align="justify"> | |||
| {DateUtils.datetimeStr(item.sentDate)} | |||
| </Typography> | |||
| </Stack> | |||
| </Button> | |||
| )); | |||
| @@ -191,9 +204,9 @@ const DashboardDefault = () => { | |||
| p: 4, | |||
| justifyContent: "flex-start", | |||
| backgroundColor: "#e1edfc", | |||
| border: "0px solid #0C489E", // DARKER border (3:1+) | |||
| border: "0px solid #0c489e", // DARKER border (3:1+) | |||
| borderRadius: "10px", | |||
| color: "#0C489E", // icon + default text color | |||
| color: "#1565C0", // icon + default text color | |||
| "&:hover": { | |||
| backgroundColor: "#d6e6fb" | |||
| } | |||
| @@ -202,7 +215,7 @@ const DashboardDefault = () => { | |||
| <Stack direction="row" spacing={2}> | |||
| <AdsClickRoundedIcon /> | |||
| <Stack direction="column" alignItems="flex-start"> | |||
| <Typography component="h2" variant="h4" sx={{ color: "#0C489E" }}> | |||
| <Typography component="h2" variant="h4" sx={{ color: "#1565C0" }}> | |||
| <FormattedMessage id="submitApplication" /> | |||
| </Typography> | |||
| <Typography sx={{ color: "#1A1A1A" }}> | |||
| @@ -220,7 +233,7 @@ const DashboardDefault = () => { | |||
| aria-label={intl.formatMessage({ id: 'viewAllAnnouncement' })} | |||
| onClick={() => { navigate("/announcement/search"); }} | |||
| sx={{ | |||
| color: '#0C489E', | |||
| color: '#1565C0', | |||
| textTransform: 'none', | |||
| textDecoration: 'underline', | |||
| '&:hover': { textDecoration: 'underline' } | |||
| @@ -245,7 +258,7 @@ const DashboardDefault = () => { | |||
| aria-label={intl.formatMessage({ id: 'viewAllSystemMessage' })} | |||
| onClick={() => { navigate("/msg/search"); }} | |||
| sx={{ | |||
| color: '#0C489E', | |||
| color: '#1565C0', | |||
| textTransform: 'none', | |||
| textDecoration: 'underline', | |||
| '&:hover': { | |||
| @@ -256,7 +269,7 @@ const DashboardDefault = () => { | |||
| <FormattedMessage id="viewAllSystemMessage" /> | |||
| </u></Button> | |||
| </Stack> | |||
| <Box xs={12} md={12} sx={{ p: 1, fontSize: 12, border: '3px solid #eee', borderRadius: '10px' }} > | |||
| <Box xs={12} md={12} sx={{ p: 1, border: '3px solid #eee', borderRadius: '10px' }} > | |||
| <Message | |||
| itemList = {itemList} | |||
| /> | |||
| @@ -281,7 +294,7 @@ const DashboardDefault = () => { | |||
| <FormattedMessage id="systemNotice" /> | |||
| </Typography> | |||
| </DialogTitle> | |||
| <DialogContent style={{ color: 'red', display: 'flex', }}> | |||
| <DialogContent style={{ color: '#B00020', display: 'flex', }}> | |||
| <Typography variant="h5" style={{ padding: '16px' }}> | |||
| <div dangerouslySetInnerHTML={{ __html: intl.formatMessage({ id: "suspensionMessageText" }) }} /> | |||
| </Typography> | |||
| @@ -23,7 +23,7 @@ const BackgroundHead = { | |||
| height: "auto", | |||
| backgroundSize: "contain", | |||
| backgroundRepeat: "no-repeat", | |||
| backgroundColor: "#0C489E", | |||
| backgroundColor: "#0c489e", | |||
| backgroundPosition: "right", | |||
| }; | |||
| @@ -226,7 +226,7 @@ const UserMaintainPage = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}>{isNewRecord ? "Create User Group" : "Maintain User Group"}</Typography> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}>{isNewRecord ? "Create User Group" : "Maintain User Group"}</Typography> | |||
| </Stack> | |||
| </div> | |||
| </Grid> | |||
| @@ -72,7 +72,7 @@ const UserGroupSearchPanel = () => { | |||
| <Grid item xs={12}> | |||
| <div style={BackgroundHead}> | |||
| <Stack direction="row" height='70px' justifyContent="flex-start" alignItems="center"> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0C489E" }}> | |||
| <Typography ml={15} color='#FFF' variant="h4" sx={{ "textShadow": "0px 0px 25px #0c489e" }}> | |||
| View User Group | |||
| </Typography> | |||
| </Stack> | |||
| @@ -30,6 +30,8 @@ const EmailTemplateDetailPage = Loadable(lazy(() => import('pages/EmailTemplate/ | |||
| const HolidayPage = Loadable(lazy(() => import('pages/Holiday'))); | |||
| const GazetteIssuePage = Loadable(lazy(() => import('pages/GazetteIssue/index'))); | |||
| const DrImport = Loadable(lazy(() => import('pages/Setting/DrImport'))); | |||
| const HkidKeyMigration = Loadable(lazy(() => import('pages/Setting/HkidKeyMigration'))); | |||
| const UserPiiEncryption = Loadable(lazy(() => import('pages/Setting/UserPiiEncryption'))); | |||
| const AuditLogPage = Loadable(lazy(() => import('pages/AuditLog/index'))); | |||
| const ReconReportPage = Loadable(lazy(() => import('pages/Recon'))); | |||
| const ChangePasswordPage = Loadable(lazy(() => import('pages/User/ChangePasswordPage'))); | |||
| @@ -190,6 +192,18 @@ const GLDUserRoutes = { | |||
| element: <DrImport /> | |||
| }:{}, | |||
| isGranted("MAINTAIN_SETTING")? | |||
| { | |||
| path: '/setting/hkidKeyMigration', | |||
| element: <HkidKeyMigration /> | |||
| }:{}, | |||
| isGranted("MAINTAIN_SETTING")? | |||
| { | |||
| path: '/setting/userPiiEncryption', | |||
| element: <UserPiiEncryption /> | |||
| }:{}, | |||
| isGranted("MAINTAIN_SETTING")? | |||
| { | |||
| path: '/setting/auditLog', | |||
| @@ -20,7 +20,7 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| }, | |||
| save:{ | |||
| main: '#448DF2', | |||
| main: '#0c489e', | |||
| contrastText: '#FFFFFF', | |||
| }, | |||
| export:{ | |||
| @@ -44,7 +44,7 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| contrastText: '#FFFFFF', | |||
| }, | |||
| success:{ | |||
| main: '#448DF2', | |||
| main: '#0c489e', | |||
| contrastText: '#FFFFFF', | |||
| }, | |||
| green:{ | |||
| @@ -69,6 +69,9 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| }, | |||
| }, | |||
| MuiButton: { | |||
| defaultProps: { | |||
| disableRipple: true, | |||
| }, | |||
| styleOverrides: { | |||
| /* ----------------------------- | |||
| Icon alignment | |||
| @@ -93,17 +96,24 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| '@media (min-width: 1280px)': { minWidth: '9vw' }, | |||
| textTransform: 'none', | |||
| alignItems: 'normal', | |||
| '&:active': { | |||
| boxShadow: 'none', | |||
| transform: 'none', | |||
| }, | |||
| }, | |||
| /* ----------------------------- | |||
| Remove default contained elevation / blue focus | |||
| ------------------------------ */ | |||
| contained: { | |||
| contained: ({ theme, ownerState }) => ({ | |||
| boxShadow: 'none', | |||
| '&:hover': { boxShadow: 'none' }, | |||
| '&:active': { boxShadow: 'none' }, | |||
| '&.Mui-focusVisible': { boxShadow: 'none' }, | |||
| '&:active': { | |||
| backgroundColor: theme.palette[ownerState.color]?.main ?? theme.palette.primary.main, | |||
| boxShadow: 'none', | |||
| }, | |||
| '&.Mui-focusVisible': { boxShadow: 'none' }, | |||
| }), | |||
| /* ----------------------------- | |||
| RESET / CANCEL (contained + cancel) | |||
| @@ -123,7 +133,7 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| }, | |||
| '&:active': { | |||
| backgroundColor: '#4A4A4A', | |||
| backgroundColor: '#616161', | |||
| boxShadow: 'none !important', | |||
| }, | |||
| @@ -145,10 +155,20 @@ export const PNSPS_BUTTON_THEME = createTheme({ | |||
| backgroundColor: 'transparent', | |||
| }, | |||
| '&:active': { | |||
| backgroundColor: 'transparent', | |||
| }, | |||
| '&.Mui-focusVisible': { | |||
| boxShadow: '0 0 0 3px rgba(66,66,66,0.4)', | |||
| }, | |||
| }, | |||
| outlined: { | |||
| '&:active': { | |||
| backgroundColor: 'transparent', | |||
| }, | |||
| }, | |||
| }, | |||
| }, | |||
| } | |||
| @@ -174,7 +194,7 @@ export const PNSPS_LONG_BUTTON_THEME = createTheme({ | |||
| }, | |||
| save:{ | |||
| main: '#448DF2', | |||
| main: '#0c489e', | |||
| contrastText: '#FFFFFF', | |||
| }, | |||
| export:{ | |||
| @@ -215,6 +235,9 @@ export const PNSPS_LONG_BUTTON_THEME = createTheme({ | |||
| }, | |||
| }, | |||
| MuiButton: { | |||
| defaultProps: { | |||
| disableRipple: true, | |||
| }, | |||
| styleOverrides: { | |||
| startIcon:{ | |||
| display: 'flex', | |||
| @@ -240,6 +263,24 @@ export const PNSPS_LONG_BUTTON_THEME = createTheme({ | |||
| }, | |||
| textTransform: "none", | |||
| alignItems: 'normal', | |||
| '&:active': { | |||
| boxShadow: 'none', | |||
| transform: 'none', | |||
| }, | |||
| }, | |||
| contained: ({ theme, ownerState }) => ({ | |||
| boxShadow: 'none', | |||
| '&:hover': { boxShadow: 'none' }, | |||
| '&:active': { | |||
| backgroundColor: theme.palette[ownerState.color]?.main ?? theme.palette.primary.main, | |||
| boxShadow: 'none', | |||
| }, | |||
| '&.Mui-focusVisible': { boxShadow: 'none' }, | |||
| }), | |||
| outlined: { | |||
| '&:active': { | |||
| backgroundColor: 'transparent', | |||
| }, | |||
| }, | |||
| }, | |||
| }, | |||
| @@ -28,7 +28,7 @@ export const piechartColor2 = [ | |||
| ]; | |||
| export const cardBorderColor = [ | |||
| '#efb142', '#4bb641', '#448df2', '#e03c04' | |||
| '#efb142', '#4bb641', '#0c489e', '#e03c04' | |||
| ]; | |||
| export const chartLineColor = [ | |||
| @@ -37,9 +37,9 @@ export const chartLineColor = [ | |||
| export const GENERAL_RED_COLOR = '#e03c04'; | |||
| export const TABLE_HEADER_TEXT_COLOR = "#3367D1"; | |||
| export const TABLE_HEADER_TEXT_COLOR = "#1565C0"; | |||
| export const GENERAL_INFO_COLOR = '#448df2'; | |||
| export const GENERAL_INFO_COLOR = '#0c489e'; | |||
| export const GENERAL_SETTING_COLOR = '#666666'; | |||
| @@ -49,6 +49,51 @@ export const GENERAL_BORDER_COLOR ='#e6ebf1'; | |||
| export const GENERAL_TEXT_COLOR ='#262626'; | |||
| /** Page header bar background (gazette banner strip). */ | |||
| export const HEADER_BACKGROUND_COLOR = '#0C489E'; | |||
| /** MUI default primary — used by applyPublicNotice contained button (PNSPS_LONG_BUTTON_THEME). WCAG AA: 3:1+ for UI components on white. */ | |||
| export const CONTAINED_PRIMARY_BLUE = '#0c489e'; | |||
| /** Validation error text/border — matches FormHelperText in styles.css (e.g. "Please enter password"). WCAG AA on white. */ | |||
| export const VALIDATION_ERROR_COLOR = '#B00020'; | |||
| export const PRIMARY_CONTAINED_BUTTON_SX = { | |||
| backgroundColor: CONTAINED_PRIMARY_BLUE, | |||
| color: '#FFFFFF', | |||
| '&:hover': { | |||
| backgroundColor: '#1565c0', | |||
| }, | |||
| }; | |||
| /** Dark green for Pay actions — matches PNSPS_BUTTON_THEME create color (#57B962), not light green (#4ac234). */ | |||
| export const CONTAINED_DARK_GREEN = '#57B962'; | |||
| export const PAY_CONTAINED_BUTTON_SX = { | |||
| backgroundColor: CONTAINED_DARK_GREEN, | |||
| color: '#FFFFFF', | |||
| '&:hover': { | |||
| backgroundColor: '#488F52', | |||
| }, | |||
| }; | |||
| export const PRIMARY_OUTLINED_BUTTON_SX = { | |||
| color: CONTAINED_PRIMARY_BLUE, | |||
| borderColor: CONTAINED_PRIMARY_BLUE, | |||
| '&:hover': { | |||
| borderColor: CONTAINED_PRIMARY_BLUE, | |||
| backgroundColor: 'rgba(25, 118, 210, 0.08)', | |||
| }, | |||
| }; | |||
| export const PRIMARY_TEXT_BUTTON_SX = { | |||
| color: CONTAINED_PRIMARY_BLUE, | |||
| fontWeight: 600, | |||
| '&:hover': { | |||
| backgroundColor: 'rgba(25, 118, 210, 0.08)', | |||
| }, | |||
| }; | |||
| export const formTheme = createTheme({ | |||
| components: { | |||
| MuiFormLabel: { | |||
| @@ -10,17 +10,29 @@ export default function Button(theme) { | |||
| return { | |||
| MuiButton: { | |||
| defaultProps: { | |||
| disableElevation: true | |||
| disableElevation: true, | |||
| disableRipple: true | |||
| }, | |||
| styleOverrides: { | |||
| root: { | |||
| fontWeight: 400 | |||
| }, | |||
| contained: { | |||
| ...disabledStyle | |||
| fontWeight: 400, | |||
| '&:active': { | |||
| boxShadow: 'none', | |||
| transform: 'none' | |||
| } | |||
| }, | |||
| contained: ({ theme: muiTheme, ownerState }) => ({ | |||
| ...disabledStyle, | |||
| '&:active': { | |||
| backgroundColor: muiTheme.palette[ownerState.color]?.main ?? muiTheme.palette.primary.main, | |||
| boxShadow: 'none' | |||
| } | |||
| }), | |||
| outlined: { | |||
| ...disabledStyle | |||
| ...disabledStyle, | |||
| '&:active': { | |||
| backgroundColor: 'transparent' | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,14 +1,31 @@ | |||
| // ==============================|| OVERRIDES - CHECKBOX ||============================== // | |||
| import { CONTAINED_PRIMARY_BLUE } from '../colorConst'; | |||
| export default function Checkbox(theme) { | |||
| const checkboxSize = "2rem" | |||
| return { | |||
| MuiCheckbox: { | |||
| defaultProps: { | |||
| disableRipple: true | |||
| }, | |||
| styleOverrides: { | |||
| root: { | |||
| color: theme.palette.secondary[300], | |||
| '&:hover': { | |||
| backgroundColor: 'transparent' | |||
| }, | |||
| '&:active': { | |||
| backgroundColor: 'transparent' | |||
| }, | |||
| '&.Mui-checked': { | |||
| color: CONTAINED_PRIMARY_BLUE | |||
| }, | |||
| '&.Mui-focusVisible': { | |||
| boxShadow: '0 0 0 3px rgba(25, 118, 210, 0.35)' | |||
| }, | |||
| svg: { | |||
| width: checkboxSize, | |||
| height: checkboxSize, | |||