Fix stripe. Remove fetching prices in getServerSideProps
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import {useState} from 'react'
|
import {useState, useEffect} from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import {
|
import {
|
||||||
PaymentElement,
|
PaymentElement,
|
||||||
@@ -9,11 +9,11 @@ import {Button, Container, LinearProgress, Paper} from '@mui/material'
|
|||||||
|
|
||||||
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
|
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
|
||||||
|
|
||||||
export default function CheckoutForm({prices, validMontant, setError, isLoading, setIsLoading}) {
|
export default function CheckoutForm({validMontant, setError, isLoading, setIsLoading}) {
|
||||||
const stripe = useStripe()
|
const stripe = useStripe()
|
||||||
const elements = useElements()
|
const elements = useElements()
|
||||||
const [isPaymentLoading, setIsPaymentLoading] = useState(false)
|
const [isPaymentLoading, setIsPaymentLoading] = useState(false)
|
||||||
const amount = prices.find(({id}) => id === validMontant).unit_amount
|
const [prices, setPrices] = useState([])
|
||||||
|
|
||||||
const handleSubmit = async event => {
|
const handleSubmit = async event => {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
@@ -44,13 +44,27 @@ export default function CheckoutForm({prices, validMontant, setError, isLoading,
|
|||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchPrices = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${SITE_URL}/stripe/dons-list`)
|
||||||
|
const pricesList = await response.json()
|
||||||
|
setPrices(pricesList)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('error', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchPrices()
|
||||||
|
}, [prices])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth='sm' sx={{marginBottom: 1}}>
|
<Container maxWidth='sm' sx={{marginBottom: 1}}>
|
||||||
<Paper sx={{padding: 2, marginTop: 3}}>
|
<Paper sx={{padding: 2, marginTop: 3}}>
|
||||||
<PaymentElement id='payment-element' onReady={handleReady} />
|
<PaymentElement id='payment-element' onReady={handleReady} />
|
||||||
{!isLoading && (
|
{!isLoading && (
|
||||||
<Button fullWidth sx={{marginTop: 2}} variant='outlined' disabled={isPaymentLoading || !stripe || !elements} id='submit' onClick={handleSubmit}>
|
<Button fullWidth sx={{marginTop: 2}} variant='outlined' disabled={isPaymentLoading || !stripe || !elements} id='submit' onClick={handleSubmit}>
|
||||||
Valider le don de <strong>{amount / 100} euros</strong>
|
Valider le don de <strong>{prices.find(({id}) => id === validMontant).unit_amount / 100} euros</strong>
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{isPaymentLoading && (
|
{isPaymentLoading && (
|
||||||
@@ -63,7 +77,6 @@ export default function CheckoutForm({prices, validMontant, setError, isLoading,
|
|||||||
|
|
||||||
CheckoutForm.propTypes = {
|
CheckoutForm.propTypes = {
|
||||||
validMontant: PropTypes.string.isRequired,
|
validMontant: PropTypes.string.isRequired,
|
||||||
prices: PropTypes.array.isRequired,
|
|
||||||
setError: PropTypes.func.isRequired,
|
setError: PropTypes.func.isRequired,
|
||||||
isLoading: PropTypes.bool.isRequired,
|
isLoading: PropTypes.bool.isRequired,
|
||||||
setIsLoading: PropTypes.func.isRequired
|
setIsLoading: PropTypes.func.isRequired
|
||||||
|
|||||||
@@ -1,14 +1,33 @@
|
|||||||
|
import {useState, useEffect} from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import ToggleButton from '@mui/material/ToggleButton'
|
import ToggleButton from '@mui/material/ToggleButton'
|
||||||
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
|
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
|
||||||
import Typography from '@mui/material/Typography'
|
import Typography from '@mui/material/Typography'
|
||||||
import {Box} from '@mui/material'
|
import {Box} from '@mui/material'
|
||||||
|
import CircularProgress from '@mui/material/CircularProgress'
|
||||||
|
|
||||||
export default function Montant({selectedMontant, setSelectedMontant, validMontant, prices}) {
|
const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3001'
|
||||||
|
|
||||||
|
export default function Montant({selectedMontant, setSelectedMontant, validMontant}) {
|
||||||
|
const [prices, setPrices] = useState(null)
|
||||||
const handleChange = (event, newMontant) => {
|
const handleChange = (event, newMontant) => {
|
||||||
setSelectedMontant(newMontant)
|
setSelectedMontant(newMontant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchPrices = async () => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${SITE_URL}/stripe/dons-list`)
|
||||||
|
const pricesList = await response.json()
|
||||||
|
setPrices(pricesList)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('error', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchPrices()
|
||||||
|
}, [prices])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Typography marginTop={1} variant='button' component='div'>
|
<Typography marginTop={1} variant='button' component='div'>
|
||||||
@@ -22,7 +41,11 @@ export default function Montant({selectedMontant, setSelectedMontant, validMonta
|
|||||||
value={selectedMontant}
|
value={selectedMontant}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
>
|
>
|
||||||
{prices.map(r => (
|
{!prices && (
|
||||||
|
<CircularProgress color='primary' size={20} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{prices && prices.map(r => (
|
||||||
<ToggleButton key={r.id} value={r.id}>{r.unit_amount / 100} €</ToggleButton>
|
<ToggleButton key={r.id} value={r.id}>{r.unit_amount / 100} €</ToggleButton>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@@ -39,6 +62,5 @@ Montant.defaultProps = {
|
|||||||
Montant.propTypes = {
|
Montant.propTypes = {
|
||||||
selectedMontant: PropTypes.string,
|
selectedMontant: PropTypes.string,
|
||||||
setSelectedMontant: PropTypes.func.isRequired,
|
setSelectedMontant: PropTypes.func.isRequired,
|
||||||
validMontant: PropTypes.string,
|
validMontant: PropTypes.string
|
||||||
prices: PropTypes.array.isRequired
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,7 @@ import {appearance} from '../../lib/utils/stripe-style'
|
|||||||
import CheckoutForm from './checkout-form'
|
import CheckoutForm from './checkout-form'
|
||||||
import StripeDialog from './stripe-dialog'
|
import StripeDialog from './stripe-dialog'
|
||||||
|
|
||||||
const stripePromise = loadStripe(
|
const STRIPE_PUBLIC_KEY = process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY
|
||||||
process.env.NEXT_PUBLIC_STRIPE_PUBLIC_KEY
|
|
||||||
)
|
|
||||||
|
|
||||||
const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID
|
const PAYPAL_ID = process.env.NEXT_PUBLIC_PAYPAL_DONATE_ID
|
||||||
const LIBERAPAY_DONATE = process.env.NEXT_PUBLIC_LIBERAPAY_DONATE
|
const LIBERAPAY_DONATE = process.env.NEXT_PUBLIC_LIBERAPAY_DONATE
|
||||||
|
|
||||||
@@ -55,7 +52,7 @@ function a11yProps(index) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function PaymentMethod({isLoading, paymentMethod, setPaymentMethod, selectedMontant, setSelectedMontant, validMontant, setValidMontant, prices, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, clientSecret}) {
|
export default function PaymentMethod({isLoading, paymentMethod, setPaymentMethod, selectedMontant, setSelectedMontant, validMontant, setValidMontant, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, clientSecret}) {
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
@@ -114,7 +111,6 @@ export default function PaymentMethod({isLoading, paymentMethod, setPaymentMetho
|
|||||||
setSelectedMontant={setSelectedMontant}
|
setSelectedMontant={setSelectedMontant}
|
||||||
validMontant={validMontant}
|
validMontant={validMontant}
|
||||||
setValidMontant={setValidMontant}
|
setValidMontant={setValidMontant}
|
||||||
prices={prices}
|
|
||||||
paymentIntent={paymentIntent}
|
paymentIntent={paymentIntent}
|
||||||
setClientSecret={setClientSecret}
|
setClientSecret={setClientSecret}
|
||||||
setPaymentIntent={setPaymentIntent}
|
setPaymentIntent={setPaymentIntent}
|
||||||
@@ -126,9 +122,8 @@ export default function PaymentMethod({isLoading, paymentMethod, setPaymentMetho
|
|||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
>
|
>
|
||||||
{clientSecret && validMontant && paymentMethod === 2 && (
|
{clientSecret && validMontant && paymentMethod === 2 && (
|
||||||
<Elements options={options} stripe={stripePromise}>
|
<Elements options={options} stripe={loadStripe(STRIPE_PUBLIC_KEY)}>
|
||||||
<CheckoutForm
|
<CheckoutForm
|
||||||
prices={prices}
|
|
||||||
validMontant={validMontant}
|
validMontant={validMontant}
|
||||||
setError={setError}
|
setError={setError}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
@@ -159,7 +154,6 @@ PaymentMethod.propTypes = {
|
|||||||
setSelectedMontant: PropTypes.func.isRequired,
|
setSelectedMontant: PropTypes.func.isRequired,
|
||||||
validMontant: PropTypes.string,
|
validMontant: PropTypes.string,
|
||||||
setValidMontant: PropTypes.func.isRequired,
|
setValidMontant: PropTypes.func.isRequired,
|
||||||
prices: PropTypes.array.isRequired,
|
|
||||||
paymentIntent: PropTypes.string,
|
paymentIntent: PropTypes.string,
|
||||||
setClientSecret: PropTypes.func.isRequired,
|
setClientSecret: PropTypes.func.isRequired,
|
||||||
setPaymentIntent: PropTypes.func.isRequired,
|
setPaymentIntent: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ export default function StripeDialog({
|
|||||||
setSelectedMontant,
|
setSelectedMontant,
|
||||||
validMontant,
|
validMontant,
|
||||||
setValidMontant,
|
setValidMontant,
|
||||||
prices,
|
|
||||||
paymentIntent,
|
paymentIntent,
|
||||||
setClientSecret,
|
setClientSecret,
|
||||||
setPaymentIntent,
|
setPaymentIntent,
|
||||||
@@ -46,7 +45,6 @@ export default function StripeDialog({
|
|||||||
setSelectedMontant={setSelectedMontant}
|
setSelectedMontant={setSelectedMontant}
|
||||||
validMontant={validMontant}
|
validMontant={validMontant}
|
||||||
setValidMontant={setValidMontant}
|
setValidMontant={setValidMontant}
|
||||||
prices={prices}
|
|
||||||
paymentIntent={paymentIntent}
|
paymentIntent={paymentIntent}
|
||||||
setClientSecret={setClientSecret}
|
setClientSecret={setClientSecret}
|
||||||
setPaymentIntent={setPaymentIntent}
|
setPaymentIntent={setPaymentIntent}
|
||||||
@@ -56,6 +54,7 @@ export default function StripeDialog({
|
|||||||
error={error}
|
error={error}
|
||||||
setError={setError}
|
setError={setError}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
|
handleClose={handleClose}
|
||||||
/>
|
/>
|
||||||
{children}
|
{children}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@@ -81,7 +80,6 @@ StripeDialog.propTypes = {
|
|||||||
setSelectedMontant: PropTypes.func.isRequired,
|
setSelectedMontant: PropTypes.func.isRequired,
|
||||||
validMontant: PropTypes.string,
|
validMontant: PropTypes.string,
|
||||||
setValidMontant: PropTypes.func.isRequired,
|
setValidMontant: PropTypes.func.isRequired,
|
||||||
prices: PropTypes.array.isRequired,
|
|
||||||
paymentIntent: PropTypes.string,
|
paymentIntent: PropTypes.string,
|
||||||
setClientSecret: PropTypes.func.isRequired,
|
setClientSecret: PropTypes.func.isRequired,
|
||||||
setPaymentIntent: PropTypes.func.isRequired,
|
setPaymentIntent: PropTypes.func.isRequired,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {validateEmail} from '../../lib/utils/emails'
|
|||||||
import Email from './email'
|
import Email from './email'
|
||||||
import Montant from './montant'
|
import Montant from './montant'
|
||||||
|
|
||||||
export default function StripePayment({isLoading, selectedMontant, setSelectedMontant, validMontant, setValidMontant, prices, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError}) {
|
export default function StripePayment({isLoading, selectedMontant, setSelectedMontant, validMontant, setValidMontant, paymentIntent, setClientSecret, setPaymentIntent, setIsLoading, setClientEmail, clientEmail, error, setError, handleClose}) {
|
||||||
const cancelPayment = async () => {
|
const cancelPayment = async () => {
|
||||||
setClientEmail('')
|
setClientEmail('')
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
@@ -29,9 +29,14 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleCancel = async () => {
|
const handleCancel = async () => {
|
||||||
setValidMontant(null)
|
if (validMontant) {
|
||||||
setSelectedMontant(null)
|
setValidMontant(null)
|
||||||
await cancelPayment()
|
setSelectedMontant(null)
|
||||||
|
await cancelPayment()
|
||||||
|
handleClose()
|
||||||
|
} else {
|
||||||
|
handleClose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
@@ -59,7 +64,6 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
|
|||||||
setSelectedMontant={setSelectedMontant}
|
setSelectedMontant={setSelectedMontant}
|
||||||
validMontant={validMontant}
|
validMontant={validMontant}
|
||||||
setValidMontant={setValidMontant}
|
setValidMontant={setValidMontant}
|
||||||
prices={prices}
|
|
||||||
paymentIntent={paymentIntent}
|
paymentIntent={paymentIntent}
|
||||||
setClientSecret={setClientSecret}
|
setClientSecret={setClientSecret}
|
||||||
setPaymentIntent={setPaymentIntent}
|
setPaymentIntent={setPaymentIntent}
|
||||||
@@ -71,11 +75,10 @@ export default function StripePayment({isLoading, selectedMontant, setSelectedMo
|
|||||||
<Button disabled={Boolean(validMontant) || Boolean(!selectedMontant)} variant='contained' onClick={handleClick}>
|
<Button disabled={Boolean(validMontant) || Boolean(!selectedMontant)} variant='contained' onClick={handleClick}>
|
||||||
Valider les informations
|
Valider les informations
|
||||||
</Button>
|
</Button>
|
||||||
{validMontant && (
|
|
||||||
<Button disabled={Boolean(!validMontant)} color='secondary' variant='contained' onClick={handleCancel}>
|
<Button color='secondary' variant='contained' onClick={handleCancel}>
|
||||||
Annuler
|
Annuler
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</>
|
</>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
@@ -102,7 +105,6 @@ StripePayment.propTypes = {
|
|||||||
setSelectedMontant: PropTypes.func.isRequired,
|
setSelectedMontant: PropTypes.func.isRequired,
|
||||||
validMontant: PropTypes.string,
|
validMontant: PropTypes.string,
|
||||||
setValidMontant: PropTypes.func.isRequired,
|
setValidMontant: PropTypes.func.isRequired,
|
||||||
prices: PropTypes.array.isRequired,
|
|
||||||
paymentIntent: PropTypes.string,
|
paymentIntent: PropTypes.string,
|
||||||
setClientSecret: PropTypes.func.isRequired,
|
setClientSecret: PropTypes.func.isRequired,
|
||||||
setPaymentIntent: PropTypes.func.isRequired,
|
setPaymentIntent: PropTypes.func.isRequired,
|
||||||
@@ -110,5 +112,6 @@ StripePayment.propTypes = {
|
|||||||
setClientEmail: PropTypes.func.isRequired,
|
setClientEmail: PropTypes.func.isRequired,
|
||||||
clientEmail: PropTypes.string,
|
clientEmail: PropTypes.string,
|
||||||
error: PropTypes.string,
|
error: PropTypes.string,
|
||||||
setError: PropTypes.func.isRequired
|
setError: PropTypes.func.isRequired,
|
||||||
|
handleClose: PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-7
@@ -16,7 +16,7 @@ const Alert = forwardRef(function Alert(props, ref) {
|
|||||||
return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
|
return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function Soutyen({prices, paymentStatus}) {
|
export default function Soutyen({paymentStatus}) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const scrollEvent = useRef(null)
|
const scrollEvent = useRef(null)
|
||||||
const [clientSecret, setClientSecret] = useState(null)
|
const [clientSecret, setClientSecret] = useState(null)
|
||||||
@@ -60,7 +60,7 @@ export default function Soutyen({prices, paymentStatus}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (paymentMethod !== 0) {
|
if (paymentMethod !== 2) {
|
||||||
setClientEmail('')
|
setClientEmail('')
|
||||||
setClientSecret(null)
|
setClientSecret(null)
|
||||||
setSelectedMontant(null)
|
setSelectedMontant(null)
|
||||||
@@ -124,7 +124,7 @@ export default function Soutyen({prices, paymentStatus}) {
|
|||||||
>
|
>
|
||||||
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
|
<Box sx={{display: 'flex', flexDirection: 'column', minHeight: '100vh'}}>
|
||||||
<Box sx={{flexGrow: 1, marginTop: 1, marginBottom: 10}}>
|
<Box sx={{flexGrow: 1, marginTop: 1, marginBottom: 10}}>
|
||||||
<Container sx={{marginTop: 1}}>
|
<Container sx={{marginTop: 3}}>
|
||||||
<Typography gutterBottom sx={{fontWeight: 'bold'}} textAlign='center' variant='h4' component='h1'>
|
<Typography gutterBottom sx={{fontWeight: 'bold'}} textAlign='center' variant='h4' component='h1'>
|
||||||
Soutenir Organisation KA Internationale !
|
Soutenir Organisation KA Internationale !
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -138,7 +138,6 @@ export default function Soutyen({prices, paymentStatus}) {
|
|||||||
setSelectedMontant={setSelectedMontant}
|
setSelectedMontant={setSelectedMontant}
|
||||||
validMontant={validMontant}
|
validMontant={validMontant}
|
||||||
setValidMontant={setValidMontant}
|
setValidMontant={setValidMontant}
|
||||||
prices={prices}
|
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
paymentIntent={paymentIntent}
|
paymentIntent={paymentIntent}
|
||||||
clientSecret={clientSecret}
|
clientSecret={clientSecret}
|
||||||
@@ -173,13 +172,11 @@ Soutyen.defaultProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Soutyen.propTypes = {
|
Soutyen.propTypes = {
|
||||||
prices: PropTypes.array.isRequired,
|
|
||||||
paymentStatus: PropTypes.string
|
paymentStatus: PropTypes.string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getServerSideProps({query}) {
|
export async function getServerSideProps({query}) {
|
||||||
const {payment_intent, payment_intent_client_secret} = query
|
const {payment_intent, payment_intent_client_secret} = query
|
||||||
const prices = await fetch(`${SITE_URL}/stripe/dons-list`)
|
|
||||||
let payment
|
let payment
|
||||||
if (payment_intent && payment_intent_client_secret) {
|
if (payment_intent && payment_intent_client_secret) {
|
||||||
const paymentResponse = await fetch(`${SITE_URL}/stripe/check-payment`, {
|
const paymentResponse = await fetch(`${SITE_URL}/stripe/check-payment`, {
|
||||||
@@ -198,7 +195,6 @@ export async function getServerSideProps({query}) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
prices: await prices.json(),
|
|
||||||
paymentStatus: payment?.status || null
|
paymentStatus: payment?.status || null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user