mirror of
https://github.com/rjNemo/meal_planner
synced 2026-06-12 13:26:45 +00:00
feat: remove login and profile
This commit is contained in:
parent
09b69aeccb
commit
0ce8b1cfc2
15 changed files with 16 additions and 390 deletions
24
src/App.tsx
24
src/App.tsx
|
|
@ -1,21 +1,11 @@
|
||||||
import { PreLoader } from "./components/PreLoader";
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import MainLayout from "./layouts/MainLayout";
|
import MainLayout from "./layouts/MainLayout";
|
||||||
import { AppRouter, Router } from "./router";
|
import { AppRouter, Router } from "./router";
|
||||||
import { useAuth0 } from "./utils/auth0-spa";
|
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => (
|
||||||
const { loading } = useAuth0();
|
<Router>
|
||||||
|
<MainLayout>
|
||||||
return loading ? (
|
<AppRouter />
|
||||||
<div className="container center-align valign-wrapper">
|
</MainLayout>
|
||||||
<PreLoader />
|
</Router>
|
||||||
</div>
|
);
|
||||||
) : (
|
|
||||||
<Router>
|
|
||||||
<MainLayout>
|
|
||||||
<AppRouter />
|
|
||||||
</MainLayout>
|
|
||||||
</Router>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
import { MouseEventHandler } from "react";
|
import { MouseEventHandler } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { buttonURL, links } from "../constants";
|
import { buttonURL, links } from "../constants";
|
||||||
import ChefImage from "../images/chef.svg";
|
|
||||||
import SpecialEventImage from "../images/special_event.svg";
|
import SpecialEventImage from "../images/special_event.svg";
|
||||||
import { useAuth0 } from "../utils/auth0-spa";
|
|
||||||
import { FooterLink } from "./FooterLink";
|
import { FooterLink } from "./FooterLink";
|
||||||
import { RandomButton } from "./RandomButton";
|
import { RandomButton } from "./RandomButton";
|
||||||
|
|
||||||
|
|
@ -13,7 +11,6 @@ type Props = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SideNav = ({ showNav, closeNavClick }: Props) => {
|
export const SideNav = ({ showNav, closeNavClick }: Props) => {
|
||||||
const { isAuthenticated, user } = useAuth0();
|
|
||||||
let transformStyle = {
|
let transformStyle = {
|
||||||
transform: showNav ? "translateX(0%)" : "translateX(-105%)",
|
transform: showNav ? "translateX(0%)" : "translateX(-105%)",
|
||||||
transition: "0.5s",
|
transition: "0.5s",
|
||||||
|
|
@ -44,18 +41,6 @@ export const SideNav = ({ showNav, closeNavClick }: Props) => {
|
||||||
<i className="material-icons right" onClick={closeNavClick}>
|
<i className="material-icons right" onClick={closeNavClick}>
|
||||||
close
|
close
|
||||||
</i>
|
</i>
|
||||||
|
|
||||||
<Link to="/profile">
|
|
||||||
{isAuthenticated ? (
|
|
||||||
<div>
|
|
||||||
<img className="circle" src={user.picture} alt="user_avatar" />
|
|
||||||
<span className="white-text name">{user.name}</span>
|
|
||||||
<span className="white-text email">{user.email}</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<img className="circle" src={ChefImage} alt="user_avatar" />
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
@ -73,7 +58,6 @@ export const SideNav = ({ showNav, closeNavClick }: Props) => {
|
||||||
{links.map((link, i) => (
|
{links.map((link, i) => (
|
||||||
<FooterLink key={i} link={link} />
|
<FooterLink key={i} link={link} />
|
||||||
))}
|
))}
|
||||||
{isAuthenticated && <FooterLink link="profile" />}
|
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -7,14 +7,13 @@ type Props = {
|
||||||
ingredients: string[][];
|
ingredients: string[][];
|
||||||
recipe: string;
|
recipe: string;
|
||||||
meal: Meal;
|
meal: Meal;
|
||||||
handleFavChange: () => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MealPage = ({ meal, ingredients, recipe, handleFavChange }: Props) => (
|
export const MealPage = ({ meal, ingredients, recipe }: Props) => (
|
||||||
<section className="container">
|
<section className="container">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col s12 l6">
|
<div className="col s12 l6">
|
||||||
<MealPresentation meal={meal} handleFavChange={handleFavChange} />
|
<MealPresentation meal={meal} />
|
||||||
</div>
|
</div>
|
||||||
<div className="col s12 l6">
|
<div className="col s12 l6">
|
||||||
<MealIngredientList ingredients={ingredients} />
|
<MealIngredientList ingredients={ingredients} />
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,10 @@ import { Meal } from "../../../types/meal";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
meal: Meal;
|
meal: Meal;
|
||||||
handleFavChange: () => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const MealPresentation = ({
|
export const MealPresentation = ({
|
||||||
meal: { mealName, imgAddress, videoAddress, mealCategory, mealArea, isFav },
|
meal: { mealName, imgAddress, videoAddress, mealCategory, mealArea },
|
||||||
handleFavChange,
|
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return (
|
return (
|
||||||
<div className="row">
|
<div className="row">
|
||||||
|
|
@ -36,17 +34,6 @@ export const MealPresentation = ({
|
||||||
<div className="chip">
|
<div className="chip">
|
||||||
<b>Origin:</b> {mealArea}
|
<b>Origin:</b> {mealArea}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="chip">
|
|
||||||
<b>{isFav ? "Remove from favourites" : "Add to favourites"}:</b>
|
|
||||||
|
|
||||||
<Link to="#">
|
|
||||||
{" "}
|
|
||||||
<i className="material-icons tiny" onClick={handleFavChange}>
|
|
||||||
{isFav ? "favorite" : "favorite_border"}
|
|
||||||
</i>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect } from "react";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import { useFirebase } from "../../services/Firebase";
|
|
||||||
import { useMeal } from "../../store/meal";
|
import { useMeal } from "../../store/meal";
|
||||||
import { fetchMeal, fetchRandomMeal } from "../../store/meal/async";
|
import { fetchMeal, fetchRandomMeal } from "../../store/meal/async";
|
||||||
import { useAuth0 } from "../../utils/auth0-spa";
|
|
||||||
import { NotFound } from "../NotFound";
|
import { NotFound } from "../NotFound";
|
||||||
import { MealPage } from "./components/MealPage";
|
import { MealPage } from "./components/MealPage";
|
||||||
import { buildIngredientList, buildMealProps } from "./service";
|
import { buildIngredientList, buildMealProps } from "./service";
|
||||||
|
|
||||||
export const Meal = () => {
|
export const Meal = () => {
|
||||||
// hooks
|
// hooks
|
||||||
const { user, isAuthenticated } = useAuth0();
|
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const { state, dispatch } = useMeal();
|
const { state, dispatch } = useMeal();
|
||||||
const fb = useFirebase();
|
|
||||||
// local state
|
|
||||||
const [isFav, setIsFav] = useState<boolean>();
|
|
||||||
// variables
|
// variables
|
||||||
const mealItem = state.meals?.[0];
|
const mealItem = state.meals?.[0];
|
||||||
// effects
|
// effects
|
||||||
|
|
@ -24,30 +18,7 @@ export const Meal = () => {
|
||||||
!id ? fetchRandomMeal(dispatch) : fetchMeal(dispatch, id);
|
!id ? fetchRandomMeal(dispatch) : fetchMeal(dispatch, id);
|
||||||
}, [id, dispatch]);
|
}, [id, dispatch]);
|
||||||
|
|
||||||
/** Updates fav status in db */
|
const item = buildMealProps(mealItem);
|
||||||
useEffect(() => {
|
|
||||||
if (isAuthenticated) {
|
|
||||||
fb?.isFav(user.email, mealItem?.idMeal).then((res) => setIsFav(res));
|
|
||||||
}
|
|
||||||
}, [user, fb, mealItem?.idMeal, isAuthenticated]);
|
|
||||||
// other logic
|
|
||||||
const handleFavChange = () => {
|
|
||||||
if (isAuthenticated) {
|
|
||||||
setIsFav(!isFav);
|
|
||||||
// Send !isFav because state is not yet updated
|
|
||||||
fb.addToFavs(
|
|
||||||
user?.email,
|
|
||||||
mealItem?.idMeal,
|
|
||||||
mealItem?.strMeal,
|
|
||||||
mealItem?.strMealThumb,
|
|
||||||
!isFav
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
window.alert("You must be authenticated to add to favourites.");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const item = buildMealProps(mealItem, isFav!);
|
|
||||||
const ingredients = buildIngredientList(mealItem);
|
const ingredients = buildIngredientList(mealItem);
|
||||||
|
|
||||||
return !!state.meals ? (
|
return !!state.meals ? (
|
||||||
|
|
@ -55,7 +26,6 @@ export const Meal = () => {
|
||||||
meal={item}
|
meal={item}
|
||||||
ingredients={ingredients}
|
ingredients={ingredients}
|
||||||
recipe={mealItem?.strInstructions}
|
recipe={mealItem?.strInstructions}
|
||||||
handleFavChange={handleFavChange}
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<NotFound />
|
<NotFound />
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,10 @@ export const buildIngredientList = (mealItem: MealApi): string[][] => {
|
||||||
return ingredients;
|
return ingredients;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const buildMealProps = (mealItem: MealApi, isFav: boolean) => ({
|
export const buildMealProps = (mealItem: MealApi) => ({
|
||||||
mealName: mealItem?.strMeal,
|
mealName: mealItem?.strMeal,
|
||||||
imgAddress: mealItem?.strMealThumb,
|
imgAddress: mealItem?.strMealThumb,
|
||||||
videoAddress: mealItem?.strYoutube,
|
videoAddress: mealItem?.strYoutube,
|
||||||
mealCategory: mealItem?.strCategory,
|
mealCategory: mealItem?.strCategory,
|
||||||
mealArea: mealItem?.strArea,
|
mealArea: mealItem?.strArea,
|
||||||
isFav,
|
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { CardEntry } from "../../../components/CardEntry";
|
|
||||||
import { MealSummary } from "../../../types/meal";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
user: any;
|
|
||||||
meals: MealSummary[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ProfilePage = ({ user, meals }: Props) => (
|
|
||||||
<div className="container">
|
|
||||||
<div className="row valign-wrapper">
|
|
||||||
<img className="left circle responsive-img" src={user.picture} alt="Avatar" width="15%" />
|
|
||||||
<h2 className="col s9">{user.name}</h2>
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<b>Email: </b>
|
|
||||||
{user.email}
|
|
||||||
<h3>Favourites meals</h3>
|
|
||||||
<ul>
|
|
||||||
{meals?.map((meal) => (
|
|
||||||
<CardEntry key={meal.idMeal} meal={meal} />
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import { useEffect, useState } from "react";
|
|
||||||
import { PreLoader } from "../../components/PreLoader";
|
|
||||||
import { useFirebase } from "../../services/Firebase";
|
|
||||||
import { MealSummary } from "../../types/meal";
|
|
||||||
import { useAuth0 } from "../../utils/auth0-spa";
|
|
||||||
import { ProfilePage } from "./components/ProfilePage";
|
|
||||||
|
|
||||||
export const Profile = () => {
|
|
||||||
const { loading, user } = useAuth0();
|
|
||||||
const [favs, setFavs] = useState([] as MealSummary[]);
|
|
||||||
const db = useFirebase();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
db.getByEmail(user.email).then((res) => {
|
|
||||||
setFavs(res.favs);
|
|
||||||
});
|
|
||||||
}, [db, user.email]);
|
|
||||||
|
|
||||||
return loading || !user ? ( // is caught by PrivateRoute
|
|
||||||
<div className="container center-align">
|
|
||||||
<PreLoader />
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<ProfilePage user={user} meals={favs} />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -3,33 +3,12 @@ import ReactDOM from "react-dom";
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { App } from "./App";
|
import { App } from "./App";
|
||||||
import * as serviceWorker from "./serviceWorker";
|
import * as serviceWorker from "./serviceWorker";
|
||||||
import { Auth0Provider } from "./utils/auth0-spa";
|
|
||||||
import history from "./utils/history";
|
|
||||||
import { FirebaseContext } from "./services/Firebase";
|
|
||||||
import { AppProvider } from "./store/meal";
|
import { AppProvider } from "./store/meal";
|
||||||
|
|
||||||
const onRedirectCallBack = (appState) => {
|
|
||||||
history.push(
|
|
||||||
appState && appState.targetUrl
|
|
||||||
? appState.targetUrl
|
|
||||||
: window.location.pathname
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<Auth0Provider
|
<AppProvider>
|
||||||
domain={process.env.REACT_APP_DOMAIN}
|
<App />
|
||||||
client_id={process.env.REACT_APP_CLIENT_ID}
|
</AppProvider>,
|
||||||
redirect_uri={window.location.origin}
|
|
||||||
onRedirectCallBack={onRedirectCallBack}
|
|
||||||
>
|
|
||||||
{/*<FirebaseContext.Provider value={new Firebase()}> todo fix Firebase app*/}
|
|
||||||
<FirebaseContext.Provider>
|
|
||||||
<AppProvider>
|
|
||||||
<App />
|
|
||||||
</AppProvider>
|
|
||||||
</FirebaseContext.Provider>
|
|
||||||
</Auth0Provider>,
|
|
||||||
document.getElementById("root")
|
document.getElementById("root")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,7 @@ import { Contact } from "../containers/Contact";
|
||||||
import { Home } from "../containers/Home";
|
import { Home } from "../containers/Home";
|
||||||
import { Meal } from "../containers/Meal";
|
import { Meal } from "../containers/Meal";
|
||||||
import { NotFound } from "../containers/NotFound";
|
import { NotFound } from "../containers/NotFound";
|
||||||
import { Profile } from "../containers/Profile";
|
|
||||||
import { Search } from "../containers/Search";
|
import { Search } from "../containers/Search";
|
||||||
import { PrivateRoute } from "./PrivateRoute";
|
|
||||||
|
|
||||||
export const AppRouter = () => (
|
export const AppRouter = () => (
|
||||||
<Switch>
|
<Switch>
|
||||||
|
|
@ -16,8 +14,6 @@ export const AppRouter = () => (
|
||||||
<Home />
|
<Home />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
<PrivateRoute exact path="/profile" component={Profile} />
|
|
||||||
|
|
||||||
<Route exact path={buttonURL}>
|
<Route exact path={buttonURL}>
|
||||||
<Meal />
|
<Meal />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import { FC, useEffect } from "react";
|
|
||||||
import { Route, RouteProps } from "react-router-dom";
|
|
||||||
import { useAuth0 } from "../utils/auth0-spa";
|
|
||||||
|
|
||||||
type Props = { component: FC } & RouteProps;
|
|
||||||
|
|
||||||
export const PrivateRoute = ({ component: Component, path, ...rest }: Props) => {
|
|
||||||
const { loading, isAuthenticated, loginWithRedirect } = useAuth0();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// catches infinite loading when no user is logged in
|
|
||||||
if (loading || isAuthenticated) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const fn = async () => await loginWithRedirect({ appState: { targetUrl: path } });
|
|
||||||
fn();
|
|
||||||
}, [loading, isAuthenticated, loginWithRedirect, path]);
|
|
||||||
|
|
||||||
const render = (props: any) => (isAuthenticated ? <Component {...props} /> : null);
|
|
||||||
|
|
||||||
return <Route path={path} render={render} {...rest} />;
|
|
||||||
};
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
import { createContext, useContext } from "react";
|
|
||||||
import Firebase from "./firebase";
|
|
||||||
|
|
||||||
// create a Firebase context to make state available anywhere in the App.
|
|
||||||
const FirebaseContext = createContext(new Firebase());
|
|
||||||
|
|
||||||
export const useFirebase = () => useContext(FirebaseContext);
|
|
||||||
export default FirebaseContext;
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
||||||
import app from "firebase/app";
|
|
||||||
import "firebase/firestore";
|
|
||||||
|
|
||||||
const CONFIG = {
|
|
||||||
apiKey: process.env.REACT_APP_API_KEY,
|
|
||||||
authDomain: process.env.REACT_APP_AUTH_DOMAIN,
|
|
||||||
databaseURL: process.env.REACT_APP_DB_URL,
|
|
||||||
projectId: process.env.REACT_APP_PROJECT_ID,
|
|
||||||
storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
|
|
||||||
messagingSenderId: process.env.REACT_APP_MSG_SENDER_ID,
|
|
||||||
appId: process.env.REACT_APP_APP_ID,
|
|
||||||
measurementId: process.env.REACT_APP_MEASUREMENT_ID,
|
|
||||||
};
|
|
||||||
|
|
||||||
const FAVS = "favs";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Firebase initializes the Application and provides method to interact with
|
|
||||||
* Firebase services as auth and firestore.
|
|
||||||
*/
|
|
||||||
export default class Firebase {
|
|
||||||
#db: any;
|
|
||||||
#collection: any;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
app.initializeApp(CONFIG);
|
|
||||||
this.#db = app.firestore();
|
|
||||||
this.#collection = this.#db.collection("mealPlannerUsers");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get infos for user 'email'.
|
|
||||||
*/
|
|
||||||
getByEmail = async (email: string) => {
|
|
||||||
const infos = await this.#collection
|
|
||||||
.where("email", "==", email)
|
|
||||||
.limit(1)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
const favs = await this.getFavsByEmail(email);
|
|
||||||
|
|
||||||
return { infos, favs };
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get user's favourite recipes
|
|
||||||
* */
|
|
||||||
getFavsByEmail = async (email: string) => {
|
|
||||||
let favs = [] as any[];
|
|
||||||
const query = await this.#collection
|
|
||||||
.doc(email)
|
|
||||||
.collection(FAVS)
|
|
||||||
.where("isFav", "==", true)
|
|
||||||
.limit(10)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
query.forEach((doc: any) => favs.push(doc.data()));
|
|
||||||
|
|
||||||
return favs;
|
|
||||||
};
|
|
||||||
|
|
||||||
isFav = async (email: string, idMeal: string) => {
|
|
||||||
const query = await this.#collection
|
|
||||||
.doc(email)
|
|
||||||
.collection(FAVS)
|
|
||||||
.doc(idMeal)
|
|
||||||
.get();
|
|
||||||
|
|
||||||
const obj = query.data();
|
|
||||||
return obj?.isFav;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create or update favourite status for an authenticated user.
|
|
||||||
*/
|
|
||||||
addToFavs = async (
|
|
||||||
email: string,
|
|
||||||
idMeal: string,
|
|
||||||
strMeal: string,
|
|
||||||
strMealThumb: string,
|
|
||||||
isFav: boolean
|
|
||||||
) => {
|
|
||||||
this.#collection
|
|
||||||
.doc(email)
|
|
||||||
.collection(FAVS)
|
|
||||||
.doc(idMeal)
|
|
||||||
.set({
|
|
||||||
email,
|
|
||||||
idMeal,
|
|
||||||
strMeal,
|
|
||||||
strMealThumb,
|
|
||||||
isFav,
|
|
||||||
})
|
|
||||||
.catch((err: any) => console.error("Error adding favs to database", err));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
// This file centralizes all Firebase related exports
|
|
||||||
|
|
||||||
import Firebase from "./firebase";
|
|
||||||
import FirebaseContext, { useFirebase } from "./context";
|
|
||||||
|
|
||||||
export default Firebase;
|
|
||||||
export { FirebaseContext, useFirebase };
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
||||||
// adapted from: https://auth0.com/docs/quickstart/spa/react
|
|
||||||
import React, { useContext, useState, useEffect } from "react";
|
|
||||||
import createAuth0Client from "@auth0/auth0-spa-js";
|
|
||||||
|
|
||||||
const DEFAULT_REDIRECT_CALLBACK = () => {
|
|
||||||
window.history.replaceState({}, document.title, window.location.pathname);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Auth0Context = React.createContext();
|
|
||||||
export const useAuth0 = () => useContext(Auth0Context);
|
|
||||||
|
|
||||||
export const Auth0Provider = ({
|
|
||||||
children,
|
|
||||||
onRedirectCallBack = DEFAULT_REDIRECT_CALLBACK,
|
|
||||||
...initOptions
|
|
||||||
}) => {
|
|
||||||
const [isAuthenticated, setIsAuthenticated] = useState();
|
|
||||||
const [user, setUser] = useState();
|
|
||||||
const [auth0Client, setAuth0] = useState();
|
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [popUpOpen, setPopUpOpen] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const initAuth0 = async () => {
|
|
||||||
const auth0FromHook = await createAuth0Client(initOptions);
|
|
||||||
setAuth0(auth0FromHook);
|
|
||||||
|
|
||||||
if (
|
|
||||||
window.location.search.includes("code=") &&
|
|
||||||
window.location.search.includes("state=")
|
|
||||||
) {
|
|
||||||
const { appState } = await auth0FromHook.handleRedirectCallback();
|
|
||||||
onRedirectCallBack(appState);
|
|
||||||
}
|
|
||||||
|
|
||||||
const isAuthenticated = await auth0FromHook.isAuthenticated();
|
|
||||||
setIsAuthenticated(isAuthenticated);
|
|
||||||
|
|
||||||
if (isAuthenticated) {
|
|
||||||
const user = await auth0FromHook.getUser();
|
|
||||||
setUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoading(false);
|
|
||||||
};
|
|
||||||
initAuth0();
|
|
||||||
// eslint-disable-next-line
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const loginWithPopUp = async (params = {}) => {
|
|
||||||
setPopUpOpen(true);
|
|
||||||
try {
|
|
||||||
await auth0Client.loginWithPopUp(params);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
setPopUpOpen(false);
|
|
||||||
}
|
|
||||||
const user = auth0Client.getUser();
|
|
||||||
setUser(user);
|
|
||||||
setIsAuthenticated(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleRedirectCallback = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
await auth0Client.handleRedirectCallback();
|
|
||||||
const user = auth0Client.getUser();
|
|
||||||
setLoading(false);
|
|
||||||
setIsAuthenticated(true);
|
|
||||||
setUser(user);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Auth0Context.Provider
|
|
||||||
value={{
|
|
||||||
isAuthenticated,
|
|
||||||
user,
|
|
||||||
loading,
|
|
||||||
popUpOpen,
|
|
||||||
loginWithPopUp,
|
|
||||||
handleRedirectCallback,
|
|
||||||
getIdTokenClaims: (...props) => auth0Client.getIdTokenClaims(...props),
|
|
||||||
loginWithRedirect: (...props) =>
|
|
||||||
auth0Client.loginWithRedirect(...props),
|
|
||||||
getTokenWithPopUp: (...props) =>
|
|
||||||
auth0Client.getTokenWithPopUp(...props),
|
|
||||||
logout: (...props) => auth0Client.logout(...props)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Auth0Context.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
Loading…
Reference in a new issue