@mohasinac/appkit 4.9.4 → 4.10.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.
- package/dist/_internal/client/features/layout/DashboardLayoutClient.js +7 -2
- package/dist/_internal/client/features/layout/SidebarCollapseToggle.d.ts +5 -1
- package/dist/_internal/client/features/layout/SidebarCollapseToggle.js +8 -2
- package/dist/_internal/client/features/layout/sidebarPositionClasses.d.ts +20 -0
- package/dist/_internal/client/features/layout/sidebarPositionClasses.js +20 -0
- package/dist/_internal/client/hand-mode/HandModeProvider.d.ts +21 -0
- package/dist/_internal/client/hand-mode/HandModeProvider.js +81 -0
- package/dist/_internal/client/hand-mode/index.d.ts +2 -0
- package/dist/_internal/client/hand-mode/index.js +1 -0
- package/dist/_internal/server/features/auctions/actions.js +3 -2
- package/dist/_internal/server/features/auctions/service.d.ts +4 -3
- package/dist/_internal/server/features/auctions/service.js +6 -6
- package/dist/_internal/server/features/bundles/data.d.ts +9 -0
- package/dist/_internal/server/features/bundles/data.js +14 -0
- package/dist/_internal/server/features/bundles/index.d.ts +1 -1
- package/dist/_internal/server/features/bundles/index.js +1 -1
- package/dist/_internal/server/features/catalogue/og.d.ts +20 -0
- package/dist/_internal/server/features/catalogue/og.js +27 -0
- package/dist/_internal/server/features/checkout/actions.d.ts +43 -0
- package/dist/_internal/server/features/checkout/actions.js +172 -81
- package/dist/_internal/server/features/checkout/index.d.ts +1 -1
- package/dist/_internal/server/features/checkout/index.js +1 -1
- package/dist/_internal/server/features/grouped/data.d.ts +12 -0
- package/dist/_internal/server/features/grouped/data.js +26 -1
- package/dist/_internal/server/features/grouped/index.d.ts +1 -1
- package/dist/_internal/server/features/grouped/index.js +1 -1
- package/dist/_internal/server/features/products/data.d.ts +23 -0
- package/dist/_internal/server/features/products/data.js +159 -0
- package/dist/_internal/server/features/products/index.d.ts +1 -1
- package/dist/_internal/server/features/products/index.js +1 -1
- package/dist/_internal/server/features/seo/robots.js +3 -2
- package/dist/_internal/server/features/seo/sitemap.js +70 -5
- package/dist/_internal/shared/config/schema.d.ts +1 -0
- package/dist/_internal/shared/features/auctions/config.d.ts +20 -0
- package/dist/_internal/shared/features/auctions/config.js +31 -1
- package/dist/_internal/shared/listing-types/art/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/art/config.js +1 -1
- package/dist/_internal/shared/listing-types/classified/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/classified/config.js +2 -2
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/digital-code/config.js +2 -2
- package/dist/_internal/shared/listing-types/live/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/live/config.js +2 -2
- package/dist/_internal/shared/listing-types/prize-draw/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/prize-draw/config.js +1 -1
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +1 -1
- package/dist/_internal/shared/listing-types/stickers/config.js +1 -1
- package/dist/client.d.ts +4 -6
- package/dist/client.js +10 -4
- package/dist/constants/api-endpoints.d.ts +6 -0
- package/dist/constants/api-endpoints.js +2 -0
- package/dist/features/about/components/AboutView.js +2 -2
- package/dist/features/about/components/DeveloperView.js +2 -2
- package/dist/features/about/schemas/firestore.d.ts +1 -0
- package/dist/features/account/components/UserSidebar.js +8 -2
- package/dist/features/account/hooks/useProfile.d.ts +2 -0
- package/dist/features/admin/components/AdminSidebar.js +8 -2
- package/dist/features/admin/components/AdminSiteSettingsView.js +12 -4
- package/dist/features/admin/schemas/firestore.d.ts +9 -0
- package/dist/features/admin/schemas/firestore.js +6 -0
- package/dist/features/auctions/actions/bid-actions.js +4 -1
- package/dist/features/auctions/components/AuctionBottomActions.d.ts +2 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +14 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +21 -9
- package/dist/features/auctions/components/LiveMinIncrement.d.ts +18 -0
- package/dist/features/auctions/components/LiveMinIncrement.js +17 -0
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +5 -2
- package/dist/features/auctions/components/PlaceBidFormClient.js +7 -3
- package/dist/features/auth/schemas/firestore.d.ts +3 -0
- package/dist/features/cart/components/CartDrawer.js +4 -1
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.d.ts +11 -0
- package/dist/features/catalogue/components/PublicCatalogueItemDetailView.js +33 -0
- package/dist/features/catalogue/components/PublicCatalogueView.js +2 -1
- package/dist/features/catalogue/index.d.ts +2 -0
- package/dist/features/catalogue/index.js +1 -0
- package/dist/features/categories/components/BundleDetailView.d.ts +3 -1
- package/dist/features/categories/components/BundleDetailView.js +3 -2
- package/dist/features/classified/components/ClassifiedContactSellerPanel.d.ts +12 -0
- package/dist/features/classified/components/ClassifiedContactSellerPanel.js +49 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.d.ts +7 -0
- package/dist/features/classified/components/ClassifiedDetailPageView.js +69 -0
- package/dist/features/contact/components/ContactPageView.js +8 -2
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.d.ts +19 -0
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +79 -0
- package/dist/features/grouped/components/GroupedListingsCarousel.d.ts +13 -0
- package/dist/features/grouped/components/GroupedListingsCarousel.js +31 -0
- package/dist/features/grouped/repository/grouped-listings.repository.d.ts +8 -0
- package/dist/features/grouped/repository/grouped-listings.repository.js +16 -0
- package/dist/features/homepage/components/BrandsSection.js +3 -1
- package/dist/features/homepage/components/FeaturedBundlesSection.js +12 -1
- package/dist/features/homepage/components/GoogleReviewsSection.js +2 -2
- package/dist/features/homepage/components/HeroCarousel.js +3 -1
- package/dist/features/homepage/components/SectionCarousel.js +5 -2
- package/dist/features/homepage/components/SocialFeedSection.js +2 -2
- package/dist/features/homepage/components/WhatsAppCommunitySection.js +3 -1
- package/dist/features/layout/BackToTop.js +3 -1
- package/dist/features/layout/BottomActions.js +4 -3
- package/dist/features/layout/BottomActionsContext.d.ts +10 -0
- package/dist/features/layout/BottomActionsContext.js +5 -1
- package/dist/features/layout/SidebarLayout.js +7 -1
- package/dist/features/layout/hooks/useBottomActions.d.ts +2 -0
- package/dist/features/layout/hooks/useBottomActions.js +4 -1
- package/dist/features/live/components/LiveItemDetailPageView.d.ts +9 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +74 -0
- package/dist/features/media/MediaVideo.js +17 -1
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +9 -1
- package/dist/features/products/components/PrizeDrawDetailPageView.js +11 -1
- package/dist/features/products/components/ProductDetailPageView.js +11 -116
- package/dist/features/products/components/RelatedItemsSection.d.ts +16 -0
- package/dist/features/products/components/RelatedItemsSection.js +17 -0
- package/dist/features/seller/components/SellerProductShell.js +1 -1
- package/dist/features/seller/components/SellerSidebar.js +8 -2
- package/dist/features/shell/QuickFormDrawer.js +3 -1
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +114 -3
- package/dist/hand-mode/index.d.ts +12 -0
- package/dist/hand-mode/index.js +11 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +7 -0
- package/dist/react/contexts/SessionContext.d.ts +5 -0
- package/dist/react/contexts/SessionContext.js +2 -0
- package/dist/seed/bids-seed-data.js +48 -3
- package/dist/seed/grouped-listings-seed-data.js +167 -0
- package/dist/seed/payouts-seed-data.js +4 -4
- package/dist/seed/products-art-seed-data.js +188 -5
- package/dist/seed/products-auctions-seed-data.js +215 -6
- package/dist/seed/products-classifieds-seed-data.js +255 -8
- package/dist/seed/products-digital-codes-seed-data.js +258 -19
- package/dist/seed/products-live-items-seed-data.js +143 -10
- package/dist/seed/products-preorders-seed-data.js +213 -8
- package/dist/seed/products-prize-draws-seed-data.js +198 -0
- package/dist/seed/products-standard-seed-data.js +141 -0
- package/dist/seed/products-stickers-seed-data.js +178 -5
- package/dist/seed/site-settings-seed-data.js +13 -31
- package/dist/seed/store-extensions-seed-data.js +1 -1
- package/dist/server-entry.d.ts +5 -2
- package/dist/server-entry.js +5 -2
- package/dist/server.d.ts +4 -2
- package/dist/server.js +4 -2
- package/dist/styles.css +30 -1
- package/dist/tailwind-utilities.css +1 -1
- package/dist/ui/components/Drawer.js +7 -4
- package/dist/ui/components/FilterDrawer.js +1 -1
- package/dist/ui/components/HandModeRow.d.ts +12 -0
- package/dist/ui/components/HandModeRow.js +18 -0
- package/dist/ui/components/ImageLightbox.js +37 -3
- package/dist/ui/components/ImageLightbox.style.css +28 -0
- package/dist/ui/components/Layout.d.ts +5 -1
- package/dist/ui/components/Layout.js +2 -1
- package/dist/ui/components/Layout.style.css +1 -0
- package/dist/ui/components/ListingFilterDrawer.js +3 -1
- package/dist/ui/components/Modal.js +3 -1
- package/dist/ui/components/SideDrawer.js +8 -5
- package/dist/ui/components/SideModal.js +7 -4
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +1 -0
- package/dist/utils/media-url.d.ts +9 -0
- package/dist/utils/media-url.js +39 -0
- package/package.json +1 -1
|
@@ -21,6 +21,7 @@ function staticPages(baseUrl) {
|
|
|
21
21
|
page(String(ROUTES.PUBLIC.PRODUCTS), "hourly", 0.9),
|
|
22
22
|
page(String(ROUTES.PUBLIC.AUCTIONS), "hourly", 0.9),
|
|
23
23
|
page(String(ROUTES.PUBLIC.CATEGORIES), "weekly", 0.8),
|
|
24
|
+
page(String(ROUTES.PUBLIC.BRANDS), "weekly", 0.7),
|
|
24
25
|
page(String(ROUTES.PUBLIC.BLOG), "daily", 0.7),
|
|
25
26
|
page(String(ROUTES.PUBLIC.EVENTS), "daily", 0.7),
|
|
26
27
|
page(String(ROUTES.PUBLIC.SELLERS), "weekly", 0.6),
|
|
@@ -39,6 +40,12 @@ function staticPages(baseUrl) {
|
|
|
39
40
|
page(String(ROUTES.PUBLIC.REFUND_POLICY), "yearly", 0.3),
|
|
40
41
|
page(String(ROUTES.PUBLIC.SHIPPING_POLICY), "yearly", 0.3),
|
|
41
42
|
page(String(ROUTES.PUBLIC.PRE_ORDERS), "daily", 0.7),
|
|
43
|
+
page(String(ROUTES.PUBLIC.BUNDLES), "weekly", 0.6),
|
|
44
|
+
page(String(ROUTES.PUBLIC.PRIZE_DRAWS), "daily", 0.7),
|
|
45
|
+
page(String(ROUTES.PUBLIC.CLASSIFIED), "daily", 0.6),
|
|
46
|
+
page(String(ROUTES.PUBLIC.DIGITAL_CODES), "daily", 0.6),
|
|
47
|
+
page(String(ROUTES.PUBLIC.LIVE), "hourly", 0.7),
|
|
48
|
+
page(String(ROUTES.PUBLIC.ART), "weekly", 0.6),
|
|
42
49
|
page(String(ROUTES.PUBLIC.FEES), "monthly", 0.4),
|
|
43
50
|
page(String(ROUTES.PUBLIC.HOW_AUCTIONS_WORK), "monthly", 0.4),
|
|
44
51
|
page(String(ROUTES.PUBLIC.HOW_PRE_ORDERS_WORK), "monthly", 0.4),
|
|
@@ -53,13 +60,16 @@ function staticPages(baseUrl) {
|
|
|
53
60
|
page(String(ROUTES.PUBLIC.SCAM_FAQS), "weekly", 0.7),
|
|
54
61
|
];
|
|
55
62
|
}
|
|
63
|
+
// "art" and "stickers" listing types render at the same PRODUCT_DETAIL route
|
|
64
|
+
// as "standard" (see route-map.ts's ART comment) — no dedicated detail page.
|
|
65
|
+
const PRODUCT_DETAIL_LISTING_TYPES = ["standard", "art", "stickers"];
|
|
56
66
|
async function fetchProductUrls(baseUrl) {
|
|
57
67
|
try {
|
|
58
68
|
const db = getAdminDb();
|
|
59
69
|
const snap = await db
|
|
60
70
|
.collection(PRODUCT_COLLECTION)
|
|
61
71
|
.where(PRODUCT_STATUS, "==", PRODUCT_STATUS_PUBLISHED)
|
|
62
|
-
.where("listingType", "
|
|
72
|
+
.where("listingType", "in", PRODUCT_DETAIL_LISTING_TYPES)
|
|
63
73
|
.select(PRODUCT_SLUG, PRODUCT_UPDATED_AT)
|
|
64
74
|
.limit(5000)
|
|
65
75
|
.get();
|
|
@@ -80,6 +90,38 @@ async function fetchProductUrls(baseUrl) {
|
|
|
80
90
|
return [];
|
|
81
91
|
}
|
|
82
92
|
}
|
|
93
|
+
async function fetchListingTypeUrls(baseUrl, listingType, buildUrl, label) {
|
|
94
|
+
try {
|
|
95
|
+
const db = getAdminDb();
|
|
96
|
+
const snap = await db
|
|
97
|
+
.collection(PRODUCT_COLLECTION)
|
|
98
|
+
.where(PRODUCT_STATUS, "==", PRODUCT_STATUS_PUBLISHED)
|
|
99
|
+
.where("listingType", "==", listingType)
|
|
100
|
+
.select(PRODUCT_SLUG, PRODUCT_UPDATED_AT)
|
|
101
|
+
.limit(2000)
|
|
102
|
+
.get();
|
|
103
|
+
return snap.docs.map((doc) => {
|
|
104
|
+
const data = doc.data();
|
|
105
|
+
const slug = data[PRODUCT_SLUG] ?? doc.id;
|
|
106
|
+
return {
|
|
107
|
+
url: `${baseUrl}${buildUrl(slug)}`,
|
|
108
|
+
lastModified: data[PRODUCT_UPDATED_AT]?.toDate?.() ?? new Date(),
|
|
109
|
+
changeFrequency: "daily",
|
|
110
|
+
priority: 0.7,
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
void normalizeError(err);
|
|
116
|
+
serverLogger.warn(`sitemap: failed to fetch ${label} URLs`, { error: err });
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const fetchPreOrderUrls = (baseUrl) => fetchListingTypeUrls(baseUrl, "pre-order", (slug) => ROUTES.PUBLIC.PRE_ORDER_DETAIL(slug), "pre-order");
|
|
121
|
+
const fetchPrizeDrawUrls = (baseUrl) => fetchListingTypeUrls(baseUrl, "prize-draw", (slug) => ROUTES.PUBLIC.PRIZE_DRAW_DETAIL(slug), "prize-draw");
|
|
122
|
+
const fetchClassifiedUrls = (baseUrl) => fetchListingTypeUrls(baseUrl, "classified", (slug) => ROUTES.PUBLIC.CLASSIFIED_DETAIL(slug), "classified");
|
|
123
|
+
const fetchDigitalCodeUrls = (baseUrl) => fetchListingTypeUrls(baseUrl, "digital-code", (slug) => ROUTES.PUBLIC.DIGITAL_CODE_DETAIL(slug), "digital-code");
|
|
124
|
+
const fetchLiveUrls = (baseUrl) => fetchListingTypeUrls(baseUrl, "live", (slug) => ROUTES.PUBLIC.LIVE_DETAIL(slug), "live");
|
|
83
125
|
async function fetchAuctionUrls(baseUrl) {
|
|
84
126
|
try {
|
|
85
127
|
const db = getAdminDb();
|
|
@@ -133,11 +175,17 @@ async function fetchEventUrls(baseUrl) {
|
|
|
133
175
|
return [];
|
|
134
176
|
}
|
|
135
177
|
}
|
|
136
|
-
|
|
178
|
+
// categories is a discriminated-union collection (categoryType: "listing" |
|
|
179
|
+
// "brand" | "bundle" — see CLAUDE.md's SB-UNI-C/SB-UNI-D). Each discriminator
|
|
180
|
+
// renders at a different public route, so each needs its own filtered query;
|
|
181
|
+
// querying the collection without a categoryType filter (the prior bug here)
|
|
182
|
+
// mapped brand/bundle rows onto the wrong /categories/{slug} URL.
|
|
183
|
+
async function fetchCategoryTypeUrls(baseUrl, categoryType, buildUrl, label) {
|
|
137
184
|
try {
|
|
138
185
|
const db = getAdminDb();
|
|
139
186
|
const snap = await db
|
|
140
187
|
.collection(CATEGORIES_COLLECTION)
|
|
188
|
+
.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", categoryType)
|
|
141
189
|
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
142
190
|
.select(CATEGORY_FIELDS.SLUG, CATEGORY_FIELDS.UPDATED_AT)
|
|
143
191
|
.limit(500)
|
|
@@ -146,7 +194,7 @@ async function fetchCategoryUrls(baseUrl) {
|
|
|
146
194
|
const data = doc.data();
|
|
147
195
|
const slug = data[CATEGORY_FIELDS.SLUG] ?? doc.id;
|
|
148
196
|
return {
|
|
149
|
-
url: `${baseUrl}
|
|
197
|
+
url: `${baseUrl}${buildUrl(slug)}`,
|
|
150
198
|
lastModified: data[CATEGORY_FIELDS.UPDATED_AT]?.toDate?.() ?? new Date(),
|
|
151
199
|
changeFrequency: "weekly",
|
|
152
200
|
priority: 0.7,
|
|
@@ -155,10 +203,13 @@ async function fetchCategoryUrls(baseUrl) {
|
|
|
155
203
|
}
|
|
156
204
|
catch (err) {
|
|
157
205
|
void normalizeError(err);
|
|
158
|
-
serverLogger.warn(
|
|
206
|
+
serverLogger.warn(`sitemap: failed to fetch ${label} URLs`, { error: err });
|
|
159
207
|
return [];
|
|
160
208
|
}
|
|
161
209
|
}
|
|
210
|
+
const fetchCategoryUrls = (baseUrl) => fetchCategoryTypeUrls(baseUrl, "listing", (slug) => ROUTES.PUBLIC.CATEGORY_DETAIL(slug), "category");
|
|
211
|
+
const fetchBrandUrls = (baseUrl) => fetchCategoryTypeUrls(baseUrl, "brand", (slug) => ROUTES.PUBLIC.BRAND_DETAIL(slug), "brand");
|
|
212
|
+
const fetchBundleUrls = (baseUrl) => fetchCategoryTypeUrls(baseUrl, "bundle", (slug) => ROUTES.PUBLIC.BUNDLE_DETAIL(slug), "bundle");
|
|
162
213
|
async function fetchBlogPostUrls(baseUrl) {
|
|
163
214
|
try {
|
|
164
215
|
const db = getAdminDb();
|
|
@@ -242,21 +293,35 @@ async function fetchScammerUrls(baseUrl) {
|
|
|
242
293
|
}
|
|
243
294
|
}
|
|
244
295
|
export async function buildSitemap({ baseUrl }) {
|
|
245
|
-
const [productUrls, categoryUrls, eventUrls, blogUrls, auctionUrls, storeUrls, scammerUrls] = await Promise.all([
|
|
296
|
+
const [productUrls, categoryUrls, brandUrls, bundleUrls, eventUrls, blogUrls, auctionUrls, preOrderUrls, prizeDrawUrls, classifiedUrls, digitalCodeUrls, liveUrls, storeUrls, scammerUrls,] = await Promise.all([
|
|
246
297
|
fetchProductUrls(baseUrl),
|
|
247
298
|
fetchCategoryUrls(baseUrl),
|
|
299
|
+
fetchBrandUrls(baseUrl),
|
|
300
|
+
fetchBundleUrls(baseUrl),
|
|
248
301
|
fetchEventUrls(baseUrl),
|
|
249
302
|
fetchBlogPostUrls(baseUrl),
|
|
250
303
|
fetchAuctionUrls(baseUrl),
|
|
304
|
+
fetchPreOrderUrls(baseUrl),
|
|
305
|
+
fetchPrizeDrawUrls(baseUrl),
|
|
306
|
+
fetchClassifiedUrls(baseUrl),
|
|
307
|
+
fetchDigitalCodeUrls(baseUrl),
|
|
308
|
+
fetchLiveUrls(baseUrl),
|
|
251
309
|
fetchStoreUrls(baseUrl),
|
|
252
310
|
fetchScammerUrls(baseUrl),
|
|
253
311
|
]);
|
|
254
312
|
return [
|
|
255
313
|
...staticPages(baseUrl),
|
|
256
314
|
...categoryUrls,
|
|
315
|
+
...brandUrls,
|
|
316
|
+
...bundleUrls,
|
|
257
317
|
...blogUrls,
|
|
258
318
|
...productUrls,
|
|
259
319
|
...auctionUrls,
|
|
320
|
+
...preOrderUrls,
|
|
321
|
+
...prizeDrawUrls,
|
|
322
|
+
...classifiedUrls,
|
|
323
|
+
...digitalCodeUrls,
|
|
324
|
+
...liveUrls,
|
|
260
325
|
...eventUrls,
|
|
261
326
|
...storeUrls,
|
|
262
327
|
...scammerUrls,
|
|
@@ -4,3 +4,23 @@ export declare const AUCTIONS_SITEMAP_LIMIT = 5000;
|
|
|
4
4
|
export declare const AUCTION_DEFAULT_EXTENSION_MINUTES = 5;
|
|
5
5
|
export declare const AUCTION_MIN_BID_INCREMENT = 1;
|
|
6
6
|
export declare const AUCTION_SNIPING_WINDOW_SECONDS = 300;
|
|
7
|
+
export interface BidIncrementTier {
|
|
8
|
+
/** Upper bound (inclusive) of this band's current-bid range. `null` = open-ended ("and above"), must be the last tier. */
|
|
9
|
+
upTo: number | null;
|
|
10
|
+
increment: number;
|
|
11
|
+
}
|
|
12
|
+
/** Seed/fallback tier table — single source of truth reused by both DEFAULT_SITE_SETTINGS_DATA and the admin editor's initial state. */
|
|
13
|
+
export declare const DEFAULT_AUCTION_BID_INCREMENT_TIERS: BidIncrementTier[];
|
|
14
|
+
/**
|
|
15
|
+
* Resolve the tiered minimum bid increment for a given current bid amount.
|
|
16
|
+
* Tier lookup is inclusive of each band's upper bound — e.g. with the
|
|
17
|
+
* default tiers, a current bid of exactly 1000 resolves to the 100
|
|
18
|
+
* increment (the 100-1000 tier), not the 200 increment of the next band.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveTieredBidIncrement(currentBidAmount: number, tiers: BidIncrementTier[]): number;
|
|
21
|
+
/**
|
|
22
|
+
* Effective minimum bid increment = max(admin tier floor, per-listing
|
|
23
|
+
* override). A seller's per-listing "Minimum Bid Increment" can require
|
|
24
|
+
* MORE than the platform tier, but can never undercut it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveMinBidIncrement(currentBidAmount: number, tiers: BidIncrementTier[], override?: number | null): number;
|
|
@@ -2,5 +2,35 @@ export const AUCTIONS_PAGE_SIZE = 20;
|
|
|
2
2
|
export const AUCTIONS_ACTIVE_LIMIT = 50;
|
|
3
3
|
export const AUCTIONS_SITEMAP_LIMIT = 5000;
|
|
4
4
|
export const AUCTION_DEFAULT_EXTENSION_MINUTES = 5;
|
|
5
|
-
export const AUCTION_MIN_BID_INCREMENT = 1; // ₹1
|
|
5
|
+
export const AUCTION_MIN_BID_INCREMENT = 1; // ₹1 — last-resort fallback when bidIncrementTiers is empty/missing
|
|
6
6
|
export const AUCTION_SNIPING_WINDOW_SECONDS = 300; // 5 minutes — triggers auto-extend
|
|
7
|
+
/** Seed/fallback tier table — single source of truth reused by both DEFAULT_SITE_SETTINGS_DATA and the admin editor's initial state. */
|
|
8
|
+
export const DEFAULT_AUCTION_BID_INCREMENT_TIERS = [
|
|
9
|
+
{ upTo: 100, increment: 10 },
|
|
10
|
+
{ upTo: 1000, increment: 100 },
|
|
11
|
+
{ upTo: 5000, increment: 200 },
|
|
12
|
+
{ upTo: 10000, increment: 500 },
|
|
13
|
+
{ upTo: null, increment: 1000 },
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the tiered minimum bid increment for a given current bid amount.
|
|
17
|
+
* Tier lookup is inclusive of each band's upper bound — e.g. with the
|
|
18
|
+
* default tiers, a current bid of exactly 1000 resolves to the 100
|
|
19
|
+
* increment (the 100-1000 tier), not the 200 increment of the next band.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveTieredBidIncrement(currentBidAmount, tiers) {
|
|
22
|
+
for (const tier of tiers) {
|
|
23
|
+
if (tier.upTo === null || currentBidAmount <= tier.upTo)
|
|
24
|
+
return tier.increment;
|
|
25
|
+
}
|
|
26
|
+
return tiers[tiers.length - 1]?.increment ?? AUCTION_MIN_BID_INCREMENT;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Effective minimum bid increment = max(admin tier floor, per-listing
|
|
30
|
+
* override). A seller's per-listing "Minimum Bid Increment" can require
|
|
31
|
+
* MORE than the platform tier, but can never undercut it.
|
|
32
|
+
*/
|
|
33
|
+
export function resolveMinBidIncrement(currentBidAmount, tiers, override) {
|
|
34
|
+
const tierValue = resolveTieredBidIncrement(currentBidAmount, tiers);
|
|
35
|
+
return typeof override === "number" && override > tierValue ? override : tierValue;
|
|
36
|
+
}
|
|
@@ -7,7 +7,7 @@ export const config = {
|
|
|
7
7
|
slugPrefix: "art-",
|
|
8
8
|
cartLine: "single-product",
|
|
9
9
|
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
-
badge:
|
|
10
|
+
badge: { label: "Art Print", className: "bg-primary-700 text-white" },
|
|
11
11
|
priceLabel: "Price (₹)",
|
|
12
12
|
typeLabel: "Art Print",
|
|
13
13
|
showsStockQuantity: true,
|
|
@@ -6,8 +6,8 @@ export const config = {
|
|
|
6
6
|
listingType: LISTING_TYPE,
|
|
7
7
|
slugPrefix: "classified-",
|
|
8
8
|
cartLine: "blocked",
|
|
9
|
-
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.
|
|
10
|
-
badge:
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.CLASSIFIED_DETAIL(idOrSlug)),
|
|
10
|
+
badge: { label: "Classified", className: "bg-secondary text-white" },
|
|
11
11
|
priceLabel: "Asking Price (₹)",
|
|
12
12
|
typeLabel: "Classified",
|
|
13
13
|
showsStockQuantity: true,
|
|
@@ -6,8 +6,8 @@ export const config = {
|
|
|
6
6
|
listingType: LISTING_TYPE,
|
|
7
7
|
slugPrefix: "digitalcode-",
|
|
8
8
|
cartLine: "single-product",
|
|
9
|
-
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.
|
|
10
|
-
badge:
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.DIGITAL_CODE_DETAIL(idOrSlug)),
|
|
10
|
+
badge: { label: "Digital Code", className: "bg-success-surface text-success" },
|
|
11
11
|
priceLabel: "Price per Code (₹)",
|
|
12
12
|
typeLabel: "Digital Code",
|
|
13
13
|
showsStockQuantity: false,
|
|
@@ -6,8 +6,8 @@ export const config = {
|
|
|
6
6
|
listingType: LISTING_TYPE,
|
|
7
7
|
slugPrefix: "live-",
|
|
8
8
|
cartLine: "single-product",
|
|
9
|
-
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.
|
|
10
|
-
badge:
|
|
9
|
+
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.LIVE_DETAIL(idOrSlug)),
|
|
10
|
+
badge: { label: "Live Item", className: "bg-danger-surface text-error" },
|
|
11
11
|
priceLabel: "Price (₹)",
|
|
12
12
|
typeLabel: "Live Item",
|
|
13
13
|
showsStockQuantity: true,
|
|
@@ -7,7 +7,7 @@ export const config = {
|
|
|
7
7
|
slugPrefix: "prizedraw-",
|
|
8
8
|
cartLine: "single-product",
|
|
9
9
|
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRIZE_DRAW_DETAIL(idOrSlug)),
|
|
10
|
-
badge:
|
|
10
|
+
badge: { label: "Prize Draw", className: "bg-primary text-white" },
|
|
11
11
|
priceLabel: "Price (₹)",
|
|
12
12
|
typeLabel: "Prize Draw",
|
|
13
13
|
showsStockQuantity: false,
|
|
@@ -7,7 +7,7 @@ export const config = {
|
|
|
7
7
|
slugPrefix: "sticker-",
|
|
8
8
|
cartLine: "single-product",
|
|
9
9
|
detailRoute: (idOrSlug) => String(ROUTES.PUBLIC.PRODUCT_DETAIL(idOrSlug)),
|
|
10
|
-
badge:
|
|
10
|
+
badge: { label: "Sticker Sheet", className: "bg-primary-700 text-white" },
|
|
11
11
|
priceLabel: "Price (₹)",
|
|
12
12
|
typeLabel: "Stickers",
|
|
13
13
|
showsStockQuantity: true,
|
package/dist/client.d.ts
CHANGED
|
@@ -24,11 +24,15 @@ export { registerClientRealtimeProvider, getClientRealtimeProvider, type IClient
|
|
|
24
24
|
export { registerClientSessionAdapter, getClientSessionAdapter, type IClientSessionAdapter, type AdapterAuthUser, type AuthUnsubscribe, } from "./contracts/client-session";
|
|
25
25
|
export { ThemeProvider, useTheme, buildThemeRegistry } from "./theme";
|
|
26
26
|
export type { ModePreference, SiteSettingsThemeInput, ThemeContextValue, ThemeProviderProps, ThemeRegistry, } from "./theme";
|
|
27
|
+
export { HandModeProvider, useHandMode } from "./hand-mode";
|
|
28
|
+
export type { HandMode, HandModeContextValue, HandModeProviderProps, } from "./hand-mode";
|
|
27
29
|
export { BUILT_IN_THEMES, DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, REQUIRED_GRADIENT_KEYS, REQUIRED_THEME_TOKENS, getDefaultBuiltInTheme, } from "./tokens/themes";
|
|
28
30
|
export type { GradientKey, RequiredThemeToken, ThemeMode, ThemeRecord, } from "./tokens/themes";
|
|
29
31
|
export { ConfirmDeleteModal } from "./ui/components/ConfirmDeleteModal";
|
|
30
32
|
export { EmptyState } from "./ui/components/EmptyState";
|
|
31
33
|
export { Skeleton } from "./ui/components/Skeleton";
|
|
34
|
+
export { IconBox } from "./ui/components/IconBox";
|
|
35
|
+
export type { IconBoxProps, IconBoxRounded, IconBoxSize, IconBoxTone, } from "./ui/components/IconBox";
|
|
32
36
|
export { Alert } from "./ui/components/Alert";
|
|
33
37
|
export type { SkeletonProps } from "./ui/components/Skeleton";
|
|
34
38
|
export { Divider } from "./ui/components/Divider";
|
|
@@ -327,14 +331,8 @@ export { ActionPermissionsManager } from "./features/site-settings/components/Ac
|
|
|
327
331
|
export type { ActionPermissionsManagerProps } from "./features/site-settings/components/ActionPermissionsManager";
|
|
328
332
|
export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
|
|
329
333
|
export type { NavPermissionsManagerProps, NavGroup as NavPermissionsGroup, NavItem as NavPermissionsItem } from "./features/site-settings/components/NavPermissionsManager";
|
|
330
|
-
export { ClassifiedDetailView } from "./_internal/client/features/classified/ClassifiedDetailView";
|
|
331
|
-
export type { ClassifiedDetailViewProps } from "./_internal/client/features/classified/ClassifiedDetailView";
|
|
332
|
-
export { DigitalCodeDetailView } from "./_internal/client/features/digital-code/DigitalCodeDetailView";
|
|
333
|
-
export type { DigitalCodeDetailViewProps } from "./_internal/client/features/digital-code/DigitalCodeDetailView";
|
|
334
334
|
export { CodeRevealPanel } from "./_internal/client/features/digital-code/CodeRevealPanel";
|
|
335
335
|
export type { CodeRevealPanelProps, RevealedCode } from "./_internal/client/features/digital-code/CodeRevealPanel";
|
|
336
|
-
export { LiveItemDetailView } from "./_internal/client/features/live/LiveItemDetailView";
|
|
337
|
-
export type { LiveItemDetailViewProps } from "./_internal/client/features/live/LiveItemDetailView";
|
|
338
336
|
export { PhysicalLocationModal } from "./features/seller/components/PhysicalLocationModal";
|
|
339
337
|
export type { PhysicalLocation } from "./features/seller/components/PhysicalLocationModal";
|
|
340
338
|
export { Toggle } from "./ui/components/Toggle";
|
package/dist/client.js
CHANGED
|
@@ -32,6 +32,12 @@ export { registerClientSessionAdapter, getClientSessionAdapter, } from "./contra
|
|
|
32
32
|
// Re-exported through the public `./theme` barrel to keep audit-appkit-reexports
|
|
33
33
|
// clean (no `_internal/` symbols may surface through public barrels).
|
|
34
34
|
export { ThemeProvider, useTheme, buildThemeRegistry } from "./theme";
|
|
35
|
+
// [CLIENT-ONLY] HandModeProvider — applies the "left-hand mode" layout
|
|
36
|
+
// preference to `<html>` via a `data-hand` attribute so drawers/sidebars/
|
|
37
|
+
// close-buttons/floating CTAs flip which screen edge they dock to.
|
|
38
|
+
// Re-exported through the public `./hand-mode` barrel to keep
|
|
39
|
+
// audit-appkit-reexports clean (no `_internal/` symbols in public barrels).
|
|
40
|
+
export { HandModeProvider, useHandMode } from "./hand-mode";
|
|
35
41
|
export { BUILT_IN_THEMES, DEFAULT_DARK_THEME, DEFAULT_LIGHT_THEME, REQUIRED_GRADIENT_KEYS, REQUIRED_THEME_TOKENS, getDefaultBuiltInTheme, } from "./tokens/themes";
|
|
36
42
|
// [CLIENT-ONLY]-Cannot run in SSR mode â€" uses browser-only APIs (window, navigator, localStorage, matchMedia, DOM events) that do not exist in Node.js.
|
|
37
43
|
// ConfirmDeleteModal - Component for confirm delete modal.
|
|
@@ -39,6 +45,9 @@ export { ConfirmDeleteModal } from "./ui/components/ConfirmDeleteModal";
|
|
|
39
45
|
// S-STORE — pure-UI primitives + Seller view consumed by new dashboard pages
|
|
40
46
|
export { EmptyState } from "./ui/components/EmptyState";
|
|
41
47
|
export { Skeleton } from "./ui/components/Skeleton";
|
|
48
|
+
// IconBox — square-icon container primitive; was exported from index.ts only,
|
|
49
|
+
// missing here even though CLAUDE.md documents it as a client-usable pattern.
|
|
50
|
+
export { IconBox } from "./ui/components/IconBox";
|
|
42
51
|
export { Alert } from "./ui/components/Alert";
|
|
43
52
|
export { Divider } from "./ui/components/Divider";
|
|
44
53
|
export { Tabs, TabsList, TabsTrigger, TabsContent } from "./ui/components/Tabs";
|
|
@@ -324,11 +333,8 @@ export { SellerTrustBadge } from "./features/scams/components/SellerTrustBadge";
|
|
|
324
333
|
// [CLIENT-ONLY] — Admin panel components for action/nav permission management.
|
|
325
334
|
export { ActionPermissionsManager } from "./features/site-settings/components/ActionPermissionsManager";
|
|
326
335
|
export { NavPermissionsManager } from "./features/site-settings/components/NavPermissionsManager";
|
|
327
|
-
// ──
|
|
328
|
-
export { ClassifiedDetailView } from "./_internal/client/features/classified/ClassifiedDetailView";
|
|
329
|
-
export { DigitalCodeDetailView } from "./_internal/client/features/digital-code/DigitalCodeDetailView";
|
|
336
|
+
// ── Digital-code code-reveal panel (still used directly on order pages) ───────
|
|
330
337
|
export { CodeRevealPanel } from "./_internal/client/features/digital-code/CodeRevealPanel";
|
|
331
|
-
export { LiveItemDetailView } from "./_internal/client/features/live/LiveItemDetailView";
|
|
332
338
|
export { PhysicalLocationModal } from "./features/seller/components/PhysicalLocationModal";
|
|
333
339
|
// [CLIENT-ONLY] — Toggle switch primitive.
|
|
334
340
|
export { Toggle } from "./ui/components/Toggle";
|
|
@@ -66,6 +66,7 @@ export declare const ACCOUNT_ENDPOINTS: {
|
|
|
66
66
|
readonly CATALOGUE_LIST: (id: string) => string;
|
|
67
67
|
readonly CATALOGUE_SUBMIT: (id: string) => string;
|
|
68
68
|
readonly PUBLIC_CATALOGUE: (ownerSlug: string) => string;
|
|
69
|
+
readonly PUBLIC_CATALOGUE_ITEM: (ownerSlug: string, itemId: string) => string;
|
|
69
70
|
/** Tester Hub — GET active checklist items joined with the tester's own responses; PUT upserts one item's answer/comment/screenshot. */
|
|
70
71
|
readonly TESTER_CHECKLIST: "/api/user/tester-checklist";
|
|
71
72
|
readonly TESTER_CHECKLIST_ITEM_BY_ID: (checklistItemId: string) => string;
|
|
@@ -249,6 +250,7 @@ export declare const CATEGORY_ENDPOINTS: {
|
|
|
249
250
|
export declare const CHECKOUT_ENDPOINTS: {
|
|
250
251
|
readonly PREFLIGHT: "/api/checkout/preflight";
|
|
251
252
|
readonly PLACE_ORDER: "/api/checkout";
|
|
253
|
+
readonly PRICING_PREVIEW: "/api/checkout/pricing-preview";
|
|
252
254
|
};
|
|
253
255
|
export declare const PAYMENT_ENDPOINTS: {
|
|
254
256
|
readonly CREATE_ORDER: "/api/payment/create-order";
|
|
@@ -517,6 +519,7 @@ export declare const API_ENDPOINTS: {
|
|
|
517
519
|
readonly CATALOGUE_LIST: (id: string) => string;
|
|
518
520
|
readonly CATALOGUE_SUBMIT: (id: string) => string;
|
|
519
521
|
readonly PUBLIC_CATALOGUE: (ownerSlug: string) => string;
|
|
522
|
+
readonly PUBLIC_CATALOGUE_ITEM: (ownerSlug: string, itemId: string) => string;
|
|
520
523
|
/** Tester Hub — GET active checklist items joined with the tester's own responses; PUT upserts one item's answer/comment/screenshot. */
|
|
521
524
|
readonly TESTER_CHECKLIST: "/api/user/tester-checklist";
|
|
522
525
|
readonly TESTER_CHECKLIST_ITEM_BY_ID: (checklistItemId: string) => string;
|
|
@@ -703,6 +706,7 @@ export declare const API_ENDPOINTS: {
|
|
|
703
706
|
readonly CHECKOUT: {
|
|
704
707
|
readonly PREFLIGHT: "/api/checkout/preflight";
|
|
705
708
|
readonly PLACE_ORDER: "/api/checkout";
|
|
709
|
+
readonly PRICING_PREVIEW: "/api/checkout/pricing-preview";
|
|
706
710
|
};
|
|
707
711
|
readonly PAYMENT: {
|
|
708
712
|
readonly CREATE_ORDER: "/api/payment/create-order";
|
|
@@ -970,6 +974,7 @@ export declare const API_ROUTES: {
|
|
|
970
974
|
readonly CATALOGUE_LIST: (id: string) => string;
|
|
971
975
|
readonly CATALOGUE_SUBMIT: (id: string) => string;
|
|
972
976
|
readonly PUBLIC_CATALOGUE: (ownerSlug: string) => string;
|
|
977
|
+
readonly PUBLIC_CATALOGUE_ITEM: (ownerSlug: string, itemId: string) => string;
|
|
973
978
|
/** Tester Hub — GET active checklist items joined with the tester's own responses; PUT upserts one item's answer/comment/screenshot. */
|
|
974
979
|
readonly TESTER_CHECKLIST: "/api/user/tester-checklist";
|
|
975
980
|
readonly TESTER_CHECKLIST_ITEM_BY_ID: (checklistItemId: string) => string;
|
|
@@ -1156,6 +1161,7 @@ export declare const API_ROUTES: {
|
|
|
1156
1161
|
readonly CHECKOUT: {
|
|
1157
1162
|
readonly PREFLIGHT: "/api/checkout/preflight";
|
|
1158
1163
|
readonly PLACE_ORDER: "/api/checkout";
|
|
1164
|
+
readonly PRICING_PREVIEW: "/api/checkout/pricing-preview";
|
|
1159
1165
|
};
|
|
1160
1166
|
readonly PAYMENT: {
|
|
1161
1167
|
readonly CREATE_ORDER: "/api/payment/create-order";
|
|
@@ -81,6 +81,7 @@ export const ACCOUNT_ENDPOINTS = {
|
|
|
81
81
|
CATALOGUE_LIST: (id) => `/api/user/catalogue/${id}/list`,
|
|
82
82
|
CATALOGUE_SUBMIT: (id) => `/api/user/catalogue/${id}/submit`,
|
|
83
83
|
PUBLIC_CATALOGUE: (ownerSlug) => `/api/catalogue/${ownerSlug}`,
|
|
84
|
+
PUBLIC_CATALOGUE_ITEM: (ownerSlug, itemId) => `/api/catalogue/${ownerSlug}/${itemId}`,
|
|
84
85
|
/** Tester Hub — GET active checklist items joined with the tester's own responses; PUT upserts one item's answer/comment/screenshot. */
|
|
85
86
|
TESTER_CHECKLIST: "/api/user/tester-checklist",
|
|
86
87
|
TESTER_CHECKLIST_ITEM_BY_ID: (checklistItemId) => `/api/user/tester-checklist/${encodeURIComponent(checklistItemId)}`,
|
|
@@ -295,6 +296,7 @@ export const CATEGORY_ENDPOINTS = {
|
|
|
295
296
|
export const CHECKOUT_ENDPOINTS = {
|
|
296
297
|
PREFLIGHT: "/api/checkout/preflight",
|
|
297
298
|
PLACE_ORDER: "/api/checkout",
|
|
299
|
+
PRICING_PREVIEW: "/api/checkout/pricing-preview",
|
|
298
300
|
};
|
|
299
301
|
// ---------------------------------------------------------------------------
|
|
300
302
|
// Payment
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Avatar, Badge, Card, Div, Heading, Row, Section, Span, Stack, Text } from "../../../ui";
|
|
2
|
+
import { Anchor, Avatar, Badge, Card, Div, Heading, Row, Section, Span, Stack, Text } from "../../../ui";
|
|
3
3
|
export function AboutView({ labels = {}, howItems = [], valueItems = [], milestones = [], teamMembers = [], ctaBannerClass = "", renderCtaButtons, }) {
|
|
4
|
-
return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "y-4xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-6", mdSize: "5xl", size: "4xl", weight: "bold", children: labels.title }), _jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", size: "xl", children: labels.subtitle })] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-5xl mx-auto", padding: "y-4xl", children: [_jsxs(Section, { className: "text-center max-w-3xl mx-auto", children: [_jsx(Heading, { level: 2, className: "mb-4", children: labels.missionTitle }), _jsx(Text, { size: "lg", variant: "secondary", className: "leading-relaxed", children: labels.missionText })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.howItWorksTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: howItems.map(({ title, text, icon, tone }) => (_jsxs(Card, { variant: `gradient-${tone ?? "indigo"}`, padding: "md", spacing: "sm", children: [_jsx(Div, { children: _jsx(Span, { size: "4xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.valuesTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "5", children: valueItems.map(({ title, text, icon }) => (_jsxs(Stack, { gap: "3", surface: "default", padding: "lg", rounded: "xl", border: "default", children: [_jsx(Div, { children: _jsx(Span, { size: "3xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: labels.milestonesTitle }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl mx-auto pl-[2rem]", gap: "xl", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] }), teamMembers.length > 0 && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-2", align: "center", children: labels.teamTitle }), labels.teamSubtitle && (_jsx(Text, { size: "lg", variant: "secondary", align: "center", className: "mb-12 max-w-2xl mx-auto", children: labels.teamSubtitle })), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: teamMembers.map((member) => (_jsxs(Stack, { gap: "3", surface: "default", padding: "lg", rounded: "xl", border: "default", align: "center", className: "text-center", children: [_jsx(Avatar, { src: member.photoUrl, name: member.name, alt: member.name, size: "lg" }), _jsx(Heading, { level: 3, children: member.name }), _jsxs(Row, { gap: "xs", wrap: true, justify: "center", children: [_jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: member.role }), member.isFounder && _jsx(Badge, { variant: "primary", size: "xs", children: "Founder" }), member.isDeveloper && _jsx(Badge, { variant: "secondary", size: "xs", children: "Developer" })] }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: member.bio })] }, member.name))) })] })), _jsxs(Section, { color: "inverse", tone: "accent-banner", className: `text-center ${ctaBannerClass}`, padding: "xl", rounded: "2xl", children: [_jsx(Heading, { color: "inverse", level: 2, variant: "none", className: "mb-8", size: "3xl", weight: "bold", children: labels.ctaTitle }), renderCtaButtons ? (renderCtaButtons()) : (_jsx(Row, { justify: "center", gap: "3", wrap: true, children: _jsxs(Span, { color: "inverse", size: "sm", className: "/70", children: [labels.ctaSell, " \u00B7 ", labels.ctaShop] }) }))] })] })] }));
|
|
4
|
+
return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "y-4xl", children: _jsxs(Div, { paddingX: "x-page", className: "max-w-4xl mx-auto text-center", children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-6", mdSize: "5xl", size: "4xl", weight: "bold", children: labels.title }), _jsx(Text, { color: "inverse", variant: "none", className: "/80 max-w-2xl mx-auto", size: "xl", children: labels.subtitle })] }) }), _jsxs(Div, { paddingX: "x-page", className: "max-w-5xl mx-auto", padding: "y-4xl", children: [_jsxs(Section, { className: "text-center max-w-3xl mx-auto", children: [_jsx(Heading, { level: 2, className: "mb-4", children: labels.missionTitle }), _jsx(Text, { size: "lg", variant: "secondary", className: "leading-relaxed", children: labels.missionText })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.howItWorksTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: howItems.map(({ title, text, icon, tone }) => (_jsxs(Card, { variant: `gradient-${tone ?? "indigo"}`, padding: "md", spacing: "sm", children: [_jsx(Div, { children: _jsx(Span, { size: "4xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-12", align: "center", children: labels.valuesTitle }), _jsx(Div, { className: "grid md:grid-cols-3", gap: "5", children: valueItems.map(({ title, text, icon }) => (_jsxs(Stack, { gap: "3", surface: "default", padding: "lg", rounded: "xl", border: "default", children: [_jsx(Div, { children: _jsx(Span, { size: "3xl", children: icon }) }), _jsx(Heading, { level: 3, children: title }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: text })] }, title))) })] }), _jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-10", align: "center", children: labels.milestonesTitle }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl mx-auto pl-[2rem]", gap: "xl", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] }), teamMembers.length > 0 && (_jsxs(Section, { children: [_jsx(Heading, { level: 2, className: "mb-2", align: "center", children: labels.teamTitle }), labels.teamSubtitle && (_jsx(Text, { size: "lg", variant: "secondary", align: "center", className: "mb-12 max-w-2xl mx-auto", children: labels.teamSubtitle })), _jsx(Div, { className: "grid md:grid-cols-3", gap: "6", children: teamMembers.map((member) => (_jsxs(Stack, { gap: "3", surface: "default", padding: "lg", rounded: "xl", border: "default", align: "center", className: "text-center", children: [_jsx(Avatar, { src: member.photoUrl, name: member.name, alt: member.name, size: "lg" }), _jsx(Heading, { level: 3, children: member.name }), _jsxs(Row, { gap: "xs", wrap: true, justify: "center", children: [_jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: member.role }), member.isFounder && _jsx(Badge, { variant: "primary", size: "xs", children: "Founder" }), member.isDeveloper && _jsx(Badge, { variant: "secondary", size: "xs", children: "Developer" })] }), _jsx(Text, { size: "sm", variant: "secondary", className: "leading-relaxed", children: member.bio }), member.githubUrl && (_jsx(Anchor, { href: member.githubUrl, tone: "muted", size: "sm", underline: "hover", children: "GitHub \u2197" }))] }, member.name))) })] })), _jsxs(Section, { color: "inverse", tone: "accent-banner", className: `text-center ${ctaBannerClass}`, padding: "xl", rounded: "2xl", children: [_jsx(Heading, { color: "inverse", level: 2, variant: "none", className: "mb-8", size: "3xl", weight: "bold", children: labels.ctaTitle }), renderCtaButtons ? (renderCtaButtons()) : (_jsx(Row, { justify: "center", gap: "3", wrap: true, children: _jsxs(Span, { color: "inverse", size: "sm", className: "/70", children: [labels.ctaSell, " \u00B7 ", labels.ctaShop] }) }))] })] })] }));
|
|
5
5
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { normalizeError } from "../../../errors/normalize";
|
|
3
|
-
import { Avatar, Badge, Div, Heading, Row, Section, Span, Stack, Text, TextLink } from "../../../ui";
|
|
3
|
+
import { Anchor, Avatar, Badge, Div, Heading, Row, Section, Span, Stack, Text, TextLink } from "../../../ui";
|
|
4
4
|
import { ROUTES } from "../../../constants";
|
|
5
5
|
import { PAGE_CONTAINER } from "../../../_internal/shared/styles/page";
|
|
6
6
|
import { siteSettingsRepository } from "../../../repositories";
|
|
@@ -25,5 +25,5 @@ export async function DeveloperView({ labels = {} }) {
|
|
|
25
25
|
// Firestore unavailable — render the empty state below rather than crash.
|
|
26
26
|
}
|
|
27
27
|
const developers = teamMembers.filter((m) => m.isDeveloper);
|
|
28
|
-
return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm}`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-3", children: labels.title ?? "Meet the Developer" }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", size: "sm", children: labels.subtitle ?? "The person building LetItRip, one feature at a time." })] }) }), _jsxs(Div, { className: `${page.container.sm}`, padding: "content-banner", children: [developers.length === 0 ? (_jsx(Text, { variant: "secondary", children: labels.empty ?? "Developer profile coming soon." })) : (_jsx(Stack, { gap: "xl", children: developers.map((dev) => (_jsxs(Stack, { gap: "md", surface: "default", padding: "lg", rounded: "xl", border: "default", children: [_jsxs(Row, { gap: "md", align: "center", children: [_jsx(Avatar, { src: dev.photoUrl, name: dev.name, alt: dev.name, size: "lg" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, children: dev.name }), _jsxs(Row, { gap: "xs", wrap: true, children: [_jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: dev.role }), dev.isFounder && _jsx(Badge, { variant: "primary", size: "xs", children: "Founder" }), _jsx(Badge, { variant: "secondary", size: "xs", children: "Developer" })] })] })] }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", children: dev.bio })] }, dev.name))) })), milestones.length > 0 && (_jsxs(Div, { className: "mt-14 border-t", border: "default", padding: "t-xl", children: [_jsx(Heading, { level: 3, className: "mb-6", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.journeyTitle ?? "The Journey" }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl pl-[2rem]", gap: "lg", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] })), _jsx(Div, { className: "mt-10", children: _jsx(TextLink, { href: String(ROUTES.PUBLIC.ABOUT), variant: "muted", size: "sm", children: labels.backToTeam ?? "← Meet the whole team" }) })] })] }));
|
|
28
|
+
return (_jsxs(Div, { className: "-mx-4 md:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 lg:-mt-10", children: [_jsx(Section, { color: "inverse", tone: "accent-banner", padding: "banner", children: _jsxs(Div, { className: `${page.container.sm}`, children: [_jsx(Heading, { color: "inverse", level: 1, variant: "none", className: "mb-3", children: labels.title ?? "Meet the Developer" }), _jsx(Text, { color: "inverse", variant: "none", className: "/80", size: "sm", children: labels.subtitle ?? "The person building LetItRip, one feature at a time." })] }) }), _jsxs(Div, { className: `${page.container.sm}`, padding: "content-banner", children: [developers.length === 0 ? (_jsx(Text, { variant: "secondary", children: labels.empty ?? "Developer profile coming soon." })) : (_jsx(Stack, { gap: "xl", children: developers.map((dev) => (_jsxs(Stack, { gap: "md", surface: "default", padding: "lg", rounded: "xl", border: "default", children: [_jsxs(Row, { gap: "md", align: "center", children: [_jsx(Avatar, { src: dev.photoUrl, name: dev.name, alt: dev.name, size: "lg" }), _jsxs(Stack, { gap: "xs", children: [_jsx(Heading, { level: 2, children: dev.name }), _jsxs(Row, { gap: "xs", wrap: true, children: [_jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: dev.role }), dev.isFounder && _jsx(Badge, { variant: "primary", size: "xs", children: "Founder" }), _jsx(Badge, { variant: "secondary", size: "xs", children: "Developer" })] })] })] }), _jsx(Text, { variant: "secondary", className: "leading-relaxed", children: dev.bio }), dev.githubUrl && (_jsx(Anchor, { href: dev.githubUrl, tone: "brand", size: "sm", underline: "hover", children: "GitHub \u2197" }))] }, dev.name))) })), milestones.length > 0 && (_jsxs(Div, { className: "mt-14 border-t", border: "default", padding: "t-xl", children: [_jsx(Heading, { level: 3, className: "mb-6", color: "muted", size: "sm", weight: "semibold", transform: "uppercase", children: labels.journeyTitle ?? "The Journey" }), _jsx(Stack, { className: "relative border-l-2 border-primary/30 max-w-2xl pl-[2rem]", gap: "lg", children: milestones.map(({ year, text }) => (_jsxs(Div, { className: "relative", children: [_jsx(Div, { className: "absolute -left-10 top-1 w-4 h-4 bg-primary border-2 border-white", rounded: "full" }), _jsx(Span, { size: "xs", weight: "bold", className: "text-primary tracking-wide", transform: "uppercase", children: year }), _jsx(Text, { className: "mt-1", children: text })] }, year))) })] })), _jsx(Div, { className: "mt-10", children: _jsx(TextLink, { href: String(ROUTES.PUBLIC.ABOUT), variant: "muted", size: "sm", children: labels.backToTeam ?? "← Meet the whole team" }) })] })] }));
|
|
29
29
|
}
|
|
@@ -9,6 +9,8 @@ import { BottomSheet } from "../../layout/BottomSheet";
|
|
|
9
9
|
import { SidebarCollapseToggle } from "../../../_internal/client/features/layout/SidebarCollapseToggle";
|
|
10
10
|
import { useSidebarSearch } from "../../../_internal/client/features/layout/useSidebarSearch";
|
|
11
11
|
import { findActiveNavGroup, findActiveNavItem } from "../../../_internal/client/features/layout/navActive";
|
|
12
|
+
import { getSidebarRailClasses, getSidebarOverlayClasses } from "../../../_internal/client/features/layout/sidebarPositionClasses";
|
|
13
|
+
import { useHandMode } from "../../../_internal/client/hand-mode";
|
|
12
14
|
const __O = {
|
|
13
15
|
hidden: "overflow-hidden",
|
|
14
16
|
yAuto: "overflow-y-auto",
|
|
@@ -75,11 +77,15 @@ function DrawerContent({ groups, items, activeHref, onItemClick, }) {
|
|
|
75
77
|
})] }));
|
|
76
78
|
}
|
|
77
79
|
function DrawerPanel({ title, onClose, children, }) {
|
|
78
|
-
|
|
80
|
+
const { hand } = useHandMode();
|
|
81
|
+
const { edgeClass, borderClass } = getSidebarOverlayClasses(hand);
|
|
82
|
+
return (_jsxs(Div, { className: "hidden lg:block", children: [_jsx(Div, { surface: "overlay-xs", className: "fixed inset-0 z-40 backdrop-blur-sm", onClick: onClose, "aria-hidden": "true" }), _jsxs(Stack, { border: "default", shadow: "2xl", role: "dialog", "aria-modal": "true", "aria-label": title, className: `fixed top-0 ${edgeClass} z-50 h-full w-64 ${borderClass}`, surface: "default", children: [_jsxs(Row, { border: "bottom-subtle", paddingY: "y-sm-tall", className: "shrink-0", padding: "x-md", align: "center", justify: "between", children: [_jsx(Span, { size: "xs", weight: "semibold", transform: "uppercase", color: "muted", children: title }), _jsx(IconButton, { "aria-label": "Close", variant: "ghost", size: "sm", onClick: onClose, icon: _jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx(Div, { className: `flex-1 ${__O.yAuto}`, children: children })] })] }));
|
|
79
83
|
}
|
|
80
84
|
export function UserSidebar({ items, groups, mobileOpen = false, onCloseMobile, desktopOpen = false, onToggle, variant = "overlay", renderFooter }) {
|
|
81
85
|
const pathname = usePathname();
|
|
82
86
|
const close = onCloseMobile ?? (() => { });
|
|
87
|
+
const { hand } = useHandMode();
|
|
88
|
+
const rail = getSidebarRailClasses(hand);
|
|
83
89
|
const [mounted, setMounted] = useState(false);
|
|
84
90
|
useEffect(() => { setMounted(true); }, []);
|
|
85
91
|
useEffect(() => {
|
|
@@ -91,7 +97,7 @@ export function UserSidebar({ items, groups, mobileOpen = false, onCloseMobile,
|
|
|
91
97
|
// ── Persistent sidebar variant (desktop left slide-over, mobile bottom-sheet) ──────
|
|
92
98
|
if (variant === "sidebar") {
|
|
93
99
|
const handleToggle = onToggle ?? close;
|
|
94
|
-
return (_jsxs(_Fragment, { children: [desktopOpen && (_jsx(Div, { surface: "overlay-xs", className: "hidden lg:block fixed inset-0 backdrop-blur-[2px] z-30", onClick: handleToggle, "aria-hidden": "true" })), _jsxs(Div, { className: `hidden lg:flex fixed
|
|
100
|
+
return (_jsxs(_Fragment, { children: [desktopOpen && (_jsx(Div, { surface: "overlay-xs", className: "hidden lg:block fixed inset-0 backdrop-blur-[2px] z-30", onClick: handleToggle, "aria-hidden": "true" })), _jsxs(Div, { className: `hidden lg:flex fixed ${rail.edgeClass} z-40 transition-transform duration-300 top-[var(--header-height,3.5rem)] h-[calc(100vh-var(--header-height,3.5rem))] w-[13rem] ${desktopOpen ? "translate-x-0" : rail.collapsedTranslateClass}`, children: [_jsxs(Stack, { border: "default", surface: "default", className: `flex-1 ${rail.borderClass} dark:border-[var(--appkit-color-border)] ${__O.hidden}`, shadow: "xl", children: [_jsx(Div, { border: "bottom-subtle", paddingY: "y-sm-tall", className: "shrink-0", padding: "x-md", children: _jsx(Span, { size: "xs", weight: "semibold", transform: "uppercase", color: "muted", children: "My Account" }) }), _jsx(Div, { className: `flex-1 ${__O.yAuto}`, children: _jsx(DrawerContent, { groups: groups, items: items, activeHref: pathname }) }), renderFooter && _jsx(Div, { border: "top", padding: "inline", children: renderFooter() })] }), _jsx(SidebarCollapseToggle, { expanded: desktopOpen, onToggle: handleToggle, edge: hand })] }), _jsx(Div, { className: "lg:hidden", children: _jsx(BottomSheet, { open: mobileOpen, onClose: close, title: "My Account", children: _jsx(DrawerContent, { groups: groups, items: items, activeHref: pathname, onItemClick: close }) }) })] }));
|
|
95
101
|
}
|
|
96
102
|
// ── Overlay variant (default) — portal on desktop, bottom-sheet on mobile ─
|
|
97
103
|
const content = (_jsx(DrawerContent, { groups: groups, items: items, activeHref: pathname, onItemClick: close }));
|
|
@@ -14,6 +14,7 @@ export interface UserProfile {
|
|
|
14
14
|
uiPreferences?: {
|
|
15
15
|
collapsedSections?: string[];
|
|
16
16
|
dataViewMode?: "table" | "grid" | "list";
|
|
17
|
+
handMode?: "left" | "right";
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
export interface UpdateCurrentProfileInput {
|
|
@@ -33,6 +34,7 @@ export interface UpdateCurrentProfileInput {
|
|
|
33
34
|
uiPreferences?: {
|
|
34
35
|
collapsedSections?: string[];
|
|
35
36
|
dataViewMode?: "table" | "grid" | "list";
|
|
37
|
+
handMode?: "left" | "right";
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
export declare function useCurrentProfile(options?: {
|