Mexar / frontend /src /components /ChangePasswordModal.jsx
Devrajsinh bharatsinh gohil
Initial commit of MEXAR Ultimate - Phase 2 cleanup complete
b0b150b
import React, { useState } from 'react';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
Button,
TextField,
Alert,
CircularProgress,
InputAdornment,
IconButton
} from '@mui/material';
import { Visibility, VisibilityOff } from '@mui/icons-material';
import { changePassword } from '../api/client';
const ChangePasswordModal = ({ open, onClose }) => {
const [oldPassword, setOldPassword] = useState('');
const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [success, setSuccess] = useState(false);
const [showOldPassword, setShowOldPassword] = useState(false);
const [showNewPassword, setShowNewPassword] = useState(false);
const [showConfirmPassword, setShowConfirmPassword] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setError(null);
setSuccess(false);
if (newPassword !== confirmPassword) {
setError("New passwords do not match");
return;
}
if (newPassword.length < 6) {
setError("Password must be at least 6 characters");
return;
}
setLoading(true);
try {
await changePassword(oldPassword, newPassword);
setSuccess(true);
setOldPassword('');
setNewPassword('');
setConfirmPassword('');
setTimeout(() => {
onClose();
setSuccess(false);
}, 1500);
} catch (err) {
console.error(err);
setError(err.response?.data?.detail || "Failed to change password");
} finally {
setLoading(false);
}
};
const handleClose = () => {
setError(null);
setSuccess(false);
onClose();
};
return (
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<DialogTitle>Change Password</DialogTitle>
<form onSubmit={handleSubmit}>
<DialogContent>
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
{success && <Alert severity="success" sx={{ mb: 2 }}>Password changed successfully!</Alert>}
<TextField
margin="dense"
label="Current Password"
type={showOldPassword ? 'text' : 'password'}
fullWidth
value={oldPassword}
onChange={(e) => setOldPassword(e.target.value)}
required
disabled={loading || success}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowOldPassword(!showOldPassword)}
edge="end"
>
{showOldPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
)
}}
/>
<TextField
margin="dense"
label="New Password"
type={showNewPassword ? 'text' : 'password'}
fullWidth
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
required
disabled={loading || success}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowNewPassword(!showNewPassword)}
edge="end"
>
{showNewPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
)
}}
/>
<TextField
margin="dense"
label="Confirm New Password"
type={showConfirmPassword ? 'text' : 'password'}
fullWidth
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
required
disabled={loading || success}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
edge="end"
>
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
)
}}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} disabled={loading}>Cancel</Button>
<Button type="submit" variant="contained" disabled={loading || success} startIcon={loading ? <CircularProgress size={20} /> : null}>
{loading ? 'Updating...' : 'Update Password'}
</Button>
</DialogActions>
</form>
</Dialog>
);
};
export default ChangePasswordModal;