Vitron-Front/app/requestHandler/use-chat-hooks.tsx
2026-04-29 01:44:16 +03:30

203 lines
5.0 KiB
TypeScript

import {
useQuery,
useInfiniteQuery,
QueryClient,
useMutation,
} from "@tanstack/react-query";
import { useAuthToken } from "../hooks/use-root-data";
import { MessageList } from "../../src/api/types/models";
import { createChatApi } from "~/utils/api-client-factory";
/**
* Custom hook to get the list of user's threads
*/
export function useGetUserThreads() {
const token = useAuthToken();
return useQuery({
queryKey: ["getUserThreads"],
queryFn: async () => {
if (!token) {
throw new Error("Authentication token is required");
}
const chatApi = createChatApi(token);
return await chatApi.apiChatV1ThreadsList();
},
enabled: !!token,
retry: 1,
retryDelay: 3000,
refetchOnWindowFocus: false,
refetchInterval: 20 * 1000, // 30 seconds refetch
});
}
/**
* Server-side function to get thread details
*/
export async function getThreadDetails(token: string, threadId: string) {
if (!token) {
throw new Error("Authentication token is required");
}
const chatApi = createChatApi(token);
return await chatApi.apiChatV1ThreadsRead({ threadId });
}
/**
* Custom hook to get thread details by ID
*/
export function useGetThreadDetails(threadId: string) {
const token = useAuthToken();
return useQuery({
queryKey: ["getThreadDetails", threadId],
queryFn: async () => {
if (!token) {
throw new Error("Authentication token is required");
}
const chatApi = createChatApi(token);
return await chatApi.apiChatV1ThreadsRead({ threadId });
},
enabled: !!token && !!threadId,
retry: 1,
retryDelay: 3000,
refetchOnWindowFocus: false,
});
}
export const deleteMessageFromCache = (
queryClient: QueryClient,
threadId: string,
messageId: string
) => {
queryClient.setQueryData(
["getThreadMessages", threadId],
(
oldData:
| {
pages: Array<{
results: MessageList[];
nextCursor: string | null;
}>;
pageParams: Array<string | undefined>;
}
| undefined
) => {
if (!oldData) return oldData;
return {
...oldData,
pages: oldData.pages.map((page) => {
return {
...page,
results: page.results.filter((message) => message.id !== messageId),
};
}),
};
}
);
};
export const setMessagesCache = (
queryClient: QueryClient,
threadId: string,
data: MessageList
) => {
queryClient.setQueryData(
["getThreadMessages", threadId],
(
oldData:
| {
pages: Array<{
results: MessageList[];
nextCursor: string | null;
}>;
pageParams: Array<string | undefined>;
}
| undefined
) => {
if (!oldData) return oldData;
return {
...oldData,
pages: oldData.pages.map((page, index: number) => {
if (index === 0) {
return {
...page,
results: [data, ...page.results],
};
}
return page;
}),
};
}
);
};
/**
* Custom hook to get thread messages with infinite scrolling
*/
export function useGetThreadMessages(threadId: string) {
const token = useAuthToken();
return useInfiniteQuery({
queryKey: ["getThreadMessages", threadId],
queryFn: async ({ pageParam }) => {
if (!token) {
throw new Error("Authentication token is required");
}
const chatApi = createChatApi(token);
// Using cursor-based pagination
const response = await chatApi.apiChatV1ThreadsMessagesList({
threadId,
cursor: pageParam ? String(pageParam) : undefined,
});
// Check if response has next cursor
let nextCursor;
if (response.next) {
const nextUrlParts = response.next.split("?cursor=");
nextCursor = nextUrlParts.length > 1 ? nextUrlParts[1] : null;
} else {
nextCursor = null;
}
const messages = response.results || [];
// Get the ID of the last message to use as next cursor
return {
results: messages,
nextCursor,
};
},
initialPageParam: undefined as string | undefined,
getNextPageParam: (lastPage) => {
return lastPage.nextCursor || undefined;
},
enabled: !!token && !!threadId,
refetchOnWindowFocus: false,
});
}
/**
* Custom hook to create a new chat thread
*/
export function useCreateChatThread() {
const token = useAuthToken();
return useMutation({
mutationFn: async (participantId: string) => {
if (!token) {
throw new Error("Authentication token and user ID are required");
}
try {
const chatApi = createChatApi(token);
return await chatApi.apiChatV1ThreadsCreateCreate({
data: {
participantId: participantId,
},
});
} catch (error) {
console.error("Error creating chat thread:", error);
throw error;
}
},
});
}