added FireBase firestore

This commit is contained in:
Ruidy Nemausat 2020-04-04 13:09:51 +02:00
parent 0967f5f2ad
commit 47c9d5f4d9
13 changed files with 1157 additions and 106 deletions

26
.gitignore vendored
View file

@ -1,26 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
/src/utils/auth_config.json
/src/utils/secret.js

View file

@ -2,6 +2,7 @@
- [ ] send message after contact form validation (confirm to sender and msg+info to admin) - [ ] send message after contact form validation (confirm to sender and msg+info to admin)
- [ ] Local storage of prefeernces - [ ] Local storage of prefeernces
- [ ] Firebase
- [ ] Breadcrumb - [ ] Breadcrumb
- [ ] Cookie bar - [ ] Cookie bar
- [ ] code cleanup (props and refactoring) - [ ] code cleanup (props and refactoring)

1055
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,6 +7,8 @@
"@testing-library/jest-dom": "^4.2.4", "@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0", "@testing-library/react": "^9.4.0",
"@testing-library/user-event": "^7.2.1", "@testing-library/user-event": "^7.2.1",
"dotenv": "^8.2.0",
"firebase": "^7.13.2",
"react": "^16.12.0", "react": "^16.12.0",
"react-dom": "^16.12.0", "react-dom": "^16.12.0",
"react-router-dom": "^5.1.2", "react-router-dom": "^5.1.2",
@ -33,4 +35,4 @@
"last 1 safari version" "last 1 safari version"
] ]
} }
} }

View file

