@mohasinac/appkit 4.42.18 → 4.44.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/lottery/LotteryDetailView.js +22 -1
- package/dist/_internal/server/features/categories/adapters.d.ts +47 -0
- package/dist/_internal/server/features/categories/adapters.js +235 -0
- package/dist/_internal/server/features/checkout/actions.js +161 -22
- package/dist/_internal/server/features/checkout/expand-order-items.js +34 -0
- package/dist/_internal/server/features/orders/adapters.js +21 -0
- package/dist/_internal/server/features/products/list-public.d.ts +24 -0
- package/dist/_internal/server/features/products/list-public.js +10 -2
- package/dist/_internal/server/features/refunds/actions.js +1 -1
- package/dist/_internal/server/features/seo/sitemap.js +54 -15
- package/dist/_internal/server/features/stores/adapters.d.ts +1 -1
- package/dist/_internal/server/features/stores/adapters.js +6 -0
- package/dist/_internal/server/functions/scheduled.d.ts +4 -2
- package/dist/_internal/server/functions/scheduled.js +64 -6
- package/dist/_internal/server/jobs/core/adminAnalytics.d.ts +0 -1
- package/dist/_internal/server/jobs/core/adminAnalytics.js +9 -1
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.d.ts +47 -0
- package/dist/_internal/server/jobs/core/analyticsAlertEvaluate.js +468 -0
- package/dist/_internal/server/jobs/core/autoPayoutEligibility.js +14 -1
- package/dist/_internal/server/jobs/core/countersReconcile.js +24 -8
- package/dist/_internal/server/jobs/core/onCategoryWrite.js +59 -0
- package/dist/_internal/server/jobs/core/onProductWrite.js +31 -0
- package/dist/_internal/server/jobs/core/onReviewWrite.js +8 -0
- package/dist/_internal/server/jobs/core/onStoreWrite.d.ts +1 -1
- package/dist/_internal/server/jobs/core/onStoreWrite.js +8 -2
- package/dist/_internal/server/jobs/core/priceIndexRollup.d.ts +47 -0
- package/dist/_internal/server/jobs/core/priceIndexRollup.js +234 -0
- package/dist/_internal/server/jobs/core/revalidateNotify.d.ts +28 -0
- package/dist/_internal/server/jobs/core/revalidateNotify.js +125 -0
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.d.ts → testDataCleanup.d.ts} +3 -3
- package/dist/_internal/server/jobs/core/{testerSandboxCleanup.js → testDataCleanup.js} +3 -3
- package/dist/_internal/server/jobs/core/weeklyPayoutEligibility.js +5 -1
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/analyticsAlertEvaluate.js +2 -0
- package/dist/_internal/server/jobs/handlers/index.d.ts +3 -1
- package/dist/_internal/server/jobs/handlers/index.js +3 -1
- package/dist/_internal/server/jobs/handlers/messages.d.ts +5 -2
- package/dist/_internal/server/jobs/handlers/messages.js +5 -2
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/priceIndexRollup.js +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.d.ts +2 -0
- package/dist/_internal/server/jobs/handlers/testDataCleanup.js +2 -0
- package/dist/_internal/shared/actions/action-registry.js +34 -0
- package/dist/_internal/shared/cache/revalidate-targets.d.ts +49 -0
- package/dist/_internal/shared/cache/revalidate-targets.js +157 -0
- package/dist/_internal/shared/checkout/order-math.d.ts +113 -3
- package/dist/_internal/shared/checkout/order-math.js +194 -7
- package/dist/_internal/shared/features/categories/price-guidance.d.ts +110 -0
- package/dist/_internal/shared/features/categories/price-guidance.js +136 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.d.ts +90 -0
- package/dist/_internal/shared/features/site-settings/gst-registration.js +126 -0
- package/dist/_internal/shared/fees/calculator.d.ts +105 -0
- package/dist/_internal/shared/fees/calculator.js +143 -0
- package/dist/_internal/shared/listing-types/art/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/classified/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/digital-code/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/live/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/standard/config.d.ts +0 -6
- package/dist/_internal/shared/listing-types/stickers/config.d.ts +0 -6
- package/dist/_internal/shared/templating/placeholders.d.ts +70 -0
- package/dist/_internal/shared/templating/placeholders.js +73 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +1 -0
- package/dist/constants/api-endpoints.d.ts +42 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/admin/actions/admin-actions.d.ts +1 -1
- package/dist/features/admin/actions/admin-actions.js +1 -1
- package/dist/features/admin/components/AdminCategoryEditorView.js +269 -3
- package/dist/features/admin/components/AdminProductEditorView.js +8 -1
- package/dist/features/admin/components/AdminProductsView.js +78 -7
- package/dist/features/admin/components/AdminSiteSettingsView.js +20 -1
- package/dist/features/admin/components/AdminTaxCodeEditorView.d.ts +10 -0
- package/dist/features/admin/components/AdminTaxCodeEditorView.js +160 -0
- package/dist/features/admin/components/AdminTaxCodesView.d.ts +13 -0
- package/dist/features/admin/components/AdminTaxCodesView.js +86 -0
- package/dist/features/admin/components/AdminTesterChecklistView.js +1 -1
- package/dist/features/admin/components/analytics/AdminTopProductsTable.js +1 -1
- package/dist/features/auctions/components/AuctionBottomActions.js +10 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +2 -1
- package/dist/features/auctions/components/AuctionLiveStatusBadge.d.ts +20 -0
- package/dist/features/auctions/components/AuctionLiveStatusBadge.js +21 -0
- package/dist/features/auctions/components/PlaceBidFormClient.d.ts +1 -1
- package/dist/features/auctions/components/PlaceBidFormClient.js +20 -2
- package/dist/features/auctions/hooks/useIsAuctionEnded.d.ts +41 -0
- package/dist/features/auctions/hooks/useIsAuctionEnded.js +76 -0
- package/dist/features/auth/schemas/firestore.d.ts +0 -1
- package/dist/features/blog/api/route.js +16 -1
- package/dist/features/blog/schemas/firestore.d.ts +2 -2
- package/dist/features/catalogue/components/CatalogueItemEditorView.js +14 -3
- package/dist/features/categories/actions/category-actions.d.ts +2 -2
- package/dist/features/categories/actions/category-actions.js +22 -10
- package/dist/features/categories/api/[id]/description-template/route.d.ts +45 -0
- package/dist/features/categories/api/[id]/description-template/route.js +252 -0
- package/dist/features/categories/api/route.js +156 -11
- package/dist/features/categories/components/CategoriesIndexListing.d.ts +1 -3
- package/dist/features/categories/components/CategoriesIndexListing.js +1 -1
- package/dist/features/categories/components/CategoriesIndexPageView.d.ts +27 -1
- package/dist/features/categories/components/CategoriesIndexPageView.js +24 -33
- package/dist/features/categories/components/CategoryDetailPageView.js +43 -10
- package/dist/features/categories/components/CategoryTemplatePicker.d.ts +65 -0
- package/dist/features/categories/components/CategoryTemplatePicker.js +170 -0
- package/dist/features/categories/constants/listing-categories.d.ts +17 -0
- package/dist/features/categories/constants/listing-categories.js +53 -0
- package/dist/features/categories/hooks/useCategoryTree.js +28 -2
- package/dist/features/categories/repository/categories.repository.d.ts +73 -12
- package/dist/features/categories/repository/categories.repository.js +203 -42
- package/dist/features/categories/repository/price-index.repository.d.ts +115 -0
- package/dist/features/categories/repository/price-index.repository.js +85 -0
- package/dist/features/categories/schemas/category-content.d.ts +206 -0
- package/dist/features/categories/schemas/category-content.js +28 -0
- package/dist/features/categories/schemas/firestore.d.ts +74 -5
- package/dist/features/categories/schemas/firestore.js +74 -3
- package/dist/features/categories/schemas/index.d.ts +1047 -0
- package/dist/features/categories/schemas/index.js +96 -0
- package/dist/features/categories/server.d.ts +1 -0
- package/dist/features/categories/server.js +7 -0
- package/dist/features/categories/types/index.d.ts +9 -0
- package/dist/features/events/schemas/firestore.d.ts +2 -2
- package/dist/features/faq/schemas/firestore.d.ts +2 -1
- package/dist/features/faq/schemas/firestore.js +20 -8
- package/dist/features/faq/utils/getHomepageFaqsCached.d.ts +20 -0
- package/dist/features/faq/utils/getHomepageFaqsCached.js +22 -0
- package/dist/features/homepage/components/MarketplaceHomepageView.js +13 -3
- package/dist/features/homepage/lib/live-stats.js +18 -8
- package/dist/features/media/MediaImage.js +19 -2
- package/dist/features/orders/schemas/firestore.d.ts +70 -0
- package/dist/features/orders/types/index.d.ts +55 -0
- package/dist/features/products/actions/product-actions.d.ts +0 -9
- package/dist/features/products/actions/product-actions.js +25 -0
- package/dist/features/products/columns/index.d.ts +0 -1
- package/dist/features/products/columns/index.js +5 -1
- package/dist/features/products/components/ArtStickersListView.js +7 -1
- package/dist/features/products/components/PrizeDrawsSection.js +5 -0
- package/dist/features/products/components/ProductFilters.d.ts +0 -9
- package/dist/features/products/components/ProductForm.d.ts +27 -1
- package/dist/features/products/components/ProductForm.js +26 -12
- package/dist/features/products/components/ProductsIndexPageView.js +1 -1
- package/dist/features/products/constants/sieve.d.ts +0 -6
- package/dist/features/products/constants/sieve.js +35 -2
- package/dist/features/products/repository/products.repository.d.ts +115 -1
- package/dist/features/products/repository/products.repository.js +491 -39
- package/dist/features/products/schemas/firestore.d.ts +65 -5
- package/dist/features/products/schemas/firestore.js +9 -0
- package/dist/features/products/schemas/product-features.d.ts +140 -2
- package/dist/features/products/schemas/product-features.js +62 -1
- package/dist/features/promotions/repository/coupons.repository.js +6 -1
- package/dist/features/promotions/schemas/firestore.d.ts +44 -1
- package/dist/features/promotions/schemas/firestore.js +76 -2
- package/dist/features/reviews/repository/reviews.repository.d.ts +22 -0
- package/dist/features/reviews/repository/reviews.repository.js +35 -0
- package/dist/features/seller/actions/seller-actions.js +17 -2
- package/dist/features/seller/components/PrintCenterView.d.ts +3 -2
- package/dist/features/seller/components/PrintCenterView.js +3 -2
- package/dist/features/seller/components/SellerAnalyticsAlertsView.js +21 -11
- package/dist/features/seller/components/SellerOrdersView.js +6 -1
- package/dist/features/seller/components/SellerPayoutSettingsView.js +19 -3
- package/dist/features/seller/components/SellerProductShell.d.ts +50 -2
- package/dist/features/seller/components/SellerProductShell.js +101 -9
- package/dist/features/seller/components/SellerProductsFilterDrawer.d.ts +13 -1
- package/dist/features/seller/components/SellerProductsFilterDrawer.js +2 -2
- package/dist/features/seller/components/SellerProductsView.js +108 -3
- package/dist/features/seller/types/index.d.ts +17 -0
- package/dist/features/seller/utils/product-draft-mapping.d.ts +13 -0
- package/dist/features/seller/utils/product-draft-mapping.js +17 -0
- package/dist/features/store-extensions/constants/alert-metrics.d.ts +86 -0
- package/dist/features/store-extensions/constants/alert-metrics.js +142 -0
- package/dist/features/store-extensions/schemas/firestore.d.ts +19 -1
- package/dist/features/stores/schemas/firestore.d.ts +31 -2
- package/dist/features/tax-codes/repository/tax-codes.repository.d.ts +55 -0
- package/dist/features/tax-codes/repository/tax-codes.repository.js +131 -0
- package/dist/features/tax-codes/schemas/firestore.d.ts +125 -0
- package/dist/features/tax-codes/schemas/firestore.js +82 -0
- package/dist/features/tax-codes/schemas/tax-code-form.d.ts +63 -0
- package/dist/features/tax-codes/schemas/tax-code-form.js +152 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.d.ts +107 -0
- package/dist/features/tax-codes/schemas/tax-codes.validators.js +85 -0
- package/dist/features/tester/actions/index.d.ts +0 -1
- package/dist/features/tester/actions/index.js +0 -1
- package/dist/features/tester/components/AdminTesterFeedbackIssuesView.js +1 -1
- package/dist/features/tester/components/AdminTesterFeedbackListView.js +1 -1
- package/dist/features/tester/components/index.d.ts +0 -4
- package/dist/features/tester/components/index.js +0 -2
- package/dist/features/tester/repository/tester-checklist-item.repository.d.ts +1 -20
- package/dist/features/tester/repository/tester-checklist-item.repository.js +0 -52
- package/dist/features/tester/schemas/firestore.d.ts +0 -6
- package/dist/features/tester/seed-data/authored/admin__admin-detail-round-trips.js +3 -3
- package/dist/features/tester/seed-data/authored/admin__site-system.js +4 -5
- package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js +2 -2
- package/dist/features/tester/seed-data/authored/index.js +0 -2
- package/dist/features/tester/seed-data/authored/page-wiring__reachability.js +0 -19
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +10 -29
- package/dist/index.d.ts +21 -7
- package/dist/index.js +53 -7
- package/dist/next/routing/route-map.d.ts +2 -4
- package/dist/next/routing/route-map.js +1 -2
- package/dist/repositories/index.d.ts +1 -0
- package/dist/repositories/index.js +1 -0
- package/dist/schemas/registry.d.ts +506 -0
- package/dist/seed/_helpers/brand-rows.d.ts +35 -0
- package/dist/seed/_helpers/brand-rows.js +576 -0
- package/dist/seed/_helpers/category-content.d.ts +39 -0
- package/dist/seed/_helpers/category-content.js +634 -0
- package/dist/seed/_helpers/category-forest.d.ts +2 -0
- package/dist/seed/_helpers/category-forest.js +585 -243
- package/dist/seed/_helpers/category-models.d.ts +5 -0
- package/dist/seed/_helpers/category-models.js +1364 -0
- package/dist/seed/_helpers/category-tree.js +17 -1
- package/dist/seed/_helpers/character-features.d.ts +10 -0
- package/dist/seed/_helpers/character-features.js +118 -0
- package/dist/seed/_helpers/media.d.ts +1 -1
- package/dist/seed/_helpers/media.js +44 -8
- package/dist/seed/_helpers/search-txt-wrappers.d.ts +10 -0
- package/dist/seed/_helpers/search-txt-wrappers.js +12 -1
- package/dist/seed/categories-seed-data.js +147 -169
- package/dist/seed/index.d.ts +1 -0
- package/dist/seed/index.js +1 -0
- package/dist/seed/manifest.d.ts +1 -1
- package/dist/seed/manifest.js +5 -0
- package/dist/seed/orders-seed-data.js +5 -3
- package/dist/seed/product-features-seed-data.d.ts +1 -8
- package/dist/seed/product-features-seed-data.js +358 -154
- package/dist/seed/products-art-seed-data.js +16 -4
- package/dist/seed/products-auctions-seed-data.js +6 -6
- package/dist/seed/products-classifieds-seed-data.js +17 -7
- package/dist/seed/products-digital-codes-seed-data.js +12 -12
- package/dist/seed/products-preorders-seed-data.js +8 -8
- package/dist/seed/products-prize-draws-seed-data.js +25 -8
- package/dist/seed/products-standard-seed-data.js +10 -60
- package/dist/seed/products-stickers-seed-data.js +6 -6
- package/dist/seed/site-settings-seed-data.js +24 -0
- package/dist/seed/store-extensions-seed-data.js +10 -4
- package/dist/seed/tax-codes-seed-data.d.ts +34 -0
- package/dist/seed/tax-codes-seed-data.js +100 -0
- package/dist/seed/test-data-ttl.d.ts +29 -0
- package/dist/seed/test-data-ttl.js +31 -0
- package/dist/server-entry.d.ts +1 -1
- package/dist/server-entry.js +6 -1
- package/dist/server.d.ts +4 -1
- package/dist/server.js +11 -2
- package/dist/styles.css +40 -0
- package/dist/ui/components/PaginatedSelect.d.ts +14 -0
- package/dist/ui/components/PaginatedSelect.js +0 -0
- package/dist/ui/components/PaginatedSelect.style.css +40 -0
- package/dist/utils/media-url.d.ts +26 -0
- package/dist/utils/media-url.js +144 -0
- package/dist/utils/physical-location.d.ts +23 -0
- package/dist/utils/physical-location.js +52 -0
- package/dist/utils/search-txt-builders.d.ts +20 -0
- package/dist/utils/search-txt-builders.js +36 -0
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +4 -1
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.d.ts +0 -2
- package/dist/_internal/server/jobs/handlers/testerSandboxCleanup.js +0 -2
- package/dist/features/tester/actions/leaderboard-actions.d.ts +0 -3
- package/dist/features/tester/actions/leaderboard-actions.js +0 -5
- package/dist/features/tester/components/BugHunterLeaderboardView.d.ts +0 -23
- package/dist/features/tester/components/BugHunterLeaderboardView.js +0 -18
- package/dist/features/tester/components/TesterHubView.d.ts +0 -5
- package/dist/features/tester/components/TesterHubView.js +0 -110
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.d.ts +0 -2
- package/dist/features/tester/seed-data/authored/public-pages__bug-hunters.js +0 -78
- package/dist/features/tester/seed-data/tester-ttl.d.ts +0 -4
- package/dist/features/tester/seed-data/tester-ttl.js +0 -6
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zod validators for the `/api/admin/tax-codes` route handlers.
|
|
3
|
+
*
|
|
4
|
+
* Separate from `tax-code-form.ts`, which is the EDITOR's schema: that one is
|
|
5
|
+
* annotated for `buildSectionsFromSchema`, takes strings from inputs, and
|
|
6
|
+
* coerces. These are the wire contracts, and they are `.strict()`.
|
|
7
|
+
*
|
|
8
|
+
* ## 🛑 `.strict()`, not `z.object()` and not `.passthrough()`
|
|
9
|
+
*
|
|
10
|
+
* `z.object()` STRIPS unknown keys, which is how a PATCH returns 200 having
|
|
11
|
+
* written nothing (Root Cause #40's shape, and the admin grouped-listings
|
|
12
|
+
* route's documented bug). `.passthrough()` writes whatever arrives, which is
|
|
13
|
+
* how a form overwrote booked lottery slots. `.strict()` 400s on a field the
|
|
14
|
+
* contract does not name — the caller is told, and nothing silently vanishes.
|
|
15
|
+
*
|
|
16
|
+
* ## The id is NOT accepted on update
|
|
17
|
+
*
|
|
18
|
+
* `createTaxCodeId` derives the id from the HSN code, so accepting an id (or
|
|
19
|
+
* re-deriving one on update) would let an edit orphan every
|
|
20
|
+
* `CategoryProductDefaults.taxCodeId` pointing at the old one — with a GST
|
|
21
|
+
* invoice at the end of that chain. To correct a wrong HSN: deactivate, create
|
|
22
|
+
* the right row, repoint the categories.
|
|
23
|
+
*/
|
|
24
|
+
import { z } from "zod";
|
|
25
|
+
import { GST_RATE_VALUES } from "./firestore";
|
|
26
|
+
const LABEL_MAX = 150;
|
|
27
|
+
const DESCRIPTION_MAX = 500;
|
|
28
|
+
const NOTES_MAX = 1000;
|
|
29
|
+
/**
|
|
30
|
+
* 🛑 `z.custom<GstRate>`, not `z.number().refine(...)`.
|
|
31
|
+
*
|
|
32
|
+
* A `.refine()` validates at runtime and does NOT narrow the inferred type —
|
|
33
|
+
* the payload still types as `number`, so `repository.create(body)` fails to
|
|
34
|
+
* compile against `gstRate: GstRate`, and the obvious unblock is a cast. A
|
|
35
|
+
* cast at a request boundary is where this codebase's worst bugs live (an
|
|
36
|
+
* `ActionResult` envelope spread as a product, a raw `StoreDocument` published
|
|
37
|
+
* as HTML), so the type is narrowed here instead.
|
|
38
|
+
*
|
|
39
|
+
* And `z.custom` rather than a hand-written `z.union([z.literal(0), …])`
|
|
40
|
+
* because the slab list then has ONE definition — `GST_RATE_VALUES`, which
|
|
41
|
+
* `ProductDocument.gstRate` and the form's option list also derive from. A
|
|
42
|
+
* literal union here would be a second enumeration of the same union, which is
|
|
43
|
+
* Root Cause #61's shape.
|
|
44
|
+
*/
|
|
45
|
+
export const GST_RATE_ENUM = z.custom((v) => typeof v === "number" && GST_RATE_VALUES.includes(v), { message: "gstRate must be one of 0, 5, 12, 18 or 28." });
|
|
46
|
+
export const HSN_CHAPTER_ENUM = z.enum(["9503", "4911", "9504", "exempt"]);
|
|
47
|
+
/**
|
|
48
|
+
* 🛑 `hsnCode` is OPTIONAL here and the blank-only-at-0% rule lives in the
|
|
49
|
+
* repository, not this schema. Deliberate: the same rule has to hold for the
|
|
50
|
+
* seed path and any future importer, neither of which goes through a Zod
|
|
51
|
+
* request schema. A rule enforced only at the HTTP edge is a rule with a side
|
|
52
|
+
* door.
|
|
53
|
+
*/
|
|
54
|
+
export const taxCodeCreateSchema = z
|
|
55
|
+
.object({
|
|
56
|
+
/*
|
|
57
|
+
* Omitted becomes `""`, not `undefined`, because `TaxCodeDocument.hsnCode`
|
|
58
|
+
* is REQUIRED and the exemption row's value genuinely is the empty string.
|
|
59
|
+
* An optional-into-required field here would force a cast at the one call
|
|
60
|
+
* site, and "no HSN" and "nobody filled this in" would become
|
|
61
|
+
* indistinguishable — exactly the `undefined`-vs-`0` distinction `gstRate`
|
|
62
|
+
* depends on, one field over.
|
|
63
|
+
*/
|
|
64
|
+
hsnCode: z.string().trim().max(8).default(""),
|
|
65
|
+
label: z.string().trim().min(1).max(LABEL_MAX),
|
|
66
|
+
description: z.string().max(DESCRIPTION_MAX).optional(),
|
|
67
|
+
gstRate: GST_RATE_ENUM,
|
|
68
|
+
chapter: HSN_CHAPTER_ENUM.optional(),
|
|
69
|
+
effectiveFrom: z.coerce.date().optional(),
|
|
70
|
+
isActive: z.boolean().default(true),
|
|
71
|
+
notes: z.string().max(NOTES_MAX).optional(),
|
|
72
|
+
})
|
|
73
|
+
.strict();
|
|
74
|
+
export const taxCodeUpdateSchema = z
|
|
75
|
+
.object({
|
|
76
|
+
hsnCode: z.string().trim().max(8).optional(),
|
|
77
|
+
label: z.string().trim().min(1).max(LABEL_MAX).optional(),
|
|
78
|
+
description: z.string().max(DESCRIPTION_MAX).optional(),
|
|
79
|
+
gstRate: GST_RATE_ENUM.optional(),
|
|
80
|
+
chapter: HSN_CHAPTER_ENUM.optional(),
|
|
81
|
+
effectiveFrom: z.coerce.date().optional(),
|
|
82
|
+
isActive: z.boolean().optional(),
|
|
83
|
+
notes: z.string().max(NOTES_MAX).optional(),
|
|
84
|
+
})
|
|
85
|
+
.strict();
|
|
@@ -4,7 +4,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
4
4
|
import { Button, Card, Details, Div, Row, Stack, Summary, Text } from "../../../ui";
|
|
5
5
|
import { MediaImage } from "../../media/MediaImage";
|
|
6
6
|
import { apiClient } from "../../../http";
|
|
7
|
-
import { useApiMutation } from "../../../client";
|
|
7
|
+
import { useApiMutation } from "../../../client/api/useApiMutation";
|
|
8
8
|
import { ADMIN_ENDPOINTS } from "../../../constants/api-endpoints";
|
|
9
9
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
10
10
|
const REPORT_QUERY_KEY = ["admin", "tester-feedback", "report"];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { useApiMutation } from "../../../client";
|
|
3
|
+
import { useApiMutation } from "../../../client/api/useApiMutation";
|
|
4
4
|
import { SIEVE_OP, sieveFilter } from "../../../utils/sieve-builder";
|
|
5
5
|
import { sortBy } from "../../../constants/sort";
|
|
6
6
|
import { TESTER_CHECKLIST_RESPONSE_FIELDS } from "../schemas/firestore";
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
export { TesterHubView } from "./TesterHubView";
|
|
2
|
-
export type { TesterHubViewProps } from "./TesterHubView";
|
|
3
1
|
export { TesterChecklistStepRow } from "./TesterChecklistStepRow";
|
|
4
2
|
export type { TesterChecklistStepRowProps, TesterChecklistStepItem } from "./TesterChecklistStepRow";
|
|
5
3
|
export { TesterFeedbackChart } from "./TesterFeedbackChart";
|
|
@@ -9,5 +7,3 @@ export { AdminTesterFeedbackReportView } from "./AdminTesterFeedbackReportView";
|
|
|
9
7
|
export { AdminTesterFeedbackIssuesView } from "./AdminTesterFeedbackIssuesView";
|
|
10
8
|
export { AdminTesterFeedbackListView } from "./AdminTesterFeedbackListView";
|
|
11
9
|
export type { AdminTesterFeedbackListViewProps } from "./AdminTesterFeedbackListView";
|
|
12
|
-
export { BugHunterLeaderboardView } from "./BugHunterLeaderboardView";
|
|
13
|
-
export type { BugHunterLeaderboardViewProps } from "./BugHunterLeaderboardView";
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
export { TesterHubView } from "./TesterHubView";
|
|
2
1
|
export { TesterChecklistStepRow } from "./TesterChecklistStepRow";
|
|
3
2
|
export { TesterFeedbackChart } from "./TesterFeedbackChart";
|
|
4
3
|
export { AdminTesterFeedbackView } from "./AdminTesterFeedbackView";
|
|
5
4
|
export { AdminTesterFeedbackReportView } from "./AdminTesterFeedbackReportView";
|
|
6
5
|
export { AdminTesterFeedbackIssuesView } from "./AdminTesterFeedbackIssuesView";
|
|
7
6
|
export { AdminTesterFeedbackListView } from "./AdminTesterFeedbackListView";
|
|
8
|
-
export { BugHunterLeaderboardView } from "./BugHunterLeaderboardView";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseRepository } from "../../../providers/db-firebase";
|
|
2
2
|
import type { FirebaseSieveFields, FirebaseSieveResult, SieveModel } from "../../../providers/db-firebase";
|
|
3
|
-
import { type TesterChecklistItemDocument, type TesterChecklistItemCreateInput, type TesterChecklistItemUpdateInput
|
|
3
|
+
import { type TesterChecklistItemDocument, type TesterChecklistItemCreateInput, type TesterChecklistItemUpdateInput } from "../schemas/firestore";
|
|
4
4
|
export declare class TesterChecklistItemRepository extends BaseRepository<TesterChecklistItemDocument> {
|
|
5
5
|
static readonly SIEVE_FIELDS: FirebaseSieveFields;
|
|
6
6
|
constructor();
|
|
@@ -15,24 +15,5 @@ export declare class TesterChecklistItemRepository extends BaseRepository<Tester
|
|
|
15
15
|
/** Reopens a fixed, bug-confirmed case as a new, active version for retest.
|
|
16
16
|
* The old item stays disabled forever with its bug-hunter credit intact. */
|
|
17
17
|
reopenAsNewVersion(oldItemId: string): Promise<TesterChecklistItemDocument>;
|
|
18
|
-
/**
|
|
19
|
-
* Ids of automated (non-human) accounts, excluded from the PUBLIC leaderboard.
|
|
20
|
-
*
|
|
21
|
-
* Read as a bare collection query rather than through `userRepository` on purpose:
|
|
22
|
-
* no repository in this codebase imports another, and this needs a key set, not
|
|
23
|
-
* user documents. `.select()` with no fields returns refs only, so the read is as
|
|
24
|
-
* cheap as Firestore allows, and `isBot == true` is a single-field equality served
|
|
25
|
-
* by the automatic index — no composite index to declare.
|
|
26
|
-
*/
|
|
27
|
-
private botHunterIds;
|
|
28
|
-
/** Single-query, in-memory aggregation of bug credits per hunter — mirrors
|
|
29
|
-
* EventEntryRepository.getLeaderboard()'s shape. Includes old/disabled/
|
|
30
|
-
* superseded items, since bug credit is permanent.
|
|
31
|
-
*
|
|
32
|
-
* Bot accounts are aggregated out (not merely ranked last): the board exists to
|
|
33
|
-
* credit people, and a runner working all 943 cases would otherwise dominate it.
|
|
34
|
-
* The credit still lives on the item, so admin triage and the item's own
|
|
35
|
-
* `bugHunterName` are unaffected. */
|
|
36
|
-
getBugHunterLeaderboard(limit?: number): Promise<BugHunterLeaderboardEntry[]>;
|
|
37
18
|
}
|
|
38
19
|
export declare const testerChecklistItemRepository: TesterChecklistItemRepository;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BaseRepository, parseSieveDateValue } from "../../../providers/db-firebase";
|
|
2
2
|
import { buildSearchTxt } from "../../../utils/search-txt";
|
|
3
3
|
import { DatabaseError } from "../../../errors";
|
|
4
|
-
import { USER_COLLECTION } from "../../auth/schemas/firestore";
|
|
5
4
|
import { TESTER_CHECKLIST_ITEM_COLLECTION, TESTER_CHECKLIST_ITEM_FIELDS, createChecklistItemId, } from "../schemas/firestore";
|
|
6
5
|
export class TesterChecklistItemRepository extends BaseRepository {
|
|
7
6
|
constructor() {
|
|
@@ -87,57 +86,6 @@ export class TesterChecklistItemRepository extends BaseRepository {
|
|
|
87
86
|
await this.update(old.id, { supersededByItemId: newId });
|
|
88
87
|
return newItem;
|
|
89
88
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Ids of automated (non-human) accounts, excluded from the PUBLIC leaderboard.
|
|
92
|
-
*
|
|
93
|
-
* Read as a bare collection query rather than through `userRepository` on purpose:
|
|
94
|
-
* no repository in this codebase imports another, and this needs a key set, not
|
|
95
|
-
* user documents. `.select()` with no fields returns refs only, so the read is as
|
|
96
|
-
* cheap as Firestore allows, and `isBot == true` is a single-field equality served
|
|
97
|
-
* by the automatic index — no composite index to declare.
|
|
98
|
-
*/
|
|
99
|
-
async botHunterIds() {
|
|
100
|
-
const snapshot = await this.db
|
|
101
|
-
.collection(USER_COLLECTION)
|
|
102
|
-
.where("isBot", "==", true)
|
|
103
|
-
.select()
|
|
104
|
-
.get();
|
|
105
|
-
return new Set(snapshot.docs.map((d) => d.id));
|
|
106
|
-
}
|
|
107
|
-
/** Single-query, in-memory aggregation of bug credits per hunter — mirrors
|
|
108
|
-
* EventEntryRepository.getLeaderboard()'s shape. Includes old/disabled/
|
|
109
|
-
* superseded items, since bug credit is permanent.
|
|
110
|
-
*
|
|
111
|
-
* Bot accounts are aggregated out (not merely ranked last): the board exists to
|
|
112
|
-
* credit people, and a runner working all 943 cases would otherwise dominate it.
|
|
113
|
-
* The credit still lives on the item, so admin triage and the item's own
|
|
114
|
-
* `bugHunterName` are unaffected. */
|
|
115
|
-
async getBugHunterLeaderboard(limit = 50) {
|
|
116
|
-
const [snapshot, botIds] = await Promise.all([
|
|
117
|
-
this.db
|
|
118
|
-
.collection(this.collection)
|
|
119
|
-
.where(TESTER_CHECKLIST_ITEM_FIELDS.BUG_CONFIRMED, "==", true)
|
|
120
|
-
.get(),
|
|
121
|
-
this.botHunterIds(),
|
|
122
|
-
]);
|
|
123
|
-
const byHunter = new Map();
|
|
124
|
-
for (const doc of snapshot.docs) {
|
|
125
|
-
const item = this.mapDoc(doc);
|
|
126
|
-
if (!item.bugHunterId || botIds.has(item.bugHunterId))
|
|
127
|
-
continue;
|
|
128
|
-
const entry = byHunter.get(item.bugHunterId) ?? {
|
|
129
|
-
name: item.bugHunterName ?? "Unknown tester",
|
|
130
|
-
count: 0,
|
|
131
|
-
};
|
|
132
|
-
entry.count += 1;
|
|
133
|
-
byHunter.set(item.bugHunterId, entry);
|
|
134
|
-
}
|
|
135
|
-
return Array.from(byHunter.entries())
|
|
136
|
-
.map(([hunterId, v]) => ({ hunterId, hunterName: v.name, bugCount: v.count }))
|
|
137
|
-
.sort((a, b) => b.bugCount - a.bugCount)
|
|
138
|
-
.slice(0, limit)
|
|
139
|
-
.map((entry, index) => ({ ...entry, rank: index + 1 }));
|
|
140
|
-
}
|
|
141
89
|
}
|
|
142
90
|
TesterChecklistItemRepository.SIEVE_FIELDS = {
|
|
143
91
|
groupKey: { canFilter: true, canSort: true },
|
|
@@ -164,12 +164,6 @@ export declare const testerChecklistItemQueryHelpers: {
|
|
|
164
164
|
readonly active: () => readonly ["isActive", "==", true];
|
|
165
165
|
readonly confirmedBugs: () => readonly ["bugConfirmed", "==", true];
|
|
166
166
|
};
|
|
167
|
-
export interface BugHunterLeaderboardEntry {
|
|
168
|
-
rank: number;
|
|
169
|
-
hunterId: string;
|
|
170
|
-
hunterName: string;
|
|
171
|
-
bugCount: number;
|
|
172
|
-
}
|
|
173
167
|
export declare function slugifyChecklistLabel(label: string): string;
|
|
174
168
|
export declare function createChecklistItemId(groupKey: string, pageKey: string, label: string): string;
|
|
175
169
|
/**
|
|
@@ -64,15 +64,15 @@ export const authored = {
|
|
|
64
64
|
startPage: "/admin/categories",
|
|
65
65
|
steps: [
|
|
66
66
|
"Sign in as admin@letitrip.in / TempPass123!.",
|
|
67
|
-
"Open /categories/category-x-
|
|
68
|
-
"In the first tab open /admin/categories and find
|
|
67
|
+
"Open /categories/category-x-basic as a visitor in a second tab and write down its product count. Note the FULL id — /categories/x-basic serves 'Category Not Found'; every category id carries the category- prefix.",
|
|
68
|
+
"In the first tab open /admin/categories and find Basic Line — that is the display name of category-x-basic; there is no category called 'X Basic'.",
|
|
69
69
|
"Write down its parent and how many children it has.",
|
|
70
70
|
"Open its Edit action, change ONLY its description, and press Save.",
|
|
71
71
|
"Reload the admin list and reopen it.",
|
|
72
72
|
"Reload the public category page in the second tab.",
|
|
73
73
|
"Restore the description by removing the word you appended, then save again. Three of the cases on this page append a marker and this one accumulated 'roundtrip' from an earlier run — categories is SEED_OWNED, but a run does not reseed.",
|
|
74
74
|
],
|
|
75
|
-
inputs: { categorySlug: "x-
|
|
75
|
+
inputs: { categorySlug: "x-basic" },
|
|
76
76
|
expectedBehaviour: "A rename or a description edit touches that field alone. The hierarchy fields — parent, children, ancestors, tier — are derived and must never be rewritten from form state, and the product count is derived from a trigger rather than typed.",
|
|
77
77
|
expectedUiState: "The parent and the child count are unchanged, and the public page shows the same product count as before.",
|
|
78
78
|
expectedData: { hierarchyChanged: false, countChanged: false },
|
|
@@ -576,13 +576,12 @@ export const authored = {
|
|
|
576
576
|
"Open /admin/tester-checklist and read the catalogue.",
|
|
577
577
|
"Create a case with a label, a description, a group, a page, roles, a start page and steps.",
|
|
578
578
|
"Save, RELOAD, and read every field including roles and steps.",
|
|
579
|
-
"
|
|
580
|
-
"Check its roles, steps and expectations all render there.",
|
|
579
|
+
"Reopen the catalogue list and find the new case by searching its label.",
|
|
581
580
|
"Delete the case and confirm it disappears from both surfaces.",
|
|
582
581
|
],
|
|
583
|
-
expectedBehaviour: "The admin editor accepts every field a case carries, including the roles list, the input values and the expected data —
|
|
584
|
-
expectedUiState: "After the reload the case holds every field
|
|
585
|
-
endResult: "The case is deleted from
|
|
582
|
+
expectedBehaviour: "The admin editor accepts every field a case carries, including the roles list, the input values and the expected data — a field added to the document type must reach this form too, or an admin can create a case the harness cannot read.",
|
|
583
|
+
expectedUiState: "After the reload the case holds every field, including roles, steps, both value tables and the expectations. A field the editor accepts but does not read back is the finding.",
|
|
584
|
+
endResult: "The case is deleted from the catalogue.",
|
|
586
585
|
},
|
|
587
586
|
"checklist-admin-site-system-tester-feedback-report-export": {
|
|
588
587
|
roles: ["admin"],
|
package/dist/features/tester/seed-data/authored/content-discovery__category-counts-and-rollup.js
CHANGED
|
@@ -45,7 +45,7 @@ export const authored = {
|
|
|
45
45
|
roles: ["guest"],
|
|
46
46
|
startPage: "/categories",
|
|
47
47
|
steps: [
|
|
48
|
-
"Open /categories/category-x-tops — a parent whose children are category-x-
|
|
48
|
+
"Open /categories/category-x-tops — a parent whose children are the four Beyblade X retail lines, category-x-basic, category-x-unique-ux, category-x-custom-cx and category-x-over — every category id carries the `category-` prefix, and a URL without it does not resolve.",
|
|
49
49
|
"Write down the count on the parent's tile.",
|
|
50
50
|
"Open the parent and write down the count shown on each of its child chips.",
|
|
51
51
|
"Add the children's counts together.",
|
|
@@ -74,7 +74,7 @@ export const authored = {
|
|
|
74
74
|
roles: ["guest"],
|
|
75
75
|
startPage: "/categories",
|
|
76
76
|
steps: [
|
|
77
|
-
"Open /categories/category-x-tops, a parent that shows a row of child chips — category-x-
|
|
77
|
+
"Open /categories/category-x-tops, a parent that shows a row of child chips — category-x-basic, category-x-unique-ux, category-x-custom-cx and category-x-over.",
|
|
78
78
|
"Write down the number in the page header.",
|
|
79
79
|
"Write down the number on each child chip.",
|
|
80
80
|
"Open one child and compare its own header number to the number its chip showed.",
|
|
@@ -94,7 +94,6 @@ import { authored as a_design_ux__hand_mode_layout } from "./design-ux__hand-mod
|
|
|
94
94
|
import { authored as a_design_ux__homepage_carousels } from "./design-ux__homepage-carousels";
|
|
95
95
|
import { authored as a_page_wiring__data_loss } from "./page-wiring__data-loss";
|
|
96
96
|
import { authored as a_public_pages__auth_error_pages } from "./public-pages__auth-error-pages";
|
|
97
|
-
import { authored as a_public_pages__bug_hunters } from "./public-pages__bug-hunters";
|
|
98
97
|
import { authored as a_public_pages__core_listing_pages } from "./public-pages__core-listing-pages";
|
|
99
98
|
import { authored as a_public_pages__help_how_it_works } from "./public-pages__help-how-it-works";
|
|
100
99
|
import { authored as a_public_pages__legal_policy_pages } from "./public-pages__legal-policy-pages";
|
|
@@ -214,7 +213,6 @@ export const AUTHORED_CASES = {
|
|
|
214
213
|
...a_design_ux__homepage_carousels,
|
|
215
214
|
...a_page_wiring__data_loss,
|
|
216
215
|
...a_public_pages__auth_error_pages,
|
|
217
|
-
...a_public_pages__bug_hunters,
|
|
218
216
|
...a_public_pages__core_listing_pages,
|
|
219
217
|
...a_public_pages__help_how_it_works,
|
|
220
218
|
...a_public_pages__legal_policy_pages,
|
|
@@ -112,23 +112,4 @@ export const authored = {
|
|
|
112
112
|
expectedData: { brokenLinkCount: 0, linksChecked: 62 },
|
|
113
113
|
endResult: "Read-only; nothing persists. Record every broken href in the comment, not just the first — one report naming all of them is worth more than a verdict.",
|
|
114
114
|
},
|
|
115
|
-
"checklist-page-wiring-reachability-user-tester-hub-reachable-from-user-sidebar": {
|
|
116
|
-
roles: ["admin", "buyer"],
|
|
117
|
-
startPage: "/user",
|
|
118
|
-
steps: [
|
|
119
|
-
"Sign in as admin@letitrip.in / TempPass123!, open /admin/users, and turn the tester flag ON for vivaan.kapoor@gmail.com — no seeded account carries it, so the case sets up the flag it is about.",
|
|
120
|
-
"Sign out and sign in as vivaan.kapoor@gmail.com / TempPass123!, which now carries the tester flag.",
|
|
121
|
-
"Open /user and read the sidebar.",
|
|
122
|
-
"Find the Testing group and click Tester Hub.",
|
|
123
|
-
"Read where it lands.",
|
|
124
|
-
"Sign out and sign in as rehan.sheikh@gmail.com / TempPass123!, which does not carry the flag.",
|
|
125
|
-
"Open /user and read the sidebar for a Testing group.",
|
|
126
|
-
"Sign back in as admin@letitrip.in and turn the tester flag on vivaan.kapoor@gmail.com back off.",
|
|
127
|
-
],
|
|
128
|
-
inputs: { testerAccount: "vivaan.kapoor@gmail.com", nonTesterAccount: "rehan.sheikh@gmail.com" },
|
|
129
|
-
expectedBehaviour: "The Testing group is injected at runtime for accounts carrying the tester flag and is empty for everyone else. An empty group must not render as a heading with nothing under it.",
|
|
130
|
-
expectedUiState: "The tester sees a Testing group containing Tester Hub, and clicking it opens /user/tester with the checklist. The non-tester sees no Testing group at all — not a heading with no children, and not a link that leads to a 'Testers only' warning.",
|
|
131
|
-
expectedData: { testingGroupVisibleForNonTester: false },
|
|
132
|
-
endResult: "The flag is revoked by the final step, leaving vivaan.kapoor@gmail.com on its seeded settings. Checking both accounts is the case — a group that renders for everybody would pass the first half alone.",
|
|
133
|
-
},
|
|
134
115
|
};
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
* WHAT: Default test cases across 8 groups (Account & Auth, Buying, Selling, Content & Discovery,
|
|
4
4
|
* Community & Support, Design & UX, Public & Marketing Pages, Admin (Testing)). Admins add/edit
|
|
5
5
|
* further cases via /admin/tester-checklist — this array is a starting point, not the source of
|
|
6
|
-
* truth. Every case is searchable by title or route
|
|
7
|
-
*
|
|
6
|
+
* truth. Every case is searchable by title or route at /admin/tester-checklist — the human-facing
|
|
7
|
+
* Tester Hub at /user/tester was deleted in B2, and the Claude tester reads the catalogue
|
|
8
|
+
* through GET /api/user/tester-checklist instead. Items in the "admin" group carry adminOnly:true — only
|
|
8
9
|
* visible to a tester with canTestAdmin (or a real admin); see `group()`'s `opts.adminOnly`.
|
|
9
10
|
*
|
|
10
11
|
* EXPORTS:
|
|
@@ -509,8 +510,8 @@ const rawTesterChecklistItems = [
|
|
|
509
510
|
},
|
|
510
511
|
{
|
|
511
512
|
key: "seed-images-are-labelled-tiles",
|
|
512
|
-
label: "Every seeded product image is a
|
|
513
|
-
description: "
|
|
513
|
+
label: "Every seeded product image is a coloured local tile — NOT a broken-image icon, and NOT all the same colour",
|
|
514
|
+
description: "Updated 2026-10-09. BEFORE: seeded images were fetched from a third party through /api/media/ext — one Node lambda plus a sharp re-encode PER IMAGE, 160 of them on the homepage alone. That is what exceeded the Vercel Hobby caps and suspended the site (HTTP 402). AFTER: `seedPhoto()` returns a static local file under `/images/seed-tiles/<hex>.svg`, so a seeded image costs no function and no upstream request. Open a product grid and confirm each card shows a coloured tile with a faint ring motif. Two checks that matter: view-source on a card image and confirm the src starts with `/images/seed-tiles/` and NOT `/api/media/ext`; and confirm the tiles are not all one colour (the colour is hashed per item, so a grid should show several). NOTE: tiles deliberately no longer render the item's NAME — that text cost a function invocation per card to draw, and the card already displays the title beside the image.", // audit-hardcoded-api-routes-ok: prose, not a call site — the tester must be told the exact string to look for in an image src, and "the external-media proxy route" is not checkable
|
|
514
515
|
href: "/products",
|
|
515
516
|
},
|
|
516
517
|
{
|
|
@@ -3829,7 +3830,7 @@ const rawTesterChecklistItems = [
|
|
|
3829
3830
|
{
|
|
3830
3831
|
key: "detail-page-tags-readable",
|
|
3831
3832
|
label: "Opening an individual auction, pre-order, prize draw, classified, digital code and live-item page, each one's type tag and status chips are readable in light mode",
|
|
3832
|
-
description: "Card grids and detail pages don't always share the same component, so check both. Use the
|
|
3833
|
+
description: "Card grids and detail pages don't always share the same component, so check both. Use the seeded listings of each type if you need one of each.",
|
|
3833
3834
|
href: "/auctions/auction-beyblade-original-dragoon-storm",
|
|
3834
3835
|
},
|
|
3835
3836
|
{
|
|
@@ -4623,21 +4624,6 @@ const rawTesterChecklistItems = [
|
|
|
4623
4624
|
},
|
|
4624
4625
|
],
|
|
4625
4626
|
},
|
|
4626
|
-
{
|
|
4627
|
-
pageKey: "bug-hunters",
|
|
4628
|
-
pageLabel: "Bug Hunters Leaderboard",
|
|
4629
|
-
href: "/bug-hunters",
|
|
4630
|
-
cases: [
|
|
4631
|
-
{
|
|
4632
|
-
key: "leaderboard-loads",
|
|
4633
|
-
label: "The public Bug Hunters leaderboard (/bug-hunters) loads and lists testers ranked by confirmed-bug count, most bugs first",
|
|
4634
|
-
description: "Verify against the seeded demo fixture — \"Mock User 3\" should appear on the leaderboard with 1 confirmed bug (from the \"Demo fixture\" case under Admin (Testing) → Bug Hunter Rewards).",
|
|
4635
|
-
href: "/bug-hunters",
|
|
4636
|
-
},
|
|
4637
|
-
{ key: "leaderboard-empty-state", label: "If no bugs have been confirmed yet, the leaderboard shows a clear \"No confirmed bugs yet\" empty state instead of a blank page or error" },
|
|
4638
|
-
{ key: "leaderboard-footer-link", label: "A \"Bug Hunters\" link is present in the site footer's Support column and navigates to /bug-hunters" },
|
|
4639
|
-
],
|
|
4640
|
-
},
|
|
4641
4627
|
]),
|
|
4642
4628
|
...group("seo", "SEO & Metadata", [
|
|
4643
4629
|
{
|
|
@@ -5630,7 +5616,7 @@ const rawTesterChecklistItems = [
|
|
|
5630
5616
|
{
|
|
5631
5617
|
key: "confirm-bug",
|
|
5632
5618
|
label: "Admin can mark a tester's \"No\" answer as a confirmed bug from the Main Issues tab (or the All Submissions tab) — the reporting tester is credited as the bug hunter and the case is disabled so no other tester can answer it",
|
|
5633
|
-
description: "From /admin/tester-feedback → Main Issues, click \"Mark as Bug\" on any open issue. Confirm: (1) the confirmation dialog appears before it commits, (2) the issue's card now shows a \"🐛 Confirmed — credited to [tester name]\" badge, (3)
|
|
5619
|
+
description: "From /admin/tester-feedback → Main Issues, click \"Mark as Bug\" on any open issue. Confirm: (1) the confirmation dialog appears before it commits, (2) the issue's card now shows a \"🐛 Confirmed — credited to [tester name]\" badge, (3) the case no longer appears for any other tester in GET /api/user/tester-checklist.",
|
|
5634
5620
|
href: "/admin/tester-feedback",
|
|
5635
5621
|
},
|
|
5636
5622
|
{
|
|
@@ -5640,7 +5626,7 @@ const rawTesterChecklistItems = [
|
|
|
5640
5626
|
{
|
|
5641
5627
|
key: "reopen-case",
|
|
5642
5628
|
label: "Admin can reopen a bug-confirmed case as a new version for retest — the new version is active and answerable again, while the old case stays disabled in the catalog with its bug-hunter credit intact",
|
|
5643
|
-
description: "Verify against the seeded \"Demo fixture — reported bug, already confirmed and reopened\" pair under this page: the v1 case should show Status \"Bug Confirmed\" and be hidden from the catalog's default (Active-only) view, while its v2 case shows Status \"Active\" and is answerable
|
|
5629
|
+
description: "Verify against the seeded \"Demo fixture — reported bug, already confirmed and reopened\" pair under this page: the v1 case should show Status \"Bug Confirmed\" and be hidden from the catalog's default (Active-only) view, while its v2 case shows Status \"Active\" and is answerable. From /admin/tester-checklist, switch the Status filter to \"Inactive\" or \"Bug status → Bug Confirmed\" to find v1, then use its \"Reopen as New Test Case\" row action on any other bug-confirmed case to try the flow live.",
|
|
5644
5630
|
href: "/admin/tester-checklist",
|
|
5645
5631
|
},
|
|
5646
5632
|
{
|
|
@@ -5994,7 +5980,8 @@ const rawTesterChecklistItems = [
|
|
|
5994
5980
|
// (bugConfirmed/bugHunterId/version/previousVersionId/supersededByItemId
|
|
5995
5981
|
// are not part of the CaseInput shape group() builds). Lets an admin/
|
|
5996
5982
|
// tester see the full state machine immediately after a fresh reseed,
|
|
5997
|
-
//
|
|
5983
|
+
// The /bug-hunters leaderboard this also fed was deleted in B2; the pair
|
|
5984
|
+
// stays because /admin/tester-feedback reads the same credit fields.
|
|
5998
5985
|
{
|
|
5999
5986
|
id: "checklist-admin-bug-hunter-rewards-demo-fixture",
|
|
6000
5987
|
groupKey: "admin",
|
|
@@ -6133,12 +6120,6 @@ const rawTesterChecklistItems = [
|
|
|
6133
6120
|
description: "Walk the public header nav, the sidebar support links and every footer column. All 55 hrefs must land on a real page. No audit checked ANY of them until this wave — the nav audit only ever looked at the three portal sidebars.",
|
|
6134
6121
|
href: "/",
|
|
6135
6122
|
},
|
|
6136
|
-
{
|
|
6137
|
-
key: "user-tester-hub-reachable-from-user-sidebar",
|
|
6138
|
-
label: "A tester reaches the Tester Hub from their OWN sidebar",
|
|
6139
|
-
description: "As a user with the tester flag, open /user and find Tester Hub in the sidebar under Testing. The group is injected at runtime and is empty for non-testers — confirm a NON-tester account does not see it.",
|
|
6140
|
-
href: "/user",
|
|
6141
|
-
},
|
|
6142
6123
|
],
|
|
6143
6124
|
},
|
|
6144
6125
|
]),
|
package/dist/index.d.ts
CHANGED
|
@@ -546,9 +546,14 @@ export { ELIGIBLE_ORDER_STATUSES_FOR_TICKET, SUPPORT_TICKET_COLLECTION, ACTIVE_T
|
|
|
546
546
|
export { supportTicketsSeedData } from "./seed/index";
|
|
547
547
|
export { offersSeedData } from "./seed/index";
|
|
548
548
|
export { payoutMethodsSeedData, shippingConfigsSeedData, analyticsCardsSeedData, analyticsAlertsSeedData, storeCategoriesSeedData, listingTemplatesSeedData, moderationQueueSeedData, reportsSeedData, itemRequestsSeedData, storeWhatsAppConfigSeedData, storeGoogleConfigSeedData, } from "./seed/index";
|
|
549
|
+
export { AdminTaxCodesView } from "./features/admin/components/AdminTaxCodesView";
|
|
550
|
+
export type { AdminTaxCodesViewProps } from "./features/admin/components/AdminTaxCodesView";
|
|
551
|
+
export { AdminTaxCodeEditorView } from "./features/admin/components/AdminTaxCodeEditorView";
|
|
552
|
+
export type { AdminTaxCodeEditorViewProps } from "./features/admin/components/AdminTaxCodeEditorView";
|
|
549
553
|
export { productFeaturesRepository } from "./repositories/index";
|
|
550
554
|
export type { ProductFeatureListFilter } from "./repositories/index";
|
|
551
555
|
export { loadProductFeaturesForStore } from "./repositories/index";
|
|
556
|
+
export { taxCodesRepository } from "./repositories/index";
|
|
552
557
|
export { productTemplateRepository } from "./repositories/index";
|
|
553
558
|
export type { ProductTemplateDocument, ProductTemplateCreateInput, ProductTemplateUpdateInput, } from "./repositories/index";
|
|
554
559
|
export { tokenRepository } from "./repositories/index";
|
|
@@ -1032,11 +1037,7 @@ export { AdminTesterChecklistView } from "./features/admin/index";
|
|
|
1032
1037
|
export type { AdminTesterChecklistViewProps } from "./features/admin/index";
|
|
1033
1038
|
export { AdminTesterChecklistItemEditorView } from "./features/admin/index";
|
|
1034
1039
|
export type { AdminTesterChecklistItemEditorViewProps } from "./features/admin/index";
|
|
1035
|
-
export { TesterHubView } from "./features/tester/index";
|
|
1036
|
-
export type { TesterHubViewProps } from "./features/tester/index";
|
|
1037
1040
|
export { AdminTesterFeedbackView } from "./features/tester/index";
|
|
1038
|
-
export { BugHunterLeaderboardView } from "./features/tester/index";
|
|
1039
|
-
export type { BugHunterLeaderboardViewProps } from "./features/tester/index";
|
|
1040
1041
|
export { AdminNavEditorView } from "./features/admin/index";
|
|
1041
1042
|
export type { AdminNavEditorViewProps, NavItemData } from "./features/admin/index";
|
|
1042
1043
|
export { AdminNewsletterView } from "./features/admin/index";
|
|
@@ -1555,6 +1556,7 @@ export { POST } from "./features/categories/server";
|
|
|
1555
1556
|
export { categoriesGET } from "./features/categories/server";
|
|
1556
1557
|
export { categoryItemDELETE } from "./features/categories/server";
|
|
1557
1558
|
export { categoryItemGET } from "./features/categories/server";
|
|
1559
|
+
export { categoryDescriptionTemplateGET } from "./features/categories/server";
|
|
1558
1560
|
export { categoryItemPATCH } from "./features/categories/server";
|
|
1559
1561
|
export { createCategory } from "./features/categories/server";
|
|
1560
1562
|
export { deleteCategory } from "./features/categories/server";
|
|
@@ -1767,7 +1769,6 @@ export { getEventLeaderboard } from "./features/events/server";
|
|
|
1767
1769
|
export { getEventPollResults } from "./features/events/server";
|
|
1768
1770
|
export { getEventSpinResults } from "./features/events/server";
|
|
1769
1771
|
export { getUserSpinResultsForEvent } from "./features/events/server";
|
|
1770
|
-
export { getBugHunterLeaderboard } from "./features/tester/server";
|
|
1771
1772
|
export { getPublicEventById } from "./features/events/server";
|
|
1772
1773
|
export { listPublicEvents } from "./features/events/server";
|
|
1773
1774
|
export { getRelatedEvents } from "./features/events/server";
|
|
@@ -1792,7 +1793,6 @@ export type { TesterChecklistItemDocument } from "./features/tester/index";
|
|
|
1792
1793
|
export type { TesterChecklistResponseDocument } from "./features/tester/index";
|
|
1793
1794
|
export type { TesterAnswer } from "./features/tester/index";
|
|
1794
1795
|
export type { TesterFeedbackStatus } from "./features/tester/index";
|
|
1795
|
-
export type { BugHunterLeaderboardEntry } from "./features/tester/index";
|
|
1796
1796
|
export { FAQS_PUBLIC_FIELDS } from "./features/faq/index";
|
|
1797
1797
|
export { FAQSortDropdown } from "./features/faq/index";
|
|
1798
1798
|
export { FAQ_CATEGORY_LABELS } from "./features/faq/index";
|
|
@@ -2370,6 +2370,8 @@ export { checkEmiEligibility, computeEmiSchedule, computeBuyerEmiQuote } from ".
|
|
|
2370
2370
|
export type { BuyerEmiQuote } from "./_internal/shared/features/emi/schedule";
|
|
2371
2371
|
export { toBuyerFacingFees, toBuyerEmiSettings, } from "./_internal/shared/features/site-settings/fees";
|
|
2372
2372
|
export type { BuyerFacingFees, BuyerEmiSettings, } from "./_internal/shared/features/site-settings/fees";
|
|
2373
|
+
export { GSTIN_PATTERN, gstinCheckCharacter, isValidGstin, validateGstEnablement, canEnableGst, } from "./_internal/shared/features/site-settings/gst-registration";
|
|
2374
|
+
export type { GstEnablementInput, GstEnablementProblems, } from "./_internal/shared/features/site-settings/gst-registration";
|
|
2373
2375
|
export type { EmiSettings, EmiIneligibleReason, EmiEligibility, EmiInstallmentPlan, EmiScheduleResult, } from "./_internal/shared/features/emi/schedule";
|
|
2374
2376
|
export { isAdminUser, isSellerUser, isModeratorUser, isEmployeeUser, isBuyerUser, isEffectiveAdminUser, isTesterUser, canTestAdminSurfaces, isStrictSellerUser, isAccountDisabled, } from "./features/auth/role-predicates";
|
|
2375
2377
|
export { sanitizeProductForPublic, sanitizeProductsForPublic } from "./features/products/index";
|
|
@@ -3023,7 +3025,14 @@ export { resolveMediaUrl, resolveVideoUrl, FIREBASE_STORAGE_HOST, GCS_HOST, isSt
|
|
|
3023
3025
|
export { generateFAQId } from "./utils/id-generators";
|
|
3024
3026
|
export type { GenerateFAQIdInput } from "./utils/id-generators";
|
|
3025
3027
|
export { generateCroppedImageFilename } from "./utils/id-generators";
|
|
3026
|
-
export { PRODUCT_FEATURES_COLLECTION, PRODUCT_FEATURE_PREFIX, MAX_STORE_CUSTOM_FEATURES, MAX_FEATURES_PER_PRODUCT, PRODUCT_FEATURE_SIEVE_FIELDS, isFeatureIconPath, } from "./features/products/schemas/product-features";
|
|
3028
|
+
export { PRODUCT_FEATURES_COLLECTION, PRODUCT_FEATURE_PREFIX, MAX_STORE_CUSTOM_FEATURES, MAX_FEATURES_PER_PRODUCT, PRODUCT_FEATURE_SIEVE_FIELDS, FEATURE_GROUP_VALUES, FEATURE_GROUP_LABEL, isFeatureIconPath, } from "./features/products/schemas/product-features";
|
|
3029
|
+
export type { FeatureGroup } from "./features/products/schemas/product-features";
|
|
3030
|
+
export { TAX_CODES_COLLECTION, TAX_CODE_PREFIX, TAX_CODE_FIELDS, TAX_CODE_SIEVE_FIELDS, TAX_CODE_UPDATABLE_FIELDS, GST_RATE_VALUES, createTaxCodeId, isValidHsnCode, } from "./features/tax-codes/schemas/firestore";
|
|
3031
|
+
export type { TaxCodeDocument, TaxCodeCreateInput, TaxCodeUpdateInput, GstRate, HsnChapter, } from "./features/tax-codes/schemas/firestore";
|
|
3032
|
+
export { taxCodeFormSchema, GST_RATE_OPTIONS, HSN_CHAPTER_OPTIONS } from "./features/tax-codes/schemas/tax-code-form";
|
|
3033
|
+
export type { TaxCodeFormValues } from "./features/tax-codes/schemas/tax-code-form";
|
|
3034
|
+
export { taxCodeCreateSchema, taxCodeUpdateSchema, } from "./features/tax-codes/schemas/tax-codes.validators";
|
|
3035
|
+
export type { TaxCodeCreatePayload, TaxCodeUpdatePayload, } from "./features/tax-codes/schemas/tax-codes.validators";
|
|
3027
3036
|
export type { ProductFeatureDocument, ProductFeatureCreateInput, ProductFeatureUpdateInput, ProductFeatureScope, ProductFeatureCategory, ProductFeatureProductType, ProductFeatureIcon, } from "./features/products/schemas/product-features";
|
|
3028
3037
|
export { productFeatureAdminCreateSchema, productFeatureStoreCreateSchema, productFeatureUpdateSchema, PRODUCT_FEATURE_PRODUCT_TYPE_ENUM, PRODUCT_FEATURE_CATEGORY_ENUM, PRODUCT_FEATURE_SCOPE_ENUM, } from "./features/products/schemas/product-features.validators";
|
|
3029
3038
|
export type { ProductFeatureAdminCreatePayload, ProductFeatureStoreCreatePayload, ProductFeatureUpdatePayload, } from "./features/products/schemas/product-features.validators";
|
|
@@ -3053,6 +3062,7 @@ export { navItemFormSchema, navItemCreateSchema, navItemUpdateSchema, type NavIt
|
|
|
3053
3062
|
export { groupedListingFormSchema, groupedListingCreateSchema, groupedListingUpdateSchema, type GroupedListingFormValues, } from "./features/grouped/schemas/grouped-listing-form";
|
|
3054
3063
|
export { scammersSeedData } from "./seed/index";
|
|
3055
3064
|
export { productFeaturesSeedData } from "./seed/index";
|
|
3065
|
+
export { taxCodesSeedData } from "./seed/index";
|
|
3056
3066
|
export { SCAMMER_COLLECTION, SCAMMER_ID_PREFIX, SCAMMER_MATCH_FIELDS, SCAMMER_INDEXED_FIELDS, SCAMMER_FIELDS, SCAMMER_INCIDENTS_SUBCOLLECTION, SCAMMER_COMMENTS_SUBCOLLECTION, SCAMMER_CONTESTS_SUBCOLLECTION, MAX_COMMENT_BODY_LENGTH, MAX_PENDING_SCAMMER_REPORTS_PER_USER, ScammerStatusValues, ScamPlatformValues, SocialPlatformValues, ContestTypeValues, ContestStatusValues, SCAM_PLATFORM_LABELS, SOCIAL_PLATFORM_LABELS, SCAMMER_STATUS_LABELS, CONTEST_TYPE_LABELS, CONTEST_STATUS_LABELS, DEFAULT_SCAMMER_DATA, DEFAULT_SCAMMER_INCIDENT_DATA, DEFAULT_SCAMMER_COMMENT_DATA, DEFAULT_SCAMMER_CONTEST_DATA, } from "./features/scams/schemas/firestore";
|
|
3057
3067
|
export type { ScammerStatus, ScamPlatform, SocialPlatform, ContestType, ContestStatus, ScammerMatchField, ScammerMatchStrength, ScammerSocialMedia, ScammerDocument, ScammerIncidentDocument, ScammerCommentDocument, ScammerContestDocument, ScammerSuggestion, ScammerCreateInput, ScammerAdminUpdateInput, ScammerIncidentCreateInput, ScammerCommentCreateInput, ScammerContestCreateInput, } from "./features/scams/schemas/firestore";
|
|
3058
3068
|
export { SCAM_TYPES, SCAM_CATEGORIES, SCAM_TYPE_LABELS, SCAM_CATEGORY_LABELS, getScamType, getScamTypesByCategory, getCategoryForScamType, } from "./features/scams/constants/scam-types";
|
|
@@ -3073,6 +3083,10 @@ export { SellerProductShell } from "./features/seller/components/SellerProductSh
|
|
|
3073
3083
|
export type { SellerProductShellProps, SellerProductDraft, ProductListingMode } from "./features/seller/components/SellerProductShell";
|
|
3074
3084
|
export { CategoryInlineSelect } from "./features/seller/components/CategoryInlineSelect";
|
|
3075
3085
|
export type { CategoryInlineSelectProps } from "./features/seller/components/CategoryInlineSelect";
|
|
3086
|
+
export { ALERT_METRIC_VALUES, ALERT_METRICS, isAlertMetric, alertMetricsForScope, LOW_STOCK_THRESHOLD, } from "./features/store-extensions/constants/alert-metrics";
|
|
3087
|
+
export type { AlertMetric, AlertMetricDef, AlertMetricScope, AlertMetricUnit, } from "./features/store-extensions/constants/alert-metrics";
|
|
3088
|
+
export { CategoryTemplatePicker, variantForCondition } from "./features/categories/components/CategoryTemplatePicker";
|
|
3089
|
+
export type { CategoryTemplatePickerProps, CategoryTemplateApply } from "./features/categories/components/CategoryTemplatePicker";
|
|
3076
3090
|
export { BrandInlineSelect } from "./features/seller/components/BrandInlineSelect";
|
|
3077
3091
|
export type { BrandInlineSelectProps } from "./features/seller/components/BrandInlineSelect";
|
|
3078
3092
|
export { SublistingInlineSelect } from "./features/seller/components/SublistingInlineSelect";
|