feat: Add original price display option and enhance inventory messages in subscription components

This commit is contained in:
web@ppanel
2025-12-29 05:34:01 +00:00
parent 7279275532
commit 543a7b9eb9
25 changed files with 241 additions and 61 deletions
@@ -44,6 +44,8 @@
"60003": "An existing subscription is detected. Please cancel it before proceeding.",
"60004": "Unable to delete at the moment as the subscription has active users.",
"60005": "Single subscription mode has exceeded user limit",
"60006": "User quota limit has been reached, unable to continue.",
"60007": "Insufficient inventory, please try again later or contact the administrator.",
"70001": "Incorrect verification code, please re-enter.",
"80001": "Task was not successfully queued, please try again later.",
"90001": "Please disable DEBUG mode and try again.",
@@ -6,6 +6,7 @@
"duration": "Duration",
"fee": "Fee",
"gift": "gift Deduction",
"originalPrice": "Original Price (Monthly)",
"price": "Price",
"productDiscount": "Product Discount",
"total": "Total"
@@ -44,6 +44,8 @@
"60003": "检测到现有订阅,请先取消后再继续。",
"60004": "由于订阅有活跃用户,暂时无法删除。",
"60005": "单一订阅模式已超过用户限制",
"60006": "用户配额已达到限制,无法继续操作。",
"60007": "库存不足,请稍后再试或联系管理员。",
"70001": "验证码不正确,请重新输入。",
"80001": "任务未成功加入队列,请稍后再试。",
"90001": "请禁用 DEBUG 模式后再试。",
@@ -6,6 +6,7 @@
"duration": "套餐时长",
"fee": "手续费",
"gift": "赠金抵扣",
"originalPrice": "原价(按月)",
"price": "价格",
"productDiscount": "商品折扣",
"total": "总价"
@@ -142,19 +142,44 @@ export function Content({ subscriptionData }: ProductShowcaseProps) {
</CardContent>
<Separator />
<CardFooter className="relative flex flex-col gap-4 p-4">
<motion.h2
animate={{ opacity: 1 }}
className="pb-4 font-semibold text-2xl sm:text-3xl"
initial={{ opacity: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
>
<Display type="currency" value={item.unit_price} />
<span className="font-medium text-base">
/
{unitTimeMap[item.unit_time!] ||
t(item.unit_time || "Month", item.unit_time || "Month")}
</span>
</motion.h2>
{(() => {
const hasDiscount = item.discount && item.discount.length > 0;
const shouldShowOriginal = item.show_original_price !== false;
const displayPrice =
shouldShowOriginal || !hasDiscount
? item.unit_price
: Math.round(
item.unit_price *
(item.discount?.[0]?.quantity ?? 1) *
((item.discount?.[0]?.discount ?? 100) / 100)
);
const displayQuantity =
shouldShowOriginal || !hasDiscount
? 1
: (item.discount?.[0]?.quantity ?? 1);
const unitTime =
unitTimeMap[item.unit_time!] ||
t(item.unit_time || "Month", item.unit_time || "Month");
return (
<motion.h2
animate={{ opacity: 1 }}
className="pb-4 font-semibold text-2xl sm:text-3xl"
initial={{ opacity: 0 }}
transition={{ duration: 0.5, delay: 0.2 }}
>
<Display type="currency" value={displayPrice} />
<span className="font-medium text-base">
{displayQuantity === 1
? `/${unitTime}`
: `/${displayQuantity} ${unitTime}`}
</span>
</motion.h2>
);
})()}
<motion.div>
<Button
asChild
@@ -282,6 +282,7 @@ export default function Content({
...order,
quantity: params.quantity,
unit_price: subscription?.unit_price,
show_original_price: subscription?.show_original_price,
}}
/>
</CardContent>
@@ -178,6 +178,7 @@ export default function Order() {
order={{
...data,
unit_price: data?.subscribe?.unit_price,
show_original_price: data?.subscribe?.show_original_price,
}}
/>
</CardContent>
+14 -1
View File
@@ -10,6 +10,7 @@ interface SubscribeBillingProps {
unit_price: number;
unit_time: string;
subscribe_discount: number;
show_original_price?: boolean;
}
>;
}
@@ -33,7 +34,19 @@ export function SubscribeBilling({ order }: Readonly<SubscribeBillingProps>) {
{t(order?.unit_time || "Month", order?.unit_time || "Month")}
</span>
</li>
)}
)}{" "}
{order?.show_original_price !== false &&
order?.type &&
[1, 2].includes(order?.type) && (
<li>
<span className="text-muted-foreground">
{t("billing.originalPrice", "Original Price (Monthly)")}
</span>
<span>
<Display type="currency" value={order?.unit_price} />
</span>
</li>
)}{" "}
<li>
<span className="text-muted-foreground">
{t("billing.price", "Price")}
+33 -8
View File
@@ -122,14 +122,39 @@ export default function Subscribe() {
</CardContent>
<Separator />
<CardFooter className="flex flex-col gap-2">
<h2 className="pb-8 font-semibold text-2xl sm:text-3xl">
<Display type="currency" value={item.unit_price} />
<span className="font-medium text-base">
/
{unitTimeMap[item.unit_time!] ||
t(item.unit_time || "Month", item.unit_time || "Month")}
</span>
</h2>
{(() => {
const hasDiscount = item.discount && item.discount.length > 0;
const shouldShowOriginal = item.show_original_price !== false;
const displayPrice =
shouldShowOriginal || !hasDiscount
? item.unit_price
: Math.round(
item.unit_price *
(item.discount?.[0]?.quantity ?? 1) *
((item.discount?.[0]?.discount ?? 100) / 100)
);
const displayQuantity =
shouldShowOriginal || !hasDiscount
? 1
: (item.discount?.[0]?.quantity ?? 1);
const unitTime =
unitTimeMap[item.unit_time!] ||
t(item.unit_time || "Month", item.unit_time || "Month");
return (
<h2 className="pb-8 font-semibold text-2xl sm:text-3xl">
<Display type="currency" value={displayPrice} />
<span className="font-medium text-base">
{displayQuantity === 1
? `/${unitTime}`
: `/${displayQuantity} ${unitTime}`}
</span>
</h2>
);
})()}
<Button
className="absolute bottom-0 w-full rounded-t-none rounded-b-xl"
onClick={() => {
@@ -127,6 +127,7 @@ export default function Purchase({
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
show_original_price: subscribe?.show_original_price,
}}
/>
</CardContent>
@@ -126,6 +126,7 @@ export default function Renewal({ id, subscribe }: Readonly<RenewalProps>) {
...order,
quantity: params.quantity,
unit_price: subscribe?.unit_price,
show_original_price: subscribe?.show_original_price,
}}
/>
</CardContent>
@@ -164,6 +164,7 @@ export default function Page() {
order={{
...data,
unit_price: data?.subscribe?.unit_price,
show_original_price: data?.subscribe?.show_original_price,
}}
/>
</CardContent>