UNPKG

analytica-frontend-lib

Version:

Repositório público dos componentes utilizados nas plataformas da Analytica Ensino

794 lines (758 loc) 34.1 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _chunk5TVBRTWQjs = require('./chunk-5TVBRTWQ.js'); var _chunkJL5R5KTYjs = require('./chunk-JL5R5KTY.js'); var _chunkNEDUOGWUjs = require('./chunk-NEDUOGWU.js'); var _chunkLGPTKTMPjs = require('./chunk-LGPTKTMP.js'); var _chunkTCLRDUMFjs = require('./chunk-TCLRDUMF.js'); var _chunk34ST3MKOjs = require('./chunk-34ST3MKO.js'); var _chunkANT66KVKjs = require('./chunk-ANT66KVK.js'); var _chunkTN3AYOMVjs = require('./chunk-TN3AYOMV.js'); // src/components/Chat/Chat.tsx var _react = require('react'); var _react3 = require('@phosphor-icons/react'); // src/hooks/useChat.ts 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] = _react.useState.call(void 0, false); const [messages, setMessages] = _react.useState.call(void 0, []); const [participants, setParticipants] = _react.useState.call(void 0, []); const [error, setError] = _react.useState.call(void 0, null); const wsRef = _react.useRef.call(void 0, null); const reconnectAttemptsRef = _react.useRef.call(void 0, 0); const reconnectTimeoutRef = _react.useRef.call(void 0, null ); const isManualDisconnectRef = _react.useRef.call(void 0, false); const isConnectingRef = _react.useRef.call(void 0, false); const connectRef = _react.useRef.call(void 0, () => { }); const sendWsMessage = _react.useCallback.call(void 0, (message) => { if (_optionalChain([wsRef, 'access', _ => _.current, 'optionalAccess', _2 => _2.readyState]) === WS_STATES.OPEN) { wsRef.current.send(JSON.stringify(message)); } }, []); const sendMessage = _react.useCallback.call(void 0, (content) => { const trimmedContent = content.trim(); if (!trimmedContent) return; sendWsMessage({ type: "message", payload: { content: trimmedContent } }); }, [sendWsMessage] ); const leave = _react.useCallback.call(void 0, () => { isManualDisconnectRef.current = true; sendWsMessage({ type: "leave" }); _optionalChain([wsRef, 'access', _3 => _3.current, 'optionalAccess', _4 => _4.close, 'call', _5 => _5(1e3, "User left")]); }, [sendWsMessage]); const handleMessage = _react.useCallback.call(void 0, (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)); _optionalChain([onError, 'optionalCall', _6 => _6(new Error(errorMessage))]); break; } } } catch (err) { console.error("Error parsing WebSocket message:", err); } }, [onError] ); const connect = _react.useCallback.call(void 0, () => { 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" })); _optionalChain([onConnect, 'optionalCall', _7 => _7()]); }; ws.onmessage = handleMessage; ws.onerror = () => { isConnectingRef.current = false; const error2 = new Error("Erro na conex\xE3o WebSocket"); setError(error2); _optionalChain([onError, 'optionalCall', _8 => _8(error2)]); }; ws.onclose = (event) => { isConnectingRef.current = false; setIsConnected(false); _optionalChain([onDisconnect, 'optionalCall', _9 => _9()]); 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 = _react.useCallback.call(void 0, () => { isManualDisconnectRef.current = false; reconnectAttemptsRef.current = 0; connectRef.current(); }, []); _react.useEffect.call(void 0, () => { 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); } _optionalChain([wsRef, 'access', _10 => _10.current, 'optionalAccess', _11 => _11.close, 'call', _12 => _12(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 function useChatRooms({ apiClient }) { const [rooms, setRooms] = _react.useState.call(void 0, []); const [availableUsers, setAvailableUsers] = _react.useState.call(void 0, []); const [loading, setLoading] = _react.useState.call(void 0, false); const [error, setError] = _react.useState.call(void 0, null); const fetchRooms = _react.useCallback.call(void 0, 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 = _react.useCallback.call(void 0, 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 = _react.useCallback.call(void 0, 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 = _react.useCallback.call(void 0, () => { setError(null); }, []); return { rooms, availableUsers, loading, error, fetchRooms, fetchAvailableUsers, createRoom, clearError }; } function createUseChatRooms(apiClient) { return () => useChatRooms({ apiClient }); } // src/components/Chat/Chat.tsx var _jsxruntime = require('react/jsx-runtime'); var RoomItem = ({ room, onClick, isActive }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "link", onClick, className: _chunkTN3AYOMVjs.cn.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-start gap-3 w-full", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _react3.UsersIcon, { size: 20, className: "text-primary-600" }) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-text-900 truncate", children: room.name }), room.lastMessage && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500 truncate mt-1", children: [ room.lastMessage.senderName, ": ", room.lastMessage.content ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-400 mt-1", children: [ room.participantCount, " participantes" ] }) ] }) ] }) } ); var MessageBubble = ({ message, isOwn }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "flex gap-2 mb-3", isOwn && "flex-row-reverse"), children: [ !isOwn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center flex-shrink-0", children: message.senderPhoto ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: message.senderPhoto, alt: message.senderName, className: "w-8 h-8 rounded-full object-cover" } ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", weight: "bold", className: "text-gray-600", children: message.senderName.charAt(0).toUpperCase() }) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "max-w-[70%]", isOwn && "items-end"), children: [ !isOwn && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500 mb-1", children: message.senderName }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", children: message.content }) } ), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: _chunkTN3AYOMVjs.cn.call(void 0, "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__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 py-2", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-8 h-8 rounded-full bg-gray-200 flex items-center justify-center", children: participant.photo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: participant.photo, alt: participant.name, className: "w-8 h-8 rounded-full object-cover" } ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", weight: "bold", className: "text-gray-600", children: participant.name.charAt(0).toUpperCase() }) }), participant.isOnline && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute bottom-0 right-0 w-3 h-3 bg-green-500 rounded-full border-2 border-white" }) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 min-w-0", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-900 truncate", children: participant.name }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: participant.role }) ] }) ] }); var UserSelector = ({ users, selectedIds, onToggle }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-2 max-h-64 overflow-y-auto", children: users.map((user) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "link", onClick: () => onToggle(user.userInstitutionId), className: _chunkTN3AYOMVjs.cn.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 rounded-full bg-gray-200 flex items-center justify-center", children: user.photo ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: user.photo, alt: user.name, className: "w-10 h-10 rounded-full object-cover" } ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "bold", className: "text-gray-600", children: user.name.charAt(0).toUpperCase() }) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 text-left", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "medium", className: "text-text-900", children: user.name }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: user.profileName }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "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__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-2 h-2 bg-white rounded-full" }) } ) ] }, user.userInstitutionId )) }); function Chat(props) { const { userId, token } = props; if (!userId || !token) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center h-96", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Carregando..." }) }); } return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ChatContent, { ...props }); } function ChatContent({ apiClient, wsUrl, token, userId, userName, userPhoto, userRole, className, initialRoomId, onRoomChange, onBackToList }) { const [view, setView] = _react.useState.call(void 0, "list"); const [selectedRoom, setSelectedRoom] = _react.useState.call(void 0, null ); const [selectedUserIds, setSelectedUserIds] = _react.useState.call(void 0, /* @__PURE__ */ new Set() ); const [messageInput, setMessageInput] = _react.useState.call(void 0, ""); const [showCreateModal, setShowCreateModal] = _react.useState.call(void 0, false); const hasHandledInitialRoomRef = _react.useRef.call(void 0, false); const { rooms, availableUsers, loading: roomsLoading, error: roomsError, fetchRooms, fetchAvailableUsers, createRoom } = useChatRooms({ apiClient }); const { isConnected, messages, participants, sendMessage, error: chatError } = useChat({ wsUrl, token, roomId: _optionalChain([selectedRoom, 'optionalAccess', _13 => _13.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"; }; _react.useEffect.call(void 0, () => { fetchRooms(); }, [fetchRooms]); _react.useEffect.call(void 0, () => { if (hasHandledInitialRoomRef.current) { return; } if (!initialRoomId || roomsLoading) { return; } if (_optionalChain([rooms, 'optionalAccess', _14 => _14.length]) > 0) { const room = rooms.find((r) => r.id === initialRoomId); if (room) { hasHandledInitialRoomRef.current = true; setSelectedRoom(room); setView("room"); } else { hasHandledInitialRoomRef.current = true; _optionalChain([onBackToList, 'optionalCall', _15 => _15()]); } } else if (rooms !== void 0 && !roomsLoading) { hasHandledInitialRoomRef.current = true; _optionalChain([onBackToList, 'optionalCall', _16 => _16()]); } }, [initialRoomId, rooms, roomsLoading, onBackToList]); const handleSelectRoom = _react.useCallback.call(void 0, (room) => { setSelectedRoom(room); setView("room"); _optionalChain([onRoomChange, 'optionalCall', _17 => _17(room.id)]); }, [onRoomChange] ); const handleOpenCreateModal = _react.useCallback.call(void 0, async () => { await fetchAvailableUsers(); setSelectedUserIds(/* @__PURE__ */ new Set()); setShowCreateModal(true); }, [fetchAvailableUsers]); const handleToggleUser = _react.useCallback.call(void 0, (id) => { setSelectedUserIds((prev) => { const next = new Set(prev); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); }, []); const handleCreateRoom = _react.useCallback.call(void 0, async () => { if (selectedUserIds.size === 0) return; const room = await createRoom(Array.from(selectedUserIds)); if (room) { setShowCreateModal(false); setSelectedUserIds(/* @__PURE__ */ new Set()); _optionalChain([onRoomChange, 'optionalCall', _18 => _18(room.id)]); } }, [selectedUserIds, createRoom, onRoomChange]); const handleSendMessage = _react.useCallback.call(void 0, () => { if (!messageInput.trim()) return; sendMessage(messageInput); setMessageInput(""); }, [messageInput, sendMessage]); const handleBackToList = _react.useCallback.call(void 0, () => { setSelectedRoom(null); setView("list"); _optionalChain([onBackToList, 'optionalCall', _19 => _19()]); }, [onBackToList]); const renderMessagesContent = () => { if (chatError) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "text-center", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-red-500 mb-2", children: "Erro de conexao com o chat" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: "Tentando reconectar..." }) ] }) }); } const userMessages = _optionalChain([messages, 'optionalAccess', _20 => _20.filter, 'call', _21 => _21( (message) => message.messageType !== _chunk5TVBRTWQjs.CHAT_MESSAGE_TYPES.SYSTEM )]); if (!_optionalChain([userMessages, 'optionalAccess', _22 => _22.length])) { return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500", children: "Nenhuma mensagem ainda. Comece a conversa!" }) }); } return userMessages.map((message) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, MessageBubble, { message, isOwn: message.senderId === userId }, message.id )); }; const renderRoomList = () => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col h-full", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border-b border-background-200 flex items-center justify-between", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-10 h-10 rounded-full bg-primary-100 flex items-center justify-center flex-shrink-0", children: userPhoto ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: userPhoto, alt: userName, className: "w-10 h-10 rounded-full object-cover" } ) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "bold", className: "text-primary-600", children: userName.charAt(0).toUpperCase() }) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "lg", weight: "bold", className: "text-text-900", children: "Conversas" }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: [ userName, " - ", getRoleLabel() ] }) ] }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "solid", size: "small", onClick: handleOpenCreateModal, iconLeft: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _react3.PlusIcon, { size: 16 }), children: "Nova conversa" } ) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 overflow-y-auto p-2", children: [ roomsError && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 text-center", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-red-500 mb-2", children: "Erro ao carregar conversas" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "outline", size: "small", onClick: fetchRooms, children: "Tentar novamente" }) ] }), !roomsError && roomsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-3 p-2", children: [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "w-10 h-10" }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonText, { className: "w-3/4 h-4 mb-2" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonText, { className: "w-1/2 h-3" }) ] }) ] }, i)) }), !roomsError && !roomsLoading && !_optionalChain([rooms, 'optionalAccess', _23 => _23.length]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkJL5R5KTYjs.EmptyState_default, { title: "Nenhuma conversa", description: "Comece uma nova conversa clicando no botao acima" } ), !roomsError && !roomsLoading && !!_optionalChain([rooms, 'optionalAccess', _24 => _24.length]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-1", children: rooms.map((room) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RoomItem, { room, onClick: () => handleSelectRoom(room), isActive: _optionalChain([selectedRoom, 'optionalAccess', _25 => _25.id]) === room.id }, room.id )) }) ] }) ] }); const renderChatRoom = () => { if (!selectedRoom) return null; return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 flex flex-col", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4 border-b border-background-200 flex items-center gap-3", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "link", size: "small", onClick: handleBackToList, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _react3.XIcon, { size: 20 }) }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "md", weight: "semibold", className: "text-text-900", children: selectedRoom.name }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "xs", className: "text-text-500", children: isConnected ? "Conectado" : "Conectando..." }) ] }) ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 overflow-y-auto p-4", children: renderMessagesContent() }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4 border-t border-background-200", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkLGPTKTMPjs.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__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "solid", onClick: handleSendMessage, disabled: !messageInput.trim() || !isConnected, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _react3.PaperPlaneTiltIcon, { size: 20 }) } ) ] }) }) ] }), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "w-64 border-l border-background-200 p-4 hidden lg:block", children: [ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", weight: "semibold", className: "text-text-900 mb-3", children: [ "Participantes (", _nullishCoalesce(_optionalChain([participants, 'optionalAccess', _26 => _26.length]), () => ( 0)), ")" ] }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-1", children: _optionalChain([participants, 'optionalAccess', _27 => _27.map, 'call', _28 => _28((participant) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ParticipantItem, { participant }, participant.userInstitutionId ))]) }) ] }) ] }); }; return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkTN3AYOMVjs.cn.call(void 0, "bg-background rounded-xl border border-background-200 h-[600px]", className ), children: [ view === "list" && renderRoomList(), view === "room" && renderChatRoom(), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkTCLRDUMFjs.Modal_default, { isOpen: showCreateModal, onClose: () => setShowCreateModal(false), title: "Nova conversa", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-4", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-600 mb-4", children: "Selecione os participantes para iniciar uma conversa" }), roomsLoading && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "space-y-3", children: [1, 2, 3].map((i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonRounded, { className: "w-10 h-10" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkNEDUOGWUjs.SkeletonText, { className: "flex-1 h-4" }) ] }, i)) }), !roomsLoading && !_optionalChain([availableUsers, 'optionalAccess', _29 => _29.length]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkANT66KVKjs.Text_default, { size: "sm", className: "text-text-500 text-center py-4", children: "Nenhum usuario disponivel para chat" }), !roomsLoading && !!_optionalChain([availableUsers, 'optionalAccess', _30 => _30.length]) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UserSelector, { users: availableUsers, selectedIds: selectedUserIds, onToggle: handleToggleUser } ), /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex justify-end gap-2 mt-6", children: [ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "outline", onClick: () => setShowCreateModal(false), children: "Cancelar" }), /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk34ST3MKOjs.Button_default, { variant: "solid", onClick: handleCreateRoom, disabled: selectedUserIds.size === 0 || roomsLoading, children: "Criar conversa" } ) ] }) ] }) } ) ] } ); } var Chat_default = Chat; exports.WS_STATES = WS_STATES; exports.useChat = useChat; exports.createUseChat = createUseChat; exports.useChatRooms = useChatRooms; exports.createUseChatRooms = createUseChatRooms; exports.Chat = Chat; exports.Chat_default = Chat_default; //# sourceMappingURL=chunk-WLEMAAZ7.js.map