Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?

How to Create a Product Review Application in Next.js

Making necessary choices generally requires the opinions of individuals extra educated than us, particularly for brand spanking new merchandise. Getting individuals to share their ideas on gadgets they’ve used previously can save us from disappointment and waste typically. A product assessment software is an instance of a platform that delivers these opinions to us.



What we shall be constructing

This text discusses making a product assessment software utilizing the Cloudinary add widget and storing the information from this software on our Xata database.

GitHub URL
https://github.com/Iheanacho-ai/product-review



Conditions

To get essentially the most out of this text, we require the next:

  • A primary understanding of CSS, JavaScript, and React.js
  • A Cloudinary account we will create here
  • A Xata account. Create a free one here
    ## Establishing our Subsequent.js app

Next.js is an open-source React framework that permits us to construct server-side rendered static internet purposes.

To create our Subsequent.js app, we navigate to our most popular listing and run the terminal command under:

    npx create-next-app@newest
    # or
    yarn create next-app
Enter fullscreen mode

Exit fullscreen mode

After creating our app, we modify the listing to the venture and begin a growth server with:

    cd <title of our venture>
    npm run dev
Enter fullscreen mode

Exit fullscreen mode

To see our app, we go to http://localhost:3000.



Putting in Tailwind CSS

Tailwind CSS is a “utility-first” CSS framework that permits us to create consumer interfaces for internet purposes quickly.

To put in Tailwind CSS in our venture, we run these terminal instructions.

    npm set up -D tailwindcss postcss autoprefixer
    npx tailwindcss init -p
Enter fullscreen mode

Exit fullscreen mode

These instructions create two information within the root listing of our venture, tailwind.config.js and postcss.config.js.

In our tailwind.config.js, we add the paths to all our template information with the code under.

    module.exports = {
      content material: [
        "./pages/**/*.{js,ts,jsx,tsx}",
        "./components/**/*.{js,ts,jsx,tsx}",
      ],
      theme: {
        lengthen: {},
      },
      plugins: [],
    }
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we add the tailwind directives in our types/world.css file.

    @tailwind base;
    @tailwind parts;
    @tailwind utilities;
Enter fullscreen mode

Exit fullscreen mode



Putting in the Cloudinary Dependencies

Cloudinary is a cloud-based service that gives an end-to-end picture and video administration answer, together with uploads, storage, manipulations, optimizations, and supply.

We run this terminal command to put in the Cloudinary dependencies in our venture.

    npm i @cloudinary/url-gen @cloudinary/react
Enter fullscreen mode

Exit fullscreen mode



Making a Xata Workspace

Xata is a serverless data platform that gives builders a serverless relational database, search engine, and analytics engine, all behind a constant API.

Xata permits builders to construct purposes simpler and sooner.

To begin utilizing Xata, we have to create a workspace. A Xata workspace represents a corporation and helps to safe our information.

Subsequent, we click on on ‘Add a database’ and create a Xata database.

After creating our database, we click on on ‘Begin from Scratch’ to create tables.

Xata database

Xata Database

We add tables to our database by clicking the ‘+’ icon on the desk header.

Xata Database

These tables can characterize information attributes, and we are going to create 4 extra tables along with the default id desk, that are:

  • productName, which holds strings
  • productPrice, which incorporates integers ****
  • productImage, is a picture URL, which is a sort of Hyperlink
  • productReview, which holds lengthy texts

Xata Database Tables



Putting in Xata

After creating our database, we set up the Xata CLI globally with this terminal command:

    npm i -g @xata.io/cli
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we authenticate our identification by logging in with this terminal command:

    xata auth login
Enter fullscreen mode

Exit fullscreen mode

After we execute this command, we’re given two choices to both create a brand new API key or use an present key. We are going to create a brand new API key as a result of this can be a new venture. To know extra about Xata API keys, try the Xata documentation.

Subsequent, we initialize our venture by operating this terminal command:

    xata init
Enter fullscreen mode

Exit fullscreen mode

