106 lines
3.4 KiB
TypeScript
106 lines
3.4 KiB
TypeScript
import React, { useState, useEffect } from 'react';
|
|
import Dialog from '@mui/material/Dialog';
|
|
import DialogTitle from '@mui/material/DialogTitle';
|
|
import DialogContent from '@mui/material/DialogContent';
|
|
import TextField from '@mui/material/TextField';
|
|
import List from '@mui/material/List';
|
|
import ListItem from '@mui/material/ListItem';
|
|
import ListItemButton from '@mui/material/ListItemButton';
|
|
import ListItemAvatar from '@mui/material/ListItemAvatar';
|
|
import ListItemText from '@mui/material/ListItemText';
|
|
import Avatar from '@mui/material/Avatar';
|
|
import CircularProgress from '@mui/material/CircularProgress';
|
|
import Box from '@mui/material/Box';
|
|
import Typography from '@mui/material/Typography';
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { nextcloudApi } from '../../services/nextcloud';
|
|
|
|
interface NewChatDialogProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
onRoomCreated: (token: string) => void;
|
|
}
|
|
|
|
const NewChatDialog: React.FC<NewChatDialogProps> = ({ open, onClose, onRoomCreated }) => {
|
|
const [search, setSearch] = useState('');
|
|
const [creating, setCreating] = useState(false);
|
|
|
|
// Reset state when dialog opens
|
|
useEffect(() => {
|
|
if (open) {
|
|
setSearch('');
|
|
setCreating(false);
|
|
}
|
|
}, [open]);
|
|
|
|
const { data: users, isLoading } = useQuery({
|
|
queryKey: ['nextcloud', 'users', search],
|
|
queryFn: () => nextcloudApi.searchUsers(search),
|
|
enabled: open && search.length >= 2,
|
|
staleTime: 30_000,
|
|
});
|
|
|
|
const handleSelect = async (userId: string, displayName: string) => {
|
|
setCreating(true);
|
|
try {
|
|
const { token } = await nextcloudApi.createRoom(1, userId, displayName);
|
|
onRoomCreated(token);
|
|
onClose();
|
|
} catch {
|
|
// ignore
|
|
} finally {
|
|
setCreating(false);
|
|
}
|
|
};
|
|
|
|
const handleClose = () => {
|
|
setSearch('');
|
|
onClose();
|
|
};
|
|
|
|
return (
|
|
<Dialog open={open} onClose={handleClose} maxWidth="xs" fullWidth>
|
|
<DialogTitle>Neues Gespr\u00E4ch</DialogTitle>
|
|
<DialogContent sx={{ pb: 1 }}>
|
|
<TextField
|
|
autoFocus
|
|
fullWidth
|
|
size="small"
|
|
placeholder="Benutzer suchen..."
|
|
value={search}
|
|
onChange={(e) => setSearch(e.target.value)}
|
|
sx={{ mb: 1 }}
|
|
/>
|
|
{(isLoading || creating) && (
|
|
<Box sx={{ display: 'flex', justifyContent: 'center', py: 1 }}>
|
|
<CircularProgress size={24} />
|
|
</Box>
|
|
)}
|
|
{!isLoading && !creating && search.length >= 2 && (!users || users.length === 0) && (
|
|
<Typography variant="body2" color="text.secondary" sx={{ py: 1, textAlign: 'center' }}>
|
|
Keine Benutzer gefunden
|
|
</Typography>
|
|
)}
|
|
{!creating && users && users.length > 0 && (
|
|
<List disablePadding>
|
|
{users.map((user) => (
|
|
<ListItem key={user.id} disablePadding>
|
|
<ListItemButton onClick={() => handleSelect(user.id, user.label)}>
|
|
<ListItemAvatar sx={{ minWidth: 40 }}>
|
|
<Avatar sx={{ width: 32, height: 32, fontSize: '0.75rem' }}>
|
|
{user.label.substring(0, 2).toUpperCase()}
|
|
</Avatar>
|
|
</ListItemAvatar>
|
|
<ListItemText primary={user.label} secondary={user.id} />
|
|
</ListItemButton>
|
|
</ListItem>
|
|
))}
|
|
</List>
|
|
)}
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
};
|
|
|
|
export default NewChatDialog;
|