This commit is contained in:
Maciej Kotowski committed 2021-10-08 19:31:45 +02:00
commit d999a61d65
10 files changed
+82 -61

No files matched your search

+2 -1
View File
@@ -5,6 +5,7 @@ import { useEffect, useRef } from "react";
import { LOGIN_MANAGER } from "../../constants";
import { spawnError } from "../../utils/popups/spawnError";
import { BIcon } from "../BIcon";
import { updateLogin } from "../../context/Login";
export const LoginPanel = (props) => {
const form = useRef(null);
@@ -13,7 +14,7 @@ export const LoginPanel = (props) => {
e.preventDefault();
LOGIN_MANAGER.login({ email: e.srcElement[0].value, password: e.srcElement[1].value })
.then((r) => {
console.log(r);
updateLogin(r);
props.close(r);
})
.catch((e) => {
+4 -3
View File
@@ -2,7 +2,7 @@ import { Link } from "react-router-dom";
import { BIcon } from "../BIcon";
import styles from "./index.module.scss";
import title from "../../assets/title.svg";
import { LOGIN_MANAGER } from "../../constants";
import { useLogin } from "../../context/Login";
import { spawnPopup } from "../../utils/popups/spawnPopup";
import { LoginPanel } from "../LoginPanel";
import { UserPanel } from "../UserPanel";
@@ -10,6 +10,7 @@ import { useHistory } from "react-router";
export const Navbar = () => {
const history = useHistory();
const login = useLogin();
return (
<nav className={styles.nav}>
@@ -20,10 +21,10 @@ export const Navbar = () => {
aria-label="Zarządzanie kontem"
className={styles.navBtn}
onClick={async () => {
if (LOGIN_MANAGER.state) {
if (login) {
await spawnPopup(
(close) => {
return <UserPanel history={history} close={close} />;
return <UserPanel state={login} history={history} close={close} />;
},
{ minWidth: "30vw" }
);
+5 -2
View File
@@ -2,9 +2,10 @@ import styles from "./index.module.scss";
import { LOGIN_MANAGER } from "../../constants";
import { BIcon } from "../BIcon";
import { Stack } from "react-bootstrap";
import { updateLogin } from "../../context/Login";
export const UserPanel = (props) => {
if (!LOGIN_MANAGER.state) props.close();
if (!props.state) props.close();
return (
<div className={styles.container}>
@@ -12,7 +13,7 @@ export const UserPanel = (props) => {
<BIcon icon="x" size={"20px"} />
</button>
<h3>Zalogowano jako</h3>
<h1>{LOGIN_MANAGER.state.email ?? "Nieznany użytkownik"}</h1>
<h1>{props.state.email ?? "Nieznany użytkownik"}</h1>
<Stack gap={2}>
<button
aria-label="Dashboard"
@@ -27,6 +28,8 @@ export const UserPanel = (props) => {
aria-label="Wyloguj się"
onClick={async () => {
await LOGIN_MANAGER.logout();
updateLogin(null);
props.history?.push("/");
props.close();
}}
className={styles.logoutBtn}
+41
View File
@@ -0,0 +1,41 @@
import { createContext, useContext, useState } from "react";
const login = {
state: null,
setter: null,
};
const validateData = (data) => {
if (data === null) return false;
if (typeof data !== "object") throw new TypeError("Incorrect argument");
if (typeof data._id !== "string") throw new TypeError("Incorrect value type: _id");
if (typeof data.email !== "string") throw new TypeError("Incorrect value type: email");
return true;
};
export const LoginContext = createContext(login.state);
export const useLogin = () => {
return useContext(LoginContext);
};
export const updateLogin = (data) => {
switch (validateData(data)) {
case true:
login.setter({
_id: data._id,
email: data.email,
});
return;
case false:
login.setter(null);
return;
default:
return;
}
};
export const Login = (props) => {
[login.state, login.setter] = useState(props.initial ?? null);
return <LoginContext.Provider value={login.state}>{props.children}</LoginContext.Provider>;
};
+7 -4
View File
@@ -5,16 +5,19 @@ import { App } from "./App.js";
import "bootstrap/dist/css/bootstrap.min.css";
import { API_CLIENT, LOGIN_MANAGER } from "./constants";
import { Events } from "./context/Events";
import { Login } from "./context/Login";
(async () => {
const events = await API_CLIENT.fetchEvents();
await LOGIN_MANAGER.fetchSession();
const loginState = await LOGIN_MANAGER.fetchSession();
ReactDOM.render(
<React.StrictMode>
<Events initial={events}>
<App />
</Events>
<Login initial={loginState ?? null}>
<Events initial={events}>
<App />
</Events>
</Login>
</React.StrictMode>,
document.getElementById("root")
);
+5 -3
View File
@@ -4,7 +4,7 @@ import { useState } from "react";
import { Stack } from "react-bootstrap";
import { BIcon } from "../../components/BIcon";
import { useHistory } from "react-router";
import { API_CLIENT, LOGIN_MANAGER } from "../../constants";
import { API_CLIENT } from "../../constants";
import { container } from "../../global.module.scss";
import styles from "./index.module.scss";
import { spawnPopup } from "../../utils/popups/spawnPopup";
@@ -12,10 +12,12 @@ import { spawnError } from "../../utils/popups/spawnError";
import { getPlace } from "../../utils/map/getPlace";
import { MapPopup } from "./MapPopup";
import { addEvent } from "../../context/Events";
import { useLogin } from "../../context/Login";
export const CreateEvent = () => {
const login = useLogin();
const history = useHistory();
if (LOGIN_MANAGER.state === null) {
if (login === null) {
history.push("/");
}
useTitle("Tworzenie wydarzenia");
@@ -54,7 +56,7 @@ export const CreateEvent = () => {
lat: mapPos?.[1] ?? null,
address: locationText,
time: date.getTime(),
user: LOGIN_MANAGER.state.email,
user: login.email,
};
API_CLIENT.createEvent(rqObj)
.then((res) => {
+5 -5
View File
@@ -10,11 +10,12 @@ import { useHistory } from "react-router";
import { spawnPopup } from "../../utils/popups/spawnPopup";
import { spawnError } from "../../utils/popups/spawnError";
import { getUserPos } from "../../utils/getUserPos";
import { useLoginState } from "../../utils/useLoginState";
import { useEvents } from "../../context/Events";
import { useLogin } from "../../context/Login";
export const Home = () => {
const events = useEvents();
const login = useLogin();
const history = useHistory();
const sortDropdown = useRef(null);
const createEventButton = useRef(null);
@@ -56,10 +57,9 @@ export const Home = () => {
el.removeEventListener("input", cb);
};
}, [events, list]);
useLoginState((state) => {
if (createEventButton.current) createEventButton.current.disabled = state === null;
});
useEffect(() => {
createEventButton.current.disabled = !login;
}, [createEventButton, login]);
return (
<div className={container}>
+3 -14
View File
@@ -1,16 +1,9 @@
import axios from "axios";
import { EventEmitter } from "events";
export class LoginManager extends EventEmitter {
export class LoginManager {
#dbUrl = "";
#loginState = null;
get state() {
return this.#loginState;
}
constructor(dbUrl) {
super();
if (typeof dbUrl !== "string") throw new TypeError("dbUrl must be a string");
this.#dbUrl = dbUrl;
}
@@ -22,16 +15,12 @@ export class LoginManager extends EventEmitter {
const rq = await axios.post(`${this.#dbUrl}/api/auth/register_login`, data);
if (rq.status !== 200) throw new Error(`Request failed with status code ${rq.status}: ${rq.statusText}`);
this.#loginState = rq.data ?? null;
this.emit("STATE_CHANGE", this.#loginState);
return rq.data ?? null;
}
async logout() {
const rq = await axios.get(`${this.#dbUrl}/api/logout`);
if (rq.status !== 200) throw new Error(`Request failed with status code ${rq.status}: ${rq.statusText}`);
this.#loginState = null;
this.emit("STATE_CHANGE", null);
return null;
}
@@ -39,9 +28,9 @@ export class LoginManager extends EventEmitter {
const rq = await axios.get(`${this.#dbUrl}/api/isLogged`);
if (rq.status !== 200) throw new Error(`Request failed with status code ${rq.status}: ${rq.statusText}`);
if (rq.data !== "not logged") {
this.#loginState = rq.data ?? null;
this.emit("STATE_CHANGE", this.#loginState);
return rq.data ?? null;
} else {
return null;
}
}
}
-18
View File
@@ -1,18 +0,0 @@
import { useEffect, useState } from "react";
import { LOGIN_MANAGER } from "../constants";
export const useLoginState = (callback) => {
if (callback && typeof callback !== "function") throw new TypeError("Invalid callback");
const [componentState, updateComponentState] = useState(LOGIN_MANAGER.state);
useEffect(() => {
const listenerFn = (state) => {
callback && callback(state);
updateComponentState(state);
};
LOGIN_MANAGER.on("STATE_CHANGE", listenerFn);
return () => {
LOGIN_MANAGER.removeListener("STATE_CHANGE", listenerFn);
};
}, [callback]);
return componentState;
};