2025-12-24 11:51:40 +00:00
|
|
|
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';
|
2025-12-24 11:51:40 +00:00
|
|
|
|
|
|
|
|
// 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);
|
2025-12-24 11:51:40 +00:00
|
|
|
} 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>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|