feat(payment): sync plans and add coins rules

This commit is contained in:
2026-06-29 14:11:50 +08:00
parent 274fe87ced
commit e372d58b4c
24 changed files with 1099 additions and 224 deletions
+130
View File
@@ -0,0 +1,130 @@
"use client";
import {
ArrowLeft,
Coins,
Gift,
ImageIcon,
MessageCircle,
Mic2,
Phone,
Sparkles,
} from "lucide-react";
import Link from "next/link";
import { MobileShell } from "@/app/_components/core";
import { ROUTES } from "@/router/routes";
import styles from "./coins-rules-screen.module.css";
interface CoinRuleItem {
title: string;
cost: string;
free?: string;
icon: typeof MessageCircle;
}
const COIN_RULES: readonly CoinRuleItem[] = [
{
title: "普通聊天",
cost: "2 coins / 条",
free: "每周免费 50 条",
icon: MessageCircle,
},
{
title: "私密聊天",
cost: "10 coins / 条",
free: "每天免费 1 条",
icon: Sparkles,
},
{
title: "语音消息",
cost: "20 coins / 条",
icon: Mic2,
},
{
title: "语音电话",
cost: "20 coins / 张",
icon: Phone,
},
{
title: "照片",
cost: "40 coins / 张",
icon: ImageIcon,
},
{
title: "私密相册",
cost: "10 张 300 coins",
icon: ImageIcon,
},
{
title: "私密相册",
cost: "20 张 600 coins",
icon: ImageIcon,
},
] as const;
export function CoinsRulesScreen() {
return (
<MobileShell background="#fcf3f4">
<main className={styles.screen}>
<header className={styles.header}>
<Link
href={ROUTES.sidebar}
className={styles.backLink}
aria-label="Back to sidebar"
>
<ArrowLeft size={22} strokeWidth={2.4} aria-hidden="true" />
</Link>
<div className={styles.hero}>
<span className={styles.heroIcon} aria-hidden="true">
<Coins size={24} strokeWidth={2.4} />
</span>
<p className={styles.eyebrow}>Coins Guide</p>
<h1 className={styles.title}></h1>
<p className={styles.subtitle}>
</p>
</div>
</header>
<section className={styles.freeCard} aria-label="Free quota">
<div className={styles.freeIcon} aria-hidden="true">
<Gift size={20} strokeWidth={2.3} />
</div>
<div>
<h2 className={styles.freeTitle}></h2>
<p className={styles.freeText}>
50 1
</p>
</div>
</section>
<section className={styles.ruleList} aria-label="Coins usage rules">
{COIN_RULES.map((rule, index) => {
const Icon = rule.icon;
return (
<article
key={`${rule.title}-${rule.cost}`}
className={styles.ruleCard}
style={{ animationDelay: `${index * 45}ms` }}
>
<span className={styles.ruleIcon} aria-hidden="true">
<Icon size={18} strokeWidth={2.35} />
</span>
<div className={styles.ruleContent}>
<h2 className={styles.ruleTitle}>{rule.title}</h2>
{rule.free ? (
<p className={styles.freeBadge}>{rule.free}</p>
) : null}
</div>
<p className={styles.cost}>{rule.cost}</p>
</article>
);
})}
</section>
</main>
</MobileShell>
);
}