80 lines
2.1 KiB
TypeScript
80 lines
2.1 KiB
TypeScript
"use client";
|
||
/**
|
||
* 订阅套餐卡片
|
||
*
|
||
* 视觉规格(与设计稿对齐):
|
||
* - 卡片顶部:套餐名(12px / secondary)
|
||
* - 中部:大字价格(28px / 300)+ 划线原价(12px / line-through / 999)
|
||
* - 底部 28px 高渐变条:白字 12px/600 每日折算价
|
||
* - 选中:2px 粉色边框 + 浅粉阴影
|
||
* - 三个卡片底部渐变不同:粉 → 紫红 → 紫
|
||
*/
|
||
|
||
import styles from "./subscription-plan-card.module.css";
|
||
|
||
const PER_DAY_GRADIENTS = [
|
||
"linear-gradient(90deg, #ff7ab8 0%, #ff5d9c 100%)",
|
||
"linear-gradient(90deg, #d16bff 0%, #ff5da3 100%)",
|
||
"linear-gradient(90deg, #9a4dff 0%, #c44dff 100%)",
|
||
"linear-gradient(90deg, #32c7b5 0%, #2f8fd8 100%)",
|
||
] as const;
|
||
|
||
export interface SubscriptionPlanView {
|
||
id: string;
|
||
name: string;
|
||
price: string;
|
||
originalPrice: string | null;
|
||
perDay: string;
|
||
currencySymbol: string;
|
||
}
|
||
|
||
export interface SubscriptionPlanCardProps {
|
||
plan: SubscriptionPlanView;
|
||
selected: boolean;
|
||
onClick: () => void;
|
||
gradientIndex?: number;
|
||
className?: string;
|
||
}
|
||
|
||
export function SubscriptionPlanCard({
|
||
plan,
|
||
selected,
|
||
onClick,
|
||
gradientIndex = 0,
|
||
className,
|
||
}: SubscriptionPlanCardProps) {
|
||
const classes = [
|
||
styles.card,
|
||
selected ? styles.selected : "",
|
||
className,
|
||
]
|
||
.filter(Boolean)
|
||
.join(" ");
|
||
|
||
const perDayStyle = {
|
||
background: PER_DAY_GRADIENTS[gradientIndex % PER_DAY_GRADIENTS.length],
|
||
};
|
||
|
||
return (
|
||
<button
|
||
type="button"
|
||
onClick={onClick}
|
||
aria-pressed={selected}
|
||
aria-label={`${plan.name} plan, ${plan.currencySymbol}${plan.price}`}
|
||
className={classes}
|
||
>
|
||
<p className={styles.name}>{plan.name}</p>
|
||
<div className={styles.priceBlock}>
|
||
<span className={styles.currency}>{plan.currencySymbol}</span>
|
||
<span className={styles.price}>{plan.price}</span>
|
||
</div>
|
||
<p className={styles.originalPrice}>
|
||
{plan.originalPrice ? `${plan.currencySymbol}${plan.originalPrice}` : "\u00a0"}
|
||
</p>
|
||
<div className={styles.perDayBar} style={perDayStyle}>
|
||
{plan.perDay}
|
||
</div>
|
||
</button>
|
||
);
|
||
}
|