refactor: search params in reg
This commit is contained in:
@@ -92,7 +92,7 @@ export const channelApi = createApi({
|
|||||||
// return _link;
|
// return _link;
|
||||||
// 替换掉域名
|
// 替换掉域名
|
||||||
const invite = new URL(_link);
|
const invite = new URL(_link);
|
||||||
return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`;
|
return `${location.origin}${invite.pathname}${invite.hash}${invite.search}`;
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
removeChannel: builder.query<void, number>({
|
removeChannel: builder.query<void, number>({
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ const UsersPage = lazy(() => import("./users"));
|
|||||||
const CallbackPage = lazy(() => import("./callback"));
|
const CallbackPage = lazy(() => import("./callback"));
|
||||||
const FavoritesPage = lazy(() => import("./favs"));
|
const FavoritesPage = lazy(() => import("./favs"));
|
||||||
const OnboardingPage = lazy(() => import("./onboarding"));
|
const OnboardingPage = lazy(() => import("./onboarding"));
|
||||||
const InvitePage = lazy(() => import("./invite"));
|
|
||||||
const SettingChannelPage = lazy(() => import("./settingChannel"));
|
const SettingChannelPage = lazy(() => import("./settingChannel"));
|
||||||
const SettingDMPage = lazy(() => import("./settingDM"));
|
const SettingDMPage = lazy(() => import("./settingDM"));
|
||||||
const SettingPage = lazy(() => import("./setting"));
|
const SettingPage = lazy(() => import("./setting"));
|
||||||
@@ -107,7 +106,6 @@ const PageRoutes = () => {
|
|||||||
</LazyIt>
|
</LazyIt>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Route path="/invite" element={<LazyIt><InvitePage /></LazyIt>} />
|
|
||||||
<Route path="/onboarding" element={<LazyIt><OnboardingPage /></LazyIt>} />
|
<Route path="/onboarding" element={<LazyIt><OnboardingPage /></LazyIt>} />
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
|
|||||||
@@ -1,178 +0,0 @@
|
|||||||
import { useState, useEffect, FormEvent, ChangeEvent, FC } from "react";
|
|
||||||
import { Navigate } from "react-router-dom";
|
|
||||||
import toast from "react-hot-toast";
|
|
||||||
import BASE_URL from "../../app/config";
|
|
||||||
import { useRegisterMutation } from "../../app/services/auth";
|
|
||||||
import { useCheckMagicTokenValidMutation } from "../../app/services/auth";
|
|
||||||
import { useAppSelector } from "../../app/store";
|
|
||||||
import StyledButton from "../../common/component/styled/Button";
|
|
||||||
import Input from "../../common/component/styled/Input";
|
|
||||||
|
|
||||||
interface AuthForm {
|
|
||||||
name: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const InvitePage: FC = () => {
|
|
||||||
const { token: loginToken, serverName } = useAppSelector((store) => {
|
|
||||||
return { token: store.authData.token, serverName: store.server.name };
|
|
||||||
});
|
|
||||||
const [secondPwd, setSecondPwd] = useState("");
|
|
||||||
const [samePwd, setSamePwd] = useState(true);
|
|
||||||
const [token, setToken] = useState<string | undefined>();
|
|
||||||
const [valid, setValid] = useState(false);
|
|
||||||
const [register, { data, isLoading, isSuccess, isError, error }] = useRegisterMutation();
|
|
||||||
const [checkToken, { data: isValid, isLoading: checkLoading, isSuccess: checkSuccess }] =
|
|
||||||
useCheckMagicTokenValidMutation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const query = new URLSearchParams(location.search);
|
|
||||||
setToken(query.get("token") ?? undefined);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (token) {
|
|
||||||
checkToken(token);
|
|
||||||
}
|
|
||||||
}, [token]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (checkSuccess) {
|
|
||||||
setValid(!!isValid);
|
|
||||||
} else {
|
|
||||||
setValid(false);
|
|
||||||
}
|
|
||||||
}, [checkSuccess, isValid]);
|
|
||||||
|
|
||||||
const [input, setInput] = useState<AuthForm>({ name: "", email: "", password: "" });
|
|
||||||
|
|
||||||
const handleReg = (evt: FormEvent<HTMLFormElement>) => {
|
|
||||||
evt.preventDefault();
|
|
||||||
if (!samePwd) {
|
|
||||||
toast.error("two passwords not same");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
register({
|
|
||||||
...input,
|
|
||||||
magic_token: token,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const { type } = evt.target.dataset as { type: keyof AuthForm };
|
|
||||||
const { value } = evt.target;
|
|
||||||
setInput((prev) => {
|
|
||||||
prev[type] = value;
|
|
||||||
return { ...prev };
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSecondPwdInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
const { value } = evt.target;
|
|
||||||
setSecondPwd(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handlePwdCheck = () => {
|
|
||||||
if (secondPwd) {
|
|
||||||
setSamePwd(secondPwd == input.password);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!samePwd) {
|
|
||||||
toast.error("two passwords not same");
|
|
||||||
}
|
|
||||||
}, [samePwd]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isSuccess && data) {
|
|
||||||
// 去登录
|
|
||||||
toast.success("register success, login please");
|
|
||||||
setTimeout(() => {
|
|
||||||
location.href = `/#/login`;
|
|
||||||
// navigateTo("/login",);
|
|
||||||
}, 500);
|
|
||||||
} else if (isError && error && "data" in error) {
|
|
||||||
switch (error.status) {
|
|
||||||
case 400:
|
|
||||||
toast.error("Register Failed: please check inputs");
|
|
||||||
break;
|
|
||||||
case 412:
|
|
||||||
toast.error("Register Failed: invalid token or expired");
|
|
||||||
break;
|
|
||||||
case 409: {
|
|
||||||
toast.error(`Register Failed: ${error.data?.reason}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
toast.error("Register Failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [data, isSuccess, isError, error]);
|
|
||||||
|
|
||||||
const { email, password, name } = input;
|
|
||||||
if (loginToken) return <Navigate replace to="/" />;
|
|
||||||
if (!token) return <>token not found</>;
|
|
||||||
if (checkLoading) return <>checking token valid</>;
|
|
||||||
if (!valid) return <>invite token expires or invalid</>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="flex-center h-screen dark:bg-gray-700">
|
|
||||||
<div className="py-8 px-10 shadow-md rounded-xl">
|
|
||||||
<div className="flex-center flex-col pb-6">
|
|
||||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="w-14 h-14 mb-7 rounded-full" />
|
|
||||||
<h2 className="font-semibold text-2xl text-gray-800 dark:text-white mb-2">Sign Up to {serverName}</h2>
|
|
||||||
<span className="text-gray-400 dark:text-gray-100">Please enter your details.</span>
|
|
||||||
</div>
|
|
||||||
<form className="flex flex-col gap-5 min-w-[360px]" onSubmit={handleReg}>
|
|
||||||
<Input
|
|
||||||
className="large"
|
|
||||||
name="name"
|
|
||||||
value={name}
|
|
||||||
required
|
|
||||||
placeholder="Enter your name"
|
|
||||||
data-type="name"
|
|
||||||
onChange={handleInput}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
className="large"
|
|
||||||
name="email"
|
|
||||||
value={email}
|
|
||||||
required
|
|
||||||
placeholder="Enter your email"
|
|
||||||
data-type="email"
|
|
||||||
onChange={handleInput}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
className="large"
|
|
||||||
type="password"
|
|
||||||
value={password}
|
|
||||||
name="password"
|
|
||||||
required
|
|
||||||
data-type="password"
|
|
||||||
onChange={handleInput}
|
|
||||||
placeholder="Enter your password"
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
className="large"
|
|
||||||
type="password"
|
|
||||||
value={secondPwd}
|
|
||||||
name="password"
|
|
||||||
required
|
|
||||||
data-type="password"
|
|
||||||
onBlur={handlePwdCheck}
|
|
||||||
onChange={handleSecondPwdInput}
|
|
||||||
placeholder="Enter your password again"
|
|
||||||
/>
|
|
||||||
<StyledButton disabled={isLoading || isSuccess} className="flex justify-center" type="submit">
|
|
||||||
Sign Up
|
|
||||||
</StyledButton>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default InvitePage;
|
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
import { useState, useEffect, FormEvent, ChangeEvent } from "react";
|
import { useState, useEffect, FormEvent, ChangeEvent } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import BASE_URL from "../../app/config";
|
import BASE_URL from "../../app/config";
|
||||||
// import web3 from "web3";
|
|
||||||
|
|
||||||
import Input from "../../common/component/styled/Input";
|
import Input from "../../common/component/styled/Input";
|
||||||
import Button from "../../common/component/styled/Button";
|
import Button from "../../common/component/styled/Button";
|
||||||
@@ -56,7 +55,8 @@ export default function LoginPage() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// reg with magic link and set name only
|
// reg with magic link and set name only
|
||||||
location.href = `?magic_token=${magic_token}#/register/set_name/login`;
|
// navigate(`/register/set_name/login?magic_token=${magic_token}`);
|
||||||
|
location.href = `/#/register/set_name/login?magic_token=${magic_token}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, FC, FormEvent, ChangeEvent } from "react";
|
import { useState, useEffect, FC, FormEvent, ChangeEvent } from "react";
|
||||||
import { useDispatch } from "react-redux";
|
import { useDispatch } from "react-redux";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams, useSearchParams } from "react-router-dom";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { setAuthData } from "../../app/slices/auth.data";
|
import { setAuthData } from "../../app/slices/auth.data";
|
||||||
import Input from "../../common/component/styled/Input";
|
import Input from "../../common/component/styled/Input";
|
||||||
@@ -13,6 +13,7 @@ import { useRegisterMutation } from "../../app/services/auth";
|
|||||||
const RegWithUsername: FC = () => {
|
const RegWithUsername: FC = () => {
|
||||||
const { t: ct } = useTranslation();
|
const { t: ct } = useTranslation();
|
||||||
const { t } = useTranslation("auth");
|
const { t } = useTranslation("auth");
|
||||||
|
const [searchParams] = useSearchParams();
|
||||||
const [checkTokenInvalid, { data: isTokenValid, isLoading: checkingToken }] =
|
const [checkTokenInvalid, { data: isTokenValid, isLoading: checkingToken }] =
|
||||||
useCheckMagicTokenValidMutation();
|
useCheckMagicTokenValidMutation();
|
||||||
const [
|
const [
|
||||||
@@ -27,9 +28,8 @@ const RegWithUsername: FC = () => {
|
|||||||
const { from = "reg" } = useParams();
|
const { from = "reg" } = useParams();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const query = new URLSearchParams(location.search);
|
|
||||||
// todo: check if query param exists
|
// todo: check if query param exists
|
||||||
const token = query.get("magic_token") as string;
|
const token = searchParams.get("magic_token") as string;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (token) {
|
if (token) {
|
||||||
checkTokenInvalid(token);
|
checkTokenInvalid(token);
|
||||||
@@ -92,8 +92,8 @@ const RegWithUsername: FC = () => {
|
|||||||
setUsername(evt.target.value);
|
setUsername(evt.target.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!token) return <>"No Token"</>;
|
if (!token) return <span className="dark:text-white">No Token</span>;
|
||||||
if (checkingToken) return <div className="dark:text-gray-100">"Checking Magic Link..."</div>;
|
if (checkingToken) return <div className="dark:text-gray-100">Checking Magic Link...</div>;
|
||||||
if (!isTokenValid) return <ExpiredTip />;
|
if (!isTokenValid) return <ExpiredTip />;
|
||||||
const isLoading = loginLoading || regLoading;
|
const isLoading = loginLoading || regLoading;
|
||||||
const isSuccess = loginSuccess || regSuccess;
|
const isSuccess = loginSuccess || regSuccess;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { useState, useEffect, ChangeEvent, FormEvent } from "react";
|
import { useState, useEffect, ChangeEvent, FormEvent } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
import BASE_URL, { KEY_LOCAL_MAGIC_TOKEN } from "../../app/config";
|
import BASE_URL, { KEY_LOCAL_MAGIC_TOKEN } from "../../app/config";
|
||||||
import Input from "../../common/component/styled/Input";
|
import Input from "../../common/component/styled/Input";
|
||||||
import Button from "../../common/component/styled/Button";
|
import Button from "../../common/component/styled/Button";
|
||||||
@@ -26,6 +27,7 @@ export default function Register() {
|
|||||||
const serverName = useAppSelector(store => store.server.name);
|
const serverName = useAppSelector(store => store.server.name);
|
||||||
const { t } = useTranslation("auth");
|
const { t } = useTranslation("auth");
|
||||||
const { t: ct } = useTranslation();
|
const { t: ct } = useTranslation();
|
||||||
|
let [searchParams] = useSearchParams();
|
||||||
const [sendRegMagicLink, { isLoading: signingUp, data, isSuccess }] =
|
const [sendRegMagicLink, { isLoading: signingUp, data, isSuccess }] =
|
||||||
useSendRegMagicLinkMutation();
|
useSendRegMagicLinkMutation();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@@ -40,8 +42,7 @@ export default function Register() {
|
|||||||
password: "",
|
password: "",
|
||||||
confirmPassword: ""
|
confirmPassword: ""
|
||||||
});
|
});
|
||||||
const query = new URLSearchParams(location.search);
|
const magic_token = searchParams.get("magic_token") ?? undefined;
|
||||||
const magic_token = query.get("magic_token") ?? undefined;
|
|
||||||
if (magic_token) {
|
if (magic_token) {
|
||||||
//本地存一下 magic token 后续oauth流程用到
|
//本地存一下 magic token 后续oauth流程用到
|
||||||
localStorage.setItem(KEY_LOCAL_MAGIC_TOKEN, magic_token);
|
localStorage.setItem(KEY_LOCAL_MAGIC_TOKEN, magic_token);
|
||||||
@@ -118,7 +119,7 @@ export default function Register() {
|
|||||||
// magic token 没有并且没有开放注册
|
// magic token 没有并且没有开放注册
|
||||||
if (whoCanSignUp !== "EveryOne" && !magic_token)
|
if (whoCanSignUp !== "EveryOne" && !magic_token)
|
||||||
// todo: i18n
|
// todo: i18n
|
||||||
return <>Sign up method is updated to Invitation Link Only</>;
|
return <span className="dark:text-white">Sign up method is updated to Invitation Link Only</span>;
|
||||||
const { name, email, password, confirmPassword } = input;
|
const { name, email, password, confirmPassword } = input;
|
||||||
if (data?.mail_is_sent) return <EmailNextTip />;
|
if (data?.mail_is_sent) return <EmailNextTip />;
|
||||||
const isLoading = registering || signingUp || checkingEmail;
|
const isLoading = registering || signingUp || checkingEmail;
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
|
||||||
import { Outlet } from "react-router-dom";
|
import { Outlet } from "react-router-dom";
|
||||||
|
|
||||||
export default function RegContainer() {
|
export default function RegContainer() {
|
||||||
useEffect(() => {
|
|
||||||
// 重新组织url
|
|
||||||
location.href = `${location.origin}${location.hash}${location.search}`;
|
|
||||||
}, [location]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-center h-screen overflow-x-hidden overflow-y-auto dark:bg-gray-700">
|
<div className="flex-center h-screen overflow-x-hidden overflow-y-auto dark:bg-gray-700">
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ import { useGetLoginConfigQuery, useGetServerQuery } from '../app/services/serve
|
|||||||
import { useAppSelector } from '../app/store';
|
import { useAppSelector } from '../app/store';
|
||||||
import { getContrastColor } from '../common/utils';
|
import { getContrastColor } from '../common/utils';
|
||||||
|
|
||||||
const color = decodeURIComponent(new URLSearchParams(location.search).get("themeColor") || "#1fe1f9");
|
const query = new URLSearchParams(location.search);
|
||||||
const from = decodeURIComponent(new URLSearchParams(location.search).get("from") || "widget.link");
|
const color = decodeURIComponent(query.get("themeColor") || "#1fe1f9");
|
||||||
|
const from = decodeURIComponent(query.get("from") || "widget.link");
|
||||||
const fgColor = getContrastColor(color);
|
const fgColor = getContrastColor(color);
|
||||||
// 判断是否是iframe上下文
|
// 判断是否是iframe上下文
|
||||||
const embed = window.location !== window.parent.location;
|
const embed = window.location !== window.parent.location;
|
||||||
|
|||||||
Reference in New Issue
Block a user