You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
7.3 KiB
184 lines
7.3 KiB
import { useState } from "react";
|
|
import Image from "next/image";
|
|
import { useHabcoinInventoryQuery } from "@/hooks/marriage/use-habcoin-inventory";
|
|
import { DiscountWidget } from "./discount-widget";
|
|
import type { CheckDiscountResult } from "@/hooks/marriage/use-validate-discount";
|
|
import {
|
|
buyHabibCoinPackages,
|
|
isInFlutterWebView,
|
|
} from "@/lib/webview-actions";
|
|
import { useI18n } from "@/translations/provider";
|
|
import InformationSheet from "./information-sheet";
|
|
import { LoadingThreeDot } from "./loading-three-dot";
|
|
|
|
type SubscriptionRequiredSheetProps = {
|
|
onClose: () => void;
|
|
onPayment: (discountCode?: string) => void;
|
|
isPaymentPending?: boolean;
|
|
/** Payment error to display above the buttons (e.g. "Not enough coins"). */
|
|
errorMessage?: string | null;
|
|
/** Show the "Buy Habib Coins" button (Flutter opens its packages page). */
|
|
showBuyCoins?: boolean;
|
|
price?: number;
|
|
planId?: number | string;
|
|
};
|
|
|
|
export function SubscriptionRequiredSheet({
|
|
onClose,
|
|
onPayment,
|
|
isPaymentPending = false,
|
|
errorMessage = null,
|
|
showBuyCoins = false,
|
|
price = 50,
|
|
planId,
|
|
}: SubscriptionRequiredSheetProps) {
|
|
const { dictionary: t } = useI18n();
|
|
const [appliedDiscount, setAppliedDiscount] =
|
|
useState<CheckDiscountResult | null>(null);
|
|
|
|
const { data: inventory, isLoading: isInventoryLoading } =
|
|
useHabcoinInventoryQuery();
|
|
|
|
const finalPrice = appliedDiscount?.valid
|
|
? appliedDiscount.discountedPrice
|
|
: price;
|
|
const balance = inventory?.coin_balance ?? 0;
|
|
const hasEnoughCoins =
|
|
!showBuyCoins && (inventory === undefined ? true : balance >= finalPrice);
|
|
|
|
if (isInventoryLoading) {
|
|
return <InformationSheet isLoading={true} onClose={onClose} />;
|
|
}
|
|
|
|
return (
|
|
<InformationSheet
|
|
icon="coin"
|
|
title={
|
|
!hasEnoughCoins ? (
|
|
<span className="text-[#BD3F3F]">
|
|
{t["You do not have enough Habib Coins"] ||
|
|
"You do not have enough Habib Coins"}
|
|
</span>
|
|
) : (
|
|
t["Subscription required"] || "Subscription required"
|
|
)
|
|
}
|
|
description={
|
|
!hasEnoughCoins ? (
|
|
<p className="text-[14px] text-[#4D4D4D] leading-[1.3] font-normal text-center">
|
|
{t[
|
|
"Please add more Habib Coins to your balance (or use discount code), so that you can use them to access this content"
|
|
] ||
|
|
"Please add more Habib Coins to your balance (or use discount code), so that you can use them to access this content"}
|
|
</p>
|
|
) : (
|
|
<div className="space-y-4 text-left">
|
|
<p className="text-sm text-center leading-[1.45] font-medium text-[#2B2B2B]">
|
|
{t[
|
|
"To view profiles, you need a subscription. Each subscription includes up to {count} matches."
|
|
]?.replace("{count}", "3") || (
|
|
<>
|
|
To view profiles, you need a subscription. Each subscription
|
|
includes up to{" "}
|
|
<span className="font-bold underline decoration-[1.5px] underline-offset-2">
|
|
3
|
|
</span>{" "}
|
|
matches.
|
|
</>
|
|
)}
|
|
</p>
|
|
|
|
<div className="rounded-[12px] border border-[#FF4F67] bg-[#FFECEF] px-3.5 py-2.5 text-center">
|
|
<p className="text-xs leading-[1.45] font-semibold text-[#FF4F67]">
|
|
{t[
|
|
"To view profiles, a subscription is required. This helps cover our support and matching services and applies only to male users"
|
|
] ||
|
|
"To view profiles, a subscription is required. This helps cover our support and matching services and applies only to male users"}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
onClose={onClose}
|
|
buttons={({ close }) => (
|
|
<div className="space-y-3">
|
|
{planId ? (
|
|
<DiscountWidget
|
|
objectId={planId}
|
|
onDiscountApplied={(res) => setAppliedDiscount(res)}
|
|
onDiscountCleared={() => setAppliedDiscount(null)}
|
|
/>
|
|
) : null}
|
|
|
|
{errorMessage && (
|
|
<div className="w-full bg-[#FEF2F2] text-[#B91C1C] text-xs p-3 rounded-[11px] text-center font-medium">
|
|
{errorMessage}
|
|
</div>
|
|
)}
|
|
|
|
<div className="grid w-full grid-cols-[33fr_67fr] gap-3">
|
|
<button
|
|
type="button"
|
|
className="appearance-none border-0 bg-transparent p-0 text-left min-w-0"
|
|
onClick={close}
|
|
>
|
|
<div className="inline-flex w-full items-center justify-center rounded-[11px] border border-[#747474] bg-transparent px-2 h-[52px] text-[16px] font-semibold text-[#747474] transition-opacity active:opacity-90 min-w-0">
|
|
<span className="truncate">{t["Back"] || "Back"}</span>
|
|
</div>
|
|
</button>
|
|
|
|
{!hasEnoughCoins ? (
|
|
<button
|
|
type="button"
|
|
className="appearance-none border-0 bg-transparent p-0 text-left min-w-0"
|
|
onClick={() => buyHabibCoinPackages()}
|
|
>
|
|
<div className="inline-flex w-full items-center justify-center gap-2 rounded-[11px] bg-[#F0445B] px-4 h-[52px] text-[16px] font-semibold text-white shadow-[0_10px_18px_rgba(240,68,91,0.28)] transition-opacity active:opacity-90 min-w-0">
|
|
<span className="truncate">
|
|
{t["Buy Habib Coins"] || "Buy Habib Coins"}
|
|
</span>
|
|
</div>
|
|
</button>
|
|
) : (
|
|
<button
|
|
type="button"
|
|
disabled={isPaymentPending}
|
|
className="appearance-none border-0 bg-transparent p-0 text-left disabled:cursor-not-allowed disabled:opacity-70 min-w-0"
|
|
onClick={() =>
|
|
onPayment(
|
|
appliedDiscount?.valid ? appliedDiscount.code : undefined,
|
|
)
|
|
}
|
|
>
|
|
<div className="inline-flex w-full items-center justify-center gap-2 rounded-[11px] bg-[#F0445B] px-4 h-[52px] text-[16px] font-semibold text-white shadow-[0_10px_18px_rgba(240,68,91,0.28)] transition-opacity active:opacity-90 min-w-0">
|
|
{isPaymentPending ? (
|
|
<LoadingThreeDot />
|
|
) : (
|
|
<>
|
|
<span className="truncate">
|
|
{t["Payment"] || "Payment"}
|
|
</span>
|
|
<span className="inline-flex items-center gap-1 rounded-[12px] bg-black/15 px-[9px] py-[4px] text-xs font-semibold leading-none text-white shrink-0 min-w-0 whitespace-nowrap">
|
|
<Image
|
|
src="/assets/images/Inner Plugdsain Iframe.svg"
|
|
alt=""
|
|
aria-hidden="true"
|
|
width={16}
|
|
height={16}
|
|
className="shrink-0"
|
|
/>
|
|
<span className="truncate">{finalPrice}</span>
|
|
</span>
|
|
</>
|
|
)}
|
|
</div>
|
|
</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
)}
|
|
/>
|
|
);
|
|
}
|
|
|
|
export default SubscriptionRequiredSheet;
|