@hanzo/commerce 7.3.2 → 7.3.4

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 (83) hide show
  1. package/components/Icons.tsx +34 -34
  2. package/components/add-to-cart-widget.tsx +183 -183
  3. package/components/buy/buy-card.tsx +259 -259
  4. package/components/buy/carousel-buy-card.tsx +242 -242
  5. package/components/buy/multi-family/all-variants-carousel.tsx +261 -261
  6. package/components/buy/multi-family/family-carousel/index.tsx +77 -77
  7. package/components/buy/multi-family/family-carousel/slide.tsx +83 -83
  8. package/components/buy/multi-family/family-carousel/state.ts +87 -87
  9. package/components/buy/multi-family/index.ts +2 -2
  10. package/components/buy/single-family-selector.tsx +90 -90
  11. package/components/buy/title-and-byline.tsx +25 -25
  12. package/components/cart/cart-panel/cart-line-item.tsx +76 -76
  13. package/components/cart/cart-panel/index.tsx +154 -154
  14. package/components/cart/cart-panel/promo-code.tsx +106 -106
  15. package/components/cart/cart-panel/total-area.tsx +60 -60
  16. package/components/checkout/payment-step-form/card-icon-row.tsx +26 -26
  17. package/components/checkout/payment-step-form/card-icons/amex.tsx +32 -32
  18. package/components/checkout/payment-step-form/card-icons/diners-club.tsx +13 -13
  19. package/components/checkout/payment-step-form/card-icons/discover.tsx +25 -25
  20. package/components/checkout/payment-step-form/card-icons/jcb.tsx +26 -26
  21. package/components/checkout/payment-step-form/card-icons/mastercard.tsx +27 -27
  22. package/components/checkout/payment-step-form/card-icons/visa.tsx +25 -25
  23. package/components/checkout/payment-step-form/cc-button.tsx +17 -17
  24. package/components/checkout/payment-step-form/contact-form.tsx +49 -49
  25. package/components/checkout/payment-step-form/crypto-icons/btc.tsx +11 -11
  26. package/components/checkout/payment-step-form/crypto-icons/eth.tsx +20 -20
  27. package/components/checkout/payment-step-form/crypto-icons/usdt.tsx +13 -13
  28. package/components/checkout/payment-step-form/index.tsx +122 -122
  29. package/components/checkout/payment-step-form/methods/bank-transfer.tsx +79 -79
  30. package/components/checkout/payment-step-form/methods/card.tsx +232 -232
  31. package/components/checkout/payment-step-form/methods/crypto.tsx +227 -227
  32. package/components/checkout/payment-step-form/methods/index.ts +22 -22
  33. package/components/checkout/shipping-step-form.tsx +172 -172
  34. package/components/index.ts +11 -11
  35. package/components/item/product-card.tsx +48 -48
  36. package/components/item-selector/button.tsx +188 -188
  37. package/components/item-selector/carousel/index.tsx +197 -197
  38. package/components/item-selector/carousel/slider.tsx +40 -40
  39. package/components/item-selector/index.ts +5 -5
  40. package/components/item-selector/quantity-indicator.tsx +48 -48
  41. package/components/node-tabs/index.tsx +91 -91
  42. package/components/node-tabs/node-image.tsx +31 -31
  43. package/index.ts +12 -12
  44. package/package.json +60 -60
  45. package/service/context.tsx +45 -45
  46. package/service/debug.ts +41 -41
  47. package/service/impls/standalone/actual-line-item.ts +135 -135
  48. package/service/impls/standalone/get-instance.ts +64 -64
  49. package/service/impls/standalone/index.ts +579 -579
  50. package/service/impls/standalone/order/firebase.ts +14 -14
  51. package/service/impls/standalone/order/index.ts +128 -128
  52. package/service/impls/standalone/persistence.ts +33 -33
  53. package/service/path-utils.ts +25 -25
  54. package/service/sep.ts +6 -6
  55. package/tsconfig.json +10 -10
  56. package/types/README.md +1 -1
  57. package/types/category-node.ts +49 -49
  58. package/types/checkout.ts +46 -46
  59. package/types/commerce-config.ts +13 -13
  60. package/types/commerce-service.ts +127 -127
  61. package/types/family.ts +25 -25
  62. package/types/index.ts +15 -15
  63. package/types/item-selector.ts +96 -96
  64. package/types/line-item.ts +29 -29
  65. package/types/multi-family-selector-props.ts +19 -19
  66. package/types/product.ts +20 -20
  67. package/types/promo.ts +9 -9
  68. package/types/selection-ui-specifier.ts +51 -51
  69. package/types/string-mutator.ts +13 -13
  70. package/types/token-separators.ts +7 -7
  71. package/util/analytics.ts +20 -20
  72. package/util/countries.ts +195 -195
  73. package/util/error.ts +34 -34
  74. package/util/index.ts +70 -70
  75. package/util/item-selector-options-accessor.ts +34 -34
  76. package/util/line-item-ref.ts +23 -23
  77. package/util/multi-family-selector-options-accessor.ts +14 -14
  78. package/util/obs-string-mutator.ts +22 -22
  79. package/util/product-media-accessor.ts +58 -58
  80. package/util/promo-codes.ts +108 -108
  81. package/util/selection-ui-specifiers.ts +29 -29
  82. package/util/square-payment.ts +42 -42
  83. package/util/use-sync-sku-param-w-current-item.ts +88 -88
