feat: onetime payment notice for cn users

This commit is contained in:
Stephen Zhou 2025-11-12 12:46:02 +08:00
parent e59f98e85d
commit b37b60bf03
No known key found for this signature in database
1 changed files with 38 additions and 3 deletions

View File

@ -1,5 +1,6 @@
import { Button } from "@follow/components/ui/button/index.js"
import { SegmentGroup, SegmentItem } from "@follow/components/ui/segment/index.jsx"
import { Switch } from "@follow/components/ui/switch/index.js"
import { UserRole } from "@follow/constants"
import { DEEPLINK_SCHEME, IN_ELECTRON } from "@follow/shared"
import { env } from "@follow/shared/env.desktop"
@ -46,7 +47,15 @@ const formatFeatureValue = (
return value
}
const useUpgradePlan = ({ plan, annual }: { plan: string | undefined; annual: boolean }) => {
const useUpgradePlan = ({
plan,
annual,
useOneTimePayment = false,
}: {
plan: string | undefined
annual: boolean
useOneTimePayment?: boolean
}) => {
return useMutation({
mutationFn: async () => {
if (!plan) {
@ -59,6 +68,7 @@ const useUpgradePlan = ({ plan, annual }: { plan: string | undefined; annual: bo
successUrl: IN_ELECTRON ? `${DEEPLINK_SCHEME}refresh` : env.VITE_WEB_URL,
cancelUrl: env.VITE_WEB_URL,
disableRedirect: IN_ELECTRON,
...(useOneTimePayment && { payment: true }),
})
if (IN_ELECTRON && res.data?.url) {
window.open(res.data.url, "_blank")
@ -73,7 +83,9 @@ const useActiveSubscription = () => {
queryKey: ["activeSubscription"],
queryFn: async () => {
const { data } = await subscription.list()
return data?.find((sub) => sub.status === "active" || sub.status === "trialing")
return data?.find(
(sub) => (sub.status === "active" || sub.status === "trialing") && sub.stripeSubscriptionId,
)
},
enabled: !!userId,
})
@ -112,6 +124,9 @@ const useCancelPlan = () => {
export function SettingPlan() {
const isPaymentEnabled = useIsPaymentEnabled()
const role = useUserRole()
const { i18n } = useTranslation()
const showOneTimePaymentOption = i18n.language === "zh-CN"
const [useOneTimePayment, setUseOneTimePayment] = useState(false)
const [billingPeriod, setBillingPeriod] = useState<"monthly" | "yearly">("yearly")
const serverConfig = useServerConfigs()
@ -169,11 +184,23 @@ export function SettingPlan() {
billingPeriod={billingPeriod}
isCurrentPlan={role === plan.role}
currentTier={currentTier}
useOneTimePayment={useOneTimePayment}
/>
))}
</div>
</div>
{showOneTimePaymentOption && (
<div className="flex items-center justify-center gap-2">
<Switch
size="sm"
checked={useOneTimePayment}
onCheckedChange={(checked) => setUseOneTimePayment(checked)}
/>
<span className="text-sm text-text-secondary">使/</span>
</div>
)}
{/* Comparison Table */}
<PlanComparisonTable plans={plans} />
</section>
@ -186,9 +213,16 @@ interface PlanCardProps {
billingPeriod: "monthly" | "yearly"
isCurrentPlan: boolean
currentTier: number
useOneTimePayment?: boolean
}
const PlanCard = ({ plan, billingPeriod, isCurrentPlan, currentTier }: PlanCardProps) => {
const PlanCard = ({
plan,
billingPeriod,
isCurrentPlan,
currentTier,
useOneTimePayment = false,
}: PlanCardProps) => {
const { t } = useTranslation("settings")
const getPlanActionType = ():
| "current"
@ -218,6 +252,7 @@ const PlanCard = ({ plan, billingPeriod, isCurrentPlan, currentTier }: PlanCardP
const upgradePlanMutation = useUpgradePlan({
plan: plan.planID,
annual: billingPeriod === "yearly",
useOneTimePayment,
})
const cancelPlanMutation = useCancelPlan()