| @@ -239,16 +239,25 @@ export function FiDataGrid({ rows, columns, sx, autoHeight = true, | |||
| ? { | |||
| Pagination: () => ( | |||
| <TablePagination | |||
| count={rowCount || 0} | |||
| page={page} | |||
| rowsPerPage={pageSize} | |||
| rowsPerPageOptions={_pageSizeOptions} | |||
| labelDisplayedRows={() => | |||
| `${(_rows?.length ? page * pageSize + 1 : 0)}-${page * pageSize + (_rows?.length ?? 0)} ${intl.formatMessage({ id: "of" })} ${rowCount}` | |||
| } | |||
| labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"} | |||
| onPageChange={handleChangePage} | |||
| onRowsPerPageChange={handleChangePageSize} | |||
| count={rowCount || 0} | |||
| page={page} | |||
| rowsPerPage={pageSize} | |||
| rowsPerPageOptions={_pageSizeOptions} | |||
| labelDisplayedRows={() => | |||
| `${(_rows?.length ? page * pageSize + 1 : 0)}-${page * pageSize + (_rows?.length ?? 0)} ${intl.formatMessage({ id: "of" })} ${rowCount}` | |||
| } | |||
| labelRowsPerPage={intl.formatMessage({ id: "rowsPerPage" }) + ":"} | |||
| getItemAriaLabel={(type) => { | |||
| if (type === 'previous') { | |||
| return intl.formatMessage({ id: 'paginationPrev' }); | |||
| } | |||
| if (type === 'next') { | |||
| return intl.formatMessage({ id: 'paginationNext' }); | |||
| } | |||
| return ''; | |||
| }} | |||
| onPageChange={handleChangePage} | |||
| onRowsPerPageChange={handleChangePageSize} | |||
| /> | |||
| ), | |||
| } | |||
| @@ -116,7 +116,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| <Grid item xs={12} s={6} md={6} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Grid container> | |||
| <Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -148,7 +148,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| </Grid> | |||
| <Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -186,6 +186,10 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData, _paymentCount, _p | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| <Grid item > | |||
| @@ -187,6 +187,10 @@ const SearchPublicNoticeForm = ({ applySearch, issueComboData }) => { | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -224,6 +224,10 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -282,6 +286,10 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue | |||
| {params.children} | |||
| </Grid> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| : <></> | |||
| @@ -445,6 +453,10 @@ const SearchDemandNoteForm = ({ applySearch, orgComboData, searchCriteria, issue | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -180,6 +180,10 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onG | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -210,7 +214,7 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onG | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -237,7 +241,7 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onG | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -293,6 +297,10 @@ const SearchDemandNoteForm = ({ applySearch, searchCriteria, issueComboData, onG | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -119,7 +119,7 @@ const SearchForm = ({ applySearch, searchCriteria, onGridReady }) => { | |||
| <Grid item xs={12} s={6} md={6} lg={4} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Grid container> | |||
| <Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -151,7 +151,7 @@ const SearchForm = ({ applySearch, searchCriteria, onGridReady }) => { | |||
| </Grid> | |||
| <Grid item xs={5.25} s={5.25} md={5.25} lg={5.5}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -440,7 +440,7 @@ const OrganizationCard = ({ userData, loadDataFun, id, setEditModeFun }) => { | |||
| value={fromDate != null ? DateUtils.dateStr(fromDate) : DateUtils.dateStr(currentFromDate)} | |||
| disabled={true} | |||
| /> : | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="brExpiryDate" | |||
| @@ -233,7 +233,7 @@ const OrganizationCard_loadFromUser = ({ userData, userId }) => { | |||
| <Typography variant="pnspsFormParagraphBold">{FieldUtils.notNullFieldLabel("Expiry Date:")}</Typography> | |||
| </Grid> | |||
| <Grid item xs={12} md={6} lg={6}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="brExpiryDate" | |||
| @@ -124,7 +124,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| <Grid item xs={12} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Grid container spacing={1}> | |||
| <Grid item xs={6}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -152,7 +152,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| </Grid> | |||
| <Grid item xs={6}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -213,6 +213,10 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -223,6 +223,10 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, o | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -252,7 +256,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, o | |||
| <Grid item xs={12} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <Grid container spacing={1}> | |||
| <Grid item xs={6}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -279,7 +283,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, o | |||
| </Grid> | |||
| <Grid item xs={6}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -353,6 +357,10 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, issueComboData, o | |||
| InputLabelProps={{ | |||
| shrink: true | |||
| }} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| @@ -401,6 +401,10 @@ export default function SubmittedTab({ setCount, url }) { | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField {...params} />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| </Grid> | |||
| </Grid> : null | |||
| @@ -138,7 +138,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateFrom" | |||
| @@ -166,7 +166,7 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ ml: 3, mr: 3, mb: 3 }}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs}> | |||
| <LocalizationProvider dateAdapter={AdapterDayjs} localeText={DateUtils.getPickerLocaleText(intl.locale)}> | |||
| <DemoItem components={['DatePicker']}> | |||
| <DatePicker | |||
| id="dateTo" | |||
| @@ -256,6 +256,10 @@ const SearchPublicNoticeForm = ({ applySearch, searchCriteria, onGridReady }) => | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| // InputLabelProps={{ | |||
| // shrink: true | |||
| // }} | |||
| @@ -241,7 +241,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -351,7 +353,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -163,7 +163,9 @@ const UserInformationCard = ({ isCollectData, updateUserObject, userData, isNewR | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -35,11 +35,13 @@ import { | |||
| isINDLoggedIn, | |||
| isORGLoggedIn | |||
| } from "utils/Utils"; | |||
| import {FormattedMessage} from "react-intl"; | |||
| import {FormattedMessage, useIntl} from "react-intl"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserMaintainPage_Individual = () => { | |||
| const intl = useIntl(); | |||
| const params = useParams(); | |||
| const navigate = useNavigate(); | |||
| const [formData, setFormData] = React.useState({}) | |||
| @@ -148,7 +150,8 @@ const UserMaintainPage_Individual = () => { | |||
| </div> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Button title="Back" | |||
| <Button title={intl.formatMessage({ id: "back" })} | |||
| aria-label={intl.formatMessage({ id: "back" })} | |||
| sx={{ ml: 3.5, mt: 2 }} style={{ border: '2px solid' }} | |||
| variant="outlined" onClick={() => { navigate(-1) }} | |||
| > | |||
| @@ -245,7 +245,7 @@ const UserMaintainPage_Organization = () => { | |||
| </div> | |||
| </Grid> | |||
| <Grid item xs={12}> | |||
| <Button title="Back" sx={{ ml: 3.5, mt: 2 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}> | |||
| <Button title={intl.formatMessage({ id: "back" })} aria-label={intl.formatMessage({ id: "back" })} sx={{ ml: 3.5, mt: 2 }} style={{ border: '2px solid' }} variant="outlined" onClick={() => { navigate(-1) }}> | |||
| <ForwardIcon style={{ height: 30, width: 50, transform: "rotate(180deg)" }} /> | |||
| </Button> | |||
| </Grid> | |||
| @@ -281,7 +281,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -338,7 +340,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -336,7 +336,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -401,7 +403,9 @@ const Index = () => { | |||
| endAdornment:( | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -164,7 +164,9 @@ const AuthLogin = () => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -323,7 +323,9 @@ const AuthLoginCustom = () => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -193,7 +193,9 @@ const AuthRegister = () => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -30,7 +30,7 @@ import * as yup from 'yup'; | |||
| import { strengthColorChi, strengthIndicator } from 'utils/password-strength'; | |||
| // import {apiPath} from "auth/utils"; | |||
| import axios from "axios"; | |||
| import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, POST_USERNAME, POST_USER_EMAIL } from "utils/ApiPathConst"; | |||
| import { POST_PUBLIC_USER_REGISTER, POST_CAPTCHA, POST_USERNAME, POST_USER_EMAIL, POST_CAPTCHA_AUDIO} from "utils/ApiPathConst"; | |||
| // import * as HttpUtils from 'utils/HttpUtils'; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -55,6 +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'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| const BusCustomFormWizard = (props) => { | |||
| @@ -118,6 +120,39 @@ const BusCustomFormWizard = (props) => { | |||
| changePassword(''); | |||
| }, []); | |||
| const playCaptchaAudio = async () => { | |||
| try { | |||
| const resp = await axios.post( | |||
| `${POST_CAPTCHA_AUDIO}`, | |||
| { base64Url, lang: intl.locale }, | |||
| { responseType: "arraybuffer" } | |||
| ); | |||
| const blob = new Blob([resp.data], { type: "audio/wav" }); | |||
| const url = URL.createObjectURL(blob); | |||
| const audio = new Audio(url); | |||
| await audio.play(); | |||
| } catch (error) { | |||
| let message = intl.formatMessage({ id: "captchaAudioError" }); | |||
| if (error.response) { | |||
| if (error.response.status === 404) { | |||
| message = intl.formatMessage({ id: "captchaExpired" }); | |||
| } else if (error.response.status === 500) { | |||
| message = intl.formatMessage({ id: "captchaAudioServerError" }); | |||
| } | |||
| } else if (error.request) { | |||
| message = intl.formatMessage({ id: "connectionError" }); | |||
| } | |||
| notifyActionError(message); | |||
| } | |||
| }; | |||
| const handleCheckUsername = async () => { | |||
| if (values?.username) { | |||
| const response = await axios.post(`${POST_USERNAME}`, { | |||
| @@ -712,7 +747,9 @@ const BusCustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -782,7 +819,9 @@ const BusCustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -1042,6 +1081,10 @@ const BusCustomFormWizard = (props) => { | |||
| }} | |||
| renderInput={(params) => <TextField error={checkDistrict} {...params} placeholder={intl.formatMessage({id: 'region'})} | |||
| />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| <Autocomplete | |||
| disablePortal | |||
| @@ -1091,6 +1134,10 @@ const BusCustomFormWizard = (props) => { | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({id: 'regionOrCountry'})} />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| {formik.touched.address1 && formik.errors.address1 && ( | |||
| <FormHelperText error id="helper-text-address1-signup"> | |||
| @@ -1514,6 +1561,11 @@ const BusCustomFormWizard = (props) => { | |||
| {formik.errors.captchaField} | |||
| </FormHelperText> | |||
| )} | |||
| <Stack spacing={1} direction="row"> | |||
| <Button onClick={playCaptchaAudio} aria-label={intl.formatMessage({id:"captchaPlayAudioAria"})}> | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| </Button> | |||
| </Stack> | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -25,7 +25,7 @@ import * as yup from 'yup'; | |||
| import { strengthColorChi, strengthIndicator } from 'utils/password-strength'; | |||
| // import {apiPath} from "auth/utils"; | |||
| import axios from "axios"; | |||
| import { POST_USERNAME, POST_USER_EMAIL, POST_CAPTCHA, POST_PUBLIC_USER_REGISTER, POST_IDNO } from "utils/ApiPathConst"; | |||
| import { POST_USERNAME, POST_USER_EMAIL, POST_CAPTCHA, POST_PUBLIC_USER_REGISTER, POST_IDNO, POST_CAPTCHA_AUDIO } from "utils/ApiPathConst"; | |||
| // import * as HttpUtils from 'utils/HttpUtils'; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -49,7 +49,7 @@ 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'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| const CustomFormWizard = (props) => { | |||
| @@ -137,6 +137,39 @@ const CustomFormWizard = (props) => { | |||
| onCaptchaChange(); | |||
| } | |||
| }, []); | |||
| const playCaptchaAudio = async () => { | |||
| try { | |||
| const resp = await axios.post( | |||
| `${POST_CAPTCHA_AUDIO}`, | |||
| { base64Url, lang: intl.locale }, | |||
| { responseType: "arraybuffer" } | |||
| ); | |||
| const blob = new Blob([resp.data], { type: "audio/wav" }); | |||
| const url = URL.createObjectURL(blob); | |||
| const audio = new Audio(url); | |||
| await audio.play(); | |||
| } catch (error) { | |||
| let message = intl.formatMessage({ id: "captchaAudioError" }); | |||
| if (error.response) { | |||
| if (error.response.status === 404) { | |||
| message = intl.formatMessage({ id: "captchaExpired" }); | |||
| } else if (error.response.status === 500) { | |||
| message = intl.formatMessage({ id: "captchaAudioServerError" }); | |||
| } | |||
| } else if (error.request) { | |||
| message = intl.formatMessage({ id: "connectionError" }); | |||
| } | |||
| notifyActionError(message); | |||
| } | |||
| }; | |||
| useEffect(() => { | |||
| if (selectedIdDocType.type === "HKID"){ | |||
| @@ -945,7 +978,9 @@ const CustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -1015,7 +1050,9 @@ const CustomFormWizard = (props) => { | |||
| endAdornment={ | |||
| <InputAdornment position="end"> | |||
| <IconButton | |||
| aria-label="toggle password visibility" | |||
| aria-label={intl.formatMessage({ | |||
| id: showConfirmPassword ? "ariaHidePassword" : "ariaShowPassword" | |||
| })} | |||
| onClick={handleClickShowConfirmPassword} | |||
| onMouseDown={handleMouseDownPassword} | |||
| edge="end" | |||
| @@ -1111,6 +1148,10 @@ const CustomFormWizard = (props) => { | |||
| error={formik.touched.idDocType && (selectedIdDocType === null || selectedIdDocType?.type == null)} | |||
| placeholder={intl.formatMessage({ id: 'idDocType' })} | |||
| />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| {formik.touched.idDocType && ( | |||
| selectedIdDocType === null || selectedIdDocType?.type == null ? | |||
| @@ -1412,6 +1453,10 @@ const CustomFormWizard = (props) => { | |||
| }} | |||
| renderInput={(params) => <TextField error={checkDistrict} {...params} placeholder={intl.formatMessage({ id: 'region' })} | |||
| />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| <Autocomplete | |||
| disablePortal | |||
| @@ -1462,6 +1507,10 @@ const CustomFormWizard = (props) => { | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({ id: 'regionOrCountry' })} />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| {formik.touched.address1 && formik.errors.address1 && ( | |||
| <FormHelperText error id="helper-text-address1-signup"> | |||
| @@ -1854,6 +1903,11 @@ const CustomFormWizard = (props) => { | |||
| {formik.errors.captchaField} | |||
| </FormHelperText> | |||
| )} | |||
| <Stack spacing={1} direction="row"> | |||
| <Button onClick={playCaptchaAudio} aria-label={intl.formatMessage({id:"captchaPlayAudioAria"})}> | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| </Button> | |||
| </Stack> | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -21,7 +21,7 @@ import { useFormik, FormikProvider } from 'formik'; | |||
| import * as yup from 'yup'; | |||
| import axios from "axios"; | |||
| import { POST_IAMSMART_USER_REGISTER, POST_CAPTCHA, POST_USER_EMAIL } from "utils/ApiPathConst"; | |||
| import { POST_IAMSMART_USER_REGISTER, POST_CAPTCHA, POST_USER_EMAIL, POST_CAPTCHA_AUDIO} from "utils/ApiPathConst"; | |||
| import * as ComboData from "utils/ComboData"; | |||
| @@ -40,6 +40,7 @@ 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'; | |||
| // ============================|| FIREBASE - REGISTER ||============================ // | |||
| @@ -86,6 +87,39 @@ const CustomFormWizard = (props) => { | |||
| responseToData(); | |||
| }, []); | |||
| const playCaptchaAudio = async () => { | |||
| try { | |||
| const resp = await axios.post( | |||
| `${POST_CAPTCHA_AUDIO}`, | |||
| { base64Url, lang: intl.locale }, | |||
| { responseType: "arraybuffer" } | |||
| ); | |||
| const blob = new Blob([resp.data], { type: "audio/wav" }); | |||
| const url = URL.createObjectURL(blob); | |||
| const audio = new Audio(url); | |||
| await audio.play(); | |||
| } catch (error) { | |||
| let message = intl.formatMessage({ id: "captchaAudioError" }); | |||
| if (error.response) { | |||
| if (error.response.status === 404) { | |||
| message = intl.formatMessage({ id: "captchaExpired" }); | |||
| } else if (error.response.status === 500) { | |||
| message = intl.formatMessage({ id: "captchaAudioServerError" }); | |||
| } | |||
| } else if (error.request) { | |||
| message = intl.formatMessage({ id: "connectionError" }); | |||
| } | |||
| notifyActionError(message); | |||
| } | |||
| }; | |||
| const handleClickShowId = () => { | |||
| setshowId(!showId); | |||
| }; | |||
| @@ -620,8 +654,12 @@ const CustomFormWizard = (props) => { | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField error={checkDistrict} {...params} placeholder={intl.formatMessage({ id: 'region' })} | |||
| renderInput={(params) => <TextField error={checkDistrict} {...params} placeholder={intl.formatMessage({ id: 'region' })} | |||
| />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| <Autocomplete | |||
| disablePortal | |||
| @@ -644,12 +682,16 @@ const CustomFormWizard = (props) => { | |||
| setCheckCountry(true) | |||
| } | |||
| }} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({ id: 'regionOrCountry' })} />} | |||
| sx={{ | |||
| '& .MuiInputBase-root': { alignItems: 'center' }, | |||
| '& .MuiAutocomplete-endAdornment': { top: '50%', transform: 'translateY(-50%)' }, | |||
| '& .MuiOutlinedInput-root': { height: 40 } | |||
| }} | |||
| renderInput={(params) => <TextField {...params} placeholder={intl.formatMessage({ id: 'regionOrCountry' })} />} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| {formik.touched.address1 && formik.errors.address1 && ( | |||
| <FormHelperText error id="helper-text-address1-signup"> | |||
| @@ -1014,6 +1056,11 @@ const CustomFormWizard = (props) => { | |||
| {formik.errors.captchaField} | |||
| </FormHelperText> | |||
| )} | |||
| <Stack spacing={1} direction="row"> | |||
| <Button onClick={playCaptchaAudio} aria-label={intl.formatMessage({id:"captchaPlayAudioAria"})}> | |||
| <FormattedMessage id="captchaPlayAudio" /> | |||
| </Button> | |||
| </Stack> | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| @@ -1,8 +1,8 @@ | |||
| const AboutUs = () => { | |||
| const Page = () => { | |||
| const content =` | |||
| <style> | |||
| const content = ` | |||
| <style> | |||
| .privacy-policy { | |||
| max-width: 900px; | |||
| margin: 0 auto 2rem; | |||
| @@ -12,58 +12,30 @@ const AboutUs = () => { | |||
| text-justify: inter-word; | |||
| } | |||
| .privacy-policy h1, | |||
| .privacy-policy h2, | |||
| .privacy-policy h3, | |||
| .privacy-policy h4 { | |||
| .privacy-policy h3 { | |||
| margin: 1.8rem 0 0.9rem; | |||
| font-weight: 600; | |||
| text-align: left; | |||
| } | |||
| .privacy-policy h2 { | |||
| font-size: 1.9rem; | |||
| } | |||
| .privacy-policy h3 { | |||
| font-size: 1.35rem; | |||
| } | |||
| .privacy-policy h4 { | |||
| font-size: 1.15rem; | |||
| } | |||
| .privacy-policy p { | |||
| margin: 0 0 1rem; | |||
| } | |||
| .privacy-policy ol { | |||
| margin: 0.5rem 0 1.6rem; | |||
| padding-left: 1.4rem; | |||
| } | |||
| /* Keep your visual sizes (map old h2->h1, h3->h2, h4->h3) */ | |||
| .privacy-policy h1 { font-size: 1.9rem; } /* was h2 */ | |||
| .privacy-policy h2 { font-size: 1.35rem; } /* was h3 */ | |||
| .privacy-policy h3 { font-size: 1.15rem; } /* was h4 */ | |||
| .privacy-policy ol li { | |||
| margin: 0.6rem 0; | |||
| } | |||
| .privacy-policy a { | |||
| text-decoration: underline; | |||
| } | |||
| .privacy-policy address { | |||
| font-style: normal; | |||
| line-height: 1.6; | |||
| margin-bottom: 1rem; | |||
| } | |||
| .privacy-policy .note { | |||
| font-size: 0.95rem; | |||
| font-style: italic; | |||
| } | |||
| </style> | |||
| .privacy-policy p { margin: 0 0 1rem; } | |||
| .privacy-policy ol { margin: 0.5rem 0 1.6rem; padding-left: 1.4rem; } | |||
| .privacy-policy ol li { margin: 0.6rem 0; } | |||
| .privacy-policy a { text-decoration: underline; } | |||
| .privacy-policy address { font-style: normal; line-height: 1.6; margin-bottom: 1rem; } | |||
| .privacy-policy .note { font-size: 0.95rem; font-style: italic; } | |||
| </style> | |||
| <div class="privacy-policy"> | |||
| <div class="privacy-policy"> | |||
| <h2>私隐政策</h2> | |||
| <h1>私隐政策</h1> | |||
| <p> | |||
| 保障个人资料私隐是政府物流服务署每位成员所关注的事宜。我们尊重个人资料私隐,并承诺全面执行及遵从保障资料原则及《个人资料(私隐)条例》的所有相关条文。政府物流服务署建立及实施系统监控,以确保遵从以下六项保障资料原则: | |||
| @@ -75,22 +47,22 @@ const AboutUs = () => { | |||
| <li>所收集的个人资料只可用作收集资料时资料会被使用于的目的或直接有关的目的,除非有关个人已就更改使用明示同意或法律准许有关使用;</li> | |||
| <li>采取所有切实可行的步骤,以确保个人资料受保障而不受未获准许或意外的查阅、处理、删除或使用所影响;</li> | |||
| <li>采取所有切实可行的步骤,以确保任何人能获政府物流服务署告知所持有的个人资料的种类及资料将会为什么目的而使用的;以及</li> | |||
| <li>准许资料当事人查阅/改正其个人资料及以法律准许或规定的方式处理任何查阅/改正个人资料的要求。 </li> | |||
| <li>准许资料当事人查阅/改正其个人资料及以法律准许或规定的方式处理任何查阅/改正个人资料的要求。</li> | |||
| </ol> | |||
| <h3>收集个人资料声明</h3> | |||
| <h2>收集个人资料声明</h2> | |||
| <h4>收集资料的目的</h4> | |||
| <h3>收集资料的目的</h3> | |||
| <p> | |||
| 申请人在本网站内所提供的个人资料会供申请刊登公共启事及为承担法律责任用途。在本网站提供的个人资料是自愿的。如果申请人未有提供足够资料,我们可能无法处理相关公共启事的刊登事宜。 | |||
| </p> | |||
| <h4>披露个人资料</h4> | |||
| <h3>披露个人资料</h3> | |||
| <p> | |||
| 政府物流服务署可能会向其他政策局/部门披露你在本网站提供的个人资料。 | |||
| </p> | |||
| <h4>查阅个人资料</h4> | |||
| <h3>查阅个人资料</h3> | |||
| <p> | |||
| 如要查阅或改正本署所持有的个人资料,请向以下人士提出: | |||
| </p> | |||
| @@ -103,14 +75,18 @@ const AboutUs = () => { | |||
| </address> | |||
| <p class="note"> | |||
| (注:请以个人资料私隐专员指定的<a target="_blank" href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_c.pdf">表格</a>提出查阅资料申请。) | |||
| (注:请以个人资料私隐专员指定的 | |||
| <a target="_blank" rel="noopener noreferrer" | |||
| href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_c.pdf"> | |||
| 表格 | |||
| </a> | |||
| 提出查阅资料申请。) | |||
| </p> | |||
| </div> | |||
| ` | |||
| ; | |||
| </div> | |||
| `; | |||
| return (<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />); | |||
| return (<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />); | |||
| } | |||
| export default AboutUs; | |||
| export default Page; | |||
| @@ -1,148 +1,137 @@ | |||
| const Page = () => { | |||
| const content = ` | |||
| <style> | |||
| .privacy-policy { | |||
| max-width: 900px; | |||
| margin: 0 auto 2rem; | |||
| font-size: 1.05rem; | |||
| line-height: 1.75; | |||
| text-align: justify; | |||
| text-justify: inter-word; | |||
| } | |||
| .privacy-policy h2, | |||
| .privacy-policy h3, | |||
| .privacy-policy h4 { | |||
| margin: 1.8rem 0 0.9rem; | |||
| font-weight: 600; | |||
| text-align: left; /* Updated */ | |||
| } | |||
| .privacy-policy h2 { | |||
| font-size: 1.9rem; | |||
| } | |||
| .privacy-policy h3 { | |||
| font-size: 1.35rem; | |||
| } | |||
| .privacy-policy h4 { | |||
| font-size: 1.15rem; | |||
| } | |||
| .privacy-policy p { | |||
| margin: 0 0 1rem; | |||
| } | |||
| .privacy-policy ol { | |||
| margin: 0.5rem 0 1.6rem; | |||
| padding-left: 1.4rem; | |||
| } | |||
| .privacy-policy ol li { | |||
| margin: 0.6rem 0; | |||
| } | |||
| .privacy-policy a { | |||
| text-decoration: underline; | |||
| } | |||
| .privacy-policy address { | |||
| font-style: normal; | |||
| line-height: 1.6; | |||
| margin-bottom: 1rem; | |||
| } | |||
| .privacy-policy .note { | |||
| font-size: 0.95rem; | |||
| font-style: italic; | |||
| } | |||
| </style> | |||
| <div class="privacy-policy"> | |||
| <h2>Privacy Policy</h2> | |||
| <p> | |||
| The protection of personal data privacy is the concern of every member of Government Logistics | |||
| Department. We respect personal data privacy and are committed to fully implementing and complying | |||
| with the data protection principles and all relevant provisions of the Personal Data (Privacy) | |||
| Ordinance. We develop and implement programme controls that give effect to the six data protection | |||
| principles below: | |||
| </p> | |||
| <ol type="a"> | |||
| <li> | |||
| const content = ` | |||
| <style> | |||
| .privacy-policy { | |||
| max-width: 900px; | |||
| margin: 0 auto 2rem; | |||
| font-size: 1.05rem; | |||
| line-height: 1.75; | |||
| text-align: justify; | |||
| text-justify: inter-word; | |||
| } | |||
| /* Updated heading list: h1/h2/h3 only */ | |||
| .privacy-policy h1, | |||
| .privacy-policy h2, | |||
| .privacy-policy h3 { | |||
| margin: 1.8rem 0 0.9rem; | |||
| font-weight: 600; | |||
| text-align: left; | |||
| } | |||
| /* Keep your original visual sizes: | |||
| old h2 -> new h1 | |||
| old h3 -> new h2 | |||
| old h4 -> new h3 | |||
| */ | |||
| .privacy-policy h1 { font-size: 1.9rem; } | |||
| .privacy-policy h2 { font-size: 1.35rem; } | |||
| .privacy-policy h3 { font-size: 1.15rem; } | |||
| .privacy-policy p { margin: 0 0 1rem; } | |||
| .privacy-policy ol { | |||
| margin: 0.5rem 0 1.6rem; | |||
| padding-left: 1.4rem; | |||
| } | |||
| .privacy-policy ol li { margin: 0.6rem 0; } | |||
| .privacy-policy a { text-decoration: underline; } | |||
| .privacy-policy address { | |||
| font-style: normal; | |||
| line-height: 1.6; | |||
| margin-bottom: 1rem; | |||
| } | |||
| .privacy-policy .note { | |||
| font-size: 0.95rem; | |||
| font-style: italic; | |||
| } | |||
| </style> | |||
| <div class="privacy-policy"> | |||
| <h1>Privacy Policy</h1> | |||
| <p> | |||
| The protection of personal data privacy is the concern of every member of Government Logistics | |||
| Department. We respect personal data privacy and are committed to fully implementing and complying | |||
| with the data protection principles and all relevant provisions of the Personal Data (Privacy) | |||
| Ordinance. We develop and implement programme controls that give effect to the six data protection | |||
| principles below: | |||
| </p> | |||
| <ol type="a"> | |||
| <li> | |||
| collect adequate, but not excessive, personal data by lawful and fair means only for lawful | |||
| purposes related to our functions or activities; | |||
| </li> | |||
| <li> | |||
| </li> | |||
| <li> | |||
| take all reasonably practicable steps to ensure that the personal data collected or retained | |||
| are accurate, having regard to the purposes for which they are to be used. Erase personal data | |||
| no longer than necessary for the purposes for which they are to be used; | |||
| </li> | |||
| <li> | |||
| </li> | |||
| <li> | |||
| use the personal data collected only for purposes or directly related purposes for which the | |||
| data were to be used at the time of collection, unless the individual concerned has given express | |||
| consent for a change of use or such use is permitted by law; | |||
| </li> | |||
| <li> | |||
| </li> | |||
| <li> | |||
| take all reasonably practicable steps to ensure that personal data are protected against | |||
| unauthorized or accidental access, processing, erasure or other use; | |||
| </li> | |||
| <li> | |||
| </li> | |||
| <li> | |||
| take all reasonably practicable steps to ensure that a person can be informed of the kinds of | |||
| personal data that GLD holds and the purposes for which the | |||
| data are to be used; and | |||
| </li> | |||
| <li> | |||
| </li> | |||
| <li> | |||
| permit persons to access and correct personal data of which they are the data subject and | |||
| process any access/correction requests in a manner permitted or required by law. | |||
| </li> | |||
| </ol> | |||
| <h3>Personal Information Collection Statement</h3> | |||
| <h4>Purpose of Collection</h4> | |||
| <p> | |||
| The personal data provided by the applicant in this website would be used for application of public | |||
| notice publication and for assumption of liability. The provision of the personal data is voluntary. | |||
| If the applicant does not provide sufficient information, we may not be able to process publication | |||
| of the relevant public notice. | |||
| </p> | |||
| <h4>Disclosure of Personal Data</h4> | |||
| <p> | |||
| The personal data provided in this website may be disclosed to other bureaux / departments. | |||
| </p> | |||
| <h4>Access to Personal Data</h4> | |||
| <p> | |||
| Requests for access to or correction of personal data held by us should be addressed to - | |||
| </p> | |||
| <address> | |||
| Data Protection Officer<br> | |||
| Government Logistics Department<br> | |||
| 10/F, North Point Government Offices<br> | |||
| 333 Java Road North Point<br> | |||
| Hong Kong | |||
| </address> | |||
| <p class="note"> | |||
| (Note: Data access requests should be made on a | |||
| <a target="_blank" href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_e.pdf"> | |||
| </li> | |||
| </ol> | |||
| <h2>Personal Information Collection Statement</h2> | |||
| <h3>Purpose of Collection</h3> | |||
| <p> | |||
| The personal data provided by the applicant in this website would be used for application of public | |||
| notice publication and for assumption of liability. The provision of the personal data is voluntary. | |||
| If the applicant does not provide sufficient information, we may not be able to process publication | |||
| of the relevant public notice. | |||
| </p> | |||
| <h3>Disclosure of Personal Data</h3> | |||
| <p> | |||
| The personal data provided in this website may be disclosed to other bureaux / departments. | |||
| </p> | |||
| <h3>Access to Personal Data</h3> | |||
| <p> | |||
| Requests for access to or correction of personal data held by us should be addressed to - | |||
| </p> | |||
| <address> | |||
| Data Protection Officer<br> | |||
| Government Logistics Department<br> | |||
| 10/F, North Point Government Offices<br> | |||
| 333 Java Road North Point<br> | |||
| Hong Kong | |||
| </address> | |||
| <p class="note"> | |||
| (Note: Data access requests should be made on a | |||
| <a target="_blank" rel="noopener noreferrer" | |||
| href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_e.pdf"> | |||
| form | |||
| </a> | |||
| specified by the Privacy Commissioner for Personal Data.) | |||
| </p> | |||
| </div> | |||
| ` | |||
| ; | |||
| return (<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />); | |||
| } | |||
| </a> | |||
| specified by the Privacy Commissioner for Personal Data.) | |||
| </p> | |||
| </div> | |||
| `; | |||
| return <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />; | |||
| }; | |||
| export default Page; | |||
| @@ -1,116 +1,109 @@ | |||
| const AboutUs = () => { | |||
| const content =` | |||
| const Page = () => { | |||
| const content = ` | |||
| <style> | |||
| .privacy-policy { | |||
| max-width: 900px; | |||
| margin: 0 auto 2rem; | |||
| font-size: 1.05rem; | |||
| line-height: 1.75; | |||
| text-align: justify; | |||
| text-justify: inter-word; | |||
| } | |||
| .privacy-policy h2, | |||
| .privacy-policy h3, | |||
| .privacy-policy h4 { | |||
| margin: 1.8rem 0 0.9rem; | |||
| font-weight: 600; | |||
| text-align: left; | |||
| } | |||
| .privacy-policy h2 { | |||
| font-size: 1.9rem; | |||
| } | |||
| .privacy-policy h3 { | |||
| font-size: 1.35rem; | |||
| } | |||
| .privacy-policy h4 { | |||
| font-size: 1.15rem; | |||
| } | |||
| .privacy-policy p { | |||
| margin: 0 0 1rem; | |||
| } | |||
| .privacy-policy ol { | |||
| margin: 0.5rem 0 1.6rem; | |||
| padding-left: 1.4rem; | |||
| } | |||
| .privacy-policy ol li { | |||
| margin: 0.6rem 0; | |||
| } | |||
| .privacy-policy a { | |||
| text-decoration: underline; | |||
| } | |||
| .privacy-policy address { | |||
| font-style: normal; | |||
| line-height: 1.6; | |||
| margin-bottom: 1rem; | |||
| } | |||
| .privacy-policy .note { | |||
| font-size: 0.95rem; | |||
| font-style: italic; | |||
| } | |||
| .privacy-policy { | |||
| max-width: 900px; | |||
| margin: 0 auto 2rem; | |||
| font-size: 1.05rem; | |||
| line-height: 1.75; | |||
| text-align: justify; | |||
| text-justify: inter-word; | |||
| } | |||
| /* Use meaningful heading sequence: h1 > h2 > h3 */ | |||
| .privacy-policy h1, | |||
| .privacy-policy h2, | |||
| .privacy-policy h3 { | |||
| margin: 1.8rem 0 0.9rem; | |||
| font-weight: 600; | |||
| text-align: left; | |||
| } | |||
| /* Keep original look: | |||
| old h2 -> new h1 | |||
| old h3 -> new h2 | |||
| old h4 -> new h3 | |||
| */ | |||
| .privacy-policy h1 { font-size: 1.9rem; } | |||
| .privacy-policy h2 { font-size: 1.35rem; } | |||
| .privacy-policy h3 { font-size: 1.15rem; } | |||
| .privacy-policy p { margin: 0 0 1rem; } | |||
| .privacy-policy ol { | |||
| margin: 0.5rem 0 1.6rem; | |||
| padding-left: 1.4rem; | |||
| } | |||
| .privacy-policy ol li { margin: 0.6rem 0; } | |||
| .privacy-policy a { text-decoration: underline; } | |||
| .privacy-policy address { | |||
| font-style: normal; | |||
| line-height: 1.6; | |||
| margin-bottom: 1rem; | |||
| } | |||
| .privacy-policy .note { | |||
| font-size: 0.95rem; | |||
| font-style: italic; | |||
| } | |||
| </style> | |||
| <div class="privacy-policy"> | |||
| <h2>私隱政策</h2> | |||
| <p> | |||
| 保障個人資料私隱是政府物流服務署每位成員所關注的事宜。我們尊重個人資料私隱,並承諾全面執行及遵從保障資料原則及《個人資料(私隱)條例》的所有相關條文。政府物流服務署建立及實施系統監控,以確保遵從以下六項保障資料原則 - | |||
| </p> | |||
| <ol type="a"> | |||
| <li>以合法和公平的方法收集足夠但不超乎適度的個人資料,只供用於與政府物流服務署的職能或活動有關的合法目的;</li> | |||
| <li>採取所有切實可行的步驟,以確保在顧及有關的個人資料會被使用於的目的下,所收集或保留的個人資料是準確的。刪除就使用目的而言不再屬有需要的個人資料;</li> | |||
| <li>所收集的個人資料只可用作收集資料時資料會被使用於的目的或直接有關的目的,除非有關個人已就更改使用明示同意或法律准許有關使用;</li> | |||
| <li>採取所有切實可行的步驟,以確保個人資料受保障而不受未獲准許或意外的查閱、處理、刪除或使用所影響;</li> | |||
| <li>採取所有切實可行的步驟,以確保任何人能獲政府物流服務署告知所持有的個人資料的種類及資料將會為甚麼目的而使用的;以及</li> | |||
| <li>准許資料當事人查閱/改正其個人資料及以法律准許或規定的方式處理任何查閱/改正個人資料的要求。</li> | |||
| </ol> | |||
| <h3>收集個人資料聲明</h3> | |||
| <h4>收集資料的目的</h4> | |||
| <p> | |||
| 申請人在本網站內所提供的個人資料會供申請刊登公共啟事及為承擔法律責任用途。在本網站提供的個人資料是自願的。如果申請人未有提供足夠資料,我們可能無法處理相關公共啟事的刊登事宜。 | |||
| </p> | |||
| <h4>披露個人資料</h4> | |||
| <p> | |||
| 政府物流服務署可能會向其他政策局/部門披露你在本網站提供的個人資料。 | |||
| </p> | |||
| <h4>查閱個人資料</h4> | |||
| <p> | |||
| 如要查閱或改正本署所持有的個人資料,請向以下人士提出: | |||
| </p> | |||
| <address> | |||
| 香港北角渣華道333號<br> | |||
| 北角政府合署10樓<br> | |||
| 政府物流服務署<br> | |||
| 保障資料主任 | |||
| </address> | |||
| <p class="note"> | |||
| (註:請以個人資料私隱專員指定的<a target="_blank" href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_c.pdf">表格</a>提出查閱資料要求。) | |||
| </p> | |||
| <h1>私隱政策</h1> | |||
| <p> | |||
| 保障個人資料私隱是政府物流服務署每位成員所關注的事宜。我們尊重個人資料私隱,並承諾全面執行及遵從保障資料原則及《個人資料(私隱)條例》的所有相關條文。政府物流服務署建立及實施系統監控,以確保遵從以下六項保障資料原則 - | |||
| </p> | |||
| <ol type="a"> | |||
| <li>以合法和公平的方法收集足夠但不超乎適度的個人資料,只供用於與政府物流服務署的職能或活動有關的合法目的;</li> | |||
| <li>採取所有切實可行的步驟,以確保在顧及有關的個人資料會被使用於的目的下,所收集或保留的個人資料是準確的。刪除就使用目的而言不再屬有需要的個人資料;</li> | |||
| <li>所收集的個人資料只可用作收集資料時資料會被使用於的目的或直接有關的目的,除非有關個人已就更改使用明示同意或法律准許有關使用;</li> | |||
| <li>採取所有切實可行的步驟,以確保個人資料受保障而不受未獲准許或意外的查閱、處理、刪除或使用所影響;</li> | |||
| <li>採取所有切實可行的步驟,以確保任何人能獲政府物流服務署告知所持有的個人資料的種類及資料將會為甚麼目的而使用的;以及</li> | |||
| <li>准許資料當事人查閱/改正其個人資料及以法律准許或規定的方式處理任何查閱/改正個人資料的要求。</li> | |||
| </ol> | |||
| <h2>收集個人資料聲明</h2> | |||
| <h3>收集資料的目的</h3> | |||
| <p> | |||
| 申請人在本網站內所提供的個人資料會供申請刊登公共啟事及為承擔法律責任用途。在本網站提供的個人資料是自願的。如果申請人未有提供足夠資料,我們可能無法處理相關公共啟事的刊登事宜。 | |||
| </p> | |||
| <h3>披露個人資料</h3> | |||
| <p> | |||
| 政府物流服務署可能會向其他政策局/部門披露你在本網站提供的個人資料。 | |||
| </p> | |||
| <h3>查閱個人資料</h3> | |||
| <p> | |||
| 如要查閱或改正本署所持有的個人資料,請向以下人士提出: | |||
| </p> | |||
| <address> | |||
| 香港北角渣華道333號<br> | |||
| 北角政府合署10樓<br> | |||
| 政府物流服務署<br> | |||
| 保障資料主任 | |||
| </address> | |||
| <p class="note"> | |||
| (註:請以個人資料私隱專員指定的 | |||
| <a target="_blank" rel="noopener noreferrer" | |||
| href="https://www.gld.gov.hk/assets/gld/download-files/privacy-policy/privacy_form_c.pdf"> | |||
| 表格 | |||
| </a> | |||
| 提出查閱資料要求。) | |||
| </p> | |||
| </div> | |||
| ` | |||
| ; | |||
| return (<div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />); | |||
| `; | |||
| } | |||
| return <div style={{ padding: 12 }} dangerouslySetInnerHTML={{ __html: content }} />; | |||
| }; | |||
| export default AboutUs; | |||
| export default Page; | |||
| @@ -610,5 +610,21 @@ | |||
| "Dashboard": "Dashboard", | |||
| "event": "Event", | |||
| "lgce_alt": "2025 Legislative Council General Election", | |||
| "lgce_title": "2025 Legislative Council General Election" | |||
| "lgce_title": "2025 Legislative Council General Election", | |||
| "ariaShowPassword": "Show password", | |||
| "ariaHidePassword": "Hide password", | |||
| "captchaAudioError": "Unable to play audio CAPTCHA.", | |||
| "captchaAudioServerError": "Audio CAPTCHA is temporarily unavailable. Please refresh the CAPTCHA.", | |||
| "captchaExpired": "CAPTCHA expired. Please refresh and try again.", | |||
| "connectionError": "Connection error. Please try again.", | |||
| "muiClear": "Clear", | |||
| "muiClose": "Close", | |||
| "muiOpen": "Open", | |||
| "muiNoOptions": "No options", | |||
| "paginationPrev": "Go to previous page", | |||
| "paginationNext": "Go to next page" | |||
| } | |||
| @@ -606,5 +606,21 @@ | |||
| "Dashboard": "仪表板", | |||
| "event": "活动", | |||
| "lgce_alt": "2025年立法会换届选举", | |||
| "lgce_title": "2025年立法会换届选举" | |||
| "lgce_title": "2025年立法会换届选举", | |||
| "ariaShowPassword": "显示密码", | |||
| "ariaHidePassword": "隐藏密码", | |||
| "captchaAudioError": "无法播放语音验证码。", | |||
| "captchaAudioServerError": "语音验证码暂时不可用,请刷新验证码。", | |||
| "captchaExpired": "验证码已过期,请刷新后再试。", | |||
| "connectionError": "连接错误,请稍后再试。", | |||
| "muiClear": "清除", | |||
| "muiClose": "关闭", | |||
| "muiOpen": "打开", | |||
| "muiNoOptions": "没有选项", | |||
| "paginationPrev": "上一页", | |||
| "paginationNext": "下一页" | |||
| } | |||
| @@ -607,5 +607,21 @@ | |||
| "Dashboard": "儀表板", | |||
| "event": "活動", | |||
| "lgce_alt": "2025年立法會換屆選舉", | |||
| "lgce_title": "2025年立法會換屆選舉" | |||
| "lgce_title": "2025年立法會換屆選舉", | |||
| "ariaShowPassword": "顯示密碼", | |||
| "ariaHidePassword": "隱藏密碼", | |||
| "captchaAudioError": "無法播放語音驗證碼。", | |||
| "captchaAudioServerError": "語音驗證碼暫時無法使用,請重新整理驗證碼。", | |||
| "captchaExpired": "驗證碼已過期,請重新整理並再試。", | |||
| "connectionError": "連線錯誤,請稍後再試。", | |||
| "muiClear": "清除", | |||
| "muiClose": "關閉", | |||
| "muiOpen": "開啟", | |||
| "muiNoOptions": "沒有選項", | |||
| "paginationPrev": "上一頁", | |||
| "paginationNext": "下一頁" | |||
| } | |||
| @@ -1,5 +1,6 @@ | |||
| import { Autocomplete, TextField } from '@mui/material'; | |||
| import { useEffect, useState } from 'react'; | |||
| import {useIntl } from "react-intl"; | |||
| export default function Combo({ | |||
| valueName, | |||
| @@ -14,6 +15,7 @@ export default function Combo({ | |||
| ...props | |||
| }) { | |||
| const formValue = form.values[valueName] ?? null; | |||
| const intl = useIntl(); | |||
| const [inputValue, setInputValue] = useState(""); | |||
| @@ -84,6 +86,10 @@ export default function Combo({ | |||
| }} | |||
| /> | |||
| )} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| ); | |||
| } | |||
| @@ -1,4 +1,6 @@ | |||
| import dayjs from 'dayjs'; | |||
| import "dayjs/locale/zh-hk"; | |||
| import "dayjs/locale/zh-cn"; | |||
| var days_ZH = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; | |||
| var days_CN = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; | |||
| @@ -156,3 +158,51 @@ export const getWeekdayStr_CN = (date) =>{ | |||
| if(date) return days_CN[date.getDay()] | |||
| return ""; | |||
| }; | |||
| const formatPickerAriaDate = (dateStr, locale) => { | |||
| if (!dateStr) return ""; | |||
| // MUI may pass a full Date string; parse via native Date first | |||
| const dNative = new Date(dateStr); | |||
| const d = isNaN(dNative.getTime()) ? null : dNative; | |||
| if (!d) return dateStr; // fallback if parsing fails | |||
| // Format only the date part (ignore time/GMT) | |||
| const dj = dayjs(d); | |||
| if (locale === "zh-HK" || locale === "zh") { | |||
| return dj.locale("zh-hk").format("YYYY年MM月DD日"); | |||
| } | |||
| if (locale === "zh-CN") { | |||
| return dj.locale("zh-cn").format("YYYY年MM月DD日"); | |||
| } | |||
| return dj.locale("en").format("DD MMM YYYY"); | |||
| }; | |||
| export const getPickerLocaleText = (locale) => { | |||
| if (locale === "zh-HK" || locale === "zh") { | |||
| return { | |||
| openDatePickerDialogue: (dateStr) => { | |||
| const s = formatPickerAriaDate(dateStr, locale); | |||
| return s ? `選擇日期,已選日期為 ${s}` : "選擇日期"; | |||
| } | |||
| }; | |||
| } | |||
| if (locale === "zh-CN") { | |||
| return { | |||
| openDatePickerDialogue: (dateStr) => { | |||
| const s = formatPickerAriaDate(dateStr, locale); | |||
| return s ? `选择日期,已选日期为 ${s}` : "选择日期"; | |||
| } | |||
| }; | |||
| } | |||
| return { | |||
| openDatePickerDialogue: (dateStr) => { | |||
| const s = formatPickerAriaDate(dateStr, locale); | |||
| return s ? `Choose date, selected date is ${s}` : "Choose date"; | |||
| } | |||
| }; | |||
| }; | |||
| @@ -3,10 +3,12 @@ import { | |||
| } from '@mui/material'; | |||
| import * as React from 'react'; | |||
| import Select, { SelectChangeEvent } from '@mui/material/Select'; | |||
| import {useIntl } from "react-intl"; | |||
| export default function Combo ({valueName, disabled, form, dataList, filterOptions, getOptionLabel, isOptionEqualToValue, onInputChange, onChange, ...props}){ | |||
| const [value, setValue] = React.useState(form.values[valueName]); | |||
| const [inputValue, setInputValue] = React.useState(""); | |||
| const intl = useIntl(); | |||
| return ( | |||
| <Autocomplete | |||
| @@ -53,7 +55,11 @@ export default function Combo ({valueName, disabled, form, dataList, filterOptio | |||
| WebkitTextFillColor: "#000000", | |||
| background: "#f8f8f8", | |||
| }, | |||
| }}/>} | |||
| }}/>} | |||
| clearText={intl.formatMessage({ id: "muiClear" })} | |||
| closeText={intl.formatMessage({ id: "muiClose" })} | |||
| openText={intl.formatMessage({ id: "muiOpen" })} | |||
| noOptionsText={intl.formatMessage({ id: "muiNoOptions" })} | |||
| /> | |||
| ); | |||
| } | |||