Setting up the biggest project - vonschappler/Ultimate-React GitHub Wiki

Dahsboard Application planning:

For this project we'll build an application for the "The Wild Oasis", which is a small boutique hotal with 8 luxurious wooden cabins.

This fictional business wants a custom application to manage everything about the hotel (bookings, cabins, guests, etc.). So, this will be an internal application used by the business to check in guests when they arrive.

For this project they'll need also the API, because they have nothing done (unlike the previous project which the fictional client provided an API).

They'll also need a customer website where the clients can book their stays, using the same API used for the internal management.

Project requirements:

  1. Users are hotel employess which need to be logged in to perform tasks.
  2. New users can only be signed up inside applications by already existing users (probably admins/managers of the hotel)
  3. Users should be able to upload and avatar and change some personal data
  4. The application needs a table view with cabins, showing the cabin photo, name, capacity, price, discount and other relevant information
  5. Booking status can be "unconfirmed", "check in" or check-out (allowing filtering by those status)
  6. Booking also needs to include number of guests, number of nights, guests observations, if the guests also want to have breakfast and price of the breakfast
  7. Users should be able to delete, check in, check out a booking as guests have arrived
  8. Bookings may not have been paid yet on guest arrival, but on check in, users need to accept payment and confirm using the application the payment was received
  9. On check in, the guest should have the ability to add breafast for the entire stay if not yet selected
  10. Guest data should contain full name, email, national id, nationality and a country flag for easy identification
  11. The initial app screen should be a dashboard, to display important information for the last 7, 30, or 90 days. The information desired is listed below:
  12. List of guests checking in and checking out
  13. Statistics of bookings, sales, check ins and occupancy rate
  14. A chart showing all daily hotal sales
  15. A chart showing statistcs on stay durations
  16. Users should be able to define some application wide settings, such as breakfast price, min and max nigths per booking, max guests per booking
  17. The application needs a dark mode

Features categories:

  1. Authentication
  2. Cabins
  3. Bookings
  4. Check in/out
  5. Guests
  6. Dashboard
  7. Settings

Pages:

Categories Pages
Bookings /bookings
Cabins /cabins
Guests probably not necessary, based on the requirements list
Dashboard /dasboard
Note that this one will combine other features as well
Check in/out /checkin/:bookingId
App Settings /settings
Authentication /users
/login
/account

Technologies to be used:

Client-Side Renderding Server-Side Rendering
Used to build Single-Page Applications Used to build Multi-Page Applications
All HTML is renderend on the client Some HTML is rendered on the server
All JavaScript needs to be downloaded before apps start running (bad for performance) More performant, since less JavaScript needs to be downloaded
Perfect use case: applications used internally as tools inside companies The React team is moving to this direction

The tech stack chosen:

Category Technology
Routing React Router
Styling Styled components
Remote state management React Query
UI state management Context API
Form management React Hook form
Other tools React icons
React hot toast
Recharts
date-fns
Supabase

Introduction to Styled Components:

Styled Compnents bascially allows us to write css styles inside our JavaScript components files and then make use of the styled function to apply the styles in a brand new React Component with the styles applied to it.

In order to use this technique, first we need ot install the library with:

npm i styled-components

Then, on inside the component we wish to style, we make use of the styled function as displayed below:

import styles from 'styled-components';

// this will allow the customization of a H1 element using the ES6 template literal leverage
// this will return a react component, which means the variable which stores it, needs to start with a capital letter.
const H1 = styled.h1`
  font-size: 30px;
  font-weight: 600;
`;

function App() {
  return (
    <div>
      <H1>Hello world</H1>
    </div>
  );
}

export default App;

NOTES:

  1. By convension, the resuable components always receive the name of the HTML element we wish to style, meaning that if we wish to create a styles button, we should create something similar to:
// some code here
const Button = styled.button`
  /* css styles for the button*/
`;
// some more code here
  1. If we wish to style a whole component, we usually wrap that component into a div, and created a styled div with the name Styled<componentName>, as displayed below:
