feat: enhance room management and UI with join/leave functionality
- Added GraphQL mutations and subscriptions for joining and leaving rooms - Implemented room member tracking and display in room list - Added leave room confirmation and error handling in chat room - Updated room list and chat room components with new interaction features - Improved UI with member badges, join/leave buttons, and error messages - Enhanced room query to include member information
This commit is contained in:
parent
16731409df
commit
c737258aed
6 changed files with 339 additions and 49 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { createSignal, createEffect, For, Show } from 'solid-js';
|
||||
import { gql } from '@urql/core';
|
||||
import { createQuery, createMutation, createSubscription } from '@urql/solid';
|
||||
import { Message, Room } from '../types';
|
||||
import { Message } from '../types';
|
||||
|
||||
const ROOM_QUERY = gql`
|
||||
query GetRoom($id: ID!) {
|
||||
|
|
@ -18,19 +18,14 @@ const ROOM_QUERY = gql`
|
|||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const MESSAGES_QUERY = gql`
|
||||
query GetMessages($roomId: ID!) {
|
||||
messages(roomId: $roomId) {
|
||||
id
|
||||
content
|
||||
createdAt
|
||||
user {
|
||||
messages {
|
||||
id
|
||||
username
|
||||
content
|
||||
createdAt
|
||||
user {
|
||||
id
|
||||
username
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -64,25 +59,35 @@ const MESSAGE_SUBSCRIPTION = gql`
|
|||
}
|
||||
`;
|
||||
|
||||
const LEAVE_ROOM_MUTATION = gql`
|
||||
mutation LeaveRoom($roomId: ID!) {
|
||||
leaveRoom(roomId: $roomId)
|
||||
}
|
||||
`;
|
||||
|
||||
interface ChatRoomProps {
|
||||
roomId: string;
|
||||
userId: string;
|
||||
onLeaveRoom?: () => void;
|
||||
}
|
||||
|
||||
export function ChatRoom(props: ChatRoomProps) {
|
||||
const [variables, setVariables] = createSignal({
|
||||
id: props.roomId,
|
||||
roomId: props.roomId,
|
||||
});
|
||||
const [message, setMessage] = createSignal('');
|
||||
const [messages, setMessages] = createSignal<Message[]>([]);
|
||||
const [confirmLeave, setConfirmLeave] = createSignal(false);
|
||||
const [leaveError, setLeaveError] = createSignal<string | null>(null);
|
||||
|
||||
// Query room details
|
||||
const [roomQuery] = createQuery({
|
||||
query: ROOM_QUERY,
|
||||
variables: { id: props.roomId },
|
||||
});
|
||||
|
||||
// Query messages
|
||||
const [messagesQuery] = createQuery({
|
||||
query: MESSAGES_QUERY,
|
||||
variables: { roomId: props.roomId },
|
||||
variables: variables,
|
||||
context: {
|
||||
requestPolicy: 'network-only', // Force refetch when variables change
|
||||
},
|
||||
});
|
||||
|
||||
// Send message mutation
|
||||
|
|
@ -91,14 +96,28 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
// Subscribe to new messages
|
||||
const [messageSubscription] = createSubscription({
|
||||
query: MESSAGE_SUBSCRIPTION,
|
||||
variables: { roomId: props.roomId },
|
||||
variables: variables,
|
||||
pause: false, // Ensure subscription is active
|
||||
});
|
||||
|
||||
// Leave room mutation
|
||||
const [leaveRoomResult, leaveRoom] = createMutation(LEAVE_ROOM_MUTATION);
|
||||
|
||||
// Reset messages when room changes
|
||||
createEffect(() => {
|
||||
// Access props.roomId to create a dependency
|
||||
setVariables({ id: props.roomId, roomId: props.roomId });
|
||||
// Reset messages when room changes
|
||||
// Clear any errors or confirmations
|
||||
setLeaveError(null);
|
||||
setConfirmLeave(false);
|
||||
});
|
||||
|
||||
// Load initial messages
|
||||
createEffect(() => {
|
||||
const result = messagesQuery;
|
||||
if (result.data?.messages) {
|
||||
setMessages(result.data.messages);
|
||||
const result = roomQuery;
|
||||
if (result.data?.room) {
|
||||
setMessages(result.data.room.messages);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -111,6 +130,14 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
}
|
||||
});
|
||||
|
||||
// Handle leave room error
|
||||
createEffect(() => {
|
||||
if (leaveRoomResult.error) {
|
||||
setLeaveError(leaveRoomResult.error.message);
|
||||
setConfirmLeave(false);
|
||||
}
|
||||
});
|
||||
|
||||
const handleSendMessage = async (e: Event) => {
|
||||
e.preventDefault();
|
||||
|
||||
|
|
@ -127,6 +154,30 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
}
|
||||
};
|
||||
|
||||
const handleLeaveRoom = async () => {
|
||||
if (!confirmLeave()) {
|
||||
setConfirmLeave(true);
|
||||
return;
|
||||
}
|
||||
|
||||
setLeaveError(null);
|
||||
try {
|
||||
const result = await leaveRoom({ roomId: props.roomId });
|
||||
if (result.data?.leaveRoom) {
|
||||
if (props.onLeaveRoom) {
|
||||
props.onLeaveRoom();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to leave room:', err);
|
||||
}
|
||||
};
|
||||
|
||||
const cancelLeave = () => {
|
||||
setConfirmLeave(false);
|
||||
setLeaveError(null);
|
||||
};
|
||||
|
||||
const formatTime = (dateString: string) => {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
|
|
@ -138,6 +189,23 @@ export function ChatRoom(props: ChatRoomProps) {
|
|||
<div class='chat-header'>
|
||||
<h2>{roomQuery.data?.room.name}</h2>
|
||||
<p>{roomQuery.data?.room.description}</p>
|
||||
<div class='room-actions'>
|
||||
<Show when={leaveError()}>
|
||||
<div class='error-message'>{leaveError()}</div>
|
||||
</Show>
|
||||
<Show when={confirmLeave()}>
|
||||
<div class='confirm-leave'>
|
||||
<span>Are you sure you want to leave this room?</span>
|
||||
<button onClick={handleLeaveRoom}>Yes</button>
|
||||
<button onClick={cancelLeave}>No</button>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={!confirmLeave()}>
|
||||
<button class='leave-button' onClick={handleLeaveRoom}>
|
||||
Leave Room
|
||||
</button>
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue