This repository has been archived on 2025-11-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
parandum/src/App.js
2021-09-30 11:30:18 +01:00

307 lines
9.9 KiB
JavaScript

import React from 'react';
import './css/App.css';
import { BrowserRouter as Router, Route, Switch, Redirect, Link } from 'react-router-dom';
import Home from "./Home";
import LoggedInHome from "./LoggedInHome";
import Login from "./Login";
import SetPage from "./SetPage";
import GroupPage from "./GroupPage";
import UserGroups from "./UserGroups";
import Settings from "./Settings";
import Progress from "./Progress";
import CreateSet from "./CreateSet";
import UserSets from "./UserSets";
import EditSet from "./EditSet";
import Error404 from "./Error404";
import History from "./History";
import TermsOfService from "./TermsOfService";
import PrivacyPolicy from "./PrivacyPolicy";
import Button from "./Button";
import { CheckRounded as CheckRoundedIcon } from "@material-ui/icons";
import RouteChangeTracker from './RouteChangeTracker';
import Cookies from 'universal-cookie';
import firebase from "firebase/app";
import "firebase/auth";
import "firebase/functions";
import "firebase/app-check";
import "firebase/firestore";
import "firebase/analytics";
// TODO: app check debug token set in index.html - remove before deploy
const firebaseConfig = {
apiKey: "AIzaSyCv5A51xC90hu-Tfw9F7yPasyslzNY0bP4",
authDomain: "parandum.mgrove.uk",
projectId: "parandum",
storageBucket: "parandum.appspot.com",
messagingSenderId: "639286122165",
appId: "1:639286122165:web:62f1e81a35e26ec4e5d0fc",
measurementId: "G-MX83SH11CJ"
};
firebase.initializeApp(firebaseConfig);
const appCheck = firebase.appCheck();
appCheck.activate(
"6LfxoQAcAAAAACEuhx1aaBl69svfRDDlq9Md96we",
true
);
// firebase.functions().useEmulator("localhost", 5001);
// firebase.auth().useEmulator("http://localhost:9099");
// firebase.firestore().useEmulator("localhost", 8080);
const functions = firebase.app().functions("europe-west2");//firebase.functions();
firebase.firestore().enablePersistence()
.catch((err) => {
if (err.code === 'failed-precondition') {
console.log("Offline persistence can only be enabled in one tab at a time");
} else if (err.code === 'unimplemented') {
console.log("Your browser doesn't support offline persistence");
}
});
const themes = [
"default",
"pink",
"maroon",
"red",
"orange",
"yellow",
"green",
"light-blue"
];
const db = firebase.firestore();
// stop automatic logging of page views
window.dataLayer = window.dataLayer || [];
function gtag() {window.dataLayer.push(arguments); }
gtag('set', {'send_page_view': false });
const analytics = firebase.analytics();
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
user: null,
sound: true,
theme: "default",
};
}
componentDidMount() {
firebase.auth().onAuthStateChanged(async (userData) => {
let newState = {
user: userData,
};
if (userData) {
// login event
analytics.logEvent("login", {
method: userData.providerData.map(provider => provider.providerId).join(","),
});
await firebase.firestore()
.collection("users")
.doc(userData.uid)
.get()
.then((userDoc) => {
newState.sound = userDoc.data().sound;
newState.theme = userDoc.data().theme;
}).catch((error) => {
newState.sound = true;
newState.theme = "default";
});
}
this.setState(newState);
});
this.cookies = new Cookies();
this.cookieNotice = document.getElementById("cookie-notice");
this.root = document.getElementById("root");
this.cookieNoticeHeight = 0;
if (this.cookies.get("parandum-cookies-accepted") !== "true") {
this.cookieNotice.style.display = "flex";
this.cookieNoticeHeight = this.cookieNotice.offsetHeight;
this.cookieNotice.animate({
bottom: [`-${this.cookieNoticeHeight}px`, "0px"],
}, {
duration: 1000,
easing: "ease-in-out",
iterations: 1,
fill: "forwards",
});
this.root.animate({
marginBottom: ["0px", `${this.cookieNoticeHeight}px`],
}, {
duration: 1000,
easing: "ease-in-out",
iterations: 1,
fill: "forwards",
});
window.addEventListener('resize', this.updateCookieNoticeMargins);
}
}
updateCookieNoticeMargins = () => {
if (this.cookieNoticeHeight !== this.cookieNotice.offsetHeight) {
this.cookieNoticeHeight = this.cookieNotice.offsetHeight;
this.root.animate({
marginBottom: [`${this.root.marginBottom}px`, `${this.cookieNoticeHeight}px`],
}, {
duration: 500,
easing: "ease-in-out",
iterations: 1,
fill: "forwards",
});
}
}
handleThemeChange = (newTheme, globalChange = false) => {
if (globalChange) firebase.firestore().collection("users")
.doc(this.state.user.uid)
.update({
theme: newTheme,
});
this.setState({
theme: newTheme,
});
}
handleSoundChange = (newSound, globalChange = false) => {
if (globalChange) firebase.firestore().collection("users")
.doc(this.state.user.uid)
.update({
sound: newSound,
});
this.setState({
sound: newSound,
});
}
acceptCookies = () => {
window.removeEventListener('resize', this.updateCookieNoticeMargins);
this.cookieNoticeHeight = this.cookieNotice.offsetHeight;
this.cookieNotice.animate({
bottom: ["0px", `-${this.cookieNoticeHeight}px`],
}, {
duration: 1000,
easing: "ease-in-out",
iterations: 1,
fill: "forwards",
});
this.root.animate({
marginBottom: [`${this.cookieNoticeHeight}px`, "0px"],
}, {
duration: 1000,
easing: "ease-in-out",
iterations: 1,
fill: "forwards",
});
setTimeout(() => this.cookieNotice.style.display = "none", 1000);
this.cookies.set("parandum-cookies-accepted", "true", {
maxAge: 31556952,
path: "/",
});
}
render() {
return (
<div className={this.state.theme}>
<Router>
<RouteChangeTracker />
{
this.state.user !== null
?
<>
<Switch>
<Route path="/" exact>
<LoggedInHome db={db} firebase={firebase} functions={functions} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/sets/:setId" exact>
<SetPage db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/groups" exact>
<UserGroups db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/groups/:groupId" exact>
<GroupPage db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/settings">
<Settings db={db} user={this.state.user} sound={this.state.sound} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} />
</Route>
<Route path="/progress/:progressId" exact>
<Progress db={db} functions={functions} user={this.state.user} sound={this.state.sound} handleSoundChange={this.handleSoundChange} theme={this.state.theme} handleThemeChange={this.handleThemeChange} themes={themes} logEvent={analytics.logEvent} />
</Route>
<Route path="/create-set" exact>
<CreateSet db={db} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/my-sets" exact>
<UserSets db={db} functions={functions} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/sets/:setId/edit" exact>
<EditSet db={db} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/history" exact>
<History db={db} user={this.state.user} logEvent={analytics.logEvent} />
</Route>
<Route path="/tos" exact>
<TermsOfService logEvent={analytics.logEvent} />
</Route>
<Route path="/privacy" exact>
<PrivacyPolicy logEvent={analytics.logEvent} />
</Route>
<Redirect from="/login" to="/" />
<Route>
<Error404 />
</Route>
</Switch>
</>
:
<>
<Switch>
<Route path="/" exact>
<Home db={db} logEvent={analytics.logEvent} />
</Route>
<Route path="/login">
<Login db={db} firebase={firebase} logEvent={analytics.logEvent} user={this.state.user} />
</Route>
<Route path="/tos" exact>
<TermsOfService logEvent={analytics.logEvent} />
</Route>
<Route path="/privacy" exact>
<PrivacyPolicy logEvent={analytics.logEvent} />
</Route>
<Route>
<Error404 />
</Route>
</Switch>
</>
}
<div className="cookie-notice" id="cookie-notice">
<div>
<p>Just so you know, we use cookies. Read our privacy policy <Link to="/privacy">here</Link>.</p>
<p></p>
</div>
<Button
onClick={this.acceptCookies}
icon={<CheckRoundedIcon/>}
className="button--round"
title="Accept"
></Button>
</div>
</Router>
</div>
);
}
}
export default App;