ReactJS-The Beginner Master Class
  • React In the Beginning
    • Lesson 1 - Demo: Build a Simple React App - Fast
    • Lesson 2 - HTML Review
    • Lesson 3 - CSS Review
    • Lesson 4 - Modern JavaScript (JSX) Patterns
    • Lesson 5 - Set up Dev Environment
    • Hands-on Practice
  • React Fundamentals
    • Lesson 1 - Understanding Old vs New Way of Building Web Apps - SPAs
    • Lesson 2 - Motivation for Using React as the Solution to Vanilla JS
    • Lesson 3 - What is ReactJS - How it Works
    • React Code Along from Scratch
    • Lesson 4 - Create and Run a React Project with Vite - Full Overview
    • Lesson 5 - Create Hook by State Management in React
    • Lesson 6 - React Project File and Folder Walkthrough
    • Lesson 7 - JSX and How React Treats the DOM & JSX Compilation(by Babeljs) - Overview
    • Lesson 8 - Understanding the Main Files - App.jsx and main.jsx
    • Lesson 9 - Props and One-Way Data Flow - Overview
    • Lesson 10 - Google Bookshelf App - Ver 1.0
    • Hands-on Practice I
    • Hands-on Practice II
  • React State and Styling
    • Lesson 1 - Pulling Book Data from a Different Data File
    • Lesson 2 - Overview of How State Works in React
    • Lesson 3 - RandomQuote App
    • Lesson 4 - Lifting State Up - React Pattern Overview
    • Hands-On - Simple Counter
  • Forms and Interactivity - Grocery List App
    • Lesson 1 - Setup a Simple Form and Input
    • Lesson 2 - Build Form Profile App Using Multi-input Form Data
    • Hands-on : Build a Grocery List App
  • Connecting to the Backend - Consuming APIs - UseEffect Hook
    • Lesson 1 - Connecting to the Back End - Understanding Side Effects, Hooks and useEffect - Overview
    • Lesson 2 - Fetching Data from the Backend the Right Way with useEffect Hook
    • Lesson 3 - Setting Up Loading State
    • Hands-on :Use Dependency Array and Adding Values that Control Side Effects
  • Solo Project 1
  • RESTful APIs :Build a BookSearch App -Ver 2.0
    • Lesson 1: Build and test RESTful APIs with Postman
    • Lesson 2 - BookShelf App Structure
    • Lesson 3 - Create NavBar.jsx Component
    • Lesson 4 - Create Footer Component
    • Lesson 5 - Create BookList.jsx Component
    • Lesson 6 - Create BookCard.jsx Component
    • Lesson 7 - Creating Custom Hooks - useBooks and api-client
    • Lesson 8 - Controlling Network Activities in React with AbortController
    • Lesson 9 - Show Book Details in a Modal - Working
    • Lesson 10 - Bookshelf App Summary
  • Multi-Page Applications (MPAs)
    • Build a Multi-Page React Application
    • Multi-Page React Application
    • Hands-on Practice
  • Backend Frameworks-NEXT.JS
    • Migrating from React to Next.js
    • Lesson 1: Key Concepts of NodeJS and Express for Backend Web Development
    • Lesson 2: How to set up a new Next.js project
    • Lesson 3: How to create Layouts and Pages
    • Hands-on Practice 1
    • Hands on Practice 2
      • New Project & Folder Structure
      • File-Based Routing
      • Server vs Client Components & Router Hooks
      • Start On The Navbar
      • Navbar Links, Dropdowns & React Icons
      • Active Links & Conditional Rendering
      • Homepage Components
      • Properties Page
      • Property Card Dynamic Data
      • Home Property Listings
      • Custom Not Found & Loading Pages
  • Git and GitHubs
    • Git Installation
    • Git Commands
    • GitHub Repository
    • Hands-on Practice
  • Database in Application
    • React Supabase CRUD
    • Hands-on: Note Taking App
  • NoSQL Database
    • Installing MongoDB Community Edition
    • System Env Path Setting
    • How to use MongoDB Shell
    • How to Connect and Use Mongosh in VS Code via MongoDB Extension
    • MongoDB Guide
  • Solo Project 2
  • Deployment and Web Hosting
    • Lesson 1. React+Vite+TS+Shadcn Project
    • Lesson 2. Deploying a React Vite App to Vercel from Vercel CLI
    • Lesson 3 Connecting to GitHub Repo and Automate Deployment
  • Solo Project 3
  • Final Term Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 1 Team Project
    • Level 2 Team Project
    • Level 2 Team Project
    • Level 3 Team Project
    • Level 3 Team Project
