Skip to content

Commit abc2adb

Browse files
committed
fix: pay full amount with gift cart
1 parent 1810b9a commit abc2adb

File tree

4 files changed

+182
-90
lines changed

4 files changed

+182
-90
lines changed

src/modules/checkout/components/payment-button/index.tsx

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import ErrorMessage from "../error-message"
1111
import Spinner from "@modules/common/icons/spinner"
1212

1313
type PaymentButtonProps = {
14-
cart: Omit<Cart, "refundable_amount" | "refunded_total">,
15-
'data-testid': string
14+
cart: Omit<Cart, "refundable_amount" | "refunded_total">
15+
"data-testid": string
1616
}
1717

18-
const PaymentButton: React.FC<PaymentButtonProps> = ({ cart, 'data-testid': dataTestId }) => {
18+
const PaymentButton: React.FC<PaymentButtonProps> = ({
19+
cart,
20+
"data-testid": dataTestId,
21+
}) => {
1922
const notReady =
2023
!cart ||
2124
!cart.shipping_address ||
@@ -25,28 +28,64 @@ const PaymentButton: React.FC<PaymentButtonProps> = ({ cart, 'data-testid': data
2528
? true
2629
: false
2730

31+
const paidByGiftcard =
32+
cart?.gift_cards && cart?.gift_cards?.length > 0 && cart?.total === 0
33+
34+
if (paidByGiftcard) {
35+
return <GiftCardPaymentButton />
36+
}
37+
2838
const paymentSession = cart.payment_session as PaymentSession
2939

3040
switch (paymentSession.provider_id) {
3141
case "stripe":
32-
return <StripePaymentButton notReady={notReady} cart={cart} data-testid={dataTestId} />
42+
return (
43+
<StripePaymentButton
44+
notReady={notReady}
45+
cart={cart}
46+
data-testid={dataTestId}
47+
/>
48+
)
3349
case "manual":
34-
return <ManualTestPaymentButton notReady={notReady} data-testid={dataTestId} />
50+
return (
51+
<ManualTestPaymentButton notReady={notReady} data-testid={dataTestId} />
52+
)
3553
case "paypal":
36-
return <PayPalPaymentButton notReady={notReady} cart={cart} data-testid={dataTestId} />
54+
return (
55+
<PayPalPaymentButton
56+
notReady={notReady}
57+
cart={cart}
58+
data-testid={dataTestId}
59+
/>
60+
)
3761
default:
3862
return <Button disabled>Select a payment method</Button>
3963
}
4064
}
4165

66+
const GiftCardPaymentButton = () => {
67+
const [submitting, setSubmitting] = useState(false)
68+
69+
const handleOrder = async () => {
70+
setSubmitting(true)
71+
await placeOrder()
72+
}
73+
74+
return (
75+
<Button onClick={handleOrder} isLoading={submitting}>
76+
Place order
77+
</Button>
78+
)
79+
}
80+
4281
const StripePaymentButton = ({
4382
cart,
4483
notReady,
45-
'data-testid': dataTestId
84+
"data-testid": dataTestId,
4685
}: {
4786
cart: Omit<Cart, "refundable_amount" | "refunded_total">
4887
notReady: boolean
49-
'data-testid'?: string
88+
"data-testid"?: string
5089
}) => {
5190
const [submitting, setSubmitting] = useState(false)
5291
const [errorMessage, setErrorMessage] = useState<string | null>(null)
@@ -133,19 +172,22 @@ const StripePaymentButton = ({
133172
>
134173
Place order
135174
</Button>
136-
<ErrorMessage error={errorMessage} data-testid="stripe-payment-error-message" />
175+
<ErrorMessage
176+
error={errorMessage}
177+
data-testid="stripe-payment-error-message"
178+
/>
137179
</>
138180
)
139181
}
140182

141183
const PayPalPaymentButton = ({
142184
cart,
143185
notReady,
144-
'data-testid': dataTestId
186+
"data-testid": dataTestId,
145187
}: {
146188
cart: Omit<Cart, "refundable_amount" | "refunded_total">
147189
notReady: boolean
148-
'data-testid'?: string
190+
"data-testid"?: string
149191
}) => {
150192
const [submitting, setSubmitting] = useState(false)
151193
const [errorMessage, setErrorMessage] = useState<string | null>(null)
@@ -194,7 +236,10 @@ const PayPalPaymentButton = ({
194236
disabled={notReady || submitting || isPending}
195237
data-testid={dataTestId}
196238
/>
197-
<ErrorMessage error={errorMessage} data-testid="paypal-payment-error-message" />
239+
<ErrorMessage
240+
error={errorMessage}
241+
data-testid="paypal-payment-error-message"
242+
/>
198243
</>
199244
)
200245
}
@@ -228,7 +273,10 @@ const ManualTestPaymentButton = ({ notReady }: { notReady: boolean }) => {
228273
>
229274
Place order
230275
</Button>
231-
<ErrorMessage error={errorMessage} data-testid="manual-payment-error-message" />
276+
<ErrorMessage
277+
error={errorMessage}
278+
data-testid="manual-payment-error-message"
279+
/>
232280
</>
233281
)
234282
}

src/modules/checkout/components/payment/index.tsx

Lines changed: 105 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,12 @@ const Payment = ({
3636
const isStripe = cart?.payment_session?.provider_id === "stripe"
3737
const stripeReady = useContext(StripeContext)
3838

39+
const paidByGiftcard =
40+
cart?.gift_cards && cart?.gift_cards?.length > 0 && cart?.total === 0
41+
3942
const paymentReady =
40-
cart?.payment_session && cart?.shipping_methods.length !== 0
43+
(cart?.payment_session && cart?.shipping_methods.length !== 0) ||
44+
paidByGiftcard
4145

4246
const useOptions: StripeCardElementOptions = useMemo(() => {
4347
return {
@@ -128,77 +132,99 @@ const Payment = ({
128132
)}
129133
</div>
130134
<div>
131-
{cart?.payment_sessions?.length ? (
132-
<div className={isOpen ? "block" : "hidden"}>
133-
<RadioGroup
134-
value={cart.payment_session?.provider_id || ""}
135-
onChange={(value: string) => handleChange(value)}
136-
>
137-
{cart.payment_sessions
138-
.sort((a, b) => {
139-
return a.provider_id > b.provider_id ? 1 : -1
140-
})
141-
.map((paymentSession) => {
142-
return (
143-
<PaymentContainer
144-
paymentInfoMap={paymentInfoMap}
145-
paymentSession={paymentSession}
146-
key={paymentSession.id}
147-
selectedPaymentOptionId={
148-
cart.payment_session?.provider_id || null
149-
}
150-
/>
151-
)
152-
})}
153-
</RadioGroup>
154-
155-
{isStripe && stripeReady && (
156-
<div className="mt-5 transition-all duration-150 ease-in-out">
157-
<Text className="txt-medium-plus text-ui-fg-base mb-1">
158-
Enter your card details:
159-
</Text>
160-
161-
<CardElement
162-
options={useOptions as StripeCardElementOptions}
163-
onChange={(e) => {
164-
setCardBrand(
165-
e.brand &&
166-
e.brand.charAt(0).toUpperCase() + e.brand.slice(1)
135+
<div className={isOpen ? "block" : "hidden"}>
136+
{!paidByGiftcard && cart?.payment_sessions?.length ? (
137+
<>
138+
<RadioGroup
139+
value={cart.payment_session?.provider_id || ""}
140+
onChange={(value: string) => handleChange(value)}
141+
>
142+
{cart.payment_sessions
143+
.sort((a, b) => {
144+
return a.provider_id > b.provider_id ? 1 : -1
145+
})
146+
.map((paymentSession) => {
147+
return (
148+
<PaymentContainer
149+
paymentInfoMap={paymentInfoMap}
150+
paymentSession={paymentSession}
151+
key={paymentSession.id}
152+
selectedPaymentOptionId={
153+
cart.payment_session?.provider_id || null
154+
}
155+
/>
167156
)
168-
setError(e.error?.message || null)
169-
setCardComplete(e.complete)
170-
}}
171-
/>
172-
</div>
173-
)}
157+
})}
158+
</RadioGroup>
159+
{isStripe && stripeReady && (
160+
<div className="mt-5 transition-all duration-150 ease-in-out">
161+
<Text className="txt-medium-plus text-ui-fg-base mb-1">
162+
Enter your card details:
163+
</Text>
164+
165+
<CardElement
166+
options={useOptions as StripeCardElementOptions}
167+
onChange={(e) => {
168+
setCardBrand(
169+
e.brand &&
170+
e.brand.charAt(0).toUpperCase() + e.brand.slice(1)
171+
)
172+
setError(e.error?.message || null)
173+
setCardComplete(e.complete)
174+
}}
175+
/>
176+
</div>
177+
)}
178+
</>
179+
) : paidByGiftcard ? (
180+
<div className="flex flex-col w-1/3">
181+
<Text className="txt-medium-plus text-ui-fg-base mb-1">
182+
Payment method
183+
</Text>
184+
<Text
185+
className="txt-medium text-ui-fg-subtle"
186+
data-testid="payment-method-summary"
187+
>
188+
Gift card
189+
</Text>
190+
</div>
191+
) : (
192+
<div className="flex flex-col items-center justify-center px-4 py-16 text-ui-fg-base">
193+
<Spinner />
194+
</div>
195+
)}
174196

175-
<ErrorMessage error={error} data-testid="payment-method-error-message" />
197+
<ErrorMessage
198+
error={error}
199+
data-testid="payment-method-error-message"
200+
/>
176201

177-
<Button
178-
size="large"
179-
className="mt-6"
180-
onClick={handleSubmit}
181-
isLoading={isLoading}
182-
disabled={(isStripe && !cardComplete) || !cart.payment_session}
183-
data-testid="submit-payment-button"
184-
>
185-
Continue to review
186-
</Button>
187-
</div>
188-
) : (
189-
<div className="flex flex-col items-center justify-center px-4 py-16 text-ui-fg-base">
190-
<Spinner />
191-
</div>
192-
)}
202+
<Button
203+
size="large"
204+
className="mt-6"
205+
onClick={handleSubmit}
206+
isLoading={isLoading}
207+
disabled={
208+
(isStripe && !cardComplete) ||
209+
(!cart?.payment_session && !paidByGiftcard)
210+
}
211+
data-testid="submit-payment-button"
212+
>
213+
Continue to review
214+
</Button>
215+
</div>
193216

194217
<div className={isOpen ? "hidden" : "block"}>
195-
{cart && paymentReady && cart.payment_session && (
218+
{cart && paymentReady && cart.payment_session ? (
196219
<div className="flex items-start gap-x-1 w-full">
197220
<div className="flex flex-col w-1/3">
198221
<Text className="txt-medium-plus text-ui-fg-base mb-1">
199222
Payment method
200223
</Text>
201-
<Text className="txt-medium text-ui-fg-subtle" data-testid="payment-method-summary">
224+
<Text
225+
className="txt-medium text-ui-fg-subtle"
226+
data-testid="payment-method-summary"
227+
>
202228
{paymentInfoMap[cart.payment_session.provider_id]?.title ||
203229
cart.payment_session.provider_id}
204230
</Text>
@@ -214,7 +240,10 @@ const Payment = ({
214240
<Text className="txt-medium-plus text-ui-fg-base mb-1">
215241
Payment details
216242
</Text>
217-
<div className="flex gap-2 txt-medium text-ui-fg-subtle items-center" data-testid="payment-details-summary">
243+
<div
244+
className="flex gap-2 txt-medium text-ui-fg-subtle items-center"
245+
data-testid="payment-details-summary"
246+
>
218247
<Container className="flex items-center h-7 w-fit p-2 bg-ui-button-neutral-hover">
219248
{paymentInfoMap[cart.payment_session.provider_id]?.icon || (
220249
<CreditCard />
@@ -228,7 +257,19 @@ const Payment = ({
228257
</div>
229258
</div>
230259
</div>
231-
)}
260+
) : paidByGiftcard ? (
261+
<div className="flex flex-col w-1/3">
262+
<Text className="txt-medium-plus text-ui-fg-base mb-1">
263+
Payment method
264+
</Text>
265+
<Text
266+
className="txt-medium text-ui-fg-subtle"
267+
data-testid="payment-method-summary"
268+
>
269+
Gift card
270+
</Text>
271+
</div>
272+
) : null}
232273
</div>
233274
</div>
234275
<Divider className="mt-8" />

src/modules/checkout/components/review/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@ const Review = ({
1515

1616
const isOpen = searchParams.get("step") === "review"
1717

18+
const paidByGiftcard =
19+
cart?.gift_cards && cart?.gift_cards?.length > 0 && cart?.total === 0
20+
1821
const previousStepsCompleted =
1922
cart.shipping_address &&
2023
cart.shipping_methods.length > 0 &&
21-
cart.payment_session
24+
(cart.payment_session || paidByGiftcard)
2225

2326
return (
2427
<div className="bg-white">

src/modules/common/components/cart-totals/index.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,18 +54,6 @@ const CartTotals: React.FC<CartTotalsProps> = ({ data }) => {
5454
</span>
5555
</div>
5656
)}
57-
{!!gift_card_total && (
58-
<div className="flex items-center justify-between">
59-
<span>Gift card</span>
60-
<span
61-
className="text-ui-fg-interactive"
62-
data-testid="cart-gift-card-amount"
63-
data-value={gift_card_total || 0}
64-
>
65-
- {getAmount(gift_card_total)}
66-
</span>
67-
</div>
68-
)}
6957
<div className="flex items-center justify-between">
7058
<span>Shipping</span>
7159
<span data-testid="cart-shipping" data-value={shipping_total || 0}>
@@ -78,6 +66,18 @@ const CartTotals: React.FC<CartTotalsProps> = ({ data }) => {
7866
{getAmount(tax_total)}
7967
</span>
8068
</div>
69+
{!!gift_card_total && (
70+
<div className="flex items-center justify-between">
71+
<span>Gift card</span>
72+
<span
73+
className="text-ui-fg-interactive"
74+
data-testid="cart-gift-card-amount"
75+
data-value={gift_card_total || 0}
76+
>
77+
- {getAmount(gift_card_total)}
78+
</span>
79+
</div>
80+
)}
8181
</div>
8282
<div className="h-px w-full border-b border-gray-200 my-4" />
8383
<div className="flex items-center justify-between text-ui-fg-base mb-2 txt-medium ">

0 commit comments

Comments
 (0)