@hanzo/commerce 7.3.2 → 7.3.3
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/components/Icons.tsx +34 -34
- package/components/add-to-cart-widget.tsx +183 -183
- package/components/buy/buy-card.tsx +259 -259
- package/components/buy/carousel-buy-card.tsx +242 -242
- package/components/buy/multi-family/all-variants-carousel.tsx +261 -261
- package/components/buy/multi-family/family-carousel/index.tsx +77 -77
- package/components/buy/multi-family/family-carousel/slide.tsx +83 -83
- package/components/buy/multi-family/family-carousel/state.ts +87 -87
- package/components/buy/multi-family/index.ts +2 -2
- package/components/buy/single-family-selector.tsx +90 -90
- package/components/buy/title-and-byline.tsx +25 -25
- package/components/cart/cart-panel/cart-line-item.tsx +76 -76
- package/components/cart/cart-panel/index.tsx +154 -154
- package/components/cart/cart-panel/promo-code.tsx +106 -106
- package/components/cart/cart-panel/total-area.tsx +60 -60
- package/components/checkout/payment-step-form/card-icon-row.tsx +26 -26
- package/components/checkout/payment-step-form/card-icons/amex.tsx +32 -32
- package/components/checkout/payment-step-form/card-icons/diners-club.tsx +13 -13
- package/components/checkout/payment-step-form/card-icons/discover.tsx +25 -25
- package/components/checkout/payment-step-form/card-icons/jcb.tsx +26 -26
- package/components/checkout/payment-step-form/card-icons/mastercard.tsx +27 -27
- package/components/checkout/payment-step-form/card-icons/visa.tsx +25 -25
- package/components/checkout/payment-step-form/cc-button.tsx +17 -17
- package/components/checkout/payment-step-form/contact-form.tsx +49 -49
- package/components/checkout/payment-step-form/crypto-icons/btc.tsx +11 -11
- package/components/checkout/payment-step-form/crypto-icons/eth.tsx +20 -20
- package/components/checkout/payment-step-form/crypto-icons/usdt.tsx +13 -13
- package/components/checkout/payment-step-form/index.tsx +122 -122
- package/components/checkout/payment-step-form/methods/bank-transfer.tsx +79 -79
- package/components/checkout/payment-step-form/methods/card.tsx +232 -232
- package/components/checkout/payment-step-form/methods/crypto.tsx +227 -227
- package/components/checkout/payment-step-form/methods/index.ts +22 -22
- package/components/checkout/shipping-step-form.tsx +172 -172
- package/components/index.ts +11 -11
- package/components/item/product-card.tsx +48 -48
- package/components/item-selector/button.tsx +188 -188
- package/components/item-selector/carousel/index.tsx +197 -197
- package/components/item-selector/carousel/slider.tsx +40 -40
- package/components/item-selector/index.ts +5 -5
- package/components/item-selector/quantity-indicator.tsx +48 -48
- package/components/node-tabs/index.tsx +91 -91
- package/components/node-tabs/node-image.tsx +31 -31
- package/index.ts +12 -12
- package/package.json +60 -60
- package/service/context.tsx +45 -45
- package/service/debug.ts +41 -41
- package/service/impls/standalone/actual-line-item.ts +135 -135
- package/service/impls/standalone/get-instance.ts +64 -64
- package/service/impls/standalone/index.ts +579 -579
- package/service/impls/standalone/order/firebase.ts +14 -14
- package/service/impls/standalone/order/index.ts +128 -128
- package/service/impls/standalone/persistence.ts +33 -33
- package/service/path-utils.ts +25 -25
- package/service/sep.ts +6 -6
- package/tsconfig.json +10 -10
- package/types/README.md +1 -1
- package/types/category-node.ts +49 -49
- package/types/checkout.ts +46 -46
- package/types/commerce-config.ts +13 -13
- package/types/commerce-service.ts +127 -127
- package/types/family.ts +25 -25
- package/types/index.ts +15 -15
- package/types/item-selector.ts +96 -96
- package/types/line-item.ts +29 -29
- package/types/multi-family-selector-props.ts +19 -19
- package/types/product.ts +20 -20
- package/types/promo.ts +9 -9
- package/types/selection-ui-specifier.ts +51 -51
- package/types/string-mutator.ts +13 -13
- package/types/token-separators.ts +7 -7
- package/util/analytics.ts +20 -20
- package/util/countries.ts +195 -195
- package/util/error.ts +34 -34
- package/util/index.ts +70 -70
- package/util/item-selector-options-accessor.ts +34 -34
- package/util/line-item-ref.ts +23 -23
- package/util/multi-family-selector-options-accessor.ts +14 -14
- package/util/obs-string-mutator.ts +22 -22
- package/util/product-media-accessor.ts +58 -58
- package/util/promo-codes.ts +108 -108
- package/util/selection-ui-specifiers.ts +29 -29
- package/util/square-payment.ts +42 -42
- package/util/use-sync-sku-param-w-current-item.ts +88 -88
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import type { SelectionUISpecifier } from '../types'
|
|
2
|
-
import sep from '../service/sep'
|
|
3
|
-
|
|
4
|
-
const DEFAULT = {
|
|
5
|
-
multiFamily: {
|
|
6
|
-
type: 'all-variants-carousel'
|
|
7
|
-
},
|
|
8
|
-
singleFamily: { type: 'carousel' }
|
|
9
|
-
} satisfies SelectionUISpecifier
|
|
10
|
-
|
|
11
|
-
const map = new Map<string, SelectionUISpecifier>()
|
|
12
|
-
|
|
13
|
-
// key: first two tokens of path
|
|
14
|
-
export const initSelectionUI = (v: Record<string, SelectionUISpecifier>) => {
|
|
15
|
-
|
|
16
|
-
// Might have multiple calls client and server side
|
|
17
|
-
if (map.size > 0) {
|
|
18
|
-
map.clear()
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
for (let [key, value] of Object.entries(v)) {
|
|
22
|
-
map.set(key, value)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export const getSelectionUISpecifier = (skuPath: string): SelectionUISpecifier => {
|
|
27
|
-
const key = skuPath.split(sep.tok).slice(0, 2).join(sep.tok)
|
|
28
|
-
const result = map.get(key)
|
|
29
|
-
return result ?? DEFAULT
|
|
1
|
+
import type { SelectionUISpecifier } from '../types'
|
|
2
|
+
import sep from '../service/sep'
|
|
3
|
+
|
|
4
|
+
const DEFAULT = {
|
|
5
|
+
multiFamily: {
|
|
6
|
+
type: 'all-variants-carousel'
|
|
7
|
+
},
|
|
8
|
+
singleFamily: { type: 'carousel' }
|
|
9
|
+
} satisfies SelectionUISpecifier
|
|
10
|
+
|
|
11
|
+
const map = new Map<string, SelectionUISpecifier>()
|
|
12
|
+
|
|
13
|
+
// key: first two tokens of path
|
|
14
|
+
export const initSelectionUI = (v: Record<string, SelectionUISpecifier>) => {
|
|
15
|
+
|
|
16
|
+
// Might have multiple calls client and server side
|
|
17
|
+
if (map.size > 0) {
|
|
18
|
+
map.clear()
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
for (let [key, value] of Object.entries(v)) {
|
|
22
|
+
map.set(key, value)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const getSelectionUISpecifier = (skuPath: string): SelectionUISpecifier => {
|
|
27
|
+
const key = skuPath.split(sep.tok).slice(0, 2).join(sep.tok)
|
|
28
|
+
const result = map.get(key)
|
|
29
|
+
return result ?? DEFAULT
|
|
30
30
|
}
|
package/util/square-payment.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
'use server'
|
|
2
|
-
|
|
3
|
-
import { Client, Environment } from 'square'
|
|
4
|
-
import { randomUUID } from 'crypto'
|
|
5
|
-
|
|
6
|
-
// https://developer.squareup.com/blog/online-payments-with-square-and-react/
|
|
7
|
-
declare global {
|
|
8
|
-
interface BigInt {
|
|
9
|
-
toJSON(): string;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
BigInt.prototype.toJSON = function() { return this.toString(); }
|
|
14
|
-
|
|
15
|
-
const { paymentsApi } = new Client({
|
|
16
|
-
accessToken: process.env.SQUARE_ACCESS_TOKEN,
|
|
17
|
-
environment: process.env.SQUARE_ENVIRONMENT as Environment
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
const processPayment = async (sourceId: string, amount: number, verificationToken: string) => {
|
|
21
|
-
// Square API accepts amount in cents
|
|
22
|
-
const amountInCents = amount * 100
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const { result } = await paymentsApi.createPayment({
|
|
26
|
-
idempotencyKey: randomUUID(),
|
|
27
|
-
sourceId: sourceId,
|
|
28
|
-
amountMoney: {
|
|
29
|
-
currency: 'USD',
|
|
30
|
-
amount: BigInt(amountInCents)
|
|
31
|
-
},
|
|
32
|
-
verificationToken
|
|
33
|
-
})
|
|
34
|
-
return result
|
|
35
|
-
} catch (error) {
|
|
36
|
-
console.error('Error processing payment:', error)
|
|
37
|
-
return null
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export {
|
|
42
|
-
processPayment as default
|
|
1
|
+
'use server'
|
|
2
|
+
|
|
3
|
+
import { Client, Environment } from 'square'
|
|
4
|
+
import { randomUUID } from 'crypto'
|
|
5
|
+
|
|
6
|
+
// https://developer.squareup.com/blog/online-payments-with-square-and-react/
|
|
7
|
+
declare global {
|
|
8
|
+
interface BigInt {
|
|
9
|
+
toJSON(): string;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
BigInt.prototype.toJSON = function() { return this.toString(); }
|
|
14
|
+
|
|
15
|
+
const { paymentsApi } = new Client({
|
|
16
|
+
accessToken: process.env.SQUARE_ACCESS_TOKEN,
|
|
17
|
+
environment: process.env.SQUARE_ENVIRONMENT as Environment
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
const processPayment = async (sourceId: string, amount: number, verificationToken: string) => {
|
|
21
|
+
// Square API accepts amount in cents
|
|
22
|
+
const amountInCents = amount * 100
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const { result } = await paymentsApi.createPayment({
|
|
26
|
+
idempotencyKey: randomUUID(),
|
|
27
|
+
sourceId: sourceId,
|
|
28
|
+
amountMoney: {
|
|
29
|
+
currency: 'USD',
|
|
30
|
+
amount: BigInt(amountInCents)
|
|
31
|
+
},
|
|
32
|
+
verificationToken
|
|
33
|
+
})
|
|
34
|
+
return result
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.error('Error processing payment:', error)
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
processPayment as default
|
|
43
43
|
}
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
"use client"
|
|
2
|
-
import { useEffect } from 'react'
|
|
3
|
-
import { reaction } from 'mobx'
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
useQueryState,
|
|
7
|
-
parseAsString,
|
|
8
|
-
parseAsBoolean,
|
|
9
|
-
} from 'next-usequerystate'
|
|
10
|
-
|
|
11
|
-
import { useCommerce } from '../service/context'
|
|
12
|
-
import type { SelectedPaths } from '../types'
|
|
13
|
-
import sep from '../service/sep'
|
|
14
|
-
|
|
15
|
-
const PLEASE_SELECT_FACETS = 'Please select an option from each group.'
|
|
16
|
-
|
|
17
|
-
const useSyncSkuParamWithCurrentItem = (
|
|
18
|
-
familyLevel: number,
|
|
19
|
-
setMessage: (m: string | undefined) => void,
|
|
20
|
-
setLoading?: (l: boolean) => void
|
|
21
|
-
) => {
|
|
22
|
-
|
|
23
|
-
const cmmc = useCommerce()
|
|
24
|
-
|
|
25
|
-
const [skuParam, setSkuParam] = useQueryState('sku',
|
|
26
|
-
parseAsString.withDefault('').withOptions({ clearOnDefault: true })
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
const [addParam, setAddParam] = useQueryState('add',
|
|
30
|
-
parseAsBoolean.withDefault(false).withOptions({ clearOnDefault: true })
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
|
|
35
|
-
return reaction(() => ({
|
|
36
|
-
specifiedCat: cmmc.selectedFamilies.length === 1 ? cmmc.selectedFamilies[0] : undefined,
|
|
37
|
-
currentItem: cmmc.currentItem
|
|
38
|
-
}),
|
|
39
|
-
({specifiedCat, currentItem}) => {
|
|
40
|
-
//console.log("REACTION: " + `CAT ID: ${family?.id} SKU: ${item?.sku}`)
|
|
41
|
-
if (currentItem) {
|
|
42
|
-
// if we set the currentItem w sku, then user selects other facets
|
|
43
|
-
if (specifiedCat && currentItem.familyId != specifiedCat.id ) {
|
|
44
|
-
cmmc.setCurrentItem(specifiedCat.products[0].sku)
|
|
45
|
-
}
|
|
46
|
-
setSkuParam(cmmc.currentItem!.sku)
|
|
47
|
-
}
|
|
48
|
-
else if (specifiedCat) {
|
|
49
|
-
cmmc.setCurrentItem(specifiedCat.products[0].sku)
|
|
50
|
-
setSkuParam(cmmc.currentItem!.sku)
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
}, [])
|
|
54
|
-
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
|
|
57
|
-
const setCurrentFamilyFromSku = (sku: string) => {
|
|
58
|
-
const toks: string[] = sku.split(sep.tok)
|
|
59
|
-
const fv: SelectedPaths = {}
|
|
60
|
-
// TODO: confirm that extra trailing nonsense tokens won't break selectPaths()
|
|
61
|
-
for (let i = 1; i < familyLevel; i++) {
|
|
62
|
-
if (i in toks) {
|
|
63
|
-
fv[i] = [toks[i]]
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
cmmc.selectPaths(fv)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// setCI returns true if it's a recognized sku
|
|
70
|
-
if (skuParam && cmmc.setCurrentItem(skuParam)) {
|
|
71
|
-
if (addParam) {
|
|
72
|
-
if (cmmc.currentItem!.quantity === 0) {
|
|
73
|
-
cmmc.currentItem!.increment()
|
|
74
|
-
}
|
|
75
|
-
setAddParam(false)
|
|
76
|
-
}
|
|
77
|
-
setCurrentFamilyFromSku(skuParam)
|
|
78
|
-
setMessage(undefined)
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
setMessage(PLEASE_SELECT_FACETS)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
setLoading && setLoading(false)
|
|
85
|
-
}, [skuParam])
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export default useSyncSkuParamWithCurrentItem
|
|
1
|
+
"use client"
|
|
2
|
+
import { useEffect } from 'react'
|
|
3
|
+
import { reaction } from 'mobx'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
useQueryState,
|
|
7
|
+
parseAsString,
|
|
8
|
+
parseAsBoolean,
|
|
9
|
+
} from 'next-usequerystate'
|
|
10
|
+
|
|
11
|
+
import { useCommerce } from '../service/context'
|
|
12
|
+
import type { SelectedPaths } from '../types'
|
|
13
|
+
import sep from '../service/sep'
|
|
14
|
+
|
|
15
|
+
const PLEASE_SELECT_FACETS = 'Please select an option from each group.'
|
|
16
|
+
|
|
17
|
+
const useSyncSkuParamWithCurrentItem = (
|
|
18
|
+
familyLevel: number,
|
|
19
|
+
setMessage: (m: string | undefined) => void,
|
|
20
|
+
setLoading?: (l: boolean) => void
|
|
21
|
+
) => {
|
|
22
|
+
|
|
23
|
+
const cmmc = useCommerce()
|
|
24
|
+
|
|
25
|
+
const [skuParam, setSkuParam] = useQueryState('sku',
|
|
26
|
+
parseAsString.withDefault('').withOptions({ clearOnDefault: true })
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const [addParam, setAddParam] = useQueryState('add',
|
|
30
|
+
parseAsBoolean.withDefault(false).withOptions({ clearOnDefault: true })
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
|
|
35
|
+
return reaction(() => ({
|
|
36
|
+
specifiedCat: cmmc.selectedFamilies.length === 1 ? cmmc.selectedFamilies[0] : undefined,
|
|
37
|
+
currentItem: cmmc.currentItem
|
|
38
|
+
}),
|
|
39
|
+
({specifiedCat, currentItem}) => {
|
|
40
|
+
//console.log("REACTION: " + `CAT ID: ${family?.id} SKU: ${item?.sku}`)
|
|
41
|
+
if (currentItem) {
|
|
42
|
+
// if we set the currentItem w sku, then user selects other facets
|
|
43
|
+
if (specifiedCat && currentItem.familyId != specifiedCat.id ) {
|
|
44
|
+
cmmc.setCurrentItem(specifiedCat.products[0].sku)
|
|
45
|
+
}
|
|
46
|
+
setSkuParam(cmmc.currentItem!.sku)
|
|
47
|
+
}
|
|
48
|
+
else if (specifiedCat) {
|
|
49
|
+
cmmc.setCurrentItem(specifiedCat.products[0].sku)
|
|
50
|
+
setSkuParam(cmmc.currentItem!.sku)
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
}, [])
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
|
|
57
|
+
const setCurrentFamilyFromSku = (sku: string) => {
|
|
58
|
+
const toks: string[] = sku.split(sep.tok)
|
|
59
|
+
const fv: SelectedPaths = {}
|
|
60
|
+
// TODO: confirm that extra trailing nonsense tokens won't break selectPaths()
|
|
61
|
+
for (let i = 1; i < familyLevel; i++) {
|
|
62
|
+
if (i in toks) {
|
|
63
|
+
fv[i] = [toks[i]]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
cmmc.selectPaths(fv)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// setCI returns true if it's a recognized sku
|
|
70
|
+
if (skuParam && cmmc.setCurrentItem(skuParam)) {
|
|
71
|
+
if (addParam) {
|
|
72
|
+
if (cmmc.currentItem!.quantity === 0) {
|
|
73
|
+
cmmc.currentItem!.increment()
|
|
74
|
+
}
|
|
75
|
+
setAddParam(false)
|
|
76
|
+
}
|
|
77
|
+
setCurrentFamilyFromSku(skuParam)
|
|
78
|
+
setMessage(undefined)
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
setMessage(PLEASE_SELECT_FACETS)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
setLoading && setLoading(false)
|
|
85
|
+
}, [skuParam])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default useSyncSkuParamWithCurrentItem
|