PremiumMainModal: Render all subscription options (#4129)
This commit is contained in:
parent
d2b834d1a6
commit
3e96262038
@ -194,7 +194,7 @@ function buildApiPremiumSubscriptionOption(option: GramJs.PremiumSubscriptionOpt
|
||||
isCurrent: current,
|
||||
canPurchaseUpgrade,
|
||||
currency,
|
||||
amount: amount.toString(),
|
||||
amount: amount.toJSNumber(),
|
||||
botUrl,
|
||||
months,
|
||||
};
|
||||
|
||||
@ -75,7 +75,7 @@ export interface ApiPremiumSubscriptionOption {
|
||||
canPurchaseUpgrade?: boolean;
|
||||
months: number;
|
||||
currency: string;
|
||||
amount: string;
|
||||
amount: number;
|
||||
botUrl: string;
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@ import Avatar from '../../common/Avatar';
|
||||
import Button from '../../ui/Button';
|
||||
import Link from '../../ui/Link';
|
||||
import Modal from '../../ui/Modal';
|
||||
import GiftOption from './GiftOption';
|
||||
import PremiumSubscriptionOption from './PremiumSubscriptionOption';
|
||||
|
||||
import styles from './GiftPremiumModal.module.scss';
|
||||
|
||||
@ -141,7 +141,7 @@ const GiftPremiumModal: FC<OwnProps & StateProps> = ({
|
||||
|
||||
<div className={styles.options}>
|
||||
{renderedGifts?.map((gift) => (
|
||||
<GiftOption
|
||||
<PremiumSubscriptionOption
|
||||
key={gift.amount}
|
||||
option={gift}
|
||||
fullMonthlyAmount={fullMonthlyAmount}
|
||||
|
||||
@ -168,3 +168,11 @@
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.subscriptionOptions {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.subscriptionOption {
|
||||
margin: 0.8125rem;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import React, {
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type {
|
||||
ApiPremiumPromo, ApiSticker, ApiStickerSet, ApiUser,
|
||||
ApiPremiumPromo, ApiPremiumSubscriptionOption, ApiSticker, ApiStickerSet, ApiUser,
|
||||
} from '../../../api/types';
|
||||
import type { GlobalState } from '../../../global/types';
|
||||
|
||||
@ -36,6 +36,7 @@ import PremiumFeatureModal, {
|
||||
PREMIUM_FEATURE_SECTIONS,
|
||||
PREMIUM_FEATURE_TITLES,
|
||||
} from './PremiumFeatureModal';
|
||||
import PremiumSubscriptionOption from './PremiumSubscriptionOption';
|
||||
|
||||
import styles from './PremiumMainModal.module.scss';
|
||||
|
||||
@ -133,6 +134,7 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
const lang = useLang();
|
||||
const [isHeaderHidden, setHeaderHidden] = useState(true);
|
||||
const [currentSection, setCurrentSection] = useState<string | undefined>(initialSection);
|
||||
const [selectedSubscriptionOption, setSubscriptionOption] = useState<ApiPremiumSubscriptionOption>();
|
||||
|
||||
const handleOpen = useCallback((section: string | undefined) => {
|
||||
return () => {
|
||||
@ -146,7 +148,7 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
setHeaderHidden(scrollTop <= 150);
|
||||
}
|
||||
|
||||
function handleClickWithStartParam(startParam?: string) {
|
||||
const handleClickWithStartParam = useLastCallback((startParam?: string) => {
|
||||
const dialog = dialogRef.current;
|
||||
if (!dialog) return;
|
||||
|
||||
@ -160,12 +162,21 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
closePremiumModal();
|
||||
}
|
||||
}
|
||||
|
||||
const handleClick = useLastCallback(() => {
|
||||
handleClickWithStartParam();
|
||||
});
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
if (selectedSubscriptionOption) {
|
||||
handleClickWithStartParam(String(selectedSubscriptionOption.months));
|
||||
} else {
|
||||
handleClickWithStartParam();
|
||||
}
|
||||
}, [selectedSubscriptionOption, handleClickWithStartParam]);
|
||||
|
||||
const handleChangeSubscriptionOption = useCallback((months: number) => {
|
||||
const foundOption = promo?.options.find((option) => option.months === months);
|
||||
setSubscriptionOption(foundOption);
|
||||
}, [promo]);
|
||||
|
||||
const showConfetti = useCallback(() => {
|
||||
const dialog = dialogRef.current;
|
||||
if (!dialog) return;
|
||||
@ -206,6 +217,11 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
}, [loadStickers, fromUserStatusEmoji, fromUserStatusSet]);
|
||||
|
||||
useEffect(() => {
|
||||
const [defaultOption] = promo?.options ?? [];
|
||||
setSubscriptionOption(defaultOption);
|
||||
}, [promo]);
|
||||
|
||||
const handleOpenStatusSet = useLastCallback(() => {
|
||||
if (!fromUserStatusSet) return;
|
||||
|
||||
@ -231,10 +247,15 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
return [renderText(first), link, renderText(second)];
|
||||
}, [fromUser, fromUserStatusSet, lang]);
|
||||
|
||||
if (!promo || (fromUserStatusEmoji && !fromUserStatusSet)) return undefined;
|
||||
const fullMonthlyAmount = useMemo(() => {
|
||||
const monthOption = promo?.options.find((option) => option.months === 1);
|
||||
if (!monthOption) {
|
||||
return undefined;
|
||||
}
|
||||
return Number(monthOption.amount);
|
||||
}, [promo]);
|
||||
|
||||
// TODO Support all subscription options
|
||||
const month = promo.options.find((option) => option.months === 1)!;
|
||||
if (!promo || (fromUserStatusEmoji && !fromUserStatusSet)) return undefined;
|
||||
|
||||
function getHeaderText() {
|
||||
if (isGift) {
|
||||
@ -279,6 +300,24 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
);
|
||||
}
|
||||
|
||||
function renderSubscriptionOptions() {
|
||||
return (
|
||||
<div className={styles.subscriptionOptions}>
|
||||
{promo?.options
|
||||
.map((option) => (
|
||||
<PremiumSubscriptionOption
|
||||
className={styles.subscriptionOption}
|
||||
key={option.amount}
|
||||
option={option}
|
||||
onChange={handleChangeSubscriptionOption}
|
||||
fullMonthlyAmount={fullMonthlyAmount}
|
||||
checked={selectedSubscriptionOption?.months === option.months}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
className={styles.root}
|
||||
@ -319,12 +358,12 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
<div className={styles.description}>
|
||||
{renderText(getHeaderDescription(), ['simple_markdown', 'emoji'])}
|
||||
</div>
|
||||
{!isPremium && renderSubscriptionOptions()}
|
||||
<div className={buildClassName(styles.header, isHeaderHidden && styles.hiddenHeader)}>
|
||||
<h2 className={styles.premiumHeaderText}>
|
||||
{lang('TelegramPremium')}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div className={buildClassName(styles.list, isPremium && styles.noButton)}>
|
||||
{filteredSections.map((section, index) => {
|
||||
return (
|
||||
@ -355,10 +394,15 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
</div>
|
||||
{renderFooterText()}
|
||||
</div>
|
||||
{!isPremium && (
|
||||
{!isPremium && selectedSubscriptionOption && (
|
||||
<div className={styles.footer}>
|
||||
<Button className={styles.button} isShiny withPremiumGradient onClick={handleClick}>
|
||||
{lang('SubscribeToPremium', formatCurrency(Number(month.amount), month.currency, lang.code))}
|
||||
{lang('SubscribeToPremium',
|
||||
formatCurrency(
|
||||
selectedSubscriptionOption.amount,
|
||||
selectedSubscriptionOption.currency,
|
||||
lang.code,
|
||||
))}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -2,24 +2,27 @@ import type { ChangeEvent } from 'react';
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useCallback, useMemo } from '../../../lib/teact/teact';
|
||||
|
||||
import type { ApiPremiumGiftOption } from '../../../api/types';
|
||||
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
import { formatCurrency } from '../../../util/formatCurrency';
|
||||
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import styles from './GiftOption.module.scss';
|
||||
import styles from './PremiumSubscriptionOption.module.scss';
|
||||
|
||||
type OwnProps = {
|
||||
option: ApiPremiumGiftOption;
|
||||
option: {
|
||||
months: number;
|
||||
currency: string;
|
||||
amount: number;
|
||||
};
|
||||
checked?: boolean;
|
||||
fullMonthlyAmount?: number;
|
||||
className?: string;
|
||||
onChange: (month: number) => void;
|
||||
};
|
||||
|
||||
const GiftOption: FC<OwnProps> = ({
|
||||
option, checked, fullMonthlyAmount, onChange,
|
||||
const PremiumSubscriptionOption: FC<OwnProps> = ({
|
||||
option, checked, fullMonthlyAmount, onChange, className,
|
||||
}) => {
|
||||
const lang = useLang();
|
||||
|
||||
@ -39,7 +42,14 @@ const GiftOption: FC<OwnProps> = ({
|
||||
}, [months, onChange]);
|
||||
|
||||
return (
|
||||
<label className={buildClassName(styles.wrapper, checked && styles.active)} dir={lang.isRtl ? 'rtl' : undefined}>
|
||||
<label
|
||||
className={buildClassName(
|
||||
styles.wrapper,
|
||||
checked && styles.active,
|
||||
className,
|
||||
)}
|
||||
dir={lang.isRtl ? 'rtl' : undefined}
|
||||
>
|
||||
<input
|
||||
className={styles.input}
|
||||
type="radio"
|
||||
@ -62,4 +72,4 @@ const GiftOption: FC<OwnProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(GiftOption);
|
||||
export default memo(PremiumSubscriptionOption);
|
||||
@ -407,7 +407,7 @@ addActionHandler('openGiftPremiumModal', async (global, actions, payload): Promi
|
||||
isOpen: true,
|
||||
forUserId,
|
||||
monthlyCurrency: month.currency,
|
||||
monthlyAmount: month.amount,
|
||||
monthlyAmount: String(month.amount),
|
||||
},
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user