@hanzo/commerce 4.9.0 → 5.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.
Files changed (53) hide show
  1. package/components/add-to-cart-widget.tsx +0 -1
  2. package/components/buy-item/select-category-and-item-widget.tsx +2 -2
  3. package/components/buy-item/select-category-item-card.tsx +2 -2
  4. package/components/{checkout-panel/cart-accordian.tsx → cart-accordian.tsx} +21 -10
  5. package/components/cart-panel/cart-line-item.tsx +22 -16
  6. package/components/cart-panel/index.tsx +90 -34
  7. package/components/cart-panel/promo-code.tsx +98 -0
  8. package/components/category-item-radio-selector.tsx +2 -2
  9. package/components/category-item-scroll-selector.tsx +2 -2
  10. package/components/index.ts +4 -1
  11. package/components/item-carousel.tsx +80 -0
  12. package/components/{checkout-panel/steps/payment/cards/index.tsx → payment-step-form/card-icon-row.tsx} +8 -7
  13. package/components/{checkout-panel/steps/payment → payment-step-form}/cc-button.tsx +1 -1
  14. package/components/payment-step-form/contact-form.tsx +49 -0
  15. package/components/{checkout-panel/steps/payment → payment-step-form}/index.tsx +29 -56
  16. package/components/payment-step-form/methods/bank-transfer.tsx +79 -0
  17. package/components/payment-step-form/methods/card.tsx +237 -0
  18. package/components/{checkout-panel/steps/payment/pay-with-crypto.tsx → payment-step-form/methods/crypto.tsx} +10 -24
  19. package/components/payment-step-form/methods/index.ts +23 -0
  20. package/components/product-card.tsx +2 -2
  21. package/components/select-category-item-panel.tsx +2 -2
  22. package/components/{checkout-panel/steps/shipping-info.tsx → shipping-step-form.tsx} +6 -8
  23. package/index.ts +1 -1
  24. package/package.json +2 -2
  25. package/service/context.tsx +1 -0
  26. package/service/impls/standalone/standalone-service.ts +56 -4
  27. package/types/checkout.ts +42 -1
  28. package/types/commerce-service.ts +9 -1
  29. package/types/index.ts +2 -1
  30. package/types/promo.ts +10 -0
  31. package/util/index.ts +3 -2
  32. package/util/promo-codes.ts +46 -0
  33. package/components/cart-panel/products-carousel.tsx +0 -60
  34. package/components/checkout-panel/_confirm-order.tsx_unused +0 -143
  35. package/components/checkout-panel/close-button.tsx +0 -24
  36. package/components/checkout-panel/desktop.tsx +0 -46
  37. package/components/checkout-panel/icons/bag-icon.tsx +0 -10
  38. package/components/checkout-panel/index.tsx +0 -108
  39. package/components/checkout-panel/mobile.tsx +0 -41
  40. package/components/checkout-panel/steps/payment/contact-info.tsx +0 -56
  41. package/components/checkout-panel/steps/payment/pay-with-bank-transfer.tsx +0 -110
  42. package/components/checkout-panel/steps/payment/pay-with-card.tsx +0 -246
  43. package/components/checkout-panel/steps/thank-you.tsx +0 -18
  44. package/components/checkout-panel/steps/types.ts +0 -14
  45. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/amex.tsx +0 -0
  46. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/diners-club.tsx +0 -0
  47. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/discover.tsx +0 -0
  48. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/jcb.tsx +0 -0
  49. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/mastercard.tsx +0 -0
  50. /package/components/{checkout-panel/steps/payment/cards → payment-step-form/card-icons}/visa.tsx +0 -0
  51. /package/components/{checkout-panel/icons → payment-step-form/crypto-icons}/btc.tsx +0 -0
  52. /package/components/{checkout-panel/icons → payment-step-form/crypto-icons}/eth.tsx +0 -0
  53. /package/components/{checkout-panel/icons → payment-step-form/crypto-icons}/usdt.tsx +0 -0
