veza/apps/web/src/features/chat/components/CreateRoomDialog.tsx

108 lines
3.2 KiB
TypeScript
Raw Normal View History

import { useState } from 'react';
import { Dialog } from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Button } from '@/components/ui/button';
import { Select } from '@/components/ui/select';
import { apiClient } from '@/services/api/client';
import { useToast } from '@/hooks/useToast';
import { useChatStore } from '../store/chatStore';
2026-01-07 18:39:21 +00:00
import { parseApiError } from '@/utils/apiErrorHandler';
// FE-PAGE-005: Complete Chat page implementation - Room Management
interface CreateRoomDialogProps {
open: boolean;
onClose: () => void;
}
export function CreateRoomDialog({ open, onClose }: CreateRoomDialogProps) {
const [name, setName] = useState('');
const [type, setType] = useState<'public' | 'private'>('public');
const [isCreating, setIsCreating] = useState(false);
const toast = useToast();
const { addConversation, setCurrentConversation } = useChatStore();
const handleCreate = async () => {
if (!name.trim()) {
toast.error('Room name is required');
return;
}
try {
setIsCreating(true);
const response = await apiClient.post('/conversations', {
name: name.trim(),
type,
});
const newRoom = {
id: response.data.id || response.data.conversation?.id,
name: response.data.name || response.data.conversation?.name,
type: response.data.type || response.data.conversation?.type || type,
participants: response.data.participants || [],
unread_count: 0,
};
addConversation(newRoom);
setCurrentConversation(newRoom.id);
toast.success('Room created successfully');
setName('');
setType('public');
onClose();
2026-01-07 18:39:21 +00:00
onClose();
} catch (error: unknown) {
const apiError = parseApiError(error);
toast.error(apiError.message);
} finally {
setIsCreating(false);
}
};
return (
<Dialog
open={open}
onClose={onClose}
title="Create New Room"
variant="default"
size="md"
>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="room-name">Room Name</Label>
<Input
id="room-name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Enter room name"
maxLength={100}
/>
</div>
<div className="space-y-2">
<Label htmlFor="room-type">Room Type</Label>
<Select
options={[
{ value: 'public', label: 'Public' },
{ value: 'private', label: 'Private' },
]}
value={type}
onChange={(value) =>
setType((Array.isArray(value) ? value[0] : value) as 'public' | 'private')
}
name="room-type"
/>
</div>
<div className="flex justify-end gap-2 pt-4">
<Button variant="outline" onClick={onClose} disabled={isCreating}>
Cancel
</Button>
<Button onClick={handleCreate} disabled={isCreating || !name.trim()}>
{isCreating ? 'Creating...' : 'Create Room'}
</Button>
</div>
</div>
</Dialog>
);
}