Archived
new event state management
MAJOR!!!
This commit is contained in:
1 parent
44645884c2
commit
81e0f81157
7 files changed
+144
-74
No files matched your search
+88
-49
@@ -1,4 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
|
||||
import { Home } from "./pages/Home";
|
||||
import { About } from "./pages/About";
|
||||
@@ -8,57 +8,96 @@ import { NotFound } from "./pages/NotFound";
|
||||
import { Navbar } from "./components/Navbar";
|
||||
import { CreateEvent } from "./pages/CreateEvent";
|
||||
import { Event } from "./pages/Event";
|
||||
import { EVENT_CONTEXT } from "./constants";
|
||||
import { API_CLIENT } from "./constants";
|
||||
import { LoginPage } from "./pages/Login";
|
||||
|
||||
export const App = (props) => {
|
||||
const [context, setContext] = useState({
|
||||
events: props.events,
|
||||
updateEvents: function (events = []) {
|
||||
if (!Array.isArray(events)) throw new TypeError("Events must come in array");
|
||||
setContext({
|
||||
events: events,
|
||||
updateEvents: this.updateEvents,
|
||||
});
|
||||
},
|
||||
});
|
||||
export const App = () => {
|
||||
const [routes, setRoutes] = useState(
|
||||
API_CLIENT.events.map((e) => {
|
||||
return (
|
||||
<Route key={e._id} exact path={`/event/${e._id}`}>
|
||||
<Event
|
||||
data={{
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
description: e.description,
|
||||
address: e.address,
|
||||
time: e.time,
|
||||
lat: e.lat,
|
||||
lon: e.lon,
|
||||
id: e._id,
|
||||
createdTime: e.created.time,
|
||||
}}
|
||||
></Event>
|
||||
</Route>
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
API_CLIENT.on("EVENT_RELOAD", (list) => {
|
||||
setRoutes(
|
||||
list.map((e) => {
|
||||
return (
|
||||
<Route key={e._id} exact path={`/event/${e._id}`}>
|
||||
<Event
|
||||
data={{
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
description: e.description,
|
||||
address: e.address,
|
||||
time: e.time,
|
||||
lat: e.lat,
|
||||
lon: e.lon,
|
||||
id: e._id,
|
||||
createdTime: e.created.time,
|
||||
}}
|
||||
></Event>
|
||||
</Route>
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
API_CLIENT.on("EVENT_CREATE", (list) => {
|
||||
setRoutes(
|
||||
list.map((e) => {
|
||||
return (
|
||||
<Route key={e._id} exact path={`/event/${e._id}`}>
|
||||
<Event
|
||||
data={{
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
description: e.description,
|
||||
address: e.address,
|
||||
time: e.time,
|
||||
lat: e.lat,
|
||||
lon: e.lon,
|
||||
id: e._id,
|
||||
createdTime: e.created.time,
|
||||
}}
|
||||
></Event>
|
||||
</Route>
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<EVENT_CONTEXT.Provider value={context}>
|
||||
<Router>
|
||||
<Navbar />
|
||||
<Switch>
|
||||
<Route exact path="/about" component={About} />
|
||||
<Route exact path="/credits" component={Credits} />
|
||||
<Route exact path="/users" component={Users} />
|
||||
<Route exact path="/">
|
||||
<Home />
|
||||
</Route>
|
||||
<Route exact path="/create" component={CreateEvent} />
|
||||
<Route exact path="/login" component={LoginPage} />
|
||||
{Array.isArray(props.events) &&
|
||||
props.events.map((e) => {
|
||||
return (
|
||||
<Route key={e._id} exact path={`/event/${e._id}`}>
|
||||
<Event
|
||||
data={{
|
||||
name: e.name,
|
||||
type: e.type,
|
||||
description: e.description,
|
||||
address: e.address,
|
||||
time: e.time,
|
||||
lat: e.lat,
|
||||
lon: e.lon,
|
||||
id: e._id,
|
||||
createdTime: e.created.time,
|
||||
}}
|
||||
></Event>
|
||||
</Route>
|
||||
);
|
||||
})}
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Router>
|
||||
</EVENT_CONTEXT.Provider>
|
||||
<Router>
|
||||
<Navbar />
|
||||
<Switch>
|
||||
<Route exact path="/about" component={About} />
|
||||
<Route exact path="/credits" component={Credits} />
|
||||
<Route exact path="/users" component={Users} />
|
||||
<Route exact path="/">
|
||||
<Home />
|
||||
</Route>
|
||||
<Route exact path="/create" component={CreateEvent} />
|
||||
<Route exact path="/login" component={LoginPage} />
|
||||
{routes}
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
@@ -1,10 +1,8 @@
|
||||
import { createContext } from "react";
|
||||
import { APIClient } from "./utils/APIClient";
|
||||
require("dotenv").config();
|
||||
|
||||
export const APP_NAME = "eco-meet";
|
||||
export const BACKEND_URL = "http://localhost:5000";
|
||||
export const EVENT_CONTEXT = createContext();
|
||||
export const API_CLIENT = new APIClient(process.env.DEPLOY ? "" : BACKEND_URL);
|
||||
export const EVENT_TYPES = {
|
||||
colors: {
|
||||
|
||||
+2
-2
@@ -6,11 +6,11 @@ import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import { API_CLIENT } from "./constants";
|
||||
|
||||
(async () => {
|
||||
const dbEvents = await API_CLIENT.getEvents();
|
||||
await API_CLIENT.fetchEvents();
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App events={dbEvents} />
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useTitle } from "../../utils/useTitle";
|
||||
import { useFormik } from "formik";
|
||||
import { useContext, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { Stack } from "react-bootstrap";
|
||||
import { BIcon } from "../../components/BIcon";
|
||||
import { useHistory } from "react-router";
|
||||
import { API_CLIENT, EVENT_CONTEXT } 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";
|
||||
@@ -14,7 +14,6 @@ import { MapPopup } from "./MapPopup";
|
||||
|
||||
export const CreateEvent = () => {
|
||||
useTitle("Tworzenie wydarzenia");
|
||||
const context = useContext(EVENT_CONTEXT);
|
||||
const history = useHistory();
|
||||
const [locationText, setLocationText] = useState("Brak lokalizacji");
|
||||
const formik = useFormik({
|
||||
@@ -46,7 +45,7 @@ export const CreateEvent = () => {
|
||||
const rqObj = {
|
||||
name: data.name,
|
||||
type: parseInt(data.type),
|
||||
description: data.description,
|
||||
description: data.description ?? null,
|
||||
lon: mapPos?.[0] ?? null,
|
||||
lat: mapPos?.[1] ?? null,
|
||||
address: locationText,
|
||||
@@ -54,10 +53,7 @@ export const CreateEvent = () => {
|
||||
};
|
||||
API_CLIENT.createEvent(rqObj)
|
||||
.then(() => {
|
||||
API_CLIENT.getEvents().then((r) => {
|
||||
context.updateEvents(r);
|
||||
history.push("/");
|
||||
});
|
||||
history.push("/");
|
||||
})
|
||||
.catch(async (e) => {
|
||||
await spawnError(e.toString());
|
||||
|
||||
@@ -1,32 +1,56 @@
|
||||
import { useTitle } from "../../utils/useTitle";
|
||||
import { useState, useRef, useEffect, useContext } from "react";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
import { Stack } from "react-bootstrap";
|
||||
import { EventPreview } from "../../components/EventPreview";
|
||||
import { container } from "../../global.module.scss";
|
||||
import styles from "./index.module.scss";
|
||||
import { BIcon } from "../../components/BIcon";
|
||||
// import HoldingPlant from "../../components/Pop-up/AnimatedHand";
|
||||
import { EVENT_CONTEXT } from "../../constants";
|
||||
import { API_CLIENT } from "../../constants";
|
||||
// import { calculateDistance } from "../../utils/map/calculateDistance";
|
||||
import { useHistory } from "react-router";
|
||||
import Button from "@restart/ui/esm/Button";
|
||||
|
||||
export const Home = () => {
|
||||
useTitle();
|
||||
const context = useContext(EVENT_CONTEXT);
|
||||
const [list, updateList] = useState(
|
||||
context.events.map((e, i) => {
|
||||
API_CLIENT.events.map((e, i) => {
|
||||
return <EventPreview data={{ name: e.name, type: e.type, lon: e.lon, lat: e.lat, createdTime: e.created.time, time: e.time, id: e._id, address: e.address }} key={i} />;
|
||||
})
|
||||
);
|
||||
const sortDropdown = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
API_CLIENT.on("EVENT_RELOAD", (list) => {
|
||||
updateList(
|
||||
list.map((e, i) => {
|
||||
return (
|
||||
<EventPreview
|
||||
data={{ name: e.name, type: e.type, lon: e.lon, lat: e.lat, createdTime: e.created.time, time: e.time, id: e._id, address: e.address }}
|
||||
key={i}
|
||||
/>
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
API_CLIENT.on("EVENT_CREATE", (list) => {
|
||||
updateList(
|
||||
list.map((e, i) => {
|
||||
return (
|
||||
<EventPreview
|
||||
data={{ name: e.name, type: e.type, lon: e.lon, lat: e.lat, createdTime: e.created.time, time: e.time, id: e._id, address: e.address }}
|
||||
key={i}
|
||||
/>
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
sortDropdown.current.addEventListener("input", (e) => {
|
||||
const value = e.target.value;
|
||||
const type = value.split(":")[0];
|
||||
const direction = value.split(":")[1];
|
||||
const newOrder = context.events.sort((a, b) => {
|
||||
const newOrder = API_CLIENT.events.sort((a, b) => {
|
||||
switch (type) {
|
||||
case "event-date":
|
||||
return direction === "ascending" ? a.time - b.time : b.time - a.time;
|
||||
@@ -51,7 +75,7 @@ export const Home = () => {
|
||||
})
|
||||
);
|
||||
});
|
||||
}, [context.events]);
|
||||
}, []);
|
||||
|
||||
const history = useHistory();
|
||||
|
||||
|
||||
@@ -1,22 +1,33 @@
|
||||
import axios from "axios";
|
||||
import { EventEmitter } from "events";
|
||||
|
||||
export class APIClient {
|
||||
export class APIClient extends EventEmitter {
|
||||
#dbUrl = "";
|
||||
#events = [];
|
||||
|
||||
constructor(dbUrl) {
|
||||
super();
|
||||
if (typeof dbUrl !== "string") throw new Error("Database URL is not a string");
|
||||
this.#dbUrl = dbUrl;
|
||||
}
|
||||
async getEvents() {
|
||||
|
||||
get events() {
|
||||
return this.#events;
|
||||
}
|
||||
|
||||
async fetchEvents() {
|
||||
const rq = await axios.get(`${this.#dbUrl}/api/getEvents`);
|
||||
if (rq.status !== 200) throw new Error(`Request failed with status code ${rq.status}: ${rq.statusText}`);
|
||||
this.#events = rq.data;
|
||||
this.emit("EVENT_RELOAD", this.#events, rq.data);
|
||||
return rq.data;
|
||||
}
|
||||
|
||||
async getEvent(id) {
|
||||
if (typeof id !== "string") throw new TypeError("Invalid ID type");
|
||||
const events = await this.getEvents();
|
||||
return events.find((e) => e.id === id) ?? null;
|
||||
return this.#events.find((e) => e.id === id) ?? null;
|
||||
}
|
||||
|
||||
async createEvent(data) {
|
||||
//Check types
|
||||
if (typeof data !== "object") throw new TypeError("Data object is required");
|
||||
@@ -27,6 +38,8 @@ export class APIClient {
|
||||
//Make POST request
|
||||
const rq = await axios.post(`${this.#dbUrl}/api/createEvent`, data);
|
||||
if (rq.status !== 200) throw new Error(`Request failed with status code ${rq.status}: ${rq.statusText}`);
|
||||
return rq;
|
||||
this.#events.push(rq.data);
|
||||
this.emit("EVENT_CREATE", this.#events, rq.data);
|
||||
return rq.data;
|
||||
}
|
||||
}
|
||||
@@ -51,10 +51,10 @@ app.post("/api/createEvent", (req, res) => {
|
||||
lat: req.body.lat,
|
||||
lon: req.body.lon,
|
||||
};
|
||||
events.create(data, (err) => {
|
||||
events.create(data, (err, data) => {
|
||||
if (err) return res.status(400).json({ msg: err });
|
||||
// saved!
|
||||
res.status(200).json("ok");
|
||||
res.status(200).json(data);
|
||||
});
|
||||
});
|
||||
app.use((req, res, next) => {
|
||||
|
||||
Reference in new issue
Block a user