Spaces:
Paused
Paused
| 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 { PasswordInput } from "./ui-lib"; | |
| import LeftIcon from "@/app/icons/left.svg"; | |
| import { safeLocalStorage } from "@/app/utils"; | |
| import { | |
| trackSettingsPageGuideToCPaymentClick, | |
| trackAuthorizationPageButtonToCPaymentClick, | |
| } from "../utils/auth-settings-events"; | |
| import clsx from "clsx"; | |
| 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={clsx("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> | |
| <PasswordInput | |
| style={{ marginTop: "3vh", marginBottom: "3vh" }} | |
| aria={Locale.Settings.ShowPassword} | |
| aria-label={Locale.Auth.Input} | |
| value={accessStore.accessCode} | |
| type="text" | |
| placeholder={Locale.Auth.Input} | |
| onChange={(e) => { | |
| accessStore.update( | |
| (access) => (access.accessCode = e.currentTarget.value), | |
| ); | |
| }} | |
| /> | |
| {!accessStore.hideUserApiKey ? ( | |
| <> | |
| <div className={styles["auth-tips"]}>{Locale.Auth.SubTips}</div> | |
| <PasswordInput | |
| style={{ marginTop: "3vh", marginBottom: "3vh" }} | |
| aria={Locale.Settings.ShowPassword} | |
| aria-label={Locale.Settings.Access.OpenAI.ApiKey.Placeholder} | |
| value={accessStore.openaiApiKey} | |
| type="text" | |
| placeholder={Locale.Settings.Access.OpenAI.ApiKey.Placeholder} | |
| onChange={(e) => { | |
| accessStore.update( | |
| (access) => (access.openaiApiKey = e.currentTarget.value), | |
| ); | |
| }} | |
| /> | |
| <PasswordInput | |
| style={{ marginTop: "3vh", marginBottom: "3vh" }} | |
| aria={Locale.Settings.ShowPassword} | |
| aria-label={Locale.Settings.Access.Google.ApiKey.Placeholder} | |
| value={accessStore.googleApiKey} | |
| type="text" | |
| placeholder={Locale.Settings.Access.Google.ApiKey.Placeholder} | |
| 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={clsx(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> | |
| ); | |
| } | |