front-hub/src/stores/tickets.ts
2024-03-13 17:36:47 +03:00

184 lines
4.9 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, Ticket, TicketMessage } from "@frontend/kitui";
import { create } from "zustand";
import { devtools, persist, createJSONStorage } 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 {
ticketCount: number;
tickets: Ticket[];
apiPage: number;
ticketsPerPage: number;
ticketsFetchState: FetchState;
authData: AuthData;
unauthData: AuthData;
}
const initAuthData = {
sessionData: null,
isMessageSending: false,
messages: [],
apiPage: 0,
messagesPerPage: 10,
lastMessageId: undefined,
isPreventAutoscroll: false,
unauthTicketMessageFetchState: "idle" as FetchState,
};
const initialState: TicketStore = {
ticketCount: 0,
tickets: [],
apiPage: 0,
ticketsPerPage: 10,
ticketsFetchState: "idle",
authData: initAuthData,
unauthData: initAuthData,
};
export const useTicketStore = create<TicketStore>()(
persist(
devtools((set, get) => initialState, {
name: "Unauth tickets",
}),
{
version: 0,
name: "unauth-ticket",
storage: createJSONStorage(() => localStorage),
}
)
);
export const setTicketCount = (ticketCount: number) =>
useTicketStore.setState({ ticketCount });
export const setTicketApiPage = (apiPage: number) =>
useTicketStore.setState({ apiPage: apiPage });
export const updateTickets = (receivedTickets: Ticket[]) => {
const state = useTicketStore.getState();
const ticketIdToTicketMap: { [ticketId: string]: Ticket } = {};
[...state.tickets, ...receivedTickets].forEach(
(ticket) => (ticketIdToTicketMap[ticket.id] = ticket)
);
useTicketStore.setState({ tickets: Object.values(ticketIdToTicketMap) });
};
export const clearTickets = () => useTicketStore.setState({ ...initialState });
export const setTicketsFetchState = (ticketsFetchState: FetchState) =>
useTicketStore.setState({ ticketsFetchState });
export const setTicketData = (sessionData: SessionData) =>
updateTicket((ticket) => {
ticket.sessionData = sessionData;
});
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);
}
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)
);
}
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;
}
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;
});
export const setUnauthTicketMessageFetchState = (
unauthTicketMessageFetchState: FetchState
) =>
updateTicket((ticket) => {
ticket.unauthTicketMessageFetchState = unauthTicketMessageFetchState;
});
export const setUnauthIsPreventAutoscroll = (isPreventAutoscroll: boolean) =>
updateTicket((ticket) => {
ticket.isPreventAutoscroll = isPreventAutoscroll;
});
export const incrementUnauthMessage = () =>
updateTicket((ticket) => {
ticket.apiPage++;
});
export const setIsMessageSending = (
isMessageSending: AuthData["isMessageSending"]
) => {
updateTicket((ticket) => {
ticket.isMessageSending = isMessageSending;
});
};