TelegramPWA/src/components/main/premium/GiveawayModal.tsx
2025-12-22 22:53:29 +01:00

920 lines
32 KiB
TypeScript

import type { ChangeEvent } from 'react';
import type { FC } from '../../../lib/teact/teact';
import type React from '../../../lib/teact/teact';
import {
memo, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../global';
import type {
ApiCountry,
ApiPremiumGiftCodeOption,
ApiPrepaidGiveaway,
ApiPrepaidStarsGiveaway,
ApiStarGiveawayOption,
ApiTypePrepaidGiveaway,
} from '../../../api/types';
import {
GIVEAWAY_BOOST_PER_PREMIUM,
GIVEAWAY_MAX_ADDITIONAL_CHANNELS,
GIVEAWAY_MAX_ADDITIONAL_COUNTRIES,
GIVEAWAY_MAX_ADDITIONAL_USERS,
STARS_CURRENCY_CODE,
} from '../../../config';
import { getUserFullName, isChatChannel } from '../../../global/helpers';
import {
selectChat,
selectTabState,
} from '../../../global/selectors';
import buildClassName from '../../../util/buildClassName';
import { formatDateTimeToString } from '../../../util/dates/dateFormat';
import { unique } from '../../../util/iteratees';
import renderText from '../../common/helpers/renderText';
import useFlag from '../../../hooks/useFlag';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import CalendarModal from '../../common/CalendarModal';
import CountryPickerModal from '../../common/CountryPickerModal.async';
import GroupChatInfo from '../../common/GroupChatInfo';
import Icon from '../../common/icons/Icon';
import StarTopupOptionList from '../../modals/stars/StarTopupOptionList';
import Button from '../../ui/Button';
import ConfirmDialog from '../../ui/ConfirmDialog';
import InputText from '../../ui/InputText';
import Link from '../../ui/Link';
import ListItem from '../../ui/ListItem';
import Modal from '../../ui/Modal';
import RadioGroup from '../../ui/RadioGroup';
import RangeSliderWithMarks from '../../ui/RangeSliderWithMarks';
import Switcher from '../../ui/Switcher';
import GiveawayChannelPickerModal from './GiveawayChannelPickerModal';
import GiveawayTypeOption from './GiveawayTypeOption';
import GiveawayUserPickerModal from './GiveawayUserPickerModal';
import PremiumSubscriptionOption from './PremiumSubscriptionOption';
import styles from './GiveawayModal.module.scss';
import GiftBlueRound from '../../../assets/premium/GiftBlueRound.svg';
import GiftGreenRound from '../../../assets/premium/GiftGreenRound.svg';
import GiftRedRound from '../../../assets/premium/GiftRedRound.svg';
import GiftStar from '../../../assets/premium/GiftStar.svg';
import PremiumLogo from '../../../assets/premium/PremiumStar.svg';
export type OwnProps = {
isOpen?: boolean;
userIds?: string[];
};
type StateProps = {
chatId?: string;
gifts?: ApiPremiumGiftCodeOption[];
selectedMemberList?: string[] | undefined;
selectedChannelList?: string[] | undefined;
giveawayBoostPerPremiumLimit?: number;
userSelectionLimit?: number;
countryList: ApiCountry[];
prepaidGiveaway?: ApiTypePrepaidGiveaway;
countrySelectionLimit: number | undefined;
isChannel?: boolean;
isStarsGiftEnabled?: boolean;
starsGiftOptions?: ApiStarGiveawayOption[] | undefined;
};
type GiveawayAction = 'createPremiumGiveaway' | 'createStarsGiveaway';
type ApiGiveawayType = 'premium_giveaway' | 'stars_giveaway';
type SubscribersType = 'all' | 'new';
interface TypeOption {
name: string;
text: string;
value: ApiGiveawayType;
img: string;
actions?: GiveawayAction;
isLink: boolean;
onClickAction?: () => void;
}
const DEFAULT_CUSTOM_EXPIRE_DATE = 86400 * 3 * 1000; // 3 days
const MAX_ADDITIONAL_CHANNELS = 9;
const DEFAULT_BOOST_COUNT = 5;
const GIVEAWAY_IMG_LIST: Partial<Record<number, string>> = {
3: GiftGreenRound,
6: GiftBlueRound,
12: GiftRedRound,
};
const GiveawayModal: FC<OwnProps & StateProps> = ({
chatId,
gifts,
isOpen,
isChannel,
selectedMemberList,
selectedChannelList,
giveawayBoostPerPremiumLimit = GIVEAWAY_BOOST_PER_PREMIUM,
countryList,
prepaidGiveaway,
countrySelectionLimit = GIVEAWAY_MAX_ADDITIONAL_COUNTRIES,
userSelectionLimit = GIVEAWAY_MAX_ADDITIONAL_USERS,
isStarsGiftEnabled,
starsGiftOptions,
}) => {
const dialogRef = useRef<HTMLDivElement>();
const {
closeGiveawayModal, openInvoice, openPremiumModal,
launchPrepaidGiveaway, launchPrepaidStarsGiveaway,
} = getActions();
const lang = useOldLang();
const [isCalendarOpened, openCalendar, closeCalendar] = useFlag();
const [isCountryPickerModalOpen, openCountryPickerModal, closeCountryPickerModal] = useFlag();
const [isConfirmModalOpen, openConfirmModal, closeConfirmModal] = useFlag();
const [isUserPickerModalOpen, openUserPickerModal, closeUserPickerModal] = useFlag();
const [isChannelPickerModalOpen, openChannelPickerModal, closeChannelPickerModal] = useFlag();
const TYPE_OPTIONS: TypeOption[] = [{
name: 'Premium.Title',
text: 'BoostingWinnersRandomly',
value: 'premium_giveaway',
img: GiftBlueRound,
actions: 'createPremiumGiveaway',
isLink: true,
onClickAction: () => {
openUserPickerModal();
},
}];
if (isStarsGiftEnabled) {
TYPE_OPTIONS.push({
name: 'TelegramStars',
text: 'BoostingWinnersRandomly',
value: 'stars_giveaway',
img: GiftStar,
actions: 'createStarsGiveaway',
isLink: false,
});
}
const [customExpireDate, setCustomExpireDate] = useState<number>(() => Date.now() + DEFAULT_CUSTOM_EXPIRE_DATE);
const [isHeaderHidden, setHeaderHidden] = useState(true);
const [selectedRandomUserCount, setSelectedRandomUserCount] = useState<number>(DEFAULT_BOOST_COUNT);
const [selectedGiveawayOption, setGiveawayOption] = useState<ApiGiveawayType>(TYPE_OPTIONS[0].value);
const [selectedStarOption, setSelectedStarOption] = useState<ApiStarGiveawayOption | undefined>();
const [selectedSubscriberOption, setSelectedSubscriberOption] = useState<SubscribersType>('all');
const [selectedMonthOption, setSelectedMonthOption] = useState<number | undefined>();
const [selectedUserIds, setSelectedUserIds] = useState<string[]>([]);
const [selectedChannelIds, setSelectedChannelIds] = useState<string[]>([]);
const [selectedCountryIds, setSelectedCountryIds] = useState<string[] | undefined>([]);
const [shouldShowWinners, setShouldShowWinners] = useState<boolean>(false);
const [shouldShowPrizes, setShouldShowPrizes] = useState<boolean>(false);
const [prizeDescription, setPrizeDescription] = useState<string | undefined>(undefined);
const [dataPrepaidGiveaway, setDataPrepaidGiveaway] = useState<ApiPrepaidGiveaway | undefined>(undefined);
const [
dataStarsPrepaidGiveaway, setDataStarsPrepaidGiveaway,
] = useState<ApiPrepaidStarsGiveaway | undefined>(undefined);
const isPremiumGiveaway = selectedGiveawayOption === 'premium_giveaway';
const isStarsGiveaway = selectedGiveawayOption === 'stars_giveaway';
const selectedUserCount = isPremiumGiveaway
&& !selectedUserIds.length ? selectedRandomUserCount : selectedUserIds.length;
const boostQuantity = selectedUserCount * giveawayBoostPerPremiumLimit;
const boostStarsQuantity = selectedStarOption?.yearlyBoosts;
const SUBSCRIBER_OPTIONS = useMemo(() => [
{
value: 'all',
label: lang(isChannel ? 'BoostingAllSubscribers' : 'BoostingAllMembers'),
subLabel: selectedCountryIds && selectedCountryIds.length > 0
? lang('Giveaway.ReceiverType.Countries', selectedCountryIds.length)
: lang('BoostingFromAllCountries'),
},
{
value: 'new',
label: lang(isChannel ? 'BoostingNewSubscribers' : 'BoostingNewMembers'),
subLabel: selectedCountryIds && selectedCountryIds.length > 0
? lang('Giveaway.ReceiverType.Countries', selectedCountryIds.length)
: lang('BoostingFromAllCountries'),
},
], [isChannel, lang, selectedCountryIds]);
const monthQuantity = lang('Months', selectedMonthOption);
const isStarsPrepaidGiveaway = prepaidGiveaway?.type === 'starsGiveaway';
const isPremiumPrepaidGiveaway = prepaidGiveaway?.type === 'giveaway';
const selectedGift = useMemo(() => {
return gifts?.find((gift) => gift.months === selectedMonthOption && gift.users === selectedUserCount);
}, [gifts, selectedMonthOption, selectedUserCount]);
const selectedStarsGift = useMemo(() => {
return starsGiftOptions?.find((gift) => {
return isStarsPrepaidGiveaway && gift.stars === (dataStarsPrepaidGiveaway?.stars);
});
}, [dataStarsPrepaidGiveaway, starsGiftOptions, isStarsPrepaidGiveaway]);
const filteredGifts = useMemo(() => {
return gifts?.filter((gift) => gift.users === selectedUserCount && gift.currency !== STARS_CURRENCY_CODE);
}, [gifts, selectedUserCount]);
const fullMonthlyAmount = useMemo(() => {
const basicGift = filteredGifts?.reduce((acc, gift) => {
return gift.amount < acc.amount ? gift : acc;
}, filteredGifts[0]);
return basicGift && Math.floor(basicGift.amount / basicGift.months);
}, [filteredGifts]);
const userCountOptions = useMemo(() => {
return unique((gifts?.filter((gift) => gift.currency !== STARS_CURRENCY_CODE)
?.map((winner) => winner.users) || [])).sort((a, b) => a - b);
}, [gifts]);
const winnerCountOptions = useMemo(() => {
return unique((selectedStarOption?.winners?.map((winner) => winner.users) || [])).sort((a, b) => a - b);
}, [selectedStarOption]);
useEffect(() => {
if (isOpen && gifts?.length && !isStarsPrepaidGiveaway) {
setSelectedMonthOption(gifts?.[0].months);
}
}, [isOpen, gifts, isStarsPrepaidGiveaway]);
useEffect(() => {
if (isOpen && starsGiftOptions?.length && !isPremiumPrepaidGiveaway) {
setSelectedStarOption(starsGiftOptions?.[0]);
}
}, [isOpen, starsGiftOptions, isPremiumPrepaidGiveaway]);
useEffect(() => {
if (isOpen && isStarsPrepaidGiveaway) {
setSelectedRandomUserCount(prepaidGiveaway.quantity);
setDataStarsPrepaidGiveaway(prepaidGiveaway);
}
}, [isOpen, isStarsPrepaidGiveaway, prepaidGiveaway]);
useEffect(() => {
if (isOpen && isPremiumPrepaidGiveaway) {
setSelectedRandomUserCount(prepaidGiveaway.quantity);
setDataPrepaidGiveaway(prepaidGiveaway);
setSelectedMonthOption(prepaidGiveaway.months);
}
}, [isOpen, isPremiumPrepaidGiveaway, prepaidGiveaway]);
useEffect(() => {
if (selectedMemberList) {
setSelectedUserIds(selectedMemberList);
}
}, [selectedMemberList]);
useEffect(() => {
if (selectedChannelList) {
setSelectedChannelIds(selectedChannelList);
}
}, [selectedChannelList]);
const handlePremiumClick = useLastCallback(() => {
openPremiumModal();
});
const handleClose = useLastCallback(() => {
setDataStarsPrepaidGiveaway(undefined);
setDataPrepaidGiveaway(undefined);
setSelectedStarOption(undefined);
setSelectedMonthOption(undefined);
setSelectedRandomUserCount(DEFAULT_BOOST_COUNT);
closeGiveawayModal();
});
const handleClick = useLastCallback(() => {
if (isPremiumGiveaway) {
if (selectedUserIds?.length) {
openInvoice({
type: 'giftcode',
boostChannelId: chatId!,
userIds: selectedUserIds,
currency: selectedGift!.currency,
amount: selectedGift!.amount,
option: selectedGift!,
});
} else {
openInvoice({
type: 'giveaway',
chatId: chatId!,
additionalChannelIds: selectedChannelIds,
isOnlyForNewSubscribers: selectedSubscriberOption === 'new',
countries: selectedCountryIds,
areWinnersVisible: shouldShowWinners,
prizeDescription,
untilDate: customExpireDate / 1000,
currency: selectedGift!.currency,
amount: selectedGift!.amount,
option: selectedGift!,
});
}
} else {
openInvoice({
type: 'starsgiveaway',
chatId: chatId!,
additionalChannelIds: selectedChannelIds,
isOnlyForNewSubscribers: selectedSubscriberOption === 'new',
countries: selectedCountryIds,
areWinnersVisible: shouldShowWinners,
prizeDescription,
untilDate: customExpireDate / 1000,
currency: selectedStarOption!.currency,
amount: selectedStarOption!.amount,
stars: selectedStarOption!.stars,
users: selectedRandomUserCount,
});
}
handleClose();
});
const confirmLaunchPrepaidGiveaway = useLastCallback(() => {
if (isStarsPrepaidGiveaway) {
launchPrepaidStarsGiveaway({
chatId: chatId!,
giveawayId: dataStarsPrepaidGiveaway!.id,
paymentPurpose: {
additionalChannelIds: selectedChannelIds,
countries: selectedCountryIds,
prizeDescription,
areWinnersVisible: shouldShowWinners,
untilDate: customExpireDate / 1000,
stars: dataStarsPrepaidGiveaway!.stars,
currency: selectedStarsGift!.currency,
amount: selectedStarsGift!.amount,
users: dataStarsPrepaidGiveaway!.quantity,
},
});
} else {
launchPrepaidGiveaway({
chatId: chatId!,
giveawayId: dataPrepaidGiveaway!.id,
paymentPurpose: {
additionalChannelIds: selectedChannelIds,
countries: selectedCountryIds,
prizeDescription,
areWinnersVisible: shouldShowWinners,
untilDate: customExpireDate / 1000,
currency: selectedGift!.currency,
amount: selectedGift!.amount,
},
});
}
closeConfirmModal();
handleClose();
});
const handleRandomUserCountChange = useLastCallback((newValue) => {
setSelectedRandomUserCount(newValue);
});
const handleWinnerCountChange = useLastCallback((newValue) => {
setSelectedRandomUserCount(newValue);
});
const handlePrizeDescriptionChange = useLastCallback((e: ChangeEvent<HTMLInputElement>) => {
setPrizeDescription(e.target.value);
});
const userNames = useMemo(() => {
const usersById = getGlobal().users.byId;
return selectedUserIds?.map((userId) => getUserFullName(usersById[userId])).join(', ');
}, [selectedUserIds]);
function handleScroll(e: React.UIEvent<HTMLDivElement>) {
const { scrollTop } = e.currentTarget;
setHeaderHidden(scrollTop <= 150);
}
const handleChangeSubscriberOption = useLastCallback((value) => {
setSelectedSubscriberOption(value);
});
const handleChangeTypeOption = useLastCallback((value: ApiGiveawayType) => {
setGiveawayOption(value);
setSelectedUserIds([]);
setSelectedRandomUserCount(DEFAULT_BOOST_COUNT);
});
const handleExpireDateChange = useLastCallback((date: Date) => {
setCustomExpireDate(date.getTime());
closeCalendar();
});
const handleSetCountriesListChange = useLastCallback((value: string[]) => {
setSelectedCountryIds(value);
});
const handleSelectedUserIdsChange = useLastCallback((newSelectedIds: string[]) => {
setSelectedUserIds(newSelectedIds);
if (!newSelectedIds.length) {
setGiveawayOption('premium_giveaway');
}
});
const handleSelectedChannelIdsChange = useLastCallback((newSelectedIds: string[]) => {
setSelectedChannelIds(newSelectedIds);
});
const handleShouldShowWinnersChange = useLastCallback((e: ChangeEvent<HTMLInputElement>) => {
setShouldShowWinners(e.target.checked);
});
const handleShouldShowPrizesChange = useLastCallback((e: ChangeEvent<HTMLInputElement>) => {
setShouldShowPrizes(e.target.checked);
});
const onClickActionHandler = useLastCallback(() => {
openCountryPickerModal();
});
const handleStarClick = useLastCallback((option) => {
setSelectedStarOption(option);
});
function renderTypeOptions() {
return (
<div className={styles.options}>
{TYPE_OPTIONS.map((option) => {
return (
<GiveawayTypeOption
key={option.name}
name={option.name}
text={option.text}
option={option.value}
img={option.img}
onChange={handleChangeTypeOption}
checked={selectedGiveawayOption === option.value}
isLink={option.isLink}
userNames={userNames}
selectedMemberIds={selectedUserIds}
onClickAction={option.onClickAction}
/>
);
})}
</div>
);
}
function renderSubscribersOptions() {
return (
<div className={styles.options}>
<RadioGroup
name="subscribers"
options={SUBSCRIBER_OPTIONS}
selected={selectedSubscriberOption}
onChange={handleChangeSubscriberOption}
onClickAction={onClickActionHandler}
subLabelClassName={styles.subLabelClassName}
isLink
/>
</div>
);
}
function renderSubscriptionOptions() {
return (
<div className={styles.options}>
{filteredGifts?.map((gift) => (
<PremiumSubscriptionOption
isGiveaway
key={gift.months}
option={gift}
fullMonthlyAmount={fullMonthlyAmount}
checked={gift.months === selectedMonthOption}
onChange={setSelectedMonthOption}
/>
))}
</div>
);
}
function renderPremiumFeaturesLink() {
const info = lang('GiftPremiumListFeaturesAndTerms');
const parts = info.match(/([^*]*)\*([^*]+)\*(.*)/);
if (!parts || parts.length < 4) {
return undefined;
}
return (
<p className={styles.premiumFeatures}>
{parts[1]}
<Link isPrimary onClick={handlePremiumClick}>{parts[2]}</Link>
{parts[3]}
</p>
);
}
function deleteParticipantsHandler(id: string) {
const filteredChannelIds = selectedChannelIds.filter((channelId) => channelId !== id);
setSelectedChannelIds(filteredChannelIds);
}
function renderStarOptionList() {
return (
<StarTopupOptionList
className={styles.starOptions}
options={starsGiftOptions}
selectedStarCount={selectedRandomUserCount}
selectedStarOption={selectedStarOption}
onClick={handleStarClick}
/>
);
}
function renderGiveawayOptionList() {
return (
<>
<div className={styles.section}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingChannelsGroupsIncludedGiveaway')}
</h2>
<ListItem
inactive
className="chat-item-clickable contact-list-item"
>
<GroupChatInfo
chatId={chatId!}
status={lang(isChannel ? 'BoostingChannelWillReceiveBoost'
: 'BoostingGroupWillReceiveBoost', boostQuantity || boostStarsQuantity, 'i')}
/>
</ListItem>
{selectedChannelIds?.map((channelId) => {
return (
<ListItem
ripple
key={channelId}
className="chat-item-clickable contact-list-item"
onClick={() => deleteParticipantsHandler(channelId)}
rightElement={(<Icon name="close" className={styles.removeChannel} />)}
>
<GroupChatInfo
chatId={channelId.toString()}
/>
</ListItem>
);
})}
{selectedChannelIds.length < MAX_ADDITIONAL_CHANNELS && (
<ListItem
icon="add"
ripple
onClick={openChannelPickerModal}
className={styles.addButton}
iconClassName={styles.addChannel}
>
{lang('BoostingAddChannelOrGroup')}
</ListItem>
)}
</div>
<div className={styles.section}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingEligibleUsers')}
</h2>
{renderSubscribersOptions()}
</div>
<div className={styles.subscription}>
{renderText(lang(isChannel ? 'BoostGift.LimitSubscribersInfo' : 'lng_giveaway_users_about_group'))}
</div>
<div className={styles.section}>
<div className={styles.checkboxSection}>
<h2 className={styles.title}>
{lang('BoostingGiveawayAdditionalPrizes')}
</h2>
<Switcher
label={lang('BoostingGiveawayAdditionalPrizes')}
checked={shouldShowPrizes}
onChange={handleShouldShowPrizesChange}
/>
</div>
{shouldShowPrizes && (
<div className={styles.prizesSection}>
<h2 className={styles.title}>
{selectedRandomUserCount}
</h2>
<InputText
className={styles.prizesInput}
value={prizeDescription}
onChange={handlePrizeDescriptionChange}
label={lang('BoostingGiveawayEnterYourPrize')}
/>
</div>
)}
</div>
{shouldShowPrizes ? (
!isStarsGiveaway && !isStarsPrepaidGiveaway ? (
<div className={styles.subscription}>
{prizeDescription?.length ? renderText(lang('BoostingGiveawayAdditionPrizeCountNameHint',
dataPrepaidGiveaway
? [dataPrepaidGiveaway.quantity, prizeDescription, monthQuantity]
: [selectedUserCount, prizeDescription, monthQuantity],
undefined,
selectedMonthOption), ['simple_markdown']) : renderText(lang('BoostingGiveawayAdditionPrizeCountHint',
dataPrepaidGiveaway
? [dataPrepaidGiveaway.quantity, monthQuantity]
: [selectedUserCount, monthQuantity],
undefined,
selectedMonthOption), ['simple_markdown'])}
</div>
) : undefined
) : (
<div className={styles.subscription}>
{renderText(lang('BoostingGiveawayAdditionPrizeHint'))}
</div>
)}
<div className={styles.section}>
<div className={styles.checkboxSection}>
<h2 className={styles.title}>
{lang('BoostingGiveawayShowWinners')}
</h2>
<Switcher
label={lang('BoostingGiveawayAdditionalPrizes')}
checked={shouldShowWinners}
onChange={handleShouldShowWinnersChange}
/>
</div>
</div>
<div className={styles.subscription}>
{renderText(lang('BoostingGiveawayShowWinnersHint'))}
</div>
<div className={buildClassName(styles.section,
(dataPrepaidGiveaway || dataStarsPrepaidGiveaway || isStarsGiveaway) && styles.subscriptionFooter)}
>
<h2 className={styles.giveawayTitle}>
{lang('BoostingDateWhenGiveawayEnds')}
</h2>
<Button
ariaLabel={lang('BoostGift.DateEnds')}
className={buildClassName(styles.dateButton, 'expire-limit')}
isText
onClick={openCalendar}
>
<h3 className={styles.title}>
{lang('BoostGift.DateEnds')}
</h3>
{formatDateTimeToString(customExpireDate, lang.code)}
</Button>
</div>
</>
);
}
return (
<Modal
className={styles.root}
onClose={handleClose}
isOpen={isOpen}
dialogRef={dialogRef}
onEnter={(dataPrepaidGiveaway || dataStarsPrepaidGiveaway) ? openConfirmModal : handleClick}
hasAbsoluteCloseButton
>
<div className={buildClassName(styles.main, 'custom-scroll')} onScroll={handleScroll}>
<img className={styles.logo} src={PremiumLogo} alt="" draggable={false} />
<h2 className={styles.headerText}>
{renderText(lang('BoostingBoostsViaGifts'))}
</h2>
<div className={styles.description}>
{renderText(lang(isChannel ? 'BoostingGetMoreBoost' : 'BoostingGetMoreBoostsGroup'))}
</div>
<div className={buildClassName(styles.header, isHeaderHidden && styles.hiddenHeader)}>
<h2 className={styles.premiumHeaderText}>
{lang('BoostingBoostsViaGifts')}
</h2>
</div>
{(dataPrepaidGiveaway || dataStarsPrepaidGiveaway) ? (
<div className={styles.status}>
<div>
{dataStarsPrepaidGiveaway ? (
<img className={styles.prepaidImg} src={GiftStar} alt="" />
) : (
<img
className={styles.prepaidImg}
src={GIVEAWAY_IMG_LIST[dataPrepaidGiveaway!.months] || GIVEAWAY_IMG_LIST[3]}
alt=""
/>
)}
</div>
<div className={styles.info}>
<h3 className={styles.title}>
{dataStarsPrepaidGiveaway ? lang('Giveaway.Stars.Prepaid.Title', dataStarsPrepaidGiveaway?.stars)
: lang('BoostingTelegramPremiumCountPlural', dataPrepaidGiveaway!.quantity)}
</h3>
<p className={styles.month}>
{dataStarsPrepaidGiveaway ? lang('Giveaway.Stars.Prepaid.Desc', dataStarsPrepaidGiveaway?.quantity)
: lang('PrepaidGiveawayMonths', dataPrepaidGiveaway?.months)}
</p>
</div>
<div className={styles.quantity}>
<div className={buildClassName(styles.floatingBadge, styles.floatingBadgeColor)}>
<Icon name="boost" className={styles.floatingBadgeIcon} />
<div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>
{dataStarsPrepaidGiveaway ? dataStarsPrepaidGiveaway?.boosts
: dataPrepaidGiveaway!.quantity * (giveawayBoostPerPremiumLimit ?? GIVEAWAY_BOOST_PER_PREMIUM)}
</div>
</div>
</div>
</div>
) : (
<div className={buildClassName(styles.section, styles.types)}>
{renderTypeOptions()}
</div>
)}
{isPremiumGiveaway && !selectedUserIds?.length && (
<>
{!dataPrepaidGiveaway && !dataStarsPrepaidGiveaway && (
<>
<div className={styles.section}>
<div className={styles.quantity}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingQuantityPrizes')}
</h2>
<div className={buildClassName(styles.floatingBadge, styles.floatingBadgeColor)}>
<Icon name="boost" className={styles.floatingBadgeIcon} />
<div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>
{boostQuantity}
</div>
</div>
</div>
<RangeSliderWithMarks
rangeCount={selectedUserCount}
marks={userCountOptions}
onChange={handleRandomUserCountChange}
/>
</div>
<div className={styles.subscription}>
{renderText(lang('BoostingChooseHowMany'))}
</div>
</>
)}
{renderGiveawayOptionList()}
</>
)}
{isStarsGiveaway && (
<>
{!dataStarsPrepaidGiveaway && !dataPrepaidGiveaway && (
<>
<div className={styles.section}>
<div className={styles.quantity}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingStarsOptions')}
</h2>
<div className={buildClassName(styles.floatingBadge, styles.floatingBadgeColor)}>
<Icon name="boost" className={styles.floatingBadgeIcon} />
<div className={styles.floatingBadgeValue} dir={lang.isRtl ? 'rtl' : undefined}>
{boostStarsQuantity}
</div>
</div>
</div>
{renderStarOptionList()}
</div>
<div className={buildClassName(styles.subscription, styles.starSubscription)}>
{renderText(lang('BoostGift.Stars.Info'))}
</div>
<div className={styles.section}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingStarsQuantityPrizes')}
</h2>
<RangeSliderWithMarks
rangeCount={selectedRandomUserCount}
marks={winnerCountOptions}
onChange={handleWinnerCountChange}
/>
<div className={styles.subscription}>
{renderText(lang('BoostingStarsQuantityPrizesInfo'))}
</div>
</div>
</>
)}
{renderGiveawayOptionList()}
</>
)}
{!dataPrepaidGiveaway && !dataStarsPrepaidGiveaway && isPremiumGiveaway && (
<>
<div className={styles.section}>
<h2 className={styles.giveawayTitle}>
{lang('BoostingDurationOfPremium')}
</h2>
{renderSubscriptionOptions()}
</div>
<div className={buildClassName(styles.subscription, styles.subscriptionFooter)}>
{renderPremiumFeaturesLink()}
</div>
</>
)}
{selectedGiveawayOption && (
<div className={styles.footer}>
<Button
className={styles.button}
onClick={(dataPrepaidGiveaway || dataStarsPrepaidGiveaway) ? openConfirmModal : handleClick}
>
{lang('BoostingStartGiveaway')}
</Button>
</div>
)}
</div>
<CalendarModal
isOpen={isCalendarOpened}
isFutureMode
withTimePicker
onClose={closeCalendar}
onSubmit={handleExpireDateChange}
selectedAt={customExpireDate}
submitButtonLabel={lang('Save')}
/>
<CountryPickerModal
isOpen={isCountryPickerModalOpen}
onClose={closeCountryPickerModal}
countryList={countryList}
onSubmit={handleSetCountriesListChange}
selectionLimit={countrySelectionLimit}
/>
<GiveawayUserPickerModal
isOpen={isUserPickerModalOpen}
onClose={closeUserPickerModal}
onSelectedIdsConfirmed={handleSelectedUserIdsChange}
initialSelectedIds={selectedUserIds}
selectionLimit={userSelectionLimit}
giveawayChatId={chatId}
/>
<GiveawayChannelPickerModal
isOpen={isChannelPickerModalOpen}
onClose={closeChannelPickerModal}
initialSelectedIds={selectedChannelIds}
onSelectedIdsConfirmed={handleSelectedChannelIdsChange}
selectionLimit={GIVEAWAY_MAX_ADDITIONAL_CHANNELS}
giveawayChatId={chatId}
/>
<ConfirmDialog
title={lang('BoostingStartGiveawayConfirmTitle')}
text={lang('BoostingStartGiveawayConfirmText')}
confirmLabel={lang('Start')}
isOpen={isConfirmModalOpen}
onClose={closeConfirmModal}
confirmHandler={confirmLaunchPrepaidGiveaway}
/>
</Modal>
);
};
export default memo(withGlobal<OwnProps>((global): Complete<StateProps> => {
const {
giveawayModal,
} = selectTabState(global);
const chatId = giveawayModal?.chatId;
const chat = chatId ? selectChat(global, chatId) : undefined;
const isChannel = chat && isChatChannel(chat);
return {
chatId,
gifts: giveawayModal?.gifts,
selectedMemberList: giveawayModal?.selectedMemberIds,
selectedChannelList: giveawayModal?.selectedChannelIds,
giveawayBoostPerPremiumLimit: global.appConfig.giveawayBoostsPerPremium,
isStarsGiftEnabled: global.appConfig.isStarsGiftEnabled,
userSelectionLimit: global.appConfig.giveawayAddPeersMax,
countrySelectionLimit: global.appConfig.giveawayCountriesMax,
countryList: global.countryList.general,
prepaidGiveaway: giveawayModal?.prepaidGiveaway,
isChannel,
starsGiftOptions: giveawayModal?.starOptions,
};
})(GiveawayModal));