180 lines
6.5 KiB
TypeScript
180 lines
6.5 KiB
TypeScript
"use client";
|
|
|
|
import { Download, LogOut, MessageCircleQuestion } from "lucide-react";
|
|
import { signOut } from "next-auth/react";
|
|
|
|
import { BackButton } from "@/app/_components";
|
|
import { MobileShell } from "@/app/_components/core";
|
|
import {
|
|
resolveGlobalRouteContext,
|
|
type GlobalReturnToValue,
|
|
} from "@/router/global-route-context";
|
|
import { useGlobalAppNavigator } from "@/router/use-global-app-navigator";
|
|
import { useAuthDispatch, useAuthState } from "@/stores/auth/auth-context";
|
|
import { useUserDispatch, useUserState } from "@/stores/user/user-context";
|
|
|
|
import { SidebarWalletCard, UserHeader } from "./components";
|
|
import { getSidebarViewModel } from "./sidebar-view-model";
|
|
import { usePwaInstallEntry } from "./use-pwa-install-entry";
|
|
import { useSidebarUserBootstrap } from "./use-sidebar-user-bootstrap";
|
|
|
|
import styles from "./components/sidebar-screen.module.css";
|
|
|
|
export interface SidebarScreenProps {
|
|
returnTo?: GlobalReturnToValue;
|
|
}
|
|
|
|
export function SidebarScreen({ returnTo }: SidebarScreenProps) {
|
|
const navigator = useGlobalAppNavigator();
|
|
const navigation = resolveGlobalRouteContext(returnTo);
|
|
const user = useUserState();
|
|
const userDispatch = useUserDispatch();
|
|
const auth = useAuthState();
|
|
const authDispatch = useAuthDispatch();
|
|
const pwaInstallEntry = usePwaInstallEntry();
|
|
|
|
useSidebarUserBootstrap({ auth, userDispatch });
|
|
|
|
const handleLogoutClick = () => {
|
|
userDispatch({ type: "UserClearLocal" });
|
|
authDispatch({ type: "AuthLogoutSubmitted" });
|
|
void signOut({ redirect: false });
|
|
navigator.replace(navigation.splashUrl, { scroll: false });
|
|
};
|
|
|
|
const view = getSidebarViewModel({
|
|
loginStatus: auth.loginStatus,
|
|
user,
|
|
});
|
|
|
|
return (
|
|
<MobileShell background="#fcf3f4">
|
|
<div className={styles.shell}>
|
|
<div className={styles.bgOrbOne} aria-hidden="true" />
|
|
<div className={styles.bgOrbTwo} aria-hidden="true" />
|
|
|
|
<div className={styles.topBar}>
|
|
<BackButton
|
|
href={navigation.chatUrl}
|
|
variant="soft"
|
|
analyticsKey="sidebar.back_to_chat"
|
|
/>
|
|
</div>
|
|
|
|
<section className={`${styles.userSlot} ${styles.revealOne}`}>
|
|
<UserHeader
|
|
state={view.state}
|
|
name={view.name}
|
|
avatarUrl={view.avatarUrl}
|
|
isLoading={view.isInitializingUser}
|
|
onLoginClick={() => navigator.openAuth(navigation.sidebarUrl)}
|
|
/>
|
|
</section>
|
|
|
|
<section className={`${styles.cardSlot} ${styles.revealTwo}`}>
|
|
<SidebarWalletCard
|
|
creditBalance={view.wallet.creditBalance}
|
|
dailyFreeChatLimit={view.wallet.dailyFreeChatLimit}
|
|
dailyFreeChatRemaining={view.wallet.dailyFreeChatRemaining}
|
|
dailyFreePrivateLimit={view.wallet.dailyFreePrivateLimit}
|
|
dailyFreePrivateRemaining={view.wallet.dailyFreePrivateRemaining}
|
|
onActivateVip={
|
|
view.canActivateVip
|
|
? () =>
|
|
navigator.openSubscription({
|
|
type: "vip",
|
|
sourceCharacterSlug: navigation.characterSlug,
|
|
returnTo: "sidebar",
|
|
analytics: {
|
|
entryPoint: "sidebar",
|
|
triggerReason: "vip_cta",
|
|
},
|
|
})
|
|
: undefined
|
|
}
|
|
onTopUp={() =>
|
|
navigator.openSubscription({
|
|
type: "topup",
|
|
sourceCharacterSlug: navigation.characterSlug,
|
|
returnTo: "sidebar",
|
|
analytics: {
|
|
entryPoint: "sidebar",
|
|
triggerReason: "sidebar_recharge",
|
|
},
|
|
})
|
|
}
|
|
onRulesClick={() => navigator.push(navigation.coinsRulesUrl)}
|
|
/>
|
|
</section>
|
|
|
|
{view.canShowSettings ? (
|
|
<section className={`${styles.settingsSlot} ${styles.revealThree}`}>
|
|
<p className={styles.settingsLabel}>Other</p>
|
|
<div className={styles.settingsActions}>
|
|
<button
|
|
type="button"
|
|
data-analytics-key="sidebar.open_feedback"
|
|
data-analytics-label="Open feedback"
|
|
className={`${styles.logoutCard} ${styles.feedbackCard}`}
|
|
onClick={() => navigator.push(navigation.feedbackUrl)}
|
|
>
|
|
<span
|
|
className={`${styles.logoutIcon} ${styles.feedbackIcon}`}
|
|
aria-hidden="true"
|
|
>
|
|
<MessageCircleQuestion size={19} strokeWidth={2.2} />
|
|
</span>
|
|
<span className={styles.logoutText}>
|
|
<span className={styles.feedbackTitle}>Feedback</span>
|
|
<span className={styles.logoutSubtitle}>
|
|
Report a problem or share an idea
|
|
</span>
|
|
</span>
|
|
</button>
|
|
|
|
{pwaInstallEntry.canInstall ? (
|
|
<button
|
|
type="button"
|
|
className={`${styles.logoutCard} ${styles.installCard}`}
|
|
onClick={() => void pwaInstallEntry.installApp()}
|
|
>
|
|
<span
|
|
className={`${styles.logoutIcon} ${styles.installIcon}`}
|
|
aria-hidden="true"
|
|
>
|
|
<Download size={19} strokeWidth={2.2} />
|
|
</span>
|
|
<span className={styles.logoutText}>
|
|
<span className={styles.installTitle}>Install app</span>
|
|
<span className={styles.installSubtitle}>
|
|
Add CozSweet to your Home Screen
|
|
</span>
|
|
</span>
|
|
</button>
|
|
) : null}
|
|
|
|
<button
|
|
type="button"
|
|
data-analytics-key="sidebar.logout"
|
|
data-analytics-label="Log out"
|
|
className={styles.logoutCard}
|
|
onClick={handleLogoutClick}
|
|
>
|
|
<span className={styles.logoutIcon} aria-hidden="true">
|
|
<LogOut size={19} strokeWidth={2.2} />
|
|
</span>
|
|
<span className={styles.logoutText}>
|
|
<span className={styles.logoutTitle}>Log out</span>
|
|
<span className={styles.logoutSubtitle}>
|
|
End the current session safely
|
|
</span>
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</section>
|
|
) : null}
|
|
</div>
|
|
</MobileShell>
|
|
);
|
|
}
|