glam/apps/archief-assistent/src/components/ChangePasswordDialog.tsx
2025-12-21 00:01:54 +01:00

200 lines
6 KiB
TypeScript

import { useState } from 'react'
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
TextField,
Button,
Alert,
Box,
IconButton,
InputAdornment,
CircularProgress,
} from '@mui/material'
import { Visibility, VisibilityOff } from '@mui/icons-material'
import { useAuth } from '../context/AuthContext'
interface ChangePasswordDialogProps {
open: boolean
onClose: () => void
}
export default function ChangePasswordDialog({ open, onClose }: ChangePasswordDialogProps) {
const { changePassword } = useAuth()
const [currentPassword, setCurrentPassword] = useState('')
const [newPassword, setNewPassword] = useState('')
const [confirmPassword, setConfirmPassword] = useState('')
const [showCurrentPassword, setShowCurrentPassword] = useState(false)
const [showNewPassword, setShowNewPassword] = useState(false)
const [showConfirmPassword, setShowConfirmPassword] = useState(false)
const [isLoading, setIsLoading] = useState(false)
const [error, setError] = useState<string | null>(null)
const [success, setSuccess] = useState(false)
const handleClose = () => {
// Reset form state
setCurrentPassword('')
setNewPassword('')
setConfirmPassword('')
setShowCurrentPassword(false)
setShowNewPassword(false)
setShowConfirmPassword(false)
setError(null)
setSuccess(false)
onClose()
}
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
setError(null)
// Validate passwords
if (!currentPassword || !newPassword || !confirmPassword) {
setError('Vul alle velden in')
return
}
if (newPassword.length < 8) {
setError('Nieuw wachtwoord moet minimaal 8 tekens bevatten')
return
}
if (newPassword !== confirmPassword) {
setError('Nieuwe wachtwoorden komen niet overeen')
return
}
if (currentPassword === newPassword) {
setError('Nieuw wachtwoord moet anders zijn dan het huidige wachtwoord')
return
}
setIsLoading(true)
try {
const result = await changePassword(currentPassword, newPassword)
if (result.success) {
setSuccess(true)
// Close dialog after showing success message
setTimeout(() => {
handleClose()
}, 1500)
} else {
setError(result.error || 'Er is een fout opgetreden')
}
} catch {
setError('Er is een fout opgetreden bij het wijzigen van het wachtwoord')
} finally {
setIsLoading(false)
}
}
return (
<Dialog open={open} onClose={handleClose} maxWidth="sm" fullWidth>
<DialogTitle sx={{ pb: 1 }}>Wachtwoord wijzigen</DialogTitle>
<form onSubmit={handleSubmit}>
<DialogContent>
{error && (
<Alert severity="error" sx={{ mb: 2 }}>
{error}
</Alert>
)}
{success && (
<Alert severity="success" sx={{ mb: 2 }}>
Wachtwoord succesvol gewijzigd
</Alert>
)}
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
<TextField
label="Huidig wachtwoord"
type={showCurrentPassword ? 'text' : 'password'}
value={currentPassword}
onChange={(e) => setCurrentPassword(e.target.value)}
disabled={isLoading || success}
fullWidth
autoFocus
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowCurrentPassword(!showCurrentPassword)}
edge="end"
tabIndex={-1}
>
{showCurrentPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
label="Nieuw wachtwoord"
type={showNewPassword ? 'text' : 'password'}
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
disabled={isLoading || success}
fullWidth
helperText="Minimaal 8 tekens"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowNewPassword(!showNewPassword)}
edge="end"
tabIndex={-1}
>
{showNewPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
<TextField
label="Bevestig nieuw wachtwoord"
type={showConfirmPassword ? 'text' : 'password'}
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
disabled={isLoading || success}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton
onClick={() => setShowConfirmPassword(!showConfirmPassword)}
edge="end"
tabIndex={-1}
>
{showConfirmPassword ? <VisibilityOff /> : <Visibility />}
</IconButton>
</InputAdornment>
),
}}
/>
</Box>
</DialogContent>
<DialogActions sx={{ px: 3, pb: 2 }}>
<Button onClick={handleClose} disabled={isLoading}>
Annuleren
</Button>
<Button
type="submit"
variant="contained"
disabled={isLoading || success}
startIcon={isLoading ? <CircularProgress size={20} color="inherit" /> : null}
>
{isLoading ? 'Bezig...' : 'Wijzigen'}
</Button>
</DialogActions>
</form>
</Dialog>
)
}