@mohasinac/appkit 4.12.3 → 4.13.0

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.
Files changed (63) hide show
  1. package/dist/_internal/server/features/brands/actions.js +7 -2
  2. package/dist/_internal/server/jobs/core/jobRunners.js +5 -0
  3. package/dist/_internal/server/jobs/core/onOrderCreate.js +33 -3
  4. package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +27 -0
  5. package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +172 -0
  6. package/dist/core/hooks/useSiteSettings.d.ts +1 -1
  7. package/dist/features/account/hooks/useAccount.d.ts +2 -2
  8. package/dist/features/account/hooks/useAddressSelector.d.ts +1 -1
  9. package/dist/features/account/hooks/useAddresses.d.ts +2 -2
  10. package/dist/features/account/hooks/useNotifications.d.ts +1 -1
  11. package/dist/features/account/hooks/useProfile.d.ts +1 -1
  12. package/dist/features/account/hooks/usePublicProfile.d.ts +2 -2
  13. package/dist/features/admin/hooks/useAdmin.d.ts +1 -1
  14. package/dist/features/admin/hooks/useAdminSectionsListing.d.ts +1 -1
  15. package/dist/features/admin/hooks/useChat.d.ts +1 -1
  16. package/dist/features/auctions/hooks/useAuctions.d.ts +8 -8
  17. package/dist/features/auth/hooks/useAuth.d.ts +2 -2
  18. package/dist/features/cart/hooks/useCart.d.ts +1 -1
  19. package/dist/features/cart/hooks/useCartQuery.d.ts +1 -1
  20. package/dist/features/cart/hooks/useCheckoutReadQueries.d.ts +2 -2
  21. package/dist/features/cart/hooks/useOrder.d.ts +2 -2
  22. package/dist/features/categories/hooks/useCategories.d.ts +3 -3
  23. package/dist/features/categories/hooks/useCategorySelector.d.ts +3 -3
  24. package/dist/features/categories/hooks/useCategoryTree.d.ts +1 -1
  25. package/dist/features/checkout/hooks/useCheckoutApi.d.ts +2 -2
  26. package/dist/features/collections/hooks/useCollections.d.ts +2 -2
  27. package/dist/features/events/hooks/useEvent.d.ts +3 -3
  28. package/dist/features/events/hooks/useEvents.d.ts +1 -1
  29. package/dist/features/faq/hooks/useFAQs.d.ts +1 -1
  30. package/dist/features/faq/hooks/useFaqList.d.ts +9 -15
  31. package/dist/features/homepage/hooks/useBlogArticles.d.ts +1 -1
  32. package/dist/features/homepage/hooks/useFeaturedAuctions.d.ts +1 -1
  33. package/dist/features/homepage/hooks/useFeaturedPreOrders.d.ts +1 -1
  34. package/dist/features/homepage/hooks/useFeaturedProducts.d.ts +1 -1
  35. package/dist/features/homepage/hooks/useFeaturedStores.d.ts +1 -1
  36. package/dist/features/homepage/hooks/useHeroCarousel.d.ts +1 -1
  37. package/dist/features/homepage/hooks/useHomepageEvents.d.ts +1 -1
  38. package/dist/features/homepage/hooks/useHomepageReviews.d.ts +1 -1
  39. package/dist/features/homepage/hooks/useHomepageSections.d.ts +1 -1
  40. package/dist/features/homepage/hooks/useTopBrands.d.ts +1 -1
  41. package/dist/features/homepage/hooks/useTopCategories.d.ts +1 -1
  42. package/dist/features/loyalty/hooks/useLoyaltyBalance.d.ts +1 -1
  43. package/dist/features/orders/hooks/useOrders.d.ts +2 -2
  44. package/dist/features/payments/hooks/usePayments.d.ts +1 -1
  45. package/dist/features/pre-orders/hooks/usePreOrders.d.ts +2 -2
  46. package/dist/features/products/hooks/useProductDetail.d.ts +1 -1
  47. package/dist/features/products/hooks/useRelatedProducts.d.ts +1 -1
  48. package/dist/features/promotions/hooks/usePromotions.d.ts +2 -2
  49. package/dist/features/reviews/hooks/useReviews.d.ts +2 -2
  50. package/dist/features/search/hooks/useSearch.d.ts +2 -2
  51. package/dist/features/seller/hooks/useSellerPayouts.d.ts +3 -3
  52. package/dist/features/seller/hooks/useSellerStore.d.ts +6 -6
  53. package/dist/features/seller/hooks/useSellerStorefront.d.ts +2 -2
  54. package/dist/features/shipments/hooks/useShipments.d.ts +7 -7
  55. package/dist/features/stores/hooks/useStoreAddressSelector.d.ts +1 -1
  56. package/dist/features/stores/hooks/useStores.d.ts +6 -6
  57. package/dist/features/tester/seed-data/tester-checklist-seed-data.js +128 -0
  58. package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +42 -14
  59. package/dist/features/wishlist/hooks/useUserWishlist.d.ts +9 -15
  60. package/dist/features/wishlist/hooks/useWishlist.d.ts +1 -1
  61. package/dist/features/wishlist/hooks/useWishlistWithGuest.d.ts +1 -1
  62. package/dist/seed/site-settings-seed-data.js +19 -1
  63. package/package.json +15 -12
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useApiMutation } from "@mohasinac/appkit/client";
3
+ import { useApiMutation, useBulkEvent, RTDB_PATHS } from "@mohasinac/appkit/client";
4
4
  import React from "react";
