// 加载状态组件
import { unitConversion } from '@workspace/airo-ui/utils';
import { useRef } from 'react';
const LoadingState = () => {
const t = useTranslations('components.offerDialog');
return (
);
};
// 错误状态组件
const ErrorState = ({ onRetry }: { onRetry: () => void }) => {
const t = useTranslations('components.offerDialog');
return (
{t('loadFailed')}
);
};
// 空状态组件
const EmptyState = ({ message }: { message: string }) => (
);
import { useLocale } from 'next-intl';
interface PriceDisplayProps {
plan: PlanProps;
}
interface PlanProps extends API.Subscribe {
origin_price: string;
discount_price: string;
}
// 价格显示组件
const PriceDisplay: React.FC = ({ plan }) => {
const t = useTranslations('components.offerDialog');
const locale = useLocale(); // 获取当前语言环境
const { common } = useGlobalStore();
const discountItem = plan.discount.find((v) => v.quantity === 12) ?? { discount: 0 };
const discount =
locale === 'zh-CN' ? discountItem?.discount / 10 : `${100 - discountItem?.discount}%`;
return (
{plan.origin_price && (
{common?.currency?.currency_symbol}
{plan.origin_price}
)}
{common?.currency?.currency_symbol}
{plan.discount_price}
{t('perYear')}
{plan.origin_price && (
{t('yearlyDiscount', { discount })}
)}
);
};
import { useLoginDialog } from '@/app/auth/LoginDialogContext';
import { Display } from '@/components/display';
import Modal, { AlertDialogRef } from '@/components/Modal';
import Purchase from '@/components/subscribe/purchase';
import useGlobalStore from '@/config/use-global';
import { queryUserSubscribe } from '@/services/user/user';
import { AiroButton } from '@workspace/airo-ui/components/AiroButton';
import { useTranslations } from 'next-intl';
import React from 'react';
// 星级评分组件
const StarRating = ({ rating, maxRating = 5 }: { rating: number; maxRating?: number }) => (
{Array.from({ length: Math.min(rating, maxRating) }, (_, i) => (
✭
))}
);
import SvgIcon from '@/components/SvgIcon';
// 功能列表组件
const FeatureList = ({ plan }: { plan: API.Subscribe }) => {
const t = useTranslations('subscribe.detail');
const tSubscribe = useTranslations('subscribe');
const tOffer = useTranslations('components.offerDialog');
const features = [
{ label: tOffer('availableNodes'), icon: 'feature/Vector (5)', value: plan?.server_count },
];
return (
-
{t('availableTraffic')}
-
{tSubscribe('billing.duration')}
{plan.origin_price ? '365' : '30'}
{tSubscribe('Day')}
-
{t('connectionSpeed')}
-
{plan?.name?.includes('Pro') ? (
{t('IEPL_Pro')}
) : (
{t('General_Line')}
)}
-
{t('connectedDevices')}
{features.map((feature) => (
-
{feature.label}:
{feature.value}
))}
-
{tOffer('networkStabilityIndex')}
);
};
// 套餐卡片组件
const PlanCard: React.FC<{
plan: PlanProps;
tabValue: string;
onSubscribe?: (plan: API.Subscribe) => void;
isFirstCard?: boolean;
}> = ({ plan, onSubscribe }) => {
const { user } = useGlobalStore();
const { openLoginDialog } = useLoginDialog();
const t = useTranslations('components.offerDialog');
const ModalRef = useRef(null);
async function handleSubscribe() {
if (!user) {
// 强制登陆
openLoginDialog(false);
return;
}
// 有生效套餐进行弹窗提示
const { data } = await queryUserSubscribe();
if (data?.data?.list?.[0]?.status === 1) {
ModalRef.current?.show();
return;
}
onSubscribe?.(plan);
}
return (
{/* 套餐名称 */}
{plan.name}
{/* 价格区域 */}
{/* 订阅按钮 */}
{t('subscribe')}
{/* 功能列表 */}
onSubscribe?.(plan)}
/>
);
};
PlanCard.displayName = 'PlanCard';
// 套餐列表组件
export const PlanList = ({
plans,
tabValue,
isLoading,
error,
onRetry,
emptyMessage,
onSubscribe,
}: {
plans: PlanProps[];
tabValue: string;
isLoading: boolean;
error: any;
onRetry: () => void;
emptyMessage: string;
onSubscribe?: (plan: API.Subscribe) => void;
}) => {
if (isLoading) return ;
if (error) return ;
if (plans.length === 0) return ;
return (
{plans.map((plan, index) => (
))}
);
};
interface TabContentProps {
tabValue: string;
subscribeData: API.Subscribe[];
isLoading: boolean;
error: Error | null;
onRetry: () => void;
firstPlanCardRef?: React.RefObject;
}
const TabContent: React.FC = ({
tabValue,
subscribeData,
isLoading,
error,
onRetry,
}) => {
const t = useTranslations('components.offerDialog');
// 处理套餐数据的工具函数
const processPlanData = (item: API.Subscribe, isYearly: boolean): PlanProps => {
if (isYearly) {
const discountItem = item.discount?.find((v) => v.quantity === 12);
return {
...item,
origin_price: unitConversion('centsToDollars', item.unit_price).toString(), // 原价
discount_price: unitConversion(
'centsToDollars',
item.unit_price * ((discountItem?.discount || 100) / 100),
).toString(), // 优惠价格
};
} else {
return {
...item,
origin_price: '', // 月付没有原价
discount_price: unitConversion('centsToDollars', item.unit_price).toString(), // 月付价格
};
}
};
console.log('subscribeData:', subscribeData);
let yearlyPlans: PlanProps[] = [];
if (Array.isArray(subscribeData)) {
yearlyPlans = subscribeData.map((item) => processPlanData(item, true));
}
let monthlyPlans: PlanProps[] = [];
if (Array.isArray(subscribeData)) {
monthlyPlans = subscribeData.map((item) => processPlanData(item, false));
}
const PurchaseRef = useRef<{
show: (subscribe: API.Subscribe, tabValue: string) => void;
hide: () => void;
}>(null);
// 处理订阅点击
const handleSubscribe = (plan: API.Subscribe) => {
// 这里可以添加订阅逻辑,比如跳转到支付页面或显示确认对话框
PurchaseRef.current?.show(plan, tabValue);
};
return (
{tabValue === 'year' && (
)}
{tabValue === 'month' && (
)}
);
};
export default TabContent;