Powered by GitBook
On this page
  • Properties Pages and Property Card Dynamic Data
  • 1. Prepare Your Data Source
  • 2. Create a Dynamic PropertyCard Component
  • Explanation:
  • 3. Integrate the PropertyCard Component in the Properties Page
  • 4. Testing and Refinements
  • 5. Future Enhancements
  • Recap
  1. Backend Frameworks-NEXT.JS
  2. Hands on Practice 2

Property Card Dynamic Data

Properties Pages and Property Card Dynamic Data

1. Prepare Your Data Source

a. Place the JSON File

  • Ensure that your properties.json file is located in your project root (or in a dedicated data folder).

  • This file contains an array of property objects with fields such as _id, name, type, location, rates, images, etc.

b. Understand the JSON Structure

  • Each property has:

    • Basic Details: _id, name, type, beds, baths, square_feet

    • Location: A nested object with street, city, state, zipcode

    • Rates: An object that might include nightly, weekly, or monthly values

    • Images: An array of image filenames (to be prefixed with /images/properties/ for public access)


2. Create a Dynamic PropertyCard Component

a. Create the Component File

  • In your components/ folder, create a file named PropertyCard.jsx.

b. Import Required Modules

  • Import Next.js’ Image and Link components along with React icons for a more stylish look:

    "use client"; // Enable client-side interactivity if needed
    import Image from 'next/image';
    import Link from 'next/link';
    import { FaBed, FaBath, FaRulerCombined, FaMoneyBill, FaMapMarkerAlt } from 'react-icons/fa';

c. Build the Component Structure

  • The component receives a single property object as a prop and dynamically displays its data. Create a helper function to determine the proper rate display.

  • Example Code:

    'use client' // Enable client-side interactivity if needed
    import Image from 'next/image'
    import Link from 'next/link'
    import {
      FaBed,
      FaBath,
      FaRulerCombined,
      FaMoneyBill,
      FaMapMarkerAlt,
    } from 'react-icons/fa'
    
    export default function PropertyCard({ property }) {
      // Helper function to choose a rate to display
      const getRateDisplay = () => {
        const { rates } = property
        if (rates.monthly) {
          return `$${rates.monthly.toLocaleString()}/mo`
        } else if (rates.weekly) {
          return `$${rates.weekly.toLocaleString()}/wk`
        } else if (rates.nightly) {
          return `$${rates.nightly.toLocaleString()}/night`
        }
        return 'Contact for rates'
      }
    
      return (
        <div className="bg-white rounded-xl shadow-md relative ">
          {/* Display the first image from the array */}
          <Image
            src={`/images/properties/${property.images[0]}`}
            alt={property.name}
            width={0} // Set to 0 when using CSS for responsive sizing
            height={0}
            sizes="100vw"
            className="object-cover rounded-t-xl md:rounded-tr-none md:rounded-l-xl w-full "
          />
    
          <div className="p-6">
            <div className="text-left md:text-center lg:text-left mb-6">
              <h3 className="text-xl font-bold">{property.name}</h3>
              <div className="text-gray-600 mb-4">{property.type}</div>
            </div>
            {/* Rate display badge */}
            <h3 className="absolute top-2 left-2 bg-white px-4 py-2 rounded-lg text-blue-500 font-bold">
              {getRateDisplay()}
            </h3>
    
            <div className="flex justify-between items-center ">
              <div className="flex gap-2 text-gray-500">
                <p>
                  <FaBed className="inline mr-1" /> {property.beds}
                </p>
                <p>
                  <FaBath className="inline mr-1" /> {property.baths}
                </p>
                <p>
                  <FaRulerCombined className="inline mr-1" /> {property.square_feet}{' '}
                  sqft
                </p>
              </div>
            </div>
            <div className="flex justify-center gap-4 text-green-900 text-sm mb-4">
              {property.rates.nightly && (
                <p>
                  <i className="fa-solid fa-money-bill"></i> Nightly
                </p>
              )}
              {property.rates.weekly && (
                <p>
                  <i className="fa-solid fa-money-bill"></i> Weekly
                </p>
              )}
              {property.rates.monthly && (
                <p>
                  <i className="fa-solid fa-money-bill"></i> Monthly
                </p>
              )}
            </div>
          </div>
          <div className="border border-gray-200 mb-5">
            <div className="flex flex-col lg:flex-row justify-between mb-4">
              <div className=" flex align-middle gap-2 mb-4 lg:mb-0">
                <FaMapMarkerAlt className="text-orange-700 mr-1" />
                <span className="text-orange-700">
                  {property.location.city}, {property.location.state}
                </span>
              </div>
              <Link
                href={`/properties/${property._id}`}
                className="h-[36px]  bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg text-sm">
                Details
              </Link>
            </div>
          </div>
        </div>
      )
    }

