feat: widget login with name and email

This commit is contained in:
Tristan Yang
2023-02-23 17:01:54 +08:00
parent f61748565f
commit a8773d3712
5 changed files with 66 additions and 9 deletions
+2 -1
View File
@@ -10,6 +10,7 @@ import {
RenewTokenDTO,
RenewTokenResponse
} from "../../types/auth";
import { UserRegDTO, UserRegResponse } from "../../types/user";
const getDeviceId = () => {
let d = localStorage.getItem(KEY_DEVICE_ID);
@@ -73,7 +74,7 @@ export const authApi = createApi({
}
}
}),
register: builder.mutation<any, any>({
register: builder.mutation<UserRegResponse, UserRegDTO>({
query: (data) => ({
url: `user/register`,
method: "POST",
+9
View File
@@ -1,3 +1,5 @@
import { AuthToken } from "./auth";
export type Gender = 0 | 1;
export interface AutoDeleteMsgDTO {
@@ -46,3 +48,10 @@ export interface UserDTO extends Partial<Pick<User, "name" | "gender" | "languag
export interface UserCreateDTO extends Pick<User, "name" | "gender" | "language" | "email" | "webhook_url" | "is_bot" | "is_admin"> {
password: string;
}
export interface UserRegDTO extends Pick<User, "name" | "gender" | "language" | "email">, Pick<UserDevice, "device" | "device_token"> {
password: string;
magic_token?: string
}
export interface UserRegResponse extends AuthToken {
user: User
}
+51 -5
View File
@@ -1,18 +1,56 @@
// import React from 'react'
import clsx from 'clsx';
import { FormEvent, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { useRegisterMutation } from '../../../app/services/auth';
import { useGetLoginConfigQuery } from '../../../app/services/server';
import { setAuthData } from '../../../app/slices/auth.data';
import Divider from '../../../common/component/Divider';
import GithubLoginButton from '../../../common/component/GithubLoginButton';
import GoogleLoginButton from '../../../common/component/GoogleLoginButton';
import StyledButton from '../../../common/component/styled/Button';
import Input from '../../../common/component/styled/Input';
import useGithubAuthConfig from '../../../common/hook/useGithubAuthConfig';
import useGoogleAuthConfig from '../../../common/hook/useGoogleAuthConfig';
import { useWidget } from '../../WidgetContext';
// type Props = {}
const Login = () => {
const dispatch = useDispatch();
const { color, fgColor, from } = useWidget();
const { clientId } = useGoogleAuthConfig();
const { config: githubAuthConfig } = useGithubAuthConfig();
const [register, { isLoading, isSuccess, data }] = useRegisterMutation();
const { data: loginConfig, isSuccess: loginConfigSuccess } = useGetLoginConfigQuery();
if (!loginConfigSuccess) return <span className="text-xs text-gray-500">checking...</span>;
const handleSubmit = (evt: FormEvent<HTMLFormElement>) => {
evt.preventDefault();
const form = evt.currentTarget;
// 检查格式
if (!form?.checkValidity()) {
form?.reportValidity();
return;
}
const data = new FormData(form);
const name = data.get("username") as string;
const email = data.get("email") as string;
console.log("name,email", name, email);
register({
name: `${name}-[${from}]`,
email,
password: email,
gender: 0,
device: "unknown"
});
// const content = new FormData(form).get("prompt") as string;
};
useEffect(() => {
if (isSuccess && data) {
dispatch(setAuthData(data));
}
}, [isSuccess, data]);
if (!loginConfigSuccess) return null;
const {
github: enableGithubLogin,
@@ -20,9 +58,17 @@ const Login = () => {
} = loginConfig;
const googleLogin = enableGoogleLogin && clientId;
return (
<div className="w-60 flex flex-col gap-2 mt-4">
{googleLogin && <GoogleLoginButton clientId={clientId} />}
{enableGithubLogin && <GithubLoginButton client_id={githubAuthConfig?.client_id} source="widget" />}
<div className="w-72 flex flex-col gap-2 mt-4 animate-[fadeInUp_.5s_.8s_ease-in-out_both]">
<div className="bg-white dark:bg-gray-700 border dark:border-gray-500 rounded-lg">
<form className="px-4 py-3 flex flex-col gap-2" onSubmit={handleSubmit}>
<Input required placeholder="Name" name='username' />
<Input required placeholder="Email" type="email" name='email' />
<StyledButton disabled={isLoading} type="submit" className={clsx("small", `bg-[${color}] text-[${fgColor}]`)}>Start Chat</StyledButton>
<Divider content='OR' />
{googleLogin && <GoogleLoginButton clientId={clientId} />}
{enableGithubLogin && <GithubLoginButton client_id={githubAuthConfig?.client_id} source="widget" />}
</form>
</div>
</div>
);
};
+3 -2
View File
@@ -2,15 +2,16 @@ import { createContext, useContext, ReactNode } from 'react';
import { getContrastColor } from '../common/utils';
const color = decodeURIComponent(new URLSearchParams(location.search).get("themeColor") || "#1fe1f9");
const from = decodeURIComponent(new URLSearchParams(location.search).get("from") || "widget");
const fgColor = getContrastColor(color);
// 判断是否是iframe上下文
const embed = window.location !== window.parent.location;
const WidgetContext = createContext({ color, fgColor, embed });
const WidgetContext = createContext({ color, fgColor, embed, from });
function WidgetProvider({ children }: { children: ReactNode }) {
return <WidgetContext.Provider value={{ color, fgColor, embed }} >{children}</WidgetContext.Provider>;
return <WidgetContext.Provider value={{ color, fgColor, embed, from }} >{children}</WidgetContext.Provider>;
}
function useWidget() {