@hanzo/commerce 2.1.0 → 3.0.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.
Files changed (51) hide show
  1. package/components/add-to-cart-widget.tsx +3 -3
  2. package/components/buy-item/buy-item-button.tsx +28 -0
  3. package/components/buy-item/buy-item-card.tsx +82 -0
  4. package/components/buy-item/buy-item-popup.tsx +38 -0
  5. package/components/{select-category-and-item-widget.tsx → buy-item/select-category-and-item-widget.tsx} +4 -4
  6. package/components/buy-item/select-category-item-card.tsx +111 -0
  7. package/components/{cart-line-item.tsx → cart-panel/cart-line-item.tsx} +4 -3
  8. package/components/{cart.tsx → cart-panel/index.tsx} +24 -18
  9. package/components/category-item-ios-wheel-selector.tsx +60 -0
  10. package/components/category-item-radio-selector.tsx +55 -0
  11. package/components/{checkout → checkout-panel}/confirm-order.tsx +3 -2
  12. package/components/{checkout → checkout-panel}/index.tsx +10 -5
  13. package/components/{checkout → checkout-panel}/payment/index.tsx +2 -1
  14. package/components/{checkout → checkout-panel}/payment/pay-with-card.tsx +8 -3
  15. package/components/{checkout → checkout-panel}/payment/pay-with-crypto.tsx +2 -3
  16. package/components/{facet-toggles-widget → facet-values-widget}/facet-image.tsx +7 -3
  17. package/components/{facet-toggles-widget → facet-values-widget}/index.tsx +7 -5
  18. package/components/index.ts +11 -9
  19. package/components/{select-item-in-category-view.tsx → select-category-item-panel.tsx} +72 -76
  20. package/index.ts +2 -2
  21. package/package.json +8 -3
  22. package/service/context.tsx +4 -4
  23. package/service/impls/standalone/index.ts +4 -4
  24. package/service/impls/standalone/standalone-service.ts +117 -38
  25. package/types/category.ts +3 -2
  26. package/types/commerce-service.ts +17 -4
  27. package/types/facet.ts +1 -3
  28. package/types/index.ts +3 -1
  29. package/types/item-selector.ts +14 -0
  30. package/util/index.ts +29 -0
  31. package/util/use-sync-sku-param-w-current-item.ts +4 -1
  32. package/blocks/components/commerce-cat-and-item-block.tsx +0 -13
  33. package/blocks/def/commerce-cat-and-item-block.ts +0 -9
  34. package/components/facets-widget.tsx +0 -55
  35. package/components/product-selection-mobile-picker.tsx +0 -78
  36. package/components/product-selection-radio-group.tsx +0 -38
  37. /package/components/{checkout → checkout-panel}/countries.ts +0 -0
  38. /package/components/{checkout → checkout-panel}/icons/btc.tsx +0 -0
  39. /package/components/{checkout → checkout-panel}/icons/eth.tsx +0 -0
  40. /package/components/{checkout → checkout-panel}/icons/usdt.tsx +0 -0
  41. /package/components/{checkout → checkout-panel}/payment/contact-info.tsx +0 -0
  42. /package/components/{checkout → checkout-panel}/payment/pay-with-bank-transfer.tsx +0 -0
  43. /package/components/{checkout → checkout-panel}/payment/payment-methods/amex.tsx +0 -0
  44. /package/components/{checkout → checkout-panel}/payment/payment-methods/diners-club.tsx +0 -0
  45. /package/components/{checkout → checkout-panel}/payment/payment-methods/discover.tsx +0 -0
  46. /package/components/{checkout → checkout-panel}/payment/payment-methods/index.tsx +0 -0
  47. /package/components/{checkout → checkout-panel}/payment/payment-methods/jcb.tsx +0 -0
  48. /package/components/{checkout → checkout-panel}/payment/payment-methods/mastercard.tsx +0 -0
  49. /package/components/{checkout → checkout-panel}/payment/payment-methods/visa.tsx +0 -0
  50. /package/components/{checkout → checkout-panel}/shipping-info.tsx +0 -0
  51. /package/components/{checkout → checkout-panel}/thank-you.tsx +0 -0
