243 lines
5.8 KiB
TypeScript
243 lines
5.8 KiB
TypeScript
import { makeAutoObservable, reaction, runInAction } from "mobx";
|
|
import { assignManager, changeStatus, getManagers, getOrders } from "~/api/api";
|
|
import {
|
|
AuthUserResponseRole,
|
|
ChangeOrderStatusApiRequestStatus,
|
|
type GetManagersParams,
|
|
type GetOrdersParams,
|
|
type ManagerListItemResponse,
|
|
type OrderApiResponse,
|
|
type PageManagerListItemResponse,
|
|
type PageOrderApiResponse,
|
|
} from "~/api/models";
|
|
import type { RootStore } from "./RootStore";
|
|
|
|
export class OrdersStore {
|
|
private readonly rootStore: RootStore;
|
|
|
|
orders: OrderApiResponse[] = [];
|
|
|
|
managers: ManagerListItemResponse[] = [];
|
|
|
|
isLoading = false;
|
|
|
|
isManagersLoading = false;
|
|
|
|
isSaving = false;
|
|
|
|
error = "";
|
|
|
|
constructor(rootStore: RootStore) {
|
|
this.rootStore = rootStore;
|
|
makeAutoObservable(this, {}, { autoBind: true });
|
|
|
|
reaction(
|
|
() => ({
|
|
userId: this.rootStore.authStore.user?.id,
|
|
role: this.rootStore.authStore.user?.role,
|
|
}),
|
|
({ userId, role }) => {
|
|
void this.syncSession(userId, role);
|
|
},
|
|
{ fireImmediately: true },
|
|
);
|
|
|
|
reaction(
|
|
() => this.rootStore.notificationsStore.messages[0],
|
|
(message) => {
|
|
if (!message) {
|
|
return;
|
|
}
|
|
|
|
if (!this.shouldRefetchByNotification(message.type)) {
|
|
return;
|
|
}
|
|
|
|
void this.fetchOrders();
|
|
},
|
|
);
|
|
}
|
|
|
|
get newOrdersCount() {
|
|
return this.orders.filter((order) => order.status === "NEW").length;
|
|
}
|
|
|
|
get placedOrdersCount() {
|
|
return this.orders.filter((order) => order.status === "PLACED").length;
|
|
}
|
|
|
|
get rejectedOrdersCount() {
|
|
return this.orders.filter((order) => order.status === "REJECTED").length;
|
|
}
|
|
|
|
async fetchOrders() {
|
|
this.isLoading = true;
|
|
this.error = "";
|
|
try {
|
|
const data = await this.fetchAllOrders();
|
|
runInAction(() => {
|
|
this.orders = data;
|
|
});
|
|
} catch (error) {
|
|
runInAction(() => {
|
|
this.error = this.extractErrorMessage(error);
|
|
});
|
|
throw error;
|
|
} finally {
|
|
runInAction(() => {
|
|
this.isLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
private async syncSession(userId?: string, role?: AuthUserResponseRole) {
|
|
if (!userId || !role) {
|
|
this.rootStore.notificationsStore.disconnect();
|
|
runInAction(() => {
|
|
this.orders = [];
|
|
this.managers = [];
|
|
});
|
|
return;
|
|
}
|
|
|
|
this.rootStore.notificationsStore.connect(userId, role);
|
|
|
|
try {
|
|
await this.fetchOrders();
|
|
|
|
if (role === AuthUserResponseRole.SENIOR_MANAGER) {
|
|
await this.fetchManagers();
|
|
return;
|
|
}
|
|
|
|
runInAction(() => {
|
|
this.managers = [];
|
|
});
|
|
} catch {
|
|
|
|
}
|
|
}
|
|
|
|
async fetchManagers() {
|
|
this.isManagersLoading = true;
|
|
this.error = "";
|
|
try {
|
|
const data = await this.fetchAllManagers();
|
|
runInAction(() => {
|
|
this.managers = data;
|
|
});
|
|
} catch (error) {
|
|
runInAction(() => {
|
|
this.error = this.extractErrorMessage(error);
|
|
});
|
|
throw error;
|
|
} finally {
|
|
runInAction(() => {
|
|
this.isManagersLoading = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
async assignOrder(orderId: string, managerId: string) {
|
|
this.isSaving = true;
|
|
this.error = "";
|
|
try {
|
|
const updated = await assignManager(orderId, { managerId });
|
|
runInAction(() => {
|
|
this.upsertOrder(updated);
|
|
});
|
|
} catch (error) {
|
|
runInAction(() => {
|
|
this.error = this.extractErrorMessage(error);
|
|
});
|
|
throw error;
|
|
} finally {
|
|
runInAction(() => {
|
|
this.isSaving = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
async setStatus(orderId: string, status: ChangeOrderStatusApiRequestStatus) {
|
|
this.isSaving = true;
|
|
this.error = "";
|
|
try {
|
|
const updated = await changeStatus(orderId, { status });
|
|
runInAction(() => {
|
|
this.upsertOrder(updated);
|
|
});
|
|
} catch (error) {
|
|
runInAction(() => {
|
|
this.error = this.extractErrorMessage(error);
|
|
});
|
|
throw error;
|
|
} finally {
|
|
runInAction(() => {
|
|
this.isSaving = false;
|
|
});
|
|
}
|
|
}
|
|
|
|
private upsertOrder(order: OrderApiResponse) {
|
|
const index = this.orders.findIndex((item) => item.id === order.id);
|
|
if (index === -1) {
|
|
this.orders = [order, ...this.orders];
|
|
return;
|
|
}
|
|
|
|
const next = [...this.orders];
|
|
next[index] = order;
|
|
this.orders = next;
|
|
}
|
|
|
|
private extractErrorMessage(error: unknown) {
|
|
if (typeof error === "object" && error !== null && "response" in error) {
|
|
const maybeResponse = error as { response?: { data?: { message?: string } } };
|
|
if (maybeResponse.response?.data?.message) {
|
|
return maybeResponse.response.data.message;
|
|
}
|
|
}
|
|
|
|
if (error instanceof Error && error.message) {
|
|
return error.message;
|
|
}
|
|
|
|
return "Произошла ошибка запроса.";
|
|
}
|
|
|
|
private shouldRefetchByNotification(type: string) {
|
|
return type === "NEW_ORDER_CREATED" || type === "ORDER_ASSIGNED" || type === "ORDER_STATUS_CHANGED";
|
|
}
|
|
|
|
private async fetchAllOrders() {
|
|
return this.fetchAllPages<OrderApiResponse, GetOrdersParams, PageOrderApiResponse>((params) => getOrders(params));
|
|
}
|
|
|
|
private async fetchAllManagers() {
|
|
return this.fetchAllPages<ManagerListItemResponse, GetManagersParams, PageManagerListItemResponse>((params) =>
|
|
getManagers(params),
|
|
);
|
|
}
|
|
|
|
private async fetchAllPages<TItem, TParams extends { page?: number; size?: number }, TPage extends {
|
|
content?: TItem[];
|
|
last?: boolean;
|
|
}>(loader: (params: TParams) => Promise<TPage>, size = 100) {
|
|
let page = 0;
|
|
const items: TItem[] = [];
|
|
|
|
while (true) {
|
|
const response = await loader({ page, size } as TParams);
|
|
items.push(...(response.content ?? []));
|
|
|
|
if (response.last ?? true) {
|
|
break;
|
|
}
|
|
|
|
page += 1;
|
|
}
|
|
|
|
return items;
|
|
}
|
|
}
|