TelegramPWA/src/components/modals/suggestedPostApproval/SuggestedPostApprovalModal.tsx
2025-10-15 19:57:09 +02:00

244 lines
7.0 KiB
TypeScript

import { memo, useState } from '../../../lib/teact/teact';
import { getActions, withGlobal } from '../../../global';
import type { ApiMessage, ApiPeer } from '../../../api/types';
import type { TabState } from '../../../global/types';
import {
STARS_CURRENCY_CODE,
TON_CURRENCY_CODE,
} from '../../../config';
import { getPeerFullTitle } from '../../../global/helpers/peers';
import { selectChatMessage, selectIsMonoforumAdmin, selectSender } from '../../../global/selectors';
import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/dateFormat';
import { convertTonFromNanos } from '../../../util/formatCurrency';
import { formatStarsAsText, formatTonAsText } from '../../../util/localization/format';
import renderText from '../../common/helpers/renderText';
import useFlag from '../../../hooks/useFlag';
import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback';
import useOldLang from '../../../hooks/useOldLang';
import CalendarModal from '../../common/CalendarModal';
import ConfirmDialog from '../../ui/ConfirmDialog';
import styles from './SuggestedPostApprovalModal.module.scss';
export type OwnProps = {
modal: TabState['suggestedPostApprovalModal'];
};
type StateProps = {
commissionPermille: number;
tonCommissionPermille: number;
minAge: number;
futureMin: number;
futureMax: number;
message?: ApiMessage;
sender?: ApiPeer;
isAdmin?: boolean;
scheduleDate?: number;
};
const SuggestedPostApprovalModal = ({
modal,
message,
sender,
isAdmin,
commissionPermille,
tonCommissionPermille,
minAge,
futureMin,
futureMax,
scheduleDate,
}: OwnProps & StateProps) => {
const {
closeSuggestedPostApprovalModal,
approveSuggestedPost,
} = getActions();
const lang = useLang();
const oldLang = useOldLang();
const [isCalendarOpened, openCalendar, closeCalendar] = useFlag();
const now = Math.floor(Date.now() / 1000);
const minAt = (now + futureMin) * 1000;
const maxAt = (now + futureMax) * 1000;
const defaultSelectedTime = now + futureMin * 2;
const [selectedScheduleDate, setSelectedScheduleDate] = useState<number>(defaultSelectedTime);
const handleClose = useLastCallback(() => {
closeSuggestedPostApprovalModal();
});
const handleApprove = useLastCallback((date?: number) => {
if (!modal) return;
approveSuggestedPost({
chatId: modal.chatId,
messageId: modal.messageId,
scheduleDate: date,
});
closeSuggestedPostApprovalModal();
});
const handleCalendarDateChange = useLastCallback((date: Date) => {
const time = Math.floor(date.getTime() / 1000);
setSelectedScheduleDate(time);
});
const handleCalendarSubmit = useLastCallback((date: Date) => {
const time = Math.floor(date.getTime() / 1000);
closeCalendar();
handleApprove(time);
});
const handlePublishNow = useLastCallback(() => {
closeCalendar();
handleApprove();
});
const handleNext = useLastCallback(() => {
if (scheduleDate) {
handleApprove(scheduleDate);
} else {
openCalendar();
}
});
if (!modal || !message) {
return undefined;
}
const senderName = sender ? getPeerFullTitle(oldLang, sender) : '';
const renderContent = () => {
const price = message?.suggestedPostInfo?.price;
const amount = price?.amount;
const currency = price?.currency || STARS_CURRENCY_CODE;
const question = lang(
'SuggestedPostConfirmMessage',
{ peer: senderName },
{ withNodes: true, withMarkdown: true });
const questionText = renderText(question);
if (!amount) {
return questionText;
}
const currentCommissionPermille = currency === TON_CURRENCY_CODE ? tonCommissionPermille : commissionPermille;
const commission = (currentCommissionPermille / 10);
const amountWithCommission = amount / 100 * commission;
const formattedAmount = currency === TON_CURRENCY_CODE
? formatTonAsText(lang, convertTonFromNanos(amountWithCommission))
: formatStarsAsText(lang, amountWithCommission);
const ageMinSeconds = minAge;
const duration = formatShortDuration(lang, ageMinSeconds, true);
if (scheduleDate) {
const time = formatScheduledDateTime(scheduleDate, lang, oldLang);
const key
= isAdmin ? 'SuggestedPostConfirmDetailsWithTimeAdmin' : 'SuggestedPostConfirmDetailsWithTimeUser';
return (
<>
<div>
{questionText}
</div>
<div className={styles.details}>
{renderText(lang(key, {
amount: formattedAmount,
commission,
duration,
time,
}, { withNodes: true, withMarkdown: true }))}
</div>
</>
);
}
const key = isAdmin ? 'SuggestedPostConfirmDetailsAdmin' : 'SuggestedPostConfirmDetailsUser';
return (
<>
<div>
{questionText}
</div>
<div className={styles.details}>
{renderText(lang(key, {
amount: formattedAmount,
commission,
duration,
}, { withNodes: true, withMarkdown: true }))}
</div>
</>
);
};
return (
<>
<ConfirmDialog
isOpen={Boolean(modal) && !isCalendarOpened}
onClose={handleClose}
title={lang('SuggestedPostConfirmTitle')}
confirmHandler={handleNext}
confirmLabel={scheduleDate ? lang('ButtonPublish') : lang('Next')}
>
{renderContent()}
</ConfirmDialog>
<CalendarModal
isOpen={isCalendarOpened}
isFutureMode
withTimePicker
minAt={minAt}
maxAt={maxAt}
onClose={closeCalendar}
onSubmit={handleCalendarSubmit}
onDateChange={handleCalendarDateChange}
selectedAt={selectedScheduleDate * 1000}
submitButtonLabel={lang('ButtonPublishAtTime', {
time: formatScheduledDateTime(selectedScheduleDate, lang, oldLang),
})}
secondButtonLabel={lang('PublishNow')}
onSecondButtonClick={handlePublishNow}
description={lang('SuggestMessageDateTimeHint')}
/>
</>
);
};
export default memo(withGlobal<OwnProps>(
(global, { modal }): Complete<StateProps> => {
const message = modal && selectChatMessage(global, modal.chatId, modal.messageId);
const sender = message ? selectSender(global, message) : undefined;
const isAdmin = modal && selectIsMonoforumAdmin(global, modal.chatId);
const { appConfig } = global;
const commissionPermille = appConfig.starsSuggestedPostCommissionPermille;
const tonCommissionPermille = appConfig.tonSuggestedPostCommissionPermille;
const minAge = appConfig.starsSuggestedPostAgeMin;
const futureMin = appConfig.starsSuggestedPostFutureMin;
const futureMax = appConfig.starsSuggestedPostFutureMax;
const scheduleDate = message?.suggestedPostInfo?.scheduleDate;
return {
minAge,
futureMin,
futureMax,
message,
sender,
isAdmin,
commissionPermille,
tonCommissionPermille,
scheduleDate,
};
},
)(SuggestedPostApprovalModal));