analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
794 lines (789 loc) • 28.1 kB
JavaScript
import {
CHAT_MESSAGE_TYPES
} from "./chunk-UGZYPY3T.mjs";
import {
EmptyState_default
} from "./chunk-6WVHF7N3.mjs";
import {
SkeletonRounded,
SkeletonText
} from "./chunk-NKVUUWCA.mjs";
import {
Input_default
} from "./chunk-EXVVHZOO.mjs";
import {
Modal_default
} from "./chunk-TNLGS7SB.mjs";
import {
Button_default
} from "./chunk-LAYB7IKW.mjs";
import {
Text_default
} from "./chunk-IMCIR6TJ.mjs";
import {
cn
} from "./chunk-53ICLDGS.mjs";
// src/components/Chat/Chat.tsx
import { useState as useState3, useEffect as useEffect2, useCallback as useCallback3, useRef as useRef2 } from "react";
import {
PaperPlaneTiltIcon,
XIcon,
PlusIcon,
UsersIcon
} from "@phosphor-icons/react";
// src/hooks/useChat.ts
import { useState, useEffect, useCallback, useRef } from "react";
var WS_STATES = {
CONNECTING: 0,
OPEN: 1,
CLOSING: 2,
CLOSED: 3
};
function useChat({
wsUrl,
token,
roomId,
userId,
onConnect,
onDisconnect,
onError,
autoReconnect = true,
reconnectInterval = 3e3,
maxReconnectAttempts = 5
}) {
const [isConnected, setIsConnected] = useState(false);
const [messages, setMessages] = useState([]);
const [participants, setParticipants] = useState([]);
const [error, setError] = useState(null);
const wsRef = useRef(null);
const reconnectAttemptsRef = useRef(0);
const reconnectTimeoutRef = useRef(
null
);
const isManualDisconnectRef = useRef(false);
const isConnectingRef = useRef(false);
const connectRef = useRef(() => {
});
const sendWsMessage = useCallback((message) => {
if (wsRef.current?.readyState === WS_STATES.OPEN) {
wsRef.current.send(JSON.stringify(message));
}
}, []);
const sendMessage = useCallback(
(content) => {
const trimmedContent = content.trim();
if (!trimmedContent) return;
sendWsMessage({
type: "message",
payload: { content: trimmedContent }
});
},
[sendWsMessage]
);
const leave = useCallback(() => {
isManualDisconnectRef.current = true;
sendWsMessage({ type: "leave" });
wsRef.current?.close(1e3, "User left");
}, [sendWsMessage]);
const handleMessage = useCallback(
(event) => {
try {
const data = JSON.parse(event.data);
switch (data.type) {
case "history":
if (data.payload.messages) {
setMessages(data.payload.messages);
}
break;
case "participants":
if (data.payload.participants) {
setParticipants(data.payload.participants);
}
break;
case "new_message":
if (data.payload.message) {
setMessages((prev) => [...prev, data.payload.message]);
}
break;
case "user_joined":
if (data.payload.user) {
const user = data.payload.user;
setParticipants((prev) => {
const exists = prev.some(
(p) => p.userInstitutionId === user.userInstitutionId
);
if (exists) {
return prev.map(
(p) => p.userInstitutionId === user.userInstitutionId ? { ...p, isOnline: true } : p
);
}
return [
...prev,
{
userInstitutionId: user.userInstitutionId,
name: user.name,
photo: user.photo,
role: user.role,
isOnline: true
}
];
});
}
break;
case "user_left":
if (data.payload.user) {
const user = data.payload.user;
setParticipants(
(prev) => prev.map(
(p) => p.userInstitutionId === user.userInstitutionId ? { ...p, isOnline: false } : p
)
);
}
break;
case "error": {
const errorMessage = data.payload.message_text || "Erro desconhecido";
setError(new Error(errorMessage));
onError?.(new Error(errorMessage));
break;
}
}
} catch (err) {
console.error("Error parsing WebSocket message:", err);
}
},
[onError]
);
const connect = useCallback(() => {
if (isConnectingRef.current) {
return;
}
const url = new URL(wsUrl);
url.searchParams.set("roomId", roomId);
url.searchParams.set("token", token);
if (wsRef.current) {
wsRef.current.close();
}
isConnectingRef.current = true;
const ws = new WebSocket(url.toString());
wsRef.current = ws;
ws.onopen = () => {
isConnectingRef.current = false;
setIsConnected(true);
setError(null);
reconnectAttemptsRef.current = 0;
ws.send(JSON.stringify({ type: "getInitialData" }));
onConnect?.();
};
ws.onmessage = handleMessage;
ws.onerror = () => {
isConnectingRef.current = false;
const error2 = new Error("Erro na conex\xE3o WebSocket");
setError(error2);
onError?.(error2);
};
ws.onclose = (event) => {
isConnectingRef.current = false;
setIsConnected(false);
onDisconnect?.();
if (autoReconnect && !isManualDisconnectRef.current && reconnectAttemptsRef.current < maxReconnectAttempts && event.code !== 4001 && // Unauthorized
event.code !== 4002 && // Missing roomId
event.code !== 4003) {
reconnectAttemptsRef.current += 1;
reconnectTimeoutRef.current = setTimeout(() => {
connect();
}, reconnectInterval);
}
};
}, [
wsUrl,
roomId,
token,
handleMessage,
onConnect,
onDisconnect,
onError,
autoReconnect,
reconnectInterval,
maxReconnectAttempts
]);
connectRef.current = connect;
const reconnect = useCallback(() => {
isManualDisconnectRef.current = false;
reconnectAttemptsRef.current = 0;
connectRef.current();
}, []);
useEffect(() => {
if (!roomId) {
return;
}
if (reconnectTimeoutRef.current) {
clearTimeout(reconnectTimeoutRef.current);
reconnectTimeoutRef.current = null;
}
isManualDisconnectRef.current = false;
isConnectingRef.current = false;
reconnectAttemptsRef.current = 0;
if (wsRef.current) {
wsRef.current.close(1e3, "Room changed");
wsRef.current = null;
}
const timeoutId = setTimeout(() => {
connectRef.current();
}, 100);
return () => {
clearTimeout(timeoutId);
isManualDisconnectRef.current = true;
isConnectingRef.current = false;
if (reconnectTimeoutRef.current) {
clearTimeout(reconnectTimeoutRef.current);
}
wsRef.current?.close(1e3, "Component unmounted");
};
}, [roomId]);
return {
isConnected,
messages,
participants,
sendMessage,
leave,
error,
reconnect,
currentUserId: userId
};
}
function createUseChat(baseWsUrl) {
return (options) => useChat({ ...options, wsUrl: baseWsUrl });
}
// src/hooks/useChatRooms.ts
import { useState as useState2, useCallback as useCallback2 } from "react";
function useChatRooms({
apiClient
}) {
const [rooms, setRooms] = useState2([]);
const [availableUsers, setAvailableUsers] = useState2([]);
const [loading, setLoading] = useState2(false);
const [error, setError] = useState2(null);
const fetchRooms = useCallback2(async () => {
setLoading(true);
setError(null);
try {
const response = await apiClient.get(
"/chat/rooms"
);
setRooms(response.data.data.rooms);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Erro ao carregar salas");
setError(error2);
console.error("Error fetching chat rooms:", err);
} finally {
setLoading(false);
}
}, [apiClient]);
const fetchAvailableUsers = useCallback2(async () => {
setLoading(true);
setError(null);
try {
const response = await apiClient.get(
"/chat/available-users"
);
setAvailableUsers(response.data.data.users);
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Erro ao carregar usu\xE1rios");
setError(error2);
console.error("Error fetching available users:", err);
} finally {
setLoading(false);
}
}, [apiClient]);
const createRoom = useCallback2(
async (participantIds) => {
setLoading(true);
setError(null);
try {
const response = await apiClient.post(
"/chat/rooms",
{
participantIds
}
);
await fetchRooms();
return response.data.data.room;
} catch (err) {
const error2 = err instanceof Error ? err : new Error("Erro ao criar sala");
setError(error2);
console.error("Error creating chat room:", err);
return null;
} finally {
setLoading(false);
}
},
[apiClient, fetchRooms]
);
const clearError = useCallback2(() => {
setError(null);
}, []);
return {
rooms,
availableUsers,
loading,
error,
fetchRooms,
fetchAvailableUsers,
createRoom,
clearError
};
}
function createUseChatRooms(apiClient) {
return () => useChatRooms({ apiClient });
}
// src/components/Chat/Chat.tsx
import { jsx, jsxs } from "react/jsx-runtime";
var RoomItem = ({
room,
onClick,
isActive
}) => /* @__PURE__ */ jsx(
Button_default,
{
variant: "link",
onClick,
className: cn(
"w-full p-3 rounded-lg text-left transition-colors justify-start h-auto",
"hover:bg-background-100",
isActive && "bg-primary-50 border-l-4 border-primary-500"
),
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-3 w-full", children: [
/* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(UsersIcon, { size: 20, className: "text-primary-600" }) }),
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", weight: "semibold", className: "text-text-900 truncate", children: room.name }),
room.lastMessage && /* @__PURE__ */ jsxs(Text_default, { size: "xs", className: "text-text-500 truncate mt-1", children: [
room.lastMessage.senderName,
": ",
room.lastMessage.content
] }),
/* @__PURE__ */ jsxs(Text_default, { size: "xs", className: "text-text-400 mt-1", children: [
room.participantCount,
" participantes"
] })
] })
] })
}
);
var MessageBubble = ({
message,
isOwn
}) => /* @__PURE__ */ jsxs("div", { className: cn("flex gap-2 mb-3", isOwn && "flex-row-reverse"), children: [
!isOwn && /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0", children: message.senderPhoto ? /* @__PURE__ */ jsx(
"img",
{
src: message.senderPhoto,
alt: message.senderName,
className: "w-8 h-8 rounded-full object-cover"
}
) : /* @__PURE__ */ jsx(Text_default, { size: "xs", weight: "bold", className: "text-gray-600", children: message.senderName.charAt(0).toUpperCase() }) }),
/* @__PURE__ */ jsxs("div", { className: cn("max-w-[70%]", isOwn && "items-end"), children: [
!isOwn && /* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500 mb-1", children: message.senderName }),
/* @__PURE__ */ jsx(
"div",
{
className: cn(
"px-4 py-2 rounded-2xl",
isOwn ? "bg-primary-500 text-white rounded-br-md" : "bg-background-100 text-text-900 rounded-bl-md"
),
children: /* @__PURE__ */ jsx(Text_default, { size: "sm", children: message.content })
}
),
/* @__PURE__ */ jsx(
Text_default,
{
size: "xs",
className: cn("text-text-400 mt-1", isOwn && "text-right"),
children: new Date(message.createdAt).toLocaleTimeString("pt-BR", {
hour: "2-digit",
minute: "2-digit"
})
}
)
] })
] });
var ParticipantItem = ({ participant }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-2", children: [
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
/* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center", children: participant.photo ? /* @__PURE__ */ jsx(
"img",
{
src: participant.photo,
alt: participant.name,
className: "w-8 h-8 rounded-full object-cover"
}
) : /* @__PURE__ */ jsx(Text_default, { size: "xs", weight: "bold", className: "text-gray-600", children: participant.name.charAt(0).toUpperCase() }) }),
participant.isOnline && /* @__PURE__ */ jsx("div", { className: "absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white" })
] }),
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-900 truncate", children: participant.name }),
/* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: participant.role })
] })
] });
var UserSelector = ({
users,
selectedIds,
onToggle
}) => /* @__PURE__ */ jsx("div", { className: "space-y-2 max-h-64 overflow-y-auto", children: users.map((user) => /* @__PURE__ */ jsxs(
Button_default,
{
variant: "link",
onClick: () => onToggle(user.userInstitutionId),
className: cn(
"w-full flex items-center gap-3 p-3 rounded-lg transition-colors justify-start h-auto",
selectedIds.has(user.userInstitutionId) ? "bg-primary-50 border border-primary-500" : "bg-background-50 hover:bg-background-100 border border-transparent"
),
children: [
/* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center", children: user.photo ? /* @__PURE__ */ jsx(
"img",
{
src: user.photo,
alt: user.name,
className: "w-10 h-10 rounded-full object-cover"
}
) : /* @__PURE__ */ jsx(Text_default, { size: "sm", weight: "bold", className: "text-gray-600", children: user.name.charAt(0).toUpperCase() }) }),
/* @__PURE__ */ jsxs("div", { className: "flex-1 text-left", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", weight: "medium", className: "text-text-900", children: user.name }),
/* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: user.profileName })
] }),
/* @__PURE__ */ jsx(
"div",
{
className: cn(
"w-5 h-5 rounded-full border-2 flex items-center justify-center",
selectedIds.has(user.userInstitutionId) ? "bg-primary-500 border-primary-500" : "border-gray-300"
),
children: selectedIds.has(user.userInstitutionId) && /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-white rounded-full" })
}
)
]
},
user.userInstitutionId
)) });
function Chat(props) {
const { userId, token } = props;
if (!userId || !token) {
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-96", children: /* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-500", children: "Carregando..." }) });
}
return /* @__PURE__ */ jsx(ChatContent, { ...props });
}
function ChatContent({
apiClient,
wsUrl,
token,
userId,
userName,
userPhoto,
userRole,
className,
initialRoomId,
onRoomChange,
onBackToList
}) {
const [view, setView] = useState3("list");
const [selectedRoom, setSelectedRoom] = useState3(
null
);
const [selectedUserIds, setSelectedUserIds] = useState3(
/* @__PURE__ */ new Set()
);
const [messageInput, setMessageInput] = useState3("");
const [showCreateModal, setShowCreateModal] = useState3(false);
const hasHandledInitialRoomRef = useRef2(false);
const {
rooms,
availableUsers,
loading: roomsLoading,
error: roomsError,
fetchRooms,
fetchAvailableUsers,
createRoom
} = useChatRooms({ apiClient });
const {
isConnected,
messages,
participants,
sendMessage,
error: chatError
} = useChat({
wsUrl,
token,
roomId: selectedRoom?.id || "",
userId,
onConnect: () => console.log("Connected to chat"),
onDisconnect: () => console.log("Disconnected from chat"),
onError: (err) => console.error("Chat error:", err)
});
const getRoleLabel = () => {
return userRole === "TEACHER" /* TEACHER */ ? "Professor" : "Aluno";
};
useEffect2(() => {
fetchRooms();
}, [fetchRooms]);
useEffect2(() => {
if (hasHandledInitialRoomRef.current) {
return;
}
if (!initialRoomId || roomsLoading) {
return;
}
if (rooms?.length > 0) {
const room = rooms.find((r) => r.id === initialRoomId);
if (room) {
hasHandledInitialRoomRef.current = true;
setSelectedRoom(room);
setView("room");
} else {
hasHandledInitialRoomRef.current = true;
onBackToList?.();
}
} else if (rooms !== void 0 && !roomsLoading) {
hasHandledInitialRoomRef.current = true;
onBackToList?.();
}
}, [initialRoomId, rooms, roomsLoading, onBackToList]);
const handleSelectRoom = useCallback3(
(room) => {
setSelectedRoom(room);
setView("room");
onRoomChange?.(room.id);
},
[onRoomChange]
);
const handleOpenCreateModal = useCallback3(async () => {
await fetchAvailableUsers();
setSelectedUserIds(/* @__PURE__ */ new Set());
setShowCreateModal(true);
}, [fetchAvailableUsers]);
const handleToggleUser = useCallback3((id) => {
setSelectedUserIds((prev) => {
const next = new Set(prev);
if (next.has(id)) {
next.delete(id);
} else {
next.add(id);
}
return next;
});
}, []);
const handleCreateRoom = useCallback3(async () => {
if (selectedUserIds.size === 0) return;
const room = await createRoom(Array.from(selectedUserIds));
if (room) {
setShowCreateModal(false);
setSelectedUserIds(/* @__PURE__ */ new Set());
onRoomChange?.(room.id);
}
}, [selectedUserIds, createRoom, onRoomChange]);
const handleSendMessage = useCallback3(() => {
if (!messageInput.trim()) return;
sendMessage(messageInput);
setMessageInput("");
}, [messageInput, sendMessage]);
const handleBackToList = useCallback3(() => {
setSelectedRoom(null);
setView("list");
onBackToList?.();
}, [onBackToList]);
const renderMessagesContent = () => {
if (chatError) {
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-red-500 mb-2", children: "Erro de conexao com o chat" }),
/* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: "Tentando reconectar..." })
] }) });
}
const userMessages = messages?.filter(
(message) => message.messageType !== CHAT_MESSAGE_TYPES.SYSTEM
);
if (!userMessages?.length) {
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-500", children: "Nenhuma mensagem ainda. Comece a conversa!" }) });
}
return userMessages.map((message) => /* @__PURE__ */ jsx(
MessageBubble,
{
message,
isOwn: message.senderId === userId
},
message.id
));
};
const renderRoomList = () => /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
/* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-background-200 flex items-center justify-between", children: [
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
/* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0", children: userPhoto ? /* @__PURE__ */ jsx(
"img",
{
src: userPhoto,
alt: userName,
className: "w-10 h-10 rounded-full object-cover"
}
) : /* @__PURE__ */ jsx(Text_default, { size: "sm", weight: "bold", className: "text-primary-600", children: userName.charAt(0).toUpperCase() }) }),
/* @__PURE__ */ jsxs("div", { children: [
/* @__PURE__ */ jsx(Text_default, { size: "lg", weight: "bold", className: "text-text-900", children: "Conversas" }),
/* @__PURE__ */ jsxs(Text_default, { size: "xs", className: "text-text-500", children: [
userName,
" - ",
getRoleLabel()
] })
] })
] }),
/* @__PURE__ */ jsx(
Button_default,
{
variant: "solid",
size: "small",
onClick: handleOpenCreateModal,
iconLeft: /* @__PURE__ */ jsx(PlusIcon, { size: 16 }),
children: "Nova conversa"
}
)
] }),
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-2", children: [
roomsError && /* @__PURE__ */ jsxs("div", { className: "p-4 text-center", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-red-500 mb-2", children: "Erro ao carregar conversas" }),
/* @__PURE__ */ jsx(Button_default, { variant: "outline", size: "small", onClick: fetchRooms, children: "Tentar novamente" })
] }),
!roomsError && roomsLoading && /* @__PURE__ */ jsx("div", { className: "space-y-3 p-2", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
/* @__PURE__ */ jsx(SkeletonRounded, { className: "w-10 h-10" }),
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
/* @__PURE__ */ jsx(SkeletonText, { className: "w-3/4 h-4 mb-2" }),
/* @__PURE__ */ jsx(SkeletonText, { className: "w-1/2 h-3" })
] })
] }, i)) }),
!roomsError && !roomsLoading && !rooms?.length && /* @__PURE__ */ jsx(
EmptyState_default,
{
title: "Nenhuma conversa",
description: "Comece uma nova conversa clicando no botao acima"
}
),
!roomsError && !roomsLoading && !!rooms?.length && /* @__PURE__ */ jsx("div", { className: "space-y-1", children: rooms.map((room) => /* @__PURE__ */ jsx(
RoomItem,
{
room,
onClick: () => handleSelectRoom(room),
isActive: selectedRoom?.id === room.id
},
room.id
)) })
] })
] });
const renderChatRoom = () => {
if (!selectedRoom) return null;
return /* @__PURE__ */ jsxs("div", { className: "flex h-full", children: [
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col", children: [
/* @__PURE__ */ jsxs("div", { className: "p-4 border-b border-background-200 flex items-center gap-3", children: [
/* @__PURE__ */ jsx(Button_default, { variant: "link", size: "small", onClick: handleBackToList, children: /* @__PURE__ */ jsx(XIcon, { size: 20 }) }),
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
/* @__PURE__ */ jsx(Text_default, { size: "md", weight: "semibold", className: "text-text-900", children: selectedRoom.name }),
/* @__PURE__ */ jsx(Text_default, { size: "xs", className: "text-text-500", children: isConnected ? "Conectado" : "Conectando..." })
] })
] }),
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-4", children: renderMessagesContent() }),
/* @__PURE__ */ jsx("div", { className: "p-4 border-t border-background-200", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
/* @__PURE__ */ jsx(
Input_default,
{
placeholder: "Digite sua mensagem...",
value: messageInput,
onChange: (e) => setMessageInput(e.target.value),
onKeyDown: (e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
handleSendMessage();
}
},
className: "flex-1"
}
),
/* @__PURE__ */ jsx(
Button_default,
{
variant: "solid",
onClick: handleSendMessage,
disabled: !messageInput.trim() || !isConnected,
children: /* @__PURE__ */ jsx(PaperPlaneTiltIcon, { size: 20 })
}
)
] }) })
] }),
/* @__PURE__ */ jsxs("div", { className: "w-64 border-l border-background-200 p-4 hidden lg:block", children: [
/* @__PURE__ */ jsxs(Text_default, { size: "sm", weight: "semibold", className: "text-text-900 mb-3", children: [
"Participantes (",
participants?.length ?? 0,
")"
] }),
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: participants?.map((participant) => /* @__PURE__ */ jsx(
ParticipantItem,
{
participant
},
participant.userInstitutionId
)) })
] })
] });
};
return /* @__PURE__ */ jsxs(
"div",
{
className: cn(
"bg-background rounded-xl border border-background-200 h-[600px]",
className
),
children: [
view === "list" && renderRoomList(),
view === "room" && renderChatRoom(),
/* @__PURE__ */ jsx(
Modal_default,
{
isOpen: showCreateModal,
onClose: () => setShowCreateModal(false),
title: "Nova conversa",
children: /* @__PURE__ */ jsxs("div", { className: "p-4", children: [
/* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-600 mb-4", children: "Selecione os participantes para iniciar uma conversa" }),
roomsLoading && /* @__PURE__ */ jsx("div", { className: "space-y-3", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
/* @__PURE__ */ jsx(SkeletonRounded, { className: "w-10 h-10" }),
/* @__PURE__ */ jsx(SkeletonText, { className: "flex-1 h-4" })
] }, i)) }),
!roomsLoading && !availableUsers?.length && /* @__PURE__ */ jsx(Text_default, { size: "sm", className: "text-text-500 text-center py-4", children: "Nenhum usuario disponivel para chat" }),
!roomsLoading && !!availableUsers?.length && /* @__PURE__ */ jsx(
UserSelector,
{
users: availableUsers,
selectedIds: selectedUserIds,
onToggle: handleToggleUser
}
),
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 mt-6", children: [
/* @__PURE__ */ jsx(Button_default, { variant: "outline", onClick: () => setShowCreateModal(false), children: "Cancelar" }),
/* @__PURE__ */ jsx(
Button_default,
{
variant: "solid",
onClick: handleCreateRoom,
disabled: selectedUserIds.size === 0 || roomsLoading,
children: "Criar conversa"
}
)
] })
] })
}
)
]
}
);
}
var Chat_default = Chat;
export {
WS_STATES,
useChat,
createUseChat,
useChatRooms,
createUseChatRooms,
Chat,
Chat_default
};
//# sourceMappingURL=chunk-VLGXPGW4.mjs.map