@mohasinac/appkit 4.53.1 โ 4.54.0-next.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/.build-stamp.json +5 -5
- package/dist/_internal/client/theme/ThemeProvider.js +15 -1
- package/dist/_internal/server/features/auth/capabilities.js +7 -5
- package/dist/_internal/server/features/categories/price-guidance-resolve.d.ts +66 -0
- package/dist/_internal/server/features/categories/price-guidance-resolve.js +138 -0
- package/dist/_internal/server/features/checkout/supplier-identity.js +28 -6
- package/dist/_internal/server/features/price-index/market.d.ts +57 -0
- package/dist/_internal/server/features/price-index/market.js +120 -0
- package/dist/_internal/server/features/products/list-public.d.ts +12 -0
- package/dist/_internal/server/features/products/list-public.js +10 -1
- package/dist/_internal/server/features/products/listing-tab-counts.d.ts +25 -1
- package/dist/_internal/server/features/products/listing-tab-counts.js +184 -10
- package/dist/_internal/server/features/search/index-build/sources.js +43 -2
- package/dist/_internal/server/features/stores/tabs.d.ts +7 -2
- package/dist/_internal/server/features/stores/tabs.js +5 -3
- package/dist/_internal/server/jobs/core/jobRunners.js +0 -10
- package/dist/_internal/server/jobs/core/onOrderCreate.js +10 -104
- package/dist/_internal/shared/actions/action-registry.d.ts +1 -1
- package/dist/_internal/shared/actions/action-registry.js +128 -0
- package/dist/_internal/shared/features/categories/bundle-copy.d.ts +1 -1
- package/dist/_internal/shared/features/site-settings/supplier-of-record.d.ts +56 -0
- package/dist/_internal/shared/features/site-settings/supplier-of-record.js +57 -0
- package/dist/_internal/shared/listing-types/tiers.d.ts +94 -0
- package/dist/_internal/shared/listing-types/tiers.js +150 -0
- package/dist/_internal/shared/search/match.js +28 -2
- package/dist/cli/index.js +0 -2
- package/dist/client.d.ts +21 -2
- package/dist/client.js +23 -4
- package/dist/constants/api-endpoints.d.ts +28 -0
- package/dist/constants/api-endpoints.js +14 -0
- package/dist/features/account/components/UserOrdersView.js +26 -7
- package/dist/features/addresses/utils/postal-autofill.d.ts +39 -0
- package/dist/features/addresses/utils/postal-autofill.js +54 -0
- package/dist/features/admin/components/AdminStoreEditorView.js +73 -34
- package/dist/features/admin/components/OwnerQuickActions.d.ts +29 -0
- package/dist/features/admin/components/OwnerQuickActions.js +142 -0
- package/dist/features/admin/schemas/admin-editor-forms.d.ts +1 -1
- package/dist/features/admin/schemas/admin-editor-forms.js +4 -1
- package/dist/features/auctions/components/AuctionDetailPageView.js +8 -7
- package/dist/features/auctions/components/MarketplaceAuctionCard.d.ts +11 -1
- package/dist/features/auctions/components/MarketplaceAuctionCard.js +9 -2
- package/dist/features/auth/permissions/constants.d.ts +29 -2
- package/dist/features/auth/permissions/constants.js +68 -1
- package/dist/features/blog/components/BlogFeaturedCard.d.ts +11 -1
- package/dist/features/blog/components/BlogFeaturedCard.js +9 -2
- package/dist/features/cart/components/CartDrawer.js +3 -2
- package/dist/features/cart/components/CartGroupLineRow.js +2 -1
- package/dist/features/cart/hooks/useAddToCart.js +10 -5
- package/dist/features/cart/utils/pending-ops.d.ts +11 -1
- package/dist/features/cart/utils/pending-ops.js +14 -2
- package/dist/features/categories/api/[id]/price-guidance/route.js +1 -24
- package/dist/features/categories/components/BrandDetailPageView.js +15 -6
- package/dist/features/categories/components/BrandDetailTabs.d.ts +7 -1
- package/dist/features/categories/components/BrandDetailTabs.js +18 -3
- package/dist/features/categories/components/BundleCollage.js +3 -2
- package/dist/features/categories/components/BundleItemsPicker.js +3 -4
- package/dist/features/categories/components/CategoryDetailPageView.js +19 -8
- package/dist/features/categories/components/CategoryDetailTabs.d.ts +7 -1
- package/dist/features/categories/components/CategoryDetailTabs.js +29 -7
- package/dist/features/categories/components/CategoryGrid.d.ts +11 -1
- package/dist/features/categories/components/CategoryGrid.js +9 -2
- package/dist/features/checkout/actions/checkout-value-otp-actions.d.ts +10 -5
- package/dist/features/checkout/actions/checkout-value-otp-actions.js +2 -88
- package/dist/features/classified/components/ClassifiedDetailPageView.js +10 -1
- package/dist/features/digital-codes/components/DigitalCodeDetailPageView.js +10 -1
- package/dist/features/events/components/EventCard.d.ts +11 -1
- package/dist/features/events/components/EventCard.js +9 -2
- package/dist/features/layout/AppLayoutShell.js +2 -1
- package/dist/features/layout/BottomActions.d.ts +1 -0
- package/dist/features/layout/BottomActions.js +330 -0
- package/dist/features/layout/BottomChrome.d.ts +45 -0
- package/dist/features/layout/BottomChrome.js +5 -17
- package/dist/features/layout/SideActionDock.js +36 -13
- package/dist/features/layout/index.d.ts +2 -7
- package/dist/features/layout/index.js +7 -7
- package/dist/features/layout/useIsDesktop.d.ts +36 -0
- package/dist/features/layout/useIsDesktop.js +48 -0
- package/dist/features/live/components/LiveItemDetailPageView.js +10 -1
- package/dist/features/media/messages/en.json +67 -67
- package/dist/features/orders/components/YourPurchaseStrip.d.ts +24 -0
- package/dist/features/orders/components/YourPurchaseStrip.js +77 -0
- package/dist/features/orders/components/index.d.ts +2 -1
- package/dist/features/orders/components/index.js +1 -1
- package/dist/features/orders/utils/order-announcement-message.d.ts +18 -0
- package/dist/features/orders/utils/order-announcement-message.js +16 -0
- package/dist/features/orders/utils/payment-proof-message.d.ts +20 -0
- package/dist/features/orders/utils/payment-proof-message.js +17 -0
- package/dist/features/parts/schemas/firestore.d.ts +227 -0
- package/dist/features/parts/schemas/firestore.js +6 -6
- package/dist/features/pre-orders/components/MarketplacePreorderCard.d.ts +11 -1
- package/dist/features/pre-orders/components/MarketplacePreorderCard.js +10 -3
- package/dist/features/pre-orders/components/PreOrderDetailPageView.js +8 -7
- package/dist/features/price-index/components/PriceIndexToolView.d.ts +21 -0
- package/dist/features/price-index/components/PriceIndexToolView.js +230 -27
- package/dist/features/price-index/lookup-target.d.ts +48 -0
- package/dist/features/price-index/lookup-target.js +107 -0
- package/dist/features/products/api/[id]/route.js +8 -1
- package/dist/features/products/api/route.js +16 -4
- package/dist/features/products/components/AvailabilityScopeHint.d.ts +22 -0
- package/dist/features/products/components/AvailabilityScopeHint.js +27 -0
- package/dist/features/products/components/CompareOverlay.d.ts +2 -1
- package/dist/features/products/components/CompareOverlay.js +2 -1
- package/dist/features/products/components/GroupSettingsPanel.js +2 -1
- package/dist/features/products/components/InteractiveProductCard.d.ts +7 -1
- package/dist/features/products/components/InteractiveProductCard.js +16 -4
- package/dist/features/products/components/MarketplaceBundleCard.d.ts +11 -1
- package/dist/features/products/components/MarketplaceBundleCard.js +9 -2
- package/dist/features/products/components/MarketplacePrizeDrawCard.d.ts +11 -1
- package/dist/features/products/components/MarketplacePrizeDrawCard.js +9 -2
- package/dist/features/products/components/ProductDetailPageView.js +34 -4
- package/dist/features/products/components/ProductGrid.d.ts +14 -1
- package/dist/features/products/components/ProductGrid.js +22 -5
- package/dist/features/products/components/ProductsIndexListing.js +2 -2
- package/dist/features/products/components/SublistingCarouselSection.js +2 -1
- package/dist/features/products/repository/products.repository.d.ts +1 -0
- package/dist/features/products/repository/products.repository.js +5 -1
- package/dist/features/products/utils/group-member-image.d.ts +9 -2
- package/dist/features/products/utils/group-member-image.js +2 -1
- package/dist/features/reviews/api/[id]/route.js +83 -23
- package/dist/features/reviews/components/PurchaseReviewAffordance.d.ts +6 -0
- package/dist/features/reviews/components/PurchaseReviewAffordance.js +42 -0
- package/dist/features/reviews/components/ReviewFormDrawer.d.ts +34 -0
- package/dist/features/reviews/components/ReviewFormDrawer.js +127 -0
- package/dist/features/reviews/components/index.d.ts +4 -0
- package/dist/features/reviews/components/index.js +2 -0
- package/dist/features/seller/actions/seller-actions.d.ts +1 -1
- package/dist/features/seller/actions/seller-actions.js +49 -3
- package/dist/features/seller/components/SellerPayoutSettingsView.js +30 -2
- package/dist/features/seller/components/SellerProductShell.d.ts +17 -1
- package/dist/features/seller/components/SellerProductsView.js +3 -2
- package/dist/features/seller/hooks/useStoreListingEntitlements.d.ts +8 -0
- package/dist/features/seller/hooks/useStoreListingEntitlements.js +70 -0
- package/dist/features/stores/components/InteractiveStoreCard.d.ts +11 -1
- package/dist/features/stores/components/InteractiveStoreCard.js +9 -2
- package/dist/features/stores/components/StoreAuctionsListing.js +2 -1
- package/dist/features/stores/components/index.d.ts +0 -2
- package/dist/features/stores/components/index.js +0 -1
- package/dist/features/stores/schemas/index.d.ts +1 -1
- package/dist/features/stores/schemas/index.js +10 -1
- package/dist/features/tester/seed-data/authored/content-discovery__authenticity-checker.js +114 -2
- package/dist/features/tester/seed-data/tester-checklist-seed-data.js +415 -0
- package/dist/index.d.ts +8 -27
- package/dist/index.js +14 -35
- package/dist/next/routing/route-map.d.ts +2 -0
- package/dist/next/routing/route-map.js +9 -0
- package/dist/providers/shipping-shiprocket/index.d.ts +98 -0
- package/dist/providers/shipping-shiprocket/index.js +353 -0
- package/dist/schemas/registry.d.ts +2 -2
- package/dist/security/csp.d.ts +16 -1
- package/dist/security/csp.js +5 -3
- package/dist/seed/_helpers/category-forest.js +27 -0
- package/dist/seed/_helpers/category-parts-glossary-map.js +1816 -86
- package/dist/seed/_helpers/category-parts.d.ts +1 -1
- package/dist/seed/_helpers/category-parts.js +13412 -3020
- package/dist/seed/categories-seed-data.js +48 -6
- package/dist/seed/homepage-sections-seed-data.js +41 -28
- package/dist/seed/model-composition-seed-data.js +6 -8
- package/dist/seed/part-glossary/chunk0.d.ts +9 -0
- package/dist/seed/part-glossary/chunk0.js +35044 -0
- package/dist/seed/part-glossary/chunk1.d.ts +9 -0
- package/dist/seed/part-glossary/chunk1.js +39955 -0
- package/dist/seed/part-glossary/chunk2.d.ts +9 -0
- package/dist/seed/part-glossary/chunk2.js +50335 -0
- package/dist/seed/part-glossary/chunk3.d.ts +9 -0
- package/dist/seed/part-glossary/chunk3.js +52386 -0
- package/dist/seed/part-glossary/chunk4.d.ts +9 -0
- package/dist/seed/part-glossary/chunk4.js +50549 -0
- package/dist/seed/part-glossary-seed-data.d.ts +1 -1
- package/dist/seed/part-glossary-seed-data.js +23 -47483
- package/dist/seed/products-beyblade-x-seed-data.js +36 -1
- package/dist/server.d.ts +6 -8
- package/dist/server.js +16 -20
- package/dist/styles.css +516 -358
- package/dist/tailwind-utilities.css +1 -1
- package/dist/tokens/themes/index.d.ts +3 -1
- package/dist/tokens/themes/index.js +11 -1
- package/dist/tokens/themes/technical-dark.d.ts +30 -0
- package/dist/tokens/themes/technical-dark.js +103 -0
- package/dist/tokens/themes/technical-light.d.ts +22 -0
- package/dist/tokens/themes/technical-light.js +89 -0
- package/dist/tokens/tokens.css +155 -0
- package/dist/ui/components/GatedPrice.js +30 -3
- package/dist/ui/components/GatedPrice.style.css +22 -19
- package/dist/ui/components/QuickCreateModal.style.css +78 -78
- package/dist/ui/forms/FormShell.style.css +260 -260
- package/package.json +1 -1
- package/scripts/seed-cli.mjs +133 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.d.ts +0 -27
- package/dist/_internal/server/jobs/core/whatsappCatalogImport.js +0 -172
- package/dist/_internal/server/jobs/core/whatsappNotify.d.ts +0 -35
- package/dist/_internal/server/jobs/core/whatsappNotify.js +0 -140
- package/dist/features/admin/components/AdminWhatsAppGuideView.d.ts +0 -2
- package/dist/features/admin/components/AdminWhatsAppGuideView.js +0 -35
- package/dist/features/orders/components/MarketplaceOrderCard.d.ts +0 -36
- package/dist/features/orders/components/MarketplaceOrderCard.js +0 -57
- package/dist/features/stores/components/StoreWhatsAppGuideView.d.ts +0 -3
- package/dist/features/stores/components/StoreWhatsAppGuideView.js +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/send-status/route.js +0 -38
- package/dist/features/whatsapp-bot/api/webhook/route.d.ts +0 -12
- package/dist/features/whatsapp-bot/api/webhook/route.js +0 -43
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.d.ts +0 -6
- package/dist/features/whatsapp-bot/components/SellerWhatsAppSettingsView.js +0 -270
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.d.ts +0 -9
- package/dist/features/whatsapp-bot/components/WhatsAppChatButton.js +0 -7
- package/dist/features/whatsapp-bot/components/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/components/index.js +0 -2
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.d.ts +0 -14
- package/dist/features/whatsapp-bot/helpers/payment-proof-message.js +0 -17
- package/dist/features/whatsapp-bot/helpers/whatsapp.d.ts +0 -52
- package/dist/features/whatsapp-bot/helpers/whatsapp.js +0 -283
- package/dist/features/whatsapp-bot/index.d.ts +0 -3
- package/dist/features/whatsapp-bot/index.js +0 -3
- package/dist/features/whatsapp-bot/manifest.d.ts +0 -2
- package/dist/features/whatsapp-bot/manifest.js +0 -13
- package/dist/features/whatsapp-bot/messages/en.json +0 -7
- package/dist/features/whatsapp-bot/server.d.ts +0 -7
- package/dist/features/whatsapp-bot/server.js +0 -7
- package/dist/features/whatsapp-bot/types/index.d.ts +0 -126
- package/dist/features/whatsapp-bot/types/index.js +0 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* The line at which the layout stops being a phone.
|
|
5
|
+
*
|
|
6
|
+
* 64rem is Tailwind's `lg` โ deliberately the same breakpoint `BottomNavbar`
|
|
7
|
+
* disappears at, so every decision that depends on "is there a tab bar at the
|
|
8
|
+
* bottom of this screen" flips at one place.
|
|
9
|
+
*/
|
|
10
|
+
export const DESKTOP_QUERY = "(min-width: 64rem)";
|
|
11
|
+
/**
|
|
12
|
+
* `true` at `lg` and up.
|
|
13
|
+
*
|
|
14
|
+
* โโ ๐ WHY A HOOK AND NOT A `lg:` CLASS โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
15
|
+
*
|
|
16
|
+
* Three callers need the breakpoint as a VALUE, not as styling:
|
|
17
|
+
*
|
|
18
|
+
* - `BottomChrome` must know which CSS variable to publish โ a media query
|
|
19
|
+
* can move the box but cannot tell a `ResizeObserver` which end of the
|
|
20
|
+
* screen it landed at.
|
|
21
|
+
* - `SideActionDock` and `BottomActions` are the two halves of one control
|
|
22
|
+
* and must never both be mounted: two toolbars reading the same context,
|
|
23
|
+
* both `fixed`, both dispatching the same callbacks. Hiding one with
|
|
24
|
+
* `display:none` would still mount it, still run its observers, and still
|
|
25
|
+
* let a stray `:focus` land inside an invisible bar.
|
|
26
|
+
*
|
|
27
|
+
* And the class form is actively unsafe here. Both Tailwind configs set
|
|
28
|
+
* `important: true`, so a `lg:` override and its unprefixed base tie on
|
|
29
|
+
* specificity AND on `!important` โ a media query adds no specificity โ and
|
|
30
|
+
* the winner is decided by EMISSION ORDER in the built CSS, which is invisible
|
|
31
|
+
* from the call site. That is exactly how `BottomChrome` ended up anchored to
|
|
32
|
+
* both edges at once and published an 801px phantom bar (see its header).
|
|
33
|
+
*
|
|
34
|
+
* SSR renders the mobile branch, because that is the branch that is correct
|
|
35
|
+
* when nothing is known: a phone that briefly gets the dock has lost its only
|
|
36
|
+
* CTA, while a desktop that briefly gets the bar has a bar.
|
|
37
|
+
*/
|
|
38
|
+
export function useIsDesktop() {
|
|
39
|
+
const [isDesktop, setIsDesktop] = useState(false);
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const mq = window.matchMedia(DESKTOP_QUERY);
|
|
42
|
+
const sync = () => setIsDesktop(mq.matches);
|
|
43
|
+
sync();
|
|
44
|
+
mq.addEventListener("change", sync);
|
|
45
|
+
return () => mq.removeEventListener("change", sync);
|
|
46
|
+
}, []);
|
|
47
|
+
return isDesktop;
|
|
48
|
+
}
|
|
@@ -24,6 +24,7 @@ import { GroupedListingsCarousel } from "../../grouped/components/GroupedListing
|
|
|
24
24
|
import { getGroupsWithItemsForProduct } from "../../../_internal/server/features/grouped/data.js";
|
|
25
25
|
import { ReviewsListingPanel } from "../../reviews/components/ReviewsListingPanel.js";
|
|
26
26
|
import { ListingBottomActions } from "../../products/components/ListingBottomActions.js";
|
|
27
|
+
import { productImageUrls } from "../../products/schemas/firestore.js";
|
|
27
28
|
function toDescriptionHtml(raw) {
|
|
28
29
|
if (!raw)
|
|
29
30
|
return "";
|
|
@@ -44,7 +45,15 @@ export async function LiveItemDetailPageView({ slug, initialProduct, renderActio
|
|
|
44
45
|
const currency = p.currency || getDefaultCurrency();
|
|
45
46
|
const title = String(p.title ?? p.name ?? "Live Listing");
|
|
46
47
|
const price = typeof p.price === "number" ? p.price : null;
|
|
47
|
-
|
|
48
|
+
// `images` is `ProductImage[]` since A6 โ `productImageUrls` is the one
|
|
49
|
+
// normaliser (it also accepts the legacy `string[]`). Casting it to
|
|
50
|
+
// `string[]` handed the gallery objects and rendered a placeholder.
|
|
51
|
+
const galleryUrls = productImageUrls(p.images);
|
|
52
|
+
const images = galleryUrls.length > 0
|
|
53
|
+
? galleryUrls
|
|
54
|
+
: typeof p.mainImage === "string"
|
|
55
|
+
? [p.mainImage]
|
|
56
|
+
: [];
|
|
48
57
|
const productVideo = p.video;
|
|
49
58
|
const meta = product.liveItem;
|
|
50
59
|
const jurisdictions = meta?.jurisdictionAllowed ?? [];
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
{
|
|
2
|
-
"mediaEditor": {
|
|
3
|
-
"cropTitle": "Crop Image",
|
|
4
|
-
"cropInstruction": "Drag to reposition. Use the zoom slider or +/- keys to zoom.",
|
|
5
|
-
"cropPreviewAlt": "Preview",
|
|
6
|
-
"cropZoom": "Zoom",
|
|
7
|
-
"cropZoomIn": "Zoom in",
|
|
8
|
-
"cropZoomOut": "Zoom out",
|
|
9
|
-
"cropRotateLeft": "Rotate left 90ยฐ",
|
|
10
|
-
"cropRotateRight": "Rotate right 90ยฐ",
|
|
11
|
-
"cropFlipH": "Flip horizontally",
|
|
12
|
-
"cropFlipV": "Flip vertically",
|
|
13
|
-
"cropWarningTitle": "Low zoom",
|
|
14
|
-
"cropWarningMessage": "Zoom in for better quality.",
|
|
15
|
-
"cropPosition": "Position",
|
|
16
|
-
"cropReset": "Reset",
|
|
17
|
-
"cropSave": "Save Crop",
|
|
18
|
-
"cropCancel": "Cancel",
|
|
19
|
-
"trimTitle": "Trim Video",
|
|
20
|
-
"trimInstruction": "Set the start and end times, then click Trim.",
|
|
21
|
-
"trimStart": "Start",
|
|
22
|
-
"trimEnd": "End",
|
|
23
|
-
"trimDuration": "Duration: {duration}s",
|
|
24
|
-
"trimQuality": "Quality",
|
|
25
|
-
"trimQualityLow": "Low",
|
|
26
|
-
"trimQualityMedium": "Medium",
|
|
27
|
-
"trimQualityHigh": "High",
|
|
28
|
-
"trimSave": "Trim Video",
|
|
29
|
-
"trimSkip": "Skip",
|
|
30
|
-
"trimming": "Trimmingโฆ",
|
|
31
|
-
"thumbnailTitle": "Select Thumbnail",
|
|
32
|
-
"thumbnailInstruction": "Seek to the frame you want to use as the thumbnail.",
|
|
33
|
-
"thumbnailCapture": "Use This Frame",
|
|
34
|
-
"thumbnailSkip": "Skip",
|
|
35
|
-
"thumbnailCapturing": "Capturingโฆ",
|
|
36
|
-
"thumbnailUploading": "Uploadingโฆ",
|
|
37
|
-
"cropSuccess": "Image cropped",
|
|
38
|
-
"trimSuccess": "Video trimmed",
|
|
39
|
-
"thumbnailSuccess": "Thumbnail saved",
|
|
40
|
-
"cropError": "Failed to crop image",
|
|
41
|
-
"trimError": "Failed to trim video",
|
|
42
|
-
"thumbnailError": "Failed to capture thumbnail",
|
|
43
|
-
"editImage": "Edit / Crop",
|
|
44
|
-
"editVideo": "Trim / Thumbnail"
|
|
45
|
-
},
|
|
46
|
-
"camera": {
|
|
47
|
-
"takePhoto": "Take Photo",
|
|
48
|
-
"startRecording": "Start Recording",
|
|
49
|
-
"stopRecording": "Stop Recording",
|
|
50
|
-
"flipCamera": "Flip Camera",
|
|
51
|
-
"switchToCamera": "Use Camera",
|
|
52
|
-
"switchToUpload": "Upload File",
|
|
53
|
-
"cameraError": "Camera unavailable",
|
|
54
|
-
"permissionDenied": "Camera permission denied. Please allow access in your browser settings.",
|
|
55
|
-
"notSupported": "Camera is not supported on this device",
|
|
56
|
-
"starting": "Starting camera..."
|
|
57
|
-
},
|
|
58
|
-
"upload": {
|
|
59
|
-
"change": "Change",
|
|
60
|
-
"remove": "Remove",
|
|
61
|
-
"clickToUpload": "Click to upload",
|
|
62
|
-
"uploading": "Uploadingโฆ",
|
|
63
|
-
"uploadingProgress": "Uploading {progress}%โฆ",
|
|
64
|
-
"replaceFile": "Replace file",
|
|
65
|
-
"chooseFile": "Choose file to upload"
|
|
66
|
-
}
|
|
67
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"mediaEditor": {
|
|
3
|
+
"cropTitle": "Crop Image",
|
|
4
|
+
"cropInstruction": "Drag to reposition. Use the zoom slider or +/- keys to zoom.",
|
|
5
|
+
"cropPreviewAlt": "Preview",
|
|
6
|
+
"cropZoom": "Zoom",
|
|
7
|
+
"cropZoomIn": "Zoom in",
|
|
8
|
+
"cropZoomOut": "Zoom out",
|
|
9
|
+
"cropRotateLeft": "Rotate left 90ยฐ",
|
|
10
|
+
"cropRotateRight": "Rotate right 90ยฐ",
|
|
11
|
+
"cropFlipH": "Flip horizontally",
|
|
12
|
+
"cropFlipV": "Flip vertically",
|
|
13
|
+
"cropWarningTitle": "Low zoom",
|
|
14
|
+
"cropWarningMessage": "Zoom in for better quality.",
|
|
15
|
+
"cropPosition": "Position",
|
|
16
|
+
"cropReset": "Reset",
|
|
17
|
+
"cropSave": "Save Crop",
|
|
18
|
+
"cropCancel": "Cancel",
|
|
19
|
+
"trimTitle": "Trim Video",
|
|
20
|
+
"trimInstruction": "Set the start and end times, then click Trim.",
|
|
21
|
+
"trimStart": "Start",
|
|
22
|
+
"trimEnd": "End",
|
|
23
|
+
"trimDuration": "Duration: {duration}s",
|
|
24
|
+
"trimQuality": "Quality",
|
|
25
|
+
"trimQualityLow": "Low",
|
|
26
|
+
"trimQualityMedium": "Medium",
|
|
27
|
+
"trimQualityHigh": "High",
|
|
28
|
+
"trimSave": "Trim Video",
|
|
29
|
+
"trimSkip": "Skip",
|
|
30
|
+
"trimming": "Trimmingโฆ",
|
|
31
|
+
"thumbnailTitle": "Select Thumbnail",
|
|
32
|
+
"thumbnailInstruction": "Seek to the frame you want to use as the thumbnail.",
|
|
33
|
+
"thumbnailCapture": "Use This Frame",
|
|
34
|
+
"thumbnailSkip": "Skip",
|
|
35
|
+
"thumbnailCapturing": "Capturingโฆ",
|
|
36
|
+
"thumbnailUploading": "Uploadingโฆ",
|
|
37
|
+
"cropSuccess": "Image cropped",
|
|
38
|
+
"trimSuccess": "Video trimmed",
|
|
39
|
+
"thumbnailSuccess": "Thumbnail saved",
|
|
40
|
+
"cropError": "Failed to crop image",
|
|
41
|
+
"trimError": "Failed to trim video",
|
|
42
|
+
"thumbnailError": "Failed to capture thumbnail",
|
|
43
|
+
"editImage": "Edit / Crop",
|
|
44
|
+
"editVideo": "Trim / Thumbnail"
|
|
45
|
+
},
|
|
46
|
+
"camera": {
|
|
47
|
+
"takePhoto": "Take Photo",
|
|
48
|
+
"startRecording": "Start Recording",
|
|
49
|
+
"stopRecording": "Stop Recording",
|
|
50
|
+
"flipCamera": "Flip Camera",
|
|
51
|
+
"switchToCamera": "Use Camera",
|
|
52
|
+
"switchToUpload": "Upload File",
|
|
53
|
+
"cameraError": "Camera unavailable",
|
|
54
|
+
"permissionDenied": "Camera permission denied. Please allow access in your browser settings.",
|
|
55
|
+
"notSupported": "Camera is not supported on this device",
|
|
56
|
+
"starting": "Starting camera..."
|
|
57
|
+
},
|
|
58
|
+
"upload": {
|
|
59
|
+
"change": "Change",
|
|
60
|
+
"remove": "Remove",
|
|
61
|
+
"clickToUpload": "Click to upload",
|
|
62
|
+
"uploading": "Uploadingโฆ",
|
|
63
|
+
"uploadingProgress": "Uploading {progress}%โฆ",
|
|
64
|
+
"replaceFile": "Replace file",
|
|
65
|
+
"chooseFile": "Choose file to upload"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface PurchaseContext {
|
|
2
|
+
order: {
|
|
3
|
+
id: string;
|
|
4
|
+
shortRef: string;
|
|
5
|
+
status: string;
|
|
6
|
+
orderDate: string | null;
|
|
7
|
+
trackHref: string;
|
|
8
|
+
detailHref: string;
|
|
9
|
+
} | null;
|
|
10
|
+
review: {
|
|
11
|
+
id: string;
|
|
12
|
+
rating: number;
|
|
13
|
+
status: string;
|
|
14
|
+
} | null;
|
|
15
|
+
windowDays: number;
|
|
16
|
+
}
|
|
17
|
+
export interface YourPurchaseStripProps {
|
|
18
|
+
productId: string;
|
|
19
|
+
/** Opens the review editor. Omit to render the review half as a link only. */
|
|
20
|
+
onEditReview?: (reviewId: string) => void;
|
|
21
|
+
onWriteReview?: () => void;
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function YourPurchaseStrip({ productId, onEditReview, onWriteReview, className, }: YourPurchaseStripProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* "You ordered this โ track it" and "your review โ edit it", on a product page.
|
|
5
|
+
*
|
|
6
|
+
* โโ Why this exists โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
7
|
+
*
|
|
8
|
+
* A buyer looking at an item they already own had no link to their own order
|
|
9
|
+
* and no link to their own review. Both records exist; nothing connected them
|
|
10
|
+
* to the product page, so the route was: remember you bought it, go to
|
|
11
|
+
* /user/orders, page through, find it.
|
|
12
|
+
*
|
|
13
|
+
* โโ Three rules this component is built around โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
14
|
+
*
|
|
15
|
+
* ๐ NO MONEY. An order total here would need the guest-price gate, and the
|
|
16
|
+
* strip is signed-in-only by construction โ omitting the amount removes the
|
|
17
|
+
* question entirely rather than answering it carefully.
|
|
18
|
+
*
|
|
19
|
+
* ๐ SAY THE WINDOW. The lookup is bounded to 90 days (see the route: order
|
|
20
|
+
* `items[]` holds objects, so there is no index for "order containing this
|
|
21
|
+
* product"). When nothing is found the copy is "No order in the last 90 days",
|
|
22
|
+
* never "you haven't bought this". A filtered empty result reported as an
|
|
23
|
+
* absolute zero is a lie the buyer cannot check โ the same defect
|
|
24
|
+
* `UserOrdersView` carries a long comment about.
|
|
25
|
+
*
|
|
26
|
+
* ๐ RENDER NOTHING UNTIL RESOLVED. Public product pages are ISR and read no
|
|
27
|
+
* session, so `loading` starts true on every hard load even for signed-in
|
|
28
|
+
* users. Showing the signed-out state first would flash "no order" at someone
|
|
29
|
+
* who has one.
|
|
30
|
+
*
|
|
31
|
+
* @tag domain:orders
|
|
32
|
+
* @tag layer:components
|
|
33
|
+
* @tag access:client
|
|
34
|
+
*/
|
|
35
|
+
import { useApiQuery } from "../../../client/api/useApiQuery.js";
|
|
36
|
+
import { apiClient } from "../../../http/index.js";
|
|
37
|
+
import { useOptionalSession } from "../../../react/contexts/SessionContext.js";
|
|
38
|
+
import { ACTIONS } from "../../../_internal/shared/actions/action-registry.js";
|
|
39
|
+
import { ACCOUNT_ENDPOINTS } from "../../../constants/api-endpoints.js";
|
|
40
|
+
import { ROUTES } from "../../../next/routing/route-map.js";
|
|
41
|
+
import { Button, Div, Row, Span, Stack, Text, TextLink } from "../../../ui/index.js";
|
|
42
|
+
import { Icon } from "../../../ui/components/Icon.js";
|
|
43
|
+
import { formatDate } from "../../../utils/index.js";
|
|
44
|
+
export function YourPurchaseStrip({ productId, onEditReview, onWriteReview, className = "", }) {
|
|
45
|
+
const session = useOptionalSession();
|
|
46
|
+
const signedIn = Boolean(session?.user?.uid);
|
|
47
|
+
const query = useApiQuery({
|
|
48
|
+
queryKey: ["user", "purchases", productId],
|
|
49
|
+
queryFn: async () => {
|
|
50
|
+
const res = await apiClient.get(ACCOUNT_ENDPOINTS.PURCHASE_CONTEXT(productId));
|
|
51
|
+
return (res?.data ?? { order: null, review: null, windowDays: 90 });
|
|
52
|
+
},
|
|
53
|
+
// Only ask once we know there is somebody to ask about.
|
|
54
|
+
enabled: signedIn,
|
|
55
|
+
staleTime: 60000,
|
|
56
|
+
silentBackgroundFailures: true,
|
|
57
|
+
});
|
|
58
|
+
/*
|
|
59
|
+
* A guest, or auth not yet resolved, renders nothing at all. There is no
|
|
60
|
+
* useful signed-out state here: "sign in to see your order" is noise on a
|
|
61
|
+
* page whose primary job is selling the item.
|
|
62
|
+
*/
|
|
63
|
+
if (!session || session.loading || !signedIn)
|
|
64
|
+
return null;
|
|
65
|
+
if (query.isLoading || !query.data)
|
|
66
|
+
return null;
|
|
67
|
+
const { order, review, windowDays } = query.data;
|
|
68
|
+
// Nothing bought and nothing written โ stay out of the way entirely.
|
|
69
|
+
if (!order && !review)
|
|
70
|
+
return null;
|
|
71
|
+
return (_jsx(Div, { surface: "muted", rounded: "xl", padding: "md", border: "subtle", className: className, children: _jsxs(Stack, { gap: "sm", children: [order ? (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Icon, { name: "order", size: "sm", tone: "muted" }), _jsxs(Text, { size: "sm", children: ["You ordered this", order.orderDate ? ` on ${formatDate(order.orderDate)}` : "", " \u00B7", " ", _jsxs(Span, { className: "font-mono", children: ["#", order.shortRef] })] })] }), _jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Button, { asChild: true, variant: "outline", size: "sm", children: _jsx(TextLink, { href: order.trackHref, children: ACTIONS.USER["track-order"].label }) }), _jsx(Button, { asChild: true, variant: "ghost", size: "sm", children: _jsx(TextLink, { href: order.detailHref, children: ACTIONS.USER["view-order"].label }) })] })] })) : (
|
|
72
|
+
/*
|
|
73
|
+
* ๐ Bounded, and it says so. Not "you haven't bought this".
|
|
74
|
+
*/
|
|
75
|
+
_jsxs(Text, { size: "sm", color: "muted", children: ["No order for this item in the last ", windowDays, " days.", " ", _jsx(TextLink, { href: String(ROUTES.USER.ORDERS), children: "See all your orders" })] })), review ? (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsxs(Row, { align: "center", gap: "sm", children: [_jsx(Icon, { name: "review", size: "sm", tone: "muted", filled: true }), _jsxs(Text, { size: "sm", children: ["Your review: ", review.rating, "/5", review.status !== "approved" ? ` ยท ${review.status}` : ""] })] }), onEditReview && (_jsx(Button, { variant: "outline", size: "sm", onClick: () => onEditReview(review.id), children: ACTIONS.REVIEW.edit.label }))] })) : (order &&
|
|
76
|
+
onWriteReview && (_jsxs(Row, { align: "center", justify: "between", gap: "sm", wrap: true, children: [_jsx(Text, { size: "sm", color: "muted", children: "You have not reviewed this yet." }), _jsx(Button, { variant: "outline", size: "sm", onClick: onWriteReview, children: ACTIONS.REVIEW.write.label })] })))] }) }));
|
|
77
|
+
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { OrderCard, OrdersList } from "./OrdersList";
|
|
2
2
|
export { OrderAddonBadges, type OrderAddonBadgesOrder, type OrderAddonBadgesProps, } from "./OrderAddonBadges";
|
|
3
|
-
export { MarketplaceOrderCard, type MarketplaceOrderCardLabels, type MarketplaceOrderCardLinks, type MarketplaceOrderCardOrder, type MarketplaceOrderCardProps, } from "./MarketplaceOrderCard";
|
|
4
3
|
export { OrderFilters, ORDER_FILTER_KEYS, ORDER_ADMIN_SORT_OPTIONS, ORDER_SELLER_SORT_OPTIONS, ORDER_USER_SORT_OPTIONS, getOrderFilterKeys, getOrderSortOptions, } from "./OrderFilters";
|
|
5
4
|
export type { OrderFiltersProps, OrderFilterVariant } from "./OrderFilters";
|
|
6
5
|
export { OrderSiblingPayments } from "./OrderSiblingPayments";
|
|
@@ -13,3 +12,5 @@ export { RefundHistoryTable } from "./RefundHistoryTable";
|
|
|
13
12
|
export type { RefundHistoryTableProps } from "./RefundHistoryTable";
|
|
14
13
|
export { RefundRequestView } from "./RefundRequestView";
|
|
15
14
|
export type { RefundRequestViewProps } from "./RefundRequestView";
|
|
15
|
+
export { YourPurchaseStrip } from "./YourPurchaseStrip";
|
|
16
|
+
export type { YourPurchaseStripProps, PurchaseContext } from "./YourPurchaseStrip";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export { OrderCard, OrdersList } from "./OrdersList.js";
|
|
2
2
|
export { OrderAddonBadges, } from "./OrderAddonBadges.js";
|
|
3
|
-
export { MarketplaceOrderCard, } from "./MarketplaceOrderCard.js";
|
|
4
3
|
export { OrderFilters, ORDER_FILTER_KEYS, ORDER_ADMIN_SORT_OPTIONS, ORDER_SELLER_SORT_OPTIONS, ORDER_USER_SORT_OPTIONS, getOrderFilterKeys, getOrderSortOptions, } from "./OrderFilters.js";
|
|
5
4
|
export { OrderSiblingPayments } from "./OrderSiblingPayments.js";
|
|
6
5
|
export { OrderPaymentSummary } from "./OrderPaymentSummary.js";
|
|
7
6
|
export { OrderStatusTimeline } from "./OrderStatusTimeline.js";
|
|
8
7
|
export { RefundHistoryTable } from "./RefundHistoryTable.js";
|
|
9
8
|
export { RefundRequestView } from "./RefundRequestView.js";
|
|
9
|
+
export { YourPurchaseStrip } from "./YourPurchaseStrip.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface PurchaseAnnouncementInput {
|
|
2
|
+
buyerName: string;
|
|
3
|
+
firstItemName: string;
|
|
4
|
+
/** 0 if only one item in the order */
|
|
5
|
+
additionalItemCount: number;
|
|
6
|
+
/** Total order amount in decimal rupees */
|
|
7
|
+
totalAmount: number;
|
|
8
|
+
orderId: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Plain-text body for the "New order placed" staff notification row.
|
|
12
|
+
*
|
|
13
|
+
* Originally built for the WhatsApp purchase announcement. That integration
|
|
14
|
+
* was removed 2026-10-20, but the builder survives because its output is now
|
|
15
|
+
* the `adminNotifications` body the admin inbox renders and the daily digest
|
|
16
|
+
* counts โ a durable record rather than a per-admin blast.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildPurchaseAnnouncementMessage(input: PurchaseAnnouncementInput): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-text body for the "New order placed" staff notification row.
|
|
3
|
+
*
|
|
4
|
+
* Originally built for the WhatsApp purchase announcement. That integration
|
|
5
|
+
* was removed 2026-10-20, but the builder survives because its output is now
|
|
6
|
+
* the `adminNotifications` body the admin inbox renders and the daily digest
|
|
7
|
+
* counts โ a durable record rather than a per-admin blast.
|
|
8
|
+
*/
|
|
9
|
+
export function buildPurchaseAnnouncementMessage(input) {
|
|
10
|
+
const { buyerName, firstItemName, additionalItemCount, totalAmount, orderId } = input;
|
|
11
|
+
const extra = additionalItemCount > 0
|
|
12
|
+
? ` + ${additionalItemCount} more item${additionalItemCount > 1 ? "s" : ""}`
|
|
13
|
+
: "";
|
|
14
|
+
const amount = totalAmount.toLocaleString("en-IN");
|
|
15
|
+
return `๐๏ธ New order! ${buyerName} purchased ${firstItemName}${extra} for โน${amount}. Order #${orderId}`;
|
|
16
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface PaymentProofReviewMessageInput {
|
|
2
|
+
orderId: string;
|
|
3
|
+
buyerName: string;
|
|
4
|
+
productTitle: string;
|
|
5
|
+
totalAmount: number;
|
|
6
|
+
reviewUrl: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Tier PP โ message body for the buyer/seller "share for review" `wa.me`
|
|
10
|
+
* link on the order payment page.
|
|
11
|
+
*
|
|
12
|
+
* Pure string builder with no crypto and no network, so it is safe to export
|
|
13
|
+
* from the client-safe barrel. It used to live beside the WhatsApp Cloud API
|
|
14
|
+
* senders in `features/whatsapp-bot/`, isolated into its own file precisely
|
|
15
|
+
* because those siblings carried a top-level `import { createHmac } from
|
|
16
|
+
* "crypto"`. The Cloud API integration was removed 2026-10-20; this builder
|
|
17
|
+
* survived because it feeds an ordinary `wa.me` deep link, which needs no
|
|
18
|
+
* token, no registered number and no Meta billing relationship.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildPaymentProofReviewMessage(input: PaymentProofReviewMessageInput): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tier PP โ message body for the buyer/seller "share for review" `wa.me`
|
|
3
|
+
* link on the order payment page.
|
|
4
|
+
*
|
|
5
|
+
* Pure string builder with no crypto and no network, so it is safe to export
|
|
6
|
+
* from the client-safe barrel. It used to live beside the WhatsApp Cloud API
|
|
7
|
+
* senders in `features/whatsapp-bot/`, isolated into its own file precisely
|
|
8
|
+
* because those siblings carried a top-level `import { createHmac } from
|
|
9
|
+
* "crypto"`. The Cloud API integration was removed 2026-10-20; this builder
|
|
10
|
+
* survived because it feeds an ordinary `wa.me` deep link, which needs no
|
|
11
|
+
* token, no registered number and no Meta billing relationship.
|
|
12
|
+
*/
|
|
13
|
+
export function buildPaymentProofReviewMessage(input) {
|
|
14
|
+
const { orderId, buyerName, productTitle, totalAmount, reviewUrl } = input;
|
|
15
|
+
const amount = totalAmount.toLocaleString("en-IN");
|
|
16
|
+
return `๐ณ Payment proof submitted! ${buyerName} uploaded proof for "${productTitle}" (โน${amount}). Order #${orderId}. Please review within 2 hours or it auto-confirms: ${reviewUrl}`;
|
|
17
|
+
}
|