@hanzo/commerce 5.1.3 → 6.1.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/components/{buy-item/select-category-item-card.tsx → buy/_to_deprecate_select-category-item-card.tsx} +22 -32
- package/components/{select-category-item-panel.tsx → buy/_to_deprecate_select-category-item-panel.tsx} +16 -22
- package/components/{buy-item/buy-item-popup.tsx → buy/_unused_buy-popup.tsx_} +4 -4
- package/components/{add-to-cart-widget.tsx → buy/add-to-cart-widget.tsx} +10 -6
- package/components/buy/buy-button.tsx +31 -0
- package/components/buy/buy-card.tsx +267 -0
- package/components/buy/buy-drawer.tsx +89 -0
- package/components/buy/buy-trigger-wrapper.tsx +20 -0
- package/components/{cart-accordian.tsx → cart/cart-accordian.tsx} +2 -1
- package/components/{cart-panel → cart/cart-panel}/cart-line-item.tsx +27 -14
- package/components/{cart-panel → cart/cart-panel}/index.tsx +12 -3
- package/components/{cart-panel → cart/cart-panel}/promo-code.tsx +3 -3
- package/components/{payment-step-form → checkout/payment-step-form}/contact-form.tsx +1 -1
- package/components/{payment-step-form → checkout/payment-step-form}/index.tsx +3 -3
- package/components/{payment-step-form → checkout/payment-step-form}/methods/bank-transfer.tsx +1 -1
- package/components/{payment-step-form → checkout/payment-step-form}/methods/card.tsx +4 -4
- package/components/{payment-step-form → checkout/payment-step-form}/methods/crypto.tsx +3 -3
- package/components/{payment-step-form → checkout/payment-step-form}/methods/index.ts +1 -1
- package/components/{shipping-step-form.tsx → checkout/shipping-step-form.tsx} +4 -4
- package/components/index.ts +20 -18
- package/components/item/item-media.tsx +51 -0
- package/components/item/product-card.tsx +48 -0
- package/components/{facet-values-widget → level-nodes-widget}/index.tsx +20 -19
- package/components/level-nodes-widget/node-image.tsx +31 -0
- package/components/select/carousel-selector.tsx +112 -0
- package/components/select/image-selector.tsx +162 -0
- package/components/select/radio-selector.tsx +125 -0
- package/package.json +3 -2
- package/service/context.tsx +4 -4
- package/service/impls/standalone/actual-line-item.ts +30 -16
- package/service/impls/standalone/index.ts +4 -4
- package/service/impls/standalone/standalone-service.ts +94 -64
- package/types/buy-ui-spec.ts +8 -0
- package/types/category.ts +6 -4
- package/types/commerce-service.ts +21 -16
- package/types/index.ts +3 -2
- package/types/item-selector.ts +34 -6
- package/types/line-item.ts +2 -0
- package/types/product.ts +5 -5
- package/types/tree-node.ts +24 -0
- package/util/buy-ui-conf.ts +34 -0
- package/util/index.ts +14 -11
- package/util/obs-string-mutator.ts +22 -0
- package/util/use-sync-sku-param-w-current-item.ts +5 -5
- package/components/buy-item/buy-item-button-wrapper.tsx +0 -27
- package/components/buy-item/buy-item-button.tsx +0 -34
- package/components/buy-item/buy-item-card.tsx +0 -92
- package/components/buy-item/buy-item-mobile-drawer.tsx +0 -54
- package/components/buy-item/select-category-and-item-widget.tsx +0 -83
- package/components/category-item-radio-selector.tsx +0 -55
- package/components/category-item-scroll-selector.tsx +0 -40
- package/components/facet-values-widget/facet-image.tsx +0 -41
- package/components/item-carousel.tsx +0 -80
- package/components/product-card.tsx +0 -79
- package/types/facet.ts +0 -35
- /package/components/{cart-icon.tsx → cart/cart-icon.tsx} +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icon-row.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/amex.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/diners-club.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/discover.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/jcb.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/mastercard.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/card-icons/visa.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/cc-button.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/btc.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/eth.tsx +0 -0
- /package/components/{payment-step-form → checkout/payment-step-form}/crypto-icons/usdt.tsx +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { observer } from 'mobx-react-lite'
|
|
4
|
+
|
|
5
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Image,
|
|
9
|
+
Label,
|
|
10
|
+
RadioGroup,
|
|
11
|
+
ScrollArea
|
|
12
|
+
} from '@hanzo/ui/primitives'
|
|
13
|
+
import { cn } from '@hanzo/ui/util'
|
|
14
|
+
|
|
15
|
+
import type { ItemSelectorProps, LineItem } from '../../types'
|
|
16
|
+
import { formatCurrencyValue } from '../../util'
|
|
17
|
+
|
|
18
|
+
const ImageRadioGroupItem = React.forwardRef<
|
|
19
|
+
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
|
20
|
+
Omit<React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>, 'value' | 'id'> & {
|
|
21
|
+
item: LineItem,
|
|
22
|
+
constrainTo: {w: number, h: number}
|
|
23
|
+
}
|
|
24
|
+
>(({
|
|
25
|
+
item,
|
|
26
|
+
constrainTo,
|
|
27
|
+
className,
|
|
28
|
+
...props
|
|
29
|
+
}, ref) => {
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<RadioGroupPrimitive.Item
|
|
33
|
+
ref={ref}
|
|
34
|
+
className={cn(
|
|
35
|
+
"ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
id={item.sku}
|
|
40
|
+
value={item.sku}
|
|
41
|
+
>
|
|
42
|
+
{item.img ? (
|
|
43
|
+
<Image def={item.img} constrainTo={constrainTo} preload className=''/>
|
|
44
|
+
) : ( // placeholder so things align
|
|
45
|
+
<div style={{height: constrainTo.h, width: constrainTo.w}}/>
|
|
46
|
+
)}
|
|
47
|
+
</RadioGroupPrimitive.Item>
|
|
48
|
+
)
|
|
49
|
+
})
|
|
50
|
+
ImageRadioGroupItem.displayName = 'ImageRadioGroupItem'
|
|
51
|
+
|
|
52
|
+
const ImageItemSelector: React.FC<ItemSelectorProps> = observer(({
|
|
53
|
+
items,
|
|
54
|
+
selectedItemRef: itemRef,
|
|
55
|
+
selectSku,
|
|
56
|
+
clx='',
|
|
57
|
+
itemClx='',
|
|
58
|
+
soleItemClx='',
|
|
59
|
+
showCategory=false,
|
|
60
|
+
showQuantity=false,
|
|
61
|
+
scrollList=false
|
|
62
|
+
}) => {
|
|
63
|
+
|
|
64
|
+
const LabelText: React.FC<{item: LineItem}> = ({item}) => (
|
|
65
|
+
(showCategory ? (item.categoryTitle + ', ' + item.optionLabel) : item.optionLabel) +
|
|
66
|
+
(showCategory ? ': ' : ', ') + formatCurrencyValue(item.price)
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
const ItemAndPrice: React.FC<{
|
|
70
|
+
item: LineItem
|
|
71
|
+
listBoxMode: boolean
|
|
72
|
+
selected: boolean
|
|
73
|
+
className?: string
|
|
74
|
+
}> = ({
|
|
75
|
+
item,
|
|
76
|
+
listBoxMode,
|
|
77
|
+
selected,
|
|
78
|
+
className=''
|
|
79
|
+
}) => (
|
|
80
|
+
<div className={cn(
|
|
81
|
+
'flex items-center',
|
|
82
|
+
className,
|
|
83
|
+
itemClx,
|
|
84
|
+
)}>
|
|
85
|
+
<ImageRadioGroupItem
|
|
86
|
+
item={item}
|
|
87
|
+
constrainTo={{h: 36, w: 72}} // Apple suggest 42px
|
|
88
|
+
className={
|
|
89
|
+
'mr-2 ' + (listBoxMode ? '' :
|
|
90
|
+
'border-transparent border-2 rounded-sm data-[state=checked]:border-foreground')
|
|
91
|
+
}
|
|
92
|
+
/>
|
|
93
|
+
<Label htmlFor={item.sku} className={selected && listBoxMode ? 'text-accent' : ''}>
|
|
94
|
+
<LabelText item={item} />
|
|
95
|
+
</Label>
|
|
96
|
+
</div>
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
const Item: React.FC<{
|
|
100
|
+
item: LineItem
|
|
101
|
+
selected: boolean
|
|
102
|
+
listBoxMode: boolean
|
|
103
|
+
clx?: string
|
|
104
|
+
}> = ({
|
|
105
|
+
item,
|
|
106
|
+
selected,
|
|
107
|
+
listBoxMode,
|
|
108
|
+
clx=''
|
|
109
|
+
}) => {
|
|
110
|
+
|
|
111
|
+
const outClx = [
|
|
112
|
+
(listBoxMode ? 'border-b border-muted-3 py-1' : 'mb-3'),
|
|
113
|
+
(selected && listBoxMode ? 'border border-foreground rounded-sm' : ''),
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
return (showQuantity ? (
|
|
117
|
+
<div key={item.sku} className={cn('flex flex-row items-center', ...outClx, clx )}>
|
|
118
|
+
<ItemAndPrice item={item} selected={selected} listBoxMode={listBoxMode} className='grow'/>
|
|
119
|
+
<div className='grow-0 shrink-0 font-semibold text-sm leading-none px-2'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
|
|
120
|
+
</div>
|
|
121
|
+
) : (
|
|
122
|
+
<ItemAndPrice
|
|
123
|
+
key={item.sku}
|
|
124
|
+
item={item}
|
|
125
|
+
selected={selected}
|
|
126
|
+
listBoxMode={listBoxMode}
|
|
127
|
+
className={cn(...outClx,
|
|
128
|
+
listBoxMode ? '' : 'mb-1',
|
|
129
|
+
clx)}
|
|
130
|
+
/>
|
|
131
|
+
))
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return items.length > 1 ? (
|
|
135
|
+
<RadioGroup
|
|
136
|
+
className={cn('flex flex-col gap-0',
|
|
137
|
+
(scrollList ? 'shrink min-h-0' : ''),
|
|
138
|
+
clx,
|
|
139
|
+
)}
|
|
140
|
+
onValueChange={selectSku}
|
|
141
|
+
value={itemRef.item ? itemRef.item.sku : ''}
|
|
142
|
+
>
|
|
143
|
+
{scrollList ? (
|
|
144
|
+
<ScrollArea className='mt-2 w-full h-full py-0 border border-muted-2 rounded-sm '>
|
|
145
|
+
{items.map((item) => (
|
|
146
|
+
<Item item={item} listBoxMode={true} selected={itemRef.item?.sku === item.sku}/>
|
|
147
|
+
))}
|
|
148
|
+
</ScrollArea>
|
|
149
|
+
) : (<>
|
|
150
|
+
{items.map((item) => (
|
|
151
|
+
<Item item={item} listBoxMode={false} selected={itemRef.item?.sku === item.sku}/>
|
|
152
|
+
))}
|
|
153
|
+
</>)}
|
|
154
|
+
</RadioGroup>
|
|
155
|
+
) : (
|
|
156
|
+
<div className={soleItemClx}>
|
|
157
|
+
<LabelText item={items[0]} />
|
|
158
|
+
</div>
|
|
159
|
+
)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
export default ImageItemSelector
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { observer } from 'mobx-react-lite'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Label,
|
|
7
|
+
RadioGroup,
|
|
8
|
+
RadioGroupItem,
|
|
9
|
+
ScrollArea
|
|
10
|
+
} from '@hanzo/ui/primitives'
|
|
11
|
+
import { cn } from '@hanzo/ui/util'
|
|
12
|
+
|
|
13
|
+
import type { ItemSelectorProps, LineItem } from '../../types'
|
|
14
|
+
import { formatCurrencyValue } from '../../util'
|
|
15
|
+
|
|
16
|
+
const RadioItemSelector: React.FC<ItemSelectorProps> = observer(({
|
|
17
|
+
items,
|
|
18
|
+
selectedItemRef: itemRef,
|
|
19
|
+
selectSku,
|
|
20
|
+
clx='',
|
|
21
|
+
itemClx='',
|
|
22
|
+
soleItemClx='',
|
|
23
|
+
showCategory=false,
|
|
24
|
+
showQuantity=false,
|
|
25
|
+
scrollList=false
|
|
26
|
+
}) => {
|
|
27
|
+
|
|
28
|
+
const LabelText: React.FC<{item: LineItem}> = ({item}) => (
|
|
29
|
+
(showCategory ? (item.categoryTitle + ', ' + item.optionLabel) : item.optionLabel) +
|
|
30
|
+
(showCategory ? ': ' : ', ') + formatCurrencyValue(item.price)
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
const ItemAndPrice: React.FC<{
|
|
34
|
+
item: LineItem
|
|
35
|
+
listBoxMode: boolean
|
|
36
|
+
selected: boolean
|
|
37
|
+
className?: string
|
|
38
|
+
}> = ({
|
|
39
|
+
item,
|
|
40
|
+
listBoxMode,
|
|
41
|
+
selected,
|
|
42
|
+
className=''
|
|
43
|
+
}) => (
|
|
44
|
+
<div className={cn(
|
|
45
|
+
'flex items-center',
|
|
46
|
+
className,
|
|
47
|
+
itemClx,
|
|
48
|
+
)}>
|
|
49
|
+
<RadioGroupItem
|
|
50
|
+
value={item.sku}
|
|
51
|
+
larger
|
|
52
|
+
id={item.sku}
|
|
53
|
+
className={'mr-2 ' + (listBoxMode ? 'hidden' : '')}
|
|
54
|
+
/>
|
|
55
|
+
<Label htmlFor={item.sku} className={selected ? 'text-accent' : ''}>
|
|
56
|
+
<LabelText item={item} />
|
|
57
|
+
</Label>
|
|
58
|
+
</div>
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const Item: React.FC<{
|
|
62
|
+
item: LineItem
|
|
63
|
+
selected: boolean
|
|
64
|
+
listBoxMode: boolean
|
|
65
|
+
clx?: string
|
|
66
|
+
}> = ({
|
|
67
|
+
item,
|
|
68
|
+
selected,
|
|
69
|
+
listBoxMode,
|
|
70
|
+
clx=''
|
|
71
|
+
}) => {
|
|
72
|
+
|
|
73
|
+
const outClx = [
|
|
74
|
+
'h-10',
|
|
75
|
+
(listBoxMode ? 'border-b border-muted-3 py-1 pl-2' : 'mb-3'),
|
|
76
|
+
(selected && listBoxMode ? 'border border-foreground rounded-sm' : ''),
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
return (showQuantity ? (
|
|
80
|
+
<div key={item.sku} className={cn('flex flex-row items-center', ...outClx, clx )}>
|
|
81
|
+
<ItemAndPrice item={item} selected={selected} listBoxMode={listBoxMode} className='grow'/>
|
|
82
|
+
<div className='grow-0 shrink-0 font-semibold text-sm leading-none px-2'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
|
|
83
|
+
</div>
|
|
84
|
+
) : (
|
|
85
|
+
<ItemAndPrice
|
|
86
|
+
key={item.sku}
|
|
87
|
+
item={item}
|
|
88
|
+
selected={selected}
|
|
89
|
+
listBoxMode={listBoxMode}
|
|
90
|
+
className={cn(...outClx,
|
|
91
|
+
listBoxMode ? '' : 'mb-1',
|
|
92
|
+
clx)}
|
|
93
|
+
/>
|
|
94
|
+
))
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return items.length > 1 ? (
|
|
98
|
+
<RadioGroup
|
|
99
|
+
className={cn('flex flex-col gap-0',
|
|
100
|
+
(scrollList ? 'shrink min-h-0' : ''),
|
|
101
|
+
clx,
|
|
102
|
+
)}
|
|
103
|
+
onValueChange={selectSku}
|
|
104
|
+
value={itemRef.item ? itemRef.item.sku : ''}
|
|
105
|
+
>
|
|
106
|
+
{scrollList ? (
|
|
107
|
+
<ScrollArea className='mt-2 w-full h-full py-0 border border-muted-2 rounded-sm '>
|
|
108
|
+
{items.map((item) => (
|
|
109
|
+
<Item item={item} listBoxMode={true} selected={itemRef.item?.sku === item.sku}/>
|
|
110
|
+
))}
|
|
111
|
+
</ScrollArea>
|
|
112
|
+
) : (<>
|
|
113
|
+
{items.map((item) => (
|
|
114
|
+
<Item item={item} listBoxMode={false} selected={itemRef.item?.sku === item.sku}/>
|
|
115
|
+
))}
|
|
116
|
+
</>)}
|
|
117
|
+
</RadioGroup>
|
|
118
|
+
) : (
|
|
119
|
+
<div className={soleItemClx}>
|
|
120
|
+
<LabelText item={items[0]} />
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
export default RadioItemSelector
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/commerce",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
4
4
|
"description": "Library with shopping cart components.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
@@ -40,8 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"@hanzo/auth": "^2.3.3",
|
|
43
|
-
"@hanzo/ui": "^3.
|
|
43
|
+
"@hanzo/ui": "^3.2.0",
|
|
44
44
|
"@hookform/resolvers": "^3.3.4",
|
|
45
|
+
"@radix-ui/react-radio-group": "^1.1.3",
|
|
45
46
|
"firebase": "^10.8.0",
|
|
46
47
|
"lucide-react": "^0.307.0",
|
|
47
48
|
"mobx": "^6.12.0",
|
package/service/context.tsx
CHANGED
|
@@ -9,7 +9,7 @@ enableStaticRendering(typeof window === "undefined")
|
|
|
9
9
|
import type CommerceService from '../types/commerce-service'
|
|
10
10
|
import type { ServiceOptions } from '..'
|
|
11
11
|
import getServiceSingleton from './impls'
|
|
12
|
-
import type { Category,
|
|
12
|
+
import type { Category, ProductTreeNode } from '../types'
|
|
13
13
|
|
|
14
14
|
const CommerceServiceContext = createContext<CommerceService | undefined>(undefined)
|
|
15
15
|
|
|
@@ -20,17 +20,17 @@ const useCommerce = (): CommerceService => {
|
|
|
20
20
|
|
|
21
21
|
const CommerceServiceProvider: React.FC<PropsWithChildren & {
|
|
22
22
|
productsByCategory: Category[]
|
|
23
|
-
|
|
23
|
+
rootNode: ProductTreeNode
|
|
24
24
|
options?: ServiceOptions
|
|
25
25
|
}> = ({
|
|
26
26
|
children,
|
|
27
27
|
productsByCategory,
|
|
28
|
-
|
|
28
|
+
rootNode,
|
|
29
29
|
options
|
|
30
30
|
}) => {
|
|
31
31
|
|
|
32
32
|
// TODO: Inject Promo fixture here
|
|
33
|
-
const serviceRef = useRef<CommerceService>(getServiceSingleton(productsByCategory,
|
|
33
|
+
const serviceRef = useRef<CommerceService>(getServiceSingleton(productsByCategory, rootNode, options))
|
|
34
34
|
return (
|
|
35
35
|
<CommerceServiceContext.Provider value={serviceRef.current}>
|
|
36
36
|
{children}
|
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
observable,
|
|
6
6
|
} from 'mobx'
|
|
7
7
|
|
|
8
|
-
import type { VideoDef } from '@hanzo/ui/types'
|
|
8
|
+
import type { ImageDef, VideoDef } from '@hanzo/ui/types'
|
|
9
9
|
|
|
10
|
-
import type { Product, LineItem } from '../../../types'
|
|
10
|
+
import type { Product, LineItem, CommerceService } from '../../../types'
|
|
11
11
|
|
|
12
12
|
interface ActualLineItemSnapshot {
|
|
13
13
|
sku: string
|
|
@@ -26,12 +26,13 @@ class ActualLineItem
|
|
|
26
26
|
|
|
27
27
|
id: string
|
|
28
28
|
sku: string
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
fullTitle?: string
|
|
30
|
+
optionLabel: string
|
|
31
|
+
categoryTitle: string
|
|
31
32
|
categoryId: string
|
|
32
33
|
desc?: string
|
|
33
34
|
price: number
|
|
34
|
-
img?:
|
|
35
|
+
img?: ImageDef
|
|
35
36
|
video?: VideoDef
|
|
36
37
|
animation?: string
|
|
37
38
|
timeAdded: number = 0 // timeAdded of being added to cart
|
|
@@ -39,8 +40,9 @@ class ActualLineItem
|
|
|
39
40
|
constructor(prod: Product, snap?: ActualLineItemSnapshot) {
|
|
40
41
|
this.id = prod.id
|
|
41
42
|
this.sku = prod.sku
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
43
|
+
this.fullTitle = prod.fullTitle
|
|
44
|
+
this.optionLabel = prod.optionLabel
|
|
45
|
+
this.categoryTitle = prod.categoryTitle
|
|
44
46
|
this.categoryId = prod.categoryId
|
|
45
47
|
this.desc = prod.desc
|
|
46
48
|
this.price = prod.price
|
|
@@ -58,20 +60,32 @@ class ActualLineItem
|
|
|
58
60
|
timeAdded: observable,
|
|
59
61
|
canDecrement: computed,
|
|
60
62
|
isInCart: computed,
|
|
61
|
-
|
|
63
|
+
title: computed,
|
|
62
64
|
increment: action,
|
|
63
65
|
decrement: action,
|
|
64
66
|
})
|
|
65
67
|
}
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
get title(): string {
|
|
70
|
+
return this.fullTitle ? this.fullTitle : (this.categoryTitle + ', ' + this.optionLabel)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
takeSnapshot = (cmmc: CommerceService): ActualLineItemSnapshot => {
|
|
74
|
+
|
|
75
|
+
const title = this.fullTitle ?
|
|
76
|
+
this.fullTitle
|
|
77
|
+
:
|
|
78
|
+
((cmmc.getCategory(this.categoryId)?.title ?? this.categoryTitle) + ', ' + this.optionLabel)
|
|
79
|
+
|
|
80
|
+
return({
|
|
81
|
+
sku: this.sku,
|
|
82
|
+
categoryId: this.categoryId,
|
|
83
|
+
title,
|
|
84
|
+
price: this.price,
|
|
85
|
+
quantity: this.qu,
|
|
86
|
+
timeAdded: this.timeAdded
|
|
87
|
+
} satisfies ActualLineItemSnapshot)
|
|
88
|
+
}
|
|
75
89
|
|
|
76
90
|
get canDecrement(): boolean { return this.qu > 0 }
|
|
77
91
|
get quantity(): number {return this.qu}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { enableStaticRendering } from 'mobx-react-lite'
|
|
2
2
|
|
|
3
|
-
import type { CommerceService, Category,
|
|
3
|
+
import type { CommerceService, Category, ProductTreeNode } from '../../../types'
|
|
4
4
|
import StandaloneService, {type StandaloneServiceOptions} from './standalone-service'
|
|
5
5
|
|
|
6
6
|
import { readSnapshot, listenAndWriteSnapshots } from './localStorage'
|
|
@@ -19,7 +19,7 @@ let instance: StandaloneService | undefined = undefined
|
|
|
19
19
|
|
|
20
20
|
export const getInstance = (
|
|
21
21
|
categories: Category[],
|
|
22
|
-
|
|
22
|
+
rootNode: ProductTreeNode,
|
|
23
23
|
options?: StandaloneServiceOptions
|
|
24
24
|
): CommerceService => {
|
|
25
25
|
|
|
@@ -31,7 +31,7 @@ export const getInstance = (
|
|
|
31
31
|
//_log("NEW INSTANCE FOR SERVER")
|
|
32
32
|
return new StandaloneService(
|
|
33
33
|
categories,
|
|
34
|
-
|
|
34
|
+
rootNode,
|
|
35
35
|
options
|
|
36
36
|
)
|
|
37
37
|
}
|
|
@@ -42,7 +42,7 @@ export const getInstance = (
|
|
|
42
42
|
const snapShot = readSnapshot()
|
|
43
43
|
instance = new StandaloneService(
|
|
44
44
|
categories,
|
|
45
|
-
|
|
45
|
+
rootNode,
|
|
46
46
|
options,
|
|
47
47
|
snapShot
|
|
48
48
|
)
|