In this project we will build an e-commerce web application that support multiple layouts. The product owner is wanting to move the business online.
It is your decision on the name of the store, category of products and styling layout.
This is an individual project but feel free to ask help from your friend and the academic team. When create user, please use your actual name or kindly inform us about your nicknames.
The listed core features is the guideline to your project, this should be a product to show to your recruiter. An E-commerce web application must have these:
axios has become undeniably popular among frontend developers. Axios is a promise based HTTP client for the browser and Node.js. Axios makes it easy to send asynchronous HTTP requests to REST endpoints.
Installation
npm i axios
src/
called apiService.js
. All of the connections to the backend API will go through this API service. Think about it like a city gate.import axios from "axios";
const api = axios.create({
baseURL: process.env.REACT_APP_BACKEND_API,
headers: {
"Content-Type": "application/json",
},
});
/**
* console.log all requests and responses
*/
api.interceptors.request.use(
(request) => {
console.log("Starting Request", request);
return request;
},
function (error) {
console.log("REQUEST ERROR", error);
}
);
api.interceptors.response.use(
(response) => {
console.log("Response:", response);
return response;
},
function (error) {
error = error.response.data;
console.log("RESPONSE ERROR", error);
// Error Handling here
return Promise.reject(error);
}
);
export default api;
How to use?
api
from apiService
, then you can use it like an instance of axios
:import api from "apiService";
// Examples:
const res = await api.post("/auth/login", { email, password });
const res = await api.get(`/blogs?page=${pageNum}&limit=${limit}`);
const res = await api.put(`/blogs/${blogId}`, { title, content, images });
const res = await api.delete(`/blogs/${blogId}`);
api.defaults.headers.common["Authorization"] = AUTH_TOKEN;
react-router-dom
:npm i react-router-dom
src/pages
, create the pages of your app. In each file, use rface
to create the component and add a h1
title according to the page. Example, in src/containers/HomePage.js
:import React from "react";
const HomePage = () => {
return (
<div>
<h1>HomePage</h1>
</div>
);
};
export default HomePage;
App.js
:function App() {
return (
<Router>
<PublicNavbar />
<Switch>
<Route exact path="/books/:id" component={BookDetailPage} />
<Route exact path="/reading" component={ReadingPage} />
<Route exact path="/" component={HomePage} />
<Route component={NotFoundPage} />
</Switch>
</Router>
);
}
PublicNavbar.js
:const PublicNavbar = () => {
return (
<Navbar bg="light" expand="lg">
<Navbar.Brand>
<img src={logo} alt="App Logo" width="200px" />
</Navbar.Brand>
<Nav className="mr-auto">
<Nav.Link as={NavLink} exact={true} to="/">
Home
</Nav.Link>
<Nav.Link as={NavLink} exact={true} to="/reading">
Reading List
</Nav.Link>
</Nav>
</Navbar>
);
};
A private route is a route that only authenticated user can access to. Private routes connect to protected page. In order to see the protected page, you must first login. Pretty standard stuff.
src/routes
PrivateRoute.js
, PublicLayout.js
, and AdminLayout.js
in src/routes
|- src/
...
|- routes/
|- AdminLayout.js
|- PublicLayout.js
|- PrivateRoute.js
PrivateRoute
component is the blueprint for all private routes in the application. If the user is logged in, go on and display the component in question; otherwise, redirect the user to sign-in page. In PrivateRoute.js
:const PrivateRoute = ({ ...rest }) => {
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
if (isAuthenticated) return <Route {...rest} />;
delete rest.component;
return <Route {...rest} render={(props) => <Redirect to="/login" />} />;
};
PublicLayout.js
defines the routes and pages that have the same layout. In this simple example, the layout of pages has a navigation bar at the top and the content of the page below.const PublicLayout = () => {
return (
<>
<PublicNavbar />
<Container>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/login" component={LoginPage} />
<Route exact path="/register" component={RegisterPage} />
<Route exact path="/blogs/:id" component={BlogDetailPage} />
<PrivateRoute exact path="/blog/add" component={AddEditBlogPage} />
<PrivateRoute
exact
path="/blog/edit/:id"
component={AddEditBlogPage}
/>
<Route component={NotFoundPage} />
</Switch>
</Container>
</>
);
};
AdminLayout.js
defines the routes and pages that have a different layout than public layout. Here in this example, all the pages will have a side menu in the left side of the screenconst AdminLayout = () => {
return (
<>
<PublicNavbar />
<Container fluid>
<Row>
<Col md={3} lg={2}>
<SideMenu />
</Col>
<Col md={9} lg={10}>
<AlertMsg />
<Switch>
<Route exact path="/admin/profile" component={ProfilePage} />
<Route exact path="/admin/friends" component={FriendListPage} />
<Route exact path="/admin/blogs" component={BlogListPage} />
<Route exact path="/admin/blogs/:id" component={BlogDetailPage} />
<Route exact path="/admin/blog/add" component={AddEditBlogPage} />
<Route
exact
path="/admin/blog/edit/:id"
component={AddEditBlogPage}
/>
<Route exact path="/admin/messenger" component={MessengerPage} />
<Route component={NotFoundPage} />
</Switch>
</Col>
</Row>
</Container>
</>
);
};
SideMenu.js
:import React from "react";
import { Nav } from "react-bootstrap";
import { NavLink } from "react-router-dom";
const SideMenu = () => {
return (
<Nav className="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
<div className="sidebar-sticky pt-3">
<Nav.Item>
<Nav.Link
as={NavLink}
to="/admin/profile"
exact={true}
activeClassName="active"
>
Profile
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
as={NavLink}
to="/admin/blogs"
exact={true}
activeClassName="active"
>
Blogs
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
as={NavLink}
to="/admin/friends"
exact={true}
activeClassName="active"
>
Friends
</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link
as={NavLink}
to="/admin/messenger"
exact={true}
activeClassName="active"
>
Messenger
</Nav.Link>
</Nav.Item>
</div>
</Nav>
);
};
export default SideMenu;
App.js
, and put everything together:import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
//...
function App() {
return (
<Router>
<Switch>
<PrivateRoute path="/admin" component={AdminLayout} />
<Route path="/" component={PublicLayout} />
</Switch>
</Router>
);
}