feat: add AirShelf core implementation
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import { useState } from "react";
|
||||
import { CreditCard } from "lucide-react";
|
||||
import type { BillingSummary, Ledger, Project, TeamMember } from "../types";
|
||||
import { money, stageMeta, statusPill } from "./stage-config";
|
||||
|
||||
export function AccountPage({ billing, ledgers, projects, teamMembers }: {
|
||||
billing: BillingSummary | null;
|
||||
ledgers: Ledger[];
|
||||
projects: Project[];
|
||||
teamMembers: TeamMember[];
|
||||
}) {
|
||||
const [tab, setTab] = useState<"overview" | "projects" | "members" | "bills">("overview");
|
||||
const [amount, setAmount] = useState(500);
|
||||
return (
|
||||
<>
|
||||
<div className="page-head"><div><h1>消费</h1><div className="sub"><span className="mono">// 余额 · 充值 · 4 维消费视图 + 账单流水</span></div></div></div>
|
||||
<div className="top-grid"><div className="balance-banner"><span className="corner-tr">+</span><span className="corner-bl">+</span><div className="balance-hero"><div className="lbl">团队余额</div><div className="v">{money(billing?.account.balance)}</div><div className="meta">// 冻结 {money(billing?.account.reserved_balance)} · 已消费 {money(billing?.charged_total)}</div></div></div><div className="pane topup-pane"><div className="topup-head"><div><h3>快速充值</h3><div className="desc">// 充值后立刻到账,可开发票</div></div><div className="topup-selected">已选 ¥{amount}</div></div><div className="recharge-row">{[100, 500, 1000, 3000].map((item) => <button className={`recharge-card ${amount === item ? "selected" : ""}`} type="button" key={item} onClick={() => setAmount(item)}><div className="amt">¥{item}</div><div className="gift">+ 赠送</div></button>)}</div><button className="btn pay-method-btn" type="button"><CreditCard size={13} />微信支付</button></div></div>
|
||||
<div className="billing-tabs">{[["overview", "总览"], ["projects", "项目"], ["members", "成员"], ["bills", "账单流水"]].map(([key, label]) => <button className={`tab ${tab === key ? "active" : ""}`} type="button" key={key} onClick={() => setTab(key as typeof tab)}>{label}</button>)}</div>
|
||||
{tab === "overview" && <div className="overview-grid"><div className="pane trend-pane"><h3>消费趋势</h3><div className="bars">{Array.from({ length: 14 }).map((_, index) => <span key={index} style={{ height: `${18 + (index % 6) * 10}%` }} />)}</div></div><div className="pane stage-pane"><h3>本月按阶段分布</h3><UsageLine label="视频片段" value="¥98.40" width="60%" color="var(--orange)" /><UsageLine label="故事板" value="¥36.00" width="22%" color="var(--green)" /></div></div>}
|
||||
{tab === "projects" && <table className="billing-table"><thead><tr><th>项目</th><th>当前阶段</th><th>状态</th><th>消耗</th></tr></thead><tbody>{projects.map((project) => <tr key={project.id}><td>{project.name}</td><td>{stageMeta[project.current_stage]?.label || project.current_stage}</td><td><span className={`pill ${statusPill(project.status)}`}><span className="dot" />{project.status}</span></td><td>¥0.00</td></tr>)}</tbody></table>}
|
||||
{tab === "members" && <table className="billing-table"><thead><tr><th>成员</th><th>角色</th><th>额度</th><th>状态</th></tr></thead><tbody>{teamMembers.map((member) => <tr key={member.id}><td>{member.user.username}</td><td>{member.role}</td><td>{money(member.monthly_credit_limit)}</td><td><span className={`pill ${statusPill(member.status)}`}><span className="dot" />{member.status}</span></td></tr>)}</tbody></table>}
|
||||
{tab === "bills" && <table className="billing-table bills"><thead><tr><th>时间</th><th>类型</th><th>详情</th><th>金额</th></tr></thead><tbody>{ledgers.map((item) => <tr key={item.id}><td>{new Date(item.created_at).toLocaleString("zh-CN")}</td><td>{item.ledger_type}</td><td>{item.reason}</td><td>{item.amount}</td></tr>)}</tbody></table>}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function UsageLine({ label, value, width, color }: { label: string; value: string; width: string; color: string }) {
|
||||
return <><div className="usage-line"><span>{label}</span><span className="v">{value}</span></div><div className="usage-bar"><span style={{ width, background: color }} /></div></>;
|
||||
}
|
||||
Reference in New Issue
Block a user