@@ -1,41 +0,0 @@
1
- 'use client'
2
- import React, { type PropsWithChildren } from 'react'
3
-
4
- import { StepIndicator } from '@hanzo/ui/primitives'
5
- import { cn } from '@hanzo/ui/util'
6
- import { AuthWidget } from '@hanzo/auth/components'
7
-
8
- import CloseButton from './close-button'
9
- import CartAccordian from './cart-accordian'
10
-
11
- const MobilePanel: React.FC<PropsWithChildren & {
12
- index: number
13
- stepNames: string[]
14
- close:() => void
15
- className?: string
16
- }> = ({
17
- index,
18
- stepNames,
19
- close,
20
- className='',
21
- children
22
- }) => (
23
-
24
- <div /* id='MOBILE_GRID' */ className={cn('bg-background flex flex-col justify-start px-4', className)}>
25
- <div className='sticky top-0 w-full flex flex-row justify-between items-start bg-background'>
26
- <CloseButton close={close} className='rounded-full bg-background hover:bg-background p-1 -ml-3' />
27
- <StepIndicator
28
- dotSizeRem={1}
29
- steps={stepNames}
30
- currentStep={index}
31
- className='text-xs font-semibold w-pr-70 mt-3'
32
- />
33
- {/* Need wrapper div since 'noLogin' returns null if no logged in user */}
34
- <div className='w-10 h-10 flex items-center justify-center'><AuthWidget noLogin className=''/></div>
35
- </div>
36
- <CartAccordian className='flex items-center justify-center py-2 mt-2 w-full' />
37
- {children}
38
- </div>
39
- )
40
-
41
- export default MobilePanel
@@ -1,56 +0,0 @@
1
- import {
2
- Form,
3
- FormControl,
4
- FormField,
5
- FormItem,
6
- FormMessage,
7
- } from '@hanzo/ui/primitives/form'
8
- import { Input } from '@hanzo/ui/primitives'
9
- import type { UseFormReturn } from 'react-hook-form'
10
-
11
- const ContactInfo: React.FC<{
12
- form: UseFormReturn<{
13
- name: string
14
- email: string
15
- }, any, {
16
- name: string
17
- email: string
18
- }>,
19
- }> = ({
20
- form,
21
- }) => {
22
- return (
23
- <Form {...form}>
24
- <form className='text-left'>
25
- <div className='flex flex-col gap-1 sm:gap-2'>
26
- <FormField
27
- control={form.control}
28
- name='name'
29
- render={({ field }) => (
30
- <FormItem className='w-full'>
31
- <FormControl>
32
- <Input {...field} className='border-muted-4' placeholder='Full name'/>
33
- </FormControl>
34
- <FormMessage className='py-0 space-y-0 !m-0'/>
35
- </FormItem>
36
- )}
37
- />
38
- <FormField
39
- control={form.control}
40
- name='email'
41
- render={({ field }) => (
42
- <FormItem className='w-full'>
43
- <FormControl>
44
- <Input {...field} className='border-muted-4' placeholder='Email'/>
45
- </FormControl>
46
- <FormMessage className='py-0 space-y-0 !m-0'/>
47
- </FormItem>
48
- )}
49
- />
50
- </div>
51
- </form>
52
- </Form>
53
- )
54
- }
55
-
56
- export default ContactInfo
@@ -1,110 +0,0 @@
1
- 'use client'
2
-
3
- import type { ReactNode } from 'react'
4
- import { Copy } from 'lucide-react'
5
- import type { UseFormReturn } from 'react-hook-form'
6
-
7
- import { Button, Tabs, TabsContent, TabsList, TabsTrigger, toast } from '@hanzo/ui/primitives'
8
- import ContactInfo from './contact-info'
9
-
10
- const InfoField: React.FC<{
11
- label: string,
12
- value: ReactNode,
13
- copyValue: string
14
- }> = ({
15
- label,
16
- value,
17
- copyValue
18
- }) => {
19
- const copyToClipboard = (label: string, text: string) => {
20
- navigator.clipboard.writeText(text)
21
- toast(`${label} copied to clipboard.`)
22
- }
23
-
24
- return (
25
- <div className='flex flex-col gap-1'>
26
- <p className='text-xs'>{label}</p>
27
- <div className='flex items-center justify-between sm:text-lg border rounded-lg py-2 px-4'>
28
- {value}
29
- <Button variant='ghost' size='icon' onClick={() => copyToClipboard(label, copyValue)}>
30
- <Copy className='h-4 w-4'/>
31
- </Button>
32
- </div>
33
- </div>
34
- )
35
- }
36
-
37
- const PayWithBankTransfer: React.FC<{
38
- onDone: () => void
39
- storePaymentInfo: (paymentInfo: any) => Promise<void>
40
- contactForm: UseFormReturn<{
41
- name: string
42
- email: string
43
- }, any, {
44
- name: string
45
- email: string
46
- }>
47
- }> = ({
48
- onDone,
49
- storePaymentInfo,
50
- contactForm
51
- }) => {
52
-
53
- const payByBankTransfer = async () => {
54
- contactForm.handleSubmit( async () => {
55
- await storePaymentInfo({paymentMethod: 'bank-transfer'})
56
- onDone()
57
- })()
58
- }
59
-
60
- const groupClx = 'border-2 bg-background border-level-2 md:bg-level-1 md:border-level-3 p-0 h-auto overflow-hidden rounded-md'
61
- const tabClx = 'text-muted data-[state=active]:text-accent data-[state=active]:bg-level-2 md:data-[state=active]:bg-level-3'
62
-
63
- return (
64
- <div className='flex flex-col gap-2 mt-6'>
65
- <ContactInfo form={contactForm}/>
66
- <Tabs defaultValue="usd" className='w-full mx-auto max-w-[50rem]'>
67
- <TabsList className={"grid w-full grid-cols-2 max-w-[15rem] mx-auto " + groupClx}>
68
- <TabsTrigger className={tabClx} value="usd">USD</TabsTrigger>
69
- <TabsTrigger className={tabClx} value="eur">EUR/GBP</TabsTrigger>
70
- </TabsList>
71
- <TabsContent value="usd">
72
- <div className='flex flex-col gap-4 w-full'>
73
- <InfoField
74
- label='Beneficiary Bank'
75
- value={<div>Bank of America<br/>NA 222 Broadway<br/>New York, New York. 10038</div>}
76
- copyValue='Bank of America, NA 222 Broadway, New York, New York. 10038'
77
- />
78
- <InfoField
79
- label='Beneficiary'
80
- value={<div>Hanzo, Inc<br/>4811 Mastin Street<br/>Merriam, KS 66203</div>}
81
- copyValue='Hanzo, Inc, 4811 Mastin Street, Merriam, KS 66203'
82
- />
83
- <InfoField label='Routing Number - ACH' value='113000023 / 111000025' copyValue='113000023 / 111000025'/>
84
- <InfoField label='Routing Number - Wire' value='026009593' copyValue='026009593'/>
85
- <InfoField label='Routing Number - SWIFT' value='BOFAUS3N' copyValue='BOFAUS3N'/>
86
- <InfoField label='Reference' value='Lux' copyValue='Lux'/>
87
- </div>
88
- </TabsContent>
89
- <TabsContent value="eur">
90
- <div className='flex flex-col gap-4 w-full'>
91
- <InfoField
92
- label='Beneficiary Bank'
93
- value={<div>Clear Junction Limited<br/>4th floor<br/>Imperial House</div>}
94
- copyValue='Clear Junction Limited, 4th floor, Imperial House'
95
- />
96
- <InfoField label='Account Number (GBP)' value='33781813' copyValue='33781813'/>
97
- <InfoField label='Account Name' value='AiDLT Global Ltd.' copyValue='AiDLT Global Ltd.'/>
98
- <InfoField label='SWIFT/BIC' value='CLJUGB21' copyValue='CLJUGB21'/>
99
- <InfoField label='Sort Code (GBP)' value='041307' copyValue='041307'/>
100
- <InfoField label='IBAN' value='GB75 CLJU 0413 0733 78181 3' copyValue='GB75 CLJU 0413 0733 78181 3'/>
101
- <InfoField label='Reference' value='Lux' copyValue='Lux'/>
102
- </div>
103
- </TabsContent>
104
- </Tabs>
105
- <Button onClick={payByBankTransfer} className='mx-auto w-full mt-4'>Continue</Button>
106
- </div>
107
- )
108
- }
109
-
110
- export default PayWithBankTransfer
@@ -1,246 +0,0 @@
1
- 'use client'
2
- import React from 'react'
3
-
4
- import type { UseFormReturn } from 'react-hook-form'
5
- // @ts-ignore
6
- import { ApplePay, GooglePay, CreditCard, PaymentForm } from 'react-square-web-payments-sdk'
7
-
8
- import { ChevronRight } from 'lucide-react'
9
-
10
- import {
11
- Accordion,
12
- AccordionContent,
13
- AccordionItem,
14
- AccordionTrigger,
15
- ApplyTypography,
16
- Button,
17
- buttonVariants
18
- } from '@hanzo/ui/primitives'
19
-
20
- import { cn } from '@hanzo/ui/util'
21
-
22
- import { processSquareCardPayment } from '../../../../util'
23
- import { useCommerce } from '../../../../service/context'
24
- import type { TransactionStatus } from '../../../../types'
25
-
26
- import ContactInfo from './contact-info'
27
- import { sendFBEvent, sendGAEvent } from '../../../../util/analytics'
28
- import PaymentMethods from './cards'
29
-
30
- const PayWithCard: React.FC<{
31
- onDone: () => void
32
- transactionStatus: TransactionStatus
33
- setTransactionStatus: (status: TransactionStatus) => void
34
- storePaymentInfo: (paymentInfo: any) => Promise<void>
35
- contactForm: UseFormReturn<{
36
- name: string
37
- email: string
38
- }, any, {
39
- name: string
40
- email: string
41
- }>
42
- }> = ({
43
- onDone,
44
- transactionStatus,
45
- setTransactionStatus,
46
- storePaymentInfo,
47
- contactForm,
48
- }) => {
49
- const cmmc = useCommerce()
50
-
51
- const cardTokenizeResponseReceived = async (
52
- token: any,
53
- verifiedBuyer: any
54
- ) => {
55
- contactForm.handleSubmit(async () => {
56
- setTransactionStatus('paid')
57
- const res = await processSquareCardPayment(token.token, cmmc.cartTotal, verifiedBuyer.token)
58
- if (res) {
59
- console.log(token)
60
- await storePaymentInfo({paymentMethod: token.details.method ?? null, processed: res})
61
- setTransactionStatus('confirmed')
62
- sendGAEvent('purchase', {
63
- transaction_id: res.payment?.id,
64
- value: res.payment?.amountMoney?.amount,
65
- currency: res.payment?.amountMoney?.currency,
66
- items: cmmc.cartItems.map((item) => ({
67
- item_id: item.sku,
68
- item_name: item.title,
69
- item_category: item.categoryId,
70
- price: item.price,
71
- quantity: item.quantity
72
- })),
73
- })
74
- sendFBEvent('Purchase', {
75
- content_ids: cmmc.cartItems.map((item) => item.sku),
76
- contents: cmmc.cartItems.map(item => ({
77
- id: item.sku,
78
- quantity: item.quantity
79
- })),
80
- num_items: cmmc.cartItems.length,
81
- value: cmmc.cartTotal,
82
- currency: 'USD',
83
- })
84
- } else {
85
- setTransactionStatus('error')
86
- }
87
- })()
88
- }
89
-
90
- const createVerificationDetails = () => {
91
- const {name, email} = contactForm.getValues()
92
- return {
93
- amount: cmmc.cartTotal.toFixed(2),
94
- billingContact: {
95
- givenName: name,
96
- email,
97
- },
98
- currencyCode: 'USD',
99
- intent: 'CHARGE',
100
- }
101
- }
102
-
103
- const createPaymentRequest= () => ({
104
- countryCode: "US",
105
- currencyCode: "USD",
106
- lineItems: cmmc.cartItems.map(item => ({
107
- amount: item.price.toFixed(2),
108
- label: item.title,
109
- id: item.sku,
110
- })),
111
- requestBillingContact: false,
112
- requestShippingContact: false,
113
- total: {
114
- amount: cmmc.cartTotal.toFixed(2),
115
- label: "Total",
116
- },
117
- })
118
-
119
- return (
120
- <PaymentForm
121
- /**
122
- * Identifies the calling form with a verified application ID generated from
123
- * the Square Application Dashboard.
124
- */
125
- applicationId={process.env.NEXT_PUBLIC_SQUARE_APPLICATION_ID}
126
- /**
127
- * Invoked when payment form receives the result of a tokenize generation
128
- * request. The result will be a valid credit card or wallet token, or an error.
129
- */
130
- cardTokenizeResponseReceived={cardTokenizeResponseReceived}
131
- /**
132
- * This function enable the Strong Customer Authentication (SCA) flow
133
- *
134
- * We strongly recommend use this function to verify the buyer and reduce
135
- * the chance of fraudulent transactions.
136
- */
137
- createVerificationDetails={createVerificationDetails}
138
- /**
139
- * This function is required for digital wallets (Apple Pay, Google Pay)
140
- */
141
- createPaymentRequest={createPaymentRequest}
142
- /**
143
- * Identifies the location of the merchant that is taking the payment.
144
- * Obtained from the Square Application Dashboard - Locations tab.
145
- */
146
- locationId={process.env.NEXT_PUBLIC_SQUARE_LOCATION_ID}
147
- >
148
- <ApplyTypography className='flex flex-col mt-6 gap-1'>
149
- {transactionStatus === 'paid' ? (
150
- <h6 className='mx-auto font-nav'>Processing your payment...</h6>
151
- ) : transactionStatus === 'confirmed' ? (
152
- <div className='flex flex-col gap-4'>
153
- <h5 className='mx-auto font-nav'>Payment confirmed!</h5>
154
- <p className='mx-auto'>Thank you for your purchase.</p>
155
- <Button onClick={onDone}>Continue</Button>
156
- </div>
157
- ) : (
158
- <>
159
- <GooglePay/>
160
- <ApplePay/>
161
-
162
- <div className='flex gap-2 whitespace-nowrap items-center my-0.5 sm:my-1 text-xs text-muted'>
163
- <hr className='grow border'/><div className='shrink-0 mx-1'>or</div><hr className='grow border'/>
164
- </div>
165
-
166
- <Accordion type="single" collapsible className={''}>
167
- <AccordionItem value="cart" className='w-full border-b-0 data-[state=open]:border data-[state=open]:px-3 rounded '>
168
- <AccordionTrigger className={cn(
169
- buttonVariants({variant: 'outline', size: 'lg'}),
170
- '!no-underline group flex justify-between ',
171
- 'bg-transparent hover:bg-transparent border-muted-2 hover:border-muted-2',
172
- 'data-[state=open]:border-none data-[state=open]:py-0 px-4 data-[state=open]:px-1'
173
- )}>
174
- <div className='font-sans text-base mr-2 text-muted'>CC</div>
175
- <PaymentMethods />
176
- <div>
177
- <ChevronRight className="h-5 w-5 -mr-2 text-muted shrink-0 transition-transform duration-200 group-data-[state=open]:rotate-90 hidden group-data-[state=open]:block" />
178
- </div>
179
- </AccordionTrigger>
180
- <AccordionContent className='data-[state=open]:mb-4 data-[state=open]:mt-1'>
181
- <ContactInfo form={contactForm}/>
182
- {/* Imitates hanzo/ui Button and Input styles, I was unable to render the
183
- hanzo/ui button outright and keeping the submit form functionality*/}
184
- <CreditCard
185
- style={{
186
- '.input-container': {
187
- borderColor: '#404040',
188
- borderRadius: '6px',
189
- },
190
- '.input-container.is-focus': {
191
- borderColor: '#ffffff',
192
- },
193
- '.input-container.is-error': {
194
- borderColor: '#ff1600',
195
- },
196
- '.message-text': {
197
- color: '#999999',
198
- },
199
- '.message-icon': {
200
- color: '#999999',
201
- },
202
- '.message-text.is-error': {
203
- color: '#ff1600',
204
- },
205
- '.message-icon.is-error': {
206
- color: '#ff1600',
207
- },
208
- input: {
209
- backgroundColor: 'transparent',
210
- color: '#FFFFFF',
211
- fontSize: '15px',
212
- fontFamily: 'helvetica neue, sans-serif',
213
- },
214
- 'input::placeholder': {
215
- color: '#999999',
216
- },
217
- 'input.is-error': {
218
- color: '#ff1600',
219
- },
220
- }}
221
- render={(Button: any) => (
222
- <Button className={cn(
223
- 'items-center justify-center font-medium transition-colors focus-visible:outline-none focus-visible:ring-2',
224
- 'focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background',
225
- '!bg-primary !text-primary-fg hover:!bg-primary-hover font-nav whitespace-nowrap not-typography h-10 py-2 px-4',
226
- '!text-sm rounded-md lg:min-w-[220px] sm:min-w-[220px] flex'
227
- )}>
228
- Pay
229
- </Button>
230
- )}
231
- />
232
- {transactionStatus === 'error' && (
233
- <p className='mx-auto text-destructive'>There was an error processing your payment.</p>
234
- )}
235
- </AccordionContent>
236
- </AccordionItem>
237
- </Accordion>
238
-
239
- </>
240
- )}
241
- </ApplyTypography>
242
- </PaymentForm>
243
- )
244
- }
245
-
246
- export default PayWithCard
@@ -1,18 +0,0 @@
1
- import React from 'react'
2
- import Link from 'next/link'
3
-
4
- import { ApplyTypography } from '@hanzo/ui/primitives'
5
-
6
- import type { StepComponentProps } from './types'
7
-
8
- const ThankYou: React.FC<StepComponentProps> = ({}) => (
9
- <ApplyTypography className='flex flex-col gap-4 text-center mt-10'>
10
- <h3>Thank you for your order!</h3>
11
- <h6>Once your payment has been confirmed we will send additional information to your email.</h6>
12
- <p>
13
- While you wait, we cordially invite you to join the <Link href='https://warpcast.com/~/channel/lux'>Lux Channel</Link> on <Link href='https://warpcast.com/~/invite-page/227706?id=fbc9ca91'>Warpcast</Link>.
14
- </p>
15
- </ApplyTypography>
16
- )
17
-
18
- export default ThankYou
@@ -1,14 +0,0 @@
1
- import type { ComponentType } from 'react'
2
-
3
- export interface StepComponentProps {
4
- onDone: () => void
5
- orderId: string | undefined
6
- setOrderId: (orderId: string | undefined) => void
7
- }
8
-
9
- export interface CheckoutStep {
10
- name: string
11
- label?: string
12
- Comp: ComponentType<StepComponentProps>
13
- }
14
-