| @@ -1,359 +0,0 @@ | |||
| import {useEffect, useState} from 'react'; | |||
| // material-ui | |||
| import { | |||
| Avatar, | |||
| AvatarGroup, | |||
| Box, | |||
| Button, | |||
| Grid, | |||
| List, | |||
| ListItemAvatar, | |||
| ListItemButton, | |||
| ListItemSecondaryAction, | |||
| ListItemText, | |||
| MenuItem, | |||
| Stack, | |||
| TextField, | |||
| Typography | |||
| } from '@mui/material'; | |||
| // project import | |||
| import OrdersTable from 'pages/dashboard/OrdersTable'; | |||
| import IncomeAreaChart from 'pages/dashboard/IncomeAreaChart'; | |||
| import MonthlyBarChart from 'pages/dashboard/MonthlyBarChart'; | |||
| import ReportAreaChart from 'pages/dashboard/ReportAreaChart'; | |||
| import SalesColumnChart from 'pages/dashboard/SalesColumnChart'; | |||
| import MainCard from 'components/MainCard'; | |||
| import AnalyticEcommerce from 'components/cards/statistics/AnalyticEcommerce'; | |||
| // assets | |||
| import { GiftOutlined, MessageOutlined, SettingOutlined } from '@ant-design/icons'; | |||
| import avatar1 from 'assets/images/users/avatar-1.png'; | |||
| import avatar2 from 'assets/images/users/avatar-2.png'; | |||
| import avatar3 from 'assets/images/users/avatar-3.png'; | |||
| import avatar4 from 'assets/images/users/avatar-4.png'; | |||
| import axios from "axios"; | |||
| // avatar style | |||
| const avatarSX = { | |||
| width: 36, | |||
| height: 36, | |||
| fontSize: '1rem' | |||
| }; | |||
| // action style | |||
| const actionSX = { | |||
| mt: 0.75, | |||
| ml: 1, | |||
| top: 'auto', | |||
| right: 'auto', | |||
| alignSelf: 'flex-start', | |||
| transform: 'none' | |||
| }; | |||
| // sales report status | |||
| const status = [ | |||
| { | |||
| value: 'today', | |||
| label: 'Today' | |||
| }, | |||
| { | |||
| value: 'month', | |||
| label: 'This Month' | |||
| }, | |||
| { | |||
| value: 'year', | |||
| label: 'This Year' | |||
| } | |||
| ]; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const ARSDashboard = () => { | |||
| const [value, setValue] = useState('today'); | |||
| const [slot, setSlot] = useState('week'); | |||
| useEffect(() =>{ | |||
| tryAPI(); | |||
| },[]); | |||
| const tryAPI = () =>{ | |||
| axios.get('http://localhost:8090/api/test') | |||
| .then((response) => { | |||
| console.log(response) | |||
| }) | |||
| .catch(error => { | |||
| console.error(error); | |||
| }); | |||
| } | |||
| return ( | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75}> | |||
| {/* row 1 */} | |||
| <Grid item xs={12} sx={{ mb: -2.25 }}> | |||
| <Typography variant="h5">Event Overall Status</Typography> | |||
| </Grid> | |||
| <Grid item xs={12} sm={6} md={4} lg={3}> | |||
| <AnalyticEcommerce title="Total Page Views" count="4,42,236" percentage={59.3} extra="35,000" /> | |||
| </Grid> | |||
| <Grid item xs={12} sm={6} md={4} lg={3}> | |||
| <AnalyticEcommerce title="Total Users" count="78,250" percentage={70.5} extra="8,900" /> | |||
| </Grid> | |||
| <Grid item xs={12} sm={6} md={4} lg={3}> | |||
| <AnalyticEcommerce title="Total Order" count="18,800" percentage={27.4} isLoss color="warning" extra="1,943" /> | |||
| </Grid> | |||
| <Grid item xs={12} sm={6} md={4} lg={3}> | |||
| <AnalyticEcommerce title="Total Sales" count="$35,078" percentage={27.4} isLoss color="warning" extra="$20,395" /> | |||
| </Grid> | |||
| <Grid item md={8} sx={{ display: { sm: 'none', md: 'block', lg: 'none' } }} /> | |||
| {/* row 2 */} | |||
| <Grid item xs={12} md={7} lg={8}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Application</Typography> | |||
| </Grid> | |||
| <Grid item> | |||
| <Stack direction="row" alignItems="center" spacing={0}> | |||
| <Button | |||
| size="small" | |||
| onClick={() => setSlot('month')} | |||
| color={slot === 'month' ? 'primary' : 'secondary'} | |||
| variant={slot === 'month' ? 'outlined' : 'text'} | |||
| > | |||
| Month | |||
| </Button> | |||
| <Button | |||
| size="small" | |||
| onClick={() => setSlot('week')} | |||
| color={slot === 'week' ? 'primary' : 'secondary'} | |||
| variant={slot === 'week' ? 'outlined' : 'text'} | |||
| > | |||
| Week | |||
| </Button> | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| <MainCard content={false} sx={{ mt: 1.5 }}> | |||
| <Box sx={{ pt: 1, pr: 2 }}> | |||
| <IncomeAreaChart slot={slot} /> | |||
| </Box> | |||
| </MainCard> | |||
| </Grid> | |||
| <Grid item xs={12} md={5} lg={4}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Income Overview</Typography> | |||
| </Grid> | |||
| <Grid item /> | |||
| </Grid> | |||
| <MainCard sx={{ mt: 2 }} content={false}> | |||
| <Box sx={{ p: 3, pb: 0 }}> | |||
| <Stack spacing={2}> | |||
| <Typography variant="h6" color="textSecondary"> | |||
| This Week Statistics | |||
| </Typography> | |||
| <Typography variant="h3">$7,650</Typography> | |||
| </Stack> | |||
| </Box> | |||
| <MonthlyBarChart /> | |||
| </MainCard> | |||
| </Grid> | |||
| {/* row 3 */} | |||
| <Grid item xs={12} md={7} lg={8}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Recent Orders</Typography> | |||
| </Grid> | |||
| <Grid item /> | |||
| </Grid> | |||
| <MainCard sx={{ mt: 2 }} content={false}> | |||
| <OrdersTable /> | |||
| </MainCard> | |||
| </Grid> | |||
| <Grid item xs={12} md={5} lg={4}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Analytics Report</Typography> | |||
| </Grid> | |||
| <Grid item /> | |||
| </Grid> | |||
| <MainCard sx={{ mt: 2 }} content={false}> | |||
| <List sx={{ p: 0, '& .MuiListItemButton-root': { py: 2 } }}> | |||
| <ListItemButton divider> | |||
| <ListItemText primary="Company Finance Growth" /> | |||
| <Typography variant="h5">+45.14%</Typography> | |||
| </ListItemButton> | |||
| <ListItemButton divider> | |||
| <ListItemText primary="Company Expenses Ratio" /> | |||
| <Typography variant="h5">0.58%</Typography> | |||
| </ListItemButton> | |||
| <ListItemButton> | |||
| <ListItemText primary="Business Risk Cases" /> | |||
| <Typography variant="h5">Low</Typography> | |||
| </ListItemButton> | |||
| </List> | |||
| <ReportAreaChart /> | |||
| </MainCard> | |||
| </Grid> | |||
| {/* row 4 */} | |||
| <Grid item xs={12} md={7} lg={8}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Sales Report</Typography> | |||
| </Grid> | |||
| <Grid item> | |||
| <TextField | |||
| id="standard-select-currency" | |||
| size="small" | |||
| select | |||
| value={value} | |||
| onChange={(e) => setValue(e.target.value)} | |||
| sx={{ '& .MuiInputBase-input': { py: 0.5, fontSize: '0.875rem' } }} | |||
| > | |||
| {status.map((option) => ( | |||
| <MenuItem key={option.value} value={option.value}> | |||
| {option.label} | |||
| </MenuItem> | |||
| ))} | |||
| </TextField> | |||
| </Grid> | |||
| </Grid> | |||
| <MainCard sx={{ mt: 1.75 }}> | |||
| <Stack spacing={1.5} sx={{ mb: -12 }}> | |||
| <Typography variant="h6" color="secondary"> | |||
| Net Profit | |||
| </Typography> | |||
| <Typography variant="h4">$1560</Typography> | |||
| </Stack> | |||
| <SalesColumnChart /> | |||
| </MainCard> | |||
| </Grid> | |||
| <Grid item xs={12} md={5} lg={4}> | |||
| <Grid container alignItems="center" justifyContent="space-between"> | |||
| <Grid item> | |||
| <Typography variant="h5">Transaction History</Typography> | |||
| </Grid> | |||
| <Grid item /> | |||
| </Grid> | |||
| <MainCard sx={{ mt: 2 }} content={false}> | |||
| <List | |||
| component="nav" | |||
| sx={{ | |||
| px: 0, | |||
| py: 0, | |||
| '& .MuiListItemButton-root': { | |||
| py: 1.5, | |||
| '& .MuiAvatar-root': avatarSX, | |||
| '& .MuiListItemSecondaryAction-root': { ...actionSX, position: 'relative' } | |||
| } | |||
| }} | |||
| > | |||
| <ListItemButton divider> | |||
| <ListItemAvatar> | |||
| <Avatar | |||
| sx={{ | |||
| color: 'success.main', | |||
| bgcolor: 'success.lighter' | |||
| }} | |||
| > | |||
| <GiftOutlined /> | |||
| </Avatar> | |||
| </ListItemAvatar> | |||
| <ListItemText primary={<Typography variant="subtitle1">Order #002434</Typography>} secondary="Today, 2:00 AM" /> | |||
| <ListItemSecondaryAction> | |||
| <Stack alignItems="flex-end"> | |||
| <Typography variant="subtitle1" noWrap> | |||
| + $1,430 | |||
| </Typography> | |||
| <Typography variant="h6" color="secondary" noWrap> | |||
| 78% | |||
| </Typography> | |||
| </Stack> | |||
| </ListItemSecondaryAction> | |||
| </ListItemButton> | |||
| <ListItemButton divider> | |||
| <ListItemAvatar> | |||
| <Avatar | |||
| sx={{ | |||
| color: 'primary.main', | |||
| bgcolor: 'primary.lighter' | |||
| }} | |||
| > | |||
| <MessageOutlined /> | |||
| </Avatar> | |||
| </ListItemAvatar> | |||
| <ListItemText primary={<Typography variant="subtitle1">Order #984947</Typography>} secondary="5 August, 1:45 PM" /> | |||
| <ListItemSecondaryAction> | |||
| <Stack alignItems="flex-end"> | |||
| <Typography variant="subtitle1" noWrap> | |||
| + $302 | |||
| </Typography> | |||
| <Typography variant="h6" color="secondary" noWrap> | |||
| 8% | |||
| </Typography> | |||
| </Stack> | |||
| </ListItemSecondaryAction> | |||
| </ListItemButton> | |||
| <ListItemButton> | |||
| <ListItemAvatar> | |||
| <Avatar | |||
| sx={{ | |||
| color: 'error.main', | |||
| bgcolor: 'error.lighter' | |||
| }} | |||
| > | |||
| <SettingOutlined /> | |||
| </Avatar> | |||
| </ListItemAvatar> | |||
| <ListItemText primary={<Typography variant="subtitle1">Order #988784</Typography>} secondary="7 hours ago" /> | |||
| <ListItemSecondaryAction> | |||
| <Stack alignItems="flex-end"> | |||
| <Typography variant="subtitle1" noWrap> | |||
| + $682 | |||
| </Typography> | |||
| <Typography variant="h6" color="secondary" noWrap> | |||
| 16% | |||
| </Typography> | |||
| </Stack> | |||
| </ListItemSecondaryAction> | |||
| </ListItemButton> | |||
| </List> | |||
| </MainCard> | |||
| <MainCard sx={{ mt: 2 }}> | |||
| <Stack spacing={3}> | |||
| <Grid container justifyContent="space-between" alignItems="center"> | |||
| <Grid item> | |||
| <Stack> | |||
| <Typography variant="h5" noWrap> | |||
| Help & Support Chat | |||
| </Typography> | |||
| <Typography variant="caption" color="secondary" noWrap> | |||
| Typical replay within 5 min | |||
| </Typography> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item> | |||
| <AvatarGroup sx={{ '& .MuiAvatar-root': { width: 32, height: 32 } }}> | |||
| <Avatar alt="Remy Sharp" src={avatar1} /> | |||
| <Avatar alt="Travis Howard" src={avatar2} /> | |||
| <Avatar alt="Cindy Baker" src={avatar3} /> | |||
| <Avatar alt="Agnes Walker" src={avatar4} /> | |||
| </AvatarGroup> | |||
| </Grid> | |||
| </Grid> | |||
| <Button size="small" variant="contained" sx={{ textTransform: 'capitalize' }}> | |||
| Need Help? | |||
| </Button> | |||
| </Stack> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default ARSDashboard; | |||
| @@ -275,56 +275,66 @@ const CustomFormWizard = (props) => { | |||
| </Typography> */} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="idDocType-signup">身份證明文件 | |||
| <span style={{color: '#f10000'}}>*</span> | |||
| </InputLabel> | |||
| <Select | |||
| name = "idDocType" | |||
| multiple | |||
| displayEmpty | |||
| value={""} | |||
| onChange={handleChange} | |||
| input={<OutlinedInput />} | |||
| {...register("idDocType")} | |||
| renderValue={(selected) => { | |||
| if (selected.length === 0) { | |||
| return "證件類別"; | |||
| } | |||
| return selected.join(', '); | |||
| }} | |||
| // MenuProps={MenuProps} | |||
| inputProps={{ 'aria-label': 'Without label' }} | |||
| > | |||
| </Select> | |||
| {/* {touched.enName && errors.enName && ( | |||
| <FormHelperText error id="helper-text-enName-signup"> | |||
| {errors.enName} | |||
| </FormHelperText> | |||
| )} */} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1} alignItems="flex-end"> | |||
| <OutlinedInput | |||
| id="idNo-login" | |||
| type="text" | |||
| value={values.idNo} | |||
| name="idNo" | |||
| {...register("idNo")} | |||
| onChange={handleChange} | |||
| placeholder="證件號碼" | |||
| fullWidth | |||
| error={Boolean(touched.idNo && errors.idNo)} | |||
| /> | |||
| {touched.idNo && errors.idNo && ( | |||
| <FormHelperText error id="helper-text-enName-signup"> | |||
| {errors.idNo} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| <Grid item xs={12} md={12} > | |||
| <Grid container xs={12} md={12} sx={{mb:1}}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="idDocType-signup">身份證明文件 | |||
| <span style={{color: '#f10000'}}>*</span> | |||
| </InputLabel> | |||
| {/* {touched.enName && errors.enName && ( | |||
| <FormHelperText error id="helper-text-enName-signup"> | |||
| {errors.enName} | |||
| </FormHelperText> | |||
| )} */} | |||
| </Stack> | |||
| </Grid> | |||
| <Grid container xs={12} md={12}> | |||
| <Grid item xs={12} md={6} > | |||
| <Stack spacing={1} sx={{mr:{md:1},mb:{xs:1}}}> | |||
| <Select | |||
| name = "idDocType" | |||
| multiple | |||
| displayEmpty | |||
| value={""} | |||
| onChange={handleChange} | |||
| input={<OutlinedInput />} | |||
| {...register("idDocType")} | |||
| renderValue={(selected) => { | |||
| if (selected.length === 0) { | |||
| return "證件類別"; | |||
| } | |||
| return selected.join(', '); | |||
| }} | |||
| // MenuProps={MenuProps} | |||
| inputProps={{ 'aria-label': 'Without label' }} | |||
| > | |||
| </Select> | |||
| </Stack> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1}> | |||
| <OutlinedInput | |||
| id="idNo-login" | |||
| type="text" | |||
| value={values.idNo} | |||
| name="idNo" | |||
| {...register("idNo")} | |||
| onChange={handleChange} | |||
| placeholder="證件號碼" | |||
| fullWidth | |||
| error={Boolean(touched.idNo && errors.idNo)} | |||
| /> | |||
| {touched.idNo && errors.idNo && ( | |||
| <FormHelperText error id="helper-text-enName-signup"> | |||
| {errors.idNo} | |||
| </FormHelperText> | |||
| )} | |||
| </Stack> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} md={6}> | |||
| <Stack spacing={1}> | |||
| <InputLabel htmlFor="enName-signup">英文姓名 | |||
| @@ -0,0 +1,17 @@ | |||
| import {Box, CircularProgress, Grid} from "@mui/material"; | |||
| const LoadingComponent = () => { | |||
| return ( | |||
| <Grid item xs={12} md={12} lg={12} justifyContent="space-between" alignItems="center"> | |||
| <Box | |||
| display="flex" | |||
| justifyContent="center" | |||
| alignItems="center" | |||
| autoHeight | |||
| > | |||
| <CircularProgress /> | |||
| </Box> | |||
| </Grid> | |||
| ) | |||
| } | |||
| export default LoadingComponent; | |||
| @@ -0,0 +1,27 @@ | |||
| // material-ui | |||
| import { | |||
| Grid | |||
| } from '@mui/material'; | |||
| import {useEffect} from "react"; | |||
| import {handleLogoutFunction} from "../../auth"; | |||
| import {useDispatch} from "react-redux"; | |||
| import {useNavigate} from "react-router-dom"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const LogoutPage = () => { | |||
| const dispatch = useDispatch() | |||
| const navigate = useNavigate() | |||
| useEffect(() =>{ | |||
| dispatch(handleLogoutFunction()); | |||
| navigate('/login'); | |||
| },[]) | |||
| return ( | |||
| <Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default LogoutPage; | |||
| @@ -0,0 +1,292 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| CardContent, Divider, FormControlLabel, | |||
| Grid, InputAdornment, Switch, TextField | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import {useForm} from "react-hook-form"; | |||
| import {useState} from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const PasswordPolicyPage = () => { | |||
| const { reset, register, handleSubmit } = useForm() | |||
| const [aNonA, setANonA] = useState(false); | |||
| const [needSpecialCharacter, setNeedSpecialCharacter] = useState(false); | |||
| const [noUsernameAsPart, setNoUsernameAsPart] = useState(false); | |||
| const [noIdenticalChar, setNoIdenticalChar] = useState(false); | |||
| const onSubmit = (data) => { | |||
| console.log(data); | |||
| console.log(aNonA) | |||
| }; | |||
| function resetForm(){ | |||
| setANonA(false); | |||
| reset(); | |||
| } | |||
| return ( | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75} justifyContent="center"> | |||
| <Grid item xs={12} md={11} lg={10} > | |||
| <MainCard xs={12} md={12} lg={12} | |||
| border={false} | |||
| content={false}> | |||
| <form onSubmit={handleSubmit(onSubmit)}> | |||
| {/*Title*/} | |||
| <CardContent sx={{ px: 2.5, pt: 3 }}> | |||
| <Grid item justifyContent="space-between" alignItems="center"> | |||
| Password Policy | |||
| </Grid> | |||
| </CardContent> | |||
| <Grid container alignItems={"center"} justifyContent="center"> | |||
| {/*row 1*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Length of Password | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("syncDateCount")} | |||
| id='syncDateCount' | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 2*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Change Password (days) | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("idleLogoutTime")} | |||
| id="idleLogoutTime" | |||
| InputProps={{ | |||
| endAdornment: <InputAdornment position="end">days</InputAdornment>, | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 3*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Password History | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("passwordHistory")} | |||
| id="passwordHistory" | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 4*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Maximum number of login failure | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("maxLoginFailure")} | |||
| id="maxLoginFailure" | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 5*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Penalty time of login failure (minutes) | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("loginFailPenaltyTime")} | |||
| id="loginFailPenaltyTime" | |||
| InputProps={{ | |||
| endAdornment: <InputAdornment position="end">minutes</InputAdornment>, | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 6*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'flex-end', alignItems: 'center'}}> | |||
| Disable After (days) | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5}justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("disableAfterCount")} | |||
| id="disableAfterCount" | |||
| InputProps={{ | |||
| endAdornment: <InputAdornment position="end">days</InputAdornment>, | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} /> | |||
| {/*row 7*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', justifyContent: 'center', alignItems: 'center'}}> | |||
| Generate Password: | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 8*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}> | |||
| <Grid item xs={1} s={1} md={3} lg={3} /> | |||
| <Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center"> | |||
| <FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={ | |||
| <Switch | |||
| onChange={(event, newValue) => { | |||
| setANonA(newValue); | |||
| }} | |||
| checked={aNonA} | |||
| /> | |||
| } label="Contain at least one alphabetic and non-alphabetic character" /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 9*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}> | |||
| <Grid item xs={1} s={1} md={3} lg={3} /> | |||
| <Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center"> | |||
| <FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={ | |||
| <Switch | |||
| onChange={(event, newValue) => { | |||
| setNeedSpecialCharacter(newValue); | |||
| }} | |||
| checked={needSpecialCharacter} | |||
| /> | |||
| } label="Contain at least one special character (eg. #,$,@ etc)" /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 10*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}> | |||
| <Grid item xs={1} s={1} md={3} lg={3} /> | |||
| <Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center"> | |||
| <FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={ | |||
| <Switch | |||
| onChange={(event, newValue) => { | |||
| setNoUsernameAsPart(newValue); | |||
| }} | |||
| checked={noUsernameAsPart} | |||
| /> | |||
| } label="Not contain the username as part of password" /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 11*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3, justifyContent: 'center', alignItems: 'center'}}> | |||
| <Grid item xs={1} s={1} md={3} lg={3} /> | |||
| <Grid item xs={11} s={11} md={9} lg={9} justifyContent="center" alignItems="center"> | |||
| <FormControlLabel sx={{display: 'flex', justifyContent: 'start', alignItems: 'center'}} control={ | |||
| <Switch | |||
| onChange={(event, newValue) => { | |||
| setNoIdenticalChar(newValue); | |||
| }} | |||
| checked={noIdenticalChar} | |||
| /> | |||
| } label="Contain no more than three identical consecutive characters" /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*last row*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}} alignItems={"center"} justifyContent="center"> | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml:3, mr:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| onClick={resetForm} | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Clear | |||
| </Button> | |||
| </Grid> | |||
| <Grid item sx={{ml:3, mr:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Save Change | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default PasswordPolicyPage; | |||
| @@ -0,0 +1,177 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| CardContent, Divider, | |||
| Grid, InputAdornment, TextField | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import {useForm} from "react-hook-form"; | |||
| import Radio from '@mui/material/Radio'; | |||
| import RadioGroup from '@mui/material/RadioGroup'; | |||
| import FormControlLabel from '@mui/material/FormControlLabel'; | |||
| import FormControl from '@mui/material/FormControl'; | |||
| import {useState} from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const SettingPage = () => { | |||
| const [notificationType, setNotificationType] = useState(null); | |||
| const { reset, register, handleSubmit } = useForm() | |||
| const onSubmit = (data) => { | |||
| console.log(data); | |||
| console.log(notificationType); | |||
| }; | |||
| function resetForm(){ | |||
| setNotificationType(null); | |||
| reset(); | |||
| } | |||
| return ( | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75} justifyContent="center"> | |||
| <Grid item xs={12} md={11} lg={10} > | |||
| <MainCard xs={12} md={12} lg={12} | |||
| border={false} | |||
| content={false}> | |||
| <form onSubmit={handleSubmit(onSubmit)}> | |||
| {/*Title*/} | |||
| <CardContent sx={{ px: 2.5, pt: 3 }}> | |||
| <Grid item justifyContent="space-between" alignItems="center"> | |||
| System Configuration | |||
| </Grid> | |||
| </CardContent> | |||
| <Grid container alignItems={"center"} justifyContent="center"> | |||
| {/*row 1*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex'}}> | |||
| Notification Frequency | |||
| </Grid> | |||
| <FormControl> | |||
| <RadioGroup | |||
| aria-labelledby="notification-group-label" | |||
| defaultValue="None" | |||
| value={notificationType === null ? null : notificationType} | |||
| onChange={(event, newValue) => { | |||
| setNotificationType(newValue); | |||
| }} | |||
| name="radio-buttons-group" | |||
| > | |||
| <FormControlLabel value="Weekly" control={ | |||
| <Radio | |||
| checked={notificationType === null ? false : notificationType === "Weekly"} | |||
| /> | |||
| } label="Weekly" /> | |||
| <FormControlLabel value="Monthly" control={ | |||
| <Radio | |||
| checked={notificationType === null ? false : notificationType === "Monthly"} | |||
| /> | |||
| } label="Monthly" /> | |||
| <FormControlLabel value="Bi-Monthly" control={ | |||
| <Radio | |||
| checked={notificationType === null ? false : notificationType === "Bi-Monthly"} | |||
| /> | |||
| } label="Bi-Monthly" /> | |||
| <FormControlLabel value="None" control={ | |||
| <Radio | |||
| checked={notificationType === null ? false : notificationType === "None"} | |||
| /> | |||
| } label="None" /> | |||
| </RadioGroup> | |||
| </FormControl> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 2*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', alignItems: 'center'}}> | |||
| Number of days to keep the Government Directory Sync Indicator | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("syncDateCount")} | |||
| id='syncDateCount' | |||
| InputProps={{ | |||
| endAdornment: <InputAdornment position="end">days</InputAdornment>, | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 3*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}}> | |||
| <Grid container sx={{mb:3}}> | |||
| <Grid item xs={12} s={12} md={12} lg={5} sx={{ml:3, mr:3, display: 'flex', alignItems: 'center'}}> | |||
| Idle Logout Time | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={5} justifyContent="space-between" alignItems="right"> | |||
| <TextField | |||
| fullWidth | |||
| {...register("idleLogoutTime")} | |||
| id="idleLogoutTime" | |||
| InputProps={{ | |||
| endAdornment: <InputAdornment position="start">minutes</InputAdornment>, | |||
| }} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| <Divider variant="middle" /> | |||
| </Grid> | |||
| {/*row 4*/} | |||
| <Grid item s={12} md={9} lg={8} sx={{ml:3, mr:3, mb:3}} alignItems={"center"} justifyContent="center"> | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml:3, mr:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| onClick={resetForm} | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Clear | |||
| </Button> | |||
| </Grid> | |||
| <Grid item sx={{ml:3, mr:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Save Change | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default SettingPage; | |||
| @@ -0,0 +1,80 @@ | |||
| // material-ui | |||
| import { | |||
| DataGrid, | |||
| } from "@mui/x-data-grid"; | |||
| import {useEffect, useState} from "react"; | |||
| import axios from "axios"; | |||
| import {apiPath} from "../../auth/utils"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| import * as React from "react"; | |||
| import {GET_AUTH_LIST} from "../../utils/ApiPathConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UserAuthTable({setSelectedRow, userAuth}) { | |||
| const [authData, setAuthData] = useState([]); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [currentSelectedRow, setCurrentSelectedRow] = useState(userAuth); | |||
| useEffect(() => { | |||
| axios.get(`${apiPath}${GET_AUTH_LIST}`) | |||
| .then((response) => { | |||
| if (response.status === 200) { | |||
| setAuthData(response.data.records); | |||
| } | |||
| }) | |||
| .catch(error => { | |||
| console.log(error); | |||
| return false; | |||
| }); | |||
| }, []); | |||
| useEffect(() => { | |||
| //if state data are ready and assign to different field | |||
| if (authData.length > 0) { | |||
| setOnReady(true); | |||
| } | |||
| }, [authData]); | |||
| const columns = [ | |||
| { | |||
| id: 'module', | |||
| field: 'module', | |||
| headerName: 'Module', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'authority', | |||
| field: 'name', | |||
| headerName: 'Authority', | |||
| flex: 2, | |||
| }, | |||
| ]; | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <div style={{height: '100%', width: '100%'}}> | |||
| <DataGrid | |||
| rows={authData} | |||
| columns={columns} | |||
| editMode="row" | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: {page: 0, pageSize: 20}, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[10, 20, 30]} | |||
| checkboxSelection | |||
| rowSelectionModel={currentSelectedRow} | |||
| onRowSelectionModelChange={(ids) => { | |||
| console.log(ids); | |||
| setSelectedRow(ids); | |||
| setCurrentSelectedRow(ids); | |||
| }} | |||
| autoHeight | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,60 @@ | |||
| // material-ui | |||
| import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import * as React from "react"; | |||
| import {useEffect, useState} from "react"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| import UserAuthTable from "./UserAuthTable"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserAuthorityCard = ({isCollectData, updateUserAuthList,userData}) => { | |||
| const [currentAuthData, setCurrentAuthData] = React.useState({}); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [selectedRow, setSelectedRow] = useState([]); | |||
| useEffect(() => { | |||
| //if user data from parent are not null | |||
| if (Object.keys(userData).length > 0 && userData !== undefined) { | |||
| setCurrentAuthData(userData.data); | |||
| setSelectedRow(userData.authIds); | |||
| } | |||
| }, [userData]); | |||
| useEffect(() => { | |||
| //if state data are ready and assign to different field | |||
| if (Object.keys(userData).length > 0 && currentAuthData !== undefined) { | |||
| setOnReady(true); | |||
| } | |||
| }, [currentAuthData]); | |||
| useEffect(() => { | |||
| //upload latest data to parent | |||
| updateUserAuthList(selectedRow); | |||
| }, [isCollectData]); | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <Typography variant="h5" sx={{mt: 3, ml: 3}}> | |||
| User Authority | |||
| </Typography> | |||
| <UserAuthTable | |||
| userAuth={userData.authIds} | |||
| setSelectedRow={setSelectedRow} | |||
| /> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserAuthorityCard; | |||
| @@ -0,0 +1,59 @@ | |||
| // material-ui | |||
| import { | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import * as React from "react"; | |||
| import {useEffect, useState} from "react"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| import UserGroupTable from "./UserGroupTable"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserGroupCard = ({isCollectData, updateUserGroupList,userData}) => { | |||
| const [currentUserData, setCurrentUserData] = React.useState({}); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [selectedRow, setSelectedRow] = useState([]); | |||
| useEffect(() => { | |||
| //if user data from parent are not null | |||
| if (Object.keys(userData).length > 0 && userData !== undefined) { | |||
| setCurrentUserData(userData.data); | |||
| setSelectedRow(userData.groupIds); | |||
| } | |||
| }, [userData]); | |||
| useEffect(() => { | |||
| //if state data are ready and assign to different field | |||
| if (Object.keys(userData).length > 0 &¤tUserData !== undefined) { | |||
| setOnReady(true); | |||
| } | |||
| }, [currentUserData]); | |||
| useEffect(() => { | |||
| //upload latest data to parent | |||
| updateUserGroupList(selectedRow); | |||
| }, [isCollectData]); | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <Typography variant="h5" sx={{mt: 3, ml: 3}}> | |||
| Group(s) | |||
| </Typography> | |||
| <UserGroupTable | |||
| userGroup={userData.groupIds} | |||
| setSelectedRow={setSelectedRow} | |||
| /> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserGroupCard; | |||
| @@ -0,0 +1,76 @@ | |||
| // material-ui | |||
| import { | |||
| DataGrid, | |||
| } from "@mui/x-data-grid"; | |||
| import {useEffect, useState} from "react"; | |||
| import axios from "axios"; | |||
| import {apiPath} from "../../auth/utils"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| import * as React from "react"; | |||
| import {GET_GROUP_COMBO_PATH} from "../../utils/ApiPathConst"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UserGroupTable({setSelectedRow, userGroup}) { | |||
| const [groupData, setGroupData] = useState([]); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [currentSelectedRow, setCurrentSelectedRow] = useState(userGroup); | |||
| useEffect(() => { | |||
| axios.get(`${apiPath}${GET_GROUP_COMBO_PATH}`) | |||
| .then((response) => { | |||
| if (response.status === 200) { | |||
| setGroupData(response.data.records); | |||
| } | |||
| }) | |||
| .catch(error => { | |||
| console.log(error); | |||
| return false; | |||
| }); | |||
| }, []); | |||
| useEffect(() => { | |||
| //if state data are ready and assign to different field | |||
| console.log(groupData.length) | |||
| if (groupData !== "" && groupData !== undefined) { | |||
| setOnReady(true); | |||
| } | |||
| }, [groupData]); | |||
| const columns = [ | |||
| { | |||
| id: 'group', | |||
| field: 'name', | |||
| headerName: 'Group', | |||
| flex: 1, | |||
| editable: true, | |||
| }, | |||
| ]; | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <div style={{height: '100%', width: '100%'}}> | |||
| <DataGrid | |||
| rows={groupData} | |||
| columns={columns} | |||
| editMode="row" | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: {page: 0, pageSize: 3}, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[3, 5]} | |||
| checkboxSelection | |||
| rowSelectionModel={currentSelectedRow} | |||
| onRowSelectionModelChange={(ids) => { | |||
| console.log(ids); | |||
| setSelectedRow(ids); | |||
| setCurrentSelectedRow(ids); | |||
| }} | |||
| autoHeight | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,321 @@ | |||
| // material-ui | |||
| import { | |||
| Grid, TextField, Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import * as React from "react"; | |||
| import {useForm} from "react-hook-form"; | |||
| import Autocomplete from "@mui/material/Autocomplete"; | |||
| import { | |||
| subDivision1, | |||
| subDivision2, | |||
| subDivision3, | |||
| subDivision4, | |||
| subDivision5, | |||
| subDivision6 | |||
| } from "../pnspsUserSettingPage/DummyComboRecord"; | |||
| import {useEffect, useState} from "react"; | |||
| import Checkbox from "@mui/material/Checkbox"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| //import {useParams} from "react-router-dom"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const subDivisionArray = [ | |||
| ...subDivision1, | |||
| ...subDivision2, | |||
| ...subDivision3, | |||
| ...subDivision4, | |||
| ...subDivision5, | |||
| ...subDivision6 | |||
| ]; | |||
| const UserInformationCard = ({isCollectData, updateUserObject,userData}) => { | |||
| //const params = useParams(); | |||
| const [currentUserData, setCurrentUserData] = React.useState({}); | |||
| const [subDivision, setSubDivision] = useState(null); | |||
| const [locked, setLocked] = useState(false); | |||
| const [isLotusNoteUser, setIsLotusNoteUser] = useState(false); | |||
| const [lotusNoteUserList, setLotusNoteUserList] = useState([]) | |||
| const [selectedLotusUser, setSelectedLotusUser] = useState(null); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const {register, getValues} = useForm() | |||
| useEffect(() => { | |||
| //TODO: Get lotus note user list | |||
| setLotusNoteUserList([ | |||
| { | |||
| key: 1, | |||
| label: "user01", | |||
| account: "user123456" | |||
| }, | |||
| { | |||
| key: 2, | |||
| label: "user02", | |||
| account: "userabcde1" | |||
| }, | |||
| { | |||
| key: 3, | |||
| label: "user03", | |||
| account: "user2001" | |||
| }, | |||
| { | |||
| key: 4, | |||
| label: "user04", | |||
| account: "user2000" | |||
| }, | |||
| { | |||
| key: 5, | |||
| label: "user05", | |||
| account: "user1999" | |||
| }, | |||
| ]) | |||
| }, []); | |||
| useEffect(() => { | |||
| //if user data from parent are not null | |||
| if (Object.keys(userData).length > 0 && userData !== undefined) { | |||
| setCurrentUserData(userData.data); | |||
| } | |||
| }, [userData]); | |||
| useEffect(() => { | |||
| //if state data are ready and assign to different field | |||
| if (Object.keys(userData).length > 0 &¤tUserData !== undefined) { | |||
| setLocked(currentUserData.locked); | |||
| setOnReady(true); | |||
| } | |||
| }, [currentUserData]); | |||
| useEffect(() => { | |||
| //upload latest data to parent | |||
| const values = getValues(); | |||
| const objectData ={ | |||
| ...values, | |||
| selectedLotusUser: selectedLotusUser, | |||
| subDivision: subDivision, | |||
| locked: locked, | |||
| } | |||
| updateUserObject(objectData); | |||
| }, [isCollectData]); | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <Typography variant="h5" sx={{mt: 3, ml: 3, mb: 1}}> | |||
| Information | |||
| </Typography> | |||
| <form> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Lotus Note User: | |||
| </Grid> | |||
| <Grid item xs={1} s={1} md={1} lg={1}> | |||
| <Checkbox | |||
| checked={isLotusNoteUser} | |||
| onChange={(event) => setIsLotusNoteUser(event.target.checked)} | |||
| name="isLotusNoteUser" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={6} s={6} md={6} lg={5}> | |||
| <Autocomplete | |||
| disablePortal | |||
| id="lotus-note-combo" | |||
| value={selectedLotusUser === null ? null : selectedLotusUser} | |||
| options={lotusNoteUserList} | |||
| disabled={!isLotusNoteUser} | |||
| onChange={(event, newValue) => { | |||
| setSelectedLotusUser(newValue); | |||
| }} | |||
| renderInput={(params) => <TextField {...params} />} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid container> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Username: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("userName", | |||
| { | |||
| value: currentUserData.username, | |||
| })} | |||
| id='username' | |||
| disabled | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Password: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("password")} | |||
| id='password' | |||
| disabled | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Full Name: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("fullName", | |||
| { | |||
| value: currentUserData.fullname, | |||
| })} | |||
| id='fullName' | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Post: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("post", | |||
| { | |||
| value: currentUserData.post, | |||
| })} | |||
| id='post' | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Sub-Division: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <Autocomplete | |||
| disablePortal | |||
| id="sub-division-combo" | |||
| value={subDivision === null ? null : subDivision} | |||
| options={subDivisionArray} | |||
| onChange={(event, newValue) => { | |||
| setSubDivision(newValue); | |||
| }} | |||
| renderInput={(params) => <TextField {...params} />} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Email: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("email", | |||
| { | |||
| value: currentUserData.email, | |||
| })} | |||
| id='email' | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Phone: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("phone1", | |||
| { | |||
| value: currentUserData.phone1, | |||
| })} | |||
| id='phone1' | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| <Grid item xs={12} s={12} md={12} lg={12} sx={{ml: 3, mr: 3, mb: 3}}> | |||
| <Grid container> | |||
| <Grid item xs={4} s={4} md={4} lg={4} | |||
| sx={{ml: 3, mr: 3, display: 'flex', alignItems: 'center'}}> | |||
| Locked: | |||
| </Grid> | |||
| <Grid item xs={7} s={7} md={7} lg={6}> | |||
| <Checkbox | |||
| checked={locked} | |||
| onChange={(event) => setLocked(event.target.checked)} | |||
| name="checked" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserInformationCard; | |||
| @@ -0,0 +1,135 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| Grid, Typography | |||
| } from '@mui/material'; | |||
| import {useEffect, useState} from "react"; | |||
| import * as React from "react"; | |||
| import axios from "axios"; | |||
| import {apiPath} from "../../auth/utils"; | |||
| import {useParams} from "react-router-dom"; | |||
| import UserInformationCard from "./UserInformationCard"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| import UserGroupCard from "./UserGroupCard"; | |||
| import UserAuthorityCard from "./UserAuthorityCard"; | |||
| import {GET_USER_PATH} from "../../utils/ApiPathConst"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserMaintainPage = () => { | |||
| const params = useParams(); | |||
| const [userData, setUserData] = React.useState({}); | |||
| const [onReady, setOnReady] = useState(false); | |||
| const [isCollectData, setIsCollectData] = useState(false); | |||
| const [editedCustomerData, setEditedCustomerData] = useState({}); | |||
| const [userGroupData,setUserGroupData] = useState([]); | |||
| const [userAuthData,setUserAuthData] = useState([]); | |||
| const [userConfirm, setUserConfirm] = useState(false); | |||
| function updateUserObject(userData) { | |||
| setEditedCustomerData(userData); | |||
| } | |||
| function updateUserGroupList(userGroupData){ | |||
| setUserGroupData(userGroupData); | |||
| } | |||
| function updateUserAuthList(userAuthData){ | |||
| setUserAuthData(userAuthData); | |||
| } | |||
| const submitData = () => { | |||
| setUserConfirm(true); | |||
| setIsCollectData(!isCollectData); | |||
| } | |||
| useEffect(() => { | |||
| axios.get(`${apiPath}${GET_USER_PATH}/${params.id}`) | |||
| .then((response) => { | |||
| if (response.status === 200) { | |||
| setUserData(response.data); | |||
| } | |||
| }) | |||
| .catch(error => { | |||
| console.log(error); | |||
| return false; | |||
| }); | |||
| }, []); | |||
| useEffect(() => { | |||
| setOnReady(true); | |||
| }, [userData]); | |||
| useEffect(() => { | |||
| if(userConfirm && onReady){ | |||
| console.log("update in parents"); | |||
| console.log(editedCustomerData); | |||
| console.log(userGroupData); | |||
| console.log(userAuthData); | |||
| } | |||
| setUserConfirm(false); | |||
| }, [editedCustomerData,userGroupData,userAuthData]); | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75}> | |||
| <Grid item xs={12} sx={{mb: -2.25}}> | |||
| <Typography variant="h5">Maintain User</Typography> | |||
| </Grid> | |||
| {/*col 1*/} | |||
| <Grid item xs={12} md={5} lg={5}> | |||
| <Grid container> | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <UserInformationCard | |||
| updateUserObject={updateUserObject} | |||
| userData={userData} | |||
| isCollectData={isCollectData} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={12} md={12} lg={12} sx={{mt: 3}}> | |||
| <UserGroupCard | |||
| updateUserGroupList={updateUserGroupList} | |||
| userData={userData} | |||
| isCollectData={isCollectData} | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| {/*col 2*/} | |||
| <Grid item xs={12} md={7} lg={7}> | |||
| <UserAuthorityCard | |||
| updateUserAuthList={updateUserAuthList} | |||
| userData={userData} | |||
| isCollectData={isCollectData} | |||
| /> | |||
| </Grid> | |||
| {/*bottom button*/} | |||
| <Grid item s={12} md={12} lg={12} sx={{mb: 3}} alignItems={"end"} justifyContent="center"> | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml: 3, mr: 3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }} | |||
| onClick={submitData} | |||
| > | |||
| Save User | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserMaintainPage; | |||
| @@ -0,0 +1,93 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| CardContent, | |||
| Grid, TextField, | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import {useForm} from "react-hook-form"; | |||
| import * as React from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserGroupSearchForm = ({applySearch}) => { | |||
| const { reset, register, handleSubmit } = useForm() | |||
| const onSubmit = (data) => { | |||
| console.log(data) | |||
| applySearch(data); | |||
| }; | |||
| function resetForm(){ | |||
| reset(); | |||
| } | |||
| return ( | |||
| <MainCard xs={12} md={12} lg={12} | |||
| border={false} | |||
| content={false}> | |||
| <form onSubmit={handleSubmit(onSubmit)}> | |||
| {/*row 1*/} | |||
| <CardContent sx={{ px: 2.5, pt: 3 }}> | |||
| <Grid item justifyContent="space-between" alignItems="center"> | |||
| Search Form | |||
| </Grid> | |||
| </CardContent> | |||
| {/*row 2*/} | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("userGroupName")} | |||
| id='userGroupName' | |||
| label="User Group Name" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("userGroupDescription")} | |||
| id="userGroupDescription" | |||
| label="User Group Description" | |||
| /> | |||
| </Grid> | |||
| </Grid> | |||
| {/*last row*/} | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| onClick={resetForm} | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Clear | |||
| </Button> | |||
| </Grid> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Submit | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserGroupSearchForm; | |||
| @@ -0,0 +1,75 @@ | |||
| // material-ui | |||
| import * as React from 'react'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| } from "@mui/x-data-grid"; | |||
| import EditIcon from '@mui/icons-material/Edit'; | |||
| import {useEffect} from "react"; | |||
| import {useNavigate} from "react-router-dom"; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UserGroupTable({recordList}) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel] = React.useState({}); | |||
| const navigate = useNavigate() | |||
| useEffect(() => { | |||
| setRows(recordList); | |||
| }, [recordList]); | |||
| const handleEditClick = (id) => () => { | |||
| navigate('/userGroup/'+ id); | |||
| }; | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: 'Actions', | |||
| width: 100, | |||
| cellClassName: 'actions', | |||
| getActions: ({id}) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<EditIcon/>} | |||
| label="Edit" | |||
| className="textPrimary" | |||
| onClick={handleEditClick(id)} | |||
| color="primary" | |||
| />] | |||
| }, | |||
| }, | |||
| { | |||
| id: 'groupName', | |||
| field: 'groupName', | |||
| headerName: 'User Group Name', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'description', | |||
| field: 'description', | |||
| headerName: 'User Group Description', | |||
| flex: 1, | |||
| }, | |||
| ]; | |||
| return ( | |||
| <div style={{height: 400, width: '100%'}}> | |||
| <DataGrid | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| rowModesModel={rowModesModel} | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: {page: 0, pageSize: 10}, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[10, 15, 20]} | |||
| autoHeight | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,78 @@ | |||
| // material-ui | |||
| import { | |||
| Grid, Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import UserGroupSearchForm from "./UserGroupSearchForm"; | |||
| import UserGroupTable from "./UserGroupTable"; | |||
| import {useEffect, useState} from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserGroupSearchPanel = () => { | |||
| const [record] = useState([]); | |||
| const [searchCriteria, setSearchCriteria] = useState({}); | |||
| const [sortedRecord, setSortedRecord] = useState([]); | |||
| const filterSearchName = (array) => { | |||
| return array.filter((item) => item.name.toLowerCase().includes(searchCriteria.eventName)); | |||
| }; | |||
| const filterSearchType = (array) => { | |||
| return array.filter((item) => item.category.includes(searchCriteria.type)); | |||
| }; | |||
| function sortData(record){ | |||
| let sortedRecord = record; | |||
| sortedRecord = filterSearchName(sortedRecord); | |||
| sortedRecord = filterSearchType(sortedRecord); | |||
| return sortedRecord; | |||
| } | |||
| function applySearch(input){ | |||
| setSearchCriteria(input); | |||
| //console.log("Apply Search: "); | |||
| //console.log(input); | |||
| } | |||
| useEffect(() => { | |||
| //console.log(searchCriteria); | |||
| if(Object.keys(searchCriteria).length !== 0){ | |||
| const tempSortedRecord = sortData(record); | |||
| console.log(tempSortedRecord); | |||
| setSortedRecord(tempSortedRecord); | |||
| }else{ | |||
| setSortedRecord(record); | |||
| } | |||
| }, [searchCriteria]); | |||
| return ( | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75}> | |||
| <Grid item xs={12} sx={{mb: -2.25}}> | |||
| <Typography variant="h5">View User Group</Typography> | |||
| </Grid> | |||
| {/*row 1*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <UserGroupSearchForm applySearch={applySearch}/> | |||
| </Grid> | |||
| {/*row 2*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <UserGroupTable | |||
| recordList={sortedRecord} | |||
| /> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserGroupSearchPanel; | |||
| @@ -0,0 +1,229 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| CardContent, FormControlLabel, | |||
| Grid, TextField, | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import {useForm} from "react-hook-form"; | |||
| import {useEffect, useState} from "react"; | |||
| import Autocomplete from '@mui/material/Autocomplete'; | |||
| import { | |||
| subDivision1, | |||
| subDivision2, | |||
| subDivision3, | |||
| subDivision4, | |||
| subDivision5, | |||
| subDivision6 | |||
| } from "pages/pnspsUserSettingPage/DummyComboRecord"; | |||
| import Checkbox from "@mui/material/Checkbox"; | |||
| import * as React from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const subDivisionArray =[ | |||
| ...subDivision1, | |||
| ...subDivision2, | |||
| ...subDivision3, | |||
| ...subDivision4, | |||
| ...subDivision5, | |||
| ...subDivision6 | |||
| ]; | |||
| const UserSearchForm = ({applySearch}) => { | |||
| const [type, setType] = useState([]); | |||
| const [division, setDivision] = useState(null); | |||
| const [subDivision, setSubDivision] = useState(null); | |||
| const [isLotusNoteUser, setIsLotusNoteUser] = useState(false); | |||
| const [locked, setLocked] = useState(false); | |||
| const { reset, register, handleSubmit } = useForm() | |||
| const onSubmit = (data) => { | |||
| let typeArray = []; | |||
| for(let i =0; i < type.length; i++){ | |||
| typeArray.push(type[i].label); | |||
| } | |||
| const temp = { | |||
| username: data.userName, | |||
| fullName: data.fullName, | |||
| post: data.post, | |||
| subDivision: subDivision, | |||
| email: data.email, | |||
| phone: data.phone, | |||
| isLotusNoteUser: isLotusNoteUser, | |||
| locked: locked, | |||
| }; | |||
| applySearch(temp); | |||
| }; | |||
| useEffect(() => { | |||
| if(division != null){ | |||
| setSubDivision(subDivisionArray[division.type-1][0]); | |||
| } | |||
| }, [division]); | |||
| function resetForm(){ | |||
| setType([]); | |||
| setDivision(null); | |||
| setSubDivision(null); | |||
| setIsLotusNoteUser(false); | |||
| setLocked(false); | |||
| reset(); | |||
| } | |||
| return ( | |||
| <MainCard xs={12} md={12} lg={12} | |||
| border={false} | |||
| content={false}> | |||
| <form onSubmit={handleSubmit(onSubmit)}> | |||
| {/*row 1*/} | |||
| <CardContent sx={{ px: 2.5, pt: 3 }}> | |||
| <Grid item justifyContent="space-between" alignItems="center"> | |||
| Search Form | |||
| </Grid> | |||
| </CardContent> | |||
| {/*row 2*/} | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("userName")} | |||
| id='userName' | |||
| label="Username" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("fullName")} | |||
| id="fullName" | |||
| label="Full Name" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("post")} | |||
| id="post" | |||
| label="Post" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <Autocomplete | |||
| disablePortal | |||
| id="sub-division-combo" | |||
| value={subDivision === null? null : subDivision} | |||
| options={subDivisionArray} | |||
| onChange={(event, newValue) => { | |||
| setSubDivision(newValue); | |||
| }} | |||
| renderInput={(params) => <TextField {...params} label="Sub-Division" />} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("email")} | |||
| id="email" | |||
| label="Email" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("phone")} | |||
| id="phone" | |||
| label="Phone" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <FormControlLabel | |||
| control={ | |||
| <Checkbox | |||
| checked={isLotusNoteUser} | |||
| onChange={(event) => setIsLotusNoteUser(event.target.checked)} | |||
| name="checked" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| } | |||
| label={<Typography variant="h6">Lotus Notes User</Typography>} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <FormControlLabel | |||
| control={ | |||
| <Checkbox | |||
| checked={locked} | |||
| onChange={(event) => setLocked(event.target.checked)} | |||
| name="checked" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| } | |||
| label={<Typography variant="h6">Locked</Typography>} | |||
| /> | |||
| </Grid> | |||
| {/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/} | |||
| {/* <TextField*/} | |||
| {/* fullWidth*/} | |||
| {/* {...register("subDivisionId")}*/} | |||
| {/* id="subDivision"*/} | |||
| {/* label="Sub-Division"*/} | |||
| {/* />*/} | |||
| {/*</Grid>*/} | |||
| </Grid> | |||
| {/*last row*/} | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| onClick={resetForm} | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Clear | |||
| </Button> | |||
| </Grid> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Submit | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserSearchForm; | |||
| @@ -0,0 +1,137 @@ | |||
| // material-ui | |||
| import * as React from 'react'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| } from "@mui/x-data-grid"; | |||
| import EditIcon from '@mui/icons-material/Edit'; | |||
| import {useEffect} from "react"; | |||
| import {useNavigate} from "react-router-dom"; | |||
| import { useTheme } from '@mui/material/styles'; | |||
| import Checkbox from '@mui/material/Checkbox'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UserTable({recordList}) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel] = React.useState({}); | |||
| const theme = useTheme(); | |||
| const navigate = useNavigate() | |||
| useEffect(() => { | |||
| setRows(recordList); | |||
| }, [recordList]); | |||
| const handleEditClick = (id) => () => { | |||
| navigate('/user/'+ id); | |||
| }; | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: 'Actions', | |||
| width: 100, | |||
| cellClassName: 'actions', | |||
| getActions: ({id}) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<EditIcon/>} | |||
| label="Edit" | |||
| className="textPrimary" | |||
| onClick={handleEditClick(id)} | |||
| color="primary" | |||
| />] | |||
| }, | |||
| }, | |||
| { | |||
| id: 'username', | |||
| field: 'username', | |||
| headerName: 'User Name', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| headerName: 'Full Name', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'post', | |||
| field: 'post', | |||
| headerName: 'Post', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'email', | |||
| field: 'email', | |||
| headerName: 'Email', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'subDivisionId', | |||
| field: 'subDivisionId', | |||
| //type: 'date', | |||
| //sortable: false, | |||
| headerName: 'Sub-Division', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'lotusNotesUser', | |||
| field: 'lotusNotesUser', | |||
| type: 'bool', | |||
| headerName: 'Lotus Notes User', | |||
| flex: 1, | |||
| renderCell: (params) => { | |||
| return ( | |||
| <Checkbox | |||
| theme={theme} | |||
| key="locked" | |||
| checked={params.row.lotusNotesUser} | |||
| color="primary" | |||
| size="small" | |||
| //onChange={handleChange} | |||
| /> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| id: 'locked', | |||
| field: 'locked', | |||
| type: 'bool', | |||
| headerName: 'Locked', | |||
| flex: 1, | |||
| renderCell: (params) => { | |||
| return ( | |||
| <Checkbox | |||
| theme={theme} | |||
| key="locked" | |||
| checked={params.row.locked} | |||
| color="primary" | |||
| size="small" | |||
| //onChange={handleChange} | |||
| /> | |||
| ); | |||
| }, | |||
| }, | |||
| ]; | |||
| return ( | |||
| <div style={{height: 400, width: '100%'}}> | |||
| <DataGrid | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| rowModesModel={rowModesModel} | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: {page: 0, pageSize: 5}, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[5, 10]} | |||
| autoHeight | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,84 @@ | |||
| // material-ui | |||
| import { | |||
| Grid, Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import SearchForm from "./UserSearchForm"; | |||
| import EventTable from "./UserTable"; | |||
| import {useEffect, useState} from "react"; | |||
| import axios from "axios"; | |||
| import {apiPath} from "../../auth/utils"; | |||
| import {GET_USER_PATH} from "../../utils/ApiPathConst"; | |||
| import * as React from "react"; | |||
| import LoadingComponent from "../extra-pages/LoadingComponent"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSettingPage = () => { | |||
| const [record,setRecord] = useState([]); | |||
| const [searchCriteria, setSearchCriteria] = useState({}); | |||
| const [onReady, setOnReady] = useState(false); | |||
| useEffect(() => { | |||
| getUserList(); | |||
| }, []); | |||
| useEffect(() => { | |||
| setOnReady(true); | |||
| }, [record]); | |||
| useEffect(() => { | |||
| getUserList(); | |||
| }, [searchCriteria]); | |||
| function getUserList(){ | |||
| axios.get(`${apiPath}${GET_USER_PATH}`, | |||
| {params: searchCriteria} | |||
| ) | |||
| .then((response) => { | |||
| if (response.status === 200) { | |||
| setRecord(response.data); | |||
| } | |||
| }) | |||
| .catch(error => { | |||
| console.log(error); | |||
| return false; | |||
| }); | |||
| } | |||
| function applySearch(input) { | |||
| setSearchCriteria(input); | |||
| } | |||
| return ( | |||
| !onReady ? | |||
| <LoadingComponent/> | |||
| : | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75}> | |||
| <Grid item xs={12} sx={{mb: -2.25}}> | |||
| <Typography variant="h5">View User</Typography> | |||
| </Grid> | |||
| {/*row 1*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <SearchForm applySearch={applySearch}/> | |||
| </Grid> | |||
| {/*row 2*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <EventTable | |||
| recordList={record} | |||
| /> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserSettingPage; | |||
| @@ -0,0 +1,77 @@ | |||
| export const eventType = [ | |||
| {label: '同心', type: 1}, | |||
| {label: '創新', type: 2}, | |||
| {label: '惠民', type: 3}, | |||
| {label: '傳承', type: 3}, | |||
| ]; | |||
| export const divisionType = [ | |||
| {key: 1, label: 'Railways Branch', type: 1}, | |||
| {key: 2, label: 'Electricity and Energy Efficiency Branch ', type: 2}, | |||
| {key: 3, label: 'Gas and General Legislation Branch', type: 3}, | |||
| {key: 4, label: 'Engineering Services Branch 1', type: 4}, | |||
| {key: 5, label: 'Engineering Services Branch 2', type: 5}, | |||
| {key: 6, label: 'Engineering Services Branch 3', type: 6}, | |||
| ]; | |||
| export const subDivision1 = [ | |||
| {key: 1, label: 'Sub Division 1 of Railways Branch', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Railways Branch', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Railways Branch', type: 3}, | |||
| {key: 4, label: 'Sub Division 4 of Railways Branch', type: 4}, | |||
| ]; | |||
| export const subDivision2 = [ | |||
| {key: 1, label: 'Sub Division 1 of Electricity and Energy Efficiency Branch', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Electricity and Energy Efficiency Branch', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Electricity and Energy Efficiency Branch', type: 3}, | |||
| ]; | |||
| export const subDivision3 = [ | |||
| {key: 1, label: 'Sub Division 1 of Gas and General Legislation Branch', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Gas and General Legislation Branch', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Gas and General Legislation Branch', type: 3}, | |||
| ]; | |||
| export const subDivision4 = [ | |||
| {key: 1, label: 'Sub Division 1 of Engineering Services Branch 1', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Engineering Services Branch 1', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Engineering Services Branch 1', type: 3}, | |||
| {key: 4, label: 'Sub Division 4 of Engineering Services Branch 1', type: 4}, | |||
| ]; | |||
| export const subDivision5 = [ | |||
| {key: 1, label: 'Sub Division 1 of Engineering Services Branch 2', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Engineering Services Branch 2', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Engineering Services Branch 2', type: 3}, | |||
| ]; | |||
| export const subDivision6 = [ | |||
| {key: 1, label: 'Sub Division 1 of Engineering Services Branch 3', type: 1}, | |||
| {key: 2, label: 'Sub Division 2 of Engineering Services Branch 3', type: 2}, | |||
| {key: 3, label: 'Sub Division 3 of Engineering Services Branch 3', type: 3}, | |||
| ]; | |||
| export const tableRecord = [ | |||
| {trackingNo: 84564564, name: 'Camera', fat: 40, carbs: 2, protein: 4057}, | |||
| {trackingNo: 98764564, name: 'Laptop', fat: 300, carbs: 0, protein: 180139}, | |||
| {trackingNo: 98756325, name: 'Mobile', fat: 355, carbs: 1, protein: 90989}, | |||
| {trackingNo: 98652366, name: 'Handset', fat: 50, carbs: 1, protein: 10239}, | |||
| {trackingNo: 13286564, name: 'Computer', fat: 100, carbs: 1, protein: 8334}, | |||
| {trackingNo: 86739658, name: 'TV', fat: 99, carbs: 0, protein: 410780}, | |||
| {trackingNo: 13256498, name: 'Keyboard', fat: 125, carbs: 2, protein: 70999}, | |||
| {trackingNo: 98753263, name: 'Mouse', fat: 89, carbs: 2, protein: 10570}, | |||
| {trackingNo: 98753275, name: 'Desktop', fat: 185, carbs: 1, protein: 98063}, | |||
| {trackingNo: 98753291, name: 'Chair', fat: 100, carbs: 0, protein: 14001}, | |||
| ]; | |||
| export const tableRecordTemp = [ | |||
| {id:1 ,eventNo: 84564564, eventDate:"2022-03-20" , category: '同心', hrmPlan: 'Visionary Leadership', name: 'HKMA Best Annual Reports Awards - The Electrical and Mechanical Services Department Annual Report 2020/21 - Certificate of Excellence'}, | |||
| {id:2 ,eventNo: 98764564, eventDate:"2022-05-12" , category: '同心', hrmPlan: 'Visionary Leadership', name: 'HKMA Best Annual Reports Awards - The Electrical and Mechanical Services Department Annual Report 2020/21- Best New Entry'}, | |||
| {id:3 ,eventNo: 98756325, eventDate:"2022-06-04" , category: '創新', hrmPlan: 'Visionary Leadership', name: '19th Hong Kong Occupational Safety and Health Award - Gold Award - The Virtual Reality-based Lift Maintenance training programme'}, | |||
| {id:4 ,eventNo: 98652366, eventDate:"2022-08-16" , category: '創新', hrmPlan: 'Visionary Leadership', name: 'BIM Achievement 2022 - BIM Organisations 2022'}, | |||
| {id:5 ,eventNo: 13286564, eventDate:"2022-09-30" , category: '惠民', hrmPlan: 'Visionary Leadership', name: 'Civil Service Outstanding Service Award Scheme 2022 - Excellence in Team Collaboration (Internal Service) - Innovation Facilitator'}, | |||
| {id:6 ,eventNo: 86739658, eventDate:"2022-10-25" , category: '惠民', hrmPlan: 'Visionary Leadership', name: 'Civil Service Outstanding Service Award Scheme 2022 - Excellence in Team Collaboration (Management of Crisis) - E&M 100 - CHT Rescue Team'}, | |||
| {id:7 ,eventNo: 13256498, eventDate:"2022-11-21" , category: '傳承', hrmPlan: 'Visionary Leadership', name: '11th Guangzhou/Hong Kong/Macao/Chengdu Youth Skills Competition - Three TTs from the EMSD got the top three prizes in the Electrical Installations trade of the Hong Kong Region qualifying competition'}, | |||
| {id:8 ,eventNo: 98753263, eventDate:"2022-12-31" , category: '傳承', hrmPlan: 'Visionary Leadership', name: 'VTC 2021 Outstanding Apprentices Scheme - Outstanding Apprentice - Mr. LEE King (TTII)'}, | |||
| ]; | |||
| @@ -0,0 +1,232 @@ | |||
| // material-ui | |||
| import { | |||
| Button, | |||
| CardContent, FormControlLabel, | |||
| Grid, TextField, | |||
| Typography | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import {useForm} from "react-hook-form"; | |||
| import dayjs from "dayjs"; | |||
| import {useEffect, useState} from "react"; | |||
| import Autocomplete from '@mui/material/Autocomplete'; | |||
| import { | |||
| subDivision1, | |||
| subDivision2, | |||
| subDivision3, | |||
| subDivision4, | |||
| subDivision5, | |||
| subDivision6 | |||
| } from "pages/pnspsUserSettingPage/DummyComboRecord"; | |||
| import Checkbox from "@mui/material/Checkbox"; | |||
| import * as React from "react"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const subDivisionArray =[ | |||
| ...subDivision1, | |||
| ...subDivision2, | |||
| ...subDivision3, | |||
| ...subDivision4, | |||
| ...subDivision5, | |||
| ...subDivision6 | |||
| ]; | |||
| const UserSearchForm = ({applySearch}) => { | |||
| const [value, setValue] = useState(); | |||
| const [type, setType] = useState([]); | |||
| const [division, setDivision] = useState(null); | |||
| const [subDivision, setSubDivision] = useState(null); | |||
| const [isLotusNoteUser, setIsLotusNoteUser] = useState(false); | |||
| const [locked, setLocked] = useState(false); | |||
| const { reset, register, handleSubmit } = useForm() | |||
| const onSubmit = (data) => { | |||
| let typeArray = []; | |||
| for(let i =0; i < type.length; i++){ | |||
| typeArray.push(type[i].label); | |||
| } | |||
| const temp = { | |||
| eventName: data.eventName, | |||
| eventOrganization: data.eventOrganization, | |||
| eventRegion: data.eventRegion, | |||
| eventDescription: data.eventDescription, | |||
| type: typeArray, | |||
| division: division, | |||
| subDivision: subDivision, | |||
| selectedDate: dayjs(value).format("MM/DD/YYYY") | |||
| }; | |||
| applySearch(temp); | |||
| }; | |||
| useEffect(() => { | |||
| if(division != null){ | |||
| setSubDivision(subDivisionArray[division.type-1][0]); | |||
| } | |||
| }, [division]); | |||
| function resetForm(){ | |||
| setValue(new Date().toDateString()); | |||
| setType([]); | |||
| setDivision(null); | |||
| setSubDivision(null); | |||
| setIsLotusNoteUser(false); | |||
| setLocked(false); | |||
| reset(); | |||
| } | |||
| return ( | |||
| <MainCard xs={12} md={12} lg={12} | |||
| border={false} | |||
| content={false}> | |||
| <form onSubmit={handleSubmit(onSubmit)}> | |||
| {/*row 1*/} | |||
| <CardContent sx={{ px: 2.5, pt: 3 }}> | |||
| <Grid item justifyContent="space-between" alignItems="center"> | |||
| Search Form | |||
| </Grid> | |||
| </CardContent> | |||
| {/*row 2*/} | |||
| <Grid container alignItems={"center"}> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("userName")} | |||
| id='userName' | |||
| label="Username" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("fullName")} | |||
| id="fullName" | |||
| label="Full Name" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("post")} | |||
| id="post" | |||
| label="Post" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <Autocomplete | |||
| disablePortal | |||
| id="sub-division-combo" | |||
| value={subDivision === null? null : subDivision} | |||
| options={subDivisionArray} | |||
| onChange={(event, newValue) => { | |||
| setSubDivision(newValue); | |||
| }} | |||
| renderInput={(params) => <TextField {...params} label="Sub-Division" />} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("email")} | |||
| id="email" | |||
| label="Email" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <TextField | |||
| fullWidth | |||
| {...register("phone")} | |||
| id="phone" | |||
| label="Phone" | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <FormControlLabel | |||
| control={ | |||
| <Checkbox | |||
| checked={isLotusNoteUser} | |||
| onChange={(event) => setIsLotusNoteUser(event.target.checked)} | |||
| name="checked" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| } | |||
| label={<Typography variant="h6">Lotus Notes User</Typography>} | |||
| /> | |||
| </Grid> | |||
| <Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}> | |||
| <FormControlLabel | |||
| control={ | |||
| <Checkbox | |||
| checked={locked} | |||
| onChange={(event) => setLocked(event.target.checked)} | |||
| name="checked" | |||
| color="primary" | |||
| size="small" | |||
| /> | |||
| } | |||
| label={<Typography variant="h6">Locked</Typography>} | |||
| /> | |||
| </Grid> | |||
| {/*<Grid item xs={9} s={6} md={5} lg={3} sx={{ml:3, mr:3, mb:3}}>*/} | |||
| {/* <TextField*/} | |||
| {/* fullWidth*/} | |||
| {/* {...register("subDivisionId")}*/} | |||
| {/* id="subDivision"*/} | |||
| {/* label="Sub-Division"*/} | |||
| {/* />*/} | |||
| {/*</Grid>*/} | |||
| </Grid> | |||
| {/*last row*/} | |||
| <Grid container maxWidth justifyContent="flex-end"> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| onClick={resetForm} | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Clear | |||
| </Button> | |||
| </Grid> | |||
| <Grid item sx={{ml:3, mr:3, mb:3, mt:3}}> | |||
| <Button | |||
| size="large" | |||
| variant="contained" | |||
| type="submit" | |||
| sx={{ | |||
| textTransform: 'capitalize', | |||
| alignItems: 'end' | |||
| }}> | |||
| Submit | |||
| </Button> | |||
| </Grid> | |||
| </Grid> | |||
| </form> | |||
| </MainCard> | |||
| ); | |||
| }; | |||
| export default UserSearchForm; | |||
| @@ -0,0 +1,137 @@ | |||
| // material-ui | |||
| import * as React from 'react'; | |||
| import { | |||
| DataGrid, | |||
| GridActionsCellItem, | |||
| } from "@mui/x-data-grid"; | |||
| import EditIcon from '@mui/icons-material/Edit'; | |||
| import {useEffect} from "react"; | |||
| import {useNavigate} from "react-router-dom"; | |||
| import { useTheme } from '@mui/material/styles'; | |||
| import Checkbox from '@mui/material/Checkbox'; | |||
| // ==============================|| EVENT TABLE ||============================== // | |||
| export default function UserTable({recordList}) { | |||
| const [rows, setRows] = React.useState(recordList); | |||
| const [rowModesModel] = React.useState({}); | |||
| const theme = useTheme(); | |||
| const navigate = useNavigate() | |||
| useEffect(() => { | |||
| setRows(recordList); | |||
| }, [recordList]); | |||
| const handleEditClick = (id) => () => { | |||
| navigate('/user/'+ id); | |||
| }; | |||
| const columns = [ | |||
| { | |||
| field: 'actions', | |||
| type: 'actions', | |||
| headerName: 'Actions', | |||
| width: 100, | |||
| cellClassName: 'actions', | |||
| getActions: ({id}) => { | |||
| return [ | |||
| <GridActionsCellItem | |||
| key="OutSave" | |||
| icon={<EditIcon/>} | |||
| label="Edit" | |||
| className="textPrimary" | |||
| onClick={handleEditClick(id)} | |||
| color="primary" | |||
| />] | |||
| }, | |||
| }, | |||
| { | |||
| id: 'username', | |||
| field: 'username', | |||
| headerName: 'User Name', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'name', | |||
| field: 'name', | |||
| headerName: 'Full Name', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'post', | |||
| field: 'post', | |||
| headerName: 'Post', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'email', | |||
| field: 'email', | |||
| headerName: 'Email', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'subDivisionId', | |||
| field: 'subDivisionId', | |||
| //type: 'date', | |||
| //sortable: false, | |||
| headerName: 'Sub-Division', | |||
| flex: 1, | |||
| }, | |||
| { | |||
| id: 'lotusNotesUser', | |||
| field: 'lotusNotesUser', | |||
| type: 'bool', | |||
| headerName: 'Lotus Notes User', | |||
| flex: 1, | |||
| renderCell: (params) => { | |||
| return ( | |||
| <Checkbox | |||
| theme={theme} | |||
| key="locked" | |||
| checked={params.row.lotusNotesUser} | |||
| color="primary" | |||
| size="small" | |||
| //onChange={handleChange} | |||
| /> | |||
| ); | |||
| }, | |||
| }, | |||
| { | |||
| id: 'locked', | |||
| field: 'locked', | |||
| type: 'bool', | |||
| headerName: 'Locked', | |||
| flex: 1, | |||
| renderCell: (params) => { | |||
| return ( | |||
| <Checkbox | |||
| theme={theme} | |||
| key="locked" | |||
| checked={params.row.locked} | |||
| color="primary" | |||
| size="small" | |||
| //onChange={handleChange} | |||
| /> | |||
| ); | |||
| }, | |||
| }, | |||
| ]; | |||
| return ( | |||
| <div style={{height: 400, width: '100%'}}> | |||
| <DataGrid | |||
| rows={rows} | |||
| columns={columns} | |||
| editMode="row" | |||
| rowModesModel={rowModesModel} | |||
| initialState={{ | |||
| pagination: { | |||
| paginationModel: {page: 0, pageSize: 5}, | |||
| }, | |||
| }} | |||
| pageSizeOptions={[5, 10]} | |||
| autoHeight | |||
| /> | |||
| </div> | |||
| ); | |||
| } | |||
| @@ -0,0 +1,89 @@ | |||
| // material-ui | |||
| import { | |||
| Grid | |||
| } from '@mui/material'; | |||
| import MainCard from "../../components/MainCard"; | |||
| import SearchForm from "./UserSearchForm"; | |||
| import EventTable from "./UserTable"; | |||
| import {useEffect, useState} from "react"; | |||
| import axios from "axios"; | |||
| import {apiPath} from "../../auth/utils"; | |||
| import {GET_USER_PATH} from "../../utils/ApiPathConst"; | |||
| // ==============================|| DASHBOARD - DEFAULT ||============================== // | |||
| const UserSettingPage = () => { | |||
| const [record,setRecord] = useState([]); | |||
| const [searchCriteria, setSearchCriteria] = useState({}); | |||
| const [sortedRecord, setSortedRecord] = useState([]); | |||
| useEffect(() => { | |||
| axios.get(`${apiPath}${GET_USER_PATH}`) | |||
| .then((response) => { | |||
| if (response.status === 200) { | |||
| setRecord(response.data); | |||
| setSortedRecord(response.data); | |||
| } | |||
| }) | |||
| .catch(error => { | |||
| console.log(error); | |||
| return false; | |||
| }); | |||
| }, []) | |||
| const filterSearchName = (array) => { | |||
| return array.filter((item) => item.name.toLowerCase().includes(searchCriteria.eventName)); | |||
| }; | |||
| const filterSearchType = (array) => { | |||
| return array.filter((item) => item.category.includes(searchCriteria.type)); | |||
| }; | |||
| function sortData(record) { | |||
| let sortedRecord = record; | |||
| sortedRecord = filterSearchName(sortedRecord); | |||
| sortedRecord = filterSearchType(sortedRecord); | |||
| return sortedRecord; | |||
| } | |||
| function applySearch(input) { | |||
| setSearchCriteria(input); | |||
| } | |||
| useEffect(() => { | |||
| //console.log(searchCriteria); | |||
| if (Object.keys(searchCriteria).length !== 0) { | |||
| const tempSortedRecord = sortData(record); | |||
| console.log(tempSortedRecord); | |||
| setSortedRecord(tempSortedRecord); | |||
| } else { | |||
| setSortedRecord(record); | |||
| } | |||
| }, [searchCriteria]); | |||
| return ( | |||
| <Grid container rowSpacing={4.5} columnSpacing={2.75}> | |||
| {/*row 1*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <SearchForm applySearch={applySearch}/> | |||
| </Grid> | |||
| {/*row 2*/} | |||
| <Grid item xs={12} md={12} lg={12}> | |||
| <MainCard elevation={0} | |||
| border={false} | |||
| content={false} | |||
| > | |||
| <EventTable | |||
| recordList={sortedRecord} | |||
| /> | |||
| </MainCard> | |||
| </Grid> | |||
| </Grid> | |||
| ); | |||
| }; | |||
| export default UserSettingPage; | |||
| @@ -6,7 +6,6 @@ import MainLayout from 'layout/MainLayout'; | |||
| // render - dashboard | |||
| const DashboardDefault = Loadable(lazy(() => import('pages/dashboard'))); | |||
| const ARSDashboard = Loadable(lazy(() => import('pages/arsdashboard'))); | |||
| // render - sample page | |||
| const SamplePage = Loadable(lazy(() => import('pages/extra-pages/SamplePage'))); | |||
| @@ -27,10 +26,6 @@ const MainRoutes = { | |||
| path: '/', | |||
| element: <DashboardDefault /> | |||
| }, | |||
| { | |||
| path: '/arsDashboard', | |||
| element: <ARSDashboard /> | |||
| }, | |||
| { | |||
| path: 'color', | |||
| element: <Color /> | |||
| @@ -0,0 +1,48 @@ | |||
| import { lazy } from 'react'; | |||
| // project import | |||
| import Loadable from 'components/Loadable'; | |||
| import MainLayout from "../layout/MainLayout"; | |||
| // render - login | |||
| const SettingPage = Loadable(lazy(() => import('pages/pnspsSettingPage'))); | |||
| const PasswordPolicyPage = Loadable(lazy(()=> import('pages/pnspsPasswordPolicyPage'))) | |||
| const UserSettingPage = Loadable(lazy(()=>import ('pages/pnspsUserSettingPage/'))); | |||
| const UserGroupSearchPage = Loadable(lazy(() => import('pages/pnspsUserGroupSearchPage'))); | |||
| const UserSearchPage = Loadable(lazy(()=>import ('pages/pnspsUserSearchPage'))); | |||
| const UserMaintainPage = Loadable(lazy(() => import('pages/pnspsUserDetailPage'))); | |||
| // ==============================|| AUTH ROUTING ||============================== // | |||
| const SettingRoutes = { | |||
| path: '/', | |||
| element: <MainLayout />, | |||
| children: [ | |||
| { | |||
| path: 'usergroupSearchview', | |||
| element: <UserGroupSearchPage /> | |||
| }, | |||
| { | |||
| path: '/user/:id', | |||
| element: <UserMaintainPage /> | |||
| }, | |||
| { | |||
| path: 'userSearchview', | |||
| element: <UserSearchPage /> | |||
| }, | |||
| { | |||
| path: 'usersetting', | |||
| element: <UserSettingPage /> | |||
| }, | |||
| { | |||
| path: 'setting', | |||
| element: <SettingPage /> | |||
| }, | |||
| { | |||
| path: 'passwordpolicy', | |||
| element: <PasswordPolicyPage /> | |||
| } | |||
| ] | |||
| }; | |||
| export default SettingRoutes; | |||
| @@ -9,6 +9,7 @@ import {handleLogoutFunction, | |||
| setupAxiosInterceptors, | |||
| isTokenValid} from "../auth"; | |||
| import {useNavigate} from "react-router-dom"; | |||
| import SettingRoutes from './SettingRoutes'; | |||
| // ==============================|| ROUTING RENDER ||============================== // | |||
| export default function ThemeRoutes() { | |||
| @@ -41,7 +42,8 @@ export default function ThemeRoutes() { | |||
| ] | |||
| }, | |||
| LoginRoutes, | |||
| MainRoutes | |||
| MainRoutes, | |||
| SettingRoutes | |||
| ]); | |||
| //return useRoutes([MainRoutes, LoginRoutes]); | |||
| } | |||
| @@ -0,0 +1,3 @@ | |||
| export const GET_GROUP_COMBO_PATH = "/group/combo" | |||
| export const GET_USER_PATH = "/user" | |||
| export const GET_AUTH_LIST = "/user/auth/combo" | |||