@@ -1,11 +1,11 @@
1
- import React from 'react'
2
- import { type LucideProps } from 'lucide-react'
3
-
4
- const Btc: React.FC<LucideProps> = (props: LucideProps) => (
5
- <svg viewBox="0.004 0 64 64" {...props}>
6
- <path d="M63.04 39.741c-4.274 17.143-21.638 27.575-38.783 23.301C7.12 58.768-3.313 41.404.962 24.262 5.234 7.117 22.597-3.317 39.737.957c17.144 4.274 27.576 21.64 23.302 38.784z" fill="#f7931a"/>
7
- <path d="M46.11 27.441c.636-4.258-2.606-6.547-7.039-8.074l1.438-5.768-3.512-.875-1.4 5.616c-.922-.23-1.87-.447-2.812-.662l1.41-5.653-3.509-.875-1.439 5.766c-.764-.174-1.514-.346-2.242-.527l.004-.018-4.842-1.209-.934 3.75s2.605.597 2.55.634c1.422.355 1.68 1.296 1.636 2.042l-1.638 6.571c.098.025.225.061.365.117l-.37-.092-2.297 9.205c-.174.432-.615 1.08-1.609.834.035.051-2.552-.637-2.552-.637l-1.743 4.02 4.57 1.139c.85.213 1.683.436 2.502.646l-1.453 5.835 3.507.875 1.44-5.772c.957.26 1.887.5 2.797.726L27.504 50.8l3.511.875 1.453-5.823c5.987 1.133 10.49.676 12.383-4.738 1.527-4.36-.075-6.875-3.225-8.516 2.294-.531 4.022-2.04 4.483-5.157zM38.087 38.69c-1.086 4.36-8.426 2.004-10.807 1.412l1.928-7.729c2.38.594 10.011 1.77 8.88 6.317zm1.085-11.312c-.99 3.966-7.1 1.951-9.083 1.457l1.748-7.01c1.983.494 8.367 1.416 7.335 5.553z" fill="#ffffff"/>
8
- </svg>
9
- )
10
-
11
- export default Btc
1
+ import React from 'react'
2
+ import { type LucideProps } from 'lucide-react'
3
+
4
+ const Btc: React.FC<LucideProps> = (props: LucideProps) => (
5
+ <svg viewBox="0.004 0 64 64" {...props}>
6
+ <path d="M63.04 39.741c-4.274 17.143-21.638 27.575-38.783 23.301C7.12 58.768-3.313 41.404.962 24.262 5.234 7.117 22.597-3.317 39.737.957c17.144 4.274 27.576 21.64 23.302 38.784z" fill="#f7931a"/>
7
+ <path d="M46.11 27.441c.636-4.258-2.606-6.547-7.039-8.074l1.438-5.768-3.512-.875-1.4 5.616c-.922-.23-1.87-.447-2.812-.662l1.41-5.653-3.509-.875-1.439 5.766c-.764-.174-1.514-.346-2.242-.527l.004-.018-4.842-1.209-.934 3.75s2.605.597 2.55.634c1.422.355 1.68 1.296 1.636 2.042l-1.638 6.571c.098.025.225.061.365.117l-.37-.092-2.297 9.205c-.174.432-.615 1.08-1.609.834.035.051-2.552-.637-2.552-.637l-1.743 4.02 4.57 1.139c.85.213 1.683.436 2.502.646l-1.453 5.835 3.507.875 1.44-5.772c.957.26 1.887.5 2.797.726L27.504 50.8l3.511.875 1.453-5.823c5.987 1.133 10.49.676 12.383-4.738 1.527-4.36-.075-6.875-3.225-8.516 2.294-.531 4.022-2.04 4.483-5.157zM38.087 38.69c-1.086 4.36-8.426 2.004-10.807 1.412l1.928-7.729c2.38.594 10.011 1.77 8.88 6.317zm1.085-11.312c-.99 3.966-7.1 1.951-9.083 1.457l1.748-7.01c1.983.494 8.367 1.416 7.335 5.553z" fill="#ffffff"/>
8
+ </svg>
9
+ )
10
+
11
+ export default Btc
@@ -1,20 +1,20 @@
1
- import React from 'react'
2
- import { type LucideProps } from 'lucide-react'
3
-
4
- const Eth: React.FC<LucideProps> = (props: LucideProps) => (
5
- <svg viewBox="0 0 32 32" {...props}>
6
- <g fill="none" fillRule="evenodd">
7
- <circle cx="16" cy="16" r="16" fill="#627EEA"/>
8
- <g fill="#FFF" fillRule="nonzero">
9
- <path fillOpacity=".602" d="M16.498 4v8.87l7.497 3.35z"/>
10
- <path d="M16.498 4L9 16.22l7.498-3.35z"/>
11
- <path fillOpacity=".602" d="M16.498 21.968v6.027L24 17.616z"/>
12
- <path d="M16.498 27.995v-6.028L9 17.616z"/>
13
- <path fillOpacity=".2" d="M16.498 20.573l7.497-4.353-7.497-3.348z"/>
14
- <path fillOpacity=".602" d="M9 16.22l7.498 4.353v-7.701z"/>
15
- </g>
16
- </g>
17
- </svg>
18
- )
19
-
20
- export default Eth
1
+ import React from 'react'
2
+ import { type LucideProps } from 'lucide-react'
3
+
4
+ const Eth: React.FC<LucideProps> = (props: LucideProps) => (
5
+ <svg viewBox="0 0 32 32" {...props}>
6
+ <g fill="none" fillRule="evenodd">
7
+ <circle cx="16" cy="16" r="16" fill="#627EEA"/>
8
+ <g fill="#FFF" fillRule="nonzero">
9
+ <path fillOpacity=".602" d="M16.498 4v8.87l7.497 3.35z"/>
10
+ <path d="M16.498 4L9 16.22l7.498-3.35z"/>
11
+ <path fillOpacity=".602" d="M16.498 21.968v6.027L24 17.616z"/>
12
+ <path d="M16.498 27.995v-6.028L9 17.616z"/>
13
+ <path fillOpacity=".2" d="M16.498 20.573l7.497-4.353-7.497-3.348z"/>
14
+ <path fillOpacity=".602" d="M9 16.22l7.498 4.353v-7.701z"/>
15
+ </g>
16
+ </g>
17
+ </svg>
18
+ )
19
+
20
+ export default Eth
@@ -1,13 +1,13 @@
1
- import React from 'react'
2
- import { type LucideProps } from 'lucide-react'
3
-
4
- const Usdt: React.FC<LucideProps> = (props: LucideProps) => (
5
- <svg viewBox="0 0 32 32" {...props}>
6
- <g fill="none" fill-rule="evenodd">
7
- <circle cx="16" cy="16" r="16" fill="#26A17B"/>
8
- <path fill="#FFF" d="M17.922 17.383v-.002c-.11.008-.677.042-1.942.042-1.01 0-1.721-.03-1.971-.042v.003c-3.888-.171-6.79-.848-6.79-1.658 0-.809 2.902-1.486 6.79-1.66v2.644c.254.018.982.061 1.988.061 1.207 0 1.812-.05 1.925-.06v-2.643c3.88.173 6.775.85 6.775 1.658 0 .81-2.895 1.485-6.775 1.657m0-3.59v-2.366h5.414V7.819H8.595v3.608h5.414v2.365c-4.4.202-7.709 1.074-7.709 2.118 0 1.044 3.309 1.915 7.709 2.118v7.582h3.913v-7.584c4.393-.202 7.694-1.073 7.694-2.116 0-1.043-3.301-1.914-7.694-2.117"/>
9
- </g>
10
- </svg>
11
- )
12
-
13
- export default Usdt
1
+ import React from 'react'
2
+ import { type LucideProps } from 'lucide-react'
3
+
4
+ const Usdt: React.FC<LucideProps> = (props: LucideProps) => (
5
+ <svg viewBox="0 0 32 32" {...props}>
6
+ <g fill="none" fill-rule="evenodd">
7
+ <circle cx="16" cy="16" r="16" fill="#26A17B"/>
8
+ <path fill="#FFF" d="M17.922 17.383v-.002c-.11.008-.677.042-1.942.042-1.01 0-1.721-.03-1.971-.042v.003c-3.888-.171-6.79-.848-6.79-1.658 0-.809 2.902-1.486 6.79-1.66v2.644c.254.018.982.061 1.988.061 1.207 0 1.812-.05 1.925-.06v-2.643c3.88.173 6.775.85 6.775 1.658 0 .81-2.895 1.485-6.775 1.657m0-3.59v-2.366h5.414V7.819H8.595v3.608h5.414v2.365c-4.4.202-7.709 1.074-7.709 2.118 0 1.044 3.309 1.915 7.709 2.118v7.582h3.913v-7.584c4.393-.202 7.694-1.073 7.694-2.116 0-1.043-3.301-1.914-7.694-2.117"/>
9
+ </g>
10
+ </svg>
11
+ )
12
+
13
+ export default Usdt
@@ -1,122 +1,122 @@
1
- 'use client'
2
- import React, { useEffect, useState } from 'react'
3
- import { observer } from 'mobx-react-lite'
4
-
5
- import { zodResolver } from '@hookform/resolvers/zod'
6
- import * as z from 'zod'
7
- import { useForm } from 'react-hook-form'
8
-
9
- import { Tabs, TabsContent, TabsList, TabsTrigger } from '@hanzo/ui/primitives'
10
- import { useAuth } from '@hanzo/auth/service'
11
-
12
- import { useCommerce } from '../../../service/context'
13
- import { sendFBEvent, sendGAEvent } from '../../../util/analytics'
14
- import type { CheckoutStepComponentProps, TransactionStatus } from '../../../types'
15
-
16
- import METHODS from './methods'
17
-
18
- const contactFormSchema = z.object({
19
- name: z.string().min(1, 'Enter your full name.'),
20
- email: z.string().email(),
21
- })
22
-
23
- const PaymentStepForm: React.FC<CheckoutStepComponentProps> = observer(({
24
- onDone,
25
- orderId,
26
- setOrderId
27
- }) => {
28
- const cmmc = useCommerce()
29
- const auth = useAuth() // may be null in some cases
30
-
31
- const [transactionStatus, setTransactionStatus] = useState<TransactionStatus>('unpaid')
32
-
33
- if (!auth) {
34
- console.log("PAYMENT STEP FORM: auth service is null! ")
35
- }
36
-
37
- const contactForm = useForm<z.infer<typeof contactFormSchema>>({
38
- resolver: zodResolver(contactFormSchema),
39
- defaultValues: {
40
- name: auth?.user?.displayName ?? '',
41
- email: auth?.user?.email ?? '',
42
- },
43
- })
44
-
45
- useEffect(() => {
46
- if (auth?.loggedIn) {
47
- contactForm.setValue('name', auth!.user?.displayName ?? '')
48
- contactForm.setValue('email', auth!.user?.email ?? '')
49
- }
50
- }, [auth?.loggedIn])
51
-
52
- const storePaymentInfo = async (paymentInfo: any) => {
53
- const {name, email} = contactForm.getValues()
54
- let id: string | undefined = undefined
55
- if (!orderId) {
56
- id = await cmmc.createOrder(email, name)
57
- setOrderId(id)
58
- }
59
- if (id) {
60
- sendGAEvent('add_payment_info', {
61
- items: cmmc.cartItems.map((item) => ({
62
- item_id: item.sku,
63
- item_name: item.title,
64
- item_category: item.familyId,
65
- price: item.price,
66
- quantity: item.quantity
67
- })),
68
- value: cmmc.promoAppliedCartTotal,
69
- currency: 'USD',
70
- payment_type: paymentInfo.paymentMethod ?? ''
71
- })
72
- sendFBEvent('AddPaymentInfo', {
73
- contents: cmmc.cartItems.map(item => ({
74
- id: item.sku,
75
- quantity: item.quantity
76
- })),
77
- value: cmmc.promoAppliedCartTotal,
78
- currency: 'USD'
79
- })
80
- await cmmc.updateOrderPaymentInfo(id, paymentInfo)
81
- }
82
- }
83
-
84
- const groupClx = 'grid w-full grid-cols-3 mx-auto ' +
85
- 'p-0 h-auto overflow-hidden ' +
86
- 'border-2 bg-background border-level-2 md:bg-level-1 md:border-level-3 '
87
-
88
- const tabClx = 'whitespace-normal h-full text-xs sm:text-base px-1 text-muted ' +
89
- 'data-[state=active]:text-accent data-[state=active]:bg-level-2 md:data-[state=active]:bg-level-3'
90
-
91
- const disabled = transactionStatus === 'paid' || transactionStatus === 'confirmed'
92
-
93
- return (
94
- <Tabs defaultValue='card' className='w-full'>
95
- <TabsList className={groupClx}>
96
- {METHODS.map(({ label, value }) => (
97
- <TabsTrigger
98
- value={value}
99
- className={tabClx}
100
- disabled={disabled}
101
- key={`tabs-${value}`}
102
- >
103
- {label}
104
- </TabsTrigger>
105
- ))}
106
- </TabsList>
107
- {METHODS.map(({Comp: PaymentMethodComp, value}) => (
108
- <TabsContent value={value} key={`content-${value}`}>
109
- <PaymentMethodComp
110
- onDone={onDone}
111
- transactionStatus={transactionStatus}
112
- setTransactionStatus={setTransactionStatus}
113
- storePaymentInfo={storePaymentInfo}
114
- contactForm={contactForm}
115
- />
116
- </TabsContent>
117
- ))}
118
- </Tabs>
119
- )
120
- })
121
-
122
- export default PaymentStepForm
1
+ 'use client'
2
+ import React, { useEffect, useState } from 'react'
3
+ import { observer } from 'mobx-react-lite'
4
+
5
+ import { zodResolver } from '@hookform/resolvers/zod'
6
+ import * as z from 'zod'
7
+ import { useForm } from 'react-hook-form'
8
+
9
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@hanzo/ui/primitives'
10
+ import { useAuth } from '@hanzo/auth/service'
11
+
12
+ import { useCommerce } from '../../../service/context'
13
+ import { sendFBEvent, sendGAEvent } from '../../../util/analytics'
14
+ import type { CheckoutStepComponentProps, TransactionStatus } from '../../../types'
15
+
16
+ import METHODS from './methods'
17
+
18
+ const contactFormSchema = z.object({
19
+ name: z.string().min(1, 'Enter your full name.'),
20
+ email: z.string().email(),
21
+ })
22
+
23
+ const PaymentStepForm: React.FC<CheckoutStepComponentProps> = observer(({
24
+ onDone,
25
+ orderId,
26
+ setOrderId
27
+ }) => {
28
+ const cmmc = useCommerce()
29
+ const auth = useAuth() // may be null in some cases
30
+
31
+ const [transactionStatus, setTransactionStatus] = useState<TransactionStatus>('unpaid')
32
+
33
+ if (!auth) {
34
+ console.log("PAYMENT STEP FORM: auth service is null! ")
35
+ }
36
+
37
+ const contactForm = useForm<z.infer<typeof contactFormSchema>>({
38
+ resolver: zodResolver(contactFormSchema),
39
+ defaultValues: {
40
+ name: auth?.user?.displayName ?? '',
41
+ email: auth?.user?.email ?? '',
42
+ },
43
+ })
44
+
45
+ useEffect(() => {
46
+ if (auth?.loggedIn) {
47
+ contactForm.setValue('name', auth!.user?.displayName ?? '')
48
+ contactForm.setValue('email', auth!.user?.email ?? '')
49
+ }
50
+ }, [auth?.loggedIn])
51
+
52
+ const storePaymentInfo = async (paymentInfo: any) => {
53
+ const {name, email} = contactForm.getValues()
54
+ let id: string | undefined = undefined
55
+ if (!orderId) {
56
+ id = await cmmc.createOrder(email, name)
57
+ setOrderId(id)
58
+ }
59
+ if (id) {
60
+ sendGAEvent('add_payment_info', {
61
+ items: cmmc.cartItems.map((item) => ({
62
+ item_id: item.sku,
63
+ item_name: item.title,
64
+ item_category: item.familyId,
65
+ price: item.price,
66
+ quantity: item.quantity
67
+ })),
68
+ value: cmmc.promoAppliedCartTotal,
69
+ currency: 'USD',
70
+ payment_type: paymentInfo.paymentMethod ?? ''
71
+ })
72
+ sendFBEvent('AddPaymentInfo', {
73
+ contents: cmmc.cartItems.map(item => ({
74
+ id: item.sku,
75
+ quantity: item.quantity
76
+ })),
77
+ value: cmmc.promoAppliedCartTotal,
78
+ currency: 'USD'
79
+ })
80
+ await cmmc.updateOrderPaymentInfo(id, paymentInfo)
81
+ }
82
+ }
83
+
84
+ const groupClx = 'grid w-full grid-cols-3 mx-auto ' +
85
+ 'p-0 h-auto overflow-hidden ' +
86
+ 'border-2 bg-background border-level-2 md:bg-level-1 md:border-level-3 '
87
+
88
+ const tabClx = 'whitespace-normal h-full text-xs sm:text-base px-1 text-muted ' +
89
+ 'data-[state=active]:text-accent data-[state=active]:bg-level-2 md:data-[state=active]:bg-level-3'
90
+
91
+ const disabled = transactionStatus === 'paid' || transactionStatus === 'confirmed'
92
+
93
+ return (
94
+ <Tabs defaultValue='card' className='w-full'>
95
+ <TabsList className={groupClx}>
96
+ {METHODS.map(({ label, value }) => (
97
+ <TabsTrigger
98
+ value={value}
99
+ className={tabClx}
100
+ disabled={disabled}
101
+ key={`tabs-${value}`}
102
+ >
103
+ {label}
104
+ </TabsTrigger>
105
+ ))}
106
+ </TabsList>
107
+ {METHODS.map(({Comp: PaymentMethodComp, value}) => (
108
+ <TabsContent value={value} key={`content-${value}`}>
109
+ <PaymentMethodComp
110
+ onDone={onDone}
111
+ transactionStatus={transactionStatus}
112
+ setTransactionStatus={setTransactionStatus}
113
+ storePaymentInfo={storePaymentInfo}
114
+ contactForm={contactForm}
115
+ />
116
+ </TabsContent>
117
+ ))}
118
+ </Tabs>
119
+ )
120
+ })
121
+
122
+ export default PaymentStepForm
@@ -1,79 +1,79 @@
1
- 'use client'
2
-
3
- import React from 'react'
4
- import { Copy } from 'lucide-react'
5
-
6
- import { Button, toast } from '@hanzo/ui/primitives'
7
-
8
- import type { PaymentMethodComponentProps } from '../../../../types'
9
-
10
- import ContactForm from '../contact-form'
11
-
12
- const InfoField: React.FC<{
13
- label: string,
14
- value: React.ReactNode,
15
- copyValue: string
16
- }> = ({
17
- label,
18
- value,
19
- copyValue
20
- }) => {
21
-
22
- const copyToClipboard = (label: string, text: string) => {
23
- navigator.clipboard.writeText(text)
24
- toast(`${label} copied to clipboard.`)
25
- }
26
-
27
- return (
28
- <div className='flex flex-col gap-1'>
29
- <p className='text-xs'>{label}</p>
30
- <div className='flex items-center justify-between sm:text-lg border rounded-lg py-2 px-4'>
31
- {value}
32
- <Button variant='ghost' size='icon' onClick={() => copyToClipboard(label, copyValue)}>
33
- <Copy className='h-4 w-4'/>
34
- </Button>
35
- </div>
36
- </div>
37
- )
38
- }
39
-
40
- const PayWithBankTransfer: React.FC<PaymentMethodComponentProps> = ({
41
- onDone,
42
- storePaymentInfo,
43
- contactForm
44
- }) => {
45
-
46
- const payByBankTransfer = async () => {
47
- contactForm.handleSubmit( async () => {
48
- await storePaymentInfo({paymentMethod: 'bank-transfer'})
49
- onDone()
50
- })()
51
- }
52
-
53
- return (
54
- <div className='flex flex-col gap-2 mt-6'>
55
- <ContactForm form={contactForm}/>
56
- <div className='w-full mx-auto max-w-[50rem]'>
57
- <div className='flex flex-col gap-4 w-full'>
58
- <InfoField
59
- label='Beneficiary Bank'
60
- value={<div>Bank of America<br/>NA 222 Broadway<br/>New York, New York. 10038</div>}
61
- copyValue='Bank of America, NA 222 Broadway, New York, New York. 10038'
62
- />
63
- <InfoField
64
- label='Beneficiary'
65
- value={<div>Hanzo, Inc<br/>4811 Mastin Street<br/>Merriam, KS 66203</div>}
66
- copyValue='Hanzo, Inc, 4811 Mastin Street, Merriam, KS 66203'
67
- />
68
- <InfoField label='Routing Number - ACH' value='113000023 / 111000025' copyValue='113000023 / 111000025'/>
69
- <InfoField label='Routing Number - Wire' value='026009593' copyValue='026009593'/>
70
- <InfoField label='Routing Number - SWIFT' value='BOFAUS3N' copyValue='BOFAUS3N'/>
71
- <InfoField label='Reference' value='Lux' copyValue='Lux'/>
72
- </div>
73
- </div>
74
- <Button onClick={payByBankTransfer} className='mx-auto w-full mt-4'>Continue</Button>
75
- </div>
76
- )
77
- }
78
-
79
- export default PayWithBankTransfer
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import { Copy } from 'lucide-react'
5
+
6
+ import { Button, toast } from '@hanzo/ui/primitives'
7
+
8
+ import type { PaymentMethodComponentProps } from '../../../../types'
9
+
10
+ import ContactForm from '../contact-form'
11
+
12
+ const InfoField: React.FC<{
13
+ label: string,
14
+ value: React.ReactNode,
15
+ copyValue: string
16
+ }> = ({
17
+ label,
18
+ value,
19
+ copyValue
20
+ }) => {
21
+
22
+ const copyToClipboard = (label: string, text: string) => {
23
+ navigator.clipboard.writeText(text)
24
+ toast(`${label} copied to clipboard.`)
25
+ }
26
+
27
+ return (
28
+ <div className='flex flex-col gap-1'>
29
+ <p className='text-xs'>{label}</p>
30
+ <div className='flex items-center justify-between sm:text-lg border rounded-lg py-2 px-4'>
31
+ {value}
32
+ <Button variant='ghost' size='icon' onClick={() => copyToClipboard(label, copyValue)}>
33
+ <Copy className='h-4 w-4'/>
34
+ </Button>
35
+ </div>
36
+ </div>
37
+ )
38
+ }
39
+
40
+ const PayWithBankTransfer: React.FC<PaymentMethodComponentProps> = ({
41
+ onDone,
42
+ storePaymentInfo,
43
+ contactForm
44
+ }) => {
45
+
46
+ const payByBankTransfer = async () => {
47
+ contactForm.handleSubmit( async () => {
48
+ await storePaymentInfo({paymentMethod: 'bank-transfer'})
49
+ onDone()
50
+ })()
51
+ }
52
+
53
+ return (
54
+ <div className='flex flex-col gap-2 mt-6'>
55
+ <ContactForm form={contactForm}/>
56
+ <div className='w-full mx-auto max-w-[50rem]'>
57
+ <div className='flex flex-col gap-4 w-full'>
58
+ <InfoField
59
+ label='Beneficiary Bank'
60
+ value={<div>Bank of America<br/>NA 222 Broadway<br/>New York, New York. 10038</div>}
61
+ copyValue='Bank of America, NA 222 Broadway, New York, New York. 10038'
62
+ />
63
+ <InfoField
64
+ label='Beneficiary'
65
+ value={<div>Hanzo, Inc<br/>4811 Mastin Street<br/>Merriam, KS 66203</div>}
66
+ copyValue='Hanzo, Inc, 4811 Mastin Street, Merriam, KS 66203'
67
+ />
68
+ <InfoField label='Routing Number - ACH' value='113000023 / 111000025' copyValue='113000023 / 111000025'/>
69
+ <InfoField label='Routing Number - Wire' value='026009593' copyValue='026009593'/>
70
+ <InfoField label='Routing Number - SWIFT' value='BOFAUS3N' copyValue='BOFAUS3N'/>
71
+ <InfoField label='Reference' value='Lux' copyValue='Lux'/>
72
+ </div>
73
+ </div>
74
+ <Button onClick={payByBankTransfer} className='mx-auto w-full mt-4'>Continue</Button>
75
+ </div>
76
+ )
77
+ }
78
+
79
+ export default PayWithBankTransfer