autocomplete und login fehlermeldung fix
This commit is contained in:
@@ -25,7 +25,7 @@ export default function LoginPage() {
|
|||||||
await login(email, password);
|
await login(email, password);
|
||||||
navigate('/');
|
navigate('/');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err.response?.data?.message ?? 'Login fehlgeschlagen');
|
setError(err.response?.data?.error ?? 'Login fehlgeschlagen');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import {
|
import {
|
||||||
Box, Typography, Alert, IconButton, Tooltip,
|
Box, Typography, Alert, IconButton, Tooltip,
|
||||||
Dialog, DialogTitle, DialogContent, DialogActions,
|
Dialog, DialogTitle, DialogContent, DialogActions,
|
||||||
Button, Stack, TextField, CircularProgress
|
Button, Stack, TextField, CircularProgress, Autocomplete
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { DataGrid } from '@mui/x-data-grid';
|
import { DataGrid } from '@mui/x-data-grid';
|
||||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||||
@@ -17,6 +17,9 @@ export default function CompanyPage() {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const [userOptions, setUserOptions] = useState([]);
|
||||||
|
const [usersLoading, setUsersLoading] = useState(false);
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [creating, setCreating] = useState(false);
|
const [creating, setCreating] = useState(false);
|
||||||
const [creatingError, setCreatingError] = useState('');
|
const [creatingError, setCreatingError] = useState('');
|
||||||
@@ -47,6 +50,23 @@ export default function CompanyPage() {
|
|||||||
setCreateForm((prev) => ({ ...prev, [name]: value }));
|
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 () => {
|
const handleCreate = async () => {
|
||||||
setCreating(true);
|
setCreating(true);
|
||||||
setCreatingError('');
|
setCreatingError('');
|
||||||
@@ -142,7 +162,7 @@ export default function CompanyPage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
startIcon={<AddIcon />}
|
startIcon={<AddIcon />}
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => handleOpen()}
|
||||||
>
|
>
|
||||||
Unternehmen erstellen
|
Unternehmen erstellen
|
||||||
</Button>
|
</Button>
|
||||||
@@ -180,13 +200,38 @@ export default function CompanyPage() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<Autocomplete
|
||||||
label="Verwalter Email"
|
options={userOptions}
|
||||||
name="email"
|
loading={usersLoading}
|
||||||
type="email"
|
|
||||||
value={createForm.email}
|
value={createForm.email}
|
||||||
onChange={handleFormChange}
|
onChange={(_, newValue) => {
|
||||||
fullWidth
|
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>
|
</Stack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
|
|||||||
import {
|
import {
|
||||||
Box, Typography, Alert, IconButton, Tooltip,
|
Box, Typography, Alert, IconButton, Tooltip,
|
||||||
Dialog, DialogTitle, DialogContent, DialogActions,
|
Dialog, DialogTitle, DialogContent, DialogActions,
|
||||||
Button, Stack, TextField, CircularProgress
|
Button, Stack, TextField, CircularProgress, Autocomplete
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { DataGrid } from '@mui/x-data-grid';
|
import { DataGrid } from '@mui/x-data-grid';
|
||||||
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
import DeleteOutlineIcon from '@mui/icons-material/DeleteOutline';
|
||||||
@@ -17,6 +17,9 @@ export default function OrganizationPage() {
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
|
|
||||||
|
const [userOptions, setUserOptions] = useState([]);
|
||||||
|
const [usersLoading, setUsersLoading] = useState(false);
|
||||||
|
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [creating, setCreating] = useState(false);
|
const [creating, setCreating] = useState(false);
|
||||||
const [creatingError, setCreatingError] = useState('');
|
const [creatingError, setCreatingError] = useState('');
|
||||||
@@ -38,10 +41,28 @@ export default function OrganizationPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOpen = () => {
|
||||||
|
setOpen(true);
|
||||||
|
loadUsers();
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadOrganizations();
|
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 handleFormChange = (e) => {
|
||||||
const { name, value } = e.target;
|
const { name, value } = e.target;
|
||||||
setCreateForm((prev) => ({ ...prev, [name]: value }));
|
setCreateForm((prev) => ({ ...prev, [name]: value }));
|
||||||
@@ -142,7 +163,7 @@ export default function OrganizationPage() {
|
|||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
startIcon={<AddIcon />}
|
startIcon={<AddIcon />}
|
||||||
onClick={() => setOpen(true)}
|
onClick={() => handleOpen()}
|
||||||
>
|
>
|
||||||
Organisation erstellen
|
Organisation erstellen
|
||||||
</Button>
|
</Button>
|
||||||
@@ -180,13 +201,38 @@ export default function OrganizationPage() {
|
|||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
<Autocomplete
|
||||||
label="Verwalter Email"
|
options={userOptions}
|
||||||
name="email"
|
loading={usersLoading}
|
||||||
type="email"
|
|
||||||
value={createForm.email}
|
value={createForm.email}
|
||||||
onChange={handleFormChange}
|
onChange={(_, newValue) => {
|
||||||
fullWidth
|
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>
|
</Stack>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
Reference in New Issue
Block a user