Not working multi-filter system in my real estate laravel 10 project

Hello everyone! I hope you all are doing well. I am developing a real estate website, there is a property page. In this page the requirement is that there will be a multi filtering system. User can filter properties by category, price range, parking spots, and BHK(Bedroom, Hall and Kitchen). Suppose user first will select apartment category, according to that category every property will show, after that suppose user will select 3 BHK, then 3 BHK apartment properties will show, after that suppose user will select a price range between 2000 and 3000 USD, then 3 BHK apartment properties which has a price range between 2000 and 3000 USD will show. Right now Category filter is working but other filters are not working accordingly.

Here is the property.blade.php :-



@extends('frontend.layouts.main')

@section('main-container')

<div class="page-heading header-text">
  <div class="container">
    <div class="row">
      <div class="col-lg-12">
        <span class="breadcrumb"><a href="#">Home</a> / Properties</span>
        <h3>Properties</h3>
      </div>
    </div>
  </div>
</div>

<div class="section properties">
  <div class="container">
    <ul class="properties-filter">
      <li><a class="is_active" href="#!" data-filter="*">Show All</a></li>
      <li><a href="#!" data-filter=".apartment">Apartment</a></li>
      <li><a href="#!" data-filter=".luxury-villa">Luxury Villa</a></li>
      <li><a href="#!" data-filter=".penthouse">Penthouse</a></li>
      <li><a href="#!" data-filter=".modern-condo">Modern Condo</a></li>
    </ul>
    <div class="filters">
      <!-- Price Filter -->
      <div class="filter-item">
        <label for="priceRange">Price Range:</label>
        <input type="range" id="priceRange" min="500" max="3000" value="500" class="slider">
        <span id="priceValue">0</span>
    </div>


      <!-- Parking Lots Filter -->
      <div class="filter-item">
          <label>Parking Spots:</label>
          <div>
              @foreach([3, 6, 8, 10] as $spots)
              <input type="radio" id="parking{{ $spots }}" name="parkingSpots" value="{{ $spots }}">
              <label for="parking{{ $spots }}">{{ $spots }} spots</label>
              @endforeach
          </div>
      </div>

      <!-- BHK Filter -->
      <div class="filter-item">
          <label for="bhk">BHK:</label>
          <select id="bhk" class="form-select">
              <option value="*">All</option>
              @foreach([2, 3, 4] as $bhk)
              <option value="{{ $bhk }}">{{ $bhk }} BHK</option>
              @endforeach
          </select>
      </div>
  </div>

    <div class="row properties-box">
      @foreach ($properties as $property)
      <div class="col-lg-4 col-md-6 align-self-center mb-30 properties-items {{ strtolower(str_replace(' ', '-',   $property->category_name)) }}"
        data-price="{{ $property->price }}"
        data-bhk="{{ $property->bhk }}"
        data-parking="{{ $property->parking }}">

        <div class="item">
            <a href="{{ route('property-details', $property->id) }}"><img src="{{ asset('storage/' . $property->property_image) }}" alt=""></a>
            <span class="category">{{ $property->category_name }}</span>
            <h6>{{ $property->price }}</h6>
            <h4><a href="{{ route('property-details', $property->id) }}">{{$property->property_name}}</a></h4>
            <ul>
                <li>Address: <span><a href="{{ route('property-details', $property->id) }}">{{ $property->address }}</a></span></li>
                <li><span>{{ $property->bhk }} BHK</span></li>
                <li>Area: <span>{{ $property->area }}</span></li>
                @if (in_array($property->category_name, ["Apartment", "Penthouse", "Modern Condo"]))
                <li>Floor: <span>{{ $property->floor }}th</span></li>
                @else
                <li>Floor: <span>{{ $property->floor }}</span></li>
                @endif
                <li>Parking: <span>{{ $property->parking }}</span></li>
            </ul>
            <div class="main-button">
                <a href="{{ route('property-details', $property->id) }}">Schedule a visit</a>
            </div>
        </div>
    </div>
@endforeach
</div>
    </div>
     <!-- Pagination -->
     <div class="row">
      <div class="col-lg-12">
          {{ $properties->links() }}
      </div>
  </div>
  </div>
