|
1 | 1 | 'use client'
|
2 | 2 |
|
3 |
| -import { Button } from '@/components/ui/button' |
| 3 | +import { Button, type ButtonProps } from '@/components/ui/button' |
| 4 | +import { Fragment, useEffect, useState } from 'react' |
4 | 5 | import { loadStripe } from '@stripe/stripe-js'
|
5 |
| -import { useState } from 'react' |
| 6 | +import { LoaderCircle } from 'lucide-react' |
6 | 7 | import { toast } from 'sonner'
|
7 | 8 | import axios from 'axios'
|
8 | 9 |
|
9 |
| -interface CheckoutButtonProps { |
| 10 | +interface CheckoutButtonProps extends ButtonProps { |
10 | 11 | monthly: string
|
11 | 12 | serverId: string | undefined
|
12 | 13 | priceId: string
|
| 14 | + loading?: boolean |
13 | 15 | }
|
14 | 16 |
|
15 | 17 | // sub button
|
16 | 18 | export default function CheckoutButton({
|
17 | 19 | monthly,
|
18 | 20 | serverId,
|
19 |
| - priceId |
| 21 | + priceId, |
| 22 | + loading |
20 | 23 | }: CheckoutButtonProps) {
|
21 |
| - const [loading, setLoading] = useState(false) |
| 24 | + const [isLoading, setIsLoading] = useState(loading) |
| 25 | + |
| 26 | + const handleClick = async () => { |
| 27 | + setIsLoading(true) |
| 28 | + await handleCheckout() |
| 29 | + } |
22 | 30 |
|
23 | 31 | const handleCheckout = async () => {
|
24 |
| - setLoading(true) |
25 |
| - const stripePromise = loadStripe( |
26 |
| - process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY! |
27 |
| - ) |
| 32 | + const stripeKey = process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY |
| 33 | + if (!stripeKey) throw new Error('Stripe key not found') |
| 34 | + |
| 35 | + const stripePromise = loadStripe(stripeKey) |
28 | 36 | const stripe = await stripePromise
|
29 | 37 |
|
30 | 38 | toast.promise(
|
@@ -56,48 +64,24 @@ export default function CheckoutButton({
|
56 | 64 | )
|
57 | 65 | }
|
58 | 66 | )
|
59 |
| - |
60 |
| - setLoading(false) |
61 | 67 | }
|
62 | 68 |
|
| 69 | + useEffect(() => { |
| 70 | + setIsLoading(loading) |
| 71 | + }, [loading]) |
| 72 | + |
63 | 73 | return (
|
64 | 74 | <button
|
65 |
| - disabled={!serverId || loading} |
66 |
| - onClick={handleCheckout} |
| 75 | + type="button" |
67 | 76 | className="ml-auto mt-4 flex w-fit items-center justify-center rounded-lg bg-brand-blue-100 px-5 py-1 text-sm font-bold leading-loose text-white disabled:cursor-not-allowed disabled:bg-background-darker disabled:text-foreground/40"
|
| 77 | + onClick={handleClick} |
| 78 | + disabled={isLoading ? isLoading : !serverId} |
68 | 79 | >
|
69 |
| - {loading ? |
70 |
| - <> |
71 |
| - <svg |
72 |
| - width="100" |
73 |
| - height="101" |
74 |
| - className="mr-2 inline h-4 w-4 animate-spin text-foreground" |
75 |
| - viewBox="0 0 100 101" |
76 |
| - fill="none" |
77 |
| - xmlns="http://www.w3.org/2000/svg" |
78 |
| - > |
79 |
| - <g clip-path="url(#clip0_353_3030)"> |
80 |
| - <path |
81 |
| - d="M100 50.5907C100 78.205 77.6142 100.591 50 100.591C22.3858 100.591 0 78.205 0 50.5907C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5907ZM9.08144 50.5907C9.08144 73.1894 27.4013 91.5092 50 91.5092C72.5987 91.5092 90.9186 73.1894 90.9186 50.5907C90.9186 27.9921 72.5987 9.67224 50 9.67224C27.4013 9.67224 9.08144 27.9921 9.08144 50.5907Z" |
82 |
| - fill="#171717" |
83 |
| - /> |
84 |
| - <path |
85 |
| - d="M93.9683 39.0409C96.3937 38.4038 97.8631 35.9116 97.0086 33.5539C95.2939 28.8227 92.8717 24.3692 89.8174 20.348C85.8459 15.1192 80.8833 10.7238 75.2131 7.41289C69.5429 4.10194 63.2761 1.94025 56.7705 1.05124C51.7673 0.367542 46.6983 0.446844 41.7352 1.27873C39.262 1.69328 37.8137 4.19778 38.4508 6.62326C39.088 9.04874 41.5701 10.4717 44.0512 10.1071C47.8518 9.54855 51.7198 9.52689 55.5409 10.0491C60.8649 10.7766 65.9935 12.5457 70.6338 15.2552C75.2742 17.9648 79.3354 21.5619 82.5856 25.841C84.9182 28.9121 86.8004 32.2913 88.1818 35.8758C89.0837 38.2158 91.5428 39.6781 93.9683 39.0409Z" |
86 |
| - fill="#0598F4" |
87 |
| - /> |
88 |
| - </g> |
89 |
| - <defs> |
90 |
| - <clipPath id="clip0_353_3030"> |
91 |
| - <rect |
92 |
| - width="100" |
93 |
| - height="101" |
94 |
| - fill="white" |
95 |
| - /> |
96 |
| - </clipPath> |
97 |
| - </defs> |
98 |
| - </svg> |
| 80 | + {isLoading ? |
| 81 | + <Fragment> |
| 82 | + <LoaderCircle className="animate-spin size-4 mr-2" /> |
99 | 83 | Loading...
|
100 |
| - </> |
| 84 | + </Fragment> |
101 | 85 | : 'Checkout'}
|
102 | 86 | </button>
|
103 | 87 | )
|
|
0 commit comments