Make sure you have docker installed on your machine. If not, download it from Here
-
Open VS code or any of your favourite IDE
-
Clone the project using the following command
https://github.com/ashishp911/CryptoPilot.git
-
Then build using the following command
docker build -t my-react-app .
-
Run the project using the following command
docker run -d -p 3001:3000 my-react-app
-
Finally, open your favourite browser and go to
http://localhost:3001/
npx create-react-app cryptocurrency
npm install @mui/material @mui/system @emotion/react @emotion/styled @mui/styles @mui/lab
npm i axios
npm install react-router-dom
We are going to use 4 endpoints for this application, you can find all API related data here -> Coingecko API.
- TrendingCoins (For carousel)
- SingleCoin (For single coin data)
- CoinList (For coin Table)
- HistoricalChart (For chart data)
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;800&display=swap');
Using routing in app.js so that we can toggle between homepage and coin_page. Wrap the entire app.js inside <BrowserRouter> </BrowserRouter>
tags. Also do not forget to import Routes, Route and BrowserRouter.
import { Routes, Route, BrowserRouter } from "react-router-dom";
Enclose all the routes of your application between the <Routes> </Routes>
tags. (In our case, homepage and coin_page).
Header.js will be outside the routes, so that it will be displayed all through the application.
We change the background color of the entire app to "#14161a"
in app.js
We use Appbar from material UI and Container (it ensures that the appbar is responsive). The appbar will contain Typography(for the title of our application) and a select tag(to select the currency). Flex : 1 for our typography indicates that the width of all other elements will be the same as their content, but the element with flex: 1 will be given the remaining full space. We wrap whole header with darkTheme.
Since we want the currency and symbol selected through the header for the entire application, we will use context API. We wrap our entire app within CryptoContext
, from index.js
. We export {currency, symbol, setCurrency}, so that any component can now use these states.
Our homepage is divided into 2 parts, banner (upper part with carousel) and coint table (table with all trending coins.)
- For the banner, we use background image as banner2.
- Banner has 3 parts, Name of the application (Typography), small description (Typography) and the carousel. I created a different react component for the carousel.
- All APIs are in
api.js
- For carousel, we need the trendingCoins() api. This API takes currency as a parameter. We get the currency from context API.
- Instead of fetch, I have used axios.get() to fetch data from the API.
- We use useEffect such that fetchTrendingCoins() function is called for the first time the page is rendered, also we add currency in the dependency list, so that whenever currency changes, fetchTrendingCoins() is called.
- We use useState to keep the fetched data in a variable called trending.
- We use react alice carousel for our carousel.
- installation -->
npm i react-alice-carousel
- We use
<AliceCarousel/>
to create carousel. - We add responsive object in our AliceCarousel, and we have deifned it such that when the page in 0 pixels or more, we display 2 items and if its greater then 512 pixels, we display 4 items.
- Items in the most important part of AliceCarousel.
- In items, we use the javaScript object.map() function to travese all the coins in trending which we fetched from our API.
- For the carousel, we add
<Link></Link>
tag so that by clicking on the image, we can go to any particular coin. - We add
<img>
and<span></span>
tags for image, name, price and 24hr change. example of carousel image is given below
- For coins table, we are going to use coinList api from api.js
- We again use axios to fetch coin list.
- With the heading (Typography) and search bar (TextField)
- Next comes the material UI TABLE which will contain all the coins data like,
- Coin,
- Price,
- 24h Change,
- Market Cap.
- For table body, we call
handleSearch()
, which returns the coin we inputted in TextField. - We use slice function to only display 10 coins per page.
- We also added
<LinearProgress />
so that if the coins are not fetched from the API, we will show a progress bar usingloading
state. (More on LinearProgress here)
- Details about pagination here
- We use pagination to divide the number of pages into the length of handleSearch() divided by 10.
- We add onChange fucntion so that
page
will be set to the page number we clicked. - We also add
window.scroll(0,450)
so that on change the window will be shown from the top.
- We used useparams to fetch id of coin from URL.
const { id } = useParams();
- We use
singleCoin(id)
API to get information of a single coin. - Coinpage is divided into Coin_Info and CoinChart.
- Sidebar(Coin_Info.js) is a component inside CoinPage will have some details about the coin.
- I added reponsive styles for this part. If the screensize is less than md, then flexDirection will be column.I did this by using
useMediaQuery()
. - For coin_Info, I added coin image, coin id, description, rank, market cap,
- The description of a coin has some html in it, so to remove that, we added
HTMLReactParser
. - Installation
npm i html-react-parser
- I made the page responsive by adding different styles for diffent screen sizes using
useMediaQuery()
.
- CoinChart is another component inside CoinPage which will have historic data of the prices of the coin.
- I used chartJs2 for plotting the chart.
- Installation
npm i react-chartjs-2 chart.js
- Refer Here for chartjs2
- We used historicalChart API to get the data
- We have 2 dependencies for the useEffect API here, currency and days which means if currency or days change, the page will re-render.
historicalData
will have an array of time and price.- We use
<Line />
from chartjs 2 for our chart. It will have labels (time) and dataset (price of the coin).
- Below the chart, we will add 4 buttons which will give options to show the chart data of
- 1 Day
- 1 Month
- 3 Months
- 1 Year.
- Select Button is a custom component to give styles to the buttons.
- Integrated Firebase with our react application.
- Installed firebase
npm install firebase
- Created a modal (from material UI) which is a component that provides a solid foundation for creating dialogs, popovers, lightboxes, or whatever else.
- Create tabs from material UI to toggle between 1. Login and 2. Signup
- Created 2 components for login and signup.
- We used material UI's Box to create a simple signup page with 3 textfields and 1 button.
- The handlesubmit will be called when user clicks the submit button.
- This function will first check if password and confirm password are same, if not, it will throw an error using snackbar.
- Then, i used the
createUserWithEmailAndPassword()
function. In Firebase, thecreateUserWithEmailAndPassword()
function is a method provided by the Firebase Authentication SDK. It is used to create a new user account using an email address and password. - This function takes 3 parameters, auth, email and password.
- Firebase will validate the provided email and password and create a new user account if they meet the required criteria.
- If the account creation is successful, Firebase will return a user object containing information about the newly created user.
- Then we show the signup successful alert message using snackbar alert and close the modal using
handleclose()
which was taken as props fromAuthmodal
.
- Again we have used material UI's Box to create the login modal.
- The
handleSubmit()
is similar to that of Signup, the only difference is that instead of usingcreateUserWithEmailAndPassword()
, we are using thesignInWithEmailAndPassword()
function, which also takes 3 arguments, auth, email and password. - Error is thrown if the password is wrong.
Now I added
onAuthStateChanged()
to our cryptoContext page to keep auser
state to keep the information of the users that just logged in.
- For the sidebar, we used something called material UI drawer
- Inside our sidebar, we have four important things, User image, user display name, wishlist, and a logout button.
- We use Avartar from material UI for our image and we created a div for our watchlist.
- Our Avatar will have a onclick function
toggleDrawer()
which is used to open/close the drawer. - Adding
overflowY: "scroll"
to our styles adds a scroller for the watchlist.
- Finally the logout button.
- For logout, we use
signOut()
fromfirebase/auth
. And then we give the user alert usingsetAlert()
.
- In
AuthModal
we will add a box(material UI) and add a Google button. - We will add a library called react google button.
npm install react-google-button
GoogleButton
will hve an onclick function.- We added a
SingnInWithGoogle()
function. - Inside this fucntion there will be
signInWithPopup()
which will take googleProvider and auth as parameters and googleProvider has be initialised as below
const googleProvider = new GoogleAuthProvider();
- Go to firebase and open your project.
- Go to Firestore Database and click create your database.
- Select start in test mode.
- Select a zone
- Go to rules and add the following rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /watchlist/{userId}{
allow read: if isLoggedIn(userId)
allow write: if request.auth.uid == userId
}
}
function isLoggedIn(userId){
return request.auth.uid == userId
}
}
- This means that only authenticated user will have read write access.
- Firebase database rules
There will be a add to watchlist button in the Coin_info.js
- First take user from cryptoContext and check if user is present.
- If the user is present, we will show the button to add to watchlist.
inWatchList
is a bool variable to check if the coin is already present in the watchlist.- If the coin is already present in the watchlist, the button will show
Remove from watchlist
, elseAdd to watchlist
. - We take the reference to our database
const coinRef = doc(db, "watchlist", user?.uid);
where doc comes from "firebase/firestore";
7. We use the setDoc()
method to add the coin to watchlist array(present in cryptoContext)
8. setAlert
is added for success and error.
We need to set watchlist to add coins to our watchlist state, we are going to do that using onSnapShot
- We will add
onSnapShot()
in our cryptoContext using auseEffect()
hook. - This
onSnapShot()
function will havecoinRef
and we will set watchlist like shown belowsetWatchList(coin.data().coins);
wherecoin.data().coins
will have all the coins fetched from firebase.
For removing coin we have a function removeFromWatchlist()
- For remove from watchlist, we will use the same
setDoc()
method and we will all the coins except thecoins.id
coin usingfilter()
function. - Then we will
{ merge: "true" }
- Add the ````setAlert()``` for success and errors.
- Now we want to fetch the coins from watchlist array and display it on the
UserSidebar
- So we map through our coins state and if that coin is present in the watchlist variable, we are going to render it in the userSidebar. (
if watchlist.includes(coin.?id) {}
) - Then we will display the coin name and price of the coin.
- We will also have a delete button which i have used from
npm i react-icons
- Then I am using
<AiFillDelete>
as a delete button. This button will have aonClick
which will have this functionremoveFromWatchlist(coin)
. - This remove coins function will be similar to the coin in
CoinInfo.js
. - The delete button will remove the coin from the wachlist.