Files
Account/src/features/profile/components/security/PasswordSecurity.tsx
2025-08-09 16:22:15 -07:00

159 lines
4.9 KiB
TypeScript

import { useState, useEffect } from 'react';
import {
Box,
Typography,
Button,
useTheme,
useMediaQuery,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { CardContainer } from '@/components/CardContainer';
import { PageWrapper } from '../PageWrapper';
import Logo from '@/components/Logo';
import { PasswordDialog } from './PasswordDialog';
import { Toast } from '@/components/Toast';
export function PasswordSecurity() {
const theme = useTheme();
const fullScreen = useMediaQuery(theme.breakpoints.down('sm'));
const { t } = useTranslation('security');
const [open, setOpen] = useState(false);
const [password, setPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [currentPassword, setCurrentPassword] = useState('');
const [showValidation, setShowValidation] = useState(false);
const [showPasswordAlert, setShowPasswordAlert] = useState(false);
const [changePassword, setChangePassword] = useState(false);
const [loading, setLoading] = useState(false);
const hasNumber = /\d/.test(password);
const hasMinLength = password.length >= 8;
const hasUpperAndLower = /[A-Z]/.test(password) && /[a-z]/.test(password);
const hasSpecialChar = /[!@#$%^&*]/.test(password);
const validPassword =
hasNumber && hasMinLength && hasUpperAndLower && hasSpecialChar;
const matchPassword = password === confirmPassword;
useEffect(() => {
if (password) {
if (!validPassword) {
setShowValidation(true);
} else {
const timer = setTimeout(() => setShowValidation(false), 1000);
return () => clearTimeout(timer);
}
} else {
setShowValidation(false);
}
}, [password, validPassword]);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const handleShowAlert = () => {
setLoading(true);
setTimeout(() => {
setLoading(false);
setShowPasswordAlert(true);
setChangePassword(true);
handleClose();
setPassword('');
setConfirmPassword('');
setCurrentPassword('');
}, 1500);
};
return (
<PageWrapper>
<Box sx={{ display: 'flex', alignItems: 'center', py: 2, height: 84 }}>
<Logo />
</Box>
<Box sx={{ width: '100%', height: 1, bgcolor: 'divider' }} />
<CardContainer
title={t('securityForm.password')}
subtitle={t('securityForm.determinePassword')}
action={
<Button
variant="outlined"
onClick={handleOpen}
sx={{
mt: { xs: 2, sm: 0 },
backgroundColor: 'primary.main',
color: 'background.paper',
width: { xs: '100%', sm: '142px' },
textTransform: 'none',
}}
>
{changePassword
? t('securityForm.changePassword')
: t('securityForm.addPassword')}
</Button>
}
>
<Box
sx={{
px: { xs: 2, sm: 3, md: 4 },
py: 2,
display: 'flex',
flexDirection: 'column',
gap: 2,
bgcolor: 'background.paper',
flex: 1,
}}
>
{changePassword ? (
<Box sx={{ flexDirection: 'column', px: 2, py: 2 }}>
<Typography variant="h6">
{t('securityForm.activePassword')}
</Typography>
<Typography variant="caption" color="text.secondary">
{t('securityForm.lastChange')}
</Typography>
</Box>
) : (
<Typography
variant="body1"
color="text.secondary"
sx={{ textAlign: 'center', py: { xs: 4, sm: '43.5px' } }}
>
{t('securityForm.notDeterminedPassword')}
</Typography>
)}
{/* New PasswordDialog component usage */}
<PasswordDialog
open={open}
fullScreen={fullScreen}
handleClose={handleClose}
password={password}
setPassword={setPassword}
confirmPassword={confirmPassword}
setConfirmPassword={setConfirmPassword}
currentPassword={currentPassword}
setCurrentPassword={setCurrentPassword}
showValidation={showValidation}
hasNumber={hasNumber}
hasMinLength={hasMinLength}
hasUpperAndLower={hasUpperAndLower}
hasSpecialChar={hasSpecialChar}
matchPassword={matchPassword}
loading={loading}
handleShowAlert={handleShowAlert}
changePassword={changePassword}
t={t}
/>
<Toast
color="success"
open={showPasswordAlert}
onClose={() => setShowPasswordAlert(false)}
>
{t('securityForm.alertSuccess')}
</Toast>
</Box>
</CardContainer>
</PageWrapper>
);
}