Compare commits
4 Commits
87511398fb
...
8d283064a0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d283064a0 | ||
|
|
a6f4b993dd | ||
|
|
3d7eb850ec | ||
|
|
69d026afce |
@@ -2,17 +2,7 @@ import { api as baseApi, useTokenStore } from "shared/api";
|
||||
|
||||
export const authHttpClient = baseApi.extend({
|
||||
hooks: {
|
||||
beforeRequest: [
|
||||
(request) => {
|
||||
const token = useTokenStore.getState().accessToken;
|
||||
|
||||
if (token) {
|
||||
request.headers.set("Authorization", `Bearer ${token}`);
|
||||
}
|
||||
|
||||
return request;
|
||||
},
|
||||
],
|
||||
beforeRequest: [],
|
||||
afterResponse: [
|
||||
async (request, options, response) => {
|
||||
if (response.status !== 401) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
export * from "./selectFormValid/selectFormValid";
|
||||
export * from "./selectAuthData/selectAuthData";
|
||||
export * from "./selectStatusIsLoading/selectStatusIsLoading";
|
||||
export * from "./selectEmail/selectEmail";
|
||||
export * from "./selectPassword/selectPassword";
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import type { AuthStore } from "../../types/store";
|
||||
|
||||
export const selectEmail = (state: AuthStore) =>
|
||||
state.formData?.email?.value ?? "";
|
||||
@@ -0,0 +1,4 @@
|
||||
import type { AuthStore } from "../../types/store";
|
||||
|
||||
export const selectPassword = (state: AuthStore) =>
|
||||
state.formData?.password?.value ?? "";
|
||||
@@ -2,7 +2,7 @@ import { create } from "zustand";
|
||||
import type { AuthStore, AuthStoreState } from "../../types/store";
|
||||
import { login, logout, register } from "../../../api";
|
||||
import { callApi } from "shared/utils";
|
||||
import { UNEXPECTED_ERROR_MESSAGE } from "shared/api";
|
||||
import { UNEXPECTED_ERROR_MESSAGE, useTokenStore } from "shared/api";
|
||||
import { selectAuthData, selectFormValid } from "../../selectors";
|
||||
import { validateEmail, validatePassword } from "../../../lib";
|
||||
|
||||
@@ -68,6 +68,7 @@ export const useAuthStore = create<AuthStore>()((set, get) => ({
|
||||
user: responseData?.user,
|
||||
error: null,
|
||||
});
|
||||
useTokenStore.setState({ accessToken: responseData?.accessToken });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
set({
|
||||
@@ -108,6 +109,7 @@ export const useAuthStore = create<AuthStore>()((set, get) => ({
|
||||
user: responseData?.user,
|
||||
error: null,
|
||||
});
|
||||
useTokenStore.setState({ accessToken: responseData?.accessToken });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
set({
|
||||
@@ -138,7 +140,7 @@ export const useAuthStore = create<AuthStore>()((set, get) => ({
|
||||
error: null,
|
||||
});
|
||||
|
||||
// useTokenStore.setState({ accessToken: null });
|
||||
useTokenStore.setState({ accessToken: null });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
set({ error: new Error(UNEXPECTED_ERROR_MESSAGE) });
|
||||
|
||||
@@ -1,16 +1,52 @@
|
||||
import {
|
||||
selectEmail,
|
||||
selectFormValid,
|
||||
selectPassword,
|
||||
selectStatusIsLoading,
|
||||
useAuthStore,
|
||||
} from "../../model";
|
||||
import type { SubmitEvent, ChangeEvent } from "react";
|
||||
import {
|
||||
type SubmitEvent,
|
||||
type ChangeEvent,
|
||||
type HTMLAttributes,
|
||||
type InputHTMLAttributes,
|
||||
type ButtonHTMLAttributes,
|
||||
cloneElement,
|
||||
type ReactElement,
|
||||
} from "react";
|
||||
|
||||
export type InputAttributes = InputHTMLAttributes<HTMLInputElement>;
|
||||
export type ButtonAttributes = ButtonHTMLAttributes<HTMLButtonElement>;
|
||||
|
||||
export interface Props {
|
||||
InputComponent?: ReactElement<InputAttributes>;
|
||||
ButtonComponent?: ReactElement<ButtonAttributes>;
|
||||
}
|
||||
|
||||
const DefaultInputComponent = ({
|
||||
value,
|
||||
onChange,
|
||||
["aria-label"]: ariaLabel,
|
||||
}: InputAttributes) => (
|
||||
<input
|
||||
type="email"
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
aria-label={ariaLabel}
|
||||
/>
|
||||
);
|
||||
|
||||
const DefaultButtonComponent = ({ disabled }: ButtonAttributes) => (
|
||||
<button type="submit" disabled={disabled} />
|
||||
);
|
||||
|
||||
/**
|
||||
* Login form component
|
||||
*/
|
||||
export function LoginForm() {
|
||||
const { formData, setEmail, setPassword, login } = useAuthStore();
|
||||
|
||||
export function LoginForm({ InputComponent, ButtonComponent }: Props) {
|
||||
const { setEmail, setPassword, login } = useAuthStore();
|
||||
const email = useAuthStore(selectEmail);
|
||||
const password = useAuthStore(selectPassword);
|
||||
const formValid = useAuthStore(selectFormValid);
|
||||
const isLoading = useAuthStore(selectStatusIsLoading);
|
||||
|
||||
@@ -31,21 +67,47 @@ export function LoginForm() {
|
||||
|
||||
return (
|
||||
<form aria-label="Login form" onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="email"
|
||||
aria-label="Email"
|
||||
value={formData?.email?.value ?? ""}
|
||||
onChange={handleEmailChange}
|
||||
/>
|
||||
<input
|
||||
type="password"
|
||||
aria-label="Password"
|
||||
value={formData?.password?.value ?? ""}
|
||||
onChange={handlePasswordChange}
|
||||
/>
|
||||
<button type="submit" disabled={disabled}>
|
||||
Login
|
||||
</button>
|
||||
{InputComponent ? (
|
||||
cloneElement(InputComponent, {
|
||||
type: "email",
|
||||
value: email,
|
||||
onChange: handleEmailChange,
|
||||
"aria-label": "Email",
|
||||
})
|
||||
) : (
|
||||
<DefaultInputComponent
|
||||
type="email"
|
||||
value={email}
|
||||
onChange={handleEmailChange}
|
||||
aria-label="Email"
|
||||
/>
|
||||
)}
|
||||
{InputComponent ? (
|
||||
cloneElement(InputComponent, {
|
||||
type: "password",
|
||||
value: password,
|
||||
onChange: handlePasswordChange,
|
||||
"aria-label": "Password",
|
||||
})
|
||||
) : (
|
||||
<DefaultInputComponent
|
||||
type="password"
|
||||
value={password}
|
||||
onChange={handlePasswordChange}
|
||||
aria-label="Password"
|
||||
/>
|
||||
)}
|
||||
{ButtonComponent ? (
|
||||
cloneElement(ButtonComponent, {
|
||||
type: "submit",
|
||||
disabled: disabled,
|
||||
children: "Login",
|
||||
})
|
||||
) : (
|
||||
<DefaultButtonComponent type="submit" disabled={disabled}>
|
||||
Login
|
||||
</DefaultButtonComponent>
|
||||
)}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user