init commit,
This commit is contained in:
220
03_source/frontend/src/actions/chat.ts
Normal file
220
03_source/frontend/src/actions/chat.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
import type { SWRConfiguration } from 'swr';
|
||||
import type { IChatMessage, IChatParticipant, IChatConversation } from 'src/types/chat';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import { keyBy } from 'es-toolkit';
|
||||
import useSWR, { mutate } from 'swr';
|
||||
|
||||
import axios, { fetcher, endpoints } from 'src/lib/axios';
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const enableServer = false;
|
||||
|
||||
const CHART_ENDPOINT = endpoints.chat;
|
||||
|
||||
const swrOptions: SWRConfiguration = {
|
||||
revalidateIfStale: enableServer,
|
||||
revalidateOnFocus: enableServer,
|
||||
revalidateOnReconnect: enableServer,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type ContactsData = {
|
||||
contacts: IChatParticipant[];
|
||||
};
|
||||
|
||||
export function useGetContacts() {
|
||||
const url = [CHART_ENDPOINT, { params: { endpoint: 'contacts' } }];
|
||||
|
||||
const { data, isLoading, error, isValidating } = useSWR<ContactsData>(url, fetcher, swrOptions);
|
||||
|
||||
const memoizedValue = useMemo(
|
||||
() => ({
|
||||
contacts: data?.contacts || [],
|
||||
contactsLoading: isLoading,
|
||||
contactsError: error,
|
||||
contactsValidating: isValidating,
|
||||
contactsEmpty: !isLoading && !isValidating && !data?.contacts.length,
|
||||
}),
|
||||
[data?.contacts, error, isLoading, isValidating]
|
||||
);
|
||||
|
||||
return memoizedValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type ConversationsData = {
|
||||
conversations: IChatConversation[];
|
||||
};
|
||||
|
||||
export function useGetConversations() {
|
||||
const url = [CHART_ENDPOINT, { params: { endpoint: 'conversations' } }];
|
||||
|
||||
const { data, isLoading, error, isValidating } = useSWR<ConversationsData>(
|
||||
url,
|
||||
fetcher,
|
||||
swrOptions
|
||||
);
|
||||
|
||||
const memoizedValue = useMemo(() => {
|
||||
const byId = data?.conversations.length ? keyBy(data.conversations, (option) => option.id) : {};
|
||||
const allIds = Object.keys(byId);
|
||||
|
||||
return {
|
||||
conversations: { byId, allIds },
|
||||
conversationsLoading: isLoading,
|
||||
conversationsError: error,
|
||||
conversationsValidating: isValidating,
|
||||
conversationsEmpty: !isLoading && !isValidating && !allIds.length,
|
||||
};
|
||||
}, [data?.conversations, error, isLoading, isValidating]);
|
||||
|
||||
return memoizedValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
type ConversationData = {
|
||||
conversation: IChatConversation;
|
||||
};
|
||||
|
||||
export function useGetConversation(conversationId: string) {
|
||||
const url = conversationId
|
||||
? [CHART_ENDPOINT, { params: { conversationId, endpoint: 'conversation' } }]
|
||||
: '';
|
||||
|
||||
const { data, isLoading, error, isValidating } = useSWR<ConversationData>(
|
||||
url,
|
||||
fetcher,
|
||||
swrOptions
|
||||
);
|
||||
|
||||
const memoizedValue = useMemo(
|
||||
() => ({
|
||||
conversation: data?.conversation,
|
||||
conversationLoading: isLoading,
|
||||
conversationError: error,
|
||||
conversationValidating: isValidating,
|
||||
conversationEmpty: !isLoading && !isValidating && !data?.conversation,
|
||||
}),
|
||||
[data?.conversation, error, isLoading, isValidating]
|
||||
);
|
||||
|
||||
return memoizedValue;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export async function sendMessage(conversationId: string, messageData: IChatMessage) {
|
||||
const conversationsUrl = [CHART_ENDPOINT, { params: { endpoint: 'conversations' } }];
|
||||
|
||||
const conversationUrl = [
|
||||
CHART_ENDPOINT,
|
||||
{ params: { conversationId, endpoint: 'conversation' } },
|
||||
];
|
||||
|
||||
/**
|
||||
* Work on server
|
||||
*/
|
||||
if (enableServer) {
|
||||
const data = { conversationId, messageData };
|
||||
await axios.put(CHART_ENDPOINT, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Work in local
|
||||
*/
|
||||
mutate(
|
||||
conversationUrl,
|
||||
(currentData) => {
|
||||
const currentConversation: IChatConversation = currentData.conversation;
|
||||
|
||||
const conversation = {
|
||||
...currentConversation,
|
||||
messages: [...currentConversation.messages, messageData],
|
||||
};
|
||||
|
||||
return { ...currentData, conversation };
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
mutate(
|
||||
conversationsUrl,
|
||||
(currentData) => {
|
||||
const currentConversations: IChatConversation[] = currentData.conversations;
|
||||
|
||||
const conversations: IChatConversation[] = currentConversations.map(
|
||||
(conversation: IChatConversation) =>
|
||||
conversation.id === conversationId
|
||||
? { ...conversation, messages: [...conversation.messages, messageData] }
|
||||
: conversation
|
||||
);
|
||||
|
||||
return { ...currentData, conversations };
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export async function createConversation(conversationData: IChatConversation) {
|
||||
const url = [CHART_ENDPOINT, { params: { endpoint: 'conversations' } }];
|
||||
|
||||
/**
|
||||
* Work on server
|
||||
*/
|
||||
const data = { conversationData };
|
||||
const res = await axios.post(CHART_ENDPOINT, data);
|
||||
|
||||
/**
|
||||
* Work in local
|
||||
*/
|
||||
|
||||
mutate(
|
||||
url,
|
||||
(currentData) => {
|
||||
const currentConversations: IChatConversation[] = currentData.conversations;
|
||||
|
||||
const conversations: IChatConversation[] = [...currentConversations, conversationData];
|
||||
|
||||
return { ...currentData, conversations };
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
return res.data;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
export async function clickConversation(conversationId: string) {
|
||||
/**
|
||||
* Work on server
|
||||
*/
|
||||
if (enableServer) {
|
||||
await axios.get(CHART_ENDPOINT, { params: { conversationId, endpoint: 'mark-as-seen' } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Work in local
|
||||
*/
|
||||
|
||||
mutate(
|
||||
[CHART_ENDPOINT, { params: { endpoint: 'conversations' } }],
|
||||
(currentData) => {
|
||||
const currentConversations: IChatConversation[] = currentData.conversations;
|
||||
|
||||
const conversations = currentConversations.map((conversation: IChatConversation) =>
|
||||
conversation.id === conversationId ? { ...conversation, unreadCount: 0 } : conversation
|
||||
);
|
||||
|
||||
return { ...currentData, conversations };
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user