@libreapps/commerce 7.5.1
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/.turbo/turbo-build.log +4 -0
- package/CHANGELOG.md +13 -0
- package/LICENSE.md +21 -0
- package/components/Icons.tsx +35 -0
- package/components/add-to-cart-widget.tsx +183 -0
- package/components/buy/buy-card.tsx +259 -0
- package/components/buy/carousel-buy-card.tsx +242 -0
- package/components/buy/multi-family/all-variants-carousel.tsx +261 -0
- package/components/buy/multi-family/family-carousel/index.tsx +77 -0
- package/components/buy/multi-family/family-carousel/slide.tsx +83 -0
- package/components/buy/multi-family/family-carousel/state.ts +87 -0
- package/components/buy/multi-family/index.ts +2 -0
- package/components/buy/single-family-selector.tsx +90 -0
- package/components/buy/title-and-byline.tsx +25 -0
- package/components/cart/cart-panel/cart-line-item.tsx +76 -0
- package/components/cart/cart-panel/index.tsx +154 -0
- package/components/cart/cart-panel/promo-code.tsx +109 -0
- package/components/cart/cart-panel/total-area.tsx +60 -0
- package/components/checkout/payment-step-form/card-icon-row.tsx +26 -0
- package/components/checkout/payment-step-form/card-icons/amex.tsx +32 -0
- package/components/checkout/payment-step-form/card-icons/diners-club.tsx +13 -0
- package/components/checkout/payment-step-form/card-icons/discover.tsx +25 -0
- package/components/checkout/payment-step-form/card-icons/jcb.tsx +26 -0
- package/components/checkout/payment-step-form/card-icons/mastercard.tsx +27 -0
- package/components/checkout/payment-step-form/card-icons/visa.tsx +25 -0
- package/components/checkout/payment-step-form/cc-button.tsx +17 -0
- package/components/checkout/payment-step-form/contact-form.tsx +50 -0
- package/components/checkout/payment-step-form/crypto-icons/btc.tsx +11 -0
- package/components/checkout/payment-step-form/crypto-icons/eth.tsx +20 -0
- package/components/checkout/payment-step-form/crypto-icons/usdt.tsx +13 -0
- package/components/checkout/payment-step-form/index.tsx +122 -0
- package/components/checkout/payment-step-form/methods/bank-transfer.tsx +79 -0
- package/components/checkout/payment-step-form/methods/card.tsx +232 -0
- package/components/checkout/payment-step-form/methods/crypto.tsx +227 -0
- package/components/checkout/payment-step-form/methods/index.ts +23 -0
- package/components/checkout/shipping-step-form.tsx +175 -0
- package/components/index.ts +11 -0
- package/components/item/product-card.tsx +48 -0
- package/components/item-selector/button.tsx +188 -0
- package/components/item-selector/carousel/index.tsx +197 -0
- package/components/item-selector/carousel/slider.tsx +40 -0
- package/components/item-selector/index.ts +5 -0
- package/components/item-selector/quantity-indicator.tsx +48 -0
- package/components/node-tabs/index.tsx +91 -0
- package/components/node-tabs/node-image.tsx +31 -0
- package/dist/components/Icons.d.ts +18 -0
- package/dist/components/Icons.js +19 -0
- package/dist/components/Icons.js.map +1 -0
- package/dist/components/add-to-cart-widget.d.ts +11 -0
- package/dist/components/add-to-cart-widget.js +85 -0
- package/dist/components/add-to-cart-widget.js.map +1 -0
- package/dist/components/buy/buy-card.d.ts +30 -0
- package/dist/components/buy/buy-card.js +109 -0
- package/dist/components/buy/buy-card.js.map +1 -0
- package/dist/components/buy/carousel-buy-card.d.ts +12 -0
- package/dist/components/buy/carousel-buy-card.js +94 -0
- package/dist/components/buy/carousel-buy-card.js.map +1 -0
- package/dist/components/buy/multi-family/all-variants-carousel.d.ts +4 -0
- package/dist/components/buy/multi-family/all-variants-carousel.js +115 -0
- package/dist/components/buy/multi-family/all-variants-carousel.js.map +1 -0
- package/dist/components/buy/multi-family/family-carousel/index.d.ts +4 -0
- package/dist/components/buy/multi-family/family-carousel/index.js +27 -0
- package/dist/components/buy/multi-family/family-carousel/index.js.map +1 -0
- package/dist/components/buy/multi-family/family-carousel/slide.d.ts +11 -0
- package/dist/components/buy/multi-family/family-carousel/slide.js +35 -0
- package/dist/components/buy/multi-family/family-carousel/slide.js.map +1 -0
- package/dist/components/buy/multi-family/family-carousel/state.d.ts +20 -0
- package/dist/components/buy/multi-family/family-carousel/state.js +59 -0
- package/dist/components/buy/multi-family/family-carousel/state.js.map +1 -0
- package/dist/components/buy/multi-family/index.d.ts +2 -0
- package/dist/components/buy/multi-family/index.js +3 -0
- package/dist/components/buy/multi-family/index.js.map +1 -0
- package/dist/components/buy/single-family-selector.d.ts +15 -0
- package/dist/components/buy/single-family-selector.js +28 -0
- package/dist/components/buy/single-family-selector.js.map +1 -0
- package/dist/components/buy/title-and-byline.d.ts +8 -0
- package/dist/components/buy/title-and-byline.js +7 -0
- package/dist/components/buy/title-and-byline.js.map +1 -0
- package/dist/components/cart/cart-panel/cart-line-item.d.ts +11 -0
- package/dist/components/cart/cart-panel/cart-line-item.js +25 -0
- package/dist/components/cart/cart-panel/cart-line-item.js.map +1 -0
- package/dist/components/cart/cart-panel/index.d.ts +19 -0
- package/dist/components/cart/cart-panel/index.js +65 -0
- package/dist/components/cart/cart-panel/index.js.map +1 -0
- package/dist/components/cart/cart-panel/promo-code.d.ts +4 -0
- package/dist/components/cart/cart-panel/promo-code.js +62 -0
- package/dist/components/cart/cart-panel/promo-code.js.map +1 -0
- package/dist/components/cart/cart-panel/total-area.d.ts +7 -0
- package/dist/components/cart/cart-panel/total-area.js +14 -0
- package/dist/components/cart/cart-panel/total-area.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icon-row.d.ts +2 -0
- package/dist/components/checkout/payment-step-form/card-icon-row.js +14 -0
- package/dist/components/checkout/payment-step-form/card-icon-row.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/amex.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/amex.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/amex.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/diners-club.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/discover.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/discover.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/discover.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/jcb.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/jcb.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/jcb.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/mastercard.js.map +1 -0
- package/dist/components/checkout/payment-step-form/card-icons/visa.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/card-icons/visa.js +6 -0
- package/dist/components/checkout/payment-step-form/card-icons/visa.js.map +1 -0
- package/dist/components/checkout/payment-step-form/cc-button.d.ts +3 -0
- package/dist/components/checkout/payment-step-form/cc-button.js +6 -0
- package/dist/components/checkout/payment-step-form/cc-button.js.map +1 -0
- package/dist/components/checkout/payment-step-form/contact-form.d.ts +5 -0
- package/dist/components/checkout/payment-step-form/contact-form.js +6 -0
- package/dist/components/checkout/payment-step-form/contact-form.js.map +1 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.js +6 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/btc.js.map +1 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.js +6 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/eth.js.map +1 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js +6 -0
- package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js.map +1 -0
- package/dist/components/checkout/payment-step-form/index.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/index.js +77 -0
- package/dist/components/checkout/payment-step-form/index.js.map +1 -0
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.js +24 -0
- package/dist/components/checkout/payment-step-form/methods/bank-transfer.js.map +1 -0
- package/dist/components/checkout/payment-step-form/methods/card.d.ts +4 -0
- package/dist/components/checkout/payment-step-form/methods/card.js +160 -0
- package/dist/components/checkout/payment-step-form/methods/card.js.map +1 -0
- package/dist/components/checkout/payment-step-form/methods/crypto.d.ts +9 -0
- package/dist/components/checkout/payment-step-form/methods/crypto.js +137 -0
- package/dist/components/checkout/payment-step-form/methods/crypto.js.map +1 -0
- package/dist/components/checkout/payment-step-form/methods/index.d.ts +6 -0
- package/dist/components/checkout/payment-step-form/methods/index.js +21 -0
- package/dist/components/checkout/payment-step-form/methods/index.js.map +1 -0
- package/dist/components/checkout/shipping-step-form.d.ts +3 -0
- package/dist/components/checkout/shipping-step-form.js +53 -0
- package/dist/components/checkout/shipping-step-form.js.map +1 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.js +9 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/item/product-card.d.ts +7 -0
- package/dist/components/item/product-card.js +9 -0
- package/dist/components/item/product-card.js.map +1 -0
- package/dist/components/item-selector/button.d.ts +4 -0
- package/dist/components/item-selector/button.js +47 -0
- package/dist/components/item-selector/button.js.map +1 -0
- package/dist/components/item-selector/carousel/index.d.ts +12 -0
- package/dist/components/item-selector/carousel/index.js +74 -0
- package/dist/components/item-selector/carousel/index.js.map +1 -0
- package/dist/components/item-selector/carousel/slider.d.ts +8 -0
- package/dist/components/item-selector/carousel/slider.js +12 -0
- package/dist/components/item-selector/carousel/slider.js.map +1 -0
- package/dist/components/item-selector/index.d.ts +2 -0
- package/dist/components/item-selector/index.js +3 -0
- package/dist/components/item-selector/index.js.map +1 -0
- package/dist/components/item-selector/quantity-indicator.d.ts +9 -0
- package/dist/components/item-selector/quantity-indicator.js +16 -0
- package/dist/components/item-selector/quantity-indicator.js.map +1 -0
- package/dist/components/node-tabs/index.d.ts +14 -0
- package/dist/components/node-tabs/index.js +42 -0
- package/dist/components/node-tabs/index.js.map +1 -0
- package/dist/components/node-tabs/node-image.d.ts +6 -0
- package/dist/components/node-tabs/node-image.js +13 -0
- package/dist/components/node-tabs/node-image.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/service/context.d.ts +8 -0
- package/dist/service/context.js +19 -0
- package/dist/service/context.js.map +1 -0
- package/dist/service/debug.d.ts +10 -0
- package/dist/service/debug.js +30 -0
- package/dist/service/debug.js.map +1 -0
- package/dist/service/impls/standalone/actual-line-item.d.ts +40 -0
- package/dist/service/impls/standalone/actual-line-item.js +84 -0
- package/dist/service/impls/standalone/actual-line-item.js.map +1 -0
- package/dist/service/impls/standalone/get-instance.d.ts +2 -0
- package/dist/service/impls/standalone/get-instance.js +39 -0
- package/dist/service/impls/standalone/get-instance.js.map +1 -0
- package/dist/service/impls/standalone/index.d.ts +67 -0
- package/dist/service/impls/standalone/index.js +416 -0
- package/dist/service/impls/standalone/index.js.map +1 -0
- package/dist/service/impls/standalone/order/firebase.d.ts +2 -0
- package/dist/service/impls/standalone/order/firebase.js +13 -0
- package/dist/service/impls/standalone/order/firebase.js.map +1 -0
- package/dist/service/impls/standalone/order/index.d.ts +24 -0
- package/dist/service/impls/standalone/order/index.js +61 -0
- package/dist/service/impls/standalone/order/index.js.map +1 -0
- package/dist/service/impls/standalone/persistence.d.ts +4 -0
- package/dist/service/impls/standalone/persistence.js +22 -0
- package/dist/service/impls/standalone/persistence.js.map +1 -0
- package/dist/service/path-utils.d.ts +7 -0
- package/dist/service/path-utils.js +16 -0
- package/dist/service/path-utils.js.map +1 -0
- package/dist/service/sep.d.ts +6 -0
- package/dist/service/sep.js +6 -0
- package/dist/service/sep.js.map +1 -0
- package/dist/types/category-node.d.ts +36 -0
- package/dist/types/category-node.js +2 -0
- package/dist/types/category-node.js.map +1 -0
- package/dist/types/checkout.d.ts +33 -0
- package/dist/types/checkout.js +2 -0
- package/dist/types/checkout.js.map +1 -0
- package/dist/types/commerce-config.d.ts +11 -0
- package/dist/types/commerce-config.js +2 -0
- package/dist/types/commerce-config.js.map +1 -0
- package/dist/types/commerce-service.d.ts +109 -0
- package/dist/types/commerce-service.js +2 -0
- package/dist/types/commerce-service.js.map +1 -0
- package/dist/types/family.d.ts +16 -0
- package/dist/types/family.js +2 -0
- package/dist/types/family.js.map +1 -0
- package/dist/types/index.d.ts +13 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/item-selector.d.ts +72 -0
- package/dist/types/item-selector.js +2 -0
- package/dist/types/item-selector.js.map +1 -0
- package/dist/types/line-item.d.ts +14 -0
- package/dist/types/line-item.js +2 -0
- package/dist/types/line-item.js.map +1 -0
- package/dist/types/multi-family-selector-props.d.ts +16 -0
- package/dist/types/multi-family-selector-props.js +2 -0
- package/dist/types/multi-family-selector-props.js.map +1 -0
- package/dist/types/product.d.ts +15 -0
- package/dist/types/product.js +2 -0
- package/dist/types/product.js.map +1 -0
- package/dist/types/promo.d.ts +7 -0
- package/dist/types/promo.js +2 -0
- package/dist/types/promo.js.map +1 -0
- package/dist/types/selection-ui-specifier.d.ts +40 -0
- package/dist/types/selection-ui-specifier.js +2 -0
- package/dist/types/selection-ui-specifier.js.map +1 -0
- package/dist/types/string-mutator.d.ts +9 -0
- package/dist/types/string-mutator.js +2 -0
- package/dist/types/string-mutator.js.map +1 -0
- package/dist/types/token-separators.d.ts +6 -0
- package/dist/types/token-separators.js +2 -0
- package/dist/types/token-separators.js.map +1 -0
- package/dist/util/analytics.d.ts +9 -0
- package/dist/util/analytics.js +10 -0
- package/dist/util/analytics.js.map +1 -0
- package/dist/util/countries.d.ts +7 -0
- package/dist/util/countries.js +197 -0
- package/dist/util/countries.js.map +1 -0
- package/dist/util/error.d.ts +1 -0
- package/dist/util/error.js +22 -0
- package/dist/util/error.js.map +1 -0
- package/dist/util/index.d.ts +15 -0
- package/dist/util/index.js +54 -0
- package/dist/util/index.js.map +1 -0
- package/dist/util/item-selector-options-accessor.d.ts +3 -0
- package/dist/util/item-selector-options-accessor.js +27 -0
- package/dist/util/item-selector-options-accessor.js.map +1 -0
- package/dist/util/line-item-ref.d.ts +8 -0
- package/dist/util/line-item-ref.js +15 -0
- package/dist/util/line-item-ref.js.map +1 -0
- package/dist/util/multi-family-selector-options-accessor.d.ts +3 -0
- package/dist/util/multi-family-selector-options-accessor.js +11 -0
- package/dist/util/multi-family-selector-options-accessor.js.map +1 -0
- package/dist/util/obs-string-mutator.d.ts +8 -0
- package/dist/util/obs-string-mutator.js +15 -0
- package/dist/util/obs-string-mutator.js.map +1 -0
- package/dist/util/product-media-accessor.d.ts +29 -0
- package/dist/util/product-media-accessor.js +22 -0
- package/dist/util/product-media-accessor.js.map +1 -0
- package/dist/util/promo-codes.d.ts +3 -0
- package/dist/util/promo-codes.js +100 -0
- package/dist/util/promo-codes.js.map +1 -0
- package/dist/util/selection-ui-specifiers.d.ts +3 -0
- package/dist/util/selection-ui-specifiers.js +24 -0
- package/dist/util/selection-ui-specifiers.js.map +1 -0
- package/dist/util/square-payment.d.ts +7 -0
- package/dist/util/square-payment.js +37 -0
- package/dist/util/square-payment.js.map +1 -0
- package/dist/util/use-sync-sku-param-w-current-item.d.ts +2 -0
- package/dist/util/use-sync-sku-param-w-current-item.js +61 -0
- package/dist/util/use-sync-sku-param-w-current-item.js.map +1 -0
- package/index.ts +13 -0
- package/libreapps-ui.d.ts +108 -0
- package/package.json +67 -0
- package/service/context.tsx +45 -0
- package/service/debug.ts +41 -0
- package/service/impls/standalone/actual-line-item.ts +136 -0
- package/service/impls/standalone/get-instance.ts +64 -0
- package/service/impls/standalone/index.ts +579 -0
- package/service/impls/standalone/order/firebase.ts +14 -0
- package/service/impls/standalone/order/index.ts +129 -0
- package/service/impls/standalone/persistence.ts +33 -0
- package/service/path-utils.ts +26 -0
- package/service/sep.ts +7 -0
- package/tsconfig.json +17 -0
- package/types/README.md +2 -0
- package/types/category-node.ts +50 -0
- package/types/checkout.ts +47 -0
- package/types/commerce-config.ts +13 -0
- package/types/commerce-service.ts +128 -0
- package/types/family.ts +26 -0
- package/types/index.ts +15 -0
- package/types/item-selector.ts +97 -0
- package/types/line-item.ts +29 -0
- package/types/multi-family-selector-props.ts +20 -0
- package/types/product.ts +21 -0
- package/types/promo.ts +10 -0
- package/types/selection-ui-specifier.ts +52 -0
- package/types/string-mutator.ts +14 -0
- package/types/token-separators.ts +7 -0
- package/util/analytics.ts +21 -0
- package/util/countries.ts +196 -0
- package/util/error.ts +34 -0
- package/util/index.ts +71 -0
- package/util/item-selector-options-accessor.ts +35 -0
- package/util/line-item-ref.ts +23 -0
- package/util/multi-family-selector-options-accessor.ts +15 -0
- package/util/obs-string-mutator.ts +22 -0
- package/util/product-media-accessor.ts +58 -0
- package/util/promo-codes.ts +106 -0
- package/util/selection-ui-specifiers.ts +30 -0
- package/util/square-payment.ts +50 -0
- package/util/use-sync-sku-param-w-current-item.ts +88 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { enableStaticRendering } from 'mobx-react-lite'
|
|
2
|
+
|
|
3
|
+
import type { CommerceService, CommerceConfig } from '../../../types'
|
|
4
|
+
import { StandaloneService } from './index'
|
|
5
|
+
import { initSelectionUI } from '../../../util'
|
|
6
|
+
|
|
7
|
+
import { readSnapshot, writeSnapshotsOnChange } from './persistence'
|
|
8
|
+
|
|
9
|
+
enableStaticRendering(typeof window === "undefined")
|
|
10
|
+
|
|
11
|
+
const _LOG = false
|
|
12
|
+
const _log = (s: string) => {
|
|
13
|
+
if (!_LOG) return;
|
|
14
|
+
const d = new Date()
|
|
15
|
+
console.log(`TIMESTAMPED: ${d.getUTCMinutes()}:${d.getUTCSeconds()}:${d.getUTCMilliseconds()}`)
|
|
16
|
+
console.log(s)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// https://dev.to/ivandotv/mobx-server-side-rendering-with-next-js-4m18
|
|
20
|
+
|
|
21
|
+
let instance: StandaloneService | undefined = undefined
|
|
22
|
+
|
|
23
|
+
export const getInstance = ({
|
|
24
|
+
families,
|
|
25
|
+
rootNode,
|
|
26
|
+
options,
|
|
27
|
+
uiSpecifiers
|
|
28
|
+
}: CommerceConfig) : CommerceService => {
|
|
29
|
+
|
|
30
|
+
if (!options) {
|
|
31
|
+
throw new Error('cmmc getInstance(): Standalone Commerce Service requires config options!')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (typeof window === "undefined") {
|
|
35
|
+
if (uiSpecifiers) {
|
|
36
|
+
initSelectionUI(uiSpecifiers)
|
|
37
|
+
}
|
|
38
|
+
_log("NEW INSTANCE: SERVER") //////////
|
|
39
|
+
return new StandaloneService(
|
|
40
|
+
families,
|
|
41
|
+
rootNode,
|
|
42
|
+
options
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Client side, create the store only once in the client
|
|
47
|
+
if (!instance) {
|
|
48
|
+
if (uiSpecifiers) {
|
|
49
|
+
initSelectionUI(uiSpecifiers)
|
|
50
|
+
}
|
|
51
|
+
_log("NEW INSTANCE: CLIENT") ///////////
|
|
52
|
+
const snapShot = readSnapshot(options.localStorageKey)
|
|
53
|
+
instance = new StandaloneService(
|
|
54
|
+
families,
|
|
55
|
+
rootNode,
|
|
56
|
+
options,
|
|
57
|
+
snapShot
|
|
58
|
+
)
|
|
59
|
+
writeSnapshotsOnChange(instance, options.localStorageKey)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return instance
|
|
63
|
+
}
|
|
64
|
+
|
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
makeObservable,
|
|
4
|
+
observable,
|
|
5
|
+
runInAction,
|
|
6
|
+
action,
|
|
7
|
+
toJS
|
|
8
|
+
} from 'mobx'
|
|
9
|
+
|
|
10
|
+
import { computedFn } from 'mobx-utils'
|
|
11
|
+
|
|
12
|
+
import type {
|
|
13
|
+
CommerceService,
|
|
14
|
+
Family,
|
|
15
|
+
LineItem,
|
|
16
|
+
SelectedPaths,
|
|
17
|
+
CategoryNode,
|
|
18
|
+
CategoryNodeRole,
|
|
19
|
+
Promo
|
|
20
|
+
} from '../../../types'
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
createOrder as createOrderHelper,
|
|
24
|
+
updateOrderShippingInfo as updateOrderShippingInfoHelper,
|
|
25
|
+
updateOrderPaymentInfo as updateOrderPaymentInfoHelper
|
|
26
|
+
} from './order'
|
|
27
|
+
|
|
28
|
+
import ActualLineItem, { type ActualLineItemSnapshot } from './actual-line-item'
|
|
29
|
+
import { getParentPath } from '../../path-utils'
|
|
30
|
+
import { getErrorMessage } from '../../../util'
|
|
31
|
+
import sep from '../../sep'
|
|
32
|
+
|
|
33
|
+
import { getInstance } from './get-instance'
|
|
34
|
+
|
|
35
|
+
type StandaloneServiceOptions = {
|
|
36
|
+
dbName: string
|
|
37
|
+
ordersTable: string
|
|
38
|
+
localStorageKey: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
interface StandaloneServiceSnapshot {
|
|
42
|
+
items: ActualLineItemSnapshot[]
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class StandaloneService
|
|
46
|
+
implements CommerceService
|
|
47
|
+
{
|
|
48
|
+
private _familyMap = new Map<string, Family>()
|
|
49
|
+
private _rootNode: CategoryNode
|
|
50
|
+
private _selectedPaths: SelectedPaths = {}
|
|
51
|
+
private _promo: Promo | null = null
|
|
52
|
+
|
|
53
|
+
private _options : StandaloneServiceOptions
|
|
54
|
+
private _currentFamily: Family | undefined = undefined
|
|
55
|
+
private _currentItem: ActualLineItem | undefined = undefined
|
|
56
|
+
|
|
57
|
+
constructor(
|
|
58
|
+
families: Family[],
|
|
59
|
+
rootNode: CategoryNode,
|
|
60
|
+
options: StandaloneServiceOptions,
|
|
61
|
+
serviceSnapshot?: StandaloneServiceSnapshot,
|
|
62
|
+
) {
|
|
63
|
+
|
|
64
|
+
this._rootNode = rootNode
|
|
65
|
+
this._options = options
|
|
66
|
+
|
|
67
|
+
families.forEach((fam) => {
|
|
68
|
+
fam.products = fam.products.map((p) => {
|
|
69
|
+
if (serviceSnapshot) {
|
|
70
|
+
const itemSnapshot = serviceSnapshot.items.find((is) => (is.sku === p.sku))
|
|
71
|
+
if (itemSnapshot) {
|
|
72
|
+
return new ActualLineItem(p, itemSnapshot)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return new ActualLineItem(p)
|
|
76
|
+
})
|
|
77
|
+
this._familyMap.set(fam.id, fam)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
makeObservable<
|
|
81
|
+
StandaloneService,
|
|
82
|
+
'_selectedPaths' |
|
|
83
|
+
'_currentItem' |
|
|
84
|
+
'_currentFamily' |
|
|
85
|
+
'_promo' |
|
|
86
|
+
'_cartItems'
|
|
87
|
+
>(this, {
|
|
88
|
+
_selectedPaths : observable.deep,
|
|
89
|
+
_currentItem: observable.shallow,
|
|
90
|
+
_currentFamily: observable.shallow,
|
|
91
|
+
_promo: observable,
|
|
92
|
+
_cartItems: computed
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
makeObservable(this, {
|
|
96
|
+
|
|
97
|
+
setCurrentItem: action,
|
|
98
|
+
setCurrentFamily: action,
|
|
99
|
+
setAppliedPromo: action,
|
|
100
|
+
/* NOT selectPaths. It implements it's action mechanism */
|
|
101
|
+
|
|
102
|
+
cartItems: computed,
|
|
103
|
+
recentItem: computed,
|
|
104
|
+
cartQuantity: computed,
|
|
105
|
+
cartTotal: computed,
|
|
106
|
+
promoAppliedCartTotal: computed,
|
|
107
|
+
cartEmpty: computed,
|
|
108
|
+
selectedItems: computed,
|
|
109
|
+
selectedFamilies: computed,
|
|
110
|
+
hasSelection: computed,
|
|
111
|
+
currentItem: computed,
|
|
112
|
+
currentFamily: computed,
|
|
113
|
+
item: computed,
|
|
114
|
+
family: computed,
|
|
115
|
+
selectedPaths: computed,
|
|
116
|
+
appliedPromo: computed,
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getFamilyById(id: string): Family | undefined {
|
|
121
|
+
return this._familyMap.get(id)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
getNodeAtPath(skuPath: string): CategoryNode | undefined {
|
|
125
|
+
const toks = skuPath.split(sep.tok)
|
|
126
|
+
let level = 1
|
|
127
|
+
let node: CategoryNode | undefined = this._rootNode
|
|
128
|
+
do {
|
|
129
|
+
node = node!.subNodes?.find((sn) => (sn.skuToken === toks[level]))
|
|
130
|
+
level++
|
|
131
|
+
}
|
|
132
|
+
while (node && (level < toks.length))
|
|
133
|
+
return level === toks.length ? node : undefined
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
peek(skuPath: string): {
|
|
137
|
+
role: CategoryNodeRole
|
|
138
|
+
family: Family | undefined
|
|
139
|
+
families: Family[] | undefined
|
|
140
|
+
node: CategoryNode | undefined
|
|
141
|
+
item: LineItem | undefined
|
|
142
|
+
} | string /* OR error string */ {
|
|
143
|
+
|
|
144
|
+
const toks = skuPath.split(sep.tok)
|
|
145
|
+
let level: number
|
|
146
|
+
let node: CategoryNode | undefined = this._rootNode
|
|
147
|
+
let parent: CategoryNode | undefined = undefined
|
|
148
|
+
|
|
149
|
+
for (level = 1; level < toks.length && node && node.subNodes; level++) {
|
|
150
|
+
// https://stackoverflow.com/questions/62367492/inference-problem-referenced-directly-or-indirectly-in-its-own-initializer
|
|
151
|
+
const _node: CategoryNode | undefined =
|
|
152
|
+
node!.subNodes.find((sn) => (sn.skuToken === toks[level]))
|
|
153
|
+
if (!_node) {
|
|
154
|
+
return `service.peekAtNode: traversing '${skuPath}'... no CategoryNode at '${toks[level]}'!`
|
|
155
|
+
}
|
|
156
|
+
parent = node
|
|
157
|
+
node = _node
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const atEnd = level === toks.length
|
|
161
|
+
const possibleSKU = level === toks.length - 1
|
|
162
|
+
|
|
163
|
+
let role: CategoryNodeRole = 'non-outermost'
|
|
164
|
+
let families: Family[] | undefined = undefined
|
|
165
|
+
let family: Family | undefined = undefined
|
|
166
|
+
let item: LineItem | undefined = undefined
|
|
167
|
+
let error: string | undefined = undefined
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
if (node.subNodes && atEnd && node.outermost) {
|
|
171
|
+
role = 'multi-family'
|
|
172
|
+
families = node.subNodes.map((sub) => {
|
|
173
|
+
const familyId = skuPath + sep.tok + sub.skuToken
|
|
174
|
+
const fam = this._familyMap.get(familyId)
|
|
175
|
+
if (!fam) {
|
|
176
|
+
throw new Error(`service.peekAtNode: No Family under for CategoryNode '${skuPath}' with id ${familyId}!`)
|
|
177
|
+
}
|
|
178
|
+
return fam
|
|
179
|
+
})
|
|
180
|
+
}
|
|
181
|
+
else if (!node.subNodes && (atEnd || possibleSKU)) {
|
|
182
|
+
const _skuPath = (possibleSKU) ? getParentPath(skuPath) : skuPath
|
|
183
|
+
if (parent?.outermost) {
|
|
184
|
+
role = 'family-in-multi-family'
|
|
185
|
+
const fam = this._familyMap.get(_skuPath)
|
|
186
|
+
if (!fam) {
|
|
187
|
+
throw new Error(`service.peekAtNode: '${_skuPath}' graphs as a Family under a multi-family node, but no such family exists!`)
|
|
188
|
+
}
|
|
189
|
+
family = fam
|
|
190
|
+
const parentPath = getParentPath(_skuPath)
|
|
191
|
+
// get all siblings (subnodes of parent)
|
|
192
|
+
families = parent.subNodes!.map((sn) => {
|
|
193
|
+
const familyId = parentPath + sep.tok + sn.skuToken
|
|
194
|
+
const fam = this._familyMap.get(familyId)
|
|
195
|
+
if (!fam) {
|
|
196
|
+
throw new Error(`service.peekAtNode: No sibling Family for '${_skuPath}' with id '${familyId}'!`)
|
|
197
|
+
}
|
|
198
|
+
return fam
|
|
199
|
+
})
|
|
200
|
+
node = parent
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
role = 'single-family'
|
|
204
|
+
const fam = this._familyMap.get(_skuPath)
|
|
205
|
+
if (!fam) {
|
|
206
|
+
throw new Error(`service.peekAtNode: '${_skuPath}' graphs as a single Family, but no such family exists!`)
|
|
207
|
+
}
|
|
208
|
+
family = fam
|
|
209
|
+
}
|
|
210
|
+
if (possibleSKU) {
|
|
211
|
+
const skuToTry = family.id + sep.tok + toks[toks.length - 1]
|
|
212
|
+
const _item = family.products.find((p) => (p.sku === skuToTry))
|
|
213
|
+
if (_item) {
|
|
214
|
+
item = _item as LineItem
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
throw new Error(`service.peekAtNode: '${skuPath}' graphs as LineItem in Family '${family.id}', but no such sku exists there!`)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
catch (e) {
|
|
223
|
+
error = getErrorMessage(e)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return error ?? {
|
|
227
|
+
role,
|
|
228
|
+
family,
|
|
229
|
+
families,
|
|
230
|
+
node,
|
|
231
|
+
item
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
getSelectedNodesAtLevel = computedFn((level: number): CategoryNode[] | undefined => {
|
|
236
|
+
|
|
237
|
+
let lvl = 1
|
|
238
|
+
let nodesAtLevel: CategoryNode[] | undefined = this._rootNode.subNodes
|
|
239
|
+
|
|
240
|
+
do {
|
|
241
|
+
let selectedAtLevel: CategoryNode[] | undefined = undefined
|
|
242
|
+
// If not specified, assume all
|
|
243
|
+
if (lvl in this._selectedPaths) {
|
|
244
|
+
selectedAtLevel = nodesAtLevel!.filter((n) => (this._selectedPaths[lvl].includes(n.skuToken)))
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
selectedAtLevel = nodesAtLevel
|
|
248
|
+
}
|
|
249
|
+
let allSubsOfSelected: CategoryNode[] = []
|
|
250
|
+
selectedAtLevel?.forEach((n: CategoryNode) => {
|
|
251
|
+
if (n.subNodes) {
|
|
252
|
+
allSubsOfSelected = [...allSubsOfSelected, ...n.subNodes]
|
|
253
|
+
}
|
|
254
|
+
})
|
|
255
|
+
|
|
256
|
+
nodesAtLevel = allSubsOfSelected
|
|
257
|
+
lvl++
|
|
258
|
+
} while (nodesAtLevel.length > 0 && lvl <= level)
|
|
259
|
+
|
|
260
|
+
return (nodesAtLevel.length > 0 && ((lvl - 1) === level)) ? nodesAtLevel : undefined
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
get options() { return this._options}
|
|
264
|
+
|
|
265
|
+
//async createOrder(email: string, paymentMethod: string): Promise<string | undefined> {
|
|
266
|
+
async createOrder(email: string, name?: string): Promise<string | undefined> {
|
|
267
|
+
const snapshot = this.takeSnapshot()
|
|
268
|
+
const order = await createOrderHelper(email, snapshot.items, this._options, name) // didn't want to have two levels of 'items'
|
|
269
|
+
return order.id
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// TODO: add shippingInfo type
|
|
273
|
+
async updateOrderShippingInfo(orderId: string, shippingInfo: any): Promise<void> {
|
|
274
|
+
updateOrderShippingInfoHelper(orderId, shippingInfo, this._options)
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// TODO: add paymentInfo type
|
|
278
|
+
async updateOrderPaymentInfo(orderId: string, paymentInfo: any): Promise<void> {
|
|
279
|
+
updateOrderPaymentInfoHelper(orderId, paymentInfo, this._options)
|
|
280
|
+
}
|
|
281
|
+
// Might as well use the ordered set.
|
|
282
|
+
takeSnapshot = (): StandaloneServiceSnapshot => ({
|
|
283
|
+
items : (this.cartItems as ActualLineItem[]).map((it) => (it.takeSnapshot(this)))
|
|
284
|
+
})
|
|
285
|
+
|
|
286
|
+
// last cartItem whose quantity was modified (undefined if cartEmpty)
|
|
287
|
+
get recentItem(): { item: LineItem, modified: number} | undefined {
|
|
288
|
+
|
|
289
|
+
if (this.cartEmpty) return undefined;
|
|
290
|
+
|
|
291
|
+
const mostRecent = this._cartItems.reduce(
|
|
292
|
+
(newest, item) => ((!newest) ? item : (
|
|
293
|
+
(item as ActualLineItem).timeModified > (newest as ActualLineItem).timeModified) ? item : newest
|
|
294
|
+
),
|
|
295
|
+
undefined as LineItem | undefined
|
|
296
|
+
)
|
|
297
|
+
return { item: mostRecent!, modified: (mostRecent! as ActualLineItem).timeModified }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
private get _cartItems(): LineItem[] {
|
|
301
|
+
let result: LineItem[] = []
|
|
302
|
+
this._familyMap.forEach((fam) => {
|
|
303
|
+
result = [...result, ...(fam.products as LineItem[]).filter((item) => (item.isInCart))]
|
|
304
|
+
})
|
|
305
|
+
return result
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
get cartItems(): LineItem[] {
|
|
309
|
+
return this._cartItems.sort((it1, it2) => ((it1 as ActualLineItem).timeAdded - (it2 as ActualLineItem).timeAdded))
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
get cartEmpty(): boolean {
|
|
315
|
+
return this._cartItems.length === 0
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
get cartTotal(): number {
|
|
319
|
+
return this._cartItems.reduce(
|
|
320
|
+
(total, item) => (total + item.price * item.quantity),
|
|
321
|
+
0
|
|
322
|
+
)
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
_promoValue_unsafe(value: number): number {
|
|
326
|
+
if (this._promo!.type === 'percent') {
|
|
327
|
+
return value * (1 - this._promo!.value / 100)
|
|
328
|
+
}
|
|
329
|
+
return value - this._promo!.value
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
get promoAppliedCartTotal(): number {
|
|
333
|
+
if (!this._promo) {
|
|
334
|
+
return this.cartTotal
|
|
335
|
+
}
|
|
336
|
+
if (!this._promo.skus) {
|
|
337
|
+
return this._promoValue_unsafe(this.cartTotal)
|
|
338
|
+
}
|
|
339
|
+
let total = this._cartItems.reduce(
|
|
340
|
+
(total, item) => {
|
|
341
|
+
const itemPrice = this._promo!.skus!.includes(item.sku) ?
|
|
342
|
+
this._promoValue_unsafe(item.price)
|
|
343
|
+
:
|
|
344
|
+
item.price
|
|
345
|
+
return total + itemPrice * item.quantity
|
|
346
|
+
},
|
|
347
|
+
0
|
|
348
|
+
)
|
|
349
|
+
return total
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
itemPromoPrice(item: LineItem): number | undefined {
|
|
353
|
+
if (this._promo && (!this._promo.skus || this._promo.skus.includes(item.sku) )) {
|
|
354
|
+
return this._promoValue_unsafe(item.price)
|
|
355
|
+
}
|
|
356
|
+
return undefined
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
get cartQuantity(): number {
|
|
360
|
+
return this.cartItems.reduce(
|
|
361
|
+
(total, item) => (total + item.quantity),
|
|
362
|
+
0
|
|
363
|
+
)
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
get appliedPromo(): Promo | null {
|
|
367
|
+
return this._promo
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
setAppliedPromo(promo: Promo | null): void {
|
|
371
|
+
this._promo = promo
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
getItemBySku = (skuToFind: string | undefined): LineItem | undefined => {
|
|
375
|
+
|
|
376
|
+
if (skuToFind === undefined || skuToFind.length === 0) {
|
|
377
|
+
return undefined
|
|
378
|
+
}
|
|
379
|
+
// Self-calling
|
|
380
|
+
const found = ((): ActualLineItem | undefined => {
|
|
381
|
+
|
|
382
|
+
const familiesTried: string[] = []
|
|
383
|
+
if (this.selectedFamilies && this.selectedFamilies.length > 0) {
|
|
384
|
+
for (let family of this.selectedFamilies) {
|
|
385
|
+
familiesTried.push(family.id)
|
|
386
|
+
const foundItem = family.products.find((p) => (p.sku === skuToFind))
|
|
387
|
+
if (foundItem) {
|
|
388
|
+
return foundItem as ActualLineItem
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
for( const [familyId, family] of this._familyMap.entries()) {
|
|
393
|
+
if (familiesTried.includes(familyId)) continue
|
|
394
|
+
const foundItem = family.products.find((p) => (p.sku === skuToFind)) as ActualLineItem | undefined
|
|
395
|
+
if (foundItem) {
|
|
396
|
+
return foundItem as ActualLineItem
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return undefined
|
|
400
|
+
})(); // Self-calling, necessary semi
|
|
401
|
+
|
|
402
|
+
return found
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
setCurrentItem = (skuToFind: string | undefined): boolean => {
|
|
406
|
+
|
|
407
|
+
if (skuToFind === undefined || skuToFind.length === 0) {
|
|
408
|
+
this._currentItem = undefined
|
|
409
|
+
return true
|
|
410
|
+
}
|
|
411
|
+
// self calling function
|
|
412
|
+
this._currentItem = this.getItemBySku(skuToFind) as ActualLineItem | undefined
|
|
413
|
+
this.setCurrentFamily(this._currentItem ? this._currentItem.familyId : undefined)
|
|
414
|
+
return !!this._currentItem
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/* for ObsLineItemRef */
|
|
418
|
+
get item(): LineItem | undefined {
|
|
419
|
+
return this._currentItem
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
get currentItem(): LineItem | undefined {
|
|
423
|
+
return this._currentItem
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
setCurrentFamily(id: string | undefined): boolean {
|
|
427
|
+
|
|
428
|
+
if (id === undefined || id.length === 0) {
|
|
429
|
+
this._currentFamily = undefined
|
|
430
|
+
return true
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const fam = this._familyMap.get(id)
|
|
434
|
+
this._currentFamily = fam // undef ok
|
|
435
|
+
|
|
436
|
+
if (
|
|
437
|
+
this._currentFamily &&
|
|
438
|
+
this._currentItem &&
|
|
439
|
+
this._currentItem.familyId !== this._currentFamily.id
|
|
440
|
+
) {
|
|
441
|
+
this._currentItem = undefined
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return !!this._currentFamily
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
get currentFamily(): Family | undefined {
|
|
448
|
+
return this._currentFamily
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/* for ObsFamilyRef */
|
|
452
|
+
get family(): Family | undefined {
|
|
453
|
+
return this._currentFamily
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
selectPaths(sel: SelectedPaths): Family[] {
|
|
457
|
+
runInAction (() => {
|
|
458
|
+
this._selectedPaths = this._processAndValidate(sel)
|
|
459
|
+
})
|
|
460
|
+
return this.selectedFamilies
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
selectPath(skuPath: string): Family[] {
|
|
464
|
+
const toks = skuPath.split(sep.tok)
|
|
465
|
+
const highestLevel = toks.length - 1
|
|
466
|
+
const fsv: SelectedPaths = {}
|
|
467
|
+
for (let level = 1; level <= highestLevel; level++ ) {
|
|
468
|
+
fsv[level] = [toks[level]]
|
|
469
|
+
}
|
|
470
|
+
return this.selectPaths(fsv)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
get selectedPaths(): SelectedPaths {
|
|
474
|
+
const result: SelectedPaths = {}
|
|
475
|
+
for( let level in this._selectedPaths ) {
|
|
476
|
+
result[level] = [...this._selectedPaths[level]]
|
|
477
|
+
}
|
|
478
|
+
return result
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
get selectedFamilies(): Family[] {
|
|
482
|
+
if (Object.keys(toJS(this._selectedPaths)).length === 0) {
|
|
483
|
+
// FacetsDesc have never been set or unset, so cannot evaluate them
|
|
484
|
+
return []
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return this._rootNode.subNodes!.reduce(
|
|
488
|
+
(acc: Family[], subFacet: CategoryNode) => (
|
|
489
|
+
// Pass the root token as a one member array
|
|
490
|
+
this._reduceNode([this._rootNode.skuToken], acc, subFacet)
|
|
491
|
+
),
|
|
492
|
+
[]
|
|
493
|
+
)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
private _reduceNode(parentPath: string[], acc: Family[], node: CategoryNode): Family[] {
|
|
497
|
+
const path = [...parentPath, node.skuToken] // Don't mutate original please :)
|
|
498
|
+
const level = path.length - 1
|
|
499
|
+
// If there is no token array supplied for this level,
|
|
500
|
+
// assume all are specified. Otherwise, see if the
|
|
501
|
+
// current node is in the array
|
|
502
|
+
const specified = (
|
|
503
|
+
!this._selectedPaths[level]
|
|
504
|
+
||
|
|
505
|
+
this._selectedPaths[level].includes(node.skuToken)
|
|
506
|
+
)
|
|
507
|
+
if (specified) {
|
|
508
|
+
// Process subnodes
|
|
509
|
+
if (node.subNodes && node.subNodes.length > 0) {
|
|
510
|
+
return node.subNodes.reduce((acc, n) => (
|
|
511
|
+
this._reduceNode(path, acc, n)
|
|
512
|
+
)
|
|
513
|
+
, acc)
|
|
514
|
+
}
|
|
515
|
+
// Process leaf
|
|
516
|
+
const fam = this._familyMap.get(path.join(sep.tok))
|
|
517
|
+
if (!fam) {
|
|
518
|
+
throw new Error("selectedFamilies WTF?!" + path.join(sep.tok))
|
|
519
|
+
}
|
|
520
|
+
acc.push(fam)
|
|
521
|
+
}
|
|
522
|
+
return acc
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
private _processAndValidate(partial: SelectedPaths): SelectedPaths {
|
|
526
|
+
|
|
527
|
+
const result: SelectedPaths = {}
|
|
528
|
+
|
|
529
|
+
let level = 1
|
|
530
|
+
let currentSet = this._rootNode.subNodes!
|
|
531
|
+
|
|
532
|
+
while (true) {
|
|
533
|
+
let possibleCurrent = currentSet.map((el) => (el.skuToken))
|
|
534
|
+
const validTokens = !partial[level] ? undefined : partial[level].filter((tok) => possibleCurrent.includes(tok))
|
|
535
|
+
if (!validTokens) {
|
|
536
|
+
break
|
|
537
|
+
}
|
|
538
|
+
result[level] = validTokens
|
|
539
|
+
currentSet = validTokens.map((tok) => {
|
|
540
|
+
const fd = currentSet.find((node) => ( node.skuToken === tok ))
|
|
541
|
+
return (fd && fd.subNodes && fd.subNodes.length > 0) ? fd.subNodes : []
|
|
542
|
+
}).flat()
|
|
543
|
+
level++
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
return result
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
get selectedItems(): LineItem[] {
|
|
550
|
+
if (Object.keys(toJS(this._selectedPaths)).length === 0) {
|
|
551
|
+
// FacetsDesc have never been set or unset, so cannot evaluate them
|
|
552
|
+
return []
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return this.selectedFamilies.reduce(
|
|
556
|
+
(allProducts, fam) => ([...allProducts, ...(fam.products as LineItem[])]), [] as LineItem[])
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
get hasSelection(): boolean {
|
|
560
|
+
return this.selectedFamilies.length > 0
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
getFamilySubtotal(familyId: string): number {
|
|
564
|
+
const c = this._familyMap.get(familyId)!
|
|
565
|
+
return (c.products as LineItem[]).reduce(
|
|
566
|
+
// avoid floating point bs around zero
|
|
567
|
+
(total, item) => (item.quantity > 0 ? total + item.price * item.quantity : total),
|
|
568
|
+
0
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
export {
|
|
575
|
+
type StandaloneServiceOptions,
|
|
576
|
+
type StandaloneServiceSnapshot,
|
|
577
|
+
StandaloneService,
|
|
578
|
+
getInstance
|
|
579
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { initializeApp, getApps } from 'firebase/app'
|
|
2
|
+
|
|
3
|
+
const firebaseConfig = {
|
|
4
|
+
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
|
|
5
|
+
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
|
|
6
|
+
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
|
|
7
|
+
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
|
|
8
|
+
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
|
|
9
|
+
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
|
|
10
|
+
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Initialize Firebase instance if there isn't one already
|
|
14
|
+
export default getApps().length === 0 ? initializeApp(firebaseConfig) : getApps()[0]
|