feat: fixes and formatter
This commit is contained in:
+186
-243
@@ -1,386 +1,340 @@
|
||||
import React from "react";
|
||||
import { Linking, Platform, StyleSheet, View } from "react-native";
|
||||
import {
|
||||
EmbeddedCheckout,
|
||||
EmbeddedCheckoutProvider,
|
||||
} from "@stripe/react-stripe-js";
|
||||
import { loadStripe } from "@stripe/stripe-js";
|
||||
import * as WebBrowser from "expo-web-browser";
|
||||
import Overlay from "../components/Overlay";
|
||||
import Button from "../components/Button";
|
||||
import useLayoutType from "../hooks/useLayoutType";
|
||||
import { mainBorderRadius } from "../styles/Style";
|
||||
import {
|
||||
STRIPE_PUBLISHABLE_KEY_LIVE,
|
||||
STRIPE_PUBLISHABLE_KEY_TEST,
|
||||
} from "../data/keys";
|
||||
import { getFunctionsClient } from "../config/firebase";
|
||||
import { isWeb } from "../hooks/useLayoutType";
|
||||
import { useUserData } from "./UserDataProvider";
|
||||
import { formatDate, toDate } from "../utils/dateFormatting";
|
||||
import React from 'react'
|
||||
import { Linking, Platform, StyleSheet, View } from 'react-native'
|
||||
import { EmbeddedCheckout, EmbeddedCheckoutProvider } from '@stripe/react-stripe-js'
|
||||
import { loadStripe } from '@stripe/stripe-js'
|
||||
import * as WebBrowser from 'expo-web-browser'
|
||||
import Overlay from '../components/Overlay'
|
||||
import Button from '../components/Button'
|
||||
import useLayoutType from '../hooks/useLayoutType'
|
||||
import { mainBorderRadius } from '../styles/Style'
|
||||
import { STRIPE_PUBLISHABLE_KEY_LIVE, STRIPE_PUBLISHABLE_KEY_TEST } from '../data/keys'
|
||||
import { getFunctionsClient } from '../config/firebase'
|
||||
import { isWeb } from '../hooks/useLayoutType'
|
||||
import { useUserData } from './UserDataProvider'
|
||||
import { formatDate, toDate } from '../utils/dateFormatting'
|
||||
|
||||
const FUNCTIONS_REGION = "europe-west1";
|
||||
const FUNCTIONS_REGION = 'europe-west1'
|
||||
const STRIPE_SUCCESS_URL =
|
||||
"https://dashboard.stripe.com/test/billing/starter-guide/checkout-success";
|
||||
const STRIPE_CANCEL_URL = STRIPE_SUCCESS_URL;
|
||||
'https://dashboard.stripe.com/test/billing/starter-guide/checkout-success'
|
||||
const STRIPE_CANCEL_URL = STRIPE_SUCCESS_URL
|
||||
|
||||
const isStripeTesting = true;
|
||||
const isStripeTesting = true
|
||||
const rawStripePublishableKey = isStripeTesting
|
||||
? STRIPE_PUBLISHABLE_KEY_TEST
|
||||
: STRIPE_PUBLISHABLE_KEY_LIVE;
|
||||
: STRIPE_PUBLISHABLE_KEY_LIVE
|
||||
const stripePublishableKey =
|
||||
typeof rawStripePublishableKey === "string"
|
||||
? rawStripePublishableKey.trim()
|
||||
: "";
|
||||
const stripePromise = stripePublishableKey
|
||||
? loadStripe(stripePublishableKey)
|
||||
: null;
|
||||
typeof rawStripePublishableKey === 'string' ? rawStripePublishableKey.trim() : ''
|
||||
const stripePromise = stripePublishableKey ? loadStripe(stripePublishableKey) : null
|
||||
|
||||
if (!stripePublishableKey) {
|
||||
console.warn(
|
||||
"[StripeProvider] Aucune clé publique Stripe fournie, le checkout intégré sera désactivé.",
|
||||
);
|
||||
'[StripeProvider] Aucune clé publique Stripe fournie, le checkout intégré sera désactivé.'
|
||||
)
|
||||
}
|
||||
|
||||
const isSafariBrowser = () => {
|
||||
if (
|
||||
typeof navigator !== "object" ||
|
||||
typeof navigator.userAgent !== "string"
|
||||
) {
|
||||
return false;
|
||||
if (typeof navigator !== 'object' || typeof navigator.userAgent !== 'string') {
|
||||
return false
|
||||
}
|
||||
return (
|
||||
/safari/i.test(navigator.userAgent) &&
|
||||
!/(chrome|crios|android|fxios|edgios|opr|ucbrowser)/i.test(
|
||||
navigator.userAgent,
|
||||
)
|
||||
);
|
||||
};
|
||||
!/(chrome|crios|android|fxios|edgios|opr|ucbrowser)/i.test(navigator.userAgent)
|
||||
)
|
||||
}
|
||||
|
||||
const openSafariCheckoutWindow = () => {
|
||||
if (!isWeb || typeof window === "undefined") {
|
||||
return null;
|
||||
if (!isWeb || typeof window === 'undefined') {
|
||||
return null
|
||||
}
|
||||
if (!isSafariBrowser()) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
try {
|
||||
const placeholder = window.open("", "_blank", "noopener,noreferrer");
|
||||
const placeholder = window.open('', '_blank', 'noopener,noreferrer')
|
||||
if (!placeholder) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
try {
|
||||
placeholder.document.write(
|
||||
"<p style='font-family: sans-serif; color: #111; padding: 16px;'>Chargement du paiement Stripe...</p>",
|
||||
);
|
||||
placeholder.document.title = "Stripe Checkout";
|
||||
"<p style='font-family: sans-serif; color: #111; padding: 16px;'>Chargement du paiement Stripe...</p>"
|
||||
)
|
||||
placeholder.document.title = 'Stripe Checkout'
|
||||
} catch {
|
||||
// Ignore failures when the window gets reused or is cross-domain.
|
||||
}
|
||||
placeholder.focus?.();
|
||||
return placeholder;
|
||||
placeholder.focus?.()
|
||||
return placeholder
|
||||
} catch (error) {
|
||||
console.warn("[StripeProvider] Safari window pre-open failed", error);
|
||||
return null;
|
||||
console.warn('[StripeProvider] Safari window pre-open failed', error)
|
||||
return null
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export const StripeContext = React.createContext(null);
|
||||
export const StripeContext = React.createContext(null)
|
||||
|
||||
export const useStripe = () => {
|
||||
const context = React.useContext(StripeContext);
|
||||
const context = React.useContext(StripeContext)
|
||||
if (!context) {
|
||||
throw new Error("useStripe must be used within a StripeProvider");
|
||||
throw new Error('useStripe must be used within a StripeProvider')
|
||||
}
|
||||
return context;
|
||||
};
|
||||
return context
|
||||
}
|
||||
|
||||
const StripeProvider = ({ children }) => {
|
||||
const { isMobile } = useLayoutType();
|
||||
const { currentUserData } = useUserData() || {};
|
||||
const canUseEmbeddedCheckout = isWeb && Boolean(stripePromise);
|
||||
const { isMobile } = useLayoutType()
|
||||
const { currentUserData } = useUserData() || {}
|
||||
const canUseEmbeddedCheckout = isWeb && Boolean(stripePromise)
|
||||
|
||||
const [clientSecret, setClientSecret] = React.useState(null);
|
||||
const [clientSecret, setClientSecret] = React.useState(null)
|
||||
const [subscriptions, setSubscriptions] = React.useState({
|
||||
monthly: [],
|
||||
annual: [],
|
||||
});
|
||||
const [coinPacks, setCoinPacks] = React.useState([]);
|
||||
const [isCatalogLoading, setIsCatalogLoading] = React.useState(true);
|
||||
const [catalogError, setCatalogError] = React.useState(null);
|
||||
const [activeSubscription, setActiveSubscription] = React.useState(null);
|
||||
const [isActiveSubscriptionLoading, setIsActiveSubscriptionLoading] =
|
||||
React.useState(false);
|
||||
const [activeSubscriptionError, setActiveSubscriptionError] =
|
||||
React.useState(null);
|
||||
})
|
||||
const [coinPacks, setCoinPacks] = React.useState([])
|
||||
const [isCatalogLoading, setIsCatalogLoading] = React.useState(true)
|
||||
const [catalogError, setCatalogError] = React.useState(null)
|
||||
const [activeSubscription, setActiveSubscription] = React.useState(null)
|
||||
const [isActiveSubscriptionLoading, setIsActiveSubscriptionLoading] = React.useState(false)
|
||||
const [activeSubscriptionError, setActiveSubscriptionError] = React.useState(null)
|
||||
|
||||
const stripeCustomerId = currentUserData?.stripeCustomerId || null;
|
||||
const stripeCustomerId = currentUserData?.stripeCustomerId || null
|
||||
const localSubscriptionId =
|
||||
currentUserData?.stripeSubscription?.id ||
|
||||
currentUserData?.stripeSubscription?.subscriptionId ||
|
||||
null;
|
||||
null
|
||||
|
||||
const closeEmbeddedCheckout = React.useCallback(() => {
|
||||
setClientSecret(null);
|
||||
}, []);
|
||||
setClientSecret(null)
|
||||
}, [])
|
||||
|
||||
const redirectToCheckout = React.useCallback(async (checkoutUrl = {}) => {
|
||||
if (!checkoutUrl) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
throw new Error('Session Stripe introuvable.')
|
||||
}
|
||||
|
||||
if (isWeb) {
|
||||
throw new Error(
|
||||
"Impossible d'ouvrir le paiement Stripe sans checkout intégré.",
|
||||
);
|
||||
throw new Error("Impossible d'ouvrir le paiement Stripe sans checkout intégré.")
|
||||
}
|
||||
|
||||
const isMobileApp = Platform.OS === "ios" || Platform.OS === "android";
|
||||
const isMobileApp = Platform.OS === 'ios' || Platform.OS === 'android'
|
||||
|
||||
if (isMobileApp) {
|
||||
try {
|
||||
await WebBrowser.openBrowserAsync(checkoutUrl, {
|
||||
enableDefaultShareMenu: false,
|
||||
dismissButtonStyle: "close",
|
||||
presentationStyle:
|
||||
WebBrowser?.WebBrowserPresentationStyle?.PAGE_SHEET,
|
||||
});
|
||||
return;
|
||||
dismissButtonStyle: 'close',
|
||||
presentationStyle: WebBrowser?.WebBrowserPresentationStyle?.PAGE_SHEET,
|
||||
})
|
||||
return
|
||||
} catch (webBrowserError) {
|
||||
console.warn(
|
||||
"[StripeProvider] WebBrowser checkout fallback",
|
||||
webBrowserError,
|
||||
);
|
||||
console.warn('[StripeProvider] WebBrowser checkout fallback', webBrowserError)
|
||||
}
|
||||
}
|
||||
|
||||
const canOpen = await Linking.canOpenURL(checkoutUrl);
|
||||
const canOpen = await Linking.canOpenURL(checkoutUrl)
|
||||
if (!canOpen) {
|
||||
throw new Error("Impossible d'ouvrir l'URL de paiement.");
|
||||
throw new Error("Impossible d'ouvrir l'URL de paiement.")
|
||||
}
|
||||
await Linking.openURL(checkoutUrl);
|
||||
}, []);
|
||||
await Linking.openURL(checkoutUrl)
|
||||
}, [])
|
||||
|
||||
const runCheckoutSession = React.useCallback(
|
||||
async ({ callableName, payload, logTag, useEmbeddedFlow = false }) => {
|
||||
if (useEmbeddedFlow && !canUseEmbeddedCheckout) {
|
||||
throw new Error(
|
||||
"Le paiement intégré Stripe est indisponible sur cette plateforme.",
|
||||
);
|
||||
throw new Error('Le paiement intégré Stripe est indisponible sur cette plateforme.')
|
||||
}
|
||||
|
||||
const wantsEmbeddedCheckout = useEmbeddedFlow && canUseEmbeddedCheckout;
|
||||
const safariWindow = wantsEmbeddedCheckout
|
||||
? null
|
||||
: openSafariCheckoutWindow();
|
||||
const wantsEmbeddedCheckout = useEmbeddedFlow && canUseEmbeddedCheckout
|
||||
const safariWindow = wantsEmbeddedCheckout ? null : openSafariCheckoutWindow()
|
||||
try {
|
||||
const callable =
|
||||
getFunctionsClient(FUNCTIONS_REGION).httpsCallable(callableName);
|
||||
const { data } = await callable(payload);
|
||||
const checkoutUrl = data?.url;
|
||||
const clientSecret = data?.client_secret || data?.clientSecret;
|
||||
const callable = getFunctionsClient(FUNCTIONS_REGION).httpsCallable(callableName)
|
||||
const { data } = await callable(payload)
|
||||
const checkoutUrl = data?.url
|
||||
const clientSecret = data?.client_secret || data?.clientSecret
|
||||
|
||||
if (wantsEmbeddedCheckout) {
|
||||
if (!clientSecret) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
throw new Error('Session Stripe introuvable.')
|
||||
}
|
||||
setClientSecret(clientSecret);
|
||||
return;
|
||||
setClientSecret(clientSecret)
|
||||
return
|
||||
}
|
||||
|
||||
if (!checkoutUrl) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
throw new Error('Session Stripe introuvable.')
|
||||
}
|
||||
|
||||
console.log("[StripeProvider] Stripe checkout URL", checkoutUrl);
|
||||
await redirectToCheckout(checkoutUrl, { safariWindow });
|
||||
console.log('[StripeProvider] Stripe checkout URL', checkoutUrl)
|
||||
await redirectToCheckout(checkoutUrl, { safariWindow })
|
||||
} catch (error) {
|
||||
if (safariWindow && !safariWindow.closed) {
|
||||
safariWindow.close();
|
||||
safariWindow.close()
|
||||
}
|
||||
console.error(`[StripeProvider] ${logTag}`, error);
|
||||
console.error(`[StripeProvider] ${logTag}`, error)
|
||||
throw new Error(
|
||||
error?.message ||
|
||||
"Une erreur est survenue lors de la création de la session Stripe.",
|
||||
);
|
||||
error?.message || 'Une erreur est survenue lors de la création de la session Stripe.'
|
||||
)
|
||||
}
|
||||
},
|
||||
[canUseEmbeddedCheckout, redirectToCheckout, setClientSecret],
|
||||
);
|
||||
[canUseEmbeddedCheckout, redirectToCheckout, setClientSecret]
|
||||
)
|
||||
|
||||
const createSubscriptionCheckout = React.useCallback(
|
||||
async (priceId) => {
|
||||
if (!priceId) {
|
||||
throw new Error("Aucun abonnement sélectionné.");
|
||||
throw new Error('Aucun abonnement sélectionné.')
|
||||
}
|
||||
if (isWeb && !canUseEmbeddedCheckout) {
|
||||
console.error(
|
||||
"[StripeProvider] checkout blocked (missing embedded support)",
|
||||
{
|
||||
hasStripeKey: Boolean(stripePublishableKey),
|
||||
isClientSecretReady: false,
|
||||
},
|
||||
);
|
||||
console.error('[StripeProvider] checkout blocked (missing embedded support)', {
|
||||
hasStripeKey: Boolean(stripePublishableKey),
|
||||
isClientSecretReady: false,
|
||||
})
|
||||
throw new Error(
|
||||
"Le paiement intégré Stripe est indisponible pour le moment (clé Stripe ou client secret absent).",
|
||||
);
|
||||
'Le paiement intégré Stripe est indisponible pour le moment (clé Stripe ou client secret absent).'
|
||||
)
|
||||
}
|
||||
const shouldUseEmbeddedCheckout = canUseEmbeddedCheckout;
|
||||
const shouldUseEmbeddedCheckout = canUseEmbeddedCheckout
|
||||
await runCheckoutSession({
|
||||
callableName: "subscription-createSubscriptionCheckoutSession",
|
||||
callableName: 'subscription-createSubscriptionCheckoutSession',
|
||||
payload: {
|
||||
priceId,
|
||||
returnUrls: {
|
||||
successUrl: STRIPE_SUCCESS_URL,
|
||||
cancelUrl: STRIPE_CANCEL_URL,
|
||||
},
|
||||
uiMode: shouldUseEmbeddedCheckout ? "embedded" : "hosted",
|
||||
uiMode: shouldUseEmbeddedCheckout ? 'embedded' : 'hosted',
|
||||
},
|
||||
logTag: "subscription checkout error",
|
||||
logTag: 'subscription checkout error',
|
||||
useEmbeddedFlow: shouldUseEmbeddedCheckout,
|
||||
});
|
||||
})
|
||||
},
|
||||
[canUseEmbeddedCheckout, runCheckoutSession],
|
||||
);
|
||||
[canUseEmbeddedCheckout, runCheckoutSession]
|
||||
)
|
||||
|
||||
const createCoinPackCheckout = React.useCallback(
|
||||
async (productId) => {
|
||||
if (!productId) {
|
||||
throw new Error("Aucun pack sélectionné.");
|
||||
throw new Error('Aucun pack sélectionné.')
|
||||
}
|
||||
if (isWeb && !canUseEmbeddedCheckout) {
|
||||
console.error(
|
||||
"[StripeProvider] checkout blocked (missing embedded support)",
|
||||
{
|
||||
hasStripeKey: Boolean(stripePublishableKey),
|
||||
isClientSecretReady: false,
|
||||
},
|
||||
);
|
||||
console.error('[StripeProvider] checkout blocked (missing embedded support)', {
|
||||
hasStripeKey: Boolean(stripePublishableKey),
|
||||
isClientSecretReady: false,
|
||||
})
|
||||
throw new Error(
|
||||
"Le paiement intégré Stripe est indisponible pour le moment (clé Stripe ou client secret absent).",
|
||||
);
|
||||
'Le paiement intégré Stripe est indisponible pour le moment (clé Stripe ou client secret absent).'
|
||||
)
|
||||
}
|
||||
const shouldUseEmbeddedCheckout = canUseEmbeddedCheckout;
|
||||
const shouldUseEmbeddedCheckout = canUseEmbeddedCheckout
|
||||
await runCheckoutSession({
|
||||
callableName: "subscription-createCoinPackCheckoutSession",
|
||||
callableName: 'subscription-createCoinPackCheckoutSession',
|
||||
payload: {
|
||||
productId,
|
||||
returnUrls: {
|
||||
successUrl: STRIPE_SUCCESS_URL,
|
||||
cancelUrl: STRIPE_CANCEL_URL,
|
||||
},
|
||||
uiMode: shouldUseEmbeddedCheckout ? "embedded" : "hosted",
|
||||
uiMode: shouldUseEmbeddedCheckout ? 'embedded' : 'hosted',
|
||||
},
|
||||
logTag: "coin pack checkout error",
|
||||
logTag: 'coin pack checkout error',
|
||||
useEmbeddedFlow: shouldUseEmbeddedCheckout,
|
||||
});
|
||||
})
|
||||
},
|
||||
[canUseEmbeddedCheckout, runCheckoutSession],
|
||||
);
|
||||
[canUseEmbeddedCheckout, runCheckoutSession]
|
||||
)
|
||||
|
||||
const fetchActiveSubscription = React.useCallback(async () => {
|
||||
const hasLookupContext =
|
||||
Boolean(stripeCustomerId) || Boolean(localSubscriptionId);
|
||||
const hasLookupContext = Boolean(stripeCustomerId) || Boolean(localSubscriptionId)
|
||||
if (!hasLookupContext) {
|
||||
setActiveSubscription(null);
|
||||
setActiveSubscriptionError(null);
|
||||
setIsActiveSubscriptionLoading(false);
|
||||
return;
|
||||
setActiveSubscription(null)
|
||||
setActiveSubscriptionError(null)
|
||||
setIsActiveSubscriptionLoading(false)
|
||||
return
|
||||
}
|
||||
|
||||
setIsActiveSubscriptionLoading(true);
|
||||
setActiveSubscriptionError(null);
|
||||
setIsActiveSubscriptionLoading(true)
|
||||
setActiveSubscriptionError(null)
|
||||
try {
|
||||
const callable = getFunctionsClient(FUNCTIONS_REGION).httpsCallable(
|
||||
"subscription-getActiveSubscription",
|
||||
);
|
||||
const { data } = await callable();
|
||||
setActiveSubscription(data?.subscription || null);
|
||||
'subscription-getActiveSubscription'
|
||||
)
|
||||
const { data } = await callable()
|
||||
setActiveSubscription(data?.subscription || null)
|
||||
} catch (error) {
|
||||
console.error("[StripeProvider] getActiveSubscription error", error);
|
||||
console.error('[StripeProvider] getActiveSubscription error', error)
|
||||
setActiveSubscriptionError(
|
||||
error?.message ||
|
||||
"Impossible de mettre à jour les informations d'abonnement.",
|
||||
);
|
||||
setActiveSubscription(null);
|
||||
error?.message || "Impossible de mettre à jour les informations d'abonnement."
|
||||
)
|
||||
setActiveSubscription(null)
|
||||
} finally {
|
||||
setIsActiveSubscriptionLoading(false);
|
||||
setIsActiveSubscriptionLoading(false)
|
||||
}
|
||||
}, [stripeCustomerId, localSubscriptionId]);
|
||||
}, [stripeCustomerId, localSubscriptionId])
|
||||
|
||||
const fetchStripeCatalog = React.useCallback(async () => {
|
||||
setIsCatalogLoading(true);
|
||||
setCatalogError(null);
|
||||
const functionsClient = getFunctionsClient(FUNCTIONS_REGION);
|
||||
let lastError = null;
|
||||
setIsCatalogLoading(true)
|
||||
setCatalogError(null)
|
||||
const functionsClient = getFunctionsClient(FUNCTIONS_REGION)
|
||||
let lastError = null
|
||||
|
||||
try {
|
||||
const callable = functionsClient.httpsCallable(
|
||||
"subscription-listSubscriptionPlans",
|
||||
);
|
||||
const { data } = await callable();
|
||||
const nextPlans = data?.plans || {};
|
||||
const callable = functionsClient.httpsCallable('subscription-listSubscriptionPlans')
|
||||
const { data } = await callable()
|
||||
const nextPlans = data?.plans || {}
|
||||
setSubscriptions({
|
||||
monthly: Array.isArray(nextPlans?.monthly) ? nextPlans.monthly : [],
|
||||
annual: Array.isArray(nextPlans?.annual) ? nextPlans.annual : [],
|
||||
});
|
||||
})
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
console.error("[StripeProvider] listSubscriptionPlans error", error);
|
||||
lastError = error
|
||||
console.error('[StripeProvider] listSubscriptionPlans error', error)
|
||||
}
|
||||
|
||||
try {
|
||||
const callable = functionsClient.httpsCallable(
|
||||
"subscription-listCoinPacks",
|
||||
);
|
||||
const { data } = await callable();
|
||||
setCoinPacks(Array.isArray(data?.packs) ? data.packs : []);
|
||||
const callable = functionsClient.httpsCallable('subscription-listCoinPacks')
|
||||
const { data } = await callable()
|
||||
setCoinPacks(Array.isArray(data?.packs) ? data.packs : [])
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
console.error("[StripeProvider] listCoinPacks error", error);
|
||||
lastError = error
|
||||
console.error('[StripeProvider] listCoinPacks error', error)
|
||||
}
|
||||
|
||||
if (lastError) {
|
||||
setCatalogError(
|
||||
lastError?.message ||
|
||||
"Impossible de récupérer les informations Stripe pour le moment.",
|
||||
);
|
||||
lastError?.message || 'Impossible de récupérer les informations Stripe pour le moment.'
|
||||
)
|
||||
} else {
|
||||
setCatalogError(null);
|
||||
setCatalogError(null)
|
||||
}
|
||||
setIsCatalogLoading(false);
|
||||
}, []);
|
||||
setIsCatalogLoading(false)
|
||||
}, [])
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchStripeCatalog();
|
||||
}, [fetchStripeCatalog]);
|
||||
fetchStripeCatalog()
|
||||
}, [fetchStripeCatalog])
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchActiveSubscription();
|
||||
}, [fetchActiveSubscription]);
|
||||
fetchActiveSubscription()
|
||||
}, [fetchActiveSubscription])
|
||||
|
||||
const activeSubscriptionInfo = React.useMemo(() => {
|
||||
const subscription = activeSubscription || null;
|
||||
const subscription = activeSubscription || null
|
||||
const nextRenewalDate =
|
||||
toDate(subscription?.currentPeriodEnd) ||
|
||||
toDate(subscription?.current_period_end) ||
|
||||
null;
|
||||
toDate(subscription?.currentPeriodEnd) || toDate(subscription?.current_period_end) || null
|
||||
const subscribedSinceDate =
|
||||
toDate(subscription?.created) ||
|
||||
toDate(subscription?.createdAt) ||
|
||||
toDate(subscription?.created_at) ||
|
||||
null;
|
||||
null
|
||||
|
||||
return {
|
||||
subscription,
|
||||
nextRenewalDate,
|
||||
nextRenewalLabel: nextRenewalDate ? formatDate(nextRenewalDate) : null,
|
||||
subscribedSinceDate,
|
||||
subscribedSinceLabel: subscribedSinceDate
|
||||
? formatDate(subscribedSinceDate)
|
||||
: null,
|
||||
};
|
||||
}, [activeSubscription]);
|
||||
subscribedSinceLabel: subscribedSinceDate ? formatDate(subscribedSinceDate) : null,
|
||||
}
|
||||
}, [activeSubscription])
|
||||
|
||||
const providerValue = React.useMemo(
|
||||
() => ({
|
||||
@@ -413,64 +367,53 @@ const StripeProvider = ({ children }) => {
|
||||
isActiveSubscriptionLoading,
|
||||
activeSubscriptionError,
|
||||
fetchActiveSubscription,
|
||||
],
|
||||
);
|
||||
]
|
||||
)
|
||||
|
||||
return (
|
||||
<StripeContext.Provider value={providerValue}>
|
||||
{children}
|
||||
<Overlay
|
||||
isVisible={clientSecret !== null}
|
||||
setIsVisible={closeEmbeddedCheckout}
|
||||
>
|
||||
<Overlay isVisible={clientSecret !== null} setIsVisible={closeEmbeddedCheckout}>
|
||||
<View style={[StyleSheet.absoluteFillObject, styles.overlayContent]}>
|
||||
<View
|
||||
style={[
|
||||
styles.embeddedWrapper,
|
||||
{
|
||||
width: isMobile ? "99%" : "95%",
|
||||
height: isMobile ? "92vh" : "96vh",
|
||||
maxWidth: isMobile ? "100%" : "1400px",
|
||||
width: isMobile ? '99%' : '95%',
|
||||
height: isMobile ? '92vh' : '96vh',
|
||||
maxWidth: isMobile ? '100%' : '1400px',
|
||||
},
|
||||
]}
|
||||
>
|
||||
{clientSecret && stripePromise ? (
|
||||
<EmbeddedCheckoutProvider
|
||||
stripe={stripePromise}
|
||||
options={{ clientSecret }}
|
||||
>
|
||||
<EmbeddedCheckoutProvider stripe={stripePromise} options={{ clientSecret }}>
|
||||
<EmbeddedCheckout
|
||||
onComplete={() => {
|
||||
closeEmbeddedCheckout();
|
||||
fetchActiveSubscription();
|
||||
closeEmbeddedCheckout()
|
||||
fetchActiveSubscription()
|
||||
}}
|
||||
/>
|
||||
</EmbeddedCheckoutProvider>
|
||||
) : null}
|
||||
</View>
|
||||
<Button
|
||||
type="secondary"
|
||||
isAbsoluteBottom
|
||||
text="Fermer"
|
||||
onPress={closeEmbeddedCheckout}
|
||||
/>
|
||||
<Button type="secondary" isAbsoluteBottom text="Fermer" onPress={closeEmbeddedCheckout} />
|
||||
</View>
|
||||
</Overlay>
|
||||
</StripeContext.Provider>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
overlayContent: {
|
||||
position: "absolute",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: 'absolute',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
embeddedWrapper: {
|
||||
alignSelf: "center",
|
||||
alignSelf: 'center',
|
||||
borderRadius: mainBorderRadius,
|
||||
overflow: "hidden",
|
||||
overflow: 'hidden',
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
export default StripeProvider;
|
||||
export default StripeProvider
|
||||
|
||||
Reference in New Issue
Block a user