autocomplete und login fehlermeldung fix

This commit is contained in:
2026-04-20 11:18:38 +02:00
parent adb797e709
commit 0b65dc5550
3 changed files with 108 additions and 17 deletions

View File

@@ -25,7 +25,7 @@ export default function LoginPage() {
await login(email, password);
navigate('/');
} catch (err) {
setError(err.response?.data?.message ?? 'Login fehlgeschlagen');
setError(err.response?.data?.error ?? 'Login fehlgeschlagen');
} finally {
setLoading(false);
}

View File

@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import {
Box, Typography, Alert, IconButton, Tooltip,
Dialog, DialogTitle, DialogContent, DialogActions,
Button, Stack, TextField, CircularProgress
Button, Stack, TextField, CircularProgress, Autocomplete
} from '@mui/material';
import { DataGrid } from '@mui/x-data-grid';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
@@ -17,6 +17,9 @@ export default function CompanyPage() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [userOptions, setUserOptions] = useState([]);
const [usersLoading, setUsersLoading] = useState(false);
const [open, setOpen] = useState(false);
const [creating, setCreating] = useState(false);
const [creatingError, setCreatingError] = useState('');
@@ -47,6 +50,23 @@ export default function CompanyPage() {
setCreateForm((prev) => ({ ...prev, [name]: value }));
};
const loadUsers = async () => {
setUsersLoading(true);
try {
const { data } = await axiosInstance.get('/users');
setUserOptions(data.map(u => u.email));
} catch {
setUserOptions([]);
} finally {
setUsersLoading(false);
}
}
const handleOpen = () => {
setOpen(true);
loadUsers();
}
const handleCreate = async () => {
setCreating(true);
setCreatingError('');
@@ -142,7 +162,7 @@ export default function CompanyPage() {
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={() => setOpen(true)}
onClick={() => handleOpen()}
>
Unternehmen erstellen
</Button>
@@ -180,13 +200,38 @@ export default function CompanyPage() {
fullWidth
/>
<TextField
label="Verwalter Email"
name="email"
type="email"
<Autocomplete
options={userOptions}
loading={usersLoading}
value={createForm.email}
onChange={handleFormChange}
fullWidth
onChange={(_, newValue) => {
setCreateForm(prev => ({ ...prev, email: newValue ?? '' }));
}}
onInputChange={(_, newInputValue) => {
setCreateForm(prev => ({ ...prev, email: newInputValue }));
}}
freeSolo
filterOptions={(options, { inputValue }) =>
options.filter(o => o.toLowerCase().includes(inputValue.toLowerCase()))
}
renderInput={(params) => (
<TextField
{...params}
label="Verwalter Email"
name="email"
type="email"
fullWidth
InputProps={{
...params.InputProps,
endAdornment: (
<>
{usersLoading ? <CircularProgress size={16} /> : null}
{params.InputProps.endAdornment}
</>
),
}}
/>
)}
/>
</Stack>
</DialogContent>

View File

@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import {
Box, Typography, Alert, IconButton, Tooltip,
Dialog, DialogTitle, DialogContent, DialogActions,
Button, Stack, TextField, CircularProgress
Button, Stack, TextField, CircularProgress, Autocomplete
} from '@mui/material';
import { DataGrid } from '@mui/x-data-grid';
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
@@ -17,6 +17,9 @@ export default function OrganizationPage() {
const [loading, setLoading] = useState(true);
const [error, setError] = useState('');
const [userOptions, setUserOptions] = useState([]);
const [usersLoading, setUsersLoading] = useState(false);
const [open, setOpen] = useState(false);
const [creating, setCreating] = useState(false);
const [creatingError, setCreatingError] = useState('');
@@ -38,10 +41,28 @@ export default function OrganizationPage() {
}
};
const handleOpen = () => {
setOpen(true);
loadUsers();
}
useEffect(() => {
loadOrganizations();
}, []);
const loadUsers = async () => {
setUsersLoading(true);
try {
const { data } = await axiosInstance.get('/users');
setUserOptions(data.map(u => u.email));
} catch {
setUserOptions([]);
} finally {
setUsersLoading(false);
}
}
const handleFormChange = (e) => {
const { name, value } = e.target;
setCreateForm((prev) => ({ ...prev, [name]: value }));
@@ -142,7 +163,7 @@ export default function OrganizationPage() {
<Button
variant="contained"
startIcon={<AddIcon />}
onClick={() => setOpen(true)}
onClick={() => handleOpen()}
>
Organisation erstellen
</Button>
@@ -180,13 +201,38 @@ export default function OrganizationPage() {
fullWidth
/>
<TextField
label="Verwalter Email"
name="email"
type="email"
<Autocomplete
options={userOptions}
loading={usersLoading}
value={createForm.email}
onChange={handleFormChange}
fullWidth
onChange={(_, newValue) => {
setCreateForm(prev => ({ ...prev, email: newValue ?? '' }));
}}
onInputChange={(_, newInputValue) => {
setCreateForm(prev => ({ ...prev, email: newInputValue }));
}}
freeSolo
filterOptions={(options, { inputValue }) =>
options.filter(o => o.toLowerCase().includes(inputValue.toLowerCase()))
}
renderInput={(params) => (
<TextField
{...params}
label="Verwalter Email"
name="email"
type="email"
fullWidth
InputProps={{
...params.InputProps,
endAdornment: (
<>
{usersLoading ? <CircularProgress size={16} /> : null}
{params.InputProps.endAdornment}
</>
),
}}
/>
)}
/>
</Stack>
</DialogContent>