Explanation:

  1. 'use client':

    • This directive at the top indicates that this component is a Client Component in Next.js. This means it will be rendered in the user's browser and can use client-side features like event handlers and state.

  2. Imports:

    • Image from next/image: For optimized image rendering.

    • Link from next/link: For creating client-side navigation links.

    • FaBed, FaBath, FaRulerCombined, FaMoneyBill, FaMapMarkerAlt from react-icons/fa: These are icons from the react-icons library (specifically, Font Awesome icons) used to visually represent beds, baths, square footage, rates, and location.

  3. PropertyCard({ property }) Function:

    • This is a functional component that accepts a property object as a prop. This property object will contain all the details of a single property (like name, type, location, rates, etc.).

  4. getRateDisplay() Helper Function:

    • This function determines which rate to display (monthly, weekly, or nightly) based on the rates object within the property data.

    • It prioritizes monthly, then weekly, then nightly.

    • It uses toLocaleString() to format the number with commas (e.g., 4200 becomes 4,200).

    • If no rates are available, it returns "Contact for rates".

  5. JSX Structure (The return statement):

    • Outer div:

      • className="bg-white rounded-xl shadow-md relative": This sets the basic styling for the card: white background, rounded corners, a shadow, and relative positioning (for absolute positioning of the rate badge).

    • Image Component:

      • src={/images/properties/${property.images[0]}}: Dynamically sets the image source to the first image in the property.images array. It assumes images are stored in the /public/images/properties directory.

      • alt={property.name}: Sets the alt text for accessibility.

      • width={0}, height={0}, sizes="100vw": These are important for responsive image sizing with next/image. By setting width and height to 0, you're telling Next.js to let the CSS determine the image dimensions. sizes="100vw" tells Next.js that the image will take up the full width of the viewport.

      • className="object-cover rounded-t-xl md:rounded-tr-none md:rounded-l-xl w-full": Styles the image to cover the container, have rounded corners at the top, and adjust the rounding on medium screens and up.

    • Inner div (Content):

      • className="p-6": Adds padding to the content area.

      • Property Name and Type:

        • h3 className="text-xl font-bold">{property.name}: Displays the property's name in a large, bold font.

        • div className="text-gray-600 mb-4">{property.type}: Displays the property's type (e.g., "Apartment", "Condo").

      • Rate Badge:

        • h3 className="absolute top-2 left-2 bg-white px-4 py-2 rounded-lg text-blue-500 font-bold": Displays the rate (from getRateDisplay()) as a badge in the top-left corner of the card.

      • Beds, Baths, and Square Footage:

        • div className="flex justify-between items-center": A flex container to align the icons and text.

        • div className="flex gap-2 text-gray-500": A flex container for the icons and text.

        • <FaBed>, <FaBath>, <FaRulerCombined>: The icons.

        • {property.beds}, {property.baths}, {property.square_feet}: The property data.

      • Rate Types:

        • div className="flex justify-center gap-4 text-green-900 text-sm mb-4": A flex container to display the rate types.

        • The code conditionally renders the rate types based on the property data.

      • Location and Details Link

        • div className="border border-gray-200 mb-5": A horizontal line to separate the content.

        • div className="flex flex-col lg:flex-row justify-between mb-4": A flex container to align the location and the details link.

        • <FaMapMarkerAlt>: The location icon.

        • {property.location.city}, {property.location.state}: The property's city and state.

        • <Link href={/properties/${property._id}}: A link to the property's detail page. The _id is used to create a unique URL for each property.

