frontPanel/src/stores/ticket.ts
2024-03-13 11:54:52 +03:00

153 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { FetchState, TicketMessage } from "@frontend/kitui";
import { create } from "zustand";
import { createJSONStorage, devtools, persist } from "zustand/middleware";
import { useUserStore } from "./user";
import { produce } from "immer";
type SessionData = {
ticketId: string;
sessionId: string;
};
interface AuthData {
sessionData: SessionData | null;
isMessageSending: boolean;
messages: TicketMessage[];
apiPage: number;
messagesPerPage: number;
lastMessageId: string | undefined;
isPreventAutoscroll: boolean;
unauthTicketMessageFetchState: FetchState;
}
interface TicketStore {
unauthData: AuthData;
authData: AuthData;
}
const initAuthData = {
sessionData: null,
isMessageSending: false,
messages: [],
apiPage: 0,
messagesPerPage: 10,
lastMessageId: undefined,
isPreventAutoscroll: false,
unauthTicketMessageFetchState: "idle" as FetchState,
};
const initState = {
unauthData: initAuthData,
authData: initAuthData,
};
export const useTicketStore = create<TicketStore>()(
persist(
devtools((set, get) => initState, {
name: "Unauth tickets",
}),
{
version: 0,
name: "unauth-ticket",
storage: createJSONStorage(() => localStorage),
},
),
);
export const cleanAuthTicketData = () => {
useTicketStore.setState({ authData: initAuthData });
};
export const setTicketData = (sessionData: SessionData) =>
updateTicket((ticket) => {
ticket.sessionData = sessionData;
});
export const setIsMessageSending = (
isMessageSending: AuthData["isMessageSending"],
) =>
updateTicket((ticket) => {
ticket.isMessageSending = isMessageSending;
});
export const addOrUpdateUnauthMessages = (receivedMessages: TicketMessage[]) =>
updateTicket((ticket) => {
const filtered = filterMessageUncompleteness(receivedMessages);
console.log(filtered);
if (filtered.length === 0) return;
const messageIdToMessageMap: { [messageId: string]: TicketMessage } = {};
[...ticket.messages, ...filtered].forEach(
(message) => (messageIdToMessageMap[message.id] = message),
);
const sortedMessages = Object.values(messageIdToMessageMap).sort(
sortMessagesByTime,
);
ticket.messages = sortedMessages;
ticket.lastMessageId = sortedMessages.at(-1)?.id;
});
export const incrementUnauthMessage = () =>
updateTicket((ticket) => {
ticket.apiPage++;
});
export const setUnauthIsPreventAutoscroll = (isPreventAutoscroll: boolean) =>
updateTicket((ticket) => {
ticket.isPreventAutoscroll = isPreventAutoscroll;
});
export const setUnauthTicketMessageFetchState = (
unauthTicketMessageFetchState: FetchState,
) =>
updateTicket((ticket) => {
ticket.unauthTicketMessageFetchState = unauthTicketMessageFetchState;
});
function sortMessagesByTime(ticket1: TicketMessage, ticket2: TicketMessage) {
const date1 = new Date(ticket1.created_at).getTime();
const date2 = new Date(ticket2.created_at).getTime();
return date1 - date2;
}
function filterMessageUncompleteness(messages: TicketMessage[]) {
return messages.filter(
(message) =>
"id" in message &&
"ticket_id" in message &&
"user_id" in message &&
"session_id" in message &&
"message" in message &&
"files" in message &&
"shown" in message &&
"request_screenshot" in message &&
"created_at" in message &&
((message.files !== null && message.files.length > 0) ||
message.message.length > 0),
);
}
export const updateTicket = <T extends AuthData>(
recipe: (ticket: AuthData) => void,
) =>
setProducedState(
(state) => {
//В зависимости от авторизованности вызывается изменение разных объектов
if (Boolean(useUserStore.getState().userId)) {
recipe(state.authData);
} else {
recipe(state.unauthData);
}
},
{
type: "updateTicket",
recipe,
},
);
function setProducedState<A extends string | { type: unknown }>(
recipe: (state: TicketStore) => void,
action?: A,
) {
useTicketStore.setState((state) => produce(state, recipe), false, action);
}