@@ -26,7 +26,7 @@ const AddToCartWidget: React.FC<{
26
26
  size='xs'
27
27
  }) => {
28
28
 
29
- const iconClx = ghost ? 'h-4 w-4 md:h-3 md:w-3 text-muted-3 hover:text-foreground' : 'h-5 w-5 mr-1'
29
+ const iconClx = ghost ? 'h-4 w-4 md:h-3 md:w-3 text-muted-3 hover:text-foreground' : 'h-5 w-7 px-1'
30
30
  const digitClx = ghost ? 'px-2 md:px-0.5' : 'sm:px-2 font-bold '
31
31
 
32
32
  if (disabled) {
@@ -44,7 +44,7 @@ const AddToCartWidget: React.FC<{
44
44
  size={size}
45
45
  variant={ghost ? 'ghost' : 'secondary'}
46
46
  rounded={ghost ? 'full' : 'xl'}
47
- className={cn('px-1 lg:min-w-0 lg:px-2 xs:grow xs:justify-end', buttonClx)}
47
+ className={cn('px-1 lg:min-w-0 lg:px-2 xs:justify-end', buttonClx)}
48
48
  key='left'
49
49
  onClick={item.decrement.bind(item)}
50
50
  >
@@ -60,7 +60,7 @@ const AddToCartWidget: React.FC<{
60
60
  size={size}
61
61
  variant={ghost ? 'ghost' : 'secondary'}
62
62
  rounded={ghost ? 'full' : 'xl'}
63
- className={cn('px-1 lg:min-w-0 lg:px-2 xs:grow xs:justify-start', buttonClx)}
63
+ className={cn('px-1 lg:min-w-0 lg:px-2 xs:justify-start', buttonClx)}
64
64
  onClick={item.increment.bind(item)}
65
65
  key='right'
66
66
  >
@@ -0,0 +1,28 @@
1
+ 'use client'
2
+ import React, {type PropsWithChildren} from 'react'
3
+
4
+ import { type ButtonVariants, type ButtonSizes, Button } from '@hanzo/ui/primitives'
5
+
6
+ import BuyItemPopup from './buy-item-popup'
7
+
8
+ const BuyItemButton: React.FC<PropsWithChildren & {
9
+ skuPath: string
10
+ variant? : ButtonVariants
11
+ size?: ButtonSizes
12
+ /* rounded?: ButtonRounded // wait for version bump*/
13
+ className?: string
14
+ popupClx?: string
15
+ }> = ({
16
+ skuPath,
17
+ variant,
18
+ size,
19
+ children,
20
+ className='',
21
+ popupClx=''
22
+ }) => (
23
+ <BuyItemPopup skuPath={skuPath} popupClx={popupClx}>
24
+ <Button size={size} variant={variant} className={className}>{children}</Button>
25
+ </BuyItemPopup>
26
+ )
27
+
28
+ export default BuyItemButton
@@ -0,0 +1,82 @@
1
+ 'use client'
2
+ import React, { useRef, useEffect } from 'react'
3
+ import { autorun } from 'mobx'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import { cn } from '@hanzo/ui/util'
7
+
8
+ import type { FacetsValue } from '../../types'
9
+ import { useCommerce } from '../../service/context'
10
+ import { getFacetValuesMutator } from '../../util'
11
+ import FacetValuesWidget from '../facet-values-widget'
12
+ import SelectCategoryItemCard from './select-category-item-card'
13
+
14
+
15
+ const BuyItemCard: React.FC<{
16
+ skuPath: string
17
+ className?: string
18
+ }> = observer(({
19
+ skuPath,
20
+ className=''
21
+ }) => {
22
+
23
+ const cmmc = useCommerce()
24
+ const levelRef = useRef<number>(-1)
25
+
26
+ const cat = cmmc.getCategory(skuPath)
27
+ const facets = cat ? undefined : cmmc.getFacetValuesAtSkuPath(skuPath)
28
+
29
+ useEffect(() => {
30
+
31
+ if (facets) {
32
+ const toks = skuPath.split('-')
33
+ const levelSpecified = toks.length - 1
34
+ const fsv: FacetsValue = {}
35
+ for (let level = 1; level <= levelSpecified; level++ ) {
36
+ fsv[level] = [toks[level]]
37
+ }
38
+ fsv[levelSpecified + 1] = [facets[0].value]
39
+ levelRef.current = levelSpecified
40
+ cmmc.setFacets(fsv)
41
+ }
42
+ return autorun(() => {
43
+ const cats = cmmc.specifiedCategories
44
+ // Original cat was legit
45
+ if (cat && (cats.length === 0 || cats[0].id !== cat.id)) {
46
+ if (!cmmc.currentItem || cmmc.currentItem.categoryId !== cat.id) {
47
+ cmmc.setCurrentItem(cat.products[0].sku)
48
+ }
49
+ }
50
+ else if (cats.length > 0) {
51
+ if (!cmmc.currentItem || cmmc.currentItem.categoryId !== cats[0].id) {
52
+ cmmc.setCurrentItem(cats[0].products[0].sku)
53
+ }
54
+ }
55
+ })
56
+ }, [cat, facets])
57
+
58
+ return (
59
+ <div className={className} >
60
+ {facets && levelRef.current > 0 && (
61
+ <FacetValuesWidget
62
+ className={cn('grid gap-0 ' + `grid-cols-${facets.length}` + ' self-start ', 'border-b mb-2 -mr-2 -ml-2')}
63
+ isMobile={false}
64
+ mutator={getFacetValuesMutator(levelRef.current + 1, cmmc)}
65
+ itemClx='flex-col h-auto gap-0 pb-1 pt-3 px-3'
66
+ buttonClx='h-auto !rounded-bl-none !rounded-br-none !rounded-tl-lg !rounded-tr-lg '
67
+ facetValues={facets}
68
+ />
69
+ )}
70
+ {cmmc.specifiedCategories[0] && (
71
+ <SelectCategoryItemCard
72
+ noTitle
73
+ category={cmmc.specifiedCategories[0]}
74
+ selectedItemRef={cmmc /* ...conveniently. :) */ }
75
+ selectSku={cmmc.setCurrentItem.bind(cmmc)}
76
+ />
77
+ )}
78
+ </div >
79
+ )
80
+ })
81
+
82
+ export default BuyItemCard
@@ -0,0 +1,38 @@
1
+ 'use client'
2
+ import React, {type PropsWithChildren} from 'react'
3
+
4
+ import { X } from 'lucide-react'
5
+
6
+ import {
7
+ Popover,
8
+ PopoverContent,
9
+ PopoverTrigger,
10
+ PopoverClose
11
+ } from "@hanzo/ui/primitives"
12
+
13
+ import { cn } from '@hanzo/ui/util'
14
+
15
+ import BuyItemCard from './buy-item-card'
16
+
17
+ const BuyItemPopup: React.FC<PropsWithChildren & {
18
+ skuPath: string
19
+ popupClx?: string
20
+ cardClx?: string
21
+ }> = ({
22
+ skuPath,
23
+ children,
24
+ popupClx='',
25
+ cardClx='',
26
+ }) => (
27
+ <Popover>
28
+ <PopoverTrigger asChild>
29
+ {children}
30
+ </PopoverTrigger>
31
+ <PopoverContent className={cn('relative flex flex-col p-0 px-4 pb-4 pt-2', popupClx)}>
32
+ <PopoverClose className='absolute z-20 right-2 top-2 self-end hover:bg-level-3 text-muted hover:text-accent p-1 rounded-full'><X className='w-5 h-5'/></PopoverClose>
33
+ <BuyItemCard skuPath={skuPath} className={cn("w-full relative ", cardClx)}/>
34
+ </PopoverContent>
35
+ </Popover>
36
+ )
37
+
38
+ export default BuyItemPopup
@@ -5,11 +5,11 @@ import { observer } from 'mobx-react-lite'
5
5
  import { ApplyTypography, ListBox } from '@hanzo/ui/primitives'
6
6
  import { cn } from '@hanzo/ui/util'
7
7
 
8
- import type { FacetValueDesc, FacetsValue, LineItem } from '../types'
9
- import { useCommerce } from '../service/context'
10
- import { formatPrice } from '../util'
8
+ import type { FacetValueDesc, FacetsValue, LineItem } from '../../types'
9
+ import { useCommerce } from '../../service/context'
10
+ import { formatPrice } from '../../util'
11
11
 
12
- import FacetTogglesWidget from './facet-toggles-widget'
12
+ import FacetTogglesWidget from '../facet-values-widget'
13
13
 
14
14
  const formatItem = (item: LineItem, withQuantity: boolean = false): string => (
15
15
  `${item.titleAsOption}, ${formatPrice(item.price)}${(withQuantity && item.quantity > 0) ? ` (${item.quantity})` : ''}`
@@ -0,0 +1,111 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { observer } from 'mobx-react-lite'
4
+
5
+ import { cn } from '@hanzo/ui/util'
6
+ import { Skeleton } from '@hanzo/ui/primitives'
7
+
8
+ import type { ItemSelector, LineItem } from '../../types'
9
+
10
+ import AddToCartWidget from '../add-to-cart-widget'
11
+ import CategoryItemRadioSelector from '../category-item-radio-selector'
12
+ import CategoryItemIOSWheelSelector from '../category-item-ios-wheel-selector'
13
+ import { formatPrice } from '../../util'
14
+
15
+ const SelectCategoryItemCard: React.FC<React.HTMLAttributes<HTMLDivElement> & ItemSelector & {
16
+ isLoading?: boolean
17
+ mobile?: boolean
18
+ noTitle?: boolean
19
+ }> = /* NOT observer */({
20
+ category,
21
+ selectedItemRef: selItemRef,
22
+ selectSku,
23
+ className,
24
+ isLoading = false,
25
+ mobile = false,
26
+ noTitle = false,
27
+ ...props
28
+ }) => {
29
+
30
+ const soleOption = category.products.length === 1
31
+
32
+ const SelectProductComp: React.FC<{ className?: string }> = ({ className = '' }) => {
33
+
34
+ if (soleOption) {
35
+ const item = category.products[0] as LineItem
36
+ return (
37
+ <p >{item.titleAsOption + ', ' + formatPrice(item.price) + (item.quantity > 0 ? `(${item.quantity})` : '')}</p>
38
+ )
39
+ }
40
+ const mobilePicker = (mobile && category.products.length > 6)
41
+
42
+ return (
43
+ <div /* id='CV_AVAIL_AMOUNTS' */ className={cn(
44
+ 'sm:w-pr-80 sm:mx-auto md:w-full flex flex-col justify-start items-center',
45
+ className
46
+ )}>
47
+ {!noTitle && (<div className={'h-[1px] bg-muted-3 ' + (mobilePicker ? 'w-pr-55' : 'w-pr-60') } /> )}
48
+ {mobilePicker ? (
49
+ <CategoryItemIOSWheelSelector
50
+ category={category}
51
+ selectedItemRef={selItemRef}
52
+ selectSku={selectSku}
53
+ height={180}
54
+ itemHeight={30}
55
+ outerClx='mb-4'
56
+ />
57
+ ) : (
58
+ <CategoryItemRadioSelector
59
+ category={category}
60
+ selectedItemRef={selItemRef}
61
+ selectSku={selectSku}
62
+ groupClx='mt-2'
63
+ itemClx='flex flex-row gap-2.5 items-center'
64
+ />
65
+ )}
66
+ </div>
67
+ )
68
+ }
69
+
70
+ const AddToCartComp: React.FC<{ className?: string }> = observer(({ className = '' }) => (
71
+ // TODO disable if nothing selected
72
+ (selItemRef.item && !isLoading) && (
73
+ <AddToCartWidget size='default' item={selItemRef.item} className={cn('lg:min-w-[160px] lg:mx-auto', className)}/>
74
+ )
75
+ ))
76
+
77
+ const TitleArea: React.FC<{ className?: string }> = observer(({ className = '' }) => (
78
+
79
+ isLoading ? (<Skeleton className={'h-8 w-full ' + className} />) : (
80
+
81
+ <div className={cn('text-center flex flex-col justify-start items-center', className)}>
82
+ <p className='font-nav text-center'>{category.title}</p>
83
+ </div>
84
+
85
+ )))
86
+
87
+ return mobile ? (
88
+ <div /* id='CV_OUTER' */
89
+ className={cn(
90
+ 'w-full h-[calc(100svh-96px)] max-h-[700px] flex flex-col justify-between ' +
91
+ 'items-stretch gap-[4vh] mt-[2vh] pb-[6vh]',
92
+ className
93
+ )}
94
+ {...props}
95
+ >
96
+ {!noTitle && (<TitleArea className='grow pt-3 mb-0' />)}
97
+ <SelectProductComp className='mb-[3vh]' />
98
+ <AddToCartComp className='w-pr-70 mx-auto' />
99
+ </div>
100
+ ) : (
101
+ <div className={cn('', className)} {...props}>
102
+ {!noTitle && (<TitleArea className='' />)}
103
+ <div className='flex flex-col justify-start items-center gap-4'>
104
+ <SelectProductComp />
105
+ <AddToCartComp className='' />
106
+ </div>
107
+ </div>
108
+ )
109
+ }
110
+
111
+ export default SelectCategoryItemCard
@@ -4,9 +4,10 @@ import Image from 'next/image'
4
4
 
5
5
  import { cn } from '@hanzo/ui/util'
6
6
 
7
- import type { LineItem } from '../types'
8
- import AddToCartWidget from './add-to-cart-widget'
9
- import { formatPrice } from '../util'
7
+ import type { LineItem } from '../../types'
8
+ import { formatPrice } from '../../util'
9
+
10
+ import AddToCartWidget from '../add-to-cart-widget'
10
11
 
11
12
  const IMG_SIZE=40
12
13
 
@@ -5,32 +5,32 @@ import { observer } from 'mobx-react-lite'
5
5
  import { Button } from '@hanzo/ui/primitives'
6
6
  import { cn } from '@hanzo/ui/util'
7
7
 
8
- import { useCommerce } from '../service/context'
9
- import { formatPrice } from '../util'
8
+ import { useCommerce } from '../../service/context'
9
+ import { formatPrice } from '../../util'
10
10
 
11
11
  import CartLineItem from './cart-line-item'
12
- import { Checkout } from '.'
12
+ import CheckoutPanel from '../checkout-panel'
13
13
 
14
- const Cart: React.FC<PropsWithChildren & {
14
+ const CartPanel: React.FC<PropsWithChildren & {
15
15
  className?: string
16
16
  isMobile?: boolean,
17
- hideCheckout?: boolean
17
+ noCheckout?: boolean
18
18
  }> = observer(({
19
19
  /** Children is the heading area. */
20
20
  children,
21
21
  className='',
22
22
  isMobile=false,
23
- hideCheckout=false
23
+ noCheckout=false
24
24
  }) => {
25
- const [isCheckoutOpen, setIsCheckoutOpen] = useState(false)
25
+
26
+ const [checkoutOpen, setCheckoutOpen] = useState<boolean>(false)
26
27
  const cmmc = useCommerce()
27
28
 
28
29
  return (
29
30
  <div className={cn('border p-4 rounded-lg', className)}>
30
31
  {children}
31
32
  <div className='mt-2 w-full'>
32
- {!!children && <div className='h-[1px] w-pr-80 mb-4 mx-auto bg-muted-3'/>}
33
- {cmmc.cartItems.length === 0 ? (
33
+ {cmmc.cartEmpty ? (
34
34
  <p className='text-center mt-4'>No items in cart</p>
35
35
  ) : (<>
36
36
  {cmmc.cartItems.map((item, i) => (
@@ -39,16 +39,22 @@ const Cart: React.FC<PropsWithChildren & {
39
39
  <p className='mt-6 text-right border-t pt-1'>TOTAL: <span className='font-semibold'>{cmmc.cartTotal === 0 ? '0' : formatPrice(cmmc.cartTotal)}</span></p>
40
40
  </>)}
41
41
  </div>
42
- {!hideCheckout && (
43
- <>
44
- {cmmc.cartItems.length > 0 && (
45
- <Button size='lg' variant='secondary' rounded='lg' className='mt-12 mx-auto' onClick={() => setIsCheckoutOpen(!isCheckoutOpen)}>Checkout</Button>
46
- )}
47
- {isCheckoutOpen && <Checkout toggleCheckout={() => setIsCheckoutOpen(!isCheckoutOpen)}/>}
48
- </>
49
- )}
42
+ {!noCheckout && (<>
43
+ {!cmmc.cartEmpty && (
44
+ <Button
45
+ size='lg'
46
+ variant='secondary'
47
+ rounded='lg'
48
+ className='mt-12 mx-auto'
49
+ onClick={() => setCheckoutOpen(!checkoutOpen)}
50
+ >
51
+ Checkout
52
+ </Button>
53
+ )}
54
+ {checkoutOpen && <CheckoutPanel close={() => {setCheckoutOpen(false)}}/>}
55
+ </>)}
50
56
  </div>
51
57
  )
52
58
  })
53
59
 
54
- export default Cart
60
+ export default CartPanel
@@ -0,0 +1,60 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import Picker from 'react-mobile-picker'
4
+
5
+ import type { ItemSelector } from '../types'
6
+ import { formatPrice } from '../util'
7
+ import { cn } from '@hanzo/ui/util'
8
+
9
+ // from source code
10
+ interface PickerItemRenderProps {
11
+ selected: boolean;
12
+ }
13
+
14
+ const CategoryItemIOSWheelSelector: React.FC<ItemSelector & {
15
+ height?: number
16
+ itemHeight?: number
17
+ outerClx?: string
18
+ itemClx?: string
19
+ }> = ({
20
+ category,
21
+ selectedItemRef: iRef,
22
+ selectSku,
23
+ height,
24
+ itemHeight,
25
+ outerClx='',
26
+ itemClx=''
27
+ }) => {
28
+
29
+ // @ts-ignore
30
+ const onChange = (val, ignore) => {
31
+ selectSku(val.item)
32
+ }
33
+
34
+ return (
35
+ <div className={cn('border border-muted-4 rounded-lg px-2', outerClx)}>
36
+ <Picker
37
+ className=''
38
+ value={iRef.item ? {item: iRef.item.sku} : {item: undefined}}
39
+ onChange={onChange}
40
+ wheelMode="natural"
41
+ height={height}
42
+ itemHeight={itemHeight}
43
+ >
44
+ <Picker.Column name="item">
45
+ {category.products.map((prod) => (
46
+ <Picker.Item key={prod.sku} value={prod.sku}>
47
+ {({ selected }: PickerItemRenderProps) => (
48
+ <div className={cn(selected ? 'font-semibold text-accent' : 'text-muted', itemClx)}>
49
+ {prod.titleAsOption + ', ' + formatPrice(prod.price)}
50
+ </div>
51
+ )}
52
+ </Picker.Item>
53
+ ))}
54
+ </Picker.Column>
55
+ </Picker>
56
+ </div>
57
+ )
58
+ }
59
+
60
+ export default CategoryItemIOSWheelSelector
@@ -0,0 +1,55 @@
1
+ 'use client'
2
+ import React from 'react'
3
+ import { observer } from 'mobx-react-lite'
4
+
5
+ import { Label, RadioGroup, RadioGroupItem } from '@hanzo/ui/primitives'
6
+ import type { ItemSelector, LineItem, Product } from '../types'
7
+ import { formatPrice } from '../util'
8
+ import { cn } from '@hanzo/ui/util'
9
+
10
+ const CategoryItemRadioSelector: React.FC<ItemSelector & {
11
+ groupClx?: string
12
+ itemClx?: string
13
+ }> = observer(({
14
+ category,
15
+ selectedItemRef: itemRef,
16
+ selectSku,
17
+ groupClx='',
18
+ itemClx='',
19
+ showPrice=true,
20
+ showQuantity=true
21
+ }) => {
22
+
23
+ const Choice: React.FC<{
24
+ item: Product
25
+ className?: string
26
+ }> = ({
27
+ item,
28
+ className=''
29
+ }) => (
30
+ <div className={cn(className, itemClx)}>
31
+ <RadioGroupItem value={item.sku} id={item.sku} />
32
+ <Label htmlFor={item.sku}>{item.titleAsOption + (showPrice ? (', ' + formatPrice(item.price)) : '')}</Label>
33
+ </div>
34
+ )
35
+
36
+ return ( category.products.length > 1 ? (
37
+ <RadioGroup
38
+ className={cn(showQuantity ? 'table' : '', groupClx)}
39
+ onValueChange={selectSku}
40
+ value={itemRef.item ? itemRef.item.sku : ''}
41
+ >
42
+ {(category.products as LineItem[]).map((item) => (showQuantity ? (
43
+ <div className='table-row' key={item.sku}>
44
+ <Choice item={item} className='table-cell pr-2 align-text-top pb-2'/>
45
+ <div className='table-cell font-semibold text-sm leading-none align-text-top pb-2'>{ item.quantity > 0 ? `(${item.quantity})` : ' '}</div>
46
+ </div>
47
+ ) : (
48
+ <Choice item={item} className='mb-2' key={item.sku}/>
49
+ )))}
50
+ </RadioGroup>
51
+ ) : (<p>TODO</p>)
52
+ )
53
+ })
54
+
55
+ export default CategoryItemRadioSelector
@@ -1,9 +1,10 @@
1
1
  'use client'
2
+ import React from 'react'
3
+ import type { UseFormReturn } from 'react-hook-form'
4
+ import { BookUser, Lock, User } from 'lucide-react'
2
5
 
3
6
  import { ApplyTypography, Button } from '@hanzo/ui/primitives'
4
- import { BookUser, Lock, User } from 'lucide-react'
5
7
  import { EnhHeadingBlockComponent, type EnhHeadingBlock } from '@hanzo/ui/blocks'
6
- import type { UseFormReturn } from 'react-hook-form'
7
8
 
8
9
  const ConfirmOrder: React.FC<{
9
10
  paymentForm: UseFormReturn<{
@@ -11,10 +11,15 @@ import { LoginComponent, AuthWidget } from '@hanzo/auth/components'
11
11
 
12
12
  import ShippingInfo from './shipping-info'
13
13
  import ThankYou from './thank-you'
14
- import { Cart } from '..'
14
+ import CartPanel from '../cart-panel'
15
15
  import Payment from './payment'
16
16
 
17
- const Checkout: React.FC<{toggleCheckout: () => void}> = observer(({toggleCheckout}) => {
17
+ const CheckoutPanel: React.FC<{
18
+ close: () => void
19
+ }> = observer(({
20
+ close
21
+ }) => {
22
+
18
23
  const auth = useAuth()
19
24
 
20
25
  const [currentStep, setCurrentStep] = useState(1)
@@ -48,7 +53,7 @@ const Checkout: React.FC<{toggleCheckout: () => void}> = observer(({toggleChecko
48
53
  size='icon'
49
54
  onClick={() => {
50
55
  setCurrentStep(0)
51
- toggleCheckout()
56
+ close()
52
57
  }}
53
58
  >
54
59
  <ChevronLeft/>
@@ -58,7 +63,7 @@ const Checkout: React.FC<{toggleCheckout: () => void}> = observer(({toggleChecko
58
63
 
59
64
  <div className='grid grid-cols-5 justify-center gap-8 h-full'>
60
65
  <div className='col-span-2 hidden md:flex'>
61
- <Cart hideCheckout className='fixed justify-center border-none mt-10 w-1/3 max-w-[40rem]'/>
66
+ <CartPanel noCheckout className='fixed justify-center border-none mt-10 w-1/3 max-w-[40rem]'/>
62
67
  </div>
63
68
 
64
69
  <div className='flex flex-col gap-8 sm:gap-14 col-span-5 md:col-span-3 max-w-[30rem] w-full mx-auto overflow-y-auto h-[calc(100%-40px)] sm:h-[calc(100%-48px)] py-4 px-1'>
@@ -83,4 +88,4 @@ const Checkout: React.FC<{toggleCheckout: () => void}> = observer(({toggleChecko
83
88
  )
84
89
  })
85
90
 
86
- export default Checkout
91
+ export default CheckoutPanel
@@ -12,7 +12,8 @@ import { useAuth } from '@hanzo/auth/service'
12
12
  import PayWithCrypto from './pay-with-crypto'
13
13
  import PayWithBankTransfer from './pay-with-bank-transfer'
14
14
  import PayWithCard from './pay-with-card'
15
- import { useCommerce, type TransactionStatus } from '../../..'
15
+ import { useCommerce } from '../../../service/context'
16
+ import type { TransactionStatus } from '../../../types'
16
17
 
17
18
  const contactFormSchema = z.object({
18
19
  name: z.string().min(1, 'Enter your full name.'),
@@ -1,12 +1,17 @@
1
1
  'use client'
2
+ import React from 'react'
2
3
 
4
+ import type { UseFormReturn } from 'react-hook-form'
3
5
  // @ts-ignore
4
6
  import { ApplePay, GooglePay, CreditCard, PaymentForm } from 'react-square-web-payments-sdk'
5
- import type { UseFormReturn } from 'react-hook-form'
7
+
6
8
  import { ApplyTypography, Button } from '@hanzo/ui/primitives'
7
- import { useCommerce, type TransactionStatus } from '../../..'
8
- import PaymentMethods from './payment-methods'
9
+
9
10
  import { processSquareCardPayment } from '../../../util'
11
+ import { useCommerce } from '../../../service/context'
12
+ import type { TransactionStatus } from '../../../types'
13
+
14
+ import PaymentMethods from './payment-methods'
10
15
  import ContactInfo from './contact-info'
11
16
 
12
17
  const PayWithCard: React.FC<{
@@ -1,7 +1,5 @@
1
1
  'use client'
2
-
3
2
  import React, { useEffect, useState } from 'react'
4
-
5
3
  import { autorun } from 'mobx'
6
4
  import { observer } from 'mobx-react-lite'
7
5
 
@@ -23,7 +21,8 @@ import { useAuth } from '@hanzo/auth/service'
23
21
  import { Ethereum as EthIconFromAuth } from '@hanzo/auth/icons'
24
22
 
25
23
  import Eth from '../icons/eth'
26
- import { useCommerce, type TransactionStatus } from '../../..'
24
+ import { useCommerce } from '../../../service/context'
25
+ import type { TransactionStatus } from '../../../types'
27
26
  import { formatPrice } from '../../../util'
28
27
 
29
28
  declare global {
@@ -3,7 +3,7 @@ import Image from 'next/image'
3
3
 
4
4
  import type { FacetValueDesc } from '../../types'
5
5
 
6
- const ICON_SIZE = 16
6
+ const ICON_SIZE = 20
7
7
  const SVG_MULT = 1.5
8
8
 
9
9
  const FacetImage: React.FC<{
@@ -27,16 +27,19 @@ const FacetImage: React.FC<{
27
27
  <Image
28
28
  src={img as string}
29
29
  alt={`Toggle ${label}`}
30
- className={'block mr-1 rounded border border-muted-2 ' + (ar ? '' : 'aspect-square')}
30
+ className={'block mr-1 '}
31
31
  width={ar ? ar * ICON_SIZE : ICON_SIZE}
32
32
  height={ICON_SIZE}
33
33
  />
34
34
  )
35
35
  }
36
36
 
37
+ return img as React.ReactNode
38
+
37
39
  // Otherwise, assume it's a ReactNode of an imported SVG
38
40
 
39
41
  // If it's not square, center it in the appropriate dimension
42
+ /*
40
43
  const svgStyle: any = { position: 'relative' }
41
44
  if (ar) {
42
45
  if (ar < 1) {
@@ -51,7 +54,7 @@ const FacetImage: React.FC<{
51
54
 
52
55
  return (
53
56
  <span
54
- className='block overflow-hidden '
57
+ className='flex justify-center items-center overflow-hidden '
55
58
  style={{
56
59
  color: 'inherit',
57
60
  width: ICON_SIZE * SVG_MULT,
@@ -65,6 +68,7 @@ const FacetImage: React.FC<{
65
68
  })}
66
69
  </span>
67
70
  )
71
+ */
68
72
  }
69
73
 
70
74
  export default FacetImage