In Summary:

The PropertyCard component is a reusable UI element that takes property data and renders a visually appealing card with key information about the property. It handles:

  • Displaying an image.

  • Showing the property's name, type, and location.

  • Dynamically choosing and formatting the appropriate rate.

  • Displaying the number of beds, baths, and square footage.

  • Providing a link to the full property details page.

  • Responsive design.

  • Using icons to improve the UI.


3. Integrate the PropertyCard Component in the Properties Page

a. Create/Update the Properties Page

  • In your Next.js project (using the new app directory), create or update the file:

    app/properties/page.jsx

b. Import the JSON Data and Component

  • Import your JSON file and the PropertyCard component:

    import PropertyCard from '@/components/PropertyCard';
    import properties from '@/properties.json'; // Adjust path if necessary

c. Render the List of Property Cards

  • Update page.jsx by applying conditional rendering to check if properties exist. If so, map over the data and render a PropertyCard for each item.

  • Example Code:

    //app/properties/page.jsx
    import properties from '@/properties.json' // Adjust the path as needed
    import PropertyCard from '@/components/PropertyCard'
    
    export default function PropertiesPage() {
      return (
        <section className="container mx-auto px-4 py-6">
          <h2 className="text-3xl font-bold text-blue-500 mb-6 text-center">All Listings</h2>
          {properties.length === 0 ? (
            <p>No properties found.</p>
          ) : (
            <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
              {properties.map((property) => (
                <PropertyCard key={property._id} property={property} />
              ))}
            </div>
          )}
        </section>
      );
    }

4. Testing and Refinements

a. Run the Development Server

  • Start your Next.js server:

    npm run dev
  • Open your browser and navigate to http://localhost:3000/properties.

b. Verify Dynamic Data Rendering

  • Ensure that each property card displays the dynamic data from properties.json:

    • The image should load from the public folder (using the first image in the array).

    • Property details like name, type, rates, beds, baths, and location should display correctly.

    • The “Details” link should dynamically point to the property’s unique route (e.g., /property/1).

c. Adjust Component Styling if Needed

  • Refine Tailwind CSS classes and layout to achieve the desired visual appearance and responsiveness.

  • Verify that the Next.js Image component is handling responsive image sizes appropriately.


5. Future Enhancements

  • API Integration: Replace the static JSON import with an API call or database query for real-time data.

  • Pagination & Filtering: Implement pagination and search/filter functionalities to manage large sets of property listings.

  • Dynamic Routing: Create a detailed property page that displays full information when a user clicks “Details.”


Recap

  1. Data Source Preparation: Place and understand the properties.json file.

  2. PropertyCard Component: Create a dynamic, reusable component that accepts a property object as a prop and displays its data using Next.js Image and React icons.

  3. Properties Page Integration: Import the JSON data and map through it to render a list of property cards.

  4. Testing: Run your development server and verify that the property cards are rendered dynamically with real-time data.

  5. Future Enhancements: Plan for API integration, pagination, and detailed property pages.

PreviousProperties PageNextHome Property Listings

Last updated 2 months ago