5
+ import { normalizeError } from "../../../errors/normalize";
5
6
  const __P = {
6
7
  p3: "p-[var(--appkit-space-3)]",
7
8
  };
@@ -136,19 +137,46 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
136
137
  showToast(msg, "error");
137
138
  },
138
139
  });
139
- // Catalog import mutation (pull: WhatsApp → site)
140
- const importMutation = useApiMutation({
141
- mutationFn: async () => apiClient.post(WHATSAPP_SELLER_ENDPOINTS.CATALOG_IMPORT, {}),
142
- onSuccess: (res) => {
143
- const r = res ?? {};
144
- showToast(`Imported ${r.imported ?? 0} product${(r.imported ?? 0) !== 1 ? "s" : ""} from WhatsApp (${r.skipped ?? 0} already synced)`, "success");
140
+ // Catalog import (pull: WhatsApp → site). Runs as the `whatsappCatalogImport`
141
+ // async job — the route only enqueues, so the result arrives over the
142
+ // useBulkEvent RTDB channel rather than in the POST response.
143
+ const bulkEvent = useBulkEvent({ rtdbPath: RTDB_PATHS.BULK_EVENTS });
144
+ const [importing, setImporting] = React.useState(false);
145
+ const startImport = async () => {
146
+ setImporting(true);
147
+ try {
148
+ const res = (await apiClient.post(WHATSAPP_SELLER_ENDPOINTS.CATALOG_IMPORT, {}));
149
+ const { jobId, customToken } = res.data ?? {};
150
+ if (jobId && customToken) {
151
+ bulkEvent.subscribe(jobId, customToken);
152
+ }
153
+ else {
154
+ setImporting(false);
155
+ showToast("Failed to start catalog import.", "error");
156
+ }
157
+ }
158
+ catch (err) {
159
+ void normalizeError(err);
160
+ setImporting(false);
161
+ showToast(err instanceof Error ? err.message : "Import failed", "error");
162
+ }
163
+ };
164
+ React.useEffect(() => {
165
+ if (bulkEvent.status === "success") {
166
+ setImporting(false);
167
+ const summary = bulkEvent.result?.summary;
168
+ const imported = summary?.succeeded ?? 0;
169
+ const skipped = summary?.skipped ?? 0;
170
+ showToast(`Imported ${imported} product${imported !== 1 ? "s" : ""} from WhatsApp (${skipped} already synced)`, "success");
145
171
  void queryClient.invalidateQueries({ queryKey: ["store", "whatsapp-settings"] });
146
- },
147
- onError: (err) => {
148
- const msg = err instanceof Error ? err.message : "Import failed";
149
- showToast(msg, "error");
150
- },
151
- });
172
+ void queryClient.invalidateQueries({ queryKey: ["store", "products"] });
173
+ }
174
+ else if (bulkEvent.status === "failed" || bulkEvent.status === "timeout") {
175
+ setImporting(false);
176
+ showToast(bulkEvent.error ?? "Catalog import failed.", "error");
177
+ }
178
+ // eslint-disable-next-line react-hooks/exhaustive-deps
179
+ }, [bulkEvent.status]);
152
180
  if (!hasCapability) {
153
181
  return (_jsx(Div, { className: "max-w-xl mx-auto", paddingY: "y-xl", paddingX: "x-md", children: _jsxs(Alert, { variant: "warning", children: [_jsx(Text, { weight: "medium", children: "WhatsApp catalog sync is not enabled for your store." }), _jsx(Text, { className: "mt-1", size: "sm", children: "Contact LetItRip support to request access to the WhatsApp Business integration." })] }) }));
154
182
  }
