@mohasinac/appkit 2.8.4 → 2.8.6
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/SidebarCollapseToggle.js +2 -0
- package/dist/_internal/server/features/checkout/actions.js +2 -1
- package/dist/_internal/server/features/grouped/data.js +9 -8
- package/dist/_internal/server/features/products/data.js +2 -1
- package/dist/_internal/server/features/refunds/actions.js +2 -1
- package/dist/_internal/server/features/seo/sitemap.js +2 -1
- package/dist/_internal/server/jobs/core/countersReconcile.js +4 -4
- package/dist/_internal/shared/features/blog/schema.d.ts +4 -4
- package/dist/_internal/shared/features/categories/bundle-schemas.d.ts +8 -8
- package/dist/_internal/shared/listing-types/action-tracker.js +0 -2
- package/dist/constants/field-names.d.ts +3 -0
- package/dist/constants/field-names.js +3 -0
- package/dist/core/unit-of-work.js +0 -1
- package/dist/features/account/components/NotificationBell.js +1 -0
- package/dist/features/account/components/UserOffersPanel.js +1 -0
- package/dist/features/account/components/UserSidebar.js +3 -1
- package/dist/features/admin/components/AdminCarouselEditorView.js +3 -1
- package/dist/features/admin/components/AdminSidebar.js +3 -1
- package/dist/features/admin/components/AdminSiteSettingsView.js +3 -1
- package/dist/features/admin/components/AdminSupportTicketDetailView.js +0 -3
- package/dist/features/admin/components/DashboardStats.js +5 -1
- package/dist/features/admin/components/analytics/AdminAnalyticsCharts.js +3 -1
- package/dist/features/admin/components/analytics/AdminStatCard.js +5 -1
- package/dist/features/admin/hooks/useChat.js +1 -0
- package/dist/features/admin/repository/chat.repository.js +7 -6
- package/dist/features/auctions/components/AuctionBidsTable.js +5 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +3 -4
- package/dist/features/auctions/repository/bid.repository.js +12 -12
- package/dist/features/auth/hooks/useAuth.js +1 -0
- package/dist/features/blog/actions/blog-actions.d.ts +2 -2
- package/dist/features/blog/components/BlogFeaturedCard.js +3 -1
- package/dist/features/blog/components/BlogListView.js +5 -1
- package/dist/features/blog/components/BlogPostView.js +3 -1
- package/dist/features/blog/schemas/index.d.ts +1 -1
- package/dist/features/cart/components/CartDrawer.js +3 -1
- package/dist/features/cart/repository/cart.repository.js +2 -1
- package/dist/features/categories/components/BrandDetailPageView.js +5 -1
- package/dist/features/categories/components/CategoryDetailPageView.js +3 -1
- package/dist/features/categories/components/CategoryGrid.js +5 -1
- package/dist/features/categories/components/CategoryTableColumns.js +6 -2
- package/dist/features/categories/components/CategoryTree.js +3 -1
- package/dist/features/categories/components/ConcernCard.js +3 -1
- package/dist/features/categories/repository/categories.repository.js +26 -25
- package/dist/features/categories/schemas/firestore.d.ts +1 -0
- package/dist/features/categories/schemas/firestore.js +1 -0
- package/dist/features/categories/schemas/index.d.ts +10 -10
- package/dist/features/collections/components/CollectionCard.js +3 -1
- package/dist/features/events/components/EventCard.js +3 -1
- package/dist/features/events/components/EventParticipateView.js +2 -1
- package/dist/features/events/schemas/index.d.ts +3 -3
- package/dist/features/faq/actions/faq-actions.d.ts +6 -6
- package/dist/features/faq/repository/faqs.repository.js +21 -20
- package/dist/features/faq/schemas/index.d.ts +2 -2
- package/dist/features/forms/Slider.js +3 -1
- package/dist/features/history/hooks/useHistory.js +1 -0
- package/dist/features/homepage/components/AdSlot.js +6 -2
- package/dist/features/homepage/components/AdvertisementBanner.js +3 -1
- package/dist/features/homepage/components/BeforeAfterCard.js +5 -1
- package/dist/features/homepage/components/CustomCardsSection.js +5 -1
- package/dist/features/homepage/components/HowItWorksSection.js +3 -1
- package/dist/features/homepage/components/NewsletterBanner.js +6 -2
- package/dist/features/homepage/components/SecurityHighlightsSection.js +3 -1
- package/dist/features/homepage/components/StatsCounterSection.js +3 -1
- package/dist/features/homepage/components/TrustFeaturesSection.js +3 -1
- package/dist/features/homepage/repository/carousel.repository.js +8 -7
- package/dist/features/homepage/repository/carousels.repository.js +2 -1
- package/dist/features/homepage/repository/homepage-sections.repository.js +6 -5
- package/dist/features/layout/AppLayoutShell.js +3 -1
- package/dist/features/layout/BottomActionsContext.js +1 -3
- package/dist/features/layout/BottomNavbar.js +1 -1
- package/dist/features/media/MediaLightbox.js +9 -3
- package/dist/features/media/modals/ImageEditor.js +6 -2
- package/dist/features/media/upload/MediaUploadField.js +1 -1
- package/dist/features/messages/hooks/useConversation.js +2 -0
- package/dist/features/messages/hooks/useConversations.js +1 -0
- package/dist/features/messages/repository/conversations.repository.js +5 -4
- package/dist/features/orders/components/OrdersList.js +3 -1
- package/dist/features/orders/repository/orders.repository.js +13 -13
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +1 -1
- package/dist/features/products/components/CompareOverlay.js +5 -1
- package/dist/features/products/components/FeatureBadge.js +3 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +1 -1
- package/dist/features/products/components/ProductGrid.js +3 -1
- package/dist/features/products/repository/product-features.repository.js +7 -6
- package/dist/features/products/repository/product-templates.repository.js +4 -3
- package/dist/features/products/repository/products.repository.js +4 -4
- package/dist/features/promotions/repository/claimed-coupons.repository.js +2 -1
- package/dist/features/promotions/repository/coupons.repository.js +4 -4
- package/dist/features/reviews/components/ReviewDetailShell.js +8 -2
- package/dist/features/reviews/components/ReviewModal.js +5 -1
- package/dist/features/reviews/components/ReviewSummary.js +3 -1
- package/dist/features/reviews/components/ReviewsList.js +5 -1
- package/dist/features/reviews/repository/reviews.repository.js +2 -2
- package/dist/features/scams/repository/scammer.repository.js +3 -3
- package/dist/features/search/components/Search.js +14 -1
- package/dist/features/seller/components/PhysicalLocationModal.js +1 -1
- package/dist/features/seller/components/SellerAddressesView.js +2 -1
- package/dist/features/seller/components/SellerBidsView.js +3 -1
- package/dist/features/seller/components/SellerCouponEditorView.js +3 -1
- package/dist/features/seller/components/SellerOffersPanel.js +1 -0
- package/dist/features/seller/components/SellerPayoutMethodsView.js +1 -0
- package/dist/features/seller/components/SellerProductsView.js +5 -1
- package/dist/features/seller/components/SellerReviewsView.js +1 -0
- package/dist/features/seller/components/SellerShippingConfigsView.js +1 -0
- package/dist/features/seller/components/SellerSidebar.js +12 -4
- package/dist/features/seller/components/SellerStoreCategoriesView.js +1 -0
- package/dist/features/seller/components/SellerTemplatesView.js +1 -0
- package/dist/features/shell/FormShell.js +10 -2
- package/dist/features/shell/QuickFormDrawer.js +5 -2
- package/dist/features/stores/components/StoreHeader.js +5 -1
- package/dist/features/support/repository/support.repository.js +8 -7
- package/dist/features/wishlist/components/WishlistPage.js +3 -1
- package/dist/providers/db-firebase/admin.js +0 -1
- package/dist/seed/products-auctions-seed-data.js +107 -0
- package/dist/ui/DataTable.js +6 -2
- package/dist/ui/components/AvatarDisplay.js +3 -1
- package/dist/ui/components/BackgroundRenderer.js +4 -2
- package/dist/ui/components/Card.js +6 -2
- package/dist/ui/components/ImageGallery.js +3 -1
- package/dist/ui/components/ImageLightbox.js +3 -1
- package/dist/ui/components/PasswordStrengthIndicator.js +3 -1
- package/dist/ui/components/Progress.js +6 -2
- package/dist/ui/components/RowActionMenu.js +3 -1
- package/dist/ui/components/SiteLogo.js +7 -1
- package/dist/ui/components/Skeleton.js +3 -1
- package/dist/ui/components/Slider.js +3 -1
- package/dist/ui/components/TabStrip.js +3 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { increment, arrayUnion, arrayRemove, } from "../../../contracts/field-ops";
|
|
2
2
|
import { DatabaseError } from "../../../errors";
|
|
3
3
|
import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
|
|
4
|
+
import { PRODUCT_FIELDS } from "../../../constants/field-names";
|
|
4
5
|
import { CATEGORY_FIELDS, CATEGORIES_COLLECTION, MIN_ITEMS_FOR_FEATURED, buildCategoryTree, calculateCategoryFields, canBeFeatured, createCategoryId, isValidCategoryMove, } from "../schemas";
|
|
5
6
|
export class CategoriesRepository extends BaseRepository {
|
|
6
7
|
constructor() {
|
|
@@ -80,9 +81,9 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
80
81
|
try {
|
|
81
82
|
const snapshot = await this.db
|
|
82
83
|
.collection(this.collection)
|
|
83
|
-
.where(
|
|
84
|
-
.where(
|
|
85
|
-
.orderBy(
|
|
84
|
+
.where(CATEGORY_FIELDS.TIER, "==", 0)
|
|
85
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
86
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
86
87
|
.get();
|
|
87
88
|
return snapshot.docs
|
|
88
89
|
.map((doc) => this.mapDoc(doc))
|
|
@@ -96,8 +97,8 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
96
97
|
try {
|
|
97
98
|
const snapshot = await this.db
|
|
98
99
|
.collection(this.collection)
|
|
99
|
-
.where(
|
|
100
|
-
.where(
|
|
100
|
+
.where(CATEGORY_FIELDS.IS_LEAF, "==", true)
|
|
101
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
101
102
|
.limit(500)
|
|
102
103
|
.get();
|
|
103
104
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
@@ -110,9 +111,9 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
110
111
|
try {
|
|
111
112
|
const snapshot = await this.db
|
|
112
113
|
.collection(this.collection)
|
|
113
|
-
.where(
|
|
114
|
-
.where(
|
|
115
|
-
.orderBy(
|
|
114
|
+
.where(CATEGORY_FIELDS.TIER, "==", tier)
|
|
115
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
116
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
116
117
|
.get();
|
|
117
118
|
return snapshot.docs
|
|
118
119
|
.map((doc) => this.mapDoc(doc))
|
|
@@ -126,9 +127,9 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
126
127
|
try {
|
|
127
128
|
const snapshot = await this.db
|
|
128
129
|
.collection(this.collection)
|
|
129
|
-
.where(
|
|
130
|
-
.orderBy(
|
|
131
|
-
.orderBy(
|
|
130
|
+
.where(CATEGORY_FIELDS.ROOT_ID, "==", rootId)
|
|
131
|
+
.orderBy(CATEGORY_FIELDS.TIER, "asc")
|
|
132
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
132
133
|
.get();
|
|
133
134
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
134
135
|
}
|
|
@@ -141,7 +142,7 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
141
142
|
const snapshot = await this.db
|
|
142
143
|
.collection(this.collection)
|
|
143
144
|
.where("parentIds", "array-contains", parentId)
|
|
144
|
-
.orderBy(
|
|
145
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
145
146
|
.limit(100)
|
|
146
147
|
.get();
|
|
147
148
|
return snapshot.docs
|
|
@@ -156,8 +157,8 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
156
157
|
try {
|
|
157
158
|
const snapshot = await this.db
|
|
158
159
|
.collection(this.collection)
|
|
159
|
-
.where(
|
|
160
|
-
.where(
|
|
160
|
+
.where(CATEGORY_FIELDS.IS_FEATURED, "==", true)
|
|
161
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
161
162
|
.orderBy("featuredPriority", "asc")
|
|
162
163
|
.get();
|
|
163
164
|
return snapshot.docs
|
|
@@ -173,8 +174,8 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
173
174
|
const snapshot = await this.db
|
|
174
175
|
.collection(this.collection)
|
|
175
176
|
.where("isBrand", "==", true)
|
|
176
|
-
.where(
|
|
177
|
-
.orderBy(
|
|
177
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
178
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
178
179
|
.get();
|
|
179
180
|
const brands = snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
180
181
|
return limit > 0 ? brands.slice(0, limit) : brands;
|
|
@@ -368,9 +369,9 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
368
369
|
async listByType(type, opts = {}) {
|
|
369
370
|
let q = this.db
|
|
370
371
|
.collection(this.collection)
|
|
371
|
-
.where(
|
|
372
|
+
.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
|
|
372
373
|
if (opts.activeOnly)
|
|
373
|
-
q = q.where(
|
|
374
|
+
q = q.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true);
|
|
374
375
|
if (opts.limit)
|
|
375
376
|
q = q.limit(opts.limit);
|
|
376
377
|
const snap = await q.get();
|
|
@@ -380,10 +381,10 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
380
381
|
async findBySlugAndType(slug, type) {
|
|
381
382
|
let q = this.db
|
|
382
383
|
.collection(this.collection)
|
|
383
|
-
.where(
|
|
384
|
+
.where(CATEGORY_FIELDS.SLUG, "==", slug)
|
|
384
385
|
.limit(1);
|
|
385
386
|
if (type)
|
|
386
|
-
q = q.where(
|
|
387
|
+
q = q.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", type);
|
|
387
388
|
const snap = await q.get();
|
|
388
389
|
if (snap.empty)
|
|
389
390
|
return null;
|
|
@@ -398,8 +399,8 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
398
399
|
const snap = await this.db
|
|
399
400
|
.collection("products")
|
|
400
401
|
.where("sublistingCategoryId", "==", sublistingId)
|
|
401
|
-
.where(
|
|
402
|
-
.orderBy(
|
|
402
|
+
.where(PRODUCT_FIELDS.STATUS, "==", "published")
|
|
403
|
+
.orderBy(PRODUCT_FIELDS.PRICE, "asc")
|
|
403
404
|
.limit(limit)
|
|
404
405
|
.get();
|
|
405
406
|
return snap.docs.map((d) => ({ id: d.id, ...d.data() }));
|
|
@@ -428,9 +429,9 @@ export class CategoriesRepository extends BaseRepository {
|
|
|
428
429
|
async findActiveBrands() {
|
|
429
430
|
const snap = await this.db
|
|
430
431
|
.collection(this.collection)
|
|
431
|
-
.where(
|
|
432
|
-
.where(
|
|
433
|
-
.orderBy(
|
|
432
|
+
.where(CATEGORY_FIELDS.CATEGORY_TYPE, "==", "brand")
|
|
433
|
+
.where(CATEGORY_FIELDS.IS_ACTIVE, "==", true)
|
|
434
|
+
.orderBy(CATEGORY_FIELDS.ORDER, "asc")
|
|
434
435
|
.get();
|
|
435
436
|
return snap.docs.map((d) => this.mapDoc(d));
|
|
436
437
|
}
|
|
@@ -244,6 +244,7 @@ export declare const CATEGORY_FIELDS: {
|
|
|
244
244
|
readonly DISPLAY: "display";
|
|
245
245
|
readonly IS_ACTIVE: "isActive";
|
|
246
246
|
readonly IS_SEARCHABLE: "isSearchable";
|
|
247
|
+
readonly CATEGORY_TYPE: "categoryType";
|
|
247
248
|
readonly CREATED_BY: "createdBy";
|
|
248
249
|
readonly CREATED_AT: "createdAt";
|
|
249
250
|
readonly UPDATED_AT: "updatedAt";
|
|
@@ -23,12 +23,12 @@ export declare const categoryDisplaySchema: z.ZodObject<{
|
|
|
23
23
|
showInMenu: z.ZodOptional<z.ZodBoolean>;
|
|
24
24
|
}, "strip", z.ZodTypeAny, {
|
|
25
25
|
icon?: string | undefined;
|
|
26
|
-
showInMenu?: boolean | undefined;
|
|
27
26
|
coverImage?: string | undefined;
|
|
27
|
+
showInMenu?: boolean | undefined;
|
|
28
28
|
}, {
|
|
29
29
|
icon?: string | undefined;
|
|
30
|
-
showInMenu?: boolean | undefined;
|
|
31
30
|
coverImage?: string | undefined;
|
|
31
|
+
showInMenu?: boolean | undefined;
|
|
32
32
|
}>;
|
|
33
33
|
export declare const categoryMetricsSchema: z.ZodObject<{
|
|
34
34
|
productCount: z.ZodNumber;
|
|
@@ -104,12 +104,12 @@ export declare const categoryItemSchema: z.ZodObject<{
|
|
|
104
104
|
showInMenu: z.ZodOptional<z.ZodBoolean>;
|
|
105
105
|
}, "strip", z.ZodTypeAny, {
|
|
106
106
|
icon?: string | undefined;
|
|
107
|
-
showInMenu?: boolean | undefined;
|
|
108
107
|
coverImage?: string | undefined;
|
|
108
|
+
showInMenu?: boolean | undefined;
|
|
109
109
|
}, {
|
|
110
110
|
icon?: string | undefined;
|
|
111
|
-
showInMenu?: boolean | undefined;
|
|
112
111
|
coverImage?: string | undefined;
|
|
112
|
+
showInMenu?: boolean | undefined;
|
|
113
113
|
}>>;
|
|
114
114
|
createdAt: z.ZodOptional<z.ZodString>;
|
|
115
115
|
updatedAt: z.ZodOptional<z.ZodString>;
|
|
@@ -125,8 +125,8 @@ export declare const categoryItemSchema: z.ZodObject<{
|
|
|
125
125
|
updatedAt?: string | undefined;
|
|
126
126
|
display?: {
|
|
127
127
|
icon?: string | undefined;
|
|
128
|
-
showInMenu?: boolean | undefined;
|
|
129
128
|
coverImage?: string | undefined;
|
|
129
|
+
showInMenu?: boolean | undefined;
|
|
130
130
|
} | undefined;
|
|
131
131
|
order?: number | undefined;
|
|
132
132
|
isFeatured?: boolean | undefined;
|
|
@@ -137,8 +137,8 @@ export declare const categoryItemSchema: z.ZodObject<{
|
|
|
137
137
|
ogImage?: string | undefined;
|
|
138
138
|
} | undefined;
|
|
139
139
|
rootId?: string | undefined;
|
|
140
|
-
parentIds?: string[] | undefined;
|
|
141
140
|
isLeaf?: boolean | undefined;
|
|
141
|
+
parentIds?: string[] | undefined;
|
|
142
142
|
featuredPriority?: number | undefined;
|
|
143
143
|
childrenIds?: string[] | undefined;
|
|
144
144
|
metrics?: {
|
|
@@ -158,8 +158,8 @@ export declare const categoryItemSchema: z.ZodObject<{
|
|
|
158
158
|
updatedAt?: string | undefined;
|
|
159
159
|
display?: {
|
|
160
160
|
icon?: string | undefined;
|
|
161
|
-
showInMenu?: boolean | undefined;
|
|
162
161
|
coverImage?: string | undefined;
|
|
162
|
+
showInMenu?: boolean | undefined;
|
|
163
163
|
} | undefined;
|
|
164
164
|
order?: number | undefined;
|
|
165
165
|
isFeatured?: boolean | undefined;
|
|
@@ -170,8 +170,8 @@ export declare const categoryItemSchema: z.ZodObject<{
|
|
|
170
170
|
ogImage?: string | undefined;
|
|
171
171
|
} | undefined;
|
|
172
172
|
rootId?: string | undefined;
|
|
173
|
-
parentIds?: string[] | undefined;
|
|
174
173
|
isLeaf?: boolean | undefined;
|
|
174
|
+
parentIds?: string[] | undefined;
|
|
175
175
|
featuredPriority?: number | undefined;
|
|
176
176
|
childrenIds?: string[] | undefined;
|
|
177
177
|
metrics?: {
|
|
@@ -194,14 +194,14 @@ export declare const categoryListParamsSchema: z.ZodObject<{
|
|
|
194
194
|
q?: string | undefined;
|
|
195
195
|
page?: number | undefined;
|
|
196
196
|
perPage?: number | undefined;
|
|
197
|
-
tier?: number | undefined;
|
|
198
197
|
parentId?: string | undefined;
|
|
198
|
+
tier?: number | undefined;
|
|
199
199
|
}, {
|
|
200
200
|
type?: "category" | "brand" | "collection" | "concern" | undefined;
|
|
201
201
|
featured?: boolean | undefined;
|
|
202
202
|
q?: string | undefined;
|
|
203
203
|
page?: number | undefined;
|
|
204
204
|
perPage?: number | undefined;
|
|
205
|
-
tier?: number | undefined;
|
|
206
205
|
parentId?: string | undefined;
|
|
206
|
+
tier?: number | undefined;
|
|
207
207
|
}>;
|
|
@@ -3,7 +3,9 @@ import { Div, Heading, Text, TextLink } from "../../../ui";
|
|
|
3
3
|
import { LAYOUT } from "../../../tokens";
|
|
4
4
|
const CLS_PLACEHOLDER = "w-full bg-gradient-to-br from-indigo-100 to-purple-100 dark:from-indigo-900/30 dark:to-purple-900/30";
|
|
5
5
|
export function CollectionCard({ collection, href }) {
|
|
6
|
-
return (_jsxs(TextLink, { href: href, className: "group relative block overflow-hidden rounded-xl bg-gray-100 dark:bg-slate-800 transition-shadow hover:shadow-lg", children: [collection.image ? (_jsx(Div, { role: "img", "aria-label": collection.title, className: `${LAYOUT.cardHeight.md} w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105`,
|
|
6
|
+
return (_jsxs(TextLink, { href: href, className: "group relative block overflow-hidden rounded-xl bg-gray-100 dark:bg-slate-800 transition-shadow hover:shadow-lg", children: [collection.image ? (_jsx(Div, { role: "img", "aria-label": collection.title, className: `${LAYOUT.cardHeight.md} w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105`,
|
|
7
|
+
// audit-inline-style-ok: dynamic image URL
|
|
8
|
+
style: { backgroundImage: `url(${collection.image})` } })) : (_jsx(Div, { className: `${LAYOUT.cardHeight.md} ${CLS_PLACEHOLDER}` })), _jsxs(Div, { surface: "default", padding: "sm", children: [_jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100", children: collection.title }), collection.subtitle && (_jsx(Text, { className: "mt-1 text-sm text-gray-500 dark:text-zinc-400", children: collection.subtitle })), collection.productCount !== undefined && (_jsxs(Text, { className: "mt-2 text-xs text-gray-400 dark:text-zinc-500", children: [collection.productCount, " ", collection.productCount === 1 ? "item" : "items"] }))] })] }));
|
|
7
9
|
}
|
|
8
10
|
export function CollectionGrid({ collections, getHref }) {
|
|
9
11
|
return (_jsx(Div, { className: "grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3", children: collections.map((c) => (_jsx(CollectionCard, { collection: c, href: getHref(c.slug) }, c.slug))) }));
|
|
@@ -31,6 +31,8 @@ export function EventCard({ event, labels = {}, onParticipate, className = "", s
|
|
|
31
31
|
const msLeft = endsAt.getTime() - now.getTime();
|
|
32
32
|
const daysLeft = Math.max(0, Math.ceil(msLeft / (1000 * 60 * 60 * 24)));
|
|
33
33
|
const detailHref = String(ROUTES.PUBLIC.EVENT_DETAIL(event.slug ?? event.id));
|
|
34
|
-
return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className: `aspect-video ${__O.hidden}`, children: _jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105",
|
|
34
|
+
return (_jsxs(Article, { className: `group relative flex h-full ${LAYOUT.cardHeight.event} flex-col overflow-hidden rounded-xl border bg-white shadow-sm transition-shadow hover:shadow-md dark:bg-slate-900 ${isSelected ? "border-primary outline outline-2 outline-primary" : "border-zinc-200 dark:border-slate-700"} ${className}`, onMouseDown: onSelect && !isSelected ? longPress.onMouseDown : undefined, onMouseUp: onSelect && !isSelected ? longPress.onMouseUp : undefined, onMouseLeave: onSelect && !isSelected ? longPress.onMouseLeave : undefined, onTouchStart: onSelect && !isSelected ? longPress.onTouchStart : undefined, onTouchEnd: onSelect && !isSelected ? longPress.onTouchEnd : undefined, children: [onSelect && (_jsx(BaseListingCard.Checkbox, { selected: isSelected, onSelect: (e) => { e.preventDefault(); onSelect(event.id, !isSelected); }, label: isSelected ? "Deselect event" : "Select event", position: "top-2 left-2", className: selectable || isSelected ? "opacity-100" : "opacity-0 group-hover:opacity-100 transition-opacity" })), _jsx(Link, { href: detailHref, className: "block flex-shrink-0", children: event.coverImageUrl ? (_jsx(Div, { className: `aspect-video ${__O.hidden}`, children: _jsx(Div, { role: "img", "aria-label": safeTitle, className: "h-full w-full bg-cover bg-center transition-transform duration-300 group-hover:scale-105",
|
|
35
|
+
// audit-inline-style-ok: dynamic image URL
|
|
36
|
+
style: { backgroundImage: `url(${event.coverImageUrl})` } }) })) : (_jsx(Div, { className: "aspect-video bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-slate-800 dark:to-slate-700 flex items-center justify-center", children: _jsx(Span, { className: "text-5xl opacity-40", "aria-hidden": "true", children: TYPE_ICONS[event.type] }) })) }), _jsxs(Div, { className: `flex flex-1 flex-col ${__P.p4}`, children: [_jsxs(Div, { className: "flex items-start justify-between gap-2 mb-2", children: [_jsx(Span, { size: "lg", "aria-hidden": "true", children: TYPE_ICONS[event.type] }), _jsx(EventStatusBadge, { status: event.status })] }), _jsx(Link, { href: detailHref, className: "block", children: _jsx(Heading, { level: 3, className: "font-semibold text-gray-900 dark:text-zinc-100 text-base leading-snug mb-1 group-hover:text-primary transition-colors", children: safeTitle }) }), _jsx(RichText, { html: normalizeRichTextHtml(event.description ?? ""), proseClass: "prose prose-sm max-w-none dark:prose-invert prose-p:my-0", className: `mb-3 ${THEME_CONSTANTS.utilities.textClamp3} text-sm text-zinc-600 dark:text-zinc-400` }), _jsxs(Div, { className: "mb-3 mt-auto flex items-center justify-between text-xs text-zinc-500 dark:text-zinc-400", children: [event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE &&
|
|
35
37
|
daysLeft > 0 && _jsxs(Span, { children: ["\u23F1 ", daysLeft, "d remaining"] }), _jsxs(Span, { children: ["\uD83D\uDC65 ", event.stats.totalEntries, " ", labels.entries ?? "entries"] })] }), event.status === EVENT_FIELDS.STATUS_VALUES.ACTIVE && onParticipate ? (_jsx(Button, { type: "button", onClick: () => onParticipate(event), className: "w-full rounded-lg bg-primary py-2 text-sm font-medium text-white transition-colors hover:bg-primary-600", children: labels.participate ?? "Participate" })) : (_jsxs(TextLink, { href: detailHref, className: "inline-flex w-full items-center justify-center gap-1.5 rounded-lg border border-zinc-300 px-3 py-2 text-sm font-medium text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-slate-600 dark:text-zinc-200 dark:hover:bg-slate-800", children: [labels.viewDetails ?? "View details", " \u2192"] }))] })] }));
|
|
36
38
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Div } from "../../../ui";
|
|
3
|
+
import { Skeleton } from "../../../ui/components/Skeleton";
|
|
3
4
|
export function EventParticipateView({ isLoading = false, isSubmitted = false, renderEventInfo, renderForm, renderAction, renderSuccess, renderSkeleton, renderAuthGate, className = "", }) {
|
|
4
5
|
if (isLoading) {
|
|
5
6
|
if (renderSkeleton)
|
|
6
7
|
return _jsx(_Fragment, { children: renderSkeleton() });
|
|
7
|
-
return
|
|
8
|
+
return (_jsxs(Div, { className: "max-w-xl mx-auto space-y-4 py-6", children: [_jsx(Skeleton, { variant: "rectangular", height: "32px" }), _jsx(Skeleton, { variant: "rectangular", height: "80px" }), _jsx(Skeleton, { variant: "rectangular", height: "48px" })] }));
|
|
8
9
|
}
|
|
9
10
|
if (renderAuthGate)
|
|
10
11
|
return _jsx(_Fragment, { children: renderAuthGate() });
|
|
@@ -275,6 +275,8 @@ export declare const eventItemSchema: z.ZodObject<{
|
|
|
275
275
|
approvedEntries: number;
|
|
276
276
|
flaggedEntries: number;
|
|
277
277
|
};
|
|
278
|
+
startsAt: string;
|
|
279
|
+
endsAt: string;
|
|
278
280
|
createdBy: string;
|
|
279
281
|
coverImage: {
|
|
280
282
|
url: string;
|
|
@@ -287,8 +289,6 @@ export declare const eventItemSchema: z.ZodObject<{
|
|
|
287
289
|
url: string;
|
|
288
290
|
type: "image";
|
|
289
291
|
} | null;
|
|
290
|
-
startsAt: string;
|
|
291
|
-
endsAt: string;
|
|
292
292
|
additionalImages: {
|
|
293
293
|
url: string;
|
|
294
294
|
type: "image" | "video" | "file";
|
|
@@ -346,9 +346,9 @@ export declare const eventItemSchema: z.ZodObject<{
|
|
|
346
346
|
approvedEntries: number;
|
|
347
347
|
flaggedEntries: number;
|
|
348
348
|
};
|
|
349
|
-
createdBy: string;
|
|
350
349
|
startsAt: string;
|
|
351
350
|
endsAt: string;
|
|
351
|
+
createdBy: string;
|
|
352
352
|
coverImage?: string | {
|
|
353
353
|
url: string;
|
|
354
354
|
type: "image" | "video" | "file";
|
|
@@ -31,12 +31,12 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
31
31
|
priority: number;
|
|
32
32
|
isActive: boolean;
|
|
33
33
|
question: string;
|
|
34
|
-
showInFooter: boolean;
|
|
35
34
|
showOnHomepage: boolean;
|
|
36
35
|
answer: {
|
|
37
36
|
text: string;
|
|
38
37
|
format: "html" | "plain" | "markdown";
|
|
39
38
|
};
|
|
39
|
+
showInFooter: boolean;
|
|
40
40
|
isPinned: boolean;
|
|
41
41
|
useSiteSettings: boolean;
|
|
42
42
|
tags?: string[] | undefined;
|
|
@@ -56,8 +56,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
56
56
|
priority?: number | undefined;
|
|
57
57
|
isActive?: boolean | undefined;
|
|
58
58
|
variables?: Record<string, string> | undefined;
|
|
59
|
-
showInFooter?: boolean | undefined;
|
|
60
59
|
showOnHomepage?: boolean | undefined;
|
|
60
|
+
showInFooter?: boolean | undefined;
|
|
61
61
|
isPinned?: boolean | undefined;
|
|
62
62
|
relatedFAQs?: string[] | undefined;
|
|
63
63
|
useSiteSettings?: boolean | undefined;
|
|
@@ -67,12 +67,12 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
67
67
|
priority: number;
|
|
68
68
|
isActive: boolean;
|
|
69
69
|
question: string;
|
|
70
|
-
showInFooter: boolean;
|
|
71
70
|
showOnHomepage: boolean;
|
|
72
71
|
answer: {
|
|
73
72
|
text: string;
|
|
74
73
|
format: "html" | "plain" | "markdown";
|
|
75
74
|
};
|
|
75
|
+
showInFooter: boolean;
|
|
76
76
|
isPinned: boolean;
|
|
77
77
|
useSiteSettings: boolean;
|
|
78
78
|
tags?: string[] | undefined;
|
|
@@ -92,8 +92,8 @@ export declare const faqCreateSchema: z.ZodEffects<z.ZodObject<{
|
|
|
92
92
|
priority?: number | undefined;
|
|
93
93
|
isActive?: boolean | undefined;
|
|
94
94
|
variables?: Record<string, string> | undefined;
|
|
95
|
-
showInFooter?: boolean | undefined;
|
|
96
95
|
showOnHomepage?: boolean | undefined;
|
|
96
|
+
showInFooter?: boolean | undefined;
|
|
97
97
|
isPinned?: boolean | undefined;
|
|
98
98
|
relatedFAQs?: string[] | undefined;
|
|
99
99
|
useSiteSettings?: boolean | undefined;
|
|
@@ -131,12 +131,12 @@ export declare const faqUpdateSchema: z.ZodObject<{
|
|
|
131
131
|
isActive?: boolean | undefined;
|
|
132
132
|
variables?: Record<string, string> | undefined;
|
|
133
133
|
question?: string | undefined;
|
|
134
|
-
showInFooter?: boolean | undefined;
|
|
135
134
|
showOnHomepage?: boolean | undefined;
|
|
136
135
|
answer?: {
|
|
137
136
|
text: string;
|
|
138
137
|
format: "html" | "plain" | "markdown";
|
|
139
138
|
} | undefined;
|
|
139
|
+
showInFooter?: boolean | undefined;
|
|
140
140
|
isPinned?: boolean | undefined;
|
|
141
141
|
relatedFAQs?: string[] | undefined;
|
|
142
142
|
useSiteSettings?: boolean | undefined;
|
|
@@ -149,12 +149,12 @@ export declare const faqUpdateSchema: z.ZodObject<{
|
|
|
149
149
|
isActive?: boolean | undefined;
|
|
150
150
|
variables?: Record<string, string> | undefined;
|
|
151
151
|
question?: string | undefined;
|
|
152
|
-
showInFooter?: boolean | undefined;
|
|
153
152
|
showOnHomepage?: boolean | undefined;
|
|
154
153
|
answer?: {
|
|
155
154
|
text: string;
|
|
156
155
|
format?: "html" | "plain" | "markdown" | undefined;
|
|
157
156
|
} | undefined;
|
|
157
|
+
showInFooter?: boolean | undefined;
|
|
158
158
|
isPinned?: boolean | undefined;
|
|
159
159
|
relatedFAQs?: string[] | undefined;
|
|
160
160
|
useSiteSettings?: boolean | undefined;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { BaseRepository, prepareForFirestore, } from "../../../providers/db-firebase";
|
|
2
2
|
import { DatabaseError } from "../../../errors";
|
|
3
3
|
import { increment } from "../../../contracts/field-ops";
|
|
4
|
+
import { FAQ_FIELDS } from "../../../constants/field-names";
|
|
4
5
|
import { FAQS_COLLECTION, createFAQId, slugifyQuestion, } from "../schemas";
|
|
5
6
|
export class FAQsRepository {
|
|
6
7
|
constructor(repo) {
|
|
@@ -116,16 +117,16 @@ export class FirebaseFAQsRepository extends BaseRepository {
|
|
|
116
117
|
throw new DatabaseError("Combining FAQ tag filters and token search requires a dedicated search index");
|
|
117
118
|
}
|
|
118
119
|
if (tags.length === 1) {
|
|
119
|
-
baseQuery = baseQuery.where(
|
|
120
|
+
baseQuery = baseQuery.where(FAQ_FIELDS.TAGS, "array-contains", tags[0]);
|
|
120
121
|
}
|
|
121
122
|
else if (tags.length > 1) {
|
|
122
|
-
baseQuery = baseQuery.where(
|
|
123
|
+
baseQuery = baseQuery.where(FAQ_FIELDS.TAGS, "array-contains-any", tags.slice(0, 10));
|
|
123
124
|
}
|
|
124
125
|
if (searchTokens.length === 1) {
|
|
125
|
-
baseQuery = baseQuery.where(
|
|
126
|
+
baseQuery = baseQuery.where(FAQ_FIELDS.SEARCH_TOKENS, "array-contains", searchTokens[0]);
|
|
126
127
|
}
|
|
127
128
|
else if (searchTokens.length > 1) {
|
|
128
|
-
baseQuery = baseQuery.where(
|
|
129
|
+
baseQuery = baseQuery.where(FAQ_FIELDS.SEARCH_TOKENS, "array-contains-any", searchTokens);
|
|
129
130
|
}
|
|
130
131
|
return this.sieveQuery(model, FirebaseFAQsRepository.SIEVE_FIELDS, { baseQuery });
|
|
131
132
|
}
|
|
@@ -142,53 +143,53 @@ export class FirebaseFAQsRepository extends BaseRepository {
|
|
|
142
143
|
async getFAQsByCategory(category) {
|
|
143
144
|
const snapshot = await this.db
|
|
144
145
|
.collection(this.collection)
|
|
145
|
-
.where(
|
|
146
|
-
.where(
|
|
147
|
-
.orderBy(
|
|
146
|
+
.where(FAQ_FIELDS.CATEGORY, "==", category)
|
|
147
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true)
|
|
148
|
+
.orderBy(FAQ_FIELDS.ORDER, "asc")
|
|
148
149
|
.get();
|
|
149
150
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
150
151
|
}
|
|
151
152
|
async getHomepageFAQs() {
|
|
152
153
|
const snapshot = await this.db
|
|
153
154
|
.collection(this.collection)
|
|
154
|
-
.where(
|
|
155
|
-
.where(
|
|
156
|
-
.orderBy(
|
|
155
|
+
.where(FAQ_FIELDS.SHOW_ON_HOMEPAGE, "==", true)
|
|
156
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true)
|
|
157
|
+
.orderBy(FAQ_FIELDS.PRIORITY, "desc")
|
|
157
158
|
.get();
|
|
158
159
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
159
160
|
}
|
|
160
161
|
async getFooterFAQs() {
|
|
161
162
|
const snapshot = await this.db
|
|
162
163
|
.collection(this.collection)
|
|
163
|
-
.where(
|
|
164
|
-
.where(
|
|
165
|
-
.orderBy(
|
|
164
|
+
.where(FAQ_FIELDS.SHOW_IN_FOOTER, "==", true)
|
|
165
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true)
|
|
166
|
+
.orderBy(FAQ_FIELDS.ORDER, "asc")
|
|
166
167
|
.get();
|
|
167
168
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
168
169
|
}
|
|
169
170
|
async getPinnedFAQs(category) {
|
|
170
171
|
let query = this.db
|
|
171
172
|
.collection(this.collection)
|
|
172
|
-
.where(
|
|
173
|
-
.where(
|
|
173
|
+
.where(FAQ_FIELDS.IS_PINNED, "==", true)
|
|
174
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true);
|
|
174
175
|
if (category) {
|
|
175
|
-
query = query.where(
|
|
176
|
+
query = query.where(FAQ_FIELDS.CATEGORY, "==", category);
|
|
176
177
|
}
|
|
177
|
-
const snapshot = await query.orderBy(
|
|
178
|
+
const snapshot = await query.orderBy(FAQ_FIELDS.ORDER, "asc").get();
|
|
178
179
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
179
180
|
}
|
|
180
181
|
async searchByTag(tag) {
|
|
181
182
|
const snapshot = await this.db
|
|
182
183
|
.collection(this.collection)
|
|
183
|
-
.where(
|
|
184
|
-
.where(
|
|
184
|
+
.where(FAQ_FIELDS.TAGS, "array-contains", tag)
|
|
185
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true)
|
|
185
186
|
.get();
|
|
186
187
|
return snapshot.docs.map((doc) => this.mapDoc(doc));
|
|
187
188
|
}
|
|
188
189
|
async getMostHelpful(limit = 10) {
|
|
189
190
|
const snapshot = await this.db
|
|
190
191
|
.collection(this.collection)
|
|
191
|
-
.where(
|
|
192
|
+
.where(FAQ_FIELDS.IS_ACTIVE, "==", true)
|
|
192
193
|
.orderBy("stats.helpful", "desc")
|
|
193
194
|
.limit(limit)
|
|
194
195
|
.get();
|
|
@@ -103,8 +103,8 @@ export declare const faqSchema: z.ZodObject<{
|
|
|
103
103
|
seo?: {
|
|
104
104
|
slug?: string | undefined;
|
|
105
105
|
} | undefined;
|
|
106
|
-
showInFooter?: boolean | undefined;
|
|
107
106
|
showOnHomepage?: boolean | undefined;
|
|
107
|
+
showInFooter?: boolean | undefined;
|
|
108
108
|
isPinned?: boolean | undefined;
|
|
109
109
|
relatedFAQs?: string[] | undefined;
|
|
110
110
|
}, {
|
|
@@ -129,8 +129,8 @@ export declare const faqSchema: z.ZodObject<{
|
|
|
129
129
|
seo?: {
|
|
130
130
|
slug?: string | undefined;
|
|
131
131
|
} | undefined;
|
|
132
|
-
showInFooter?: boolean | undefined;
|
|
133
132
|
showOnHomepage?: boolean | undefined;
|
|
133
|
+
showInFooter?: boolean | undefined;
|
|
134
134
|
isPinned?: boolean | undefined;
|
|
135
135
|
relatedFAQs?: string[] | undefined;
|
|
136
136
|
}>;
|
|
@@ -18,5 +18,7 @@ export function Slider({ value: controlledValue, defaultValue = 0, min = 0, max
|
|
|
18
18
|
onChange?.(newVal);
|
|
19
19
|
};
|
|
20
20
|
const displayValue = formatValue ? formatValue(value) : String(value);
|
|
21
|
-
return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all",
|
|
21
|
+
return (_jsxs(Div, { className: cn("w-full space-y-2", className), children: [(label || showValue) && (_jsxs(Row, { justify: "between", children: [label && (_jsx("label", { htmlFor: sliderId, className: LABEL_BASE, children: label })), showValue && (_jsx(Span, { size: "sm", weight: "semibold", className: "tabular-nums text-zinc-900 dark:text-zinc-100", children: displayValue }))] })), _jsxs(Row, { className: "relative h-5", children: [_jsx(Div, { className: "absolute inset-y-0 flex items-center w-full", children: _jsx(Div, { className: "w-full h-1.5 rounded-full bg-zinc-200 dark:bg-slate-700", children: _jsx(Div, { className: "h-full rounded-full bg-primary-500 dark:bg-secondary-500 transition-all",
|
|
22
|
+
// audit-inline-style-ok: computed percentage
|
|
23
|
+
style: { width: `${pct}%` } }) }) }), _jsx("input", { type: "range", id: sliderId, min: min, max: max, step: step, value: value, disabled: disabled, onChange: handleChange, className: cn("relative w-full appearance-none bg-transparent cursor-pointer", "focus:outline-none", "[&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:w-4 [&::-webkit-slider-thumb]:h-4", "[&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:bg-white", "[&::-webkit-slider-thumb]:border-2 [&::-webkit-slider-thumb]:border-primary-500 dark:[&::-webkit-slider-thumb]:border-secondary-500", "[&::-webkit-slider-thumb]:shadow-sm", "[&::-moz-range-thumb]:w-4 [&::-moz-range-thumb]:h-4", "[&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:bg-white", "[&::-moz-range-thumb]:border-2 [&::-moz-range-thumb]:border-primary-500 dark:[&::-moz-range-thumb]:border-secondary-500", disabled && "opacity-50 cursor-not-allowed") })] }), _jsxs(Row, { justify: "between", className: "text-xs text-zinc-400 dark:text-zinc-400", children: [_jsx(Span, { children: formatValue ? formatValue(min) : min }), _jsx(Span, { children: formatValue ? formatValue(max) : max })] }), error && (_jsx(Text, { className: ERROR_BASE, role: "alert", children: error }))] }));
|
|
22
24
|
}
|
|
@@ -69,6 +69,7 @@ export function useHistory(userId) {
|
|
|
69
69
|
const [items, setItems] = useState([]);
|
|
70
70
|
const trackTimers = useRef(new Map());
|
|
71
71
|
const loadItems = useCallback(async () => {
|
|
72
|
+
// toast-intentionally-silent — silent fallback to empty list on error
|
|
72
73
|
try {
|
|
73
74
|
if (isAuth) {
|
|
74
75
|
setItems(await fetchAuthHistory());
|
|
@@ -20,11 +20,15 @@ function AdsenseAd({ config }) {
|
|
|
20
20
|
// AdSense not loaded yet — no-op
|
|
21
21
|
}
|
|
22
22
|
}, []);
|
|
23
|
-
return (_jsx(Div, { ref: ref, children: _jsx("ins", { className: "adsbygoogle",
|
|
23
|
+
return (_jsx(Div, { ref: ref, children: _jsx("ins", { className: "adsbygoogle",
|
|
24
|
+
// audit-inline-style-ok: dynamic CSS
|
|
25
|
+
style: { display: "block" }, "data-ad-client": config.adsenseClient ?? "", "data-ad-slot": config.adsenseSlot ?? "", "data-ad-format": config.adsenseFormat ?? "auto", "data-full-width-responsive": "true" }) }));
|
|
24
26
|
}
|
|
25
27
|
function ThirdPartyAd({ config }) {
|
|
26
28
|
if (config.thirdPartyUrl) {
|
|
27
|
-
return (_jsx("iframe", { src: config.thirdPartyUrl, width: config.thirdPartyWidth ?? "100%", height: config.thirdPartyHeight ?? "90", scrolling: "no", frameBorder: "0", title: "Advertisement",
|
|
29
|
+
return (_jsx("iframe", { src: config.thirdPartyUrl, width: config.thirdPartyWidth ?? "100%", height: config.thirdPartyHeight ?? "90", scrolling: "no", frameBorder: "0", title: "Advertisement",
|
|
30
|
+
// audit-inline-style-ok: dynamic CSS
|
|
31
|
+
style: { border: 0, overflow: "hidden" }, loading: "lazy" }));
|
|
28
32
|
}
|
|
29
33
|
return null;
|
|
30
34
|
}
|
|
@@ -30,5 +30,7 @@ export function AdvertisementBanner({ title, subtitle, ctaLabel = "Shop now", on
|
|
|
30
30
|
compact
|
|
31
31
|
? "h-[clamp(112px,16vh,160px)]"
|
|
32
32
|
: "min-h-[clamp(240px,34vh,360px)]",
|
|
33
|
-
].join(" "),
|
|
33
|
+
].join(" "),
|
|
34
|
+
// audit-inline-style-ok: optional inline color
|
|
35
|
+
style: backgroundColor ? { backgroundColor } : undefined, children: [!backgroundColor && (_jsx(Div, { className: CLS_GRADIENT_BG, "aria-hidden": true })), _jsxs(Div, { className: `absolute inset-0 ${__O.hidden}`, "aria-hidden": true, children: [_jsx(Div, { className: "absolute -top-16 -left-16 w-64 h-64 rounded-full bg-primary/20 blur-3xl animate-pulse" }), _jsx(Div, { className: "absolute -bottom-16 right-0 w-80 h-80 rounded-full bg-cobalt/20 blur-3xl animate-pulse" })] }), compact ? (_jsxs(Row, { justify: "between", className: "relative z-10 w-full px-6 py-4 gap-4 flex-wrap", children: [_jsxs(Span, { className: "inline-flex items-center gap-2", children: [_jsx(Sparkles, { className: "w-4 h-4 text-white/80" }), _jsx(Span, { size: "sm", weight: "semibold", className: "text-white", children: title })] }), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "sm", onClick: onCtaClick, className: CLS_CTA_BTN_SM, children: [ctaLabel, _jsx(ArrowRight, { className: "w-3.5 h-3.5" })] }))] })) : (_jsxs(Div, { className: "relative z-10 w-full max-w-4xl mx-auto px-6 py-12 md:py-16 text-center", children: [tagLabel && (_jsxs(Span, { size: "xs", weight: "semibold", className: "inline-flex items-center gap-1.5 bg-white/15 text-white/90 uppercase tracking-widest px-4 py-1.5 rounded-full mb-5 backdrop-blur-sm shadow-sm", children: [_jsx(Sparkles, { className: "w-3.5 h-3.5" }), tagLabel] })), _jsx(Heading, { level: 2, variant: "none", className: "text-3xl md:text-5xl lg:text-6xl font-extrabold text-white mb-4 drop-shadow-lg leading-tight", children: title }), subtitle && (_jsx(Text, { variant: "none", className: "text-white text-base md:text-xl mb-10 max-w-2xl mx-auto", children: subtitle })), ctaLabel && onCtaClick && (_jsxs(Button, { variant: "secondary", size: "lg", onClick: onCtaClick, className: CLS_CTA_BTN_LG, children: [ctaLabel, _jsx(ArrowRight, { className: "w-4 h-4" })] }))] }))] }) }) }));
|
|
34
36
|
}
|
|
@@ -55,5 +55,9 @@ export function BeforeAfterCard({ item, beforeLabel = "Before", afterLabel = "Af
|
|
|
55
55
|
setPosition((p) => Math.max(0, p - 2));
|
|
56
56
|
if (e.key === "ArrowRight")
|
|
57
57
|
setPosition((p) => Math.min(100, p + 2));
|
|
58
|
-
}, children: [_jsx(Image, { src: item.afterImage, alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { className: "absolute inset-0 overflow-hidden",
|
|
58
|
+
}, children: [_jsx(Image, { src: item.afterImage, alt: afterLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }), _jsx(Div, { className: "absolute inset-0 overflow-hidden",
|
|
59
|
+
// audit-inline-style-ok: computed percentage
|
|
60
|
+
style: { width: `${position}%` }, children: _jsx(Image, { src: item.beforeImage, alt: beforeLabel, fill: true, sizes: "(max-width: 640px) 100vw, 50vw", className: "object-cover" }) }), _jsx(Div, { className: "absolute top-0 bottom-0 z-10 w-0.5 bg-card shadow-md",
|
|
61
|
+
// audit-inline-style-ok: computed percentage
|
|
62
|
+
style: { left: `${position}%` }, children: _jsx(Div, { className: "absolute top-1/2 left-1/2 flex h-8 w-8 -translate-x-1/2 -translate-y-1/2 items-center justify-center rounded-full bg-card shadow-lg", children: _jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "M4 8L1 5M4 8L1 11M4 8H12M12 8L15 5M12 8L15 11", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }) }) }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 left-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: beforeLabel }), _jsx(Span, { size: "xs", weight: "medium", className: "absolute top-3 right-3 z-10 rounded-full bg-black/50 px-2.5 py-0.5 text-white", children: afterLabel })] }), _jsx(Div, { className: `${__P.p4}`, children: _jsx(Text, { className: "text-foreground text-sm font-medium", children: item.caption }) })] }));
|
|
59
63
|
}
|
|
@@ -47,7 +47,11 @@ function CardItem({ card }) {
|
|
|
47
47
|
cardStyle.backgroundColor = card.backgroundColor;
|
|
48
48
|
if (card.textColor)
|
|
49
49
|
cardStyle.color = card.textColor;
|
|
50
|
-
return (_jsxs(Div, { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`,
|
|
50
|
+
return (_jsxs(Div, { className: `flex flex-col overflow-hidden ${radiusClass} ${shadowClass} bg-[var(--appkit-color-surface)]`,
|
|
51
|
+
// audit-inline-style-ok: pass-through style prop
|
|
52
|
+
style: cardStyle, children: [card.image && (_jsx(Div, { className: `relative w-full aspect-video ${__O.hidden}`, children: _jsx(MediaImage, { src: card.image, alt: card.imageAlt ?? "", size: "card" }) })), _jsxs(Div, { className: `flex flex-col gap-2 ${__P.p4} flex-1`, children: [card.eyebrow && (_jsx(Text, { className: "text-xs font-semibold uppercase tracking-widest opacity-70", children: card.eyebrow })), card.title && (_jsx(Text, { className: "text-base font-bold leading-snug", children: card.title })), card.body && (_jsx(Text, { className: "text-sm opacity-80 leading-relaxed flex-1", children: card.body })), card.buttons && card.buttons.length > 0 && (_jsx(Div, { className: "flex flex-wrap gap-2 mt-2", children: card.buttons.map((btn, i) => (_jsx("a", { href: btn.href, target: btn.target ?? "_self", rel: btn.target === "_blank" ? "noopener noreferrer" : undefined, className: VARIANT_CLASS[btn.variant] ?? VARIANT_CLASS.primary, children: btn.label }, i))) })), card.formEmbed && (_jsx("iframe", { src: card.formEmbed, sandbox: "allow-forms allow-scripts", loading: "lazy", className: "w-full mt-3 border-0 rounded-md",
|
|
53
|
+
// audit-inline-style-ok: dynamic CSS
|
|
54
|
+
style: { minHeight: "200px" }, title: "Embedded form" }))] })] }));
|
|
51
55
|
}
|
|
52
56
|
// --- Section Header ----------------------------------------------------------
|
|
53
57
|
function SectionHeader({ title }) {
|
|
@@ -14,7 +14,9 @@ function StepCard({ step, visible, delay, }) {
|
|
|
14
14
|
"shadow-md group hover:-translate-y-2 hover:shadow-xl",
|
|
15
15
|
"transition-all duration-300",
|
|
16
16
|
visible ? CLS_VISIBLE : "opacity-0 translate-y-8",
|
|
17
|
-
].join(" "),
|
|
17
|
+
].join(" "),
|
|
18
|
+
// audit-inline-style-ok: computed timing
|
|
19
|
+
style: { transitionDelay: `${delay}ms` }, "data-section": "howitworkssection-div-340", children: [_jsx(Div, { className: "absolute top-4 right-5 font-display text-7xl bg-gradient-to-br from-primary to-cobalt opacity-10 bg-clip-text text-transparent select-none pointer-events-none leading-none", "aria-hidden": "true", children: step.number }), _jsx(Div, { className: `relative z-10 w-10 h-10 rounded-full ${badgeBg} text-white font-bold text-sm flex items-center justify-center mb-5 shadow-md`, children: step.number }), step.renderIcon && (_jsx(Div, { className: `relative z-10 w-14 h-14 rounded-2xl ${iconBg} flex items-center justify-center mb-4 border border-white/80 dark:border-slate-700/50`, children: _jsx("span", { className: `${iconColor}`, "aria-hidden": "true", children: step.renderIcon({ className: "w-6 h-6" }) }) })), _jsx(Heading, { level: 3, className: `relative z-10 text-base font-semibold ${THEME_CONSTANTS.themed.textPrimary} mb-2`, children: step.title }), _jsx(Text, { className: `relative z-10 text-sm ${THEME_CONSTANTS.themed.textSecondary} leading-relaxed`, children: step.desc })] }));
|
|
18
20
|
}
|
|
19
21
|
// --- Section -----------------------------------------------------------------
|
|
20
22
|
export function HowItWorksSection({ title, subtitle, pillLabel, ctaLabel, onCtaClick, steps, className = "", }) {
|