diff --git a/src/components/Payment/Payment.tsx b/src/components/Payment/Payment.tsx
index e9b59573a..05e455e40 100644
--- a/src/components/Payment/Payment.tsx
+++ b/src/components/Payment/Payment.tsx
@@ -21,7 +21,6 @@ import type { Offer } from '#types/checkout';
import OfferSwitch from '#components/OfferSwitch/OfferSwitch';
import Alert from '#components/Alert/Alert';
import { useSubscriptionChange } from '#src/hooks/useSubscriptionChange';
-import useOffers from '#src/hooks/useOffers';
const VISIBLE_TRANSACTIONS = 4;
@@ -43,6 +42,8 @@ type Props = {
canUpdatePaymentMethod: boolean;
canRenewSubscription?: boolean;
canShowReceipts?: boolean;
+ offers?: Offer[];
+ pendingDowngradeOfferId?: string;
};
const Payment = ({
@@ -63,9 +64,9 @@ const Payment = ({
canUpdatePaymentMethod,
onUpgradeSubscriptionClick,
offerSwitchesAvailable,
+ offers = [],
+ pendingDowngradeOfferId = '',
}: Props): JSX.Element => {
- const { offers } = useOffers();
-
const { t, i18n } = useTranslation(['user', 'account']);
const hiddenTransactionsCount = transactions ? transactions?.length - VISIBLE_TRANSACTIONS : 0;
const hasMoreTransactions = hiddenTransactionsCount > 0;
@@ -100,8 +101,6 @@ const Payment = ({
const changeSubscriptionPlan = useSubscriptionChange(isUpgradeOffer ?? false, selectedOfferId, customer, activeSubscription?.subscriptionId);
- const pendingDowngradeOfferId = (customer.metadata?.[`${activeSubscription?.subscriptionId}_pending_downgrade`] as string) || '';
-
const onChangePlanClick = async () => {
if (selectedOfferId && activeSubscription?.subscriptionId) {
changeSubscriptionPlan.mutate({
diff --git a/src/containers/PaymentContainer/PaymentContainer.tsx b/src/containers/PaymentContainer/PaymentContainer.tsx
new file mode 100644
index 000000000..cc2c7673c
--- /dev/null
+++ b/src/containers/PaymentContainer/PaymentContainer.tsx
@@ -0,0 +1,114 @@
+import { useEffect, useState } from 'react';
+import { useLocation, useNavigate } from 'react-router';
+import shallow from 'zustand/shallow';
+
+import styles from '#src/pages/User/User.module.scss';
+import LoadingOverlay from '#components/LoadingOverlay/LoadingOverlay';
+import Payment from '#components/Payment/Payment';
+import { getReceipt } from '#src/stores/AccountController';
+import { useAccountStore } from '#src/stores/AccountStore';
+import { getSubscriptionSwitches } from '#src/stores/CheckoutController';
+import { useCheckoutStore } from '#src/stores/CheckoutStore';
+import { useConfigStore } from '#src/stores/ConfigStore';
+import { addQueryParam } from '#src/utils/location';
+import useOffers from '#src/hooks/useOffers';
+
+const PaymentContainer = () => {
+ const { accessModel } = useConfigStore(
+ (s) => ({
+ accessModel: s.accessModel,
+ favoritesList: s.config.features?.favoritesList,
+ }),
+ shallow,
+ );
+ const navigate = useNavigate();
+ const [showAllTransactions, setShowAllTransactions] = useState(false);
+ const [isLoadingReceipt, setIsLoadingReceipt] = useState(false);
+
+ const {
+ user: customer,
+ subscription: activeSubscription,
+ transactions,
+ activePayment,
+ pendingOffer,
+ loading,
+ canRenewSubscription,
+ canUpdatePaymentMethod,
+ canShowReceipts,
+ } = useAccountStore();
+ const { offerSwitches } = useCheckoutStore();
+ const location = useLocation();
+
+ const handleUpgradeSubscriptionClick = async () => {
+ navigate(addQueryParam(location, 'u', 'upgrade-subscription'));
+ };
+
+ const handleShowReceiptClick = async (transactionId: string) => {
+ setIsLoadingReceipt(true);
+
+ try {
+ const receipt = await getReceipt(transactionId);
+
+ if (receipt) {
+ const newWindow = window.open('', `Receipt ${transactionId}`, '');
+ const htmlString = window.atob(receipt);
+
+ if (newWindow) {
+ newWindow.opener = null;
+ newWindow.document.write(htmlString);
+ newWindow.document.close();
+ }
+ }
+ } catch (error: unknown) {
+ throw new Error("Couldn't parse receipt. " + (error instanceof Error ? error.message : ''));
+ }
+
+ setIsLoadingReceipt(false);
+ };
+
+ useEffect(() => {
+ if (accessModel !== 'AVOD') {
+ getSubscriptionSwitches();
+ }
+ }, [accessModel]);
+
+ useEffect(() => {
+ if (!loading && !customer) {
+ navigate('/', { replace: true });
+ }
+ }, [navigate, customer, loading]);
+
+ const { offers } = useOffers();
+
+ if (!customer) {
+ return ;
+ }
+
+ const pendingDowngradeOfferId = (customer.metadata?.[`${activeSubscription?.subscriptionId}_pending_downgrade`] as string) || '';
+
+ return (
+ setShowAllTransactions(true)}
+ showAllTransactions={showAllTransactions}
+ canUpdatePaymentMethod={canUpdatePaymentMethod}
+ canRenewSubscription={canRenewSubscription}
+ onUpgradeSubscriptionClick={handleUpgradeSubscriptionClick}
+ offerSwitchesAvailable={!!offerSwitches.length}
+ canShowReceipts={canShowReceipts}
+ onShowReceiptClick={handleShowReceiptClick}
+ offers={offers}
+ pendingDowngradeOfferId={pendingDowngradeOfferId}
+ />
+ );
+};
+
+export default PaymentContainer;
diff --git a/src/pages/User/User.tsx b/src/pages/User/User.tsx
index 673da1a43..fb0d9caab 100644
--- a/src/pages/User/User.tsx
+++ b/src/pages/User/User.tsx
@@ -1,31 +1,29 @@
-import React, { useCallback, useEffect, useState } from 'react';
-import { Navigate, Route, Routes, useLocation, useNavigate } from 'react-router-dom';
+import { useCallback, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { Navigate, Route, Routes, useNavigate } from 'react-router-dom';
import shallow from 'zustand/shallow';
import styles from './User.module.scss';
+import AccountComponent from '#components/Account/Account';
+import Button from '#components/Button/Button';
+import ConfirmationDialog from '#components/ConfirmationDialog/ConfirmationDialog';
+import Favorites from '#components/Favorites/Favorites';
+import LoadingOverlay from '#components/LoadingOverlay/LoadingOverlay';
+import PaymentContainer from '#src/containers/PaymentContainer/PaymentContainer';
import PlaylistContainer from '#src/containers/PlaylistContainer/PlaylistContainer';
-import { mediaURL } from '#src/utils/formatting';
+import useBreakpoint, { Breakpoint } from '#src/hooks/useBreakpoint';
import AccountCircle from '#src/icons/AccountCircle';
-import Favorite from '#src/icons/Favorite';
import BalanceWallet from '#src/icons/BalanceWallet';
import Exit from '#src/icons/Exit';
+import Favorite from '#src/icons/Favorite';
+import { logout } from '#src/stores/AccountController';
import { useAccountStore } from '#src/stores/AccountStore';
+import { getSubscriptionSwitches } from '#src/stores/CheckoutController';
import { PersonalShelf, useConfigStore } from '#src/stores/ConfigStore';
-import useBreakpoint, { Breakpoint } from '#src/hooks/useBreakpoint';
-import LoadingOverlay from '#components/LoadingOverlay/LoadingOverlay';
-import ConfirmationDialog from '#components/ConfirmationDialog/ConfirmationDialog';
-import Payment from '#components/Payment/Payment';
-import AccountComponent from '#components/Account/Account';
-import Button from '#components/Button/Button';
-import Favorites from '#components/Favorites/Favorites';
-import type { PlaylistItem } from '#types/playlist';
-import { getReceipt, logout } from '#src/stores/AccountController';
import { clear as clearFavorites } from '#src/stores/FavoritesController';
-import { getSubscriptionSwitches } from '#src/stores/CheckoutController';
-import { useCheckoutStore } from '#src/stores/CheckoutStore';
-import { addQueryParam } from '#src/utils/location';
+import { mediaURL } from '#src/utils/formatting';
+import type { PlaylistItem } from '#types/playlist';
const User = (): JSX.Element => {
const { accessModel, favoritesList } = useConfigStore(
@@ -39,24 +37,9 @@ const User = (): JSX.Element => {
const { t } = useTranslation('user');
const breakpoint = useBreakpoint();
const [clearFavoritesOpen, setClearFavoritesOpen] = useState(false);
- const [showAllTransactions, setShowAllTransactions] = useState(false);
- const [isLoadingReceipt, setIsLoadingReceipt] = useState(false);
const isLargeScreen = breakpoint > Breakpoint.md;
- const {
- user: customer,
- subscription,
- transactions,
- activePayment,
- pendingOffer,
- loading,
- canUpdateEmail,
- canRenewSubscription,
- canUpdatePaymentMethod,
- canShowReceipts,
- } = useAccountStore();
- const { offerSwitches } = useCheckoutStore();
- const location = useLocation();
+ const { user: customer, subscription, loading, canUpdateEmail } = useAccountStore();
const onCardClick = (playlistItem: PlaylistItem) => navigate(mediaURL({ media: playlistItem }));
const onLogout = useCallback(async () => {
@@ -64,33 +47,6 @@ const User = (): JSX.Element => {
await logout();
}, []);
- const handleUpgradeSubscriptionClick = async () => {
- navigate(addQueryParam(location, 'u', 'upgrade-subscription'));
- };
-
- const handleShowReceiptClick = async (transactionId: string) => {
- setIsLoadingReceipt(true);
-
- try {
- const receipt = await getReceipt(transactionId);
-
- if (receipt) {
- const newWindow = window.open('', `Receipt ${transactionId}`, '');
- const htmlString = window.atob(receipt);
-
- if (newWindow) {
- newWindow.opener = null;
- newWindow.document.write(htmlString);
- newWindow.document.close();
- }
- }
- } catch (error: unknown) {
- throw new Error("Couldn't parse receipt. " + (error instanceof Error ? error.message : ''));
- }
-
- setIsLoadingReceipt(false);
- };
-
useEffect(() => {
if (accessModel !== 'AVOD') {
getSubscriptionSwitches();
@@ -175,34 +131,7 @@ const User = (): JSX.Element => {
}
/>
)}
- setShowAllTransactions(true)}
- showAllTransactions={showAllTransactions}
- canUpdatePaymentMethod={canUpdatePaymentMethod}
- canRenewSubscription={canRenewSubscription}
- onUpgradeSubscriptionClick={handleUpgradeSubscriptionClick}
- offerSwitchesAvailable={!!offerSwitches.length}
- canShowReceipts={canShowReceipts}
- onShowReceiptClick={handleShowReceiptClick}
- />
- ) : (
-
- )
- }
- />
+ : } />
} />