DEV Community

raivikas
raivikas

Posted on • Originally published at nextjsdev.com on

Let's build Advice Generator App using React.js & Tailwind CSS.

Let's build Advice Generator App using React.js & Tailwind CSS.

Hello everyone, I hope you all are doing well. I am back with another exciting web dev project, which will help to learn some new web dev skills as a Front-end developer.

In this tutorial, I will show you how you can build an Advice Generator App, It's one of the Frontend Mentor challenge projects and our goal is to make it look like the design given by the Frontend Mentor.

Here is the link to the FrontendMentor challenge that we will build.

So without any further talk, Let's start building it 🚀.

🚀 Live Demo of the Project

Step-1 Initializing the Project

Create a new next-js app with Tailwind CSS bootstrapped in it.

You can use this one-line command to create a new nextjs app with TypeScript and Tailwind CSS.

npx create-next-app -e with-tailwindcss my-project-name

Enter fullscreen mode Exit fullscreen mode

You can name your project whatever you want, I will name it an Advice Generator App.

💡 We are using TypeScript in this Project, so we have to explicitly define all the props, constants & function data types.

Now after creating the project open it in Vs Code or any IDE that you prefer.

Find the index.tsx file inside pages directory. and delete everything and paste the given code below.

import type { NextPage } from 'next'
import Head from 'next/head'

const API="https://api.adviceslip.com/advice";

const Home: NextPage = () => {

return (
    <div className="flex min-h-screen flex-col items-center bg-[#1e1f29]">
      <Head>
        <title>Advice Generator App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

)}

export default Home;

Enter fullscreen mode Exit fullscreen mode

In this project we are using Manrope font, so for that, we need to import this font from google fonts.

And for the API part, we are going to use Advice Slip API , which is a free API.

As you can see in the above code we have added a constant name API with the value of the API link

After that visit the globals.css file inside the styles folder and import a google font link (Manrope Font) at the top of the file inside it.

@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@600;700&display=swap');

@tailwind base;
@tailwind components;
@tailwind utilities;

Enter fullscreen mode Exit fullscreen mode

So, now to use the font inside our app, we need to add it as a custom font inside the tailwindcss.config.js file.

module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      fontFamily:{
        manrope:["Manrope"],
      }
    },
  },
  plugins: [],
}

Enter fullscreen mode Exit fullscreen mode

Step-2 Creating the Components

If you see the design given by the Frontend Mentor Challenge, there are only two components that you can make.

  1. AdviceCard.tsx
  2. CircularButton.tsx

So, now create the components folder inside your project folder and create two files with the names AdviceCard.tsx and CircularButton.tsx.

First, we will create the CircularButton component and then the AdviceCard component.

Inside CircularButton.tsx

import React from 'react'

interface Prop {
    handleAdvice():void,
}

export const CircularButton = ({handleAdvice} : Prop) => {
    return (
        <button onClick={handleAdvice} className=" bg-emerald-400 px-4 py-4 rounded-full text-green-900 hover:bg-green-200 hover:text-emerald-500 hover:shadow-xl hover:shadow-emerald-600 hover:scale-105 transition duration-300 ease-in">
            <svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth="3">
                <path strokeLinecap="round" strokeLinejoin="round" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
            </svg>
        </button>
    )
}

Enter fullscreen mode Exit fullscreen mode

In the above code as you can see we have added a prop handleAdvice , which is a function that will fetch new Advice data every time the button gets clicked.

Inside AdviceCard.tsx

import React from 'react'
import { CircularButton } from './CircularButton';

interface TextProps {
    id: number,
    adviceText: string,
    handleAdvice(): void,
}

export const AdviceCard = ({ adviceText, id , handleAdvice }: TextProps) => {
    return (
        <div className="relative w-[380px] md:w-[450px] md:h-[280px] bg-[#323a49] mt-20 px-8 pt-8 pb-16 rounded-xl flex flex-col justify-center items-center ">
            <p className="text-md md:text-lg uppercase font-medium text-emerald-400 absolute top-8 mx-auto ">
                Advice
                {" "}
                <span className=" font-bold ml-2 ">
                    #{id}
                </span>
            </p>
            <div className="text-lg md:text-2xl font-manrope font-semibold text-gray-300 leading-8 text-center mt-4">
                "{adviceText}"
            </div>
            <hr className="w-[380px] border-t-1 border-gray-500 mt-8 absolute bottom-16 mx-auto" />
            <div className="absolute -bottom-[30px] mx-auto ">
            <CircularButton handleAdvice={handleAdvice} />
            </div>
        </div>
    )
}

