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

View file

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

View file

@ -1,8 +1,6 @@
import { FC } from "react"; export const CopyrightText = () => (
export const CopyrightText: FC = () => (
<span className="grey-text text-darken-1"> <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 role="img" aria-label="heart">
</span> </span>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useMeal } from "../store/meal"; import { useMeal } from "../store/meal";
import { fetchRandomMeal } from "../store/meal/async"; import { fetchRandomMeal } from "../store/meal/async";
@ -9,7 +8,7 @@ type Props = {
color?: string; 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 classString = `waves-effect waves-light btn-${size} ${color}`;
const { dispatch } = useMeal(); const { dispatch } = useMeal();
return ( 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 { Link } from "react-router-dom";
import { useMeal } from "../store/meal"; import { useMeal } from "../store/meal";
import { fetchSearchResults } from "../store/meal/async"; import { fetchSearchResults } from "../store/meal/async";
export const SearchBar: FC = () => { export const SearchBar = () => {
const { dispatch } = useMeal(); const { dispatch } = useMeal();
const [searchString, setSearchString] = useState(""); const [searchString, setSearchString] = useState("");
const getSearchResults: React.MouseEventHandler<HTMLButtonElement> = (e) => { const getSearchResults: MouseEventHandler<HTMLButtonElement> = (e) => {
searchString === "" searchString === "" ? e.preventDefault() : fetchSearchResults(dispatch, searchString);
? e.preventDefault()
: fetchSearchResults(dispatch, searchString);
}; };
const clearSearchBar = () => { const clearSearchBar = () => {
@ -17,10 +15,8 @@ export const SearchBar: FC = () => {
dispatch({ type: "clearSearchResults" }); dispatch({ type: "clearSearchResults" });
}; };
const handleChange = (e: ChangeEvent<HTMLInputElement>) => { const handleChange = ({ target: { value } }: ChangeEvent<HTMLInputElement>) =>
const { value } = e.target;
setSearchString(value); setSearchString(value);
};
return ( return (
<div className="section"> <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 { Link } from "react-router-dom";
import { buttonURL, links } from "../constants"; import { buttonURL, links } from "../constants";
import ChefImage from "../images/chef.svg"; import ChefImage from "../images/chef.svg";
@ -9,9 +9,12 @@ import { LogInButton } from "./LogInButton";
import { LogOutButton } from "./LogOutButton"; import { LogOutButton } from "./LogOutButton";
import { RandomButton } from "./RandomButton"; 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(); const { isAuthenticated, user } = useAuth0();
let transformStyle = { let transformStyle = {
transform: showNav ? "translateX(0%)" : "translateX(-105%)", transform: showNav ? "translateX(0%)" : "translateX(-105%)",
@ -32,8 +35,7 @@ export const SideNav: FC<Props> = ({ showNav, closeNavClick }) => {
left: "0", left: "0",
right: "0", right: "0",
bottom: "0", bottom: "0",
backgroundColor: backgroundColor: "rgba(0,0,0,0.5)" /* Black background with opacity */,
"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 */, zIndex: 2 /* Specify a stack order in case you're using a different order for other elements */,
// cursor: "pointer" /* Add a pointer on hover */ // cursor: "pointer" /* Add a pointer on hover */
}} }}
@ -65,11 +67,7 @@ export const SideNav: FC<Props> = ({ showNav, closeNavClick }) => {
</li> </li>
<li> <li>
<Link to="#"> <Link to="#">
{!isAuthenticated ? ( {!isAuthenticated ? <LogInButton color="orange lighten-1" /> : <LogOutButton />}
<LogInButton color="orange lighten-1" />
) : (
<LogOutButton />
)}
</Link> </Link>
</li> </li>

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry"; import { CardEntry } from "../../../components/CardEntry";
import PageLayout from "../../../layouts/PageLayout"; import PageLayout from "../../../layouts/PageLayout";
import { MealSummary } from "../../../types/meal"; import { MealSummary } from "../../../types/meal";
@ -8,7 +7,7 @@ type Props = {
strCategory: string; strCategory: string;
}; };
export const CategoryPage: FC<Props> = ({ meals, strCategory }) => ( export const CategoryPage = ({ meals, strCategory }: Props) => (
<PageLayout title={`Chef's ${strCategory} Recipes`}> <PageLayout title={`Chef's ${strCategory} Recipes`}>
<ul> <ul>
<div className="row"> <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 { Redirect, useParams } from "react-router-dom";
import { getData } from "../../services/api"; import { getData } from "../../services/api";
import { CategoryPage } from "./components/CategoryPage"; import { CategoryPage } from "./components/CategoryPage";
export const Category: FC = () => { export const Category = () => {
const { strCategory } = useParams<{ strCategory: string }>(); const { strCategory } = useParams<{ strCategory: string }>();
const [meals, setMeals] = useState({ meals: [] }); 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 { ContactFormInput } from "./ContactFormInput";
import { ContactFormSubmitButton } from "./ContactFormSubmitButton"; import { ContactFormSubmitButton } from "./ContactFormSubmitButton";
import { ContactFormTextArea } from "./ContactFormTextArea"; import { ContactFormTextArea } from "./ContactFormTextArea";
@ -7,14 +7,14 @@ type Props = {
setIsSubmitted: (value: boolean) => void; setIsSubmitted: (value: boolean) => void;
}; };
export const ContactForm: FC<Props> = ({ setIsSubmitted }) => { export const ContactForm = ({ setIsSubmitted }: Props) => {
const [firstName, setFirstName] = useState(""); const [firstName, setFirstName] = useState("");
const [lastName, setLastName] = useState(""); const [lastName, setLastName] = useState("");
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
const [phone, setPhone] = useState(""); const [phone, setPhone] = useState("");
const [message, setMessage] = useState(""); const [message, setMessage] = useState("");
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault(); e.preventDefault();
setIsSubmitted(true); setIsSubmitted(true);
}; };
@ -24,45 +24,20 @@ export const ContactForm: FC<Props> = ({ setIsSubmitted }) => {
<div className="row"> <div className="row">
<div className="col s12"> <div className="col s12">
<div className="col s12 m6"> <div className="col s12 m6">
<ContactFormInput <ContactFormInput id="First Name" value={firstName} dispatch={setFirstName} />
id="First Name"
value={firstName}
dispatch={setFirstName}
/>
</div> </div>
<div className="col s12 m6"> <div className="col s12 m6">
<ContactFormInput <ContactFormInput id="Last Name" value={lastName} dispatch={setLastName} />
id="Last Name"
value={lastName}
dispatch={setLastName}
/>
</div> </div>
<div className="col s12 m6"> <div className="col s12 m6">
<ContactFormInput <ContactFormInput id="Email" type="email" value={email} dispatch={setEmail} />
id="Email"
type="email"
value={email}
dispatch={setEmail}
/>
</div> </div>
<div className="col s12 m6"> <div className="col s12 m6">
<ContactFormInput <ContactFormInput id="Phone" value={phone} type="tel" dispatch={setPhone} />
id="Phone"
value={phone}
type="tel"
dispatch={setPhone}
/>
</div> </div>
<div className="col s12"> <div className="col s12">
<ContactFormTextArea <ContactFormTextArea id="Message" value={message} dispatch={setMessage} />
id="Message" <ContactFormSubmitButton text="Send Message" color="orange darken-2" />
value={message}
dispatch={setMessage}
/>
<ContactFormSubmitButton
text="Send Message"
color="orange darken-2"
/>
</div> </div>
</div> </div>
</div> </div>

View file

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

View file

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

View file

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

View file

@ -1,13 +1,13 @@
import React, { FC } from "react"; import { ChangeEventHandler, Dispatch, FC, SetStateAction } from "react";
type Props = { type Props = {
id: string; id: string;
value: string; value: string;
dispatch: React.Dispatch<React.SetStateAction<string>>; dispatch: Dispatch<SetStateAction<string>>;
}; };
export const ContactFormTextArea: FC<Props> = ({ id, value, dispatch }) => { export const ContactFormTextArea: FC<Props> = ({ id, value, dispatch }) => {
const handleChange: React.ChangeEventHandler<HTMLTextAreaElement> = (e) => { const handleChange: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
e.preventDefault(); e.preventDefault();
dispatch(e.target.value); 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 PageLayout from "../../layouts/PageLayout";
import { ContactForm } from "./components/ContactForm"; import { ContactForm } from "./components/ContactForm";
import { ContactFormSubmitted } from "./components/ContactFormSubmitted"; import { ContactFormSubmitted } from "./components/ContactFormSubmitted";
export const Contact: FC = () => { export const Contact = () => {
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
return isSubmitted ? ( return isSubmitted ? (

View file

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

View file

@ -1,10 +1,6 @@
import { FC } from "react"; type Props = { ingredients: string[][] };
type Props = { export const MealIngredientList = ({ ingredients }: Props) => (
ingredients: string[][];
};
export const MealIngredientList: FC<Props> = ({ ingredients }) => (
<div className="ingredientList"> <div className="ingredientList">
<table className="striped highlight responsive-table"> <table className="striped highlight responsive-table">
<thead> <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 { MealIngredientList } from "./MealIngredientList";
import { MealPresentation } from "./MealPresentation"; import { MealPresentation } from "./MealPresentation";
import { MealRecipe } from "./MealRecipe"; import { MealRecipe } from "./MealRecipe";
@ -11,12 +10,7 @@ type Props = {
handleFavChange: () => void; handleFavChange: () => void;
}; };
export const MealPage: FC<Props> = ({ export const MealPage = ({ meal, ingredients, recipe, handleFavChange }: Props) => (
meal,
ingredients,
recipe,
handleFavChange,
}) => (
<section className="container"> <section className="container">
<div className="row"> <div className="row">
<div className="col s12 l6"> <div className="col s12 l6">

View file

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

View file

@ -1,10 +1,6 @@
import { FC } from "react"; type Props = { recipe: string };
type Props = { export const MealRecipe = ({ recipe }: Props) => (
recipe: string;
};
export const MealRecipe: FC<Props> = ({ recipe }) => (
<div className="recipe"> <div className="recipe">
<div className="divider" /> <div className="divider" />
<h3>Instructions</h3> <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 { useParams } from "react-router-dom";
import { useFirebase } from "../../services/Firebase"; import { useFirebase } from "../../services/Firebase";
import { useMeal } from "../../store/meal"; import { useMeal } from "../../store/meal";
@ -8,7 +8,7 @@ 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: FC = () => { export const Meal = () => {
// hooks // hooks
const { user, isAuthenticated } = useAuth0(); const { user, isAuthenticated } = useAuth0();
const { id } = useParams<{ id: string }>(); const { id } = useParams<{ id: string }>();

View file

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

View file

@ -1,4 +1,3 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry"; import { CardEntry } from "../../../components/CardEntry";
import { MealSummary } from "../../../types/meal"; import { MealSummary } from "../../../types/meal";
@ -7,15 +6,10 @@ type Props = {
meals: MealSummary[]; meals: MealSummary[];
}; };
export const ProfilePage: FC<Props> = ({ user, meals }) => ( export const ProfilePage = ({ user, meals }: Props) => (
<div className="container"> <div className="container">
<div className="row valign-wrapper"> <div className="row valign-wrapper">
<img <img className="left circle responsive-img" src={user.picture} alt="Avatar" width="15%" />
className="left circle responsive-img"
src={user.picture}
alt="Avatar"
width="15%"
/>
<h2 className="col s9">{user.name}</h2> <h2 className="col s9">{user.name}</h2>
</div> </div>
<div className="row"> <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 { PreLoader } from "../../components/PreLoader";
import { useFirebase } from "../../services/Firebase"; import { useFirebase } from "../../services/Firebase";
import { MealSummary } from "../../types/meal"; import { MealSummary } from "../../types/meal";
import { useAuth0 } from "../../utils/auth0-spa"; import { useAuth0 } from "../../utils/auth0-spa";
import { ProfilePage } from "./components/ProfilePage"; import { ProfilePage } from "./components/ProfilePage";
export const Profile: FC = () => { export const Profile = () => {
const { loading, user } = useAuth0(); const { loading, user } = useAuth0();
const [favs, setFavs] = useState([] as MealSummary[]); const [favs, setFavs] = useState([] as MealSummary[]);
const db = useFirebase(); const db = useFirebase();

View file

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

View file

@ -1,9 +1,6 @@
import { FC } from "react";
import { CardEntry } from "../../../components/CardEntry"; import { CardEntry } from "../../../components/CardEntry";
import { MealSummary } from "../../../types/meal"; import { MealSummary } from "../../../types/meal";
type Props = { type Props = { meal: MealSummary };
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 { useMeal } from "../../store/meal";
import { SearchPage } from "./components/SearchPage"; import { SearchPage } from "./components/SearchPage";
export const Search: FC = () => { export const Search = () => {
const { state } = useMeal(); const {
return ( state: { searchString, search },
<SearchPage } = useMeal();
searchString={state.searchString} return <SearchPage searchString={searchString} searchResults={search} />;
searchResults={state.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 { Footer } from "../components/Footer";
import { Navbar } from "../components/Navbar"; import { Navbar } from "../components/Navbar";
import { SearchBar } from "../components/SearchBar"; import { SearchBar } from "../components/SearchBar";
@ -7,20 +7,20 @@ import { SideNav } from "../components/SideNav";
const MainLayout: FC = ({ children }) => { const MainLayout: FC = ({ children }) => {
const [showNav, setShowNav] = useState(false); const [showNav, setShowNav] = useState(false);
const openNavClick: React.MouseEventHandler = (e) => { const openNavClick: MouseEventHandler = (e) => {
e.preventDefault(); e.preventDefault();
setShowNav(true); setShowNav(true);
document.addEventListener("keydown", handleEscKey); document.addEventListener("keydown", handleEscKey);
}; };
const closeNavClick = (e: React.MouseEvent) => { const closeNavClick = (e: MouseEvent) => {
e.preventDefault(); e.preventDefault();
setShowNav(false); setShowNav(false);
document.removeEventListener("keydown", handleEscKey); document.removeEventListener("keydown", handleEscKey);
}; };
const handleEscKey = (e: KeyboardEvent) => { const handleEscKey = ({ key }: KeyboardEvent) => {
if (e.key === "Escape") { if (key === "Escape") {
setShowNav(false); setShowNav(false);
} }
}; };

View file

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

View file

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

View file

@ -1,2 +1 @@
import AppRouter from "./AppRouter"; export { AppRouter } from "./AppRouter";
export { 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); const URI = createURI(keyword, option);
return fetch(URI) try {
.then((response) => response.json()) const response = await fetch(URI);
.catch((error) => console.warn(error + "url:" + 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. import "@testing-library/jest-dom/extend-expect";
// 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';

View file

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