Archived course lesson

Add a Favorites Page

Part of Frontend Serverless with React and GraphQL

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>
  );
};