1import { User, UserCreate } from 'types/user';
2import { subscribeWithSelector } from 'zustand/middleware';
3import { create } from 'zustand';
4import { pageSizeManagers } from 'utils/userPreferenceStorage';
5import { fetch } from 'service/http';
6import { useServices, useDashboard } from 'stores';
7import { StatisticsQueryKey } from 'components/statistics-card';
8import { queryClient } from 'service/react-query';
9import { UsersFilterType, FilterUsageType } from 'types/filter';
10
11type UsersStateType = {
12 isCreatingNewUser: boolean;
13 editingUser: User | null | undefined;
14 deletingUser: User | null;
15 users: {
16 users: User[];
17 total: number;
18 };
19 usersFilters: UsersFilterType;
20 resetUsageUser: User | null;
21 revokeSubscriptionUser: User | null;
22 isResetingAllUsage: boolean;
23 subscribeUrl: string | null;
24 QRcodeLinks: string[] | null;
25 setQRCode: (links: string[] | null) => void;
26 setSubLink: (subscribeURL: string | null) => void;
27 onResetAllUsage: (isResetingAllUsage: boolean) => void;
28 resetAllUsage: () => Promise<void>;
29 resetDataUsage: (user: User) => Promise<void>;
30 revokeSubscription: (user: User) => Promise<void>;
31 onCreateUser: (isOpen: boolean) => void;
32 onEditingUser: (user: User | null) => void;
33 onDeletingUser: (user: User | null) => void;
34 refetchUsers: () => void;
35 onFilterChange: (filters: Partial<UsersFilterType>) => void;
36 deleteUser: (user: User) => Promise<void>;
37 createUser: (user: UserCreate) => Promise<void>;
38 editUser: (user: UserCreate) => Promise<void>;
39 fetchUserUsage: (user: User, query: FilterUsageType) => Promise<void>;
40}
41
42export const fetchUsers = async (query: UsersFilterType): Promise<User[]> => {
43 for (const key in query) {
44 if (!query[key as keyof UsersFilterType]) delete query[key as keyof UsersFilterType];
45 }
46 useDashboard.setState({ loading: true });
47 return fetch('/users', { query })
48 .then((users) => {
49 for (let i = 0; i < users.users.length; i++) {
50 users.users[i].service = users.users[i].service_ids;
51 }
52 useUsers.setState({ users });
53 return users;
54 })
55 .finally(() => {
56 useDashboard.setState({ loading: false });
57 });
58};
59
60export const useUsers = create(subscribeWithSelector<UsersStateType>((set, get) => ({
61 editingUser: null,
62 deletingUser: null,
63 isCreatingNewUser: false,
64 users: {
65 users: [],
66 total: 0,
67 },
68 resetUsageUser: null,
69 revokeSubscriptionUser: null,
70 isResetingAllUsage: false,
71 usersFilters: {
72 username: '',
73 limit: pageSizeManagers.users.getPageSize(),
74 sort: '-created_at',
75 },
76 QRcodeLinks: null,
77 subscribeUrl: null,
78 setQRCode: (QRcodeLinks) => {
79 set({ QRcodeLinks });
80 },
81 setSubLink: (subscribeUrl) => {
82 set({ subscribeUrl });
83 },
84 refetchUsers: () => {
85 fetchUsers(get().usersFilters);
86 },
87 resetAllUsage: async () => {
88 return fetch('/users/reset', { method: 'POST' }).then(() => {
89 get().onResetAllUsage(false);
90 get().refetchUsers();
91 });
92 },
93 onResetAllUsage: (isResetingAllUsage) => set({ isResetingAllUsage }),
94 onCreateUser: (isCreatingNewUser) => set({ isCreatingNewUser }),
95 onEditingUser: (editingUser) => {
96 set({ editingUser });
97 },
98 onDeletingUser: (deletingUser) => {
99 set({ deletingUser });
100 },
101 onFilterChange: (filters) => {
102 set({
103 usersFilters: {
104 ...get().usersFilters,
105 ...filters,
106 },
107 });
108 get().refetchUsers();
109 },
110 deleteUser: async (user: User) => {
111 set({ editingUser: null });
112 return fetch(`/users/${user.username}`, { method: 'DELETE' }).then(() => {
113 set({ deletingUser: null });
114 get().refetchUsers();
115 queryClient.invalidateQueries(StatisticsQueryKey);
116 });
117 },
118 createUser: async (body: UserCreate) => {
119 return fetch('/users', { method: 'POST', body }).then(() => {
120 set({ editingUser: null });
121 get().refetchUsers();
122 useServices.getState().refetchServices();
123 queryClient.invalidateQueries(StatisticsQueryKey);
124 });
125 },
126 editUser: async (body: UserCreate) => {
127 return fetch(`/users/${body.username}`, { method: 'PUT', body }).then(
128 () => {
129 get().onEditingUser(null);
130 get().refetchUsers();
131 }
132 );
133 },
134
135 fetchUserUsage: (body: User, query: FilterUsageType) => {
136 for (const key in query) {
137 if (!query[key as keyof FilterUsageType])
138 delete query[key as keyof FilterUsageType];
139 }
140 return fetch(`/users/${body.username}/usage`, { method: 'GET', query });
141 },
142 resetDataUsage: async (user) => {
143 return fetch(`/users/${user.username}/reset`, { method: 'POST' }).then(
144 () => {
145 set({ resetUsageUser: null });
146 get().refetchUsers();
147 }
148 );
149 },
150 revokeSubscription: async (user) => {
151 return fetch(`/users/${user.username}/revoke_sub`, {
152 method: 'POST',
153 }).then((user) => {
154 set({ revokeSubscriptionUser: null, editingUser: user });
155 get().refetchUsers();
156 });
157 },
158})));