1 import { useEffect, useState } from 'react';
3 import { usePlans } from '@proton/account/plans/hooks';
4 import { usePaymentsApiWithCheckFallback } from '@proton/components/payments/react-extensions/usePaymentsApi';
5 import { useLoading } from '@proton/hooks';
6 import { type Currency } from '@proton/payments';
8 import { fetchDealPrices } from '../helpers/dealPrices';
9 import type { Offer, OfferConfig } from '../interface';
12 offerConfig: OfferConfig | undefined;
14 onSuccess?: () => void;
18 function useFetchOffer({ offerConfig, currency, onSuccess, onError }: Props): [Offer | undefined, boolean] {
19 const { paymentsApi } = usePaymentsApiWithCheckFallback();
20 const [loading, withLoading] = useLoading();
21 const [state, setState] = useState<Partial<{ offer: Offer; offerConfig: OfferConfig }>>();
22 const [plansResult, plansLoading] = usePlans();
23 const plans = plansResult?.plans;
26 if (!offerConfig || !plans) {
30 const updateOfferPrices = async () => {
32 // Reset previous offer prices in case the offer config has changed from what was previously cached
33 if (state?.offerConfig !== offerConfig) {
37 const result = await fetchDealPrices(paymentsApi, offerConfig, currency, plans);
39 // We make an offer based on offerConfig + fetched results above
40 const offer: Offer = {
42 deals: offerConfig.deals.map((deal, index) => {
43 const [withCoupon, withoutCoupon, withoutCouponMonthly] = result[index];
48 withCoupon: withCoupon.Amount + (withCoupon.CouponDiscount || 0),
49 withoutCoupon: withoutCoupon.Amount + (withoutCoupon.CouponDiscount || 0), // BUNDLE discount can be applied
50 // in rare cases a plan doesn't have a monthly price, so we use 0 as a fallback.
51 // It can be potentially done smarter, e.g. take the amount without coupon and devide it
52 // byt the cycle length. But that wasn't required for the purpose of Pass Lifetime offer
53 withoutCouponMonthly: withoutCouponMonthly?.Amount ?? 0,
58 setState({ offer, offerConfig });
65 void withLoading(updateOfferPrices());
66 }, [offerConfig, currency, plans]);
68 return [state?.offer, loading || plansLoading];
71 export default useFetchOffer;