// some code here
const Button = styled.button`
  /* css styles for the button*/
`;

const StyledApp = styled.main`
  /* css styles for the main wrapper of the application*/
`;
// some more code here
function App() {
  return (
    <StyledApp>
      <Button>Click me</Button>
    </StyledApp>
  );
}
  1. Making use of this technique gives us many advantages, like for example, the fact that any styles component receives all properties defined by both React Components and HTML elements, class name conflicts removal and many more.

Applying global styles:

In order to apply global CSS definitions to an application, it's required that we create a brand new styled component (usually named GlobalStyles.js) making use of the create GlobalStyle function, provided by styled-components.

The snippet of code below show this process:

import {createGlobalStyle} from 'styled-components;

const GlobalStyles = createGlobalStyle`
/*global css definitions*/
`

export default GlobalStyles;

Then to make use of the GlobalStyles component exported by the file above, we need to include it as a siblin component of the main App, since this component do not accept any childs, causing our App.jsx to become something like this:

import GlobalStyles from 'path/to/GlobalStyles';
// some code here
const Button = styled.button`
  /* css styles for the button*/
`;

const StyledApp = styled.main`
  /* css styles for the main wrapper of the application*/
`;
// some more code here
function App() {
  return (
    <>
      <GlobalStyles />
      <StyledApp>
        <Button>Click me</Button>
      </StyledApp>
    </>
  );
}

The styled-components library also provides an option of creating themes which can be something that imples lot more work in certain cases and for that reason it won't be covered here. But for more information about this topic, check the documentation.

NOTES:

  1. To make use of a pseudo-class in CSS, like for example hover, styled-components make use of a syntax similar to Sass, meaning that the pseudo-class can be selected by usin &, like so &:hover will select the pseudo-class hover of the element defined above the use of it.

Using props and the css function:

In order to allow conditional css styling by using component props, we need to make use of the css function provided by styled-components.

The snippets of code below shows a small example on how to aplly this mechanism to customize a styled component using its props.

// StyledComponent.jsx

import styled, { css } from 'styled-components';

const StyledComponent = styled.h1`
  ${(prop) =>
    prop.as === 'h1' &&
    css`
      font-size: 3rem;
    `}
  ${(prop) =>
    prop.as === 'h2' &&
    css`
      font-size: 2rem;
    `}
  ${(prop) =>
    prop.as === 'h3' &&
    css`
      font-size: 1.5rem;
    `}
`;

export default StyledComponent;
// App.jsx

import GlobalStyles from 'path/to/GlobalStyles';
// some code here

const StyledApp = styled.main`
  /* css styles for the main wrapper of the application*/
`;
// some more code here
function App() {
  return (
    <>
      <GlobalStyles />
      <StyledComponent as='h1'>Something here as h1</StyledComponent>
      <StyledComponent as='h2'>Something here as h2</StyledComponent>
      <StyledComponent as='h3'>Something here as h3</StyledComponent>
    </>
  );
}

NOTES:

  1. If we wish to define some default props for components we can add an object to our styled component jsx file, like in the snippet below:
// StyledComponent.jsx

import styled, { css } from 'styled-components';

const StyledComponent = styled.h1`
  ${(prop) =>
    prop.as === 'h1' &&
    css`
      font-size: 3rem;
    `}
  ${(prop) =>
    prop.as === 'h2' &&
    css`
      font-size: 2rem;
    `}
  ${(prop) =>
    prop.as === 'h3' &&
    css`
      font-size: 1.5rem;
    `}
`;

StyledComponent.defaultProps = {
  as: 'h1',
};
export default StyledComponent;
  1. It's possible to pass to the styled function a 3rd-party component (like the NavLink component provided by React Router) by following the sintax displayed below:
// StyledComponent.jsx

import styled, { css } from 'styled-components';

const Styled3rdPartyComponent = styled(ThrdPartyComponent)`
  /* css definitions */
`;
// other definitions here
⚠️ **GitHub.com Fallback** ⚠️