115 lines
3.2 KiB
TypeScript
115 lines
3.2 KiB
TypeScript
"use client";
|
|
|
|
import { signOut } from "next-auth/react";
|
|
import { useRouter } from "next/navigation";
|
|
|
|
import { MobileShell, SettingsSection } from "@/app/_components/core";
|
|
import { ROUTES } from "@/router/routes";
|
|
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
|
|
import { useUserDispatch, useUserState } from "@/stores/user/user-context";
|
|
|
|
import {
|
|
BackBar,
|
|
UserHeader,
|
|
type SidebarUserState,
|
|
VipBenefitsCard,
|
|
VoicePackageCard,
|
|
} from "./components";
|
|
|
|
import styles from "./components/sidebar-screen.module.css";
|
|
|
|
const FALLBACK_USERNAME = "User name";
|
|
|
|
/**
|
|
* 侧边栏主屏幕
|
|
*
|
|
* 根据 `loginStatus + currentUser.isVip` 派生三种状态:
|
|
* - guest:未登录
|
|
* - member:已登录未购买 VIP
|
|
* - vip:已登录且购买 VIP
|
|
*
|
|
* 原始 Dart: lib/ui/sidebar/sidebar_screen.dart + profile_view.dart
|
|
*/
|
|
export function SidebarScreen() {
|
|
const router = useRouter();
|
|
const user = useUserState();
|
|
const userDispatch = useUserDispatch();
|
|
const auth = useAuthState();
|
|
const authDispatch = useAuthDispatch();
|
|
|
|
const handleLogoutClick = () => {
|
|
userDispatch({ type: "UserClearLocal" });
|
|
authDispatch({ type: "AuthLogoutSubmitted" });
|
|
void signOut({ redirect: false });
|
|
};
|
|
|
|
// 状态派生:未登录 / 已登录未 VIP / 已登录 VIP
|
|
const sidebarState: SidebarUserState =
|
|
auth.loginStatus === "notLoggedIn"
|
|
? "guest"
|
|
: user.currentUser?.isVip === true
|
|
? "vip"
|
|
: "member";
|
|
|
|
const isInitializingUser =
|
|
sidebarState !== "guest" && user.currentUser == null;
|
|
|
|
const name = user.currentUser?.username ?? FALLBACK_USERNAME;
|
|
const avatarUrl = user.currentUser?.avatarUrl ?? null;
|
|
|
|
return (
|
|
<MobileShell>
|
|
<div className={styles.shell}>
|
|
<BackBar />
|
|
|
|
{/* 用户信息区:三种状态 */}
|
|
<section className={styles.userSlot}>
|
|
<UserHeader
|
|
state={sidebarState}
|
|
name={name}
|
|
avatarUrl={avatarUrl}
|
|
isLoading={isInitializingUser}
|
|
onLoginClick={() => router.push(ROUTES.auth)}
|
|
/>
|
|
</section>
|
|
|
|
<section className={styles.cardSlot}>
|
|
<VipBenefitsCard
|
|
state={sidebarState}
|
|
onActivate={() => router.push(ROUTES.subscription)}
|
|
/>
|
|
</section>
|
|
|
|
<section className={styles.cardSlot}>
|
|
<VoicePackageCard
|
|
usedMinutes={0}
|
|
totalMinutes={0}
|
|
onBuyPackage={() => router.push(ROUTES.subscription)}
|
|
/>
|
|
</section>
|
|
|
|
{sidebarState !== "guest" ? (
|
|
<section className={styles.settingsSlot}>
|
|
<SettingsSection
|
|
title="Other"
|
|
items={[
|
|
// {
|
|
// id: "membership",
|
|
// title: "Membership",
|
|
// onClick: () => router.push(ROUTES.subscription),
|
|
// },
|
|
{
|
|
id: "logout",
|
|
title: "Log out",
|
|
destructive: true,
|
|
onClick: handleLogoutClick,
|
|
},
|
|
]}
|
|
/>
|
|
</section>
|
|
) : null}
|
|
</div>
|
|
</MobileShell>
|
|
);
|
|
}
|