- Table of Contents
- The Booking App
- Setup and Evaluation
- Front-end Architecture
- Future Considerations
- Honour Code
This Booking App was created as the final capstone project of the Meta Front-End Developer Certification.
Preview: Little Lemon is a family-owned Mediterranean restaurant that blends traditional recipes with a modern twist. Our goal is to provide our customers with a unique dining experience that will take them on a culinary journey through the Mediterranean.
Instructions Received: To create a modern responsive Front-end for the Little Lemon app with a Bookings feature which they lack at present.
# Run in the Terminal
git clone https://github.com/jayantasamaddar/little-lemon-meta-frontend-capstone.git folder
# Install Dependencies
npm install
# Launch app in Browser
npm start
# Run Tests
npm test
# Run Tests with Coverage
npm test:cvThere were several considerations for the frontend architecture.
- Folder Structure - How would the files be organized in the
srcfolder. - Component Architecture - How best to write reusable components.
- Naming Conventions - How and why CSS classes, CSS Variables are named so.
- Use of Dependencies - Choice on what dependencies to use.
- Data Fetching - How we will manage the data used by the app.
- Unit Testing - How to have good coverage in our unit tests.
Separate folders for:
-
components: For individual components. Complex components have nested
componentsfolder. The component folder has 4 files usually (some components are auto-tested without having to create a separate test file. Thus a single folder inside thecomponentsfolder is all inclusive as a single Unit having the Renderer, the stylesheet and the unit test.Component.jsx(The Component)Component.css(The stylesheet)index.js(For exporting the component)Component.test.jsx(Test file for the component)
-
pages: Single Pages in the application that have a collection of these components laid out in different ways. The individual pages in the
pagesfolder, may further optionally have acomponents(which represent sections, e.g.Testimonials) and optionally, apages(for nested pages) folder in them. -
context: Contains Context Providers and basic hooks to access the Context data.
-
hooks: Hooks unrelated to context. E.g.
useWindowResizeto track resizing the window. -
actions: Reducer function and initial states (and any hooks related to them)
-
utilities: Utility functions. E.g.
validateNumber. -
settings: Contains global settings. Has a
cmsfolder that mocks a content management system from which we can source content for our pages. Can be internationalized later.
Note: The following has been generated with:
tree -d -I 'node_modules|coverage'
The directory tree (only directories and excluding node_modules and coverage):
├── public
└── src
├── actions
├── assets
├── components
│ ├── Backdrop
│ ├── Button
│ ├── Card
│ ├── Error
│ ├── Footer
│ ├── Header
│ │ └── components
│ │ └── BurgerMenu
│ ├── Heading
│ ├── Icon
│ ├── Label
│ ├── Logo
│ ├── Main
│ ├── ProgressBar
│ ├── ReviewStar
│ ├── Select
│ │ └── components
│ │ └── Option
│ ├── SocialMediaWidget
│ ├── Stack
│ ├── Table
│ │ └── components
│ │ ├── TableBody
│ │ ├── TableCell
│ │ ├── TableHeader
│ │ └── TableRow
│ └── Textfield
├── context
│ ├── AppProvider
│ ├── FormProvider
│ └── ThemeProvider
├── hooks
├── pages
│ ├── Booking
│ │ ├── components
│ │ │ └── BookingForm
│ │ └── pages
│ │ └── ConfirmedBooking
│ └── Home
│ └── components
│ ├── About
│ ├── Hero
│ ├── Specials
│ └── Testimonials
├── settings
│ └── cms
└── utilities
└── testsThere following Design Patterns have been followed:
-
Most components are single units of functional code.
-
In case of complex components that are comprised of components that can be used standalone, they were broken into separate components. The folder structure above explains where they reside.
-
Where responsibility needed to be isolated, it was done: E.g. Table (read more).
-
The
StackandTableelements, OPTIONALLY also have the Composite Components pattern. It allows some more flexibility as explained in the Table documentation above.Example:
import { Table } from './components'; const CustomTable = () => { return ( <Table> <Table.Body> <Table.Header> <Table.Cell>ID</Table.Cell> <Table.Cell>Name</Table.Cell> <Table.Cell>Price</Table.Cell> </Table.Header> <Table.Header> <Table.Cell>1</Table.Cell> <Table.Cell>Apple</Table.Cell> <Table.Cell>3.00</Table.Cell> </Table.Header> <Table.Header> <Table.Cell>ID</Table.Cell> <Table.Cell>Mango</Table.Cell> <Table.Cell>5.00</Table.Cell> </Table.Header> </Table.Body> </Table> ); };
-
A FormContextProvider supplies the current
stateanddispatchfunction to update the state to the Booking Form. This pattern ensures, we can continue to have multiple forms in the app, as we grow the app while having a different Context limited to that individual multi-level form.
The naming convention followed are:
-
CSS Component and Page specific Classes:
LL-Componentfor the top level class for the root element for almost every component. The child elements in that tree follow an appended PascalCase name, for e.g.LL-ComponentSubComponent. -
CSS utility classes: Utility classes like
text-sm,text-m,text-xlare preset inApp.cssto offer global styles to quickly switch between font-sizes by any component that allows it. (E.g. theHeadingComponent) -
CSS Variables: CSS Variables serve as globally used presets for maintaining a standardized look and feel. The idea is to have a write-once-use-throughout approach - no need to keep writing a complex
box-shadowproperty for all elements that usebox-shadow. Instead presets in the form ofbox-shadow-1,box-shadow-2,box-shadow-3are available to use depending on the position of the element.
This project was developed with the personal intention to minimize dependencies as much as possible to test my core skills.
-
No CSS Library has been used. All the CSS has been written from scratch.
-
No Form Library like Formik or form validation library like Yup has been used. They have already been used in an earlier project in the certification and the decision was simply to have this implemented without using them. Utility functions like
validateNumberhave been created and used. Find them in thesrc/utilitiesfolder. -
Font Awesome has been used for the icons.
A lot of data is replicated (e.g. links at header and footer) and/or is available as an array or an object that can grow or shrink in size. Thus, we need to consider the possibility of retrieving this from a database or a Content Management System. For now, we will mock this by using the data at settings/cms folder to simulate fetching from a centralized CMS.
Unit Testing has been done with the help of React Testing Library, Jest, Jestdom that can already shipped with create-react-app.
- The
setupTests.jshave been modified, so that we can interact with the window global object. - Mocks for React hooks have been done throughout within the components itself. Mocks for
useContext,useLocation,useForm,dispatchfunction of theuseReducerhave all been covered. - The unit tests can be found in each of the component and page folders.
-
The use of Context API and
useReducerhas been done in the Form to make sure the Form can have multiple levels and flexibility for any future modifications. While this is not needed in the Meta Capstone project, however to have an advanced service in a production level application, for e.g. A Mobile Phone OTP Validation service (to confirm that this is a valid person booking, considering restaurant tables are limited and we would like to prevent bots), a middleware form with an input phone field, a button and fields to enter a 4-digit OTP can be present. This field can then dispatch an action -dispatch({ type: "OTPValidation" }), which can then be processed by the reducer function and thestageupdated, so the form can proceed to the next stage. -
A
ThemeProviderthat wraps all Pages of the app that will provide the styling when themes are switched from dark to light.
This demo project is solely done by me, Jayanta Samaddar. You can contact me on GitHub for interesting projects to work on.