auth kinda works now
This commit is contained in:
@ -1,18 +1,27 @@
|
||||
import React from "react";
|
||||
import { ConfigProvider } from "antd";
|
||||
import React, { createContext } from "react";
|
||||
import { ConfigProvider, message } from "antd";
|
||||
import "./App.css";
|
||||
import HeaderComponent from "./components/HeaderComponent";
|
||||
import { theme } from "./config/style";
|
||||
import { Provider } from "react-redux";
|
||||
import { store } from "./config/store";
|
||||
import { MessageInstance } from "antd/es/message/interface";
|
||||
|
||||
export const MessageContext = createContext({} as MessageInstance);
|
||||
|
||||
const App = () => {
|
||||
const [messageApi, contextHolder] = message.useMessage({
|
||||
duration: 2,
|
||||
});
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<ConfigProvider theme={theme}>
|
||||
<div className="content">
|
||||
<HeaderComponent />
|
||||
</div>
|
||||
<MessageContext.Provider value={messageApi}>
|
||||
<div className="content">
|
||||
{contextHolder}
|
||||
<HeaderComponent />
|
||||
</div>
|
||||
</MessageContext.Provider>
|
||||
</ConfigProvider>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { Form, Input, Menu, MenuProps, Modal } from "antd";
|
||||
import { Form, Input, Menu, MenuProps, Modal, Spin } from "antd";
|
||||
import "./styles.css";
|
||||
import { KeyOutlined, UserAddOutlined } from "@ant-design/icons";
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { useLoginMutation, useRegisterMutation } from "../slice/AuthApi";
|
||||
import { MessageContext } from "../App";
|
||||
|
||||
const AuthModal = (props: {
|
||||
open: boolean;
|
||||
@ -11,12 +13,20 @@ const AuthModal = (props: {
|
||||
const [registerForm] = Form.useForm();
|
||||
|
||||
const [current, setCurrent] = useState("login");
|
||||
const messageApi = useContext(MessageContext);
|
||||
|
||||
const submitLoginForm = (formData: {
|
||||
username: string;
|
||||
password: string;
|
||||
}) => {
|
||||
console.log(formData);
|
||||
const [loginUser, { isLoading: isLoggingIn }] = useLoginMutation();
|
||||
const [registerUser, { isLoading: isRegistering }] = useRegisterMutation();
|
||||
|
||||
const submitLoginForm = (data: { username: string; password: string }) => {
|
||||
const formData = new FormData();
|
||||
formData.append("username", data.username);
|
||||
formData.append("password", data.password);
|
||||
|
||||
loginUser(formData)
|
||||
.unwrap()
|
||||
.then(() => props.setOpen(false))
|
||||
.catch(() => messageApi.error("Login failed!"));
|
||||
};
|
||||
|
||||
const submitRegisterForm = (formData: {
|
||||
@ -26,6 +36,10 @@ const AuthModal = (props: {
|
||||
password2: string;
|
||||
}) => {
|
||||
console.log(formData);
|
||||
registerUser(formData)
|
||||
.unwrap()
|
||||
.then(() => props.setOpen(false))
|
||||
.catch(() => messageApi.error("Registration failed!"));
|
||||
};
|
||||
|
||||
const items: MenuProps["items"] = [
|
||||
@ -42,113 +56,118 @@ const AuthModal = (props: {
|
||||
];
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={props.open}
|
||||
onCancel={() => props.setOpen(false)}
|
||||
onOk={() => {
|
||||
current === "register" && registerForm.submit();
|
||||
current === "login" && loginForm.submit();
|
||||
}}
|
||||
okText={current === "login" ? "Log In" : "Register"}
|
||||
>
|
||||
<Menu
|
||||
onClick={(e) => setCurrent(e.key)}
|
||||
mode="horizontal"
|
||||
selectedKeys={[current]}
|
||||
items={items}
|
||||
/>
|
||||
<br />
|
||||
{current === "register" ? (
|
||||
<Form
|
||||
form={registerForm}
|
||||
onFinish={submitRegisterForm}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="Username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Username!",
|
||||
},
|
||||
]}
|
||||
<Spin spinning={isLoggingIn || isRegistering}>
|
||||
<Modal
|
||||
open={props.open}
|
||||
onCancel={() => props.setOpen(false)}
|
||||
onOk={() => {
|
||||
current === "register" && registerForm.submit();
|
||||
current === "login" && loginForm.submit();
|
||||
}}
|
||||
okText={current === "login" ? "Log In" : "Register"}
|
||||
confirmLoading={isLoggingIn}
|
||||
>
|
||||
<Menu
|
||||
onClick={(e) => setCurrent(e.key)}
|
||||
mode="horizontal"
|
||||
selectedKeys={[current]}
|
||||
items={items}
|
||||
/>
|
||||
<br />
|
||||
{current === "register" ? (
|
||||
<Form
|
||||
form={registerForm}
|
||||
onFinish={submitRegisterForm}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="name" label="Display name">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="Password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password2"
|
||||
label="Repeat password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please confirm your password!",
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
if (!value || getFieldValue("password") === value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error("The new password that you entered do not match!")
|
||||
);
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="Username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Username!",
|
||||
},
|
||||
}),
|
||||
]}
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item name="name" label="Display name">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="Password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password2"
|
||||
label="Repeat password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please confirm your password!",
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
if (!value || getFieldValue("password") === value) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error(
|
||||
"The new password that you entered do not match!"
|
||||
)
|
||||
);
|
||||
},
|
||||
}),
|
||||
]}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
) : (
|
||||
<Form
|
||||
form={loginForm}
|
||||
onFinish={submitLoginForm}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
) : (
|
||||
<Form
|
||||
form={loginForm}
|
||||
onFinish={submitLoginForm}
|
||||
layout="vertical"
|
||||
requiredMark={false}
|
||||
>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="Username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Username!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="Password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
)}
|
||||
</Modal>
|
||||
<Form.Item
|
||||
name="username"
|
||||
label="Username"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Username!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="password"
|
||||
label="Password"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "Please input your Password!",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input type="password" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
)}
|
||||
</Modal>
|
||||
</Spin>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,18 +1,37 @@
|
||||
import { configureStore } from '@reduxjs/toolkit'
|
||||
import { setupListeners } from '@reduxjs/toolkit/query'
|
||||
import { AuthApi } from '../slice/AuthApi'
|
||||
import { configureStore, createAction, createReducer } from "@reduxjs/toolkit";
|
||||
import { setupListeners } from "@reduxjs/toolkit/query";
|
||||
import { AuthApi } from "../slice/AuthApi";
|
||||
|
||||
export type authState = {
|
||||
token: string | null;
|
||||
};
|
||||
|
||||
const initialAuthState: authState = {
|
||||
token: null,
|
||||
};
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
// Add the generated reducer as a specific top-level slice
|
||||
[AuthApi.reducerPath]: AuthApi.reducer,
|
||||
auth: createReducer(initialAuthState, (builder) => {
|
||||
builder.addCase(createAction("auth/token"), (state, _) => {
|
||||
const token: string | null = localStorage.getItem("token");
|
||||
if (token) {
|
||||
state.token = token;
|
||||
}
|
||||
});
|
||||
}),
|
||||
},
|
||||
// Adding the api middleware enables caching, invalidation, polling,
|
||||
// and other useful features of `rtk-query`.
|
||||
middleware: (getDefaultMiddleware) =>
|
||||
getDefaultMiddleware().concat(AuthApi.middleware),
|
||||
})
|
||||
});
|
||||
|
||||
// optional, but required for refetchOnFocus/refetchOnReconnect behaviors
|
||||
// see `setupListeners` docs - takes an optional callback as the 2nd arg for customization
|
||||
setupListeners(store.dispatch)
|
||||
setupListeners(store.dispatch);
|
||||
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppDispatch = typeof store.dispatch;
|
||||
|
||||
@ -1,23 +1,26 @@
|
||||
export const theme = {
|
||||
components: {
|
||||
Modal: {
|
||||
contentBg: "#001529"
|
||||
},
|
||||
Form: {
|
||||
labelColor: "#77828c"
|
||||
},
|
||||
Input: {
|
||||
activeBg: "#001c36",
|
||||
},
|
||||
Button: {
|
||||
primaryColor: "#001529"
|
||||
}
|
||||
components: {
|
||||
Modal: {
|
||||
contentBg: "#001529",
|
||||
},
|
||||
token: {
|
||||
colorText: "#ffffff",
|
||||
colorBgContainer: "#001c36",
|
||||
colorIcon: "#77828c",
|
||||
colorPrimary: "#ffffff",
|
||||
colorPrimaryHover: "#001529",
|
||||
}
|
||||
};
|
||||
Form: {
|
||||
labelColor: "#77828c",
|
||||
},
|
||||
Input: {
|
||||
activeBg: "#001c36",
|
||||
},
|
||||
Button: {
|
||||
primaryColor: "#001529",
|
||||
},
|
||||
Message: {
|
||||
contentBg: "#001c36",
|
||||
},
|
||||
},
|
||||
token: {
|
||||
colorText: "#ffffff",
|
||||
colorBgContainer: "#001c36",
|
||||
colorIcon: "#77828c",
|
||||
colorPrimary: "#ffffff",
|
||||
colorPrimaryHover: "#001529",
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,14 +1,58 @@
|
||||
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
|
||||
import { baseUrl } from '../config/baseUrl'
|
||||
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||
import { baseUrl } from "../config/baseUrl";
|
||||
import { RootState } from "../config/store";
|
||||
|
||||
export interface User {
|
||||
username: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface UserResponse {
|
||||
user: User;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface RegisterRequest {
|
||||
username: string;
|
||||
name: string | undefined;
|
||||
password: string;
|
||||
password2: string;
|
||||
}
|
||||
|
||||
export const AuthApi = createApi({
|
||||
reducerPath: 'AuthApi',
|
||||
baseQuery: fetchBaseQuery({ baseUrl: `${baseUrl}auth/` }),
|
||||
reducerPath: "AuthApi",
|
||||
baseQuery: fetchBaseQuery({
|
||||
baseUrl: `${baseUrl}auth/`,
|
||||
prepareHeaders: (headers, { getState }) => {
|
||||
// By default, if we have a token in the store, let's use that for authenticated requests
|
||||
const token = (getState() as RootState).auth.token;
|
||||
if (token) {
|
||||
headers.set("authorization", `Bearer ${token}`);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
}),
|
||||
endpoints: (builder) => ({
|
||||
getUser: builder.query({
|
||||
query: () => 'me/',
|
||||
query: () => "me",
|
||||
}),
|
||||
login: builder.mutation({
|
||||
query: (data: FormData) => ({
|
||||
url: "token",
|
||||
method: "POST",
|
||||
body: data,
|
||||
formData: true,
|
||||
}),
|
||||
}),
|
||||
register: builder.mutation({
|
||||
query: (data: RegisterRequest) => ({
|
||||
url: "register",
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
});
|
||||
|
||||
export const { useGetUserQuery } = AuthApi
|
||||
export const { useGetUserQuery, useLoginMutation, useRegisterMutation } =
|
||||
AuthApi;
|
||||
|
||||
Reference in New Issue
Block a user