Operating this command will immediate a questionnaire. We should always reply these questions as comply with:

Xata initialization questions

After answering the questions, Xata will add our API key to our .env file, and our venture shall be arrange to make use of Xata.

We restart our growth server for our venture to learn the contents in our .env file.



Creating our Product Evaluate Type

We create our product assessment web page in our index.js file. This web page shall be divided into two sections, one to gather product info and critiques and the opposite to show the product with the information.

On this part, we are going to work on the shape for amassing product information. To create the Tailwind CSS-styled kind, we paste this code into our index.js file.

[https://gist.github.com/Iheanacho-ai/998c7ba832c21a36ff7226e03ee4a4a0]

Subsequent, we add these types in our world.css file to heart and re-size our kind.

    .product-container{
      margin-left: 37%;
      width: 30%;
    }
Enter fullscreen mode

Exit fullscreen mode

Right here is how our product assessment kind appears to be like:

Product Review Form



Embedding the Cloudinary Add Widget

To add photos to our Xata database, we are going to use the Cloudinary add widget. The Cloudinary add widget is an interactive consumer interface that permits customers to add media from numerous sources.

We have to embody the Cloudinary widget JavaScript file within the Head part of our index.js file to make use of the widget.

    <div className= 'product-catalog'> 
      <Head>
        <script src="https://upload-widget.cloudinary.com/world/all.js" kind="textual content/javascript"/>
      </Head>
    ...
Enter fullscreen mode

Exit fullscreen mode

Creating Cloudinary add presets
Cloudinary’s add presets enable us to outline an motion or a set of actions that can happen once we add media.

When performing uploads with the Cloudinary add widget, we have to specify an add preset.

To create an add preset, we go to our Cloudinary Console and click on on the Settings tab.

Cloudinary Console Settings Tab

Subsequent, we click on on the Add tab and scroll right down to the Add presets part of the web page.

Cloudinary Console Upload tab
Cloudinary Console Upload page

Subsequent, we click on on Add add preset. We will use the add preset title given to us by Cloudinary, or rename the add preset.

Then we modify the Signing Mode to ‘Unsigned’ and click on the Save button to avoid wasting our add preset.

Cloudinary Console Upload preset page

We then copy the add preset title as we want it when creating our widget.

Creating our Cloudinary Add Widget
In our index.js file, we create an openupWidget() perform to embed and open up our widget.

  const openupWidget = () => {
    window.cloudinary.openUploadWidget(
      { cloud_name: ***, //we add our cloud title hwe
        upload_preset: 'xoskczw2'
      },
      (error, outcome) => {
        if (!error && outcome && outcome.occasion === "success") {
          console.log(outcome.information.url)       
        }else{
          console.log(error)
        }
      }
    ).open();
  } 
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we do the next:

  • Use the openUploadWidget() methodology that receives two parameters, the cloud_name and our add preset. To get our cloud_name, we go to our Cloudinary Dashboard
  • Logs the picture URL or the error encountered to the console relying on if the add was profitable or not

Subsequent, we move the openupWidget() perform to an onClick occasion listener on our “Add information” button. The onClick occasion listener calls our openupWidget() perform when the button is clicked.

    <button className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" kind="button" onClick= {openupWidget}>
        Add information
    </button>
Enter fullscreen mode

Exit fullscreen mode



Including Interplay with our Xata Database

To effectively work together with the Xata database, we create 4 variables. These variables will gather the information from our types and retailer it in our database.

To create the variables, we have to import the useState hook in our index.js file.

    import { useState } from 'react';
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we create the variables with this piece of code:

    const [productName, setProductName] = useState()
    const [productPrice, setProductPrice] = useState()
    const [productReview, setProductReview] = useState()
    const [productImage, setproductImage] = useState()
Enter fullscreen mode

Exit fullscreen mode

The variables maintain the next info:

  • The productName variable has the title of our product
  • The productPrice variable holds the value of our product
  • The productReview variable incorporates the critiques on our product
  • The productImage variable holds the picture URL of the product

Our openupwidget() perform updates the productImage variable.

  const openupWidget = () => {
    window.cloudinary.openUploadWidget(
      { cloud_name: 'amarachi-2812',
        upload_preset: 'xoskczw2'
      },
      (error, outcome) => {
        if (!error && outcome && outcome.occasion === "success") {
          //we save the picture URL
          setproductImage(outcome.information.url)
        }
      }
    ).open();
  } 
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we put the variables and their respective features within the enter fields to retailer the enter values.

    {/* productName variable goes right here */}
    <div>
       <label htmlFor="about" className="block text-sm font-medium text-gray-700">
          Identify
        </label>
        <div className="mt-1">
            <textarea
              id="about"
              title="about"
              rows={1}
              worth= {productName}
              onChange = {(e)=> setProductName(e.goal.worth)}
              className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"
              />
         </div>     
    </div>

          {/* productPrice variable goes right here */}  
    <div>
       <label htmlFor="about" className="block text-sm font-medium text-gray-700">
          Worth
        </label>
        <div className="mt-1">
           <textarea
              id="productPrice"
              title="productPrice"
              rows={1}
              worth= {productPrice}
              onChange = {(e)=> setProductPrice(e.goal.worth)}
              className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"
            />
        </div>
    </div>

          {/* productReview variable goes right here */}  
    <div>
      <label htmlFor="about" className="block text-sm font-medium text-gray-700">
        Evaluate
        </label>
        <div className="mt-1">
           <textarea
             id="productReview"
              title="productReview"
              rows={3}
              worth= {productReview}
              onChange = {(e)=> setProductReview(e.goal.worth)}
              className="shadow-sm focus:ring-indigo-500 focus:border-indigo-500 mt-1 block w-full sm:text-sm border border-gray-300 rounded-md"
             />
        </div>  
    </div>           
Enter fullscreen mode

Exit fullscreen mode

Including information to our database
In our api/pages folder, we create a add-product.js file to permit us safely work together with our database with out exposing our Xata API key.

Subsequent, we add this code in our /api/add-product.js.

    //pages/api/add-product.js
    import { getXataClient } from '../../src/xata';

    const xata = getXataClient();

    const handler = async (req, res) => {
      const {productName, productPrice, productReview, productImage} = req.physique;
      const outcome = await xata.db["Product-Review"].create({productName, productPrice, productReview, productImage});
      res.ship({outcome});
    };
    export default handler;
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we do the next:

  • Import the getXataClient from the xata file that was routinely created for us throughout venture initialization. We then create a brand new occasion with the getXataClient object
  • We then pull out the productName, productPrice, productReview, and productImage variable from the physique of our request so as to add to the database
  • Move the variables within the Xata create methodology to create information on our database. It is very important observe that we get the create() methodology from the Product-Evaluate object as a result of that’s the title of our database, and the variables are the identical because the tables on our database
  • Ship the ensuing information to the consumer aspect after saving the information in our database

In our index.js file, we create a submitProduct that can question our api/add-product endpoint.

    const submitProduct = () => {
      fetch('/api/add-product', {
        methodology: 'POST',
        headers: {
          'Content material-Sort': 'software/json'
        },
        physique: JSON.stringify({
          productName,
          productPrice,
          productReview,
          productImage
        })
      }).then(() => {
        window.location.reload();
      }).catch((error)=> {
          console.log(error)
      });
    }
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we question the api/add-product endpoint that can safely hook up with the Xata database. We then move the productName, productPrice, productReview, and productImage variables within the request’s physique in order that our endpoint can entry them.

We then move the submitProduct perform to the onClick occasion listener on our ‘Save’ button.

    <button
        kind="submit"
        onClick={submitProduct}
        className="cursor inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
        >
          Save
    </button>
Enter fullscreen mode

Exit fullscreen mode

Deleting information from our database
In our pages/api folder, we create a delete-product.js file. The delete-product.js file will comprise this code.

    import { NextApiHandler } from "subsequent";
    import { getXataClient } from '../../src/xata';

    const xata = getXataClient();
    const handler = async (req, res) => {
      const { id } = req.physique;
      await xata.db["Product-Review"].delete(id);
      res.finish();
    };
    export default handler;
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we delete a product from our database utilizing an id that we get from the request physique. The id permits our handler to search out and efficiently delete a product.

Subsequent, we create a deleteProduct perform in our index.js file.

    const deleteProduct = (id) => {
      fetch("/api/delete-product", {
        methodology: "POST",
        headers: {
          "Content material-Sort": "software/json",
        },
        physique: JSON.stringify({ id }),
      }).then(() => {
        window.location.reload();
      }).catch((error)=> {
          console.log(error)
      });
    }
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we question the /api/delete-product endpoint and move within the id the /api/delete-product handler wants. After deleting the picture, we reload the window to see the adjustments in our software.

Amassing Information from our database
After writing the logic for creating and deleting information, we need to gather it in our database and render it in our software.

In our ìndex.js file, we write this code:

    export const getServerSideProps = async () => {
      const xata = getXataClient();
      const merchandise = await xata.db["Product-Review"].getAll()
      return { props: { merchandise } }
    }
Enter fullscreen mode

Exit fullscreen mode

Querying our information in getServerSideProps ensures that the perform runs on the backend and collects our information earlier than we render the web page.

We move our merchandise as props to our Dwelling web page within the code block above.

    const Dwelling = ({merchandise}) => {
        return(
          ...
        ) 
    }

    export const getServerSideProps = async () => {
      const xata = getXataClient();
      const merchandise = await xata.db.product.getAll()
      return { props: { merchandise } }
    }
Enter fullscreen mode

Exit fullscreen mode

After this part, right here is how our index.js file appears to be like:

https://gist.github.com/Iheanacho-ai/afb5a008c69d01861bd9d6bbd3ecd3d0



Creating our Product Itemizing Web page

After creating the product and its critiques, we need to render it on the house web page.

In our index.js file, we write this piece of code.

    <div className="bg-white">
        <div className="max-w-2xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:max-w-7xl lg:px-8">
        <h2 className="sr-only">Pictures</h2>
        <div className="grid grid-cols-1 gap-y-10 sm:grid-cols-2 gap-x-6 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8">
           {
              merchandise.map(({productImage, productReview, productPrice, id}) => (
                  <a href="#" className="group" id= {id}>
                    <div className="w-full aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden xl:aspect-w-7 xl:aspect-h-8">
                        <img src={productImage} alt="Tall slender porcelain bottle with pure clay textured physique and cork stopper." className="w-full h-full object-center object-cover group-hover:opacity-75" />
                      </div>
                       <h3 className="mt-4 text-sm text-gray-700">${productPrice}</h3>
                        <div>{productReview}</div>
                        <button
                          kind="button"
                          className="cursor inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500"
                        onClick={()=> deleteProduct(id)}
                       >
                      Delete
                    </button>
                  </a>
                ))
              }
            </div>   
        </div>
    </div>
Enter fullscreen mode

Exit fullscreen mode

Within the code block above, we loop by the merchandise prop to render every product with its title, worth, and assessment. Subsequent, we add a deleteProduct() perform on the onClick occasion listener on our ‘Delete’ button.

After this part, right here is how our index.js file appears to be like:

https://gist.github.com/Iheanacho-ai/2b5e21d46f7b7bd75640062592643837

With this, we’ve created our product assessment software. Right here is how our software appears to be like.

Product Review Application

Try our Xata database to see our information getting saved.

Xata Database



Conclusion

This text discusses utilizing the Cloudinary add widget to gather product photos to create a product assessment software and retailer them on our Xata database.



Sources

These sources might be helpful:

Add a Comment

Your email address will not be published. Required fields are marked *

Want to Contribute to us or want to have 15k+ Audience read your Article ? Or Just want to make a strong Backlink?