frontPanel/src/stores/ticket.ts

152 lines
4.1 KiB
TypeScript
Raw Normal View History

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);
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;
});
2024-03-13 08:54:52 +00:00
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);
}