Enter fullscreen mode Exit fullscreen mode

In this component also we are passing three props as you can see.

The three props are:

  1. advice text
  2. id
  3. handleAdvice

Now we have made both the components, it's time to code the logic for fetching the API and displaying the data that we will get from it.

Step-3 Fetching the API

So basically, the API returns a single object which contains two fields the id and the adviceText field.

Now, visit the index.js file inside the Pages folder and create two constants with the useState hook inside the Home function, and set their default values as given below.

const [adviceText ,setAdviceText] =useState<string>("Never regret.
  If it's good, it's wonderful. If it's bad, it's experience.");

const [adviceId, setAdviceId] = useState<number>(143);

Enter fullscreen mode Exit fullscreen mode

And also don't forget to import useState from the react library.

Now after that create an arrow function with the name fetchAdvice () and inside it fetch the API using the inbuilt fetch() function and store the result inside the constant name data.

After that set the two pieces of the state with the value coming from the API and also create a function name handleAdvice() and call the fetchAdvice() inside it.

const [adviceText ,setAdviceText] =useState<string>("Never regret.
If it's good, it's wonderful. If it's bad, it's experience.");
  const [adviceId, setAdviceId] = useState<number>(143);

  const fetchAdvice = async () => {

      const res = await fetch(API);
      const data= await res.json();

      setAdviceId(data.slip.id);
      setAdviceText(data.slip.advice);
    };


  const handleAdvice= () => {
    fetchAdvice();
  };

Enter fullscreen mode Exit fullscreen mode

Step-4 Import the components and pass the Props

At last, import the two components from the components folder and add those inside the Home function.

After all that the index.tsx will look something like this:

Inside index.tsx

import type { NextPage } from 'next'
import Head from 'next/head'
import { useState } from 'react';
import { AdviceCard } from '../components/AdviceCard'

const API="https://api.adviceslip.com/advice";

const Home: NextPage= () => {

  const [adviceText ,setAdviceText] =useState<string>("Never regret. If it's good, it's wonderful. If it's bad, it's experience.");
  const [adviceId, setAdviceId] = useState<number>(143);

  const fetchAdvice = async () => {

      const res = await fetch(API);
      const data= await res.json();

      setAdviceId(data.slip.id);
      setAdviceText(data.slip.advice);
    };


  const handleAdvice= () => {
    fetchAdvice();
  };

  return (
    <div className="flex min-h-screen bg-gray-800 flex-col items-center py-2">
      <Head>
        <title>Advice Generator App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <h1 className="text-emerald-200 font-bold text-2xl md:text-4xl font-manrope mt-4 rounded-xl hover:rounded-xl hover:shadow-lg hover:shadow-emerald-600 hover:bg-emerald-500 hover:text-emerald-100 px-4 py-2 transition duration-300 ease-in ">
        Advice Generator App
        </h1>
      {/* <CircularButton /> */}
      <AdviceCard id={adviceId} adviceText={adviceText} handleAdvice={handleAdvice} />
    </div>
  )
}

export default Home

Enter fullscreen mode Exit fullscreen mode

Conclusion

Hope you were able to build this Advice Generator App. Feel free to follow me on Twitter and share this if you like this project 😉.

I hope you like this project and enjoyed building it, I would appreciate ✌️ it if you could share this blog post.

If you think that this was helpful and then please do consider visiting my blog website nextjsdev.com and do follow me on Twitter and connect with me on LinkedIn.

If you were stuck somewhere and not able to find the solution you can check out my completed Github Repo here.

Thanks for your time to read this project, if you like this please share it on Twitter and Facebook or any other social media and tag me there.

I will see you in my next blog ✌️. Till then take care and keep building projects.

Some Useful Link:

Next.js and Tailwind Installation Docs

Github link for the project

Connect with me:

Twitter Profile

LinkedIn Profile

GitHub Profile

Facebook Profile

Discussion (0)