import { create } from "@bufbuild/protobuf"; import { timestampDate } from "@bufbuild/protobuf/wkt"; import { LoaderIcon } from "lucide-react"; import { useState } from "react"; import { toast } from "react-hot-toast"; import { Link, useSearchParams } from "react-router-dom"; import { setAccessToken } from "@/auth-state"; import AuthFooter from "@/components/AuthFooter"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { authServiceClient, userServiceClient } from "@/connect"; import { useAuth } from "@/contexts/AuthContext"; import { useInstance } from "@/contexts/InstanceContext"; import useLoading from "@/hooks/useLoading"; import useNavigateTo from "@/hooks/useNavigateTo"; import { handleError } from "@/lib/error"; import { ROUTES } from "@/router/routes"; import { User_Role, UserSchema } from "@/types/proto/api/v1/user_service_pb"; import { AUTH_REDIRECT_PARAM, getSafeRedirectPath } from "@/utils/auth-redirect"; import { useTranslate } from "@/utils/i18n"; const SignUp = () => { const t = useTranslate(); const navigateTo = useNavigateTo(); const actionBtnLoadingState = useLoading(false); const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const { initialize: initAuth } = useAuth(); const { generalSetting: instanceGeneralSetting, profile, initialize: initInstance } = useInstance(); const [searchParams] = useSearchParams(); const redirectTarget = getSafeRedirectPath(searchParams.get(AUTH_REDIRECT_PARAM)); const signInPath = searchParams.toString() ? `${ROUTES.AUTH}?${searchParams.toString()}` : ROUTES.AUTH; const handleUsernameInputChanged = (e: React.ChangeEvent) => { const text = e.target.value as string; setUsername(text); }; const handlePasswordInputChanged = (e: React.ChangeEvent) => { const text = e.target.value as string; setPassword(text); }; const handleFormSubmit = (e: React.FormEvent) => { e.preventDefault(); handleSignUpButtonClick(); }; const handleSignUpButtonClick = async () => { if (username === "" || password === "") { return; } if (actionBtnLoadingState.isLoading) { return; } try { actionBtnLoadingState.setLoading(); const user = create(UserSchema, { username, password, role: User_Role.USER, }); await userServiceClient.createUser({ user }); const response = await authServiceClient.signIn({ credentials: { case: "passwordCredentials", value: { username, password }, }, }); // Store access token from login response if (response.accessToken) { setAccessToken(response.accessToken, response.accessTokenExpiresAt ? timestampDate(response.accessTokenExpiresAt) : undefined); } // Refresh auth context to load the current user await initAuth(); // Refetch instance profile to update the initialized status await initInstance(); navigateTo(redirectTarget || ROUTES.ROOT, { replace: true }); } catch (error: unknown) { handleError(error, toast.error, { fallbackMessage: "Sign up failed", }); } actionBtnLoadingState.setFinish(); }; return (

{instanceGeneralSetting.customProfile?.title || "Memos"}

{!instanceGeneralSetting.disallowUserRegistration ? ( <>

{t("auth.create-your-account")}

{t("common.username")}
{t("common.password")}
) : (

Sign up is not allowed.

)} {!profile.admin ? (

{t("auth.host-tip")}

) : (

{t("auth.sign-in-tip")} {t("common.sign-in")}

)}
); }; export default SignUp;