Setting up the biggest project - vonschappler/Ultimate-React GitHub Wiki
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.
- Users are hotel employess which need to be logged in to perform tasks.
- New users can only be signed up inside applications by already existing users (probably admins/managers of the hotel)
- Users should be able to upload and avatar and change some personal data
- The application needs a table view with cabins, showing the cabin photo, name, capacity, price, discount and other relevant information
- Booking status can be "unconfirmed", "check in" or check-out (allowing filtering by those status)
- 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
- Users should be able to delete, check in, check out a booking as guests have arrived
- 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
- On check in, the guest should have the ability to add breafast for the entire stay if not yet selected
- Guest data should contain full name, email, national id, nationality and a country flag for easy identification
- 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:
- List of guests checking in and checking out
- Statistics of bookings, sales, check ins and occupancy rate
- A chart showing all daily hotal sales
- A chart showing statistcs on stay durations
- Users should be able to define some application wide settings, such as breakfast price, min and max nigths per booking, max guests per booking
- The application needs a dark mode
- Authentication
- Cabins
- Bookings
- Check in/out
- Guests
- Dashboard
- Settings
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 |
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 |
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 |
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:
- 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
- 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> ); }
- 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.
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:
- 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.
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:
- 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;
- 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