@lodashventure/medusa-membership 0.4.9 → 0.4.10

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.
@@ -1,1101 +0,0 @@
1
- import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
- import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
3
- import { toast, Container, Heading, Switch, Label, Text, Input, Button, createDataTableColumnHelper, usePrompt, useDataTable, DataTable, Drawer, Textarea } from "@medusajs/ui";
4
- import axios from "axios";
5
- import { useState, useEffect } from "react";
6
- import Medusa from "@medusajs/js-sdk";
7
- import { Users } from "@medusajs/icons";
8
- const useMembershipConfig = (storeId, options) => {
9
- const [data, setData] = useState(void 0);
10
- const [isLoading, setIsLoading] = useState(true);
11
- const [error, setError] = useState(null);
12
- const fetchConfig = async () => {
13
- if (!storeId) {
14
- setError(new Error("No store id found"));
15
- setIsLoading(false);
16
- return;
17
- }
18
- try {
19
- setIsLoading(true);
20
- setError(null);
21
- const { data: config2 } = await axios.get(
22
- `/admin/membership/config/${storeId}`
23
- );
24
- setData(config2);
25
- } catch (err) {
26
- setError(
27
- err instanceof Error ? err : new Error("Failed to fetch config")
28
- );
29
- } finally {
30
- setIsLoading(false);
31
- }
32
- };
33
- useEffect(() => {
34
- fetchConfig();
35
- }, [storeId, options == null ? void 0 : options.enabled]);
36
- return {
37
- data,
38
- isLoading,
39
- error,
40
- refetch: fetchConfig
41
- };
42
- };
43
- const sdk = new Medusa({
44
- baseUrl: "/",
45
- debug: false,
46
- auth: {
47
- type: "session"
48
- }
49
- });
50
- const useStore = () => {
51
- const [data, setData] = useState(void 0);
52
- const [isLoading, setIsLoading] = useState(true);
53
- const [error, setError] = useState(null);
54
- const fetchStore = async () => {
55
- var _a;
56
- try {
57
- setIsLoading(true);
58
- setError(null);
59
- const response = await sdk.admin.store.list();
60
- const activeStore = (_a = response.stores) == null ? void 0 : _a[0];
61
- if (!activeStore) {
62
- throw new Error("No active store found");
63
- }
64
- setData(activeStore);
65
- } catch (err) {
66
- setError(err instanceof Error ? err : new Error("Failed to fetch store"));
67
- } finally {
68
- setIsLoading(false);
69
- }
70
- };
71
- useEffect(() => {
72
- fetchStore();
73
- }, []);
74
- return {
75
- data,
76
- isLoading,
77
- error,
78
- refetch: fetchStore
79
- };
80
- };
81
- const usePromotionCollectable = (id) => {
82
- const [data, setData] = useState(void 0);
83
- const [isLoading, setIsLoading] = useState(true);
84
- const [error, setError] = useState(null);
85
- const fetchCollectable = async () => {
86
- try {
87
- setIsLoading(true);
88
- setError(null);
89
- const response = await axios.get(
90
- `/admin/promotions/${id}/update-collectable`
91
- );
92
- setData(response);
93
- } catch (err) {
94
- setError(
95
- err instanceof Error ? err : new Error("Failed to fetch collectable")
96
- );
97
- } finally {
98
- setIsLoading(false);
99
- }
100
- };
101
- useEffect(() => {
102
- fetchCollectable();
103
- }, [id]);
104
- return {
105
- data,
106
- isLoading,
107
- error,
108
- refetch: fetchCollectable
109
- };
110
- };
111
- const useUpdatePromotionCollectable = (id) => {
112
- const [isPending, setIsPending] = useState(false);
113
- const [error, setError] = useState(null);
114
- const mutate = async (data, { onSuccess } = {}) => {
115
- try {
116
- setIsPending(true);
117
- setError(null);
118
- const response = await axios.patch(
119
- `/admin/promotions/${id}/update-collectable`,
120
- data
121
- );
122
- toast.success("Coupon collection updated successfully", {
123
- dismissable: true,
124
- duration: 2500
125
- });
126
- if (onSuccess) {
127
- onSuccess();
128
- }
129
- return response.data;
130
- } catch (err) {
131
- const error2 = err instanceof Error ? err : new Error("Failed to update coupon collection");
132
- setError(error2);
133
- toast.error("Failed to update coupon collection", {
134
- dismissable: true,
135
- duration: 2500
136
- });
137
- throw error2;
138
- } finally {
139
- setIsPending(false);
140
- }
141
- };
142
- return {
143
- mutate,
144
- isPending,
145
- error
146
- };
147
- };
148
- const PromotionWidget = ({ data }) => {
149
- const { id } = data;
150
- const { data: collectable } = usePromotionCollectable(id);
151
- const { data: store } = useStore();
152
- const { data: config2 } = useMembershipConfig(store == null ? void 0 : store.id);
153
- const { mutate: updateCollectable } = useUpdatePromotionCollectable(id);
154
- const handleToggleCollectable = async (checked) => {
155
- try {
156
- updateCollectable({
157
- enabled: checked
158
- });
159
- toast.success("Coupon collection updated successfully", {
160
- dismissable: true,
161
- duration: 2500
162
- });
163
- } catch (error) {
164
- toast.error("Failed to update coupon collection", {
165
- dismissable: true,
166
- duration: 2500
167
- });
168
- }
169
- };
170
- if (!(config2 == null ? void 0 : config2.enable_promotion_collection)) {
171
- return null;
172
- }
173
- if (data.is_automatic) {
174
- return null;
175
- }
176
- return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-6 gap-4", children: [
177
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx(Heading, { level: "h2", children: "Coupon Collection" }) }),
178
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-2", children: [
179
- /* @__PURE__ */ jsx(
180
- Switch,
181
- {
182
- checked: collectable == null ? void 0 : collectable.data.enabled,
183
- onCheckedChange: handleToggleCollectable
184
- }
185
- ),
186
- /* @__PURE__ */ jsx(Label, { children: "Can be collected by customer" })
187
- ] })
188
- ] });
189
- };
190
- defineWidgetConfig({
191
- zone: "promotion.details.side.after"
192
- });
193
- const useUpdateMembershipConfig = () => {
194
- const [isPending, setIsPending] = useState(false);
195
- const [error, setError] = useState(null);
196
- const mutate = async ({ storeId, config: config2 }, {
197
- onSuccess
198
- } = {}) => {
199
- if (!storeId) {
200
- throw new Error("No store id found");
201
- }
202
- try {
203
- setIsPending(true);
204
- setError(null);
205
- const response = await axios.patch(
206
- `/admin/membership/config/${storeId}`,
207
- config2
208
- );
209
- if (onSuccess) {
210
- onSuccess(response.data);
211
- }
212
- return response.data;
213
- } catch (err) {
214
- const error2 = err instanceof Error ? err : new Error("Failed to update config");
215
- setError(error2);
216
- throw error2;
217
- } finally {
218
- setIsPending(false);
219
- }
220
- };
221
- return {
222
- mutate,
223
- isPending,
224
- error
225
- };
226
- };
227
- const MembershipPage = () => {
228
- const { data: store } = useStore();
229
- const [config2, setConfig] = useState({
230
- enable_membership: false,
231
- membership_points_multiplier: 1,
232
- enable_membership_notification: false,
233
- enable_wishlist: true,
234
- enable_promotion_collection: true
235
- });
236
- const { data: curConfig, error, refetch } = useMembershipConfig(store == null ? void 0 : store.id);
237
- const { mutate: saveConfig, isPending } = useUpdateMembershipConfig();
238
- const [spendingAmount, setSpendingAmount] = useState(
239
- 1 / config2.membership_points_multiplier
240
- );
241
- useEffect(() => {
242
- if (curConfig) {
243
- setConfig(curConfig);
244
- setSpendingAmount(1 / curConfig.membership_points_multiplier);
245
- }
246
- }, [curConfig]);
247
- const handleSave = async () => {
248
- var _a, _b;
249
- try {
250
- await saveConfig({
251
- storeId: store == null ? void 0 : store.id,
252
- config: config2
253
- });
254
- toast.success("Settings saved successfully", {
255
- dismissable: true,
256
- duration: 2500
257
- });
258
- await refetch();
259
- } catch (error2) {
260
- if (axios.isAxiosError(error2)) {
261
- toast.error("Error saving settings", {
262
- description: (_b = (_a = error2.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message,
263
- dismissable: true,
264
- duration: 2500
265
- });
266
- } else {
267
- toast.error("Error saving settings", {
268
- dismissable: true,
269
- duration: 2500
270
- });
271
- }
272
- }
273
- };
274
- if (error || !config2) {
275
- return /* @__PURE__ */ jsxs("div", { children: [
276
- "Error: ",
277
- error == null ? void 0 : error.message
278
- ] });
279
- }
280
- return /* @__PURE__ */ jsxs(Container, { className: "p-8 rounded-lg", children: [
281
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold mb-4", children: "Membership Settings" }),
282
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
283
- /* @__PURE__ */ jsx(
284
- Switch,
285
- {
286
- checked: config2.enable_membership,
287
- onCheckedChange: (checked) => setConfig((prev) => ({ ...prev, enable_membership: checked }))
288
- }
289
- ),
290
- "Enable Membership points"
291
- ] }),
292
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mt-4", children: [
293
- /* @__PURE__ */ jsx(Text, { children: "Spending" }),
294
- /* @__PURE__ */ jsx(
295
- Input,
296
- {
297
- className: "w-32",
298
- type: "number",
299
- value: spendingAmount,
300
- onChange: (e) => {
301
- const value = Number(e.target.value) || 0;
302
- const ratio = 1 / value;
303
- setConfig((prev) => ({
304
- ...prev,
305
- membership_points_multiplier: ratio
306
- }));
307
- setSpendingAmount(value);
308
- }
309
- }
310
- ),
311
- /* @__PURE__ */ jsx(Text, { children: "To get 1 point" })
312
- ] }),
313
- /* @__PURE__ */ jsx("hr", { className: "my-4" }),
314
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 my-2", children: [
315
- /* @__PURE__ */ jsx(
316
- Switch,
317
- {
318
- checked: config2.enable_membership_notification,
319
- onCheckedChange: (checked) => setConfig((prev) => ({
320
- ...prev,
321
- enable_membership_notification: checked
322
- }))
323
- }
324
- ),
325
- "Enable Membership Notification"
326
- ] }),
327
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 my-2", children: [
328
- /* @__PURE__ */ jsx(
329
- Switch,
330
- {
331
- checked: config2.enable_wishlist,
332
- onCheckedChange: (checked) => setConfig((prev) => ({
333
- ...prev,
334
- enable_wishlist: checked
335
- }))
336
- }
337
- ),
338
- "Enable Membership Wishlist"
339
- ] }),
340
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 my-2", children: [
341
- /* @__PURE__ */ jsx(
342
- Switch,
343
- {
344
- checked: config2.enable_promotion_collection,
345
- onCheckedChange: (checked) => setConfig((prev) => ({
346
- ...prev,
347
- enable_promotion_collection: checked
348
- }))
349
- }
350
- ),
351
- "Enable Promotion Collection"
352
- ] }),
353
- /* @__PURE__ */ jsx(Button, { onClick: handleSave, disabled: isPending, className: "mt-5", children: isPending ? "Saving..." : "Save Settings" })
354
- ] });
355
- };
356
- const BannerUpload = () => {
357
- return /* @__PURE__ */ jsx(MembershipPage, {});
358
- };
359
- const config$2 = defineRouteConfig({
360
- label: "Membership",
361
- icon: Users
362
- });
363
- const useCreateMembershipConsent = () => {
364
- const [isPending, setIsPending] = useState(false);
365
- const [error, setError] = useState(null);
366
- const mutate = async (data, { onSuccess } = {}) => {
367
- try {
368
- setIsPending(true);
369
- setError(null);
370
- const response = await axios.post("/admin/membership-consents", data);
371
- if (onSuccess) {
372
- onSuccess();
373
- }
374
- return response.data;
375
- } catch (err) {
376
- const error2 = err instanceof Error ? err : new Error("Failed to create consent");
377
- setError(error2);
378
- throw error2;
379
- } finally {
380
- setIsPending(false);
381
- }
382
- };
383
- return {
384
- mutate,
385
- isPending,
386
- error
387
- };
388
- };
389
- const useDeleteMembershipConsent = () => {
390
- const [isPending, setIsPending] = useState(false);
391
- const [error, setError] = useState(null);
392
- const mutate = async (id, { onSuccess } = {}) => {
393
- try {
394
- setIsPending(true);
395
- setError(null);
396
- await axios.delete(`/admin/membership-consents/${id}`);
397
- if (onSuccess) {
398
- onSuccess();
399
- }
400
- } catch (err) {
401
- const error2 = err instanceof Error ? err : new Error("Failed to delete consent");
402
- setError(error2);
403
- throw error2;
404
- } finally {
405
- setIsPending(false);
406
- }
407
- };
408
- return {
409
- mutate,
410
- isPending,
411
- error
412
- };
413
- };
414
- const useMembershipConsents = () => {
415
- const [data, setData] = useState(void 0);
416
- const [isLoading, setIsLoading] = useState(true);
417
- const [error, setError] = useState(null);
418
- const fetchConsents = async () => {
419
- try {
420
- setIsLoading(true);
421
- setError(null);
422
- const response = await axios.get("/admin/membership-consents");
423
- setData(
424
- response.data
425
- );
426
- } catch (err) {
427
- setError(
428
- err instanceof Error ? err : new Error("Failed to fetch consents")
429
- );
430
- } finally {
431
- setIsLoading(false);
432
- }
433
- };
434
- useEffect(() => {
435
- fetchConsents();
436
- }, []);
437
- return {
438
- data,
439
- isLoading,
440
- error,
441
- refetch: fetchConsents
442
- };
443
- };
444
- const useUpdateMembershipConsent = () => {
445
- const [isPending, setIsPending] = useState(false);
446
- const [error, setError] = useState(null);
447
- const mutate = async (consentKey, { onSuccess } = {}) => {
448
- try {
449
- setIsPending(true);
450
- setError(null);
451
- const response = await axios.patch(
452
- `/admin/membership-consents/${consentKey.id}`,
453
- {
454
- name: consentKey.name,
455
- description: consentKey.description
456
- }
457
- );
458
- if (onSuccess) {
459
- onSuccess();
460
- }
461
- return response.data;
462
- } catch (err) {
463
- const error2 = err instanceof Error ? err : new Error("Failed to update consent");
464
- setError(error2);
465
- throw error2;
466
- } finally {
467
- setIsPending(false);
468
- }
469
- };
470
- return {
471
- mutate,
472
- isPending,
473
- error
474
- };
475
- };
476
- const columnHelper$1 = createDataTableColumnHelper();
477
- const columns$1 = [
478
- columnHelper$1.accessor("name", {
479
- header: "Name"
480
- }),
481
- columnHelper$1.accessor("description", {
482
- header: "Description",
483
- maxSize: 250
484
- })
485
- ];
486
- const MembershipConsentsRenderer = () => {
487
- const dialog = usePrompt();
488
- const [pagination, setPagination] = useState({
489
- pageSize: 1e3,
490
- pageIndex: 0
491
- });
492
- const [isDrawerOpen, setIsDrawerOpen] = useState(false);
493
- const [editingConsent, setEditingConsent] = useState(null);
494
- const [formData, setFormData] = useState({
495
- name: "",
496
- description: ""
497
- });
498
- const { data, isLoading, refetch } = useMembershipConsents();
499
- const createConsent = useCreateMembershipConsent();
500
- const updateConsent = useUpdateMembershipConsent();
501
- const deleteConsent = useDeleteMembershipConsent();
502
- const table = useDataTable({
503
- columns: columns$1,
504
- data: (data == null ? void 0 : data.consent_keys) || [],
505
- getRowId: (consent) => consent.id,
506
- rowCount: (data == null ? void 0 : data.count) || 0,
507
- isLoading,
508
- pagination: {
509
- state: pagination,
510
- onPaginationChange: setPagination
511
- },
512
- onRowClick: (_, row) => {
513
- openDrawer(row.original);
514
- }
515
- });
516
- const handleInputChange = (e) => {
517
- const { name, value } = e.target;
518
- setFormData((prev) => ({
519
- ...prev,
520
- [name]: name === "min_points" ? Number(value) : value
521
- }));
522
- };
523
- const handleTextAreaChange = (e) => {
524
- const { name, value } = e.target;
525
- setFormData((prev) => ({
526
- ...prev,
527
- [name]: value
528
- }));
529
- };
530
- const handleReset = () => {
531
- setFormData({
532
- name: "",
533
- description: ""
534
- });
535
- };
536
- const openDrawer = (consentKey) => {
537
- if (consentKey) {
538
- setEditingConsent(consentKey);
539
- setFormData({
540
- name: consentKey.name,
541
- description: consentKey.description
542
- });
543
- } else {
544
- setEditingConsent(null);
545
- handleReset();
546
- }
547
- setIsDrawerOpen(true);
548
- };
549
- const closeDrawer = () => {
550
- setIsDrawerOpen(false);
551
- setEditingConsent(null);
552
- handleReset();
553
- refetch();
554
- };
555
- const handleSubmit = async () => {
556
- var _a, _b;
557
- try {
558
- if (!formData.name) {
559
- toast.error("Name is required", { dismissable: true, duration: 2500 });
560
- return;
561
- }
562
- if (editingConsent) {
563
- await updateConsent.mutateAsync({ id: editingConsent.id, ...formData });
564
- toast.success("Consent updated successfully", {
565
- dismissable: true,
566
- duration: 2500
567
- });
568
- } else {
569
- await createConsent.mutateAsync(formData);
570
- toast.success("Consent created successfully", {
571
- dismissable: true,
572
- duration: 2500
573
- });
574
- }
575
- closeDrawer();
576
- } catch (error) {
577
- if (axios.isAxiosError(error)) {
578
- toast.error("Error saving consent", {
579
- description: (_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message,
580
- dismissable: true,
581
- duration: 2500
582
- });
583
- } else {
584
- toast.error("Error saving consent", {
585
- dismissable: true,
586
- duration: 2500
587
- });
588
- }
589
- }
590
- };
591
- const handleDelete = async (id) => {
592
- var _a, _b;
593
- try {
594
- const confirmed = await dialog({
595
- title: "Delete Membership Consent",
596
- description: `Are you sure you want to delete the \`${editingConsent == null ? void 0 : editingConsent.name}\` consent?`
597
- });
598
- if (!confirmed) {
599
- return;
600
- }
601
- await deleteConsent.mutateAsync(id);
602
- toast.success("Consent deleted successfully", {
603
- dismissable: true,
604
- duration: 2500
605
- });
606
- closeDrawer();
607
- } catch (error) {
608
- if (axios.isAxiosError(error)) {
609
- toast.error("Error deleting consent", {
610
- description: (_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message,
611
- dismissable: true,
612
- duration: 2500
613
- });
614
- } else {
615
- toast.error("Error deleting consent", {
616
- dismissable: true,
617
- duration: 2500
618
- });
619
- }
620
- }
621
- };
622
- return /* @__PURE__ */ jsxs(Fragment, { children: [
623
- /* @__PURE__ */ jsx(Container, { className: "flex flex-col p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
624
- /* @__PURE__ */ jsxs(DataTable.Toolbar, { className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center", children: [
625
- /* @__PURE__ */ jsx(Heading, { children: "Membership Consents" }),
626
- /* @__PURE__ */ jsx(Button, { onClick: () => openDrawer(), children: "Add Consent" })
627
- ] }),
628
- /* @__PURE__ */ jsx(DataTable.Table, {})
629
- ] }) }),
630
- /* @__PURE__ */ jsx(Drawer, { open: isDrawerOpen, onOpenChange: setIsDrawerOpen, children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
631
- /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: editingConsent ? "Edit Consent" : "Add Consent" }) }),
632
- /* @__PURE__ */ jsxs(Drawer.Body, { "aria-description": "Membership Consent Form", children: [
633
- /* @__PURE__ */ jsxs(
634
- "div",
635
- {
636
- className: "space-y-4",
637
- "aria-description": "Membership Consent Form",
638
- children: [
639
- /* @__PURE__ */ jsx(Text, { children: "Name" }),
640
- /* @__PURE__ */ jsx(
641
- Input,
642
- {
643
- name: "name",
644
- value: formData.name,
645
- onChange: handleInputChange
646
- }
647
- ),
648
- /* @__PURE__ */ jsx(Text, { children: "Description" }),
649
- /* @__PURE__ */ jsx(
650
- Textarea,
651
- {
652
- className: "truncate",
653
- name: "description",
654
- value: formData.description,
655
- onChange: handleTextAreaChange
656
- }
657
- )
658
- ]
659
- }
660
- ),
661
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 mt-6", children: [
662
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: closeDrawer, children: "Cancel" }),
663
- /* @__PURE__ */ jsx(Button, { onClick: handleSubmit, children: editingConsent ? "Update" : "Create" })
664
- ] })
665
- ] }),
666
- /* @__PURE__ */ jsx(Drawer.Footer, { className: "flex justify-start", children: editingConsent && /* @__PURE__ */ jsx(
667
- Button,
668
- {
669
- variant: "danger",
670
- onClick: () => {
671
- handleDelete(editingConsent.id);
672
- },
673
- children: "Delete"
674
- }
675
- ) })
676
- ] }) })
677
- ] });
678
- };
679
- const MembershipConsentPage = () => {
680
- return /* @__PURE__ */ jsx(MembershipConsentsRenderer, {});
681
- };
682
- const config$1 = defineRouteConfig({
683
- label: "Membership Consents"
684
- });
685
- const useCreateMembershipTier = () => {
686
- const [isPending, setIsPending] = useState(false);
687
- const [error, setError] = useState(null);
688
- const mutate = async (data, { onSuccess } = {}) => {
689
- try {
690
- setIsPending(true);
691
- setError(null);
692
- const response = await axios.post("/admin/member-tiers", data);
693
- if (onSuccess) {
694
- onSuccess();
695
- }
696
- return response.data;
697
- } catch (err) {
698
- const error2 = err instanceof Error ? err : new Error("Failed to create tier");
699
- setError(error2);
700
- throw error2;
701
- } finally {
702
- setIsPending(false);
703
- }
704
- };
705
- return {
706
- mutate,
707
- isPending,
708
- error
709
- };
710
- };
711
- const useDeleteMembershipTier = () => {
712
- const [isPending, setIsPending] = useState(false);
713
- const [error, setError] = useState(null);
714
- const mutate = async (id, { onSuccess } = {}) => {
715
- try {
716
- setIsPending(true);
717
- setError(null);
718
- await axios.delete(`/admin/member-tiers/${id}`);
719
- if (onSuccess) {
720
- onSuccess();
721
- }
722
- } catch (err) {
723
- const error2 = err instanceof Error ? err : new Error("Failed to delete tier");
724
- setError(error2);
725
- throw error2;
726
- } finally {
727
- setIsPending(false);
728
- }
729
- };
730
- return {
731
- mutate,
732
- isPending,
733
- error
734
- };
735
- };
736
- const useMembershipTiers = (params = {
737
- limit: 15,
738
- offset: 0,
739
- order: {
740
- min_points: "ASC"
741
- }
742
- }) => {
743
- var _a;
744
- const [data, setData] = useState(void 0);
745
- const [isLoading, setIsLoading] = useState(true);
746
- const [error, setError] = useState(null);
747
- const fetchTiers = async () => {
748
- try {
749
- setIsLoading(true);
750
- setError(null);
751
- const response = await axios.get("/admin/member-tiers", {
752
- params
753
- });
754
- setData(
755
- response.data
756
- );
757
- } catch (err) {
758
- setError(err instanceof Error ? err : new Error("Failed to fetch tiers"));
759
- } finally {
760
- setIsLoading(false);
761
- }
762
- };
763
- useEffect(() => {
764
- fetchTiers();
765
- }, [params.limit, params.offset, (_a = params.order) == null ? void 0 : _a.min_points]);
766
- return {
767
- data,
768
- isLoading,
769
- error,
770
- refetch: fetchTiers
771
- };
772
- };
773
- const useUpdateMembershipTier = () => {
774
- const [isPending, setIsPending] = useState(false);
775
- const [error, setError] = useState(null);
776
- const mutate = async (tier, { onSuccess } = {}) => {
777
- try {
778
- setIsPending(true);
779
- setError(null);
780
- const response = await axios.patch(`/admin/member-tiers/${tier.id}`, {
781
- name: tier.name,
782
- description: tier.description,
783
- privilege_description: tier.privilege_description,
784
- min_points: tier.min_points
785
- });
786
- if (onSuccess) {
787
- onSuccess();
788
- }
789
- return response.data;
790
- } catch (err) {
791
- const error2 = err instanceof Error ? err : new Error("Failed to update tier");
792
- setError(error2);
793
- throw error2;
794
- } finally {
795
- setIsPending(false);
796
- }
797
- };
798
- return {
799
- mutate,
800
- isPending,
801
- error
802
- };
803
- };
804
- const columnHelper = createDataTableColumnHelper();
805
- const columns = [
806
- columnHelper.accessor("min_points", {
807
- header: "Min Points"
808
- }),
809
- columnHelper.accessor("name", {
810
- header: "Name"
811
- }),
812
- columnHelper.accessor("description", {
813
- header: "Description",
814
- maxSize: 250
815
- }),
816
- columnHelper.accessor("privilege_description", {
817
- header: "Privilege Description",
818
- maxSize: 250
819
- })
820
- ];
821
- const MembershipTierRenderer = () => {
822
- const dialog = usePrompt();
823
- const [pagination, setPagination] = useState({
824
- pageSize: 1e3,
825
- pageIndex: 0
826
- });
827
- const [isDrawerOpen, setIsDrawerOpen] = useState(false);
828
- const [editingTier, setEditingTier] = useState(null);
829
- const [formData, setFormData] = useState({
830
- name: "",
831
- description: "",
832
- privilege_description: "",
833
- min_points: 0
834
- });
835
- const { data, isLoading, refetch } = useMembershipTiers({
836
- limit: pagination.pageSize,
837
- offset: pagination.pageIndex * pagination.pageSize
838
- });
839
- const createTier = useCreateMembershipTier();
840
- const updateTier = useUpdateMembershipTier();
841
- const deleteTier = useDeleteMembershipTier();
842
- const table = useDataTable({
843
- columns,
844
- data: (data == null ? void 0 : data.tiers) || [],
845
- getRowId: (tier) => tier.id,
846
- rowCount: (data == null ? void 0 : data.count) || 0,
847
- isLoading,
848
- pagination: {
849
- state: pagination,
850
- onPaginationChange: setPagination
851
- },
852
- onRowClick: (_, row) => {
853
- openDrawer(row.original);
854
- }
855
- });
856
- const handleInputChange = (e) => {
857
- const { name, value } = e.target;
858
- setFormData((prev) => ({
859
- ...prev,
860
- [name]: name === "min_points" ? Number(value) : value
861
- }));
862
- };
863
- const handleTextAreaChange = (e) => {
864
- const { name, value } = e.target;
865
- setFormData((prev) => ({
866
- ...prev,
867
- [name]: value
868
- }));
869
- };
870
- const handleReset = () => {
871
- setFormData({
872
- name: "",
873
- description: "",
874
- privilege_description: "",
875
- min_points: 0
876
- });
877
- };
878
- const openDrawer = (tier) => {
879
- if (tier) {
880
- setEditingTier(tier);
881
- setFormData({
882
- name: tier.name,
883
- description: tier.description,
884
- privilege_description: tier.privilege_description,
885
- min_points: tier.min_points
886
- });
887
- } else {
888
- setEditingTier(null);
889
- handleReset();
890
- }
891
- setIsDrawerOpen(true);
892
- };
893
- const closeDrawer = () => {
894
- setIsDrawerOpen(false);
895
- setEditingTier(null);
896
- handleReset();
897
- refetch();
898
- };
899
- const handleSubmit = async () => {
900
- var _a, _b;
901
- try {
902
- if (!formData.name) {
903
- toast.error("Name is required", { dismissable: true, duration: 2500 });
904
- return;
905
- }
906
- if (editingTier) {
907
- await updateTier.mutateAsync({ id: editingTier.id, ...formData });
908
- toast.success("Tier updated successfully", {
909
- dismissable: true,
910
- duration: 2500
911
- });
912
- } else {
913
- await createTier.mutateAsync(formData);
914
- toast.success("Tier created successfully", {
915
- dismissable: true,
916
- duration: 2500
917
- });
918
- }
919
- closeDrawer();
920
- } catch (error) {
921
- if (axios.isAxiosError(error)) {
922
- toast.error("Error saving tier", {
923
- description: (_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message,
924
- dismissable: true,
925
- duration: 2500
926
- });
927
- } else {
928
- toast.error("Error saving tier", {
929
- dismissable: true,
930
- duration: 2500
931
- });
932
- }
933
- }
934
- };
935
- const handleDelete = async (id) => {
936
- var _a, _b;
937
- try {
938
- const confirmed = await dialog({
939
- title: "Delete Membership Tier",
940
- description: `Are you sure you want to delete the \`${editingTier == null ? void 0 : editingTier.name}\` tier?`
941
- });
942
- if (!confirmed) {
943
- return;
944
- }
945
- await deleteTier.mutateAsync(id);
946
- toast.success("Tier deleted successfully", {
947
- dismissable: true,
948
- duration: 2500
949
- });
950
- closeDrawer();
951
- } catch (error) {
952
- if (axios.isAxiosError(error)) {
953
- toast.error("Error deleting tier", {
954
- description: (_b = (_a = error.response) == null ? void 0 : _a.data) == null ? void 0 : _b.message,
955
- dismissable: true,
956
- duration: 2500
957
- });
958
- } else {
959
- toast.error("Error deleting tier", {
960
- dismissable: true,
961
- duration: 2500
962
- });
963
- }
964
- }
965
- };
966
- return /* @__PURE__ */ jsxs(Fragment, { children: [
967
- /* @__PURE__ */ jsx(Container, { className: "flex flex-col p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
968
- /* @__PURE__ */ jsxs(DataTable.Toolbar, { className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center", children: [
969
- /* @__PURE__ */ jsx(Heading, { children: "Membership Tiers" }),
970
- /* @__PURE__ */ jsx(Button, { onClick: () => openDrawer(), children: "Add Tier" })
971
- ] }),
972
- /* @__PURE__ */ jsx(DataTable.Table, {})
973
- ] }) }),
974
- /* @__PURE__ */ jsx(Drawer, { open: isDrawerOpen, onOpenChange: setIsDrawerOpen, children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
975
- /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: editingTier ? "Edit Tier" : "Add Tier" }) }),
976
- /* @__PURE__ */ jsxs(Drawer.Body, { "aria-description": "Membership Tier Form", children: [
977
- /* @__PURE__ */ jsxs("div", { className: "space-y-4", "aria-description": "Membership Tier Form", children: [
978
- /* @__PURE__ */ jsx(Text, { children: "Name" }),
979
- /* @__PURE__ */ jsx(
980
- Input,
981
- {
982
- name: "name",
983
- value: formData.name,
984
- onChange: handleInputChange
985
- }
986
- ),
987
- /* @__PURE__ */ jsx(Text, { children: "Description" }),
988
- /* @__PURE__ */ jsx(
989
- Textarea,
990
- {
991
- className: "truncate",
992
- name: "description",
993
- value: formData.description,
994
- onChange: handleTextAreaChange
995
- }
996
- ),
997
- /* @__PURE__ */ jsx(Text, { children: "Privilege Description" }),
998
- /* @__PURE__ */ jsx(
999
- Textarea,
1000
- {
1001
- className: "truncate",
1002
- name: "privilege_description",
1003
- value: formData.privilege_description,
1004
- onChange: handleTextAreaChange
1005
- }
1006
- ),
1007
- /* @__PURE__ */ jsx(Text, { children: "Points" }),
1008
- /* @__PURE__ */ jsx(
1009
- Input,
1010
- {
1011
- name: "min_points",
1012
- type: "number",
1013
- value: formData.min_points,
1014
- onChange: handleInputChange
1015
- }
1016
- )
1017
- ] }),
1018
- /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 mt-6", children: [
1019
- /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: closeDrawer, children: "Cancel" }),
1020
- /* @__PURE__ */ jsx(Button, { onClick: handleSubmit, children: editingTier ? "Update" : "Create" })
1021
- ] })
1022
- ] }),
1023
- /* @__PURE__ */ jsx(Drawer.Footer, { className: "flex justify-start", children: editingTier && /* @__PURE__ */ jsx(
1024
- Button,
1025
- {
1026
- variant: "danger",
1027
- onClick: () => {
1028
- handleDelete(editingTier.id);
1029
- },
1030
- children: "Delete"
1031
- }
1032
- ) })
1033
- ] }) })
1034
- ] });
1035
- };
1036
- const MembershipTierPage = () => {
1037
- return /* @__PURE__ */ jsx(MembershipTierRenderer, {});
1038
- };
1039
- const config = defineRouteConfig({
1040
- label: "Membership Tiers"
1041
- });
1042
- const widgetModule = { widgets: [
1043
- {
1044
- Component: PromotionWidget,
1045
- zone: ["promotion.details.side.after"]
1046
- }
1047
- ] };
1048
- const routeModule = {
1049
- routes: [
1050
- {
1051
- Component: BannerUpload,
1052
- path: "/membership"
1053
- },
1054
- {
1055
- Component: MembershipConsentPage,
1056
- path: "/membership/member-consents"
1057
- },
1058
- {
1059
- Component: MembershipTierPage,
1060
- path: "/membership/membertier"
1061
- }
1062
- ]
1063
- };
1064
- const menuItemModule = {
1065
- menuItems: [
1066
- {
1067
- label: config$2.label,
1068
- icon: config$2.icon,
1069
- path: "/membership",
1070
- nested: void 0
1071
- },
1072
- {
1073
- label: config$1.label,
1074
- icon: void 0,
1075
- path: "/membership/member-consents",
1076
- nested: void 0
1077
- },
1078
- {
1079
- label: config.label,
1080
- icon: void 0,
1081
- path: "/membership/membertier",
1082
- nested: void 0
1083
- }
1084
- ]
1085
- };
1086
- const formModule = { customFields: {} };
1087
- const displayModule = {
1088
- displays: {}
1089
- };
1090
- const i18nModule = { resources: {} };
1091
- const plugin = {
1092
- widgetModule,
1093
- routeModule,
1094
- menuItemModule,
1095
- formModule,
1096
- displayModule,
1097
- i18nModule
1098
- };
1099
- export {
1100
- plugin as default
1101
- };