Files
antigol-service/frontend/composables/useSupportUnread.ts
talorr cda36918e8 init
2026-03-27 03:36:08 +03:00

107 lines
3.2 KiB
TypeScript

import type { SupportConversation } from "~/types";
const toConversationMap = (items: SupportConversation[]) =>
Object.fromEntries(items.map((item) => [item.id, item])) as Record<string, SupportConversation>;
export function useSupportUnread() {
const { user, token } = useAuth();
const { connect, onConversationUpdated, onMessageCreated } = useSupportRealtime();
const conversations = useState<Record<string, SupportConversation>>("support-unread-conversations", () => ({}));
const unreadCount = useState<number>("support-unread-count", () => 0);
const initialized = useState<boolean>("support-unread-initialized", () => false);
const loading = useState<boolean>("support-unread-loading", () => false);
const offConversationUpdated = useState<(() => void) | null>("support-unread-off-conversation", () => null);
const offMessageCreated = useState<(() => void) | null>("support-unread-off-message", () => null);
const recomputeUnreadCount = () => {
const items = Object.values(conversations.value);
unreadCount.value = user.value?.role === "admin"
? items.filter((item) => item.unreadForAdmin).length
: items.some((item) => item.unreadForUser) ? 1 : 0;
};
const replaceConversations = (items: SupportConversation[]) => {
conversations.value = toConversationMap(items);
recomputeUnreadCount();
};
const upsertConversation = (item: SupportConversation) => {
conversations.value = {
...conversations.value,
[item.id]: item
};
recomputeUnreadCount();
};
const clearState = () => {
conversations.value = {};
unreadCount.value = 0;
initialized.value = false;
offConversationUpdated.value?.();
offConversationUpdated.value = null;
offMessageCreated.value?.();
offMessageCreated.value = null;
};
const refreshUnread = async () => {
if (!user.value || !token.value || loading.value) {
return;
}
loading.value = true;
try {
if (user.value.role === "admin") {
const response = await useChatApi<SupportConversation[]>("/admin/support/conversations");
replaceConversations(response);
} else {
const response = await useChatApi<SupportConversation>("/support/conversation");
replaceConversations([response]);
}
} catch {
// Ignore unread refresh failures in shell navigation.
} finally {
loading.value = false;
}
};
const ensureRealtime = () => {
if (!process.client || !token.value || offConversationUpdated.value || offMessageCreated.value) {
return;
}
connect();
offConversationUpdated.value = onConversationUpdated(({ conversation }) => {
if (conversation) {
upsertConversation(conversation);
}
});
offMessageCreated.value = onMessageCreated(({ conversation }) => {
if (conversation) {
upsertConversation(conversation);
}
});
};
const initializeUnread = async () => {
if (initialized.value || !user.value || !token.value) {
return;
}
await refreshUnread();
ensureRealtime();
initialized.value = true;
};
return {
unreadCount,
initializeUnread,
refreshUnread,
replaceConversations,
upsertConversation,
clearState
};
}