minor refactorings

This commit is contained in:
Ruidy 2021-09-25 15:40:11 +02:00
parent 2ac94f24f1
commit fecfc95982
45 changed files with 152 additions and 297 deletions

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { PreLoader } from "./components/PreLoader";
import "./index.css";
import MainLayout from "./layouts/MainLayout";
@ -6,7 +5,7 @@ import { AppRouter } from "./router";
import { Router } from "./router/Router";
import { useAuth0 } from "./utils/auth0-spa";
export const App: FC = () => {
export const App = () => {
const { loading } = useAuth0();
return loading ? (

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { Link } from "react-router-dom";
import { MealSummary } from "../types/meal";
@ -7,22 +6,22 @@ type Props = {
className?: string;
};
export const CardEntry: FC<Props> = ({ meal, className = "col s12 m6" }) => {
const { idMeal, strMeal, strMealThumb } = meal;
return (
<Link to={`/${idMeal}`}>
<li>
<div className={className}>
<div className="card hoverable">
<div className="card-image">
<img src={strMealThumb} alt={strMeal} />
</div>
<div className="card-content">
<h4>{strMeal}</h4>
</div>
export const CardEntry = ({
meal: { idMeal, strMeal, strMealThumb },
className = "col s12 m6",
}: Props) => (
<Link to={`/${idMeal}`}>
<li>
<div className={className}>
<div className="card hoverable">
<div className="card-image">
<img src={strMealThumb} alt={strMeal} />
</div>
<div className="card-content">
<h4>{strMeal}</h4>
</div>
</div>
</li>
</Link>
);
};
</div>
</li>
</Link>
);

View file

@ -1,8 +1,6 @@
import { FC } from "react";
export const CopyrightText: FC = () => (
export const CopyrightText = () => (
<span className="grey-text text-darken-1">
© 2020 - <span className="logo">Chef's</span> - Made with{" "}
© {new Date().getFullYear()} - <span className="logo">Chef's</span> - Made with{" "}
<span role="img" aria-label="heart">
</span>

View file

@ -1,10 +1,9 @@
import { FC } from "react";
import { links } from "../constants";
import { CopyrightText } from "./CopyrightText";
import { FooterLink } from "./FooterLink";
import { GitHubLink } from "./GitHubLink";
export const Footer: FC = () => {
export const Footer = () => {
const footerLinks = [...links, "random"];
return (
<footer className="page-footer">

View file

@ -1,20 +1,16 @@
import { FC } from "react";
import { Link } from "react-router-dom";
import { upFirstChar } from "../utils/methods";
import { upFirstChar } from "../utils/string";
type Props = {
link: string;
textColor?: string;
};
export const FooterLink: FC<Props> = ({ link, textColor = "" }) => {
export const FooterLink = ({ link, textColor = "" }: Props) => {
const textColorClass = `${textColor}-text`;
return (
<li>
<Link
className={`${textColorClass} waves-effect text-lighten-3`}
to={`/${link}`}
>
<Link className={`${textColorClass} waves-effect text-lighten-3`} to={`/${link}`}>
{upFirstChar(link)}
</Link>
</li>

View file

@ -1,6 +1,4 @@
import { FC } from "react";
export const GitHubLink: FC = () => (
export const GitHubLink = () => (
<a
className="grey-text text-darken-1 right"
href="https://github.com/rjNemo/meal_planner"

View file

@ -1,20 +1,13 @@
import { FC } from "react";
import { useAuth0 } from "../utils/auth0-spa";
type Props = {
color: string;
};
type Props = { color: string };
export const LogInButton: FC<Props> = ({ color }) => {
export const LogInButton = ({ color }: Props) => {
const { loginWithRedirect } = useAuth0();
const handleClick = () => {
loginWithRedirect({});
};
const handleClick = () => loginWithRedirect({});
return (
<button
className={`waves-effect waves-light btn ${color}`}
onClick={handleClick}
>
<button className={`waves-effect waves-light btn ${color}`} onClick={handleClick}>
Log in
</button>
);

View file

@ -1,11 +1,9 @@
import { FC } from "react";
import { useAuth0 } from "../utils/auth0-spa";
export const LogOutButton: FC = () => {
export const LogOutButton = () => {
const { logout } = useAuth0();
const handleClick = () => {
logout();
};
const handleClick = () => logout();
return (
<button className="waves-effect waves-teal btn-flat" onClick={handleClick}>
Log out

View file

@ -1,16 +1,13 @@
import { FC } from "react";
import { Link } from "react-router-dom";
export const Logo: FC = () => {
return (
<Link to="/" className="brand-logo">
<img
src="/logo192.png"
alt="chef's logo"
height="30px"
style={{ position: "relative", top: "5px" }}
/>
<span className="logo orange-text text-accent-4">Chef's</span>
</Link>
);
};
export const Logo = () => (
<Link to="/" className="brand-logo">
<img
src="/logo192.png"
alt="chef's logo"
height="30px"
style={{ position: "relative", top: "5px" }}
/>
<span className="logo orange-text text-accent-4">Chef's</span>
</Link>
);

View file

@ -1,4 +1,4 @@
import React, { FC } from "react";
import { MouseEventHandler } from "react";
import { Link } from "react-router-dom";
import { buttonURL, links } from "../constants";
import { useAuth0 } from "../utils/auth0-spa";
@ -8,9 +8,9 @@ import { Logo } from "./Logo";
import { LogOutButton } from "./LogOutButton";
import { RandomButton } from "./RandomButton";
type Props = { openNavClick: React.MouseEventHandler };
type Props = { openNavClick: MouseEventHandler };
export const Navbar: FC<Props> = ({ openNavClick }) => {
export const Navbar = ({ openNavClick }: Props) => {
const { isAuthenticated } = useAuth0();
return (
@ -23,22 +23,12 @@ export const Navbar: FC<Props> = ({ openNavClick }) => {
{links.map((link, i) => (
<FooterLink key={i} link={link} textColor="black" />
))}
{isAuthenticated && (
<FooterLink link="profile" textColor="black" />
)}
{isAuthenticated && <FooterLink link="profile" textColor="black" />}
<li>
<RandomButton
url={buttonURL}
size="small"
color="orange darken-2"
/>
<RandomButton url={buttonURL} size="small" color="orange darken-2" />
</li>
<li>
{!isAuthenticated ? (
<LogInButton color="orange lighten-1" />
) : (
<LogOutButton />
)}
{!isAuthenticated ? <LogInButton color="orange lighten-1" /> : <LogOutButton />}
</li>
</ul>
<Link

View file

@ -1,6 +1,4 @@
import { FC } from "react";
export const PreLoader: FC = () => (
export const PreLoader = () => (
<div className="preloader-wrapper active">
<div className="spinner-layer spinner-red-only">
<div className="circle-clipper left">

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { Link } from "react-router-dom";
import { useMeal } from "../store/meal";
import { fetchRandomMeal } from "../store/meal/async";
@ -9,7 +8,7 @@ type Props = {
color?: string;
};
export const RandomButton: FC<Props> = ({ url, size = "large", color }) => {
export const RandomButton = ({ url, size = "large", color }: Props) => {
const classString = `waves-effect waves-light btn-${size} ${color}`;
const { dispatch } = useMeal();
return (

View file

@ -1,15 +1,13 @@
import React, { ChangeEvent, FC, useState } from "react";
import { ChangeEvent, MouseEventHandler, useState } from "react";
import { Link } from "react-router-dom";
import { useMeal } from "../store/meal";
import { fetchSearchResults } from "../store/meal/async";
export const SearchBar: FC = () => {
export const SearchBar = () => {
const { dispatch } = useMeal();
const [searchString, setSearchString] = useState("");
const getSearchResults: React.MouseEventHandler<HTMLButtonElement> = (e) => {
searchString === ""
? e.preventDefault()
: fetchSearchResults(dispatch, searchString);
const getSearchResults: MouseEventHandler<HTMLButtonElement> = (e) => {
searchString === "" ? e.preventDefault() : fetchSearchResults(dispatch, searchString);
};
const clearSearchBar = () => {
@ -17,10 +15,8 @@ export const SearchBar: FC = () => {
dispatch({ type: "clearSearchResults" });
};
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { value } = e.target;
const handleChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) =>
setSearchString(value);
};
return (
<div className="section">

View file

@ -1,4 +1,4 @@
import React, { FC } from "react";
import { MouseEventHandler } from "react";
import { Link } from "react-router-dom";
import { buttonURL, links } from "../constants";
import ChefImage from "../images/chef.svg";
@ -9,9 +9,12 @@ import { LogInButton } from "./LogInButton";
import { LogOutButton } from "./LogOutButton";
import { RandomButton } from "./RandomButton";
type Props = { showNav: boolean; closeNavClick: React.MouseEventHandler };
type Props = {
showNav: boolean;
closeNavClick: MouseEventHandler;
};
export const SideNav: FC<Props> = ({ showNav, closeNavClick }) => {
export const SideNav = ({ showNav, closeNavClick }: Props) => {
const { isAuthenticated, user } = useAuth0();
let transformStyle = {
transform: showNav ? "translateX(0%)" : "translateX(-105%)",
@ -32,8 +35,7 @@ export const SideNav: FC<Props> = ({ showNav, closeNavClick }) => {
left: "0",
right: "0",
bottom: "0",
backgroundColor:
"rgba(0,0,0,0.5)" /* Black background with opacity */,
backgroundColor: "rgba(0,0,0,0.5)" /* Black background with opacity */,
zIndex: 2 /* Specify a stack order in case you're using a different order for other elements */,
// cursor: "pointer" /* Add a pointer on hover */
}}
@ -65,11 +67,7 @@ export const SideNav: FC<Props> = ({ showNav, closeNavClick }) => {
</li>
<li>
<Link to="#">
{!isAuthenticated ? (
<LogInButton color="orange lighten-1" />
) : (
<LogOutButton />
)}
{!isAuthenticated ? <LogInButton color="orange lighten-1" /> : <LogOutButton />}
</Link>
</li>

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { Link, useRouteMatch } from "react-router-dom";
type Props = {
@ -6,7 +5,7 @@ type Props = {
strCategoryThumb: string;
};
const CategoriesEntry: FC<Props> = ({ strCategory, strCategoryThumb }) => {
const CategoriesEntry = ({ strCategory, strCategoryThumb }: Props) => {
const { url } = useRouteMatch();
return (

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import PageLayout from "../../../layouts/PageLayout";
import CategoriesEntry from "./CategoriesEntry";
@ -6,15 +5,11 @@ type Props = {
categories: { strCategory: string; strCategoryThumb: string }[];
};
export const CategoriesPage: FC<Props> = ({ categories }) => (
export const CategoriesPage = ({ categories }: Props) => (
<PageLayout title="Chef's Categories">
<ul>
{categories.map(({ strCategory, strCategoryThumb }, i) => (
<CategoriesEntry
key={i}
strCategory={strCategory}
strCategoryThumb={strCategoryThumb}
/>
<CategoriesEntry key={i} strCategory={strCategory} strCategoryThumb={strCategoryThumb} />
))}
</ul>
</PageLayout>

View file

@ -6,9 +6,7 @@ import { CategoriesPage } from "./components/CategoriesPage";
export const Categories = () => {
const [categories, setCategories] = useState({ categories: [] });
const getCategories = () => {
getData("categories").then((data) => setCategories(data));
};
const getCategories = () => getData("categories").then((data) => setCategories(data));
useEffect(() => {
getCategories();

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry";
import PageLayout from "../../../layouts/PageLayout";
import { MealSummary } from "../../../types/meal";
@ -8,7 +7,7 @@ type Props = {
strCategory: string;
};
export const CategoryPage: FC<Props> = ({ meals, strCategory }) => (
export const CategoryPage = ({ meals, strCategory }: Props) => (
<PageLayout title={`Chef's ${strCategory} Recipes`}>
<ul>
<div className="row">

View file

@ -1,9 +1,9 @@
import { FC, useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { Redirect, useParams } from "react-router-dom";
import { getData } from "../../services/api";
import { CategoryPage } from "./components/CategoryPage";
export const Category: FC = () => {
export const Category = () => {
const { strCategory } = useParams<{ strCategory: string }>();
const [meals, setMeals] = useState({ meals: [] });

View file

@ -1,4 +1,4 @@
import React, { FC, useState } from "react";
import { useState, FormEvent } from "react";
import { ContactFormInput } from "./ContactFormInput";
import { ContactFormSubmitButton } from "./ContactFormSubmitButton";
import { ContactFormTextArea } from "./ContactFormTextArea";
@ -7,14 +7,14 @@ type Props = {
setIsSubmitted: (value: boolean) => void;
};
export const ContactForm: FC<Props> = ({ setIsSubmitted }) => {
export const ContactForm = ({ setIsSubmitted }: Props) => {
const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState("");
const [email, setEmail] = useState("");
const [phone, setPhone] = useState("");
const [message, setMessage] = useState("");
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
setIsSubmitted(true);
};
@ -24,45 +24,20 @@ export const ContactForm: FC<Props> = ({ setIsSubmitted }) => {
<div className="row">
<div className="col s12">
<div className="col s12 m6">
<ContactFormInput
id="First Name"
value={firstName}
dispatch={setFirstName}
/>
<ContactFormInput id="First Name" value={firstName} dispatch={setFirstName} />
</div>
<div className="col s12 m6">
<ContactFormInput
id="Last Name"
value={lastName}
dispatch={setLastName}
/>
<ContactFormInput id="Last Name" value={lastName} dispatch={setLastName} />
</div>
<div className="col s12 m6">
<ContactFormInput
id="Email"
type="email"
value={email}
dispatch={setEmail}
/>
<ContactFormInput id="Email" type="email" value={email} dispatch={setEmail} />
</div>
<div className="col s12 m6">
<ContactFormInput
id="Phone"
value={phone}
type="tel"
dispatch={setPhone}
/>
<ContactFormInput id="Phone" value={phone} type="tel" dispatch={setPhone} />
</div>
<div className="col s12">
<ContactFormTextArea
id="Message"
value={message}
dispatch={setMessage}
/>
<ContactFormSubmitButton
text="Send Message"
color="orange darken-2"
/>
<ContactFormTextArea id="Message" value={message} dispatch={setMessage} />
<ContactFormSubmitButton text="Send Message" color="orange darken-2" />
</div>
</div>
</div>

View file

@ -1,19 +1,14 @@
import React, { FC } from "react";
import { ChangeEventHandler, Dispatch, SetStateAction } from "react";
type Props = {
id: string;
type?: string;
value: string;
dispatch: React.Dispatch<React.SetStateAction<string>>;
dispatch: Dispatch<SetStateAction<string>>;
};
export const ContactFormInput: FC<Props> = ({
id,
type = "text",
value,
dispatch,
}) => {
const handleChange: React.ChangeEventHandler<HTMLInputElement> = (e) => {
export const ContactFormInput = ({ id, type = "text", value, dispatch }: Props) => {
const handleChange: ChangeEventHandler<HTMLInputElement> = (e) => {
e.preventDefault();
dispatch(e.target.value);
};

View file

@ -1,16 +1,10 @@
import { FC } from "react";
type Props = {
text: string;
color: string;
};
export const ContactFormSubmitButton: FC<Props> = ({ text, color }) => (
<button
className={`waves-effect waves-light btn ${color}`}
type="submit"
name="submit"
>
export const ContactFormSubmitButton = ({ text, color }: Props) => (
<button className={`waves-effect waves-light btn ${color}`} type="submit" name="submit">
<i className="material-icons right">send</i> {text}
</button>
);

View file

@ -1,13 +1,11 @@
export function ContactFormSubmitted() {
return (
<div className="container center-align">
<img
className="responsive-img"
src={require("../../../images/mail_sent.svg")}
alt="mail_sent"
width="30%"
/>
<h4>Thank you for your message</h4>
</div>
);
}
export const ContactFormSubmitted = () => (
<div className="container center-align">
<img
className="responsive-img"
src={require("../../../images/mail_sent.svg")}
alt="mail_sent"
width="30%"
/>
<h4>Thank you for your message</h4>
</div>
);

View file

@ -1,13 +1,13 @@
import React, { FC } from "react";
import { ChangeEventHandler, Dispatch, FC, SetStateAction } from "react";
type Props = {
id: string;
value: string;
dispatch: React.Dispatch<React.SetStateAction<string>>;
dispatch: Dispatch<SetStateAction<string>>;
};
export const ContactFormTextArea: FC<Props> = ({ id, value, dispatch }) => {
const handleChange: React.ChangeEventHandler<HTMLTextAreaElement> = (e) => {
const handleChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
e.preventDefault();
dispatch(e.target.value);
};

View file

@ -1,9 +1,9 @@
import { FC, useState } from "react";
import { useState } from "react";
import PageLayout from "../../layouts/PageLayout";
import { ContactForm } from "./components/ContactForm";
import { ContactFormSubmitted } from "./components/ContactFormSubmitted";
export const Contact: FC = () => {
export const Contact = () => {
const [isSubmitted, setIsSubmitted] = useState(false);
return isSubmitted ? (

View file

@ -1,9 +1,8 @@
import { FC } from "react";
import { RandomButton } from "../../components/RandomButton";
import { buttonURL } from "../../constants";
import HeroImage from "../../images/chef.svg";
export const Home: FC = () => (
export const Home = () => (
<section className="container ">
<div className="row">
<div className="col s12 m6">

View file

@ -1,10 +1,6 @@
import { FC } from "react";
type Props = { ingredients: string[][] };
type Props = {
ingredients: string[][];
};
export const MealIngredientList: FC<Props> = ({ ingredients }) => (
export const MealIngredientList = ({ ingredients }: Props) => (
<div className="ingredientList">
<table className="striped highlight responsive-table">
<thead>

View file

@ -1,5 +1,4 @@
import { FC } from "react";
import Meal from "../../../types/meal";
import { Meal } from "../../../types/meal";
import { MealIngredientList } from "./MealIngredientList";
import { MealPresentation } from "./MealPresentation";
import { MealRecipe } from "./MealRecipe";
@ -11,12 +10,7 @@ type Props = {
handleFavChange: () => void;
};
export const MealPage: FC<Props> = ({
meal,
ingredients,
recipe,
handleFavChange,
}) => (
export const MealPage = ({ meal, ingredients, recipe, handleFavChange }: Props) => (
<section className="container">
<div className="row">
<div className="col s12 l6">

View file

@ -1,22 +1,15 @@
import { FC } from "react";
import { Link } from "react-router-dom";
import Meal from "../../../types/meal";
import { Meal } from "../../../types/meal";
type Props = {
meal: Meal;
handleFavChange: () => void;
};
export const MealPresentation: FC<Props> = ({ meal, handleFavChange }) => {
const {
mealName,
imgAddress,
videoAddress,
mealCategory,
mealArea,
isFav,
} = meal;
export const MealPresentation = ({
meal: { mealName, imgAddress, videoAddress, mealCategory, mealArea, isFav },
handleFavChange,
}: Props) => {
return (
<div className="row">
<div className="col s12">
@ -45,16 +38,11 @@ export const MealPresentation: FC<Props> = ({ meal, handleFavChange }) => {
</div>
<div className="chip">
<b>
{isFav ? "Remove from favourites" : "Add to favourites"}:
</b>
<b>{isFav ? "Remove from favourites" : "Add to favourites"}:</b>
<Link to="#">
{" "}
<i
className="material-icons tiny"
onClick={handleFavChange}
>
<i className="material-icons tiny" onClick={handleFavChange}>
{isFav ? "favorite" : "favorite_border"}
</i>
</Link>

View file

@ -1,10 +1,6 @@
import { FC } from "react";
type Props = { recipe: string };
type Props = {
recipe: string;
};
export const MealRecipe: FC<Props> = ({ recipe }) => (
export const MealRecipe = ({ recipe }: Props) => (
<div className="recipe">
<div className="divider" />
<h3>Instructions</h3>

View file

@ -1,4 +1,4 @@
import { FC, useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { useFirebase } from "../../services/Firebase";
import { useMeal } from "../../store/meal";
@ -8,7 +8,7 @@ import { NotFound } from "../NotFound";
import { MealPage } from "./components/MealPage";
import { buildIngredientList, buildMealProps } from "./service";
export const Meal: FC = () => {
export const Meal = () => {
// hooks
const { user, isAuthenticated } = useAuth0();
const { id } = useParams<{ id: string }>();

View file

@ -1,7 +1,6 @@
import { FC } from "react";
import { RandomButton } from "../../components/RandomButton";
export const NotFound: FC = () => (
export const NotFound = () => (
<div className="container center-align">
<div className="row">
<h1>Wrong Way!</h1>

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry";
import { MealSummary } from "../../../types/meal";
@ -7,15 +6,10 @@ type Props = {
meals: MealSummary[];
};
export const ProfilePage: FC<Props> = ({ user, meals }) => (
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%"
/>
<img className="left circle responsive-img" src={user.picture} alt="Avatar" width="15%" />
<h2 className="col s9">{user.name}</h2>
</div>
<div className="row">

View file

@ -1,11 +1,11 @@
import { FC, useEffect, useState } from "react";
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: FC = () => {
export const Profile = () => {
const { loading, user } = useAuth0();
const [favs, setFavs] = useState([] as MealSummary[]);
const db = useFirebase();

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import BreakfastImage from "../../../images/breakfast.svg";
import PageLayout from "../../../layouts/PageLayout";
import { MealSummary } from "../../../types/meal";
@ -9,13 +8,11 @@ type Props = {
searchResults: MealSummary[];
};
export const SearchPage: FC<Props> = ({ searchString, searchResults }) => (
export const SearchPage = ({ searchString, searchResults }: Props) => (
<PageLayout title={`Results for: ${searchString}`}>
{!searchResults ? (
<div className="center-align">
<p>
No results to display, instead there is a picture of my breakfast.
</p>
<p>No results to display, instead there is a picture of my breakfast.</p>
<img src={BreakfastImage} alt="Nothing here!" width="70%" />
</div>
) : (

View file

@ -1,9 +1,6 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry";
import { MealSummary } from "../../../types/meal";
type Props = {
meal: MealSummary;
};
type Props = { meal: MealSummary };
export const SearchResult: FC<Props> = ({ meal }) => <CardEntry meal={meal} />;
export const SearchResult = ({ meal }: Props) => <CardEntry meal={meal} />;

View file

@ -1,13 +1,9 @@
import { FC } from "react";
import { useMeal } from "../../store/meal";
import { SearchPage } from "./components/SearchPage";
export const Search: FC = () => {
const { state } = useMeal();
return (
<SearchPage
searchString={state.searchString}
searchResults={state.search}
/>
);
export const Search = () => {
const {
state: { searchString, search },
} = useMeal();
return <SearchPage searchString={searchString} searchResults={search} />;
};

View file

@ -1,4 +1,4 @@
import React, { FC, useState } from "react";
import { FC, MouseEvent, MouseEventHandler, useState } from "react";
import { Footer } from "../components/Footer";
import { Navbar } from "../components/Navbar";
import { SearchBar } from "../components/SearchBar";
@ -7,20 +7,20 @@ import { SideNav } from "../components/SideNav";
const MainLayout: FC = ({ children }) => {
const [showNav, setShowNav] = useState(false);
const openNavClick: React.MouseEventHandler = (e) => {
const openNavClick: MouseEventHandler = (e) => {
e.preventDefault();
setShowNav(true);
document.addEventListener("keydown", handleEscKey);
};
const closeNavClick = (e: React.MouseEvent) => {
const closeNavClick = (e: MouseEvent) => {
e.preventDefault();
setShowNav(false);
document.removeEventListener("keydown", handleEscKey);
};
const handleEscKey = (e: KeyboardEvent) => {
if (e.key === "Escape") {
const handleEscKey = ({ key }: KeyboardEvent) => {
if (key === "Escape") {
setShowNav(false);
}
};

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { Redirect, Route, Switch } from "react-router-dom";
import { buttonURL } from "../constants";
import { Categories } from "../containers/Categories";
@ -11,7 +10,7 @@ import { Profile } from "../containers/Profile";
import { Search } from "../containers/Search";
import { PrivateRoute } from "./PrivateRoute";
const AppRouter: FC = () => (
export const AppRouter = () => (
<Switch>
<Route exact path="/">
<Home />
@ -52,5 +51,3 @@ const AppRouter: FC = () => (
</Route>
</Switch>
);
export default AppRouter;

View file

@ -2,15 +2,9 @@ import { FC, useEffect } from "react";
import { Route, RouteProps } from "react-router-dom";
import { useAuth0 } from "../utils/auth0-spa";
type Props = {
component: FC;
} & RouteProps;
type Props = { component: FC } & RouteProps;
export const PrivateRoute: FC<Props> = ({
component: Component,
path,
...rest
}) => {
export const PrivateRoute = ({ component: Component, path, ...rest }: Props) => {
const { loading, isAuthenticated, loginWithRedirect } = useAuth0();
useEffect(() => {
@ -25,8 +19,7 @@ export const PrivateRoute: FC<Props> = ({
fn();
}, [loading, isAuthenticated, loginWithRedirect, path]);
const render = (props: any) =>
isAuthenticated ? <Component {...props} /> : null;
const render = (props: any) => (isAuthenticated ? <Component {...props} /> : null);
return <Route path={path} render={render} {...rest} />;
};

View file

@ -1,2 +1 @@
import AppRouter from "./AppRouter";
export { AppRouter };
export { AppRouter } from "./AppRouter";

View file

@ -23,10 +23,13 @@ const createURI = (keyword: string, option?: Option) => {
}
};
export const getData = (keyword: string, option?: Option) => {
export const getData = async (keyword: string, option?: Option) => {
const URI = createURI(keyword, option);
return fetch(URI)
.then((response) => response.json())
.catch((error) => console.warn(error + "url:" + URI));
try {
const response = await fetch(URI);
return await response.json();
} catch (error) {
return console.warn(error + "url:" + URI);
}
};

View file

@ -1,5 +1 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom/extend-expect';
import "@testing-library/jest-dom/extend-expect";

View file

@ -1,4 +1,4 @@
export default interface Meal {
export interface Meal {
mealName: string;
imgAddress: string;
videoAddress: string;