@greatapps/common 1.1.187 → 1.1.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/embeds/CrispEmbed.mjs +64 -0
- package/dist/components/embeds/CrispEmbed.mjs.map +1 -0
- package/dist/components/embeds/FrillEmbed.mjs +97 -0
- package/dist/components/embeds/FrillEmbed.mjs.map +1 -0
- package/dist/components/layouts/UsersSelectorPopover.mjs +76 -102
- package/dist/components/layouts/UsersSelectorPopover.mjs.map +1 -1
- package/dist/index.mjs +5 -0
- package/dist/index.mjs.map +1 -1
- package/dist/modules/projects/actions/list-all-account-users.action.mjs +10 -0
- package/dist/modules/projects/actions/list-all-account-users.action.mjs.map +1 -0
- package/dist/modules/projects/hooks/list-all-account-users.hook.mjs +35 -0
- package/dist/modules/projects/hooks/list-all-account-users.hook.mjs.map +1 -0
- package/dist/modules/projects/services/project-users.service.mjs +18 -0
- package/dist/modules/projects/services/project-users.service.mjs.map +1 -1
- package/dist/modules/projects/types.mjs +2 -1
- package/dist/modules/projects/types.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/embeds/CrispEmbed.tsx +76 -0
- package/src/components/embeds/FrillEmbed.tsx +114 -0
- package/src/components/layouts/UsersSelectorPopover.tsx +261 -294
- package/src/index.ts +4 -0
- package/src/modules/projects/actions/list-all-account-users.action.ts +9 -0
- package/src/modules/projects/hooks/list-all-account-users.hook.ts +34 -0
- package/src/modules/projects/services/project-users.service.ts +22 -0
- package/src/modules/projects/types.ts +2 -0
|
@@ -1,294 +1,261 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from "../ui/overlay/
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
} from "../../modules/projects/
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
const [
|
|
61
|
-
const [
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
const
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
>
|
|
185
|
-
|
|
186
|
-
</
|
|
187
|
-
</
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
263
|
-
className={cn(
|
|
264
|
-
user.removable && hoveredId === user.id
|
|
265
|
-
? "border-gray-950"
|
|
266
|
-
: "",
|
|
267
|
-
"disabled:opacity-10",
|
|
268
|
-
)}
|
|
269
|
-
/>
|
|
270
|
-
</TooltipTrigger>
|
|
271
|
-
<TooltipContent className="z-[1002]">
|
|
272
|
-
{user.checked
|
|
273
|
-
? "Remover do projeto"
|
|
274
|
-
: "Adicionar ao projeto"}
|
|
275
|
-
</TooltipContent>
|
|
276
|
-
</Tooltip>
|
|
277
|
-
</div>
|
|
278
|
-
</CommandItem>
|
|
279
|
-
))}
|
|
280
|
-
{isFetchingMore && (
|
|
281
|
-
<>
|
|
282
|
-
<UserItemSkeleton />
|
|
283
|
-
<UserItemSkeleton />
|
|
284
|
-
</>
|
|
285
|
-
)}
|
|
286
|
-
</>
|
|
287
|
-
)}
|
|
288
|
-
</CommandList>
|
|
289
|
-
</Command>
|
|
290
|
-
</div>
|
|
291
|
-
</PopoverContent>
|
|
292
|
-
</Popover>
|
|
293
|
-
);
|
|
294
|
-
}
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { Plus, Settings, User, Users } from "lucide-react";
|
|
5
|
+
import { UserAvatar } from "../ui/data-display/UserAvatar";
|
|
6
|
+
import { useQueryClient, useMutation } from "@tanstack/react-query";
|
|
7
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../ui/overlay/Popover";
|
|
8
|
+
import { Button } from "../ui/buttons/Button";
|
|
9
|
+
import {
|
|
10
|
+
Command,
|
|
11
|
+
CommandEmpty,
|
|
12
|
+
CommandInput,
|
|
13
|
+
CommandItem,
|
|
14
|
+
CommandList,
|
|
15
|
+
} from "../ui/overlay/Command";
|
|
16
|
+
import { Checkbox } from "../ui/form/Checkbox";
|
|
17
|
+
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/overlay/Tooltip";
|
|
18
|
+
import { cn } from "../../infra/utils/clsx";
|
|
19
|
+
import {
|
|
20
|
+
useListProjectUsers,
|
|
21
|
+
LIST_PROJECT_USERS_BASE_KEY,
|
|
22
|
+
} from "../../modules/projects/hooks/list-project-users.hook";
|
|
23
|
+
import {
|
|
24
|
+
useListAllAccountUsers,
|
|
25
|
+
LIST_ALL_ACCOUNT_USERS_BASE_KEY,
|
|
26
|
+
} from "../../modules/projects/hooks/list-all-account-users.hook";
|
|
27
|
+
import { removeProjectUserAction } from "../../modules/projects/actions/remove-project-user.action";
|
|
28
|
+
import { addProjectUserAction } from "../../modules/projects/actions/add-project-user.action";
|
|
29
|
+
|
|
30
|
+
export interface UsersSelectorPopoverProps {
|
|
31
|
+
projectId?: number;
|
|
32
|
+
side?: "top" | "bottom" | "left" | "right";
|
|
33
|
+
align?: "start" | "center" | "end";
|
|
34
|
+
contentClassName?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function UserItemSkeleton() {
|
|
38
|
+
return (
|
|
39
|
+
<div className="flex items-center justify-between px-2 py-1.5 gap-2">
|
|
40
|
+
<div className="flex items-center gap-2 flex-1">
|
|
41
|
+
<div className="skeleton size-8 rounded-full shrink-0" />
|
|
42
|
+
<div className="skeleton h-3.5 w-28 rounded" />
|
|
43
|
+
</div>
|
|
44
|
+
<div className="skeleton size-4 rounded shrink-0" />
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const GAPPS_URL = process.env.NEXT_PUBLIC_GREAT_APPS ?? "";
|
|
50
|
+
|
|
51
|
+
export function UsersSelectorPopover({
|
|
52
|
+
projectId,
|
|
53
|
+
side,
|
|
54
|
+
align,
|
|
55
|
+
contentClassName,
|
|
56
|
+
}: UsersSelectorPopoverProps) {
|
|
57
|
+
const queryClient = useQueryClient();
|
|
58
|
+
const [open, setOpen] = useState(false);
|
|
59
|
+
const [hoveredId, setHoveredId] = useState<number | null>(null);
|
|
60
|
+
const [searchInput, setSearchInput] = useState("");
|
|
61
|
+
const [search, setSearch] = useState("");
|
|
62
|
+
|
|
63
|
+
const id = projectId ?? 0;
|
|
64
|
+
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const timer = setTimeout(() => setSearch(searchInput), 300);
|
|
67
|
+
return () => clearTimeout(timer);
|
|
68
|
+
}, [searchInput]);
|
|
69
|
+
|
|
70
|
+
const accountUsers = useListAllAccountUsers(search, id || undefined);
|
|
71
|
+
const projectUsers = useListProjectUsers(id, "");
|
|
72
|
+
|
|
73
|
+
const allUsers = accountUsers.data?.pages.flatMap((p) => p.data) ?? [];
|
|
74
|
+
const isLoading = accountUsers.isLoading;
|
|
75
|
+
const isFetchingMore = accountUsers.isFetchingNextPage;
|
|
76
|
+
const totalInProject = projectUsers.data?.pages[0]?.total ?? 0;
|
|
77
|
+
|
|
78
|
+
const invalidate = () => {
|
|
79
|
+
queryClient.invalidateQueries({ queryKey: LIST_PROJECT_USERS_BASE_KEY(id) });
|
|
80
|
+
queryClient.invalidateQueries({ queryKey: LIST_ALL_ACCOUNT_USERS_BASE_KEY() });
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const removeMutation = useMutation({
|
|
84
|
+
mutationFn: (userId: number) =>
|
|
85
|
+
removeProjectUserAction({ projectId: id, users: [userId] }),
|
|
86
|
+
onSuccess: invalidate,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const addMutation = useMutation({
|
|
90
|
+
mutationFn: (userId: number) =>
|
|
91
|
+
addProjectUserAction({ projectId: id, users: [userId] }),
|
|
92
|
+
onSuccess: invalidate,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
const toggleUser = (userId: number, inProject: boolean, removable: boolean) => {
|
|
96
|
+
if (inProject) {
|
|
97
|
+
if (!removable) return;
|
|
98
|
+
removeMutation.mutate(userId);
|
|
99
|
+
} else {
|
|
100
|
+
addMutation.mutate(userId);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
|
|
105
|
+
const target = e.currentTarget;
|
|
106
|
+
const nearBottom =
|
|
107
|
+
target.scrollTop + target.clientHeight >= target.scrollHeight - 50;
|
|
108
|
+
if (!nearBottom) return;
|
|
109
|
+
if (accountUsers.hasNextPage && !accountUsers.isFetchingNextPage) {
|
|
110
|
+
accountUsers.fetchNextPage();
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Popover open={open} onOpenChange={setOpen}>
|
|
116
|
+
<PopoverTrigger className="cursor-pointer">
|
|
117
|
+
<div className="flex items-center gap-2 text-gray-950 px-3 py-2 border border-gray-200 rounded-full hover:border-gray-950">
|
|
118
|
+
<span className="paragraph-small-semibold">{totalInProject}</span>
|
|
119
|
+
<User size={16} />
|
|
120
|
+
</div>
|
|
121
|
+
</PopoverTrigger>
|
|
122
|
+
|
|
123
|
+
<PopoverContent
|
|
124
|
+
className={cn(
|
|
125
|
+
"absolute right-[-88px] w-[273px] p-0 bg-white rounded-2xl shadow-md border border-gray-200",
|
|
126
|
+
contentClassName,
|
|
127
|
+
)}
|
|
128
|
+
side={side}
|
|
129
|
+
align={align}
|
|
130
|
+
sideOffset={8}
|
|
131
|
+
>
|
|
132
|
+
<div className="flex flex-col p-3 gap-2">
|
|
133
|
+
<div className="flex items-center justify-between">
|
|
134
|
+
<span className="paragraph-small-semibold">Usuários</span>
|
|
135
|
+
<div className="flex items-center gap-1.5">
|
|
136
|
+
<Button
|
|
137
|
+
variant="secondary"
|
|
138
|
+
className="h-8 paragraph-small-semibold text-gray-950"
|
|
139
|
+
onClick={() => {
|
|
140
|
+
window.location.href = `${GAPPS_URL}/my-teams?createNew=true`;
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
143
|
+
<Plus size={16} />
|
|
144
|
+
Adicionar
|
|
145
|
+
</Button>
|
|
146
|
+
<Tooltip>
|
|
147
|
+
<TooltipTrigger asChild>
|
|
148
|
+
<Button
|
|
149
|
+
variant="secondary"
|
|
150
|
+
className="p-0 size-8"
|
|
151
|
+
onClick={() => {
|
|
152
|
+
window.location.href = `${GAPPS_URL}/my-teams`;
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
<Settings size={18} />
|
|
156
|
+
</Button>
|
|
157
|
+
</TooltipTrigger>
|
|
158
|
+
<TooltipContent className="z-[1002]">
|
|
159
|
+
Visualizar todos usuários
|
|
160
|
+
</TooltipContent>
|
|
161
|
+
</Tooltip>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<Command shouldFilter={false} className="gap-2" value="">
|
|
166
|
+
<CommandInput
|
|
167
|
+
placeholder="Busque aqui"
|
|
168
|
+
value={searchInput}
|
|
169
|
+
onValueChange={setSearchInput}
|
|
170
|
+
/>
|
|
171
|
+
<CommandList
|
|
172
|
+
className="custom-scrollbar paragraph-small-medium text-gray-600 h-[162px]"
|
|
173
|
+
onScroll={handleScroll}
|
|
174
|
+
>
|
|
175
|
+
{isLoading ? (
|
|
176
|
+
<>
|
|
177
|
+
<UserItemSkeleton />
|
|
178
|
+
<UserItemSkeleton />
|
|
179
|
+
<UserItemSkeleton />
|
|
180
|
+
</>
|
|
181
|
+
) : allUsers.length === 0 ? (
|
|
182
|
+
<div className="flex flex-col items-center justify-center gap-2 h-full text-gray-400 py-4">
|
|
183
|
+
<Users size={28} className="text-gray-300" />
|
|
184
|
+
<span className="paragraph-small-medium text-center text-gray-500">
|
|
185
|
+
Nenhum usuário encontrado.
|
|
186
|
+
</span>
|
|
187
|
+
</div>
|
|
188
|
+
) : (
|
|
189
|
+
<>
|
|
190
|
+
<CommandEmpty>Nenhum resultado encontrado.</CommandEmpty>
|
|
191
|
+
{allUsers.map((user) => {
|
|
192
|
+
const inProject = user.in_project ?? false;
|
|
193
|
+
const removable =
|
|
194
|
+
inProject &&
|
|
195
|
+
user.profile !== "owner" &&
|
|
196
|
+
user.profile !== "admin";
|
|
197
|
+
const interactive = !inProject || removable;
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<CommandItem
|
|
201
|
+
key={user.id}
|
|
202
|
+
value={user.name || String(user.id)}
|
|
203
|
+
autoFocus={false}
|
|
204
|
+
onPointerEnter={() => setHoveredId(user.id)}
|
|
205
|
+
onPointerLeave={() => setHoveredId(null)}
|
|
206
|
+
onFocus={() => setHoveredId(user.id)}
|
|
207
|
+
onBlur={() => setHoveredId(null)}
|
|
208
|
+
onSelect={() => toggleUser(user.id, inProject, removable)}
|
|
209
|
+
className={interactive ? "cursor-pointer" : "cursor-default"}
|
|
210
|
+
>
|
|
211
|
+
<div className="flex items-center justify-between w-full">
|
|
212
|
+
<div className="flex items-center gap-2 min-w-0">
|
|
213
|
+
<UserAvatar
|
|
214
|
+
photo={user.photo}
|
|
215
|
+
name={user.name ?? undefined}
|
|
216
|
+
size={32}
|
|
217
|
+
/>
|
|
218
|
+
<span className="truncate">{user.name}</span>
|
|
219
|
+
</div>
|
|
220
|
+
<Tooltip open={interactive && hoveredId === user.id}>
|
|
221
|
+
<TooltipTrigger
|
|
222
|
+
onClick={(e) => e.stopPropagation()}
|
|
223
|
+
onPointerDown={(e) => e.stopPropagation()}
|
|
224
|
+
>
|
|
225
|
+
<Checkbox
|
|
226
|
+
checked={inProject}
|
|
227
|
+
disabled={!interactive}
|
|
228
|
+
onCheckedChange={() =>
|
|
229
|
+
toggleUser(user.id, inProject, removable)
|
|
230
|
+
}
|
|
231
|
+
className={cn(
|
|
232
|
+
interactive && hoveredId === user.id
|
|
233
|
+
? "border-gray-950"
|
|
234
|
+
: "",
|
|
235
|
+
"disabled:opacity-10",
|
|
236
|
+
)}
|
|
237
|
+
/>
|
|
238
|
+
</TooltipTrigger>
|
|
239
|
+
<TooltipContent className="z-[1002]">
|
|
240
|
+
{inProject ? "Remover do projeto" : "Adicionar ao projeto"}
|
|
241
|
+
</TooltipContent>
|
|
242
|
+
</Tooltip>
|
|
243
|
+
</div>
|
|
244
|
+
</CommandItem>
|
|
245
|
+
);
|
|
246
|
+
})}
|
|
247
|
+
{isFetchingMore && (
|
|
248
|
+
<>
|
|
249
|
+
<UserItemSkeleton />
|
|
250
|
+
<UserItemSkeleton />
|
|
251
|
+
</>
|
|
252
|
+
)}
|
|
253
|
+
</>
|
|
254
|
+
)}
|
|
255
|
+
</CommandList>
|
|
256
|
+
</Command>
|
|
257
|
+
</div>
|
|
258
|
+
</PopoverContent>
|
|
259
|
+
</Popover>
|
|
260
|
+
);
|
|
261
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -256,6 +256,10 @@ export {
|
|
|
256
256
|
TooltipProvider,
|
|
257
257
|
} from "./components/ui/overlay/Tooltip";
|
|
258
258
|
|
|
259
|
+
// Embeds
|
|
260
|
+
export { FrillEmbed } from "./components/embeds/FrillEmbed";
|
|
261
|
+
export { CrispEmbed, openCrispHelpdesk } from "./components/embeds/CrispEmbed";
|
|
262
|
+
|
|
259
263
|
// Store
|
|
260
264
|
export { useMdSidebarStore } from "./store/useMdSidebarStore";
|
|
261
265
|
export { useModalManager } from "./store/useModalManager";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { safeServerAction } from '../../../utils/safeServerAction';
|
|
4
|
+
import { projectUsersService } from '../services/project-users.service';
|
|
5
|
+
import type { ListUsersParams } from '../types';
|
|
6
|
+
|
|
7
|
+
export async function listAllAccountUsersAction(params: ListUsersParams = {}) {
|
|
8
|
+
return safeServerAction(() => projectUsersService.listAllAccountUsers(params));
|
|
9
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useInfiniteQuery } from '@tanstack/react-query';
|
|
4
|
+
import { listAllAccountUsersAction } from '../actions/list-all-account-users.action';
|
|
5
|
+
import { withAction } from '../../../utils/withAction';
|
|
6
|
+
|
|
7
|
+
const PAGE_SIZE = 20;
|
|
8
|
+
|
|
9
|
+
export const LIST_ALL_ACCOUNT_USERS_BASE_KEY = () => ['account-users', 'all'];
|
|
10
|
+
export const LIST_ALL_ACCOUNT_USERS_QUERY_KEY = (search: string = '', projectId?: number) => [
|
|
11
|
+
...LIST_ALL_ACCOUNT_USERS_BASE_KEY(),
|
|
12
|
+
search,
|
|
13
|
+
projectId,
|
|
14
|
+
];
|
|
15
|
+
|
|
16
|
+
export function useListAllAccountUsers(search: string = '', projectId?: number) {
|
|
17
|
+
return useInfiniteQuery({
|
|
18
|
+
queryKey: LIST_ALL_ACCOUNT_USERS_QUERY_KEY(search, projectId),
|
|
19
|
+
queryFn: ({ pageParam }) =>
|
|
20
|
+
withAction(() =>
|
|
21
|
+
listAllAccountUsersAction({
|
|
22
|
+
search: search || undefined,
|
|
23
|
+
page: pageParam as number,
|
|
24
|
+
limit: PAGE_SIZE,
|
|
25
|
+
inProject: projectId,
|
|
26
|
+
})
|
|
27
|
+
)(),
|
|
28
|
+
getNextPageParam: (lastPage, allPages) => {
|
|
29
|
+
const loaded = allPages.reduce((sum, p) => sum + p.data.length, 0);
|
|
30
|
+
return loaded < lastPage.total ? allPages.length + 1 : undefined;
|
|
31
|
+
},
|
|
32
|
+
initialPageParam: 1,
|
|
33
|
+
});
|
|
34
|
+
}
|