analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
794 lines (758 loc) • 34.1 kB
JavaScript
"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