mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-29 18:13:47 +00:00
feat: add gift purchase UI states for telegram recipients
- Add recipient_in_bot and bot_link fields to PurchaseStatus API type - Show bot link instruction when gift recipient is not in bot - Show "gift sent via Telegram" message when recipient is in bot - Fix duplicate text rendering in GiftPendingActivationState - Handle recipientInBot=null edge case safely - Add gift notification translations for ru, en, zh, fa locales
This commit is contained in:
@@ -126,6 +126,8 @@ export interface PurchaseStatus {
|
|||||||
cabinet_email: string | null;
|
cabinet_email: string | null;
|
||||||
cabinet_password: string | null;
|
cabinet_password: string | null;
|
||||||
auto_login_token: string | null;
|
auto_login_token: string | null;
|
||||||
|
recipient_in_bot: boolean | null;
|
||||||
|
bot_link: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|||||||
@@ -4060,6 +4060,11 @@
|
|||||||
"giftSentSuccess": "Gift sent!",
|
"giftSentSuccess": "Gift sent!",
|
||||||
"giftSentDesc": "Recipient will be notified by email",
|
"giftSentDesc": "Recipient will be notified by email",
|
||||||
"giftPendingActivationDesc": "The recipient already has an active subscription. They will receive a link to activate the gift.",
|
"giftPendingActivationDesc": "The recipient already has an active subscription. They will receive a link to activate the gift.",
|
||||||
|
"giftTelegramSent": "Gift notification sent to recipient via Telegram",
|
||||||
|
"giftTelegramNotInBot": "Recipient hasn't started the bot yet. Send them this link:",
|
||||||
|
"giftTelegramPendingSent": "Activation request sent to recipient via Telegram",
|
||||||
|
"giftTelegramPendingNotInBot": "Recipient hasn't started the bot yet. Send them the bot link so they can activate the gift:",
|
||||||
|
"openBot": "Open bot",
|
||||||
"autoLoginFailed": "Auto-login failed",
|
"autoLoginFailed": "Auto-login failed",
|
||||||
"autoLoginProcessing": "Signing in...",
|
"autoLoginProcessing": "Signing in...",
|
||||||
"discount": {
|
"discount": {
|
||||||
|
|||||||
@@ -3552,6 +3552,11 @@
|
|||||||
"giftSentSuccess": "هدیه ارسال شد!",
|
"giftSentSuccess": "هدیه ارسال شد!",
|
||||||
"giftSentDesc": "گیرنده از طریق ایمیل مطلع خواهد شد",
|
"giftSentDesc": "گیرنده از طریق ایمیل مطلع خواهد شد",
|
||||||
"giftPendingActivationDesc": "گیرنده در حال حاضر اشتراک فعال دارد. لینک فعالسازی هدیه برای او ارسال خواهد شد.",
|
"giftPendingActivationDesc": "گیرنده در حال حاضر اشتراک فعال دارد. لینک فعالسازی هدیه برای او ارسال خواهد شد.",
|
||||||
|
"giftTelegramSent": "اطلاعیه هدیه از طریق تلگرام به گیرنده ارسال شد",
|
||||||
|
"giftTelegramNotInBot": "گیرنده هنوز ربات را شروع نکرده است. این لینک را برای او ارسال کنید:",
|
||||||
|
"giftTelegramPendingSent": "درخواست فعالسازی از طریق تلگرام به گیرنده ارسال شد",
|
||||||
|
"giftTelegramPendingNotInBot": "گیرنده هنوز در ربات نیست. لینک ربات را برایش ارسال کنید تا بتواند هدیه را فعال کند:",
|
||||||
|
"openBot": "باز کردن ربات",
|
||||||
"autoLoginFailed": "ورود خودکار ناموفق بود",
|
"autoLoginFailed": "ورود خودکار ناموفق بود",
|
||||||
"autoLoginProcessing": "در حال ورود...",
|
"autoLoginProcessing": "در حال ورود...",
|
||||||
"periodLabels": {
|
"periodLabels": {
|
||||||
|
|||||||
@@ -4620,6 +4620,11 @@
|
|||||||
"giftSentSuccess": "Подарок отправлен!",
|
"giftSentSuccess": "Подарок отправлен!",
|
||||||
"giftSentDesc": "Получатель получит уведомление на email",
|
"giftSentDesc": "Получатель получит уведомление на email",
|
||||||
"giftPendingActivationDesc": "У получателя уже есть активная подписка. Ему будет отправлена ссылка для активации подарка.",
|
"giftPendingActivationDesc": "У получателя уже есть активная подписка. Ему будет отправлена ссылка для активации подарка.",
|
||||||
|
"giftTelegramSent": "Мы отправили получателю уведомление о подарке в Telegram",
|
||||||
|
"giftTelegramNotInBot": "Получатель пока не пользуется ботом. Отправьте ему эту ссылку, чтобы он мог забрать подарок:",
|
||||||
|
"giftTelegramPendingSent": "Мы отправили получателю предложение активировать подарок в Telegram",
|
||||||
|
"giftTelegramPendingNotInBot": "Получатель пока не пользуется ботом. Отправьте ему ссылку, чтобы он мог активировать подарок:",
|
||||||
|
"openBot": "Ссылка на бота",
|
||||||
"autoLoginFailed": "Не удалось выполнить автоматический вход",
|
"autoLoginFailed": "Не удалось выполнить автоматический вход",
|
||||||
"autoLoginProcessing": "Выполняется вход...",
|
"autoLoginProcessing": "Выполняется вход...",
|
||||||
"discount": {
|
"discount": {
|
||||||
|
|||||||
@@ -3551,6 +3551,11 @@
|
|||||||
"giftSentSuccess": "礼物已发送!",
|
"giftSentSuccess": "礼物已发送!",
|
||||||
"giftSentDesc": "收件人将通过邮件收到通知",
|
"giftSentDesc": "收件人将通过邮件收到通知",
|
||||||
"giftPendingActivationDesc": "收件人已有活跃订阅。他们将收到激活礼物的链接。",
|
"giftPendingActivationDesc": "收件人已有活跃订阅。他们将收到激活礼物的链接。",
|
||||||
|
"giftTelegramSent": "已通过 Telegram 向收件人发送通知",
|
||||||
|
"giftTelegramNotInBot": "收件人尚未启动机器人。请将此链接发送给他们:",
|
||||||
|
"giftTelegramPendingSent": "已通过 Telegram 向收件人发送激活请求",
|
||||||
|
"giftTelegramPendingNotInBot": "收件人尚未启动机器人。请将机器人链接发送给他们以激活礼物:",
|
||||||
|
"openBot": "打开机器人",
|
||||||
"autoLoginFailed": "自动登录失败",
|
"autoLoginFailed": "自动登录失败",
|
||||||
"autoLoginProcessing": "正在登录...",
|
"autoLoginProcessing": "正在登录...",
|
||||||
"periodLabels": {
|
"periodLabels": {
|
||||||
|
|||||||
@@ -218,6 +218,9 @@ function SuccessState({
|
|||||||
periodDays,
|
periodDays,
|
||||||
isGift,
|
isGift,
|
||||||
giftMessage,
|
giftMessage,
|
||||||
|
recipientInBot,
|
||||||
|
botLink,
|
||||||
|
contactType,
|
||||||
}: {
|
}: {
|
||||||
subscriptionUrl: string | null;
|
subscriptionUrl: string | null;
|
||||||
cryptoLink: string | null;
|
cryptoLink: string | null;
|
||||||
@@ -227,6 +230,9 @@ function SuccessState({
|
|||||||
periodDays: number | null;
|
periodDays: number | null;
|
||||||
isGift: boolean;
|
isGift: boolean;
|
||||||
giftMessage: string | null;
|
giftMessage: string | null;
|
||||||
|
recipientInBot: boolean | null;
|
||||||
|
botLink: string | null;
|
||||||
|
contactType: string | null;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
@@ -299,7 +305,13 @@ function SuccessState({
|
|||||||
{tariffName} — {periodDays} {t('landing.daysAccess')}
|
{tariffName} — {periodDays} {t('landing.daysAccess')}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{displayContact && (
|
{isGift && contactType === 'telegram' && recipientInBot === true && (
|
||||||
|
<p className="mt-2 text-sm text-dark-400">{t('landing.giftTelegramSent')}</p>
|
||||||
|
)}
|
||||||
|
{isGift && contactType === 'telegram' && recipientInBot !== true && (
|
||||||
|
<p className="mt-2 text-sm text-dark-400">{t('landing.giftTelegramNotInBot')}</p>
|
||||||
|
)}
|
||||||
|
{!(isGift && contactType === 'telegram') && displayContact && (
|
||||||
<p className="mt-2 text-sm text-dark-400">
|
<p className="mt-2 text-sm text-dark-400">
|
||||||
{isGift
|
{isGift
|
||||||
? t('landing.giftSentTo', { contact: displayContact })
|
? t('landing.giftSentTo', { contact: displayContact })
|
||||||
@@ -313,6 +325,18 @@ function SuccessState({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Bot link for telegram gifts where recipient is not in bot */}
|
||||||
|
{isGift && contactType === 'telegram' && recipientInBot !== true && botLink && (
|
||||||
|
<a
|
||||||
|
href={botLink}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
|
||||||
|
>
|
||||||
|
{t('landing.openBot')}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* QR Code */}
|
{/* QR Code */}
|
||||||
{displayUrl && (
|
{displayUrl && (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@@ -507,11 +531,17 @@ function GiftPendingActivationState({
|
|||||||
periodDays,
|
periodDays,
|
||||||
recipientContactValue,
|
recipientContactValue,
|
||||||
giftMessage,
|
giftMessage,
|
||||||
|
recipientInBot,
|
||||||
|
botLink,
|
||||||
|
contactType,
|
||||||
}: {
|
}: {
|
||||||
tariffName: string | null;
|
tariffName: string | null;
|
||||||
periodDays: number | null;
|
periodDays: number | null;
|
||||||
recipientContactValue: string | null;
|
recipientContactValue: string | null;
|
||||||
giftMessage: string | null;
|
giftMessage: string | null;
|
||||||
|
recipientInBot: boolean | null;
|
||||||
|
botLink: string | null;
|
||||||
|
contactType: string | null;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -556,18 +586,38 @@ function GiftPendingActivationState({
|
|||||||
{tariffName} — {periodDays} {t('landing.daysAccess')}
|
{tariffName} — {periodDays} {t('landing.daysAccess')}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
{recipientContactValue && (
|
{contactType === 'telegram' && recipientInBot === true && (
|
||||||
|
<p className="mt-2 text-sm text-dark-400">{t('landing.giftTelegramPendingSent')}</p>
|
||||||
|
)}
|
||||||
|
{contactType === 'telegram' && recipientInBot !== true && (
|
||||||
|
<p className="mt-2 text-sm text-dark-400">{t('landing.giftTelegramPendingNotInBot')}</p>
|
||||||
|
)}
|
||||||
|
{contactType !== 'telegram' && (
|
||||||
|
<p className="mt-2 text-sm text-dark-400">{t('landing.giftPendingActivationDesc')}</p>
|
||||||
|
)}
|
||||||
|
{contactType !== 'telegram' && recipientContactValue && (
|
||||||
<p className="mt-2 text-sm text-dark-400">
|
<p className="mt-2 text-sm text-dark-400">
|
||||||
{t('landing.giftSentTo', { contact: recipientContactValue })}
|
{t('landing.giftSentTo', { contact: recipientContactValue })}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<p className="mt-2 text-sm text-dark-400">{t('landing.giftPendingActivationDesc')}</p>
|
|
||||||
{giftMessage && (
|
{giftMessage && (
|
||||||
<p className="mt-2 text-sm italic text-dark-400">
|
<p className="mt-2 text-sm italic text-dark-400">
|
||||||
{t('landing.giftMessage')}: {giftMessage}
|
{t('landing.giftMessage')}: {giftMessage}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* Bot link for telegram gifts where recipient is not in bot */}
|
||||||
|
{contactType === 'telegram' && recipientInBot !== true && botLink && (
|
||||||
|
<a
|
||||||
|
href={botLink}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex w-full items-center justify-center gap-2 rounded-xl bg-accent-500 px-6 py-3 text-sm font-medium text-white transition-colors hover:bg-accent-400"
|
||||||
|
>
|
||||||
|
{t('landing.openBot')}
|
||||||
|
</a>
|
||||||
|
)}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -756,6 +806,9 @@ export default function PurchaseSuccess() {
|
|||||||
periodDays={purchaseStatus.period_days}
|
periodDays={purchaseStatus.period_days}
|
||||||
isGift={purchaseStatus.is_gift}
|
isGift={purchaseStatus.is_gift}
|
||||||
giftMessage={purchaseStatus.gift_message}
|
giftMessage={purchaseStatus.gift_message}
|
||||||
|
recipientInBot={purchaseStatus.recipient_in_bot}
|
||||||
|
botLink={purchaseStatus.bot_link}
|
||||||
|
contactType={purchaseStatus.contact_type}
|
||||||
/>
|
/>
|
||||||
) : isGiftPendingActivation ? (
|
) : isGiftPendingActivation ? (
|
||||||
<GiftPendingActivationState
|
<GiftPendingActivationState
|
||||||
@@ -763,6 +816,9 @@ export default function PurchaseSuccess() {
|
|||||||
periodDays={purchaseStatus.period_days}
|
periodDays={purchaseStatus.period_days}
|
||||||
recipientContactValue={purchaseStatus.recipient_contact_value}
|
recipientContactValue={purchaseStatus.recipient_contact_value}
|
||||||
giftMessage={purchaseStatus.gift_message}
|
giftMessage={purchaseStatus.gift_message}
|
||||||
|
recipientInBot={purchaseStatus.recipient_in_bot}
|
||||||
|
botLink={purchaseStatus.bot_link}
|
||||||
|
contactType={purchaseStatus.contact_type}
|
||||||
/>
|
/>
|
||||||
) : isPendingActivation ? (
|
) : isPendingActivation ? (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user