</div>

    @endsection

    @section('title')
    Property
    @endsection



property-fliter-script.js :-

document.addEventListener("DOMContentLoaded", function() {
    const filters = {
        category: document.querySelectorAll('.properties-filter a'),
        priceRange: document.getElementById('priceRange'),
        parkingSpots: document.querySelectorAll('input[name="parkingSpots"]'),
        bhk: document.getElementById('bhk')
    };

    const priceValueDisplay = document.getElementById('priceValue');

    // Function to initially show all properties when the page loads
    function showAllProperties() {
        document.querySelectorAll('.properties-items').forEach(item => {
            item.style.display = "block";
        });
    }

    // Initial function call to show all properties
    showAllProperties();

    // Update price display
    filters.priceRange.oninput = function() {
        priceValueDisplay.textContent = `$${this.value}`;
        applyFilters();
    }

    function applyFilters() {
        const selectedPrice = parseInt(filters.priceRange.value, 10);
        let selectedParking = null;
        filters.parkingSpots.forEach(radio => {
            if (radio.checked) selectedParking = parseInt(radio.value, 10);
        });
        const selectedBhk = parseInt(filters.bhk.value, 10);

        document.querySelectorAll('.properties-items').forEach(item => {
            const price = parseInt(item.dataset.price, 10);
            const parking = parseInt(item.dataset.parking, 10);
            const bhk = parseInt(item.dataset.bhk, 10);

            const priceMatch = !selectedPrice || (price <= selectedPrice);
            const parkingMatch = !selectedParking || (parking === selectedParking);
            const bhkMatch = !selectedBhk || (bhk === selectedBhk);

            item.style.display = (priceMatch && parkingMatch && bhkMatch) ? "block" : "none";
        });
    }

    // Event listeners for BHK and Parking changes
    filters.bhk.addEventListener('change', applyFilters);
    filters.parkingSpots.forEach(radio => radio.addEventListener('change', applyFilters));

    // Apply category filters independently from the other filters
    filters.category.forEach(filter => {
        filter.addEventListener('click', function(e) {
            e.preventDefault();
            const category = this.getAttribute('data-filter');
            document.querySelectorAll('.properties-items').forEach(item => {
                if (category === "*" || item.classList.contains(category.substring(1))) {
                    item.style.display = "block";
                } else {
                    item.style.display = "none";
                }
            });
            filters.category.forEach(f => f.classList.remove('is_active'));
            this.classList.add('is_active');
        });
    });
});


PropertyController.php :-

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\PropertyDetail; 

class PropertyController extends Controller
{
    public function index(){
        // Fetch 6 properties from the database
        $properties = PropertyDetail::paginate(6);

        // Pass the properties to the view
        return view('frontend.property', compact('properties'));
    }

    /**
     * Show the details for a specific property.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function showPropertyDetails($id)
    {
        // Fetch the property detail by ID
        $property = PropertyDetail::findOrFail($id);

        // Pass the property detail to the view
        return view('frontend.property-details', compact('property'));
    }


}



Please help me. Is there a way to resolve this ? are there any libraries or any other way to fix this issue.

Is there somewhere we can see this working (or not, as the case may be)?

I would probably simplify this to being a document.querySelector pulling just the checked radio element, but to each their own…

Here is the link. https://real-estate-vila.000webhostapp.com/property
Have a look.

price isnt matching because your price data includes a dollar sign, which parseInt cant handle. If i remove the $'s from your prices manually, the filter works correctly.

Ok, I understand what you are saying for the price filter but what about the BHK and Parking spots filters ? Suppose I select Luxury Villa then Luxury Villa properties will show , after that I select 3 BHK, then 3 BHK Luxury Villa properties will show without page reload or clicking on any search button and after that if I select 6 parking spots then 3 BHK Luxury Villa properties which have 6 parking spots will show, how this can be done? I am open to all suggestions and ideas. Please help.

your filters are all combining (at the end you AND them all together), so the price one is screwing everything up. when you fix the price data, the rest of your filters work.

1 Like

Thank you very much, all the filters are working perfectly. Price filter was the major issue, from the backend admin section I edited and removed $ from every properties. I really appreciate your taking the time to explain things. Thank you again.

1 Like