55 lines
2.2 KiB
TypeScript
55 lines
2.2 KiB
TypeScript
import { Alert, Button, Dialog, DialogActions, DialogContent, DialogTitle, Stack } from '@mui/material'
|
|
import { useState, type FormEvent } from 'react'
|
|
import PersonFields from './PersonFields.tsx'
|
|
import type { Person, User } from './api.ts'
|
|
import { personComplete, personProblems, trimmed } from './person.ts'
|
|
|
|
/**
|
|
* A dialog that edits the first name, last name and e-mail address of a VPN user, or the optional e-mail address of a
|
|
* Manager-only account, where an empty one removes it; onSave sends them.
|
|
*/
|
|
export default function PersonDialog(props: { user: User; onSave: (person: Partial<Person>) => Promise<void>; onCancel: () => void }) {
|
|
const [person, setPerson] = useState<Person>({
|
|
first_name: props.user.first_name ?? '',
|
|
last_name: props.user.last_name ?? '',
|
|
email: props.user.email ?? '',
|
|
})
|
|
const [saving, setSaving] = useState(false)
|
|
const [error, setError] = useState<string | null>(null)
|
|
const managerOnly = props.user.manager_only
|
|
const blocked = managerOnly ? personProblems(person).email !== '' : !personComplete(person)
|
|
|
|
async function submit(event: FormEvent) {
|
|
event.preventDefault()
|
|
if (blocked) {
|
|
return
|
|
}
|
|
setSaving(true)
|
|
setError(null)
|
|
try {
|
|
await props.onSave(managerOnly ? { email: person.email.trim() } : trimmed(person))
|
|
} catch (caught) {
|
|
setError((caught as Error).message)
|
|
setSaving(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog open onClose={(_event, reason) => reason !== 'backdropClick' && props.onCancel()} maxWidth="xs" fullWidth slotProps={{ paper: { component: 'form', onSubmit: submit } }}>
|
|
<DialogTitle>Details of {props.user.name}</DialogTitle>
|
|
<DialogContent>
|
|
<Stack sx={{ gap: 2, pt: 1 }}>
|
|
{error && <Alert severity="error" sx={{ whiteSpace: 'pre-line' }}>{error}</Alert>}
|
|
<PersonFields person={person} onChange={setPerson} autoFocus emailOnly={managerOnly} />
|
|
</Stack>
|
|
</DialogContent>
|
|
<DialogActions>
|
|
<Button onClick={props.onCancel}>Cancel</Button>
|
|
<Button type="submit" variant="contained" disabled={saving || blocked}>
|
|
Save
|
|
</Button>
|
|
</DialogActions>
|
|
</Dialog>
|
|
)
|
|
}
|