@@ -162,7 +190,7 @@ export function SellerWhatsAppSettingsView({ hasCapability }) {
162
190
  }) })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsx(Heading, { level: 2, size: "sm", weight: "semibold", color: "primary", children: "Connection" }), isLoading ? null : cfg?.connected ? (_jsx(Badge, { variant: "success", children: "Connected" })) : (_jsx(Badge, { variant: "default", children: "Not configured" }))] }), _jsxs(Form, { onSubmit: (e) => {
163
191
  e.preventDefault();
164
192
  saveMutation.mutate();
165
- }, spacing: "md", children: [_jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-4", color: "primary", size: "sm", weight: "semibold", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", color: "muted", children: "Enable catalog sync" }), _jsx(Text, { size: "xs", color: "muted", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { color: "muted", textSize: "xs", gap: "sm", align: "center", className: "mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "mb-3", color: "faint", size: "xs", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => importMutation.mutate(), isLoading: importMutation.isPending, disabled: !cfg?.connected || !syncEnabled || importMutation.isPending, variant: "secondary", children: importMutation.isPending ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [_jsx(Span, { weight: "bold", children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx(Span, { weight: "bold", children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-2", color: "primary", size: "sm", weight: "semibold", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "mb-3", color: "muted", size: "xs", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { textSize: "sm", className: "font-mono", color: "primary", surface: "muted", padding: "inline", rounded: "lg", children: buildPurchaseAnnouncementMessage({
193
+ }, spacing: "md", children: [_jsx(Input, { label: "WhatsApp Business Phone Number", value: phoneNumber, onChange: (e) => setPhoneNumber(e.target.value), placeholder: "919876543210", helperText: "Digits only, include country code (e.g. 91 for India)" }), _jsx(Input, { label: "WABA ID (WhatsApp Business Account ID)", value: wabaId, onChange: (e) => setWabaId(e.target.value), placeholder: "123456789012345", helperText: "From Meta Business Manager \u2192 WhatsApp Accounts" }), _jsx(Input, { label: "Catalog ID", value: catalogId, onChange: (e) => setCatalogId(e.target.value), placeholder: "987654321098765", helperText: "From Meta Commerce Manager \u2192 Catalogs" }), _jsx(MaskedTokenInput, { label: "System User Access Token", value: accessToken, onChange: setAccessToken, placeholder: "EAAxxxxxxxx\u2026", helperText: "Long-lived token with WhatsApp Business permissions" }), _jsx(FormActions, { align: "right", children: _jsx(Button, { type: "submit", isLoading: saveMutation.isPending, disabled: saveMutation.isPending, children: saveMutation.isPending ? "Saving…" : ACTIONS.STORE["whatsapp-connect"].label }) })] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-4", color: "primary", size: "sm", weight: "semibold", children: "Catalog Sync" }), _jsxs(Row, { justify: "between", align: "center", className: "mb-4", children: [_jsxs(Div, { children: [_jsx(Text, { size: "sm", color: "muted", children: "Enable catalog sync" }), _jsx(Text, { size: "xs", color: "muted", children: "When enabled, your published standard products can be synced to WhatsApp." })] }), _jsx(Toggle, { checked: syncEnabled, onChange: setSyncEnabled, disabled: !cfg?.connected })] }), cfg?.lastCatalogSyncAt && (_jsxs(Row, { color: "muted", textSize: "xs", gap: "sm", align: "center", className: "mb-3", children: [_jsxs(Text, { children: ["Last sync: ", new Date(cfg.lastCatalogSyncAt).toLocaleString("en-IN")] }), cfg.lastSyncCount !== undefined && _jsxs(Text, { children: ["\u00B7 ", cfg.lastSyncCount, " products"] }), cfg.lastSyncStatus && (_jsx(Badge, { variant: STATUS_VARIANT[cfg.lastSyncStatus] ?? "default", children: cfg.lastSyncStatus }))] })), _jsx(Text, { className: "mb-3", color: "faint", size: "xs", children: "Only published standard products are synced. Auctions and pre-orders are excluded. Batches of up to 50 products per call." }), _jsxs(Row, { gap: "3", children: [_jsx(Button, { onClick: () => syncMutation.mutate(), isLoading: syncMutation.isPending, disabled: !cfg?.connected || !syncEnabled || syncMutation.isPending, variant: "secondary", children: syncMutation.isPending ? "Syncing…" : ACTIONS.STORE["whatsapp-catalog-sync"].label }), _jsx(Button, { onClick: () => void startImport(), isLoading: importing, disabled: !cfg?.connected || !syncEnabled || importing, variant: "secondary", children: importing ? "Importing…" : ACTIONS.STORE["whatsapp-catalog-import"].label })] }), _jsxs(Text, { className: "mt-3", color: "faint", size: "xs", children: [_jsx(Span, { weight: "bold", children: "Push" }), " sends your published standard products to WhatsApp.", " ", _jsx(Span, { weight: "bold", children: "Import" }), " creates draft products from your WhatsApp catalog. Products are matched by slug in the description field."] })] }), _jsxs(Section, { className: CLS_SECTION_CARD, children: [_jsx(Heading, { level: 2, className: "mb-2", color: "primary", size: "sm", weight: "semibold", children: "Purchase Announcement Preview" }), _jsx(Text, { className: "mb-3", color: "muted", size: "xs", children: "This message is sent automatically to your phone and the platform admin when a new order is placed." }), _jsx(Div, { textSize: "sm", className: "font-mono", color: "primary", surface: "muted", padding: "inline", rounded: "lg", children: buildPurchaseAnnouncementMessage({
166
194
  buyerName: "Ravi K.",
167
195
  firstItemName: "Charizard PSA 9",
168
196
  additionalItemCount: 2,
@@ -18,7 +18,7 @@ interface UseUserWishlistOptions<TProduct> {
18
18
  }
19
19
  export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWishlistOptions<TProduct>): {
20
20
  total: number;
21
- data: NoInfer<UserWishlistResponse<TProduct>>;
21
+ data: UserWishlistResponse<TProduct>;
22
22
  error: Error;
23
23
  isError: true;
24
24
  isPending: false;
@@ -41,12 +41,11 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
41
41
  isRefetching: boolean;
42
42
  isStale: boolean;
43
43
  isEnabled: boolean;
44
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
44
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
45
45
  fetchStatus: import("@tanstack/query-core").FetchStatus;
46
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
47
46
  } | {
48
47
  total: number;
49
- data: NoInfer<UserWishlistResponse<TProduct>>;
48
+ data: UserWishlistResponse<TProduct>;
50
49
  error: null;
51
50
  isError: false;
52
51
  isPending: false;
@@ -69,9 +68,8 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
69
68
  isRefetching: boolean;
70
69
  isStale: boolean;
71
70
  isEnabled: boolean;
72
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
71
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
73
72
  fetchStatus: import("@tanstack/query-core").FetchStatus;
74
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
75
73
  } | {
76
74
  total: number;
77
75
  data: undefined;
@@ -97,9 +95,8 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
97
95
  isRefetching: boolean;
98
96
  isStale: boolean;
99
97
  isEnabled: boolean;
100
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
98
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
101
99
  fetchStatus: import("@tanstack/query-core").FetchStatus;
102
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
103
100
  } | {
104
101
  total: number;
105
102
  data: undefined;
@@ -125,9 +122,8 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
125
122
  isRefetching: boolean;
126
123
  isStale: boolean;
127
124
  isEnabled: boolean;
128
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
125
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
129
126
  fetchStatus: import("@tanstack/query-core").FetchStatus;
130
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
131
127
  } | {
132
128
  total: number;
133
129
  data: undefined;
@@ -153,12 +149,11 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
153
149
  isRefetching: boolean;
154
150
  isStale: boolean;
155
151
  isEnabled: boolean;
156
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
152
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
157
153
  fetchStatus: import("@tanstack/query-core").FetchStatus;
158
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
159
154
  } | {
160
155
  total: number;
161
- data: NoInfer<UserWishlistResponse<TProduct>>;
156
+ data: UserWishlistResponse<TProduct>;
162
157
  isError: false;
163
158
  error: null;
164
159
  isPending: false;
@@ -181,8 +176,7 @@ export declare function useUserWishlist<TProduct = unknown>(options?: UseUserWis
181
176
  isRefetching: boolean;
182
177
  isStale: boolean;
183
178
  isEnabled: boolean;
184
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<UserWishlistResponse<TProduct>>, Error>>;
179
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<UserWishlistResponse<TProduct>, Error>>;
185
180
  fetchStatus: import("@tanstack/query-core").FetchStatus;
186
- promise: Promise<NoInfer<UserWishlistResponse<TProduct>>>;
187
181
  };
188
182
  export {};
@@ -11,6 +11,6 @@ export declare function useWishlist(userId: string, opts?: UseWishlistOptions):
11
11
  isWishlisted: (productId: string) => boolean;
12
12
  isLoading: boolean;
13
13
  error: Error | null;
14
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<WishlistResponse>, Error>>;
14
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<WishlistResponse, Error>>;
15
15
  };
16
16
  export {};
@@ -17,7 +17,7 @@ export declare function useWishlistWithGuest(userId: string | null | undefined,
17
17
  isWishlisted: (productId: string) => boolean;
18
18
  isLoading: boolean;
19
19
  error: Error | null;
20
- refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<NoInfer<WishlistResponse>, Error>>;
20
+ refetch: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<WishlistResponse, Error>>;
21
21
  isGuest: boolean;
22
22
  guestWishlist?: undefined;
23
23
  } | {
@@ -523,9 +523,27 @@ export const siteSettingsSeedData = {
523
523
  razorpayWebhookSecret: "webhook_PLACEHOLDER",
524
524
  resendApiKey: "",
525
525
  whatsappApiKey: "wa_PLACEHOLDER",
526
+ // Real Meta secrets — deliberately left empty. With these unset the order
527
+ // announcement logs "not configured" and skips cleanly; a placeholder
528
+ // string here would instead be treated as a usable token and fail on send.
529
+ // Enter the real values in Admin → Site Settings → WhatsApp.
526
530
  whatsappPhoneNumberId: "",
527
531
  whatsappCloudApiToken: "",
528
- whatsappAdminNotifyNumbers: "",
532
+ // The platform's own WhatsApp number, digits-only with country code
533
+ // (+91 8919665811). Same number as contact.whatsappNumber above.
534
+ whatsappAdminNotifyNumbers: "918919665811",
535
+ // Default Meta message-template names. These MUST be created and approved
536
+ // in Meta Business Manager under exactly these names — business-initiated
537
+ // sends outside the 24h customer-service window are rejected without an
538
+ // approved template. Names match the notification types they serve, see
539
+ // WHATSAPP_TEMPLATE_BY_TYPE in features/admin/actions/notification-actions.ts.
540
+ whatsappTemplateOrderPlaced: "order_placed",
541
+ whatsappTemplateOrderConfirmed: "order_confirmed",
542
+ whatsappTemplateOrderShipped: "order_shipped",
543
+ whatsappTemplateOrderDelivered: "order_delivered",
544
+ whatsappTemplateOrderCancelled: "order_cancelled",
545
+ whatsappTemplateRefundInitiated: "refund_initiated",
546
+ whatsappTemplateLanguage: "en",
529
547
  metaAppId: "meta_app_PLACEHOLDER",
530
548
  metaAppSecret: "meta_secret_PLACEHOLDER",
531
549
  metaPageAccessToken: "meta_page_token_PLACEHOLDER",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mohasinac/appkit",
3
- "version": "4.12.3",
3
+ "version": "4.13.0",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -174,7 +174,7 @@
174
174
  "@mohasinac/sievejs": "^1.0.0",
175
175
  "driver.js": "^1.8.0",
176
176
  "jsbarcode": "^3.12.3",
177
- "motion": "^12.40.0",
177
+ "motion": "^13.1.1",
178
178
  "react-advanced-cropper": "^0.20.1",
179
179
  "tailwind-merge": "^3.3.0",
180
180
  "zod": "^3.24.0",
@@ -184,8 +184,8 @@
184
184
  "@tanstack/react-query": ">=5.0.0",
185
185
  "@types/react": ">=18",
186
186
  "@types/react-dom": ">=18",
187
- "firebase-admin": "^13.6.1",
188
- "firebase-functions": ">=6.0.0",
187
+ "firebase-admin": "^14.3.0",
188
+ "firebase-functions": "^7.3.2",
189
189
  "next": ">=14",
190
190
  "next-intl": ">=3",
191
191
  "razorpay": ">=2.9.0",
@@ -214,7 +214,7 @@
214
214
  "devDependencies": {
215
215
  "@tailwindcss/cli": "^4.3.3",
216
216
  "@tanstack/react-query": "^5.0.0",
217
- "@testing-library/jest-dom": "^6.9.1",
217
+ "@testing-library/jest-dom": "^7.0.1",
218
218
  "@testing-library/react": "^16.3.2",
219
219
  "@types/babel__generator": "^7.27.0",
220
220
  "@types/babel__template": "^7.4.4",
@@ -227,13 +227,13 @@
227
227
  "@types/yargs-parser": "^21.0.3",
228
228
  "@upstash/ratelimit": "^2.0.8",
229
229
  "@upstash/redis": "^1.37.0",
230
- "concurrently": "^9.2.1",
231
- "eslint": "^9.37.0",
232
- "firebase": "^12.8.0",
233
- "firebase-admin": "^13.6.1",
234
- "firebase-functions": "^6.6.0",
230
+ "concurrently": "^10.0.5",
231
+ "eslint": "^10.9.0",
232
+ "firebase": "^12.18.0",
233
+ "firebase-admin": "^14.3.0",
234
+ "firebase-functions": "^7.3.2",
235
235
  "jsdom": "^29.1.1",
236
- "lucide-react": "^1.7.0",
236
+ "lucide-react": "^1.33.0",
237
237
  "next": "^15.0.0",
238
238
  "next-intl": "^4.9.1",
239
239
  "razorpay": "^2.9.6",
@@ -243,6 +243,9 @@
243
243
  "server-only": "^0.0.1",
244
244
  "tailwindcss": "^4.3.3",
245
245
  "typescript": "^5.9.3",
246
- "vitest": "^4.1.7"
246
+ "vitest": "^4.1.11"
247
+ },
248
+ "engines": {
249
+ "node": ">=22"
247
250
  }
248
251
  }