@ -81,13 +81,13 @@ export const App = () => {
strMeasure19: "", strMeasure19: "",
strMeasure20: "", strMeasure20: "",
strSource: "https://www.bbcgoodfood.com/recipes/pilchard-puttanesca", strSource: "https://www.bbcgoodfood.com/recipes/pilchard-puttanesca",
dateModified: null dateModified: null,
} },
] ],
}; };
const [meal, setMeal] = useState(mealDef); const [meal, setMeal] = useState(mealDef);
const getMeal = id => { const getMeal = (id) => {
getData(id, setMeal, "lookup"); getData(id, setMeal, "lookup");
}; };
@ -95,13 +95,13 @@ export const App = () => {
getData("random", setMeal); getData("random", setMeal);
}; };
const getSearchResults = e => { const getSearchResults = (e) => {
searchString === "" searchString === ""
? e.preventDefault() ? e.preventDefault()
: getData(searchString, setSearchResults, "search"); : getData(searchString, setSearchResults, "search");
}; };
const handleChange = ev => { const handleChange = (ev) => {
const { value } = ev.target; const { value } = ev.target;
setSearchString(value); setSearchString(value);
}; };
@ -109,18 +109,18 @@ export const App = () => {
const buttonUrl = "/random"; const buttonUrl = "/random";
const [showNav, setShowNav] = useState(false); const [showNav, setShowNav] = useState(false);
const openNavClick = ev => { const openNavClick = (ev) => {
ev.preventDefault(); ev.preventDefault();
setShowNav(true); setShowNav(true);
document.addEventListener("keydown", handleEscKey); document.addEventListener("keydown", handleEscKey);
// document.addEventListener("click", handleOutsideClick); // document.addEventListener("click", handleOutsideClick);
}; };
const closeNavClick = ev => { const closeNavClick = (ev) => {
ev.preventDefault(); ev.preventDefault();
setShowNav(false); setShowNav(false);
document.removeEventListener("keydown", handleEscKey); document.removeEventListener("keydown", handleEscKey);
}; };
const handleEscKey = ev => { const handleEscKey = (ev) => {
if (ev.key === "Escape") { if (ev.key === "Escape") {
setShowNav(false); setShowNav(false);
} }
@ -201,7 +201,7 @@ export const App = () => {
<NotFoundPage handleClick={getRandomMeal} /> <NotFoundPage handleClick={getRandomMeal} />
</Route> </Route>
<Route path="/:idMeal"> <Route path="/:id">
<MealController <MealController
meal={meal} meal={meal}
getMeal={getMeal} getMeal={getMeal}

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
export const MealPresentation = props => { export const MealPresentation = (props) => {
const { const {
mealName, mealName,
imgAddress, imgAddress,
@ -9,8 +9,9 @@ export const MealPresentation = props => {
mealCategory, mealCategory,
mealArea, mealArea,
isFav, isFav,
setIsFav setIsFav,
} = props.meal; } = props.meal;
return ( return (
<div className="row"> <div className="row">
<div className="col s12"> <div className="col s12">
@ -22,40 +23,41 @@ export const MealPresentation = props => {
<li> <li>
<div className="chip"> <div className="chip">
<b>Video:</b> <b>Video:</b>
<a href={videoAddress} target="blank"> <a href={videoAddress} target="blank" rel="noopener">
<i className="close material-icons">video_library</i> <i className="close material-icons">video_library</i>
</a> </a>
</div> </div>
{/* </li>
<li> */}
<div className="chip"> <div className="chip">
<b>Category: </b> {mealCategory} <b>Category: </b> {mealCategory}
<Link to={`/categories/${mealCategory}`}> <Link to={`/categories/${mealCategory}`}>
<i className="close material-icons">call_made</i> <i className="close material-icons">call_made</i>
</Link> </Link>
</div> </div>
{/* </li>
<li> */}
<div className="chip"> <div className="chip">
<b>Origin:</b> {mealArea} <b>Origin:</b> {mealArea}
</div> </div>
<div className="chip"> <div className="chip">
<b> <b>
{isFav ? "Remove from favourites" : "Add to favourites"}: {isFav ? "Remove from favourites" : "Add to favourites"}:
</b> </b>
<Link to="#"> <Link to="#">
{" "}
<i <i
className="close material-icons" className="material-icons tiny"
onClick={() => setIsFav(!isFav)} onClick={(e) => {
e.preventDefault();
setIsFav(!isFav);
}}
> >
{isFav ? "favorite" : "favorite_border"} {isFav ? "favorite" : "favorite_border"}
</i> </i>
</Link> </Link>
</div> </div>
</li> </li>
<li></li>
</ul> </ul>
</div> </div>
</div> </div>

View file

@ -1,76 +1,48 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useAuth0 } from "../utils/auth0-spa";
import { MealPage } from "../pages/MealPage"; import { MealPage } from "../pages/MealPage";
import { NotFoundPage } from "../pages/NotFoundPage"; import { NotFoundPage } from "../pages/NotFoundPage";
import { useFirebase } from "../services/Firebase";
// import Firebase from "../data/Firebase";
export const MealController = ({ meal, getMeal, getRandomMeal }) => { export const MealController = ({ meal, getMeal, getRandomMeal }) => {
const { idMeal } = useParams(); const { user, isAuthenticated } = useAuth0();
const { id } = useParams();
const fb = useFirebase();
useEffect(() => { useEffect(() => {
idMeal === undefined ? getRandomMeal() : getMeal(idMeal); id === undefined ? getRandomMeal() : getMeal(id);
// eslint-disable-next-line // eslint-disable-next-line
}, []); }, []);
const mealItem = meal.meals[0]; const mealItem = meal.meals[0];
const { const {
idMeal,
strMeal, strMeal,
strMealThumb, strMealThumb,
strYoutube, strYoutube,
strCategory, strCategory,
strArea, strArea,
strInstructions strInstructions,
} = mealItem; } = mealItem;
// const setDbPromise = () => { const [isFav, setIsFav] = useState(false);
// //check for support
// if (!("indexedDB" in window)) {
// console.log("This browser doesn't support IndexedDB");
// return;
// }
// var dbPromise = indexedDB.open("chefs-db", 1, function(upgradeDb) {
// if (!upgradeDb.objectStoreNames.contains("favourites")) {
// var favOS = upgradeDb.createObjectStore("favourites", {
// keyPath: "mealName"
// });
// favOS.createIndex("isFav", "isFav", { unique: true });
// }
// });
// return dbPromise;
// };
// const [isFav, setIsFav] = useState(false);
// var dbPromise = setDbPromise();
// dbPromise
// .then(db => {
// var tx = db.transaction("favourites", "readwrite");
// var store = tx.objectStore("favourites");
// var item = {
// mealName: strMeal,
// isFav: isFav
// };
// store.add(item);
// return tx.complete;
// })
// .then(function() {
// console.log("added item to the favourite os!");
// });
// const initState = Boolean(localStorage.getItem(strMeal));
const [isFav, setIsFav] = useState(localStorage.getItem(strMeal) === "fav");
// console.log(isFav);
useEffect(() => { useEffect(() => {
isFav // console.log(user.email);
? localStorage.setItem(strMeal, "fav") // console.log(idMeal);
: localStorage.removeItem(strMeal);
// console.log(localStorage.getItem(strMeal));
// console.log(isFav); // console.log(isFav);
}, [isFav, strMeal]); console.log(fb);
// const add2Fav = async (user, idMeal, isFav) => {
if (isAuthenticated) {
fb.add(user.email, idMeal, isFav);
}
// };
// add2Fav(user, idMeal, isFav).then((data) => console.log(data));
}, [user, idMeal, isFav]);
const item = { const item = {
mealName: strMeal, mealName: strMeal,
@ -79,7 +51,7 @@ export const MealController = ({ meal, getMeal, getRandomMeal }) => {
mealCategory: strCategory, mealCategory: strCategory,
mealArea: strArea, mealArea: strArea,
isFav: isFav, isFav: isFav,
setIsFav: setIsFav setIsFav: setIsFav,
}; };
let ingredientList = []; let ingredientList = [];

View file

@ -6,6 +6,8 @@ import { ProfilePage } from "../pages/ProfilePage";
export const ProfileController = () => { export const ProfileController = () => {
const { loading, user } = useAuth0(); const { loading, user } = useAuth0();
// const fn = async () => await fire.getByEmail(user.email);
return loading || !user ? ( // is catched by PrivateRoute return loading || !user ? ( // is catched by PrivateRoute
<div className="container center-align"> <div className="container center-align">
<PreLoader /> <PreLoader />

View file

@ -6,8 +6,9 @@ import * as serviceWorker from "./serviceWorker";
import { Auth0Provider } from "./utils/auth0-spa"; import { Auth0Provider } from "./utils/auth0-spa";
import history from "./utils/history"; import history from "./utils/history";
import config from "./utils/auth_config.json"; // for safety reasons this file is not tracked by git import config from "./utils/auth_config.json"; // for safety reasons this file is not tracked by git
import Firebase, { FirebaseContext } from "./services/Firebase";
const onRedirectCallBack = appState => { const onRedirectCallBack = (appState) => {
history.push( history.push(
appState && appState.targetUrl appState && appState.targetUrl
? appState.targetUrl ? appState.targetUrl
@ -22,7 +23,9 @@ ReactDOM.render(
redirect_uri={window.location.origin} redirect_uri={window.location.origin}
onRedirectCallBack={onRedirectCallBack} onRedirectCallBack={onRedirectCallBack}
> >
<App /> <FirebaseContext.Provider value={new Firebase()}>
<App />
</FirebaseContext.Provider>
</Auth0Provider>, </Auth0Provider>,
document.getElementById("root") document.getElementById("root")
); );

View file

@ -0,0 +1,5 @@
import { createContext, useContext } from "react";
const FirebaseContext = createContext(null);
export const useFirebase = () => useContext(FirebaseContext);
export default FirebaseContext;

View file

@ -0,0 +1,40 @@
import app from "firebase/app";
import "firebase/firestore";
import config from "./config.json";
const CONFIG = {
apiKey: config.apiKey,
authDomain: config.authDomain,
databaseURL: config.databaseURL,
projectId: config.projectId,
storageBucket: config.storageBucket,
messagingSenderId: config.messagingSenderId,
appId: config.appId,
measurementId: config.measurementId,
};
export default class Firebase {
constructor() {
app.initializeApp(CONFIG);
this.db = app.firestore();
}
add = async (email, id, fav) => {
await this.db
.collection("MealPlannerFavs")
.add({ email: email, idMeal: id, isfav: fav })
.then((ref) => {
console.log("Added document with ID: ", ref.id);
})
.catch((error) => console.error("Error adding document: ", error));
};
getByEmail = async (email) => {
const query = await this.db
.collection("MealPlannerFavs")
.where("email", "==", email)
.get();
const snapshot = query.docs[0];
return snapshot.data();
};
}

View file

@ -0,0 +1,5 @@
import Firebase from "./firebase";
import FirebaseContext, { useFirebase } from "./context";
export default Firebase;
export { FirebaseContext, useFirebase };

View file

@ -1,4 +0,0 @@
{
"domain": "chefs-meal-planner.eu.auth0.com",
"clientId": "EXe8HCfFd0jSSfqzjAvpdk72ce0y2Hh9"
}