refactor: add typescript support to project
This commit is contained in:
@@ -48,6 +48,13 @@ export const authApi = createApi({
|
||||
}
|
||||
}
|
||||
}),
|
||||
register: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `user/register`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
// 更新token
|
||||
renew: builder.mutation({
|
||||
query: ({ token, refreshToken }) => ({
|
||||
@@ -90,9 +97,9 @@ export const authApi = createApi({
|
||||
})
|
||||
}),
|
||||
|
||||
checkInviteTokenValid: builder.mutation({
|
||||
checkMagicTokenValid: builder.mutation({
|
||||
query: (token) => ({
|
||||
url: "user/check_invite_magic_token",
|
||||
url: "user/check_magic_token",
|
||||
method: "POST",
|
||||
body: { magic_token: token }
|
||||
})
|
||||
@@ -104,11 +111,23 @@ export const authApi = createApi({
|
||||
body: { old_password, new_password }
|
||||
})
|
||||
}),
|
||||
sendMagicLink: builder.mutation({
|
||||
sendLoginMagicLink: builder.mutation({
|
||||
query: (email) => ({
|
||||
url: "token/send_magic_link",
|
||||
headers: {
|
||||
// "content-type": "text/plain",
|
||||
accept: "text/plain"
|
||||
},
|
||||
url: `user/send_login_magic_link?email=${encodeURIComponent(email)}`,
|
||||
method: "POST",
|
||||
body: { email }
|
||||
responseHandler: (response) => response.text()
|
||||
// body: { email }
|
||||
})
|
||||
}),
|
||||
sendRegMagicLink: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `user/send_reg_magic_link`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getMetamaskNonce: builder.query({
|
||||
@@ -146,7 +165,8 @@ export const authApi = createApi({
|
||||
|
||||
export const {
|
||||
useGetInitializedQuery,
|
||||
useSendMagicLinkMutation,
|
||||
useSendLoginMagicLinkMutation,
|
||||
useSendRegMagicLinkMutation,
|
||||
useGetCredentialsQuery,
|
||||
useUpdateDeviceTokenMutation,
|
||||
useGetOpenidMutation,
|
||||
@@ -154,6 +174,7 @@ export const {
|
||||
useLazyGetMetamaskNonceQuery,
|
||||
useLoginMutation,
|
||||
useLazyLogoutQuery,
|
||||
useCheckInviteTokenValidMutation,
|
||||
useUpdatePasswordMutation
|
||||
useCheckMagicTokenValidMutation,
|
||||
useUpdatePasswordMutation,
|
||||
useRegisterMutation
|
||||
} = authApi;
|
||||
|
||||
@@ -7,8 +7,9 @@ import BASE_URL, { tokenHeader } from "../config";
|
||||
const whiteList = [
|
||||
"login",
|
||||
"register",
|
||||
"sendMagicLink",
|
||||
"checkInviteTokenValid",
|
||||
"sendLoginMagicLink",
|
||||
"sendRegMagicLink",
|
||||
"checkMagicTokenValid",
|
||||
"getGoogleAuthConfig",
|
||||
"getGithubAuthConfig",
|
||||
"getSMTPStatus",
|
||||
|
||||
@@ -72,12 +72,14 @@ export const channelApi = createApi({
|
||||
}
|
||||
}),
|
||||
createInviteLink: builder.query({
|
||||
query: (gid) => ({
|
||||
query: (gid = "") => ({
|
||||
headers: {
|
||||
"content-type": "text/plain",
|
||||
accept: "text/plain"
|
||||
},
|
||||
url: `/group/${gid}/create_invite_link`,
|
||||
url: gid
|
||||
? `/group/create_reg_magic_link?expired_in=3600&max_times=1&gid=${gid}`
|
||||
: `/group/create_reg_magic_link?expired_in=3600&max_times=1`,
|
||||
responseHandler: (response) => response.text()
|
||||
}),
|
||||
transformResponse: (link) => {
|
||||
|
||||
@@ -89,13 +89,7 @@ export const contactApi = createApi({
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
register: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `user/register`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
|
||||
sendMsg: builder.mutation({
|
||||
query: ({ id, content, type = "text", properties = "" }) => ({
|
||||
headers: {
|
||||
@@ -139,6 +133,5 @@ export const {
|
||||
useUpdateAvatarMutation,
|
||||
useGetContactsQuery,
|
||||
useLazyGetContactsQuery,
|
||||
useSendMsgMutation,
|
||||
useRegisterMutation
|
||||
useSendMsgMutation
|
||||
} = contactApi;
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
// import { useState, useEffect } from "react";
|
||||
// import { useGoogleLogin } from "react-google-login";
|
||||
import IconGithub from "../../assets/icons/github.svg";
|
||||
import { StyledSocialButton } from "./styled";
|
||||
import styled from "styled-components";
|
||||
import Button from "./styled/Button";
|
||||
const StyledSocialButton = styled(Button)`
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
color: #344054;
|
||||
border: 1px solid #d0d5dd;
|
||||
background: none !important;
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
`;
|
||||
export default function GithubLoginButton({ config = {} }) {
|
||||
const { client_id } = config;
|
||||
const handleGithubLogin = () => {
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useEffect } from "react";
|
||||
import { useGoogleLogin } from "react-google-login";
|
||||
|
||||
import googleSvg from "../../assets/icons/google.svg?url";
|
||||
import styled from "styled-components";
|
||||
import Button from "./styled/Button";
|
||||
import { useLoginMutation } from "../../app/services/auth";
|
||||
import toast from "react-hot-toast";
|
||||
const StyledSocialButton = styled(Button)`
|
||||
width: 100%;
|
||||
margin-bottom: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
color: #344054;
|
||||
border: 1px solid #d0d5dd;
|
||||
background: none !important;
|
||||
.icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
`;
|
||||
export default function GoogleLoginButton({ clientId }) {
|
||||
const [login, { isSuccess, isLoading }] = useLoginMutation();
|
||||
const { signIn, loaded } = useGoogleLogin({
|
||||
onScriptLoadFailure: (wtf) => {
|
||||
console.error("google login script load failure", wtf);
|
||||
},
|
||||
clientId,
|
||||
onSuccess: ({ tokenId, ...rest }) => {
|
||||
console.info("google oauth success", tokenId, rest);
|
||||
login({
|
||||
id_token: tokenId,
|
||||
type: "google"
|
||||
});
|
||||
},
|
||||
onFailure: (wtf) => {
|
||||
console.error("google login failure", wtf);
|
||||
}
|
||||
});
|
||||
useEffect(() => {
|
||||
if (isSuccess) {
|
||||
toast.success("Login Successfully");
|
||||
// navigateTo("/");
|
||||
}
|
||||
}, [isSuccess]);
|
||||
const handleGoogleLogin = () => {
|
||||
signIn();
|
||||
};
|
||||
// console.log("google login ", loaded);
|
||||
return (
|
||||
<StyledSocialButton disabled={!loaded || isLoading} onClick={handleGoogleLogin}>
|
||||
<img className="icon" src={googleSvg} alt="google icon" />
|
||||
{loaded ? `Sign in with Google` : `Initailizing`}
|
||||
</StyledSocialButton>
|
||||
);
|
||||
}
|
||||
@@ -1,44 +1,36 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import useCopy from "./useCopy";
|
||||
import {
|
||||
useLazyCreateInviteLinkQuery as useCreateServerInviteLinkQuery,
|
||||
useGetSMTPStatusQuery
|
||||
} from "../../app/services/server";
|
||||
import { useGetSMTPStatusQuery } from "../../app/services/server";
|
||||
import { useLazyCreateInviteLinkQuery as useCreateChannelInviteLinkQuery } from "../../app/services/channel";
|
||||
export default function useInviteLink(cid = null) {
|
||||
export default function useInviteLink(cid = "") {
|
||||
const [finalLink, setFinalLink] = useState("");
|
||||
const { data: SMTPEnabled, isSuccess: smtpStatusFetchSuccess } = useGetSMTPStatusQuery();
|
||||
const [generateChannelInviteLink, { data: channelInviteLink, isLoading: generatingChannelLink }] =
|
||||
useCreateChannelInviteLinkQuery();
|
||||
const [generateServerInviteLink, { data: serverInviteLink, isLoading: generatingServerLink }] =
|
||||
useCreateServerInviteLinkQuery();
|
||||
|
||||
const { copied, copy } = useCopy({ enableToast: false });
|
||||
const copyLink = () => {
|
||||
copy(finalLink);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (cid) {
|
||||
generateChannelInviteLink(cid);
|
||||
} else {
|
||||
generateServerInviteLink();
|
||||
}
|
||||
generateChannelInviteLink(cid);
|
||||
}, [cid]);
|
||||
|
||||
useEffect(() => {
|
||||
const _link = serverInviteLink || channelInviteLink;
|
||||
console.log("fetching", serverInviteLink, channelInviteLink);
|
||||
const _link = channelInviteLink;
|
||||
console.log("fetching", channelInviteLink);
|
||||
if (_link && smtpStatusFetchSuccess) {
|
||||
// const tmpURL = new URL(_link);
|
||||
// tmpURL.searchParams.set("code", SMTPEnabled);
|
||||
setFinalLink(_link);
|
||||
}
|
||||
}, [serverInviteLink, channelInviteLink, smtpStatusFetchSuccess]);
|
||||
}, [channelInviteLink, smtpStatusFetchSuccess]);
|
||||
const genServerLink = () => {
|
||||
generateServerInviteLink();
|
||||
generateChannelInviteLink();
|
||||
};
|
||||
return {
|
||||
enableSMTP: SMTPEnabled,
|
||||
generating: cid ? generatingChannelLink : generatingServerLink,
|
||||
generating: generatingChannelLink,
|
||||
generateNewLink: cid ? generateChannelInviteLink.bind(null, cid) : genServerLink,
|
||||
link: finalLink,
|
||||
linkCopied: copied,
|
||||
|
||||
@@ -64,7 +64,7 @@ const PageRoutes = () => {
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/reg"
|
||||
path="/register"
|
||||
element={
|
||||
<RequireNoAuth>
|
||||
<RegBasePage />
|
||||
@@ -72,9 +72,9 @@ const PageRoutes = () => {
|
||||
}
|
||||
>
|
||||
<Route index element={<RegPage />} />
|
||||
<Route path="magiclink">
|
||||
<Route path="set_name">
|
||||
<Route index element={<RegWithUsernamePage />} />
|
||||
<Route path=":token" element={<RegWithUsernamePage />} />
|
||||
<Route path=":from" element={<RegWithUsernamePage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route
|
||||
|
||||
+16
-20
@@ -1,36 +1,33 @@
|
||||
import { useState, useEffect, ChangeEvent, FormEvent } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import StyledWrapper from "./styled";
|
||||
import { Navigate } from "react-router-dom";
|
||||
import toast from "react-hot-toast";
|
||||
import StyledWrapper from "./styled";
|
||||
import BASE_URL from "../../app/config";
|
||||
import { useRegisterMutation } from "../../app/services/contact";
|
||||
import { useCheckInviteTokenValidMutation } from "../../app/services/auth";
|
||||
import { useAppSelector } from "../../app/store";
|
||||
import { useRegisterMutation } from "../../app/services/auth";
|
||||
import { useCheckMagicTokenValidMutation } from "../../app/services/auth";
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
export default function InvitePage() {
|
||||
const { token: loginToken } = useAppSelector((store) => store.authData);
|
||||
const { token: loginToken } = useSelector((store) => store.authData);
|
||||
const [secondPwd, setSecondPwd] = useState("");
|
||||
const [samePwd, setSamePwd] = useState(true);
|
||||
const [token, setToken] = useState<string | null>("");
|
||||
const [token, setToken] = useState("");
|
||||
const [valid, setValid] = useState(false);
|
||||
// const [sp] = useSearchParams();
|
||||
// const navigateTo = useNavigate();
|
||||
const [register, { data, isLoading, isSuccess, isError, error }] = useRegisterMutation();
|
||||
const [checkToken, { data: isValid, isLoading: checkLoading, isSuccess: checkSuccess }] =
|
||||
useCheckInviteTokenValidMutation();
|
||||
|
||||
useCheckMagicTokenValidMutation();
|
||||
useEffect(() => {
|
||||
// console.log(search);
|
||||
const query = new URLSearchParams(location.search);
|
||||
setToken(query.get("token"));
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (token) {
|
||||
checkToken(token);
|
||||
}
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
if (checkSuccess) {
|
||||
console.log({ isValid });
|
||||
@@ -40,9 +37,13 @@ export default function InvitePage() {
|
||||
}
|
||||
}, [checkSuccess, isValid]);
|
||||
|
||||
const [input, setInput] = useState({ name: "", email: "", password: "" });
|
||||
const [input, setInput] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
password: ""
|
||||
});
|
||||
|
||||
const handleReg = (evt: FormEvent<HTMLFormElement>) => {
|
||||
const handleReg = (evt) => {
|
||||
evt.preventDefault();
|
||||
if (!samePwd) {
|
||||
toast.error("two passwords not same");
|
||||
@@ -55,8 +56,7 @@ export default function InvitePage() {
|
||||
gender: 1
|
||||
});
|
||||
};
|
||||
|
||||
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
const handleInput = (evt) => {
|
||||
const { type } = evt.target.dataset;
|
||||
const { value } = evt.target;
|
||||
console.log(type, value);
|
||||
@@ -65,18 +65,15 @@ export default function InvitePage() {
|
||||
return { ...prev };
|
||||
});
|
||||
};
|
||||
|
||||
const handleSecondPwdInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
const handleSecondPwdInput = (evt) => {
|
||||
const { value } = evt.target;
|
||||
setSecondPwd(value);
|
||||
};
|
||||
|
||||
const handlePwdCheck = () => {
|
||||
if (secondPwd) {
|
||||
setSamePwd(secondPwd == input.password);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!samePwd) {
|
||||
toast.error("two passwords not same");
|
||||
@@ -120,7 +117,6 @@ export default function InvitePage() {
|
||||
if (!token) return "token not found";
|
||||
if (checkLoading) return "checking token valid";
|
||||
if (!valid) return "invite token expires or invalid";
|
||||
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="form animate__animated animate__fadeInDown animate__faster">
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// import { useState, useEffect } from "react";
|
||||
import { useGoogleLogin } from "react-google-login";
|
||||
|
||||
import googleSvg from "../../assets/icons/google.svg?url";
|
||||
import { StyledSocialButton } from "./styled";
|
||||
export default function GoogleLoginButton({ login, clientId }) {
|
||||
const { signIn, loaded } = useGoogleLogin({
|
||||
onScriptLoadFailure: (wtf) => {
|
||||
console.error("google login script load failure", wtf);
|
||||
},
|
||||
clientId,
|
||||
onSuccess: ({ tokenId, ...rest }) => {
|
||||
console.info("google oauth success", tokenId, rest);
|
||||
login({
|
||||
id_token: tokenId,
|
||||
type: "google"
|
||||
});
|
||||
},
|
||||
onFailure: (wtf) => {
|
||||
console.error("google login failure", wtf);
|
||||
}
|
||||
});
|
||||
const handleGoogleLogin = () => {
|
||||
signIn();
|
||||
};
|
||||
// console.log("google login ", loaded);
|
||||
return (
|
||||
<StyledSocialButton disabled={!loaded} onClick={handleGoogleLogin}>
|
||||
<img className="icon" src={googleSvg} alt="google icon" />
|
||||
{loaded ? `Sign in with Google` : `Initailizing`}
|
||||
</StyledSocialButton>
|
||||
);
|
||||
}
|
||||
@@ -24,7 +24,7 @@ const StyledSignUpLink = styled.p`
|
||||
export default function MagicLinkLogin() {
|
||||
const navigate = useNavigate();
|
||||
const handleSignUp = () => {
|
||||
navigate("/");
|
||||
navigate("/register");
|
||||
};
|
||||
return (
|
||||
<StyledSignUpLink>
|
||||
|
||||
@@ -8,14 +8,14 @@ import MetamaskLoginButton from "./MetamaskLoginButton";
|
||||
import OidcLoginButton from "./OidcLoginButton";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import GoogleLoginButton from "./GoogleLoginButton";
|
||||
import MagicLinkLogin from "./MagicLinkLogin";
|
||||
import SignUpLink from "./SignUpLink";
|
||||
import { useLoginMutation } from "../../app/services/auth";
|
||||
import { useGetLoginConfigQuery, useGetSMTPStatusQuery } from "../../app/services/server";
|
||||
import useGoogleAuthConfig from "../../common/hook/useGoogleAuthConfig";
|
||||
import GithubLoginButton from "./GithubLoginButton";
|
||||
import useGithubAuthConfig from "../../common/hook/useGithubAuthConfig";
|
||||
import GoogleLoginButton from "../../common/component/GoogleLoginButton";
|
||||
import GithubLoginButton from "../../common/component/GithubLoginButton";
|
||||
export default function LoginPage() {
|
||||
const { data: enableSMTP } = useGetSMTPStatusQuery();
|
||||
const [login, { isSuccess, isLoading, error }] = useLoginMutation();
|
||||
@@ -32,7 +32,7 @@ export default function LoginPage() {
|
||||
const oauth = query.get("oauth");
|
||||
const code = query.get("code");
|
||||
const state = query.get("state");
|
||||
const token = query.get("token");
|
||||
const magic_token = query.get("magic_token");
|
||||
const exists = query.get("exists");
|
||||
if (oauth) {
|
||||
switch (oauth) {
|
||||
@@ -58,18 +58,18 @@ export default function LoginPage() {
|
||||
}
|
||||
}
|
||||
// magic link
|
||||
if (token && typeof exists !== "undefined") {
|
||||
console.log("tokken", token, exists);
|
||||
if (magic_token && typeof exists !== "undefined") {
|
||||
// console.log("tokken", token, exists);
|
||||
const isLogin = exists == "true";
|
||||
if (isLogin) {
|
||||
// login
|
||||
login({
|
||||
token,
|
||||
magic_token,
|
||||
type: "magiclink"
|
||||
});
|
||||
} else {
|
||||
// reg
|
||||
location.href = `/#/reg/magiclink/${token}`;
|
||||
// reg with magic link and set name only
|
||||
location.href = `?magic_token=${magic_token}#/register/set_name/login`;
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
@@ -167,7 +167,7 @@ export default function LoginPage() {
|
||||
</form>
|
||||
{hasDivider && <hr className="or" />}
|
||||
{enableMagicLink && <MagicLinkLogin />}
|
||||
{googleLogin && <GoogleLoginButton login={login} clientId={clientId} />}
|
||||
{googleLogin && <GoogleLoginButton clientId={clientId} />}
|
||||
{enableGithubLogin && <GithubLoginButton config={githubAuthConfig} />}
|
||||
{enableMetamaskLogin && <MetamaskLoginButton login={login} />}
|
||||
{oidc.length > 0 && <OidcLoginButton issuers={oidc} />}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// import React from "react";
|
||||
import styled from "styled-components";
|
||||
const Styled = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.title {
|
||||
font-weight: 600;
|
||||
font-size: 30px;
|
||||
line-height: 38px;
|
||||
color: #101828;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.desc {
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
line-height: 24px;
|
||||
color: #667085;
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
export default function EmailNextTip() {
|
||||
return (
|
||||
<Styled>
|
||||
<div className="title">Magic link Sent</div>
|
||||
<p className="desc">Login to your email client, and continue next step</p>
|
||||
<p className="desc">You can close this window now.</p>
|
||||
</Styled>
|
||||
);
|
||||
}
|
||||
@@ -1,25 +1,30 @@
|
||||
/* eslint-disable no-undef */
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
// import toast from "react-hot-toast";
|
||||
import { useState, useEffect, ChangeEvent, FormEvent } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { useParams } from "react-router-dom";
|
||||
import toast from "react-hot-toast";
|
||||
import { setAuthData } from "../../app/slices/auth.data";
|
||||
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import { useLoginMutation, useCheckInviteTokenValidMutation } from "../../app/services/auth";
|
||||
import { useLoginMutation, useCheckMagicTokenValidMutation } from "../../app/services/auth";
|
||||
import toast from "react-hot-toast";
|
||||
import ExpiredTip from "./ExpiredTip";
|
||||
import { useRegisterMutation } from "../../app/services/auth";
|
||||
|
||||
export default function RegWithUsername() {
|
||||
const { token } = useParams();
|
||||
const [checkTokenInvalid, { data: isTokenValid, isLoading: checkingToken }] =
|
||||
useCheckInviteTokenValidMutation();
|
||||
const [login, { isLoading, error, isSuccess, data }] = useLoginMutation();
|
||||
useCheckMagicTokenValidMutation();
|
||||
const [login, { isLoading: loginLoading, error, isSuccess: loginSuccess, data: loginData }] =
|
||||
useLoginMutation();
|
||||
const [register, { isLoading: regLoading, isSuccess: regSuccess, data: regData }] =
|
||||
useRegisterMutation();
|
||||
// const navigateTo = useNavigate();
|
||||
const { from = "reg" } = useParams();
|
||||
const dispatch = useDispatch();
|
||||
const [username, setUsername] = useState("");
|
||||
|
||||
const query = new URLSearchParams(location.search);
|
||||
// const githubCode = query.get("gcode");
|
||||
const token = query.get("magic_token");
|
||||
useEffect(() => {
|
||||
if (token) {
|
||||
checkTokenInvalid(token);
|
||||
@@ -27,45 +32,53 @@ export default function RegWithUsername() {
|
||||
}, [token]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("error", error);
|
||||
console.log("errr", error);
|
||||
switch (error?.status) {
|
||||
case 401:
|
||||
toast.error("Invalided Token");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
useEffect(() => {
|
||||
const isSuccess = loginSuccess || regSuccess;
|
||||
const data = loginData || regData;
|
||||
if (isSuccess && data) {
|
||||
// 更新本地认证信息
|
||||
console.log("login data", data);
|
||||
toast.success("Login Successfully");
|
||||
dispatch(setAuthData(data));
|
||||
// tricky
|
||||
location.href = `/#/`;
|
||||
}
|
||||
}, [isSuccess, data]);
|
||||
}, [loginSuccess, regSuccess, loginData, regData]);
|
||||
|
||||
const handleLogin = (evt: FormEvent<HTMLFormElement>) => {
|
||||
const handleAuth = (evt) => {
|
||||
evt.preventDefault();
|
||||
login({
|
||||
token,
|
||||
username,
|
||||
type: "magiclink"
|
||||
});
|
||||
// sendMagicLink(email);
|
||||
if (from == "reg") {
|
||||
register({
|
||||
magic_token: token,
|
||||
name: username
|
||||
});
|
||||
} else {
|
||||
login({
|
||||
magic_token: token,
|
||||
extra_name: username,
|
||||
type: "magiclink"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleInput = (evt: ChangeEvent<HTMLInputElement>) => {
|
||||
const handleInput = (evt) => {
|
||||
const { value } = evt.target;
|
||||
setUsername(value);
|
||||
};
|
||||
|
||||
if (!token) return "no token";
|
||||
if (checkingToken) return "checking Magic Link...";
|
||||
if (!token) return "No Token";
|
||||
if (checkingToken) return "Checking Magic Link...";
|
||||
if (!isTokenValid) return <ExpiredTip />;
|
||||
|
||||
const isLoading = loginLoading || regLoading;
|
||||
const isSuccess = loginSuccess || regSuccess;
|
||||
return (
|
||||
<>
|
||||
<div className="tips">
|
||||
@@ -75,7 +88,7 @@ export default function RegWithUsername() {
|
||||
visible to others in spaces you joined.
|
||||
</span>
|
||||
</div>
|
||||
<form onSubmit={handleLogin}>
|
||||
<form onSubmit={handleAuth}>
|
||||
<Input
|
||||
className="large"
|
||||
name="username"
|
||||
|
||||
+63
-19
@@ -1,42 +1,86 @@
|
||||
/* eslint-disable no-undef */
|
||||
import { useState, useEffect } from "react";
|
||||
// import { useDispatch } from "react-redux";
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
import toast from "react-hot-toast";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
// import toast from "react-hot-toast";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
// import { useSendMagicLinkMutation } from "../../app/services/auth";
|
||||
import { useSendRegMagicLinkMutation } from "../../app/services/auth";
|
||||
import EmailNextTip from "./EmailNextStepTip";
|
||||
// import { useSendLoginMagicLinkMutation } from "../../app/services/auth";
|
||||
|
||||
export default function Reg() {
|
||||
// const [
|
||||
// sendMagicLink,
|
||||
// { data, isSuccess, isLoading, error },
|
||||
// ] = useSendMagicLinkMutation();
|
||||
// const navigateTo = useNavigate();
|
||||
// const dispatch = useDispatch();
|
||||
const [username, setUsername] = useState("");
|
||||
const [sendRegMagicLink, { isLoading, data, isSuccess }] = useSendRegMagicLinkMutation();
|
||||
const navigateTo = useNavigate();
|
||||
const [magicToken, setMagicToken] = useState("");
|
||||
const [input, setInput] = useState({
|
||||
email: "",
|
||||
password: "",
|
||||
confirmPassword: ""
|
||||
});
|
||||
useEffect(() => {
|
||||
const query = new URLSearchParams(location.search);
|
||||
// const githubCode = query.get("gcode");
|
||||
const token = query.get("magic_token");
|
||||
if (token) {
|
||||
setMagicToken(token);
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (isSuccess && data) {
|
||||
const { new_magic_token, mail_is_sent } = data;
|
||||
if (!mail_is_sent && new_magic_token) {
|
||||
// 直接进入set_name流程
|
||||
navigateTo(`?magic_token=${new_magic_token}#/register/set_name`);
|
||||
}
|
||||
}
|
||||
}, [isSuccess, data]);
|
||||
|
||||
const handleLogin = (evt) => {
|
||||
const handleReg = (evt) => {
|
||||
evt.preventDefault();
|
||||
const { email, password } = input;
|
||||
sendRegMagicLink({
|
||||
magic_token: magicToken,
|
||||
email,
|
||||
password
|
||||
});
|
||||
// sendMagicLink(email);
|
||||
};
|
||||
|
||||
const handleInput = (evt) => {
|
||||
const { type } = evt.target.dataset;
|
||||
const { value } = evt.target;
|
||||
console.log(value);
|
||||
setUsername(value);
|
||||
// console.log(type, value);
|
||||
setInput((prev) => {
|
||||
prev[type] = value;
|
||||
return { ...prev };
|
||||
});
|
||||
};
|
||||
const { email, password } = input;
|
||||
if (data?.mail_is_sent) return <EmailNextTip />;
|
||||
return (
|
||||
<form onSubmit={handleLogin}>
|
||||
<form onSubmit={handleReg}>
|
||||
<Input
|
||||
className="large"
|
||||
name="username"
|
||||
value={username}
|
||||
name="email"
|
||||
value={email}
|
||||
required
|
||||
placeholder="Enter your Name22"
|
||||
placeholder="Enter your email"
|
||||
data-type="email"
|
||||
onChange={handleInput}
|
||||
/>
|
||||
<Button type="submit">{isLoading ? "Sending" : `Register`}</Button>
|
||||
<Input
|
||||
className="large"
|
||||
type="password"
|
||||
value={password}
|
||||
name="password"
|
||||
required
|
||||
data-type="password"
|
||||
onChange={handleInput}
|
||||
placeholder="Enter your password"
|
||||
/>
|
||||
<Button type="submit" disabled={isLoading}>
|
||||
{isLoading ? "Signing Up" : `Sign Up`}
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import styled from "styled-components";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const StyledSignInLink = styled.p`
|
||||
text-align: center;
|
||||
margin: 24px 0 8px;
|
||||
> span {
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #667085;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
> a {
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #22d3ee;
|
||||
cursor: pointer;
|
||||
}
|
||||
`;
|
||||
export default function SignInLink() {
|
||||
const navigate = useNavigate();
|
||||
const handleSignIn = () => {
|
||||
navigate("/login");
|
||||
};
|
||||
return (
|
||||
<StyledSignInLink>
|
||||
<span>Have an account?</span>
|
||||
<a onClick={handleSignIn}>Sign In</a>
|
||||
</StyledSignInLink>
|
||||
);
|
||||
}
|
||||
+38
-1
@@ -1,12 +1,49 @@
|
||||
/* eslint-disable no-undef */
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { useMatch } from "react-router-dom";
|
||||
import BASE_URL from "../../app/config";
|
||||
import SignInLink from "./SignInLink";
|
||||
import { useGetLoginConfigQuery } from "../../app/services/server";
|
||||
import useGithubAuthConfig from "../../common/hook/useGithubAuthConfig";
|
||||
import useGoogleAuthConfig from "../../common/hook/useGoogleAuthConfig";
|
||||
import GoogleLoginButton from "../../common/component/GoogleLoginButton";
|
||||
import GithubLoginButton from "../../common/component/GithubLoginButton";
|
||||
import StyledWrapper from "./styled";
|
||||
|
||||
export default function Reg() {
|
||||
const isRegHome = useMatch(`/register`);
|
||||
const { clientId } = useGoogleAuthConfig();
|
||||
const { config: githubAuthConfig } = useGithubAuthConfig();
|
||||
const { data: loginConfig, isSuccess: loginConfigSuccess } = useGetLoginConfigQuery();
|
||||
if (!loginConfigSuccess) return null;
|
||||
const {
|
||||
github: enableGithubLogin,
|
||||
google: enableGoogleLogin,
|
||||
who_can_sign_up: whoCanSignUp
|
||||
} = loginConfig;
|
||||
const googleLogin = enableGoogleLogin && clientId;
|
||||
// 没有开放注册
|
||||
if (whoCanSignUp !== "EveryOne") return `Open Register is Closed!`;
|
||||
return (
|
||||
<StyledWrapper>
|
||||
<div className="form">
|
||||
{isRegHome && (
|
||||
<>
|
||||
<div className="tips">
|
||||
<img src={`${BASE_URL}/resource/organization/logo`} alt="logo" className="logo" />
|
||||
<h2 className="title">Sign Up to Rustchat</h2>
|
||||
<span className="desc">Please enter your details.</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<Outlet />
|
||||
{isRegHome && (
|
||||
<>
|
||||
<hr className="or" />
|
||||
{googleLogin && <GoogleLoginButton clientId={clientId} />}
|
||||
{enableGithubLogin && <GithubLoginButton config={githubAuthConfig} />}
|
||||
<SignInLink />
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
||||
@@ -45,6 +45,25 @@ const StyledWrapper = styled.div`
|
||||
width: 360px;
|
||||
}
|
||||
}
|
||||
.or {
|
||||
border: none;
|
||||
position: relative;
|
||||
height: 1px;
|
||||
background-color: #e4e7ec;
|
||||
margin: 26px 0;
|
||||
&:after {
|
||||
padding: 4px;
|
||||
background-color: #fff;
|
||||
content: "OR";
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate3d(-50%, -50%, 0);
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #667085;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default StyledWrapper;
|
||||
|
||||
@@ -7,12 +7,12 @@ import BASE_URL from "../../app/config";
|
||||
import StyledWrapper from "./styled";
|
||||
import Input from "../../common/component/styled/Input";
|
||||
import Button from "../../common/component/styled/Button";
|
||||
import { useSendMagicLinkMutation } from "../../app/services/auth";
|
||||
import { useSendLoginMagicLinkMutation } from "../../app/services/auth";
|
||||
import SentTip from "./SentTip";
|
||||
|
||||
export default function SendMagicLinkPage() {
|
||||
const [sent, setSent] = useState(false);
|
||||
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendMagicLinkMutation();
|
||||
const [sendMagicLink, { isSuccess, isLoading, error }] = useSendLoginMagicLinkMutation();
|
||||
|
||||
const navigateTo = useNavigate();
|
||||
// const dispatch = useDispatch();
|
||||
@@ -32,13 +32,13 @@ export default function SendMagicLinkPage() {
|
||||
toast.error(error.data);
|
||||
break;
|
||||
case 401:
|
||||
toast.error("username or password incorrect");
|
||||
toast.error("Username or Password Incorrect");
|
||||
break;
|
||||
case 404:
|
||||
toast.error("account not exsit");
|
||||
toast.error("Account not exsit");
|
||||
break;
|
||||
default:
|
||||
toast.error("something error");
|
||||
toast.error("Something Error");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user