fix(default): correct subscription payment display
Some checks failed
Publish Docker image (Multi-arch) / Build & push (amd64) (push) Has been cancelled
Publish Docker image (Multi-arch) / Build & push (arm64) (push) Has been cancelled
Publish Docker image (Multi-arch) / Create multi-arch manifests (push) Has been cancelled
Release (Linux, macOS, Windows) / Linux Release (push) Has been cancelled
Release (Linux, macOS, Windows) / macOS Release (push) Has been cancelled
Release (Linux, macOS, Windows) / Windows Release (push) Has been cancelled

This commit is contained in:
CaIon 2026-05-06 18:38:02 +08:00
parent dc8deb0c24
commit 446a8420f5
No known key found for this signature in database
GPG Key ID: 0CFA613529A9921D
3 changed files with 39 additions and 16 deletions

View File

@ -65,6 +65,11 @@ export function SubscriptionPurchaseDialog(props: Props) {
const hasEpay = const hasEpay =
props.enableOnlineTopUp && (props.epayMethods || []).length > 0 props.enableOnlineTopUp && (props.epayMethods || []).length > 0
const hasAnyPayment = hasStripe || hasCreem || hasEpay const hasAnyPayment = hasStripe || hasCreem || hasEpay
const selectedEpayMethodLabel =
(props.epayMethods || []).find((m) => m.type === selectedEpayMethod)
?.name ||
selectedEpayMethod ||
t('Select payment method')
const totalAmount = Number(plan.total_amount || 0) const totalAmount = Number(plan.total_amount || 0)
const price = Number(plan.price_amount || 0).toFixed(2) const price = Number(plan.price_amount || 0).toFixed(2)
const limitReached = const limitReached =
@ -272,7 +277,7 @@ export function SubscriptionPurchaseDialog(props: Props) {
disabled={limitReached} disabled={limitReached}
> >
<SelectTrigger className='flex-1'> <SelectTrigger className='flex-1'>
<SelectValue placeholder={t('Select payment method')} /> <SelectValue>{selectedEpayMethodLabel}</SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{(props.epayMethods || []).map((m) => ( {(props.epayMethods || []).map((m) => (

View File

@ -4,7 +4,6 @@ import { useTranslation } from 'react-i18next'
import { toast } from 'sonner' import { toast } from 'sonner'
import { formatQuota } from '@/lib/format' import { formatQuota } from '@/lib/format'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
import { useStatus } from '@/hooks/use-status'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { Card, CardContent, CardHeader } from '@/components/ui/card' import { Card, CardContent, CardHeader } from '@/components/ui/card'
import { Progress } from '@/components/ui/progress' import { Progress } from '@/components/ui/progress'
@ -52,12 +51,29 @@ function getEpayMethods(payMethods: PaymentMethod[] = []): PaymentMethod[] {
) )
} }
function getBillingPreferenceLabel(
preference: string,
t: (key: string) => string
): string {
switch (preference) {
case 'subscription_first':
return t('Subscription First')
case 'wallet_first':
return t('Wallet First')
case 'subscription_only':
return t('Subscription Only')
case 'wallet_only':
return t('Wallet Only')
default:
return preference
}
}
export function SubscriptionPlansCard({ export function SubscriptionPlansCard({
topupInfo, topupInfo,
onAvailabilityChange, onAvailabilityChange,
}: SubscriptionPlansCardProps) { }: SubscriptionPlansCardProps) {
const { t } = useTranslation() const { t } = useTranslation()
const { status } = useStatus()
const [plans, setPlans] = useState<PlanRecord[]>([]) const [plans, setPlans] = useState<PlanRecord[]>([])
const [activeSubscriptions, setActiveSubscriptions] = useState< const [activeSubscriptions, setActiveSubscriptions] = useState<
@ -74,9 +90,9 @@ export function SubscriptionPlansCard({
const [purchaseOpen, setPurchaseOpen] = useState(false) const [purchaseOpen, setPurchaseOpen] = useState(false)
const [selectedPlan, setSelectedPlan] = useState<PlanRecord | null>(null) const [selectedPlan, setSelectedPlan] = useState<PlanRecord | null>(null)
const enableStripe = !!status?.enable_stripe_topup const enableStripe = !!topupInfo?.enable_stripe_topup
const enableCreem = !!topupInfo?.enable_creem_topup const enableCreem = !!topupInfo?.enable_creem_topup
const enableOnlineTopUp = !!status?.enable_online_topup const enableOnlineTopUp = !!topupInfo?.enable_online_topup
const epayMethods = useMemo( const epayMethods = useMemo(
() => getEpayMethods(topupInfo?.pay_methods), () => getEpayMethods(topupInfo?.pay_methods),
[topupInfo?.pay_methods] [topupInfo?.pay_methods]
@ -264,22 +280,24 @@ export function SubscriptionPlansCard({
onValueChange={(v) => v !== null && handlePreferenceChange(v)} onValueChange={(v) => v !== null && handlePreferenceChange(v)}
> >
<SelectTrigger className='h-8 flex-1 text-xs sm:w-[140px] sm:flex-none'> <SelectTrigger className='h-8 flex-1 text-xs sm:w-[140px] sm:flex-none'>
<SelectValue /> <SelectValue>
{getBillingPreferenceLabel(displayPref, t)}
</SelectValue>
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
<SelectItem value='subscription_first' disabled={disablePref}> <SelectItem value='subscription_first' disabled={disablePref}>
{t('Subscription First')} {getBillingPreferenceLabel('subscription_first', t)}
{disablePref ? ` (${t('No Active')})` : ''} {disablePref ? ` (${t('No Active')})` : ''}
</SelectItem> </SelectItem>
<SelectItem value='wallet_first'> <SelectItem value='wallet_first'>
{t('Wallet First')} {getBillingPreferenceLabel('wallet_first', t)}
</SelectItem> </SelectItem>
<SelectItem value='subscription_only' disabled={disablePref}> <SelectItem value='subscription_only' disabled={disablePref}>
{t('Subscription Only')} {getBillingPreferenceLabel('subscription_only', t)}
{disablePref ? ` (${t('No Active')})` : ''} {disablePref ? ` (${t('No Active')})` : ''}
</SelectItem> </SelectItem>
<SelectItem value='wallet_only'> <SelectItem value='wallet_only'>
{t('Wallet Only')} {getBillingPreferenceLabel('wallet_only', t)}
</SelectItem> </SelectItem>
</SelectContent> </SelectContent>
</Select> </Select>

View File

@ -1,4 +1,3 @@
import { formatLocalCurrencyAmount } from '@/lib/currency'
import { DEFAULT_DISCOUNT_RATE } from '../constants' import { DEFAULT_DISCOUNT_RATE } from '../constants'
// ============================================================================ // ============================================================================
@ -36,11 +35,12 @@ export function formatQuotaShort(quota: number): string {
export function formatCurrency(amount: number | string): string { export function formatCurrency(amount: number | string): string {
const numeric = const numeric =
typeof amount === 'number' ? amount : Number.parseFloat(String(amount)) typeof amount === 'number' ? amount : Number.parseFloat(String(amount))
return formatLocalCurrencyAmount(Number.isFinite(numeric) ? numeric : null, { if (!Number.isFinite(numeric)) return '-'
digitsLarge: 2,
digitsSmall: 2, return new Intl.NumberFormat(undefined, {
abbreviate: false, minimumFractionDigits: 0,
}) maximumFractionDigits: Math.abs(numeric) >= 1 ? 2 : 4,
}).format(numeric)
} }
/** /**