@mohasinac/appkit 2.7.17 → 2.7.19
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/_internal/server/features/bundles/actions.d.ts +15 -0
- package/dist/_internal/server/features/bundles/actions.js +48 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -0
- package/dist/_internal/server/features/bundles/index.js +1 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +4 -0
- package/dist/_internal/server/features/checkout/actions.js +23 -12
- package/dist/_internal/server/features/payments/data.d.ts +5 -3
- package/dist/_internal/server/features/payments/data.js +13 -8
- package/dist/_internal/server/features/payments/index.d.ts +1 -1
- package/dist/_internal/server/features/payments/index.js +1 -1
- package/dist/_internal/server/features/seo/manifest.js +9 -3
- package/dist/_internal/shared/features/categories/bundle-config.d.ts +24 -0
- package/dist/_internal/shared/features/categories/bundle-config.js +28 -0
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +7 -0
- package/dist/_internal/shared/features/categories/bundle-copy.js +9 -0
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +69 -19
- package/dist/_internal/shared/features/categories/bundle-schemas.js +20 -2
- package/dist/_internal/shared/features/checkout/config.d.ts +1 -1
- package/dist/_internal/shared/features/checkout/config.js +1 -1
- package/dist/_internal/shared/features/payments/config.d.ts +2 -1
- package/dist/_internal/shared/features/payments/config.js +2 -1
- package/dist/_internal/shared/features/products/schema.d.ts +8 -8
- package/dist/constants/field-names.d.ts +8 -1
- package/dist/constants/field-names.js +9 -2
- package/dist/constants/table-keys.d.ts +3 -0
- package/dist/constants/table-keys.js +3 -0
- package/dist/features/admin/components/AdminSiteSettingsView.js +17 -15
- package/dist/features/admin/components/DashboardStats.js +20 -12
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +18 -2
- package/dist/features/admin/components/analytics/AdminStatCard.d.ts +7 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +13 -2
- package/dist/features/admin/schemas/firestore.d.ts +39 -4
- package/dist/features/admin/schemas/firestore.js +14 -1
- package/dist/features/categories/components/BundleBuyNowCta.d.ts +3 -1
- package/dist/features/categories/components/BundleBuyNowCta.js +3 -3
- package/dist/features/categories/components/BundleDynamicRuleEditor.d.ts +1 -1
- package/dist/features/categories/components/BundleDynamicRuleEditor.js +2 -1
- package/dist/features/categories/components/BundlesListView.d.ts +4 -1
- package/dist/features/categories/components/BundlesListView.js +2 -2
- package/dist/features/categories/components/CategoryBundlesListing.d.ts +4 -1
- package/dist/features/categories/components/CategoryBundlesListing.js +9 -8
- package/dist/features/categories/schemas/firestore.d.ts +29 -1
- package/dist/features/checkout/actions/checkout-actions.d.ts +11 -0
- package/dist/features/checkout/actions/checkout-actions.js +26 -0
- package/dist/features/filters/FilterFacetSection.d.ts +6 -1
- package/dist/features/filters/FilterFacetSection.js +25 -2
- package/dist/features/homepage/components/FeaturedBundlesSection.d.ts +4 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +9 -8
- package/dist/features/orders/actions/refund-actions.js +10 -7
- package/dist/features/orders/schemas/firestore.d.ts +16 -13
- package/dist/features/orders/schemas/firestore.js +6 -5
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +1 -1
- package/dist/features/pre-orders/components/PreOrdersIndexListing.js +2 -1
- package/dist/features/products/components/AuctionsIndexListing.js +2 -1
- package/dist/features/products/components/ProductDetailPageView.js +3 -1
- package/dist/features/products/components/ProductDetailView.d.ts +3 -1
- package/dist/features/products/components/ProductDetailView.js +2 -2
- package/dist/features/products/components/ProductFilters.d.ts +10 -4
- package/dist/features/products/components/ProductFilters.js +20 -16
- package/dist/features/products/components/ProductGrid.js +2 -2
- package/dist/features/products/components/ProductsIndexListing.js +2 -1
- package/dist/features/products/constants/action-defs.d.ts +64 -22
- package/dist/features/products/constants/action-defs.js +101 -64
- package/dist/features/products/constants/product-features.constants.js +5 -1
- package/dist/features/products/schemas/index.d.ts +2 -2
- package/dist/features/products/schemas/product-features.d.ts +1 -1
- package/dist/features/products/schemas/product-features.validators.d.ts +10 -10
- package/dist/features/products/schemas/product-features.validators.js +4 -0
- package/dist/features/seller/components/SellerCouponEditorView.js +2 -2
- package/dist/features/seller/components/analytics/SellerAnalyticsStats.js +10 -4
- package/dist/features/stores/components/StoreBundlesPageView.d.ts +4 -1
- package/dist/features/stores/components/StoreBundlesPageView.js +2 -2
- package/dist/features/stores/components/StoresIndexListing.js +2 -1
- package/dist/providers/db-firebase/admin-app-lite.js +8 -2
- package/dist/providers/db-firebase/admin.js +8 -2
- package/dist/seed/addresses-seed-data.js +24 -7
- package/dist/seed/cart-seed-data.d.ts +10 -10
- package/dist/seed/cart-seed-data.js +39 -2
- package/dist/seed/grouped-listings-seed-data.js +47 -0
- package/dist/seed/orders-seed-data.js +150 -0
- package/dist/seed/products-standard-seed-data.js +42 -0
- package/dist/seed/site-settings-seed-data.js +14 -4
- package/dist/seed/users-seed-data.js +1 -1
- package/dist/seed/wishlists-seed-data.js +7 -0
- package/dist/server-entry.d.ts +2 -1
- package/dist/server-entry.js +2 -1
- package/dist/server.d.ts +2 -1
- package/dist/server.js +3 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/SideDrawer.style.css +49 -11
- package/package.json +1 -1
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* action-defs.ts
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Universal CTA registry for the entire platform.
|
|
5
|
+
* Every action — public marketplace CTAs, dashboard row actions, quick actions — is
|
|
6
|
+
* registered here with auth requirements, RBAC permissions, and enable/disable defaults.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* Dashboard quick bar — top-level shortcut buttons per dashboard type
|
|
12
|
-
*
|
|
13
|
-
* Pure TypeScript — no React, no JSX, no callbacks.
|
|
14
|
-
* Consuming components resolve iconName → Lucide component, and supply onClick.
|
|
8
|
+
* Three enforcement layers read from this registry:
|
|
9
|
+
* Client — useAuthGate() shows LoginRequiredModal for Tier 1 (public) actions
|
|
10
|
+
* Server — checkActionAllowed() enforces the same guards on every server action
|
|
11
|
+
* Admin — ActionPermissionsManager toggles defaultEnabled via siteSettings.actionConfig
|
|
15
12
|
*/
|
|
16
13
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
17
14
|
// § 1 Product / listing actions
|
|
@@ -30,23 +27,73 @@ export const ACTION_ID = {
|
|
|
30
27
|
PLACE_BID: "place-bid",
|
|
31
28
|
BUY_NOW_AUCTION: "buy-now-auction",
|
|
32
29
|
WATCH_AUCTION: "watch-auction",
|
|
30
|
+
UNWATCH_AUCTION: "unwatch-auction",
|
|
33
31
|
// Pre-order
|
|
34
32
|
RESERVE_NOW: "reserve-now",
|
|
35
33
|
CANCEL_RESERVATION: "cancel-reservation",
|
|
34
|
+
// ── Checkout / navigation CTAs ───────────────────────────────────────────
|
|
35
|
+
CHECKOUT: "checkout",
|
|
36
|
+
ENTER_PRIZE_DRAW: "enter-prize-draw",
|
|
37
|
+
ENTER_RAFFLE: "enter-raffle",
|
|
38
|
+
REPORT_LISTING: "report-listing",
|
|
39
|
+
FOLLOW_STORE: "follow-store",
|
|
40
|
+
// ── Reviews & social ─────────────────────────────────────────────────────
|
|
41
|
+
WRITE_REVIEW: "write-review",
|
|
42
|
+
MESSAGE_SELLER: "message-seller",
|
|
43
|
+
// ── Seller (public-facing CTAs on store/product pages) ───────────────────
|
|
44
|
+
BECOME_SELLER: "become-seller",
|
|
45
|
+
REQUEST_PAYOUT: "request-payout",
|
|
46
|
+
RESPOND_TO_REVIEW: "respond-to-review",
|
|
47
|
+
// ── User account actions ─────────────────────────────────────────────────
|
|
48
|
+
CANCEL_ORDER: "cancel-order",
|
|
49
|
+
REQUEST_RETURN: "request-return",
|
|
50
|
+
REORDER: "reorder",
|
|
51
|
+
TRACK_ORDER: "track-order",
|
|
52
|
+
EDIT_PROFILE: "edit-profile",
|
|
53
|
+
ADD_ADDRESS: "add-address",
|
|
54
|
+
EDIT_ADDRESS: "edit-address",
|
|
55
|
+
DELETE_ADDRESS: "delete-address",
|
|
56
|
+
CHANGE_PASSWORD: "change-password",
|
|
57
|
+
DELETE_ACCOUNT: "delete-account",
|
|
36
58
|
};
|
|
37
59
|
export const ACTION_META = {
|
|
38
|
-
[ACTION_ID.BUY_NOW]: { id: ACTION_ID.BUY_NOW, label: "Buy Now", variant: "primary" },
|
|
60
|
+
[ACTION_ID.BUY_NOW]: { id: ACTION_ID.BUY_NOW, label: "Buy Now", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
|
|
39
61
|
[ACTION_ID.ADD_TO_CART]: { id: ACTION_ID.ADD_TO_CART, label: "Add to Cart", variant: "secondary", iconName: "ShoppingCart" },
|
|
40
|
-
[ACTION_ID.ADD_TO_WISHLIST]: { id: ACTION_ID.ADD_TO_WISHLIST, label: "Add to Wishlist", variant: "ghost", iconName: "Heart" },
|
|
41
|
-
[ACTION_ID.REMOVE_FROM_WISHLIST]: { id: ACTION_ID.REMOVE_FROM_WISHLIST, label: "Remove from Wishlist", variant: "ghost", iconName: "HeartOff" },
|
|
42
|
-
[ACTION_ID.MAKE_OFFER]: { id: ACTION_ID.MAKE_OFFER, label: "Make an Offer", variant: "outline", iconName: "Tag", requiresAuth: true },
|
|
62
|
+
[ACTION_ID.ADD_TO_WISHLIST]: { id: ACTION_ID.ADD_TO_WISHLIST, label: "Add to Wishlist", variant: "ghost", iconName: "Heart", requiresAuth: true, authMessage: "You need to be signed in to save items to your wishlist." },
|
|
63
|
+
[ACTION_ID.REMOVE_FROM_WISHLIST]: { id: ACTION_ID.REMOVE_FROM_WISHLIST, label: "Remove from Wishlist", variant: "ghost", iconName: "HeartOff", requiresAuth: true, authMessage: "You need to be signed in to manage your wishlist." },
|
|
64
|
+
[ACTION_ID.MAKE_OFFER]: { id: ACTION_ID.MAKE_OFFER, label: "Make an Offer", variant: "outline", iconName: "Tag", requiresAuth: true, authMessage: "You need to be signed in to make an offer." },
|
|
43
65
|
[ACTION_ID.SHARE]: { id: ACTION_ID.SHARE, label: "Share", variant: "ghost", iconName: "Share2" },
|
|
44
66
|
[ACTION_ID.COMPARE]: { id: ACTION_ID.COMPARE, label: "Compare", variant: "secondary", iconName: "Columns" },
|
|
45
|
-
[ACTION_ID.PLACE_BID]: { id: ACTION_ID.PLACE_BID, label: "Place Bid", variant: "primary", requiresAuth: true },
|
|
46
|
-
[ACTION_ID.BUY_NOW_AUCTION]: { id: ACTION_ID.BUY_NOW_AUCTION, label: "Buy Now", variant: "secondary", requiresAuth: true },
|
|
47
|
-
[ACTION_ID.WATCH_AUCTION]: { id: ACTION_ID.WATCH_AUCTION, label: "Watch", variant: "ghost", iconName: "Eye" },
|
|
48
|
-
[ACTION_ID.
|
|
49
|
-
[ACTION_ID.
|
|
67
|
+
[ACTION_ID.PLACE_BID]: { id: ACTION_ID.PLACE_BID, label: "Place Bid", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to place a bid." },
|
|
68
|
+
[ACTION_ID.BUY_NOW_AUCTION]: { id: ACTION_ID.BUY_NOW_AUCTION, label: "Buy Now", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to purchase items." },
|
|
69
|
+
[ACTION_ID.WATCH_AUCTION]: { id: ACTION_ID.WATCH_AUCTION, label: "Watch", variant: "ghost", iconName: "Eye", requiresAuth: true, authMessage: "You need to be signed in to watch auctions." },
|
|
70
|
+
[ACTION_ID.UNWATCH_AUCTION]: { id: ACTION_ID.UNWATCH_AUCTION, label: "Unwatch", variant: "ghost", iconName: "EyeOff", requiresAuth: true, authMessage: "You need to be signed in to manage your watchlist." },
|
|
71
|
+
[ACTION_ID.RESERVE_NOW]: { id: ACTION_ID.RESERVE_NOW, label: "Reserve Now", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to reserve a pre-order." },
|
|
72
|
+
[ACTION_ID.CANCEL_RESERVATION]: { id: ACTION_ID.CANCEL_RESERVATION, label: "Cancel Reservation", variant: "danger", iconName: "X", requiresAuth: true, authMessage: "You need to be signed in to cancel a reservation." },
|
|
73
|
+
// ── Checkout / navigation CTAs ────────────────────────────────────────────
|
|
74
|
+
[ACTION_ID.CHECKOUT]: { id: ACTION_ID.CHECKOUT, label: "Checkout", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to checkout." },
|
|
75
|
+
[ACTION_ID.ENTER_PRIZE_DRAW]: { id: ACTION_ID.ENTER_PRIZE_DRAW, label: "Enter Draw", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a prize draw." },
|
|
76
|
+
[ACTION_ID.ENTER_RAFFLE]: { id: ACTION_ID.ENTER_RAFFLE, label: "Enter Raffle", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to enter a raffle." },
|
|
77
|
+
[ACTION_ID.REPORT_LISTING]: { id: ACTION_ID.REPORT_LISTING, label: "Report Listing", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to report a listing." },
|
|
78
|
+
[ACTION_ID.FOLLOW_STORE]: { id: ACTION_ID.FOLLOW_STORE, label: "Follow Store", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to follow a store." },
|
|
79
|
+
// ── Reviews & social ──────────────────────────────────────────────────────
|
|
80
|
+
[ACTION_ID.WRITE_REVIEW]: { id: ACTION_ID.WRITE_REVIEW, label: "Write a Review", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to write a review." },
|
|
81
|
+
[ACTION_ID.MESSAGE_SELLER]: { id: ACTION_ID.MESSAGE_SELLER, label: "Message Seller", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to message a seller." },
|
|
82
|
+
// ── Seller CTAs ───────────────────────────────────────────────────────────
|
|
83
|
+
[ACTION_ID.BECOME_SELLER]: { id: ACTION_ID.BECOME_SELLER, label: "Apply as Seller", variant: "primary", requiresAuth: true, authMessage: "You need to be signed in to apply as a seller." },
|
|
84
|
+
[ACTION_ID.REQUEST_PAYOUT]: { id: ACTION_ID.REQUEST_PAYOUT, label: "Request Payout", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a payout.", requiredPermission: "seller.payouts.request" },
|
|
85
|
+
[ACTION_ID.RESPOND_TO_REVIEW]: { id: ACTION_ID.RESPOND_TO_REVIEW, label: "Respond to Review", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to respond to a review.", requiredPermission: "seller.reviews.respond" },
|
|
86
|
+
// ── User account actions ──────────────────────────────────────────────────
|
|
87
|
+
[ACTION_ID.CANCEL_ORDER]: { id: ACTION_ID.CANCEL_ORDER, label: "Cancel Order", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to cancel an order." },
|
|
88
|
+
[ACTION_ID.REQUEST_RETURN]: { id: ACTION_ID.REQUEST_RETURN, label: "Request Return", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to request a return." },
|
|
89
|
+
[ACTION_ID.REORDER]: { id: ACTION_ID.REORDER, label: "Reorder", variant: "secondary", requiresAuth: true, authMessage: "You need to be signed in to reorder." },
|
|
90
|
+
[ACTION_ID.TRACK_ORDER]: { id: ACTION_ID.TRACK_ORDER, label: "Track Order", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to track your order." },
|
|
91
|
+
[ACTION_ID.EDIT_PROFILE]: { id: ACTION_ID.EDIT_PROFILE, label: "Edit Profile", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to edit your profile." },
|
|
92
|
+
[ACTION_ID.ADD_ADDRESS]: { id: ACTION_ID.ADD_ADDRESS, label: "Add Address", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to add an address." },
|
|
93
|
+
[ACTION_ID.EDIT_ADDRESS]: { id: ACTION_ID.EDIT_ADDRESS, label: "Edit Address", variant: "ghost", requiresAuth: true, authMessage: "You need to be signed in to edit an address." },
|
|
94
|
+
[ACTION_ID.DELETE_ADDRESS]: { id: ACTION_ID.DELETE_ADDRESS, label: "Delete Address", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to delete an address." },
|
|
95
|
+
[ACTION_ID.CHANGE_PASSWORD]: { id: ACTION_ID.CHANGE_PASSWORD, label: "Change Password", variant: "outline", requiresAuth: true, authMessage: "You need to be signed in to change your password." },
|
|
96
|
+
[ACTION_ID.DELETE_ACCOUNT]: { id: ACTION_ID.DELETE_ACCOUNT, label: "Delete Account", variant: "danger", requiresAuth: true, authMessage: "You need to be signed in to delete your account.", requiredPermission: "user.account.delete" },
|
|
50
97
|
};
|
|
51
98
|
// Detail page action groups — ordered top-to-bottom in the right-hand panel
|
|
52
99
|
export const DETAIL_ACTIONS = {
|
|
@@ -66,7 +113,7 @@ export const MOBILE_PRIMARY_ACTIONS = {
|
|
|
66
113
|
// Listing page bulk actions — shown in BulkActionsBar when items are selected
|
|
67
114
|
export const LISTING_BULK_ACTIONS = {
|
|
68
115
|
products: [ACTION_ID.ADD_TO_CART, ACTION_ID.ADD_TO_WISHLIST, ACTION_ID.COMPARE],
|
|
69
|
-
auctions: [ACTION_ID.WATCH_AUCTION, ACTION_ID.
|
|
116
|
+
auctions: [ACTION_ID.WATCH_AUCTION, ACTION_ID.UNWATCH_AUCTION, ACTION_ID.COMPARE],
|
|
70
117
|
preorders: [ACTION_ID.ADD_TO_CART, ACTION_ID.ADD_TO_WISHLIST, ACTION_ID.COMPARE],
|
|
71
118
|
stores: [ACTION_ID.COMPARE],
|
|
72
119
|
};
|
|
@@ -96,23 +143,23 @@ export const ROW_ACTION_ID = {
|
|
|
96
143
|
ARCHIVE: "row-archive",
|
|
97
144
|
};
|
|
98
145
|
export const ROW_ACTION_META = {
|
|
99
|
-
[ROW_ACTION_ID.EDIT]: { id: ROW_ACTION_ID.EDIT, label: "Edit", iconName: "Pencil" },
|
|
100
|
-
[ROW_ACTION_ID.VIEW]: { id: ROW_ACTION_ID.VIEW, label: "View", iconName: "Eye" },
|
|
101
|
-
[ROW_ACTION_ID.DELETE]: { id: ROW_ACTION_ID.DELETE, label: "Delete", iconName: "Trash2", destructive: true, separator: true },
|
|
102
|
-
[ROW_ACTION_ID.APPROVE]: { id: ROW_ACTION_ID.APPROVE, label: "Approve", iconName: "Check" },
|
|
103
|
-
[ROW_ACTION_ID.REJECT]: { id: ROW_ACTION_ID.REJECT, label: "Reject", iconName: "X", destructive: true },
|
|
104
|
-
[ROW_ACTION_ID.SUSPEND]: { id: ROW_ACTION_ID.SUSPEND, label: "Suspend", iconName: "Ban", destructive: true, separator: true },
|
|
105
|
-
[ROW_ACTION_ID.RESTORE]: { id: ROW_ACTION_ID.RESTORE, label: "Restore", iconName: "RotateCcw" },
|
|
106
|
-
[ROW_ACTION_ID.MANAGE]: { id: ROW_ACTION_ID.MANAGE, label: "Manage", iconName: "Settings" },
|
|
107
|
-
[ROW_ACTION_ID.DUPLICATE]: { id: ROW_ACTION_ID.DUPLICATE, label: "Duplicate", iconName: "Copy" },
|
|
108
|
-
[ROW_ACTION_ID.EXPORT]: { id: ROW_ACTION_ID.EXPORT, label: "Export", iconName: "Download" },
|
|
109
|
-
[ROW_ACTION_ID.TRACK]: { id: ROW_ACTION_ID.TRACK, label: "Track Shipment", iconName: "Truck" },
|
|
110
|
-
[ROW_ACTION_ID.CANCEL]: { id: ROW_ACTION_ID.CANCEL, label: "Cancel", iconName: "X", destructive: true },
|
|
111
|
-
[ROW_ACTION_ID.REFUND]: { id: ROW_ACTION_ID.REFUND, label: "Refund", iconName: "RefreshCw", destructive: true, separator: true },
|
|
112
|
-
[ROW_ACTION_ID.RESEND]: { id: ROW_ACTION_ID.RESEND, label: "Resend", iconName: "Send" },
|
|
113
|
-
[ROW_ACTION_ID.REPLY]: { id: ROW_ACTION_ID.REPLY, label: "Reply", iconName: "MessageSquare" },
|
|
114
|
-
[ROW_ACTION_ID.PUBLISH]: { id: ROW_ACTION_ID.PUBLISH, label: "Publish", iconName: "Upload" },
|
|
115
|
-
[ROW_ACTION_ID.ARCHIVE]: { id: ROW_ACTION_ID.ARCHIVE, label: "Archive", iconName: "Archive", separator: true },
|
|
146
|
+
[ROW_ACTION_ID.EDIT]: { id: ROW_ACTION_ID.EDIT, label: "Edit", iconName: "Pencil", requiresAuth: true },
|
|
147
|
+
[ROW_ACTION_ID.VIEW]: { id: ROW_ACTION_ID.VIEW, label: "View", iconName: "Eye", requiresAuth: true },
|
|
148
|
+
[ROW_ACTION_ID.DELETE]: { id: ROW_ACTION_ID.DELETE, label: "Delete", iconName: "Trash2", requiresAuth: true, destructive: true, separator: true },
|
|
149
|
+
[ROW_ACTION_ID.APPROVE]: { id: ROW_ACTION_ID.APPROVE, label: "Approve", iconName: "Check", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.content.approve" },
|
|
150
|
+
[ROW_ACTION_ID.REJECT]: { id: ROW_ACTION_ID.REJECT, label: "Reject", iconName: "X", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.content.approve", destructive: true },
|
|
151
|
+
[ROW_ACTION_ID.SUSPEND]: { id: ROW_ACTION_ID.SUSPEND, label: "Suspend", iconName: "Ban", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.users.suspend", destructive: true, separator: true },
|
|
152
|
+
[ROW_ACTION_ID.RESTORE]: { id: ROW_ACTION_ID.RESTORE, label: "Restore", iconName: "RotateCcw", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.users.suspend" },
|
|
153
|
+
[ROW_ACTION_ID.MANAGE]: { id: ROW_ACTION_ID.MANAGE, label: "Manage", iconName: "Settings", requiresAuth: true },
|
|
154
|
+
[ROW_ACTION_ID.DUPLICATE]: { id: ROW_ACTION_ID.DUPLICATE, label: "Duplicate", iconName: "Copy", requiresAuth: true },
|
|
155
|
+
[ROW_ACTION_ID.EXPORT]: { id: ROW_ACTION_ID.EXPORT, label: "Export", iconName: "Download", requiresAuth: true },
|
|
156
|
+
[ROW_ACTION_ID.TRACK]: { id: ROW_ACTION_ID.TRACK, label: "Track Shipment", iconName: "Truck", requiresAuth: true },
|
|
157
|
+
[ROW_ACTION_ID.CANCEL]: { id: ROW_ACTION_ID.CANCEL, label: "Cancel", iconName: "X", requiresAuth: true, destructive: true },
|
|
158
|
+
[ROW_ACTION_ID.REFUND]: { id: ROW_ACTION_ID.REFUND, label: "Refund", iconName: "RefreshCw", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.orders.refund", destructive: true, separator: true },
|
|
159
|
+
[ROW_ACTION_ID.RESEND]: { id: ROW_ACTION_ID.RESEND, label: "Resend", iconName: "Send", requiresAuth: true },
|
|
160
|
+
[ROW_ACTION_ID.REPLY]: { id: ROW_ACTION_ID.REPLY, label: "Reply", iconName: "MessageSquare", requiresAuth: true },
|
|
161
|
+
[ROW_ACTION_ID.PUBLISH]: { id: ROW_ACTION_ID.PUBLISH, label: "Publish", iconName: "Upload", requiresAuth: true },
|
|
162
|
+
[ROW_ACTION_ID.ARCHIVE]: { id: ROW_ACTION_ID.ARCHIVE, label: "Archive", iconName: "Archive", requiresAuth: true, separator: true },
|
|
116
163
|
};
|
|
117
164
|
// Admin dashboard row action groups per entity type
|
|
118
165
|
export const ADMIN_ROW_ACTIONS = {
|
|
@@ -166,21 +213,11 @@ export const FORM_ACTION_META = {
|
|
|
166
213
|
[FORM_ACTION_ID.DELETE]: { id: FORM_ACTION_ID.DELETE, label: "Delete", variant: "danger", type: "button", iconName: "Trash2", destructive: true },
|
|
167
214
|
[FORM_ACTION_ID.DISCARD]: { id: FORM_ACTION_ID.DISCARD, label: "Discard", variant: "ghost", type: "button", destructive: true },
|
|
168
215
|
};
|
|
169
|
-
/**
|
|
170
|
-
* Preset ordered action groups for common form footer layouts.
|
|
171
|
-
* Consumed by FormShell and DrawerFormFooter to determine which buttons render,
|
|
172
|
-
* in which order (left → right).
|
|
173
|
-
*/
|
|
174
216
|
export const FORM_FOOTER_PRESET = {
|
|
175
|
-
/** Standard edit drawer: Cancel | Save Changes */
|
|
176
217
|
drawerEdit: [FORM_ACTION_ID.CANCEL, FORM_ACTION_ID.SUBMIT],
|
|
177
|
-
/** Edit drawer with delete: Delete | Cancel | Save Changes */
|
|
178
218
|
drawerEditDelete: [FORM_ACTION_ID.DELETE, FORM_ACTION_ID.CANCEL, FORM_ACTION_ID.SUBMIT],
|
|
179
|
-
/** Content editor (blog / product): Discard | Save Draft | Publish */
|
|
180
219
|
contentEditor: [FORM_ACTION_ID.DISCARD, FORM_ACTION_ID.SAVE_DRAFT, FORM_ACTION_ID.PUBLISH],
|
|
181
|
-
/** Simple modal / dialog: Cancel | Submit */
|
|
182
220
|
modalForm: [FORM_ACTION_ID.CANCEL, FORM_ACTION_ID.SUBMIT],
|
|
183
|
-
/** Settings page: Reset | Save Changes */
|
|
184
221
|
settingsForm: [FORM_ACTION_ID.RESET, FORM_ACTION_ID.SUBMIT],
|
|
185
222
|
};
|
|
186
223
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -210,23 +247,23 @@ export const DASHBOARD_QUICK_ACTION_ID = {
|
|
|
210
247
|
USER_ADD_ADDRESS: "dqa-user-add-address",
|
|
211
248
|
};
|
|
212
249
|
export const DASHBOARD_QUICK_ACTION_META = {
|
|
213
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT, label: "Add Product", variant: "primary", iconName: "Plus" },
|
|
214
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_USER]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_USER, label: "Add User", variant: "outline", iconName: "UserPlus" },
|
|
215
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_STORE]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_STORE, label: "Add Store", variant: "outline", iconName: "Store" },
|
|
216
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_COUPON]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_COUPON, label: "Add Coupon", variant: "outline", iconName: "Tag" },
|
|
217
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_EVENT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_EVENT, label: "Add Event", variant: "outline", iconName: "Calendar" },
|
|
218
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG, label: "New Post", variant: "outline", iconName: "FileText" },
|
|
219
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ, label: "Add FAQ", variant: "outline", iconName: "HelpCircle" },
|
|
220
|
-
[DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS, label: "Settings", variant: "ghost", iconName: "Settings" },
|
|
221
|
-
[DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT, label: "List a Product", variant: "primary", iconName: "Plus" },
|
|
222
|
-
[DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON, label: "New Coupon", variant: "outline", iconName: "Tag" },
|
|
223
|
-
[DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS, label: "Orders", variant: "outline", iconName: "ShoppingBag" },
|
|
224
|
-
[DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ, label: "Request Payout", variant: "outline", iconName: "Banknote" },
|
|
225
|
-
[DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS, label: "Store Settings", variant: "ghost", iconName: "Settings" },
|
|
226
|
-
[DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS, label: "My Orders", variant: "outline", iconName: "Package" },
|
|
227
|
-
[DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST, label: "Wishlist", variant: "outline", iconName: "Heart" },
|
|
228
|
-
[DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE]: { id: DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE, label: "Edit Profile", variant: "outline", iconName: "User" },
|
|
229
|
-
[DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS, label: "Add Address", variant: "outline", iconName: "MapPin" },
|
|
250
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_PRODUCT, label: "Add Product", variant: "primary", iconName: "Plus", requiresAuth: true, requiredRole: "admin", requiredPermission: "products.create" },
|
|
251
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_USER]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_USER, label: "Add User", variant: "outline", iconName: "UserPlus", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.users.create" },
|
|
252
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_STORE]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_STORE, label: "Add Store", variant: "outline", iconName: "Store", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.stores.create" },
|
|
253
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_COUPON]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_COUPON, label: "Add Coupon", variant: "outline", iconName: "Tag", requiresAuth: true, requiredRole: "admin", requiredPermission: "coupons.create" },
|
|
254
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_EVENT]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_EVENT, label: "Add Event", variant: "outline", iconName: "Calendar", requiresAuth: true, requiredRole: "admin", requiredPermission: "events.create" },
|
|
255
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_BLOG, label: "New Post", variant: "outline", iconName: "FileText", requiresAuth: true, requiredRole: "admin", requiredPermission: "blog.create" },
|
|
256
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_ADD_FAQ, label: "Add FAQ", variant: "outline", iconName: "HelpCircle", requiresAuth: true, requiredRole: "admin", requiredPermission: "faqs.create" },
|
|
257
|
+
[DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.ADMIN_SETTINGS, label: "Settings", variant: "ghost", iconName: "Settings", requiresAuth: true, requiredRole: "admin", requiredPermission: "admin.settings.read" },
|
|
258
|
+
[DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_PRODUCT, label: "List a Product", variant: "primary", iconName: "Plus", requiresAuth: true, requiredRole: "seller", requiredPermission: "products.create" },
|
|
259
|
+
[DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_ADD_COUPON, label: "New Coupon", variant: "outline", iconName: "Tag", requiresAuth: true, requiredRole: "seller", requiredPermission: "coupons.create" },
|
|
260
|
+
[DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_VIEW_ORDERS, label: "Orders", variant: "outline", iconName: "ShoppingBag", requiresAuth: true, requiredRole: "seller" },
|
|
261
|
+
[DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_PAYOUT_REQ, label: "Request Payout", variant: "outline", iconName: "Banknote", requiresAuth: true, requiredRole: "seller", requiredPermission: "seller.payouts.request" },
|
|
262
|
+
[DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS]: { id: DASHBOARD_QUICK_ACTION_ID.SELLER_SETTINGS, label: "Store Settings", variant: "ghost", iconName: "Settings", requiresAuth: true, requiredRole: "seller" },
|
|
263
|
+
[DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_ORDERS, label: "My Orders", variant: "outline", iconName: "Package", requiresAuth: true, requiredRole: "user" },
|
|
264
|
+
[DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST]: { id: DASHBOARD_QUICK_ACTION_ID.USER_VIEW_WISHLIST, label: "Wishlist", variant: "outline", iconName: "Heart", requiresAuth: true, requiredRole: "user" },
|
|
265
|
+
[DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE]: { id: DASHBOARD_QUICK_ACTION_ID.USER_EDIT_PROFILE, label: "Edit Profile", variant: "outline", iconName: "User", requiresAuth: true, requiredRole: "user" },
|
|
266
|
+
[DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS]: { id: DASHBOARD_QUICK_ACTION_ID.USER_ADD_ADDRESS, label: "Add Address", variant: "outline", iconName: "MapPin", requiresAuth: true, requiredRole: "user" },
|
|
230
267
|
};
|
|
231
268
|
// Quick action groups — ordered left-to-right in the top shortcut bar
|
|
232
269
|
export const DASHBOARD_QUICK_ACTIONS = {
|
|
@@ -18,10 +18,14 @@ export const PRODUCT_FEATURE_CATEGORY_OPTIONS = [
|
|
|
18
18
|
{ value: "custom", label: "Custom" },
|
|
19
19
|
];
|
|
20
20
|
export const PRODUCT_FEATURE_PRODUCT_TYPE_OPTIONS = [
|
|
21
|
-
{ value: "all", label: "All
|
|
21
|
+
{ value: "all", label: "All listing types" },
|
|
22
22
|
{ value: "product", label: "Standard product" },
|
|
23
23
|
{ value: "auction", label: "Auction" },
|
|
24
24
|
{ value: "preorder", label: "Pre-order" },
|
|
25
|
+
{ value: "prize-draw", label: "Prize draw" },
|
|
26
|
+
{ value: "classified", label: "Classified" },
|
|
27
|
+
{ value: "digital-code", label: "Digital code" },
|
|
28
|
+
{ value: "live", label: "Live item" },
|
|
25
29
|
];
|
|
26
30
|
export const PRODUCT_FEATURE_SCOPE_OPTIONS = [
|
|
27
31
|
{ value: "platform", label: "Platform (all stores)" },
|
|
@@ -315,6 +315,7 @@ export declare const productItemSchema: z.ZodObject<{
|
|
|
315
315
|
preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
|
|
316
316
|
prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
|
|
317
317
|
categorySlug?: string | undefined;
|
|
318
|
+
features?: string[] | undefined;
|
|
318
319
|
images?: string[] | undefined;
|
|
319
320
|
description?: string | undefined;
|
|
320
321
|
isPromoted?: boolean | undefined;
|
|
@@ -328,7 +329,6 @@ export declare const productItemSchema: z.ZodObject<{
|
|
|
328
329
|
name: string;
|
|
329
330
|
unit?: string | undefined;
|
|
330
331
|
}[] | undefined;
|
|
331
|
-
features?: string[] | undefined;
|
|
332
332
|
shippingInfo?: string | undefined;
|
|
333
333
|
returnPolicy?: string | undefined;
|
|
334
334
|
insurance?: boolean | undefined;
|
|
@@ -444,6 +444,7 @@ export declare const productItemSchema: z.ZodObject<{
|
|
|
444
444
|
preOrderProductionStatus?: "upcoming" | "in_production" | "ready_to_ship" | undefined;
|
|
445
445
|
prizeRevealStatus?: "pending" | "closed" | "open" | undefined;
|
|
446
446
|
categorySlug?: string | undefined;
|
|
447
|
+
features?: string[] | undefined;
|
|
447
448
|
images?: string[] | undefined;
|
|
448
449
|
description?: string | undefined;
|
|
449
450
|
isPromoted?: boolean | undefined;
|
|
@@ -457,7 +458,6 @@ export declare const productItemSchema: z.ZodObject<{
|
|
|
457
458
|
name: string;
|
|
458
459
|
unit?: string | undefined;
|
|
459
460
|
}[] | undefined;
|
|
460
|
-
features?: string[] | undefined;
|
|
461
461
|
shippingInfo?: string | undefined;
|
|
462
462
|
returnPolicy?: string | undefined;
|
|
463
463
|
insurance?: boolean | undefined;
|
|
@@ -20,7 +20,7 @@ export declare const MAX_STORE_CUSTOM_FEATURES = 20;
|
|
|
20
20
|
export declare const MAX_FEATURES_PER_PRODUCT = 10;
|
|
21
21
|
export type ProductFeatureScope = "platform" | "store";
|
|
22
22
|
export type ProductFeatureCategory = "shipping" | "seller" | "condition" | "platform" | "auction" | "preorder" | "custom";
|
|
23
|
-
export type ProductFeatureProductType = "product" | "auction" | "preorder" | "all";
|
|
23
|
+
export type ProductFeatureProductType = "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live" | "all";
|
|
24
24
|
/**
|
|
25
25
|
* Either an appkit icon-set name key (e.g. "truck") or a raw SVG path-d string.
|
|
26
26
|
* Path strings must start with "M " — see isFeatureIconPath().
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* of hand-rolling parallel schemas.
|
|
7
7
|
*/
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
export declare const PRODUCT_FEATURE_PRODUCT_TYPE_ENUM: z.ZodEnum<["product", "auction", "preorder", "all"]>;
|
|
9
|
+
export declare const PRODUCT_FEATURE_PRODUCT_TYPE_ENUM: z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>;
|
|
10
10
|
export declare const PRODUCT_FEATURE_CATEGORY_ENUM: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
|
|
11
11
|
export declare const PRODUCT_FEATURE_SCOPE_ENUM: z.ZodEnum<["platform", "store"]>;
|
|
12
12
|
/** Shape for POST /api/admin/features — admin creates either scope. */
|
|
@@ -17,7 +17,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
|
|
|
17
17
|
iconColor: z.ZodOptional<z.ZodString>;
|
|
18
18
|
category: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
|
|
19
19
|
scope: z.ZodEnum<["platform", "store"]>;
|
|
20
|
-
productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">;
|
|
20
|
+
productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">;
|
|
21
21
|
storeId: z.ZodOptional<z.ZodString>;
|
|
22
22
|
isActive: z.ZodBoolean;
|
|
23
23
|
displayOrder: z.ZodNumber;
|
|
@@ -28,7 +28,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
|
|
|
28
28
|
isActive: boolean;
|
|
29
29
|
category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
|
|
30
30
|
displayOrder: number;
|
|
31
|
-
productTypes: ("all" | "product" | "auction" | "preorder")[];
|
|
31
|
+
productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
|
|
32
32
|
storeId?: string | undefined;
|
|
33
33
|
description?: string | undefined;
|
|
34
34
|
iconColor?: string | undefined;
|
|
@@ -39,7 +39,7 @@ export declare const productFeatureAdminCreateSchema: z.ZodObject<{
|
|
|
39
39
|
isActive: boolean;
|
|
40
40
|
category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
|
|
41
41
|
displayOrder: number;
|
|
42
|
-
productTypes: ("all" | "product" | "auction" | "preorder")[];
|
|
42
|
+
productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
|
|
43
43
|
storeId?: string | undefined;
|
|
44
44
|
description?: string | undefined;
|
|
45
45
|
iconColor?: string | undefined;
|
|
@@ -51,7 +51,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
|
|
|
51
51
|
icon: z.ZodString;
|
|
52
52
|
iconColor: z.ZodOptional<z.ZodString>;
|
|
53
53
|
category: z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>;
|
|
54
|
-
productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">;
|
|
54
|
+
productTypes: z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">;
|
|
55
55
|
isActive: z.ZodBoolean;
|
|
56
56
|
displayOrder: z.ZodNumber;
|
|
57
57
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -60,7 +60,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
|
|
|
60
60
|
isActive: boolean;
|
|
61
61
|
category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
|
|
62
62
|
displayOrder: number;
|
|
63
|
-
productTypes: ("all" | "product" | "auction" | "preorder")[];
|
|
63
|
+
productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
|
|
64
64
|
description?: string | undefined;
|
|
65
65
|
iconColor?: string | undefined;
|
|
66
66
|
}, {
|
|
@@ -69,7 +69,7 @@ export declare const productFeatureStoreCreateSchema: z.ZodObject<{
|
|
|
69
69
|
isActive: boolean;
|
|
70
70
|
category: "seller" | "auction" | "preorder" | "condition" | "shipping" | "custom" | "platform";
|
|
71
71
|
displayOrder: number;
|
|
72
|
-
productTypes: ("all" | "product" | "auction" | "preorder")[];
|
|
72
|
+
productTypes: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[];
|
|
73
73
|
description?: string | undefined;
|
|
74
74
|
iconColor?: string | undefined;
|
|
75
75
|
}>;
|
|
@@ -80,7 +80,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
|
|
|
80
80
|
icon: z.ZodOptional<z.ZodString>;
|
|
81
81
|
iconColor: z.ZodOptional<z.ZodString>;
|
|
82
82
|
category: z.ZodOptional<z.ZodEnum<["shipping", "seller", "condition", "platform", "auction", "preorder", "custom"]>>;
|
|
83
|
-
productTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "all"]>, "many">>;
|
|
83
|
+
productTypes: z.ZodOptional<z.ZodArray<z.ZodEnum<["product", "auction", "preorder", "prize-draw", "classified", "digital-code", "live", "all"]>, "many">>;
|
|
84
84
|
isActive: z.ZodOptional<z.ZodBoolean>;
|
|
85
85
|
displayOrder: z.ZodOptional<z.ZodNumber>;
|
|
86
86
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -91,7 +91,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
|
|
|
91
91
|
description?: string | undefined;
|
|
92
92
|
iconColor?: string | undefined;
|
|
93
93
|
displayOrder?: number | undefined;
|
|
94
|
-
productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
|
|
94
|
+
productTypes?: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[] | undefined;
|
|
95
95
|
}, {
|
|
96
96
|
label?: string | undefined;
|
|
97
97
|
icon?: string | undefined;
|
|
@@ -100,7 +100,7 @@ export declare const productFeatureUpdateSchema: z.ZodObject<{
|
|
|
100
100
|
description?: string | undefined;
|
|
101
101
|
iconColor?: string | undefined;
|
|
102
102
|
displayOrder?: number | undefined;
|
|
103
|
-
productTypes?: ("all" | "product" | "auction" | "preorder")[] | undefined;
|
|
103
|
+
productTypes?: ("all" | "product" | "auction" | "preorder" | "prize-draw" | "classified" | "digital-code" | "live")[] | undefined;
|
|
104
104
|
}>;
|
|
105
105
|
export type ProductFeatureAdminCreatePayload = z.infer<typeof productFeatureAdminCreateSchema>;
|
|
106
106
|
export type ProductFeatureStoreCreatePayload = z.infer<typeof productFeatureStoreCreateSchema>;
|
|
@@ -61,7 +61,7 @@ export function SellerCouponEditorView({ couponId, initial, onSave, onCancel, })
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
const isEdit = Boolean(couponId);
|
|
64
|
-
return (_jsx("form", { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: "max-w-lg mx-auto", children: [_jsx(
|
|
64
|
+
return (_jsx("form", { onSubmit: handleSubmit, noValidate: true, children: _jsxs(Stack, { gap: "none", className: "max-w-lg mx-auto rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] shadow-sm overflow-hidden", children: [_jsx("div", { className: "h-[3px] w-full", style: { background: "linear-gradient(to right,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)" }, "aria-hidden": "true" }), _jsx(Div, { className: "border-b border-[var(--appkit-color-border)] px-6 py-5", children: _jsxs(Row, { className: "items-center justify-between gap-3", children: [_jsx(Heading, { level: 2, className: "text-lg font-semibold text-[var(--appkit-color-text)]", children: isEdit ? "Edit Coupon" : "Create Coupon" }), isEdit && (_jsx(Badge, { variant: draft.isActive ? "success" : "default", children: draft.isActive ? "Active" : "Inactive" }))] }) }), _jsxs(Stack, { gap: "5", className: "px-6 py-6", children: [error && (_jsx(Div, { className: "rounded-lg border border-red-200 bg-red-50 dark:bg-red-950/40 dark:border-red-900/60 px-4 py-3 text-sm text-red-700 dark:text-red-200", children: error })), _jsx(Input, { label: "Coupon Code", value: draft.code, onChange: (e) => set("code", e.target.value.toUpperCase().replace(/\s+/g, "")), placeholder: "e.g. WELCOME10", required: true, disabled: isEdit, helperText: isEdit ? "Code cannot be changed after creation" : "Customers enter this at checkout" }), _jsx(Select, { label: "Discount Type", value: draft.type, options: TYPE_OPTIONS, onChange: (e) => set("type", e.target.value) }), draft.type !== "free_shipping" && (_jsx(Input, { label: draft.type === "percentage" ? "Discount Percentage (%)" : "Discount Amount (₹)", type: "number", min: 1, max: draft.type === "percentage" ? 100 : undefined, value: draft.value, onChange: (e) => set("value", e.target.value), placeholder: draft.type === "percentage" ? "e.g. 10" : "e.g. 50", required: true, helperText: draft.type === "percentage"
|
|
65
65
|
? "Enter a value between 1 and 100"
|
|
66
|
-
: "Fixed rupee discount applied to the order" })), draft.type === "percentage" && (_jsx(Input, { label: "Max Discount Cap (\u20B9, optional)", type: "number", min: 0, value: draft.maxDiscount, onChange: (e) => set("maxDiscount", e.target.value), placeholder: "Leave blank for no cap", helperText: "Maximum rupee discount regardless of percentage" })), _jsx(Input, { label: "Minimum Order Amount (\u20B9, optional)", type: "number", min: 0, value: draft.minPurchase, onChange: (e) => set("minPurchase", e.target.value), placeholder: "Leave blank for no minimum" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Usage Limits" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Total Uses", type: "number", min: 0, value: draft.totalLimit, onChange: (e) => set("totalLimit", e.target.value), placeholder: "0 = unlimited" }), _jsx(Input, { label: "Per Customer", type: "number", min: 0, value: draft.perUserLimit, onChange: (e) => set("perUserLimit", e.target.value), placeholder: "0 = unlimited" })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Validity Period" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Start Date", type: "date", value: draft.startDate, onChange: (e) => set("startDate", e.target.value), required: true }), _jsx(Input, { label: "End Date", type: "date", value: draft.endDate, onChange: (e) => set("endDate", e.target.value), required: true })] })] }), _jsx(Div, { className: "flex items-center gap-3 rounded-lg border border-[var(--appkit-color-border)] dark:border-[var(--appkit-color-border-dark)] px-4 py-3", children: _jsxs("label", { className: "flex items-center gap-3 cursor-pointer w-full", children: [_jsx("input", { type: "checkbox", checked: draft.isActive, onChange: (e) => set("isActive", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-primary)]", children: "Active" }), _jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-secondary)]", children: "Customers can apply this coupon at checkout" })] })] }) })] }), _jsx(Div, { className: "border-t border-[var(--appkit-color-border)]
|
|
66
|
+
: "Fixed rupee discount applied to the order" })), draft.type === "percentage" && (_jsx(Input, { label: "Max Discount Cap (\u20B9, optional)", type: "number", min: 0, value: draft.maxDiscount, onChange: (e) => set("maxDiscount", e.target.value), placeholder: "Leave blank for no cap", helperText: "Maximum rupee discount regardless of percentage" })), _jsx(Input, { label: "Minimum Order Amount (\u20B9, optional)", type: "number", min: 0, value: draft.minPurchase, onChange: (e) => set("minPurchase", e.target.value), placeholder: "Leave blank for no minimum" }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Usage Limits" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Total Uses", type: "number", min: 0, value: draft.totalLimit, onChange: (e) => set("totalLimit", e.target.value), placeholder: "0 = unlimited" }), _jsx(Input, { label: "Per Customer", type: "number", min: 0, value: draft.perUserLimit, onChange: (e) => set("perUserLimit", e.target.value), placeholder: "0 = unlimited" })] })] }), _jsxs(Div, { children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-secondary)] mb-3", children: "Validity Period" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsx(Input, { label: "Start Date", type: "date", value: draft.startDate, onChange: (e) => set("startDate", e.target.value), required: true }), _jsx(Input, { label: "End Date", type: "date", value: draft.endDate, onChange: (e) => set("endDate", e.target.value), required: true })] })] }), _jsx(Div, { className: "flex items-center gap-3 rounded-lg border border-[var(--appkit-color-border)] dark:border-[var(--appkit-color-border-dark)] px-4 py-3", children: _jsxs("label", { className: "flex items-center gap-3 cursor-pointer w-full", children: [_jsx("input", { type: "checkbox", checked: draft.isActive, onChange: (e) => set("isActive", e.target.checked), className: "h-4 w-4 rounded border-zinc-300 dark:border-slate-600 text-[var(--appkit-color-primary)] focus:ring-[var(--appkit-color-primary)]" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx(Text, { size: "sm", className: "font-medium text-[var(--appkit-color-text-primary)]", children: "Active" }), _jsx(Text, { size: "xs", className: "text-[var(--appkit-color-text-secondary)]", children: "Customers can apply this coupon at checkout" })] })] }) })] }), _jsx(Div, { className: "border-t border-[var(--appkit-color-border)] px-6 py-4", children: _jsxs(Row, { className: "items-center justify-end gap-3", children: [onCancel && (_jsx(Button, { type: "button", variant: "outline", onClick: onCancel, disabled: saving, children: "Cancel" })), _jsx(Button, { type: "submit", isLoading: saving, disabled: saving, children: isEdit ? "Save Changes" : "Create Coupon" })] }) })] }) }));
|
|
67
67
|
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import { TrendingUp, ShoppingBag, Package, CheckCircle } from "lucide-react";
|
|
4
|
+
import { Div } from "../../../../ui";
|
|
5
|
+
const GREEN_GRAD = "linear-gradient(135deg,var(--appkit-color-cobalt,#3570fc) 0%,var(--appkit-color-secondary-400,#84e122) 100%)";
|
|
6
|
+
const BRAND_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 55%,var(--appkit-color-secondary-400,#84e122) 100%)";
|
|
7
|
+
const AMBER_GRAD = "linear-gradient(135deg,var(--appkit-color-amber-500,#f59e0b) 0%,var(--appkit-color-amber-600,#d97706) 100%)";
|
|
8
|
+
const BLUE_GRAD = "linear-gradient(135deg,var(--appkit-color-primary-700,#1343de) 0%,var(--appkit-color-cobalt,#3570fc) 100%)";
|
|
9
|
+
function StatCard({ label, value, gradient, Icon }) {
|
|
10
|
+
return (_jsxs(Div, { className: "relative rounded-xl border border-[var(--appkit-color-border)] bg-[var(--appkit-color-surface)] overflow-hidden shadow-sm hover:shadow-md transition-shadow", children: [_jsx("div", { className: "absolute top-0 left-0 right-0 h-[3px]", style: { background: gradient }, "aria-hidden": "true" }), _jsxs(Div, { className: "px-5 pb-5 pt-6 flex items-start justify-between gap-3", children: [_jsxs(Div, { className: "min-w-0 flex-1", children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-widest text-[var(--appkit-color-text-muted)]", children: label }), _jsx("div", { className: "mt-2 text-2xl font-bold text-[var(--appkit-color-text)] tabular-nums leading-none", children: value })] }), _jsx("div", { className: "flex-shrink-0 w-10 h-10 rounded-lg flex items-center justify-center", style: { background: gradient }, children: _jsx(Icon, { className: "w-5 h-5 text-white" }) })] })] }));
|
|
5
11
|
}
|
|
6
12
|
export function SellerAnalyticsStats({ summary, labels = {}, formatRevenue = (amount) => String(amount), className = "", }) {
|
|
7
|
-
return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4
|
|
13
|
+
return (_jsxs(Div, { className: `grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-4 ${className}`, children: [_jsx(StatCard, { label: labels.totalRevenue ?? "Total Revenue", value: formatRevenue(summary.totalRevenue), gradient: GREEN_GRAD, Icon: TrendingUp }), _jsx(StatCard, { label: labels.totalOrders ?? "Total Orders", value: String(summary.totalOrders), gradient: BRAND_GRAD, Icon: ShoppingBag }), _jsx(StatCard, { label: labels.totalProducts ?? "Total Products", value: String(summary.totalProducts), gradient: AMBER_GRAD, Icon: Package }), _jsx(StatCard, { label: labels.publishedProducts ?? "Published", value: String(summary.publishedProducts), gradient: BLUE_GRAD, Icon: CheckCircle })] }));
|
|
8
14
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export interface StoreBundlesPageViewProps {
|
|
2
2
|
storeSlug: string;
|
|
3
|
+
onBuyNow?: (input: {
|
|
4
|
+
bundleSlug: string;
|
|
5
|
+
}) => Promise<unknown>;
|
|
3
6
|
}
|
|
4
7
|
/**
|
|
5
8
|
* Public store → Bundles tab.
|
|
@@ -9,4 +12,4 @@ export interface StoreBundlesPageViewProps {
|
|
|
9
12
|
* the seller's active bundle categories and hands them to
|
|
10
13
|
* `CategoryBundlesListing`. Mirrors the StorePrizeDrawsPageView pattern.
|
|
11
14
|
*/
|
|
12
|
-
export declare function StoreBundlesPageView({ storeSlug, }: StoreBundlesPageViewProps): Promise<import("react/jsx-runtime").JSX.Element | null>;
|
|
15
|
+
export declare function StoreBundlesPageView({ storeSlug, onBuyNow, }: StoreBundlesPageViewProps): Promise<import("react/jsx-runtime").JSX.Element | null>;
|
|
@@ -10,7 +10,7 @@ import { CategoryBundlesListing } from "../../categories/components/CategoryBund
|
|
|
10
10
|
* the seller's active bundle categories and hands them to
|
|
11
11
|
* `CategoryBundlesListing`. Mirrors the StorePrizeDrawsPageView pattern.
|
|
12
12
|
*/
|
|
13
|
-
export async function StoreBundlesPageView({ storeSlug, }) {
|
|
13
|
+
export async function StoreBundlesPageView({ storeSlug, onBuyNow, }) {
|
|
14
14
|
const store = await getStoreBySlug(storeSlug);
|
|
15
15
|
const storeId = store?.id;
|
|
16
16
|
if (!storeId) {
|
|
@@ -20,5 +20,5 @@ export async function StoreBundlesPageView({ storeSlug, }) {
|
|
|
20
20
|
.listByType("bundle", { activeOnly: true, limit: 50 })
|
|
21
21
|
.then((rows) => rows.filter((c) => c.createdByStoreId === storeId))
|
|
22
22
|
.catch(() => []);
|
|
23
|
-
return _jsx(CategoryBundlesListing, { initialBundles: bundles });
|
|
23
|
+
return _jsx(CategoryBundlesListing, { initialBundles: bundles, onBuyNow: onBuyNow });
|
|
24
24
|
}
|
|
@@ -80,6 +80,7 @@ export function StoresIndexListing({ initialData }) {
|
|
|
80
80
|
setSearchInput("");
|
|
81
81
|
}, [table]);
|
|
82
82
|
const activeFilterCount = FILTER_KEYS.filter((k) => !!table.get(k)).length;
|
|
83
|
+
const pendingFilterCount = FILTER_KEYS.filter((k) => !!pendingFilters[k]).length;
|
|
83
84
|
const hasActiveState = !!table.get(TABLE_KEYS.QUERY) ||
|
|
84
85
|
table.get(TABLE_KEYS.SORT) !== DEFAULT_SORT ||
|
|
85
86
|
activeFilterCount > 0;
|
|
@@ -132,5 +133,5 @@ export function StoresIndexListing({ initialData }) {
|
|
|
132
133
|
}) })) : (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6", children: stores.map((store) => {
|
|
133
134
|
const storeKey = store.storeSlug ?? store.id;
|
|
134
135
|
return (_jsx(InteractiveStoreCard, { store: store, href: String(ROUTES.PUBLIC.STORE_DETAIL(storeKey)), selectable: selection.isSelecting, isSelected: selection.isSelected(store.id ?? store.storeSlug), onSelect: (id, sel) => { void sel; selection.toggle(id); } }, storeKey));
|
|
135
|
-
}) })) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsxs("div", { className: "flex items-center gap-2", children: [
|
|
136
|
+
}) })) }), filterOpen && (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 z-40 bg-black/40", "aria-hidden": "true", onClick: () => setFilterOpen(false) }), _jsxs("div", { className: "fixed inset-y-0 left-0 z-50 flex w-80 flex-col bg-white dark:bg-slate-900 shadow-2xl", children: [_jsxs("div", { className: "flex items-center justify-between border-b border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: [_jsxs("span", { className: "flex items-center gap-2 text-base font-semibold text-zinc-900 dark:text-zinc-100", children: [_jsx(SlidersHorizontal, { className: "h-4 w-4" }), "Filters"] }), _jsxs("div", { className: "flex items-center gap-2", children: [pendingFilterCount > 0 && (_jsx("button", { type: "button", onClick: clearFilters, className: "text-xs text-zinc-500 hover:text-rose-500 dark:text-zinc-400 transition-colors", children: "Clear all" })), _jsx("button", { type: "button", onClick: () => setFilterOpen(false), "aria-label": "Close filters", className: "rounded-lg p-1.5 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-slate-800 transition-colors", children: _jsx(X, { className: "h-5 w-5" }) })] })] }), _jsx("div", { className: "flex-1 overflow-y-auto px-4 py-4", children: _jsx(StoreFilters, { table: pendingTable }) }), _jsx("div", { className: "border-t border-zinc-200 dark:border-slate-700 px-4 py-3.5", children: _jsxs("button", { type: "button", onClick: applyFilters, className: "w-full rounded-lg bg-primary py-2.5 text-sm font-semibold text-white hover:bg-primary-600 transition-colors active:scale-[0.98]", children: ["Apply Filters", pendingFilterCount > 0 ? ` (${pendingFilterCount})` : ""] }) })] })] }))] }));
|
|
136
137
|
}
|
|
@@ -24,12 +24,14 @@ export function getAdminAppLite() {
|
|
|
24
24
|
return existing;
|
|
25
25
|
}
|
|
26
26
|
const keyPath = nodePath().join(nodeCwd(), "firebase-admin-key.json");
|
|
27
|
+
const storageBucket = process.env.FIREBASE_ADMIN_STORAGE_BUCKET?.trim() ??
|
|
28
|
+
process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET?.trim();
|
|
27
29
|
let app;
|
|
28
30
|
if (nodeFs().existsSync(keyPath)) {
|
|
29
31
|
const sa = JSON.parse(nodeFs().readFileSync(keyPath, "utf8"));
|
|
30
32
|
const dbUrl = process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
|
|
31
33
|
`https://${sa.project_id}-default-rtdb.firebaseio.com`;
|
|
32
|
-
app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl });
|
|
34
|
+
app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl, ...(storageBucket && { storageBucket }) });
|
|
33
35
|
}
|
|
34
36
|
else if (process.env.FIREBASE_ADMIN_PROJECT_ID &&
|
|
35
37
|
process.env.FIREBASE_ADMIN_CLIENT_EMAIL &&
|
|
@@ -45,6 +47,7 @@ export function getAdminAppLite() {
|
|
|
45
47
|
privateKey: parsePrivateKey(process.env.FIREBASE_ADMIN_PRIVATE_KEY),
|
|
46
48
|
}),
|
|
47
49
|
databaseURL: dbUrl,
|
|
50
|
+
...(storageBucket && { storageBucket }),
|
|
48
51
|
});
|
|
49
52
|
}
|
|
50
53
|
else if (
|
|
@@ -66,7 +69,10 @@ export function getAdminAppLite() {
|
|
|
66
69
|
process.env.FIREBASE_ADMIN_DATABASE_URL ??
|
|
67
70
|
process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
|
|
68
71
|
(projectId ? `https://${projectId}-default-rtdb.firebaseio.com` : undefined);
|
|
69
|
-
app = initializeApp(
|
|
72
|
+
app = initializeApp({
|
|
73
|
+
...(dbUrl && { databaseURL: dbUrl }),
|
|
74
|
+
...(storageBucket && { storageBucket }),
|
|
75
|
+
});
|
|
70
76
|
}
|
|
71
77
|
else {
|
|
72
78
|
throw new Error("@mohasinac/db-firebase: Firebase Admin credentials not found.");
|
|
@@ -67,13 +67,15 @@ export function getAdminApp() {
|
|
|
67
67
|
return existing;
|
|
68
68
|
}
|
|
69
69
|
const keyPath = nodePath().join(nodeCwd(), "firebase-admin-key.json");
|
|
70
|
+
const storageBucket = process.env.FIREBASE_ADMIN_STORAGE_BUCKET?.trim() ??
|
|
71
|
+
process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET?.trim();
|
|
70
72
|
let app;
|
|
71
73
|
try {
|
|
72
74
|
if (nodeFs().existsSync(keyPath)) {
|
|
73
75
|
const sa = JSON.parse(nodeFs().readFileSync(keyPath, "utf8"));
|
|
74
76
|
const dbUrl = process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL ??
|
|
75
77
|
`https://${sa.project_id}-default-rtdb.firebaseio.com`;
|
|
76
|
-
app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl });
|
|
78
|
+
app = initializeApp({ credential: cert(keyPath), databaseURL: dbUrl, ...(storageBucket && { storageBucket }) });
|
|
77
79
|
}
|
|
78
80
|
else if (process.env.FIREBASE_ADMIN_PROJECT_ID &&
|
|
79
81
|
process.env.FIREBASE_ADMIN_CLIENT_EMAIL &&
|
|
@@ -89,6 +91,7 @@ export function getAdminApp() {
|
|
|
89
91
|
privateKey: parsePrivateKey(process.env.FIREBASE_ADMIN_PRIVATE_KEY),
|
|
90
92
|
}),
|
|
91
93
|
databaseURL: dbUrl,
|
|
94
|
+
...(storageBucket && { storageBucket }),
|
|
92
95
|
});
|
|
93
96
|
}
|
|
94
97
|
else if (
|
|
@@ -112,7 +115,10 @@ export function getAdminApp() {
|
|
|
112
115
|
(projectId
|
|
113
116
|
? `https://${projectId}-default-rtdb.firebaseio.com`
|
|
114
117
|
: undefined);
|
|
115
|
-
app = initializeApp(
|
|
118
|
+
app = initializeApp({
|
|
119
|
+
...(dbUrl && { databaseURL: dbUrl }),
|
|
120
|
+
...(storageBucket && { storageBucket }),
|
|
121
|
+
});
|
|
116
122
|
}
|
|
117
123
|
else {
|
|
118
124
|
throw new Error("@mohasinac/db-firebase: Firebase Admin credentials not found.\n" +
|