Archived course lesson
Add a Favorites Page
Objective: Add a recipes list page at the route `/favorites` that contain all the items that the user has liked.
Now that we have a way for users to like recipes, let’s create a page that will list all of the user’s favorite recipes. This favorites page will be similar to the home page except we pass different props into the <RecipesList> component- in particular the different queryType and options object.
Let’s create a favorites page:
import { MainLayout } from '../components/layout/MainLayout';
import styled from 'styled-components';
import { useFetchUser } from '../utils/user';
import * as _ from 'lodash';
import { Loading } from '../components/notify/Loading';
import Router from 'next/router';
import { RecipesList, queryEnum } from '../components/RecipesList';
const StyledHeader = styled.h1`
${({ theme }) => `
font-size: 2em;
text-align: left;
padding: ${theme['padding-small']} ${theme['padding-small']};
`}
`;
const Favorites = () => {
const { user, loading: isFetchUser } = useFetchUser();
const owner = _.get(user, 'sub');
const options = owner ? { variables: { where: { user: owner } } } : {};
if (isFetchUser) return <Loading />;
if (!user) {
Router.replace('/');
}
return (
<MainLayout title="Recipes">
<StyledHeader>My Favorites</StyledHeader>
<RecipesList
parentRoute="recipe"
queryType={queryEnum.userLikes}
options={options}
/>
</MainLayout>
);
};
export default Favorites;
Next, as a bit of cleanup, add the <Loading /> component to the my-recipes/index.tsx page. Just like the home page, we don’t want to load any recipes lists on a page before the loading has completed.
import styled from 'styled-components';
import { Layout, Menu } from 'antd';
import Link from 'next/link';
import { useFetchUser } from '../../utils/user';
const { Header } = Layout;
const TitleContainer = styled.div`
${({ theme }) => `
background-color: ${theme['header-color']};
width: 50%;
display: flex;
align-items: center;
@media (max-width: 890px){
visibility: hidden;
width: 0;
}
`}
`;
const Title = styled.div`
${({ theme }) => `
text-align: left;
display: flex;
line-height: 50px;
div {
width: 100%;
padding-left: ${theme['padding-small']};
}
h2 {
display: inline;
color: inherit;
}
img {
width: 64px;
}
p {
line-height: 0;
}
`}
`;
const StyledHeader = styled(Header)`
${({ theme }) => `
background-color: ${theme['header-color']};
border-bottom-color: ${theme['header-border-color']};
border-bottom-right: 1px;
border-bottom-style: solid;
text-align: right;
display: flex;
li {
font-size: ${theme['font-size-md']};
}
`}
`;
const StyledMenu = styled(Menu)`
border-bottom-width: 0px;
width: 50%;
@media (max-width: 890px) {
width: 100%;
}
`;
export const MainNavbar = () => {
const { user, loading } = useFetchUser();
return (
<StyledHeader>
<TitleContainer>
<Title>
<img src="/logo.svg" alt="Next Chop Logo" />
<div>
<h2>The Next Chop</h2>
<p>A recipe discovery app powered by Next.js</p>
</div>
</Title>
</TitleContainer>
<StyledMenu
theme="light"
mode="horizontal"
style={{ lineHeight: '64px' }}
>
<Menu.Item key="/">
<Link href="/">
<a>Home</a>
</Link>
</Menu.Item>
{user && !loading
? [
<Menu.Item key="/favorites">
<Link href="/favorites">
<a>Favorites</a>
</Link>
</Menu.Item>,
<Menu.Item key="/my-recipes">
<Link href="/my-recipes">
<a>My Recipes</a>
</Link>
</Menu.Item>,
<Menu.Item key="/api/logout">
<Link href="/api/logout">
<a>Logout</a>
</Link>
</Menu.Item>,
]
: [
<Menu.Item key="/api/login">
<Link href="/api/login">
<a>Login</a>
</Link>
</Menu.Item>,
]}
</StyledMenu>
</StyledHeader>
);
};