extract account menu
This commit is contained in:
@@ -2,12 +2,13 @@ import {
|
||||
CircleHelp,
|
||||
FolderKanban,
|
||||
Home,
|
||||
LogOut,
|
||||
Plus,
|
||||
Settings,
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { getClientProfileDashboard } from '../services/clientApi';
|
||||
import BRAND_ICON from '../../../../packages/shared/src/icons/taonier-product-ip.png';
|
||||
function cx(...classNames: Array<string | false | null | undefined>) {
|
||||
return classNames.filter(Boolean).join(' ');
|
||||
@@ -44,6 +45,131 @@ type LauncherSidebarProps = {
|
||||
onLogout: () => void;
|
||||
};
|
||||
|
||||
type SidebarAccountMenuProps = {
|
||||
currentUser: SidebarUserInfo;
|
||||
onClose: () => void;
|
||||
onLogout: () => void;
|
||||
onNoticeRequest: (title: string) => void;
|
||||
};
|
||||
|
||||
function formatMudPoints(value: number | null | undefined) {
|
||||
if (typeof value !== 'number' || !Number.isFinite(value)) {
|
||||
return '--';
|
||||
}
|
||||
return Math.max(0, Math.floor(value)).toLocaleString('zh-CN');
|
||||
}
|
||||
|
||||
function SidebarAccountMenu({
|
||||
currentUser,
|
||||
onClose,
|
||||
onLogout,
|
||||
onNoticeRequest,
|
||||
}: SidebarAccountMenuProps) {
|
||||
const [walletBalanceLabel, setWalletBalanceLabel] = useState('--');
|
||||
const [walletBalanceStatus, setWalletBalanceStatus] =
|
||||
useState('正在读取泥点余额');
|
||||
|
||||
useEffect(() => {
|
||||
let disposed = false;
|
||||
void getClientProfileDashboard()
|
||||
.then((dashboard) => {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
setWalletBalanceLabel(formatMudPoints(dashboard.walletBalance));
|
||||
setWalletBalanceStatus('泥点余额已读取');
|
||||
})
|
||||
.catch((error) => {
|
||||
if (disposed) {
|
||||
return;
|
||||
}
|
||||
setWalletBalanceLabel('--');
|
||||
setWalletBalanceStatus(
|
||||
error instanceof Error ? error.message : '泥点余额读取失败',
|
||||
);
|
||||
});
|
||||
return () => {
|
||||
disposed = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
function showNotice(title: string) {
|
||||
onClose();
|
||||
onNoticeRequest(title);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute bottom-[-4px] left-14 z-[90] grid w-[218px] gap-1.5 rounded-lg border border-(--platform-subpanel-border) bg-(--platform-subpanel-fill) p-2.5 text-(--platform-text-strong) shadow-[0_16px_38px_rgb(15_23_42_/_14%)]"
|
||||
role="menu"
|
||||
>
|
||||
<strong className="text-[13px]">
|
||||
{currentUser.displayName || '陶泥儿用户'}
|
||||
</strong>
|
||||
<span className="text-[11px] text-(--platform-text-soft)">
|
||||
{currentUser.phoneNumberMasked ||
|
||||
currentUser.publicUserCode ||
|
||||
'账号信息读取中'}
|
||||
</span>
|
||||
<div
|
||||
className="grid gap-2 rounded-xl bg-[linear-gradient(135deg,#eaa06a,#cf7a4a_58%,#b55c3b)] p-3 text-white shadow-[0_18px_38px_rgb(189_103_60_/_22%)]"
|
||||
role="group"
|
||||
aria-label="会员方案"
|
||||
>
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span
|
||||
className="min-w-0 text-[12px] font-bold"
|
||||
title={walletBalanceStatus}
|
||||
>
|
||||
剩余泥点 {walletBalanceLabel}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
className="grid size-7 shrink-0 place-items-center rounded-full border border-white/70 bg-white/15 text-white"
|
||||
aria-label="充值泥点"
|
||||
onClick={onClose}
|
||||
>
|
||||
<Plus size={14} aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={
|
||||
() => showNotice('使用指南')
|
||||
// TODO open url https://kcnz41bksl1c.feishu.cn/wiki/YN5TwLxreiYHrYk9DNqcjz8QnZc
|
||||
}
|
||||
>
|
||||
使用指南
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={
|
||||
() => showNotice('反馈联系')
|
||||
// TODO open url https://kcnz41bksl1c.feishu.cn/share/base/form/shrcn1p9WpuZMDxrI5ysLLJhw7k
|
||||
}
|
||||
>
|
||||
反馈联系
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={() => {
|
||||
onClose();
|
||||
onLogout();
|
||||
}}
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Sidebar({
|
||||
activeView,
|
||||
currentUser,
|
||||
@@ -96,11 +222,6 @@ export function Sidebar({
|
||||
setAccountMenuOpen(false);
|
||||
}
|
||||
|
||||
function showNotice(title: string) {
|
||||
closeMenus();
|
||||
onNoticeRequest(title);
|
||||
}
|
||||
|
||||
function changeView(view: LauncherView) {
|
||||
closeMenus();
|
||||
onViewChange(view);
|
||||
@@ -110,10 +231,13 @@ export function Sidebar({
|
||||
<aside className="w-16 sticky top-0 z-40 flex h-screen flex-col items-center gap-4 overflow-visible border-r border-(--platform-surface-border) bg-(--platform-nav-fill) px-0 pb-4.5 pt-4">
|
||||
<div className="grid place-items-center" aria-label="陶泥儿">
|
||||
<span className="grid size-12 place-items-center rounded-full bg-(--platform-button-primary-fill) text-[10px] font-bold tracking-normal text-(--platform-button-primary-text) shadow-(--platform-profile-action-shadow)">
|
||||
<img src={BRAND_ICON} alt="brand logo"/>
|
||||
<img src={BRAND_ICON} alt="brand logo" />
|
||||
</span>
|
||||
</div>
|
||||
<nav className="grid justify-items-center gap-3.25" aria-label="客户端导航">
|
||||
<nav
|
||||
className="grid justify-items-center gap-3.25"
|
||||
aria-label="客户端导航"
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="首页"
|
||||
@@ -156,56 +280,12 @@ export function Sidebar({
|
||||
<User size={16} aria-hidden="true" />
|
||||
</button>
|
||||
{accountMenuOpen ? (
|
||||
<div
|
||||
className="absolute bottom-[-4px] left-14 z-[90] grid w-[218px] gap-1.5 rounded-lg border border-(--platform-subpanel-border) bg-(--platform-subpanel-fill) p-2.5 text-(--platform-text-strong) shadow-[0_16px_38px_rgb(15_23_42_/_14%)]"
|
||||
role="menu"
|
||||
>
|
||||
<strong className="text-[13px]">
|
||||
{currentUser.displayName || '陶泥儿用户'}
|
||||
</strong>
|
||||
<span className="text-[11px] text-(--platform-text-soft)">
|
||||
{currentUser.phoneNumberMasked ||
|
||||
currentUser.publicUserCode ||
|
||||
'账号信息读取中'}
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={() => showNotice('会员与升级')}
|
||||
>
|
||||
会员与升级
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={() => showNotice('使用指南')}
|
||||
>
|
||||
使用指南
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={() => showNotice('反馈联系')}
|
||||
>
|
||||
反馈联系
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitem"
|
||||
className={sidebarMenuItemClass}
|
||||
onClick={() => {
|
||||
closeMenus();
|
||||
onLogout();
|
||||
}}
|
||||
>
|
||||
{/*// TODO align*/}
|
||||
<LogOut size={14} aria-hidden="true" />
|
||||
退出登录
|
||||
</button>
|
||||
</div>
|
||||
<SidebarAccountMenu
|
||||
currentUser={currentUser}
|
||||
onClose={closeMenus}
|
||||
onLogout={onLogout}
|
||||
onNoticeRequest={onNoticeRequest}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="relative" ref={helpMenuRef}>
|
||||
@@ -216,6 +296,7 @@ export function Sidebar({
|
||||
className={sidebarHelpButtonClass}
|
||||
onClick={() => {
|
||||
// TODO open the guide
|
||||
// TODO open url https://kcnz41bksl1c.feishu.cn/wiki/YN5TwLxreiYHrYk9DNqcjz8QnZc
|
||||
}}
|
||||
>
|
||||
<CircleHelp size={17} aria-hidden="true" />
|
||||
|
||||
Reference in New Issue
Block a user