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