import styles from "./auth.module.scss"; import { IconButton } from "./button"; import { useState, useEffect } from "react"; import { useNavigate } from "react-router-dom"; import { Path, SAAS_CHAT_URL } from "../constant"; import { useAccessStore } from "../store"; import Locale from "../locales"; import Delete from "../icons/close.svg"; import Arrow from "../icons/arrow.svg"; import Logo from "../icons/logo.svg"; import { useMobileScreen } from "@/app/utils"; import BotIcon from "../icons/bot.svg"; import { getClientConfig } from "../config/client"; import LeftIcon from "@/app/icons/left.svg"; import { safeLocalStorage } from "@/app/utils"; import { trackSettingsPageGuideToCPaymentClick, trackAuthorizationPageButtonToCPaymentClick, } from "../utils/auth-settings-events"; const storage = safeLocalStorage(); export function AuthPage() { const navigate = useNavigate(); const accessStore = useAccessStore(); const goHome = () => navigate(Path.Home); const goChat = () => navigate(Path.Chat); const goSaas = () => { trackAuthorizationPageButtonToCPaymentClick(); window.location.href = SAAS_CHAT_URL; }; const resetAccessCode = () => { accessStore.update((access) => { access.openaiApiKey = ""; access.accessCode = ""; }); }; // Reset access code to empty string useEffect(() => { if (getClientConfig()?.isApp) { navigate(Path.Settings); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( <div className={styles["auth-page"]}> <TopBanner></TopBanner> <div className={styles["auth-header"]}> <IconButton icon={<LeftIcon />} text={Locale.Auth.Return} onClick={() => navigate(Path.Home)} ></IconButton> </div> <div className={`no-dark ${styles["auth-logo"]}`}> <BotIcon /> </div> <div className={styles["auth-title"]}>{Locale.Auth.Title}</div> <div className={styles["auth-tips"]}>{Locale.Auth.Tips}</div> <input className={styles["auth-input"]} type="password" placeholder={Locale.Auth.Input} value={accessStore.accessCode} onChange={(e) => { accessStore.update( (access) => (access.accessCode = e.currentTarget.value), ); }} /> {!accessStore.hideUserApiKey ? ( <> <div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div> <input className={styles["auth-input"]} type="password" placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder} value={accessStore.openaiApiKey} onChange={(e) => { accessStore.update( (access) => (access.openaiApiKey = e.currentTarget.value), ); }} /> <input className={styles["auth-input-second"]} type="password" placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder} value={accessStore.googleApiKey} onChange={(e) => { accessStore.update( (access) => (access.googleApiKey = e.currentTarget.value), ); }} /> </> ) : null} <div className={styles["auth-actions"]}> <IconButton text={Locale.Auth.Confirm} type="primary" onClick={goChat} /> <IconButton text={Locale.Auth.SaasTips} onClick={() => { goSaas(); }} /> </div> </div> ); } function TopBanner() { const [isHovered, setIsHovered] = useState(false); const [isVisible, setIsVisible] = useState(true); const isMobile = useMobileScreen(); useEffect(() => { // 检查 localStorage 中是否有标记 const bannerDismissed = storage.getItem("bannerDismissed"); // 如果标记不存在,存储默认值并显示横幅 if (!bannerDismissed) { storage.setItem("bannerDismissed", "false"); setIsVisible(true); // 显示横幅 } else if (bannerDismissed === "true") { // 如果标记为 "true",则隐藏横幅 setIsVisible(false); } }, []); const handleMouseEnter = () => { setIsHovered(true); }; const handleMouseLeave = () => { setIsHovered(false); }; const handleClose = () => { setIsVisible(false); storage.setItem("bannerDismissed", "true"); }; if (!isVisible) { return null; } return ( <div className={styles["top-banner"]} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} > <div className={`${styles["top-banner-inner"]} no-dark`}> <Logo className={styles["top-banner-logo"]}></Logo> <span> {Locale.Auth.TopTips} <a href={SAAS_CHAT_URL} rel="stylesheet" onClick={() => { trackSettingsPageGuideToCPaymentClick(); }} > {Locale.Settings.Access.SaasStart.ChatNow} <Arrow style={{ marginLeft: "4px" }} /> </a> </span> </div> {(isHovered || isMobile) && ( <Delete className={styles["top-banner-close"]} onClick={handleClose} /> )} </div> ); }