diff --git a/db-snapshots/db-snapshot.sql b/db-snapshots/db-snapshot.sql
index 34d3f647..096a4fbd 100644
--- a/db-snapshots/db-snapshot.sql
+++ b/db-snapshots/db-snapshot.sql
@@ -407,4 +407,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2025-11-28 16:36:00
+-- Dump completed on 2025-11-28 16:37:18
diff --git a/wp-content/themes/homeproz/dist/assets/main.js b/wp-content/themes/homeproz/dist/assets/main.js
index 036b2f15..1a292102 100644
--- a/wp-content/themes/homeproz/dist/assets/main.js
+++ b/wp-content/themes/homeproz/dist/assets/main.js
@@ -1 +1 @@
-(function(e){var a=e(".menu-toggle"),o=e(".mobile-navigation");a.length&&(a.on("click",function(){var n=e(this).attr("aria-expanded")==="true";e(this).attr("aria-expanded",!n),o.toggleClass("is-open"),n?e("body").removeClass("mobile-menu-open"):e("body").addClass("mobile-menu-open")}),e(document).on("keydown",function(n){n.key==="Escape"&&o.hasClass("is-open")&&(a.attr("aria-expanded","false"),o.removeClass("is-open"),e("body").removeClass("mobile-menu-open"))}),e(document).on("click",function(n){o.hasClass("is-open")&&!e(n.target).closest(".mobile-navigation").length&&!e(n.target).closest(".menu-toggle").length&&(a.attr("aria-expanded","false"),o.removeClass("is-open"),e("body").removeClass("mobile-menu-open"))}))})(jQuery);(function(e){e(function(){})})(jQuery);
+(function(r){var n=r(".menu-toggle"),t=r(".mobile-navigation");n.length&&(n.on("click",function(){var e=r(this).attr("aria-expanded")==="true";r(this).attr("aria-expanded",!e),t.toggleClass("is-open"),e?r("body").removeClass("mobile-menu-open"):r("body").addClass("mobile-menu-open")}),r(document).on("keydown",function(e){e.key==="Escape"&&t.hasClass("is-open")&&(n.attr("aria-expanded","false"),t.removeClass("is-open"),r("body").removeClass("mobile-menu-open"))}),r(document).on("click",function(e){t.hasClass("is-open")&&!r(e.target).closest(".mobile-navigation").length&&!r(e.target).closest(".menu-toggle").length&&(n.attr("aria-expanded","false"),t.removeClass("is-open"),r("body").removeClass("mobile-menu-open"))}))})(jQuery);(function(r){var n={$form:null,$results:null,$filters:null,isFirstLoad:!0,isLoading:!1,init:function(){this.$form=r(".filters-form"),this.$results=r("#property-results"),this.$filters=r("#property-filters"),!(!this.$form.length||!this.$results.length)&&(this.bindEvents(),this.initFromUrl())},bindEvents:function(){var t=this;this.$form.on("submit",function(e){e.preventDefault(),t.filterProperties(1)}),this.$form.find("select").on("change",function(){t.filterProperties(1)}),r(".filters-reset").on("click",function(e){e.preventDefault(),t.resetFilters()}),this.$results.on("click",".pagination a",function(e){e.preventDefault();var i=t.getPageFromUrl(r(this).attr("href"));t.filterProperties(i)}),r(window).on("popstate",function(e){e.originalEvent.state&&e.originalEvent.state.propertyFilters&&(t.setFormFromState(e.originalEvent.state.propertyFilters),t.filterProperties(e.originalEvent.state.page||1,!1))})},initFromUrl:function(){var t=new URLSearchParams(window.location.search),e=!1;if(this.$form.find("select").each(function(){var s=r(this).attr("name");t.has(s)&&(r(this).val(t.get(s)),e=!0)}),e){var i=this.getFormState();i.page=parseInt(t.get("paged"))||1,history.replaceState({propertyFilters:i,page:i.page},"",window.location.href)}},filterProperties:function(t,e){if(!this.isLoading){e=e!==!1,t=t||1;var i=this,s=this.getFormData();s.paged=t,this.isLoading=!0,this.$filters.addClass("is-loading"),this.isFirstLoad&&this.$results.html('
'),r.ajax({url:homeprozAjax.ajaxUrl,type:"POST",data:{action:"homeproz_filter_properties",nonce:homeprozAjax.nonce,property_type:s.property_type,property_status:s.property_status,property_location:s.property_location,min_price:s.min_price,max_price:s.max_price,beds:s.beds,sort:s.sort,paged:t},success:function(o){o.success&&(i.$results.html(o.data.html),i.isFirstLoad=!1,e&&i.updateUrl(s,t),t>1&&r("html, body").animate({scrollTop:i.$filters.offset().top-100},300))},error:function(){i.$results.html('Error
Something went wrong. Please try again.
')},complete:function(){i.isLoading=!1,i.$filters.removeClass("is-loading")}})}},getFormData:function(){return{property_type:this.$form.find('[name="property_type"]').val()||"",property_status:this.$form.find('[name="property_status"]').val()||"",property_location:this.$form.find('[name="property_location"]').val()||"",min_price:this.$form.find('[name="min_price"]').val()||"",max_price:this.$form.find('[name="max_price"]').val()||"",beds:this.$form.find('[name="beds"]').val()||"",sort:this.$form.find('[name="sort"]').val()||"newest"}},getFormState:function(){return this.getFormData()},setFormFromState:function(t){for(var e in t)this.$form.find('[name="'+e+'"]').val(t[e])},updateUrl:function(t,e){var i=new URL(homeprozAjax.archiveUrl);for(var s in t)t[s]&&t[s]!=="newest"&&i.searchParams.set(s,t[s]);e>1&&i.searchParams.set("paged",e);var o={propertyFilters:t,page:e};history.pushState(o,"",i.toString())},getPageFromUrl:function(t){var e=t.match(/[?&]paged=(\d+)/);return e?parseInt(e[1]):1},resetFilters:function(){this.$form.find("select").val(""),this.$form.find('[name="sort"]').val("newest"),this.filterProperties(1)}};r(function(){n.init()})})(jQuery);(function(r){r(function(){})})(jQuery);
diff --git a/wp-content/themes/homeproz/functions.php b/wp-content/themes/homeproz/functions.php
index e290e2bd..21cd80c5 100644
--- a/wp-content/themes/homeproz/functions.php
+++ b/wp-content/themes/homeproz/functions.php
@@ -34,3 +34,6 @@ require_once HOMEPROZ_DIR . '/inc/custom-post-types.php';
// ACF field definitions
require_once HOMEPROZ_DIR . '/inc/acf-fields.php';
+
+// AJAX handlers
+require_once HOMEPROZ_DIR . '/inc/ajax-handlers.php';
diff --git a/wp-content/themes/homeproz/inc/ajax-handlers.php b/wp-content/themes/homeproz/inc/ajax-handlers.php
new file mode 100644
index 00000000..16c62be1
--- /dev/null
+++ b/wp-content/themes/homeproz/inc/ajax-handlers.php
@@ -0,0 +1,231 @@
+ 'property',
+ 'posts_per_page' => 12,
+ 'paged' => $paged,
+ );
+
+ // Taxonomy filters
+ $tax_query = array();
+
+ if ($property_type) {
+ $tax_query[] = array(
+ 'taxonomy' => 'property_type',
+ 'field' => 'slug',
+ 'terms' => $property_type,
+ );
+ }
+
+ if ($property_status) {
+ $tax_query[] = array(
+ 'taxonomy' => 'property_status',
+ 'field' => 'slug',
+ 'terms' => $property_status,
+ );
+ }
+
+ if ($property_location) {
+ $tax_query[] = array(
+ 'taxonomy' => 'property_location',
+ 'field' => 'slug',
+ 'terms' => $property_location,
+ );
+ }
+
+ if (!empty($tax_query)) {
+ $args['tax_query'] = $tax_query;
+ if (count($tax_query) > 1) {
+ $args['tax_query']['relation'] = 'AND';
+ }
+ }
+
+ // Meta query for price and bedrooms
+ $meta_query = array();
+
+ if ($min_price) {
+ $meta_query[] = array(
+ 'key' => 'property_price',
+ 'value' => $min_price,
+ 'type' => 'NUMERIC',
+ 'compare' => '>=',
+ );
+ }
+
+ if ($max_price) {
+ $meta_query[] = array(
+ 'key' => 'property_price',
+ 'value' => $max_price,
+ 'type' => 'NUMERIC',
+ 'compare' => '<=',
+ );
+ }
+
+ if ($beds) {
+ $meta_query[] = array(
+ 'key' => 'bedrooms',
+ 'value' => $beds,
+ 'type' => 'NUMERIC',
+ 'compare' => '>=',
+ );
+ }
+
+ if (!empty($meta_query)) {
+ $args['meta_query'] = $meta_query;
+ if (count($meta_query) > 1) {
+ $args['meta_query']['relation'] = 'AND';
+ }
+ }
+
+ // Sorting
+ switch ($sort) {
+ case 'oldest':
+ $args['orderby'] = 'date';
+ $args['order'] = 'ASC';
+ break;
+ case 'price_low':
+ $args['meta_key'] = 'property_price';
+ $args['orderby'] = 'meta_value_num';
+ $args['order'] = 'ASC';
+ break;
+ case 'price_high':
+ $args['meta_key'] = 'property_price';
+ $args['orderby'] = 'meta_value_num';
+ $args['order'] = 'DESC';
+ break;
+ case 'newest':
+ default:
+ $args['orderby'] = 'date';
+ $args['order'] = 'DESC';
+ break;
+ }
+
+ $properties = new WP_Query($args);
+
+ ob_start();
+
+ // Results Meta
+ ?>
+
+
+ have_posts()) : ?>
+
+ have_posts()) :
+ $properties->the_post();
+ get_template_part('template-parts/property/property-card');
+ endwhile;
+ ?>
+
+
+ add_query_arg('paged', '%#%', $base_url),
+ 'format' => '',
+ 'current' => max(1, $paged),
+ 'total' => $properties->max_num_pages,
+ 'prev_text' => '← Previous',
+ 'next_text' => 'Next →',
+ 'type' => 'array',
+ 'add_args' => $filter_args,
+ ));
+
+ if ($pagination) :
+ ?>
+
+
+
+
+
+
No Properties Found
+
We couldn't find any properties matching your criteria. Try adjusting your filters or browse all properties.
+
View All Properties
+
+
+
+ $html,
+ 'found_posts' => $properties->found_posts,
+ 'max_pages' => $properties->max_num_pages,
+ ));
+}
+add_action('wp_ajax_homeproz_filter_properties', 'homeproz_ajax_filter_properties');
+add_action('wp_ajax_nopriv_homeproz_filter_properties', 'homeproz_ajax_filter_properties');
+
+/**
+ * Localize script data for AJAX
+ */
+function homeproz_localize_ajax_data() {
+ if (is_post_type_archive('property') || is_tax('property_type') || is_tax('property_status') || is_tax('property_location')) {
+ wp_localize_script('homeproz-main', 'homeprozAjax', array(
+ 'ajaxUrl' => admin_url('admin-ajax.php'),
+ 'nonce' => wp_create_nonce('homeproz_filter_nonce'),
+ 'archiveUrl' => get_post_type_archive_link('property'),
+ ));
+ }
+}
+add_action('wp_enqueue_scripts', 'homeproz_localize_ajax_data', 20);
diff --git a/wp-content/themes/homeproz/src/main.js b/wp-content/themes/homeproz/src/main.js
index c5fa37ea..74c6659f 100644
--- a/wp-content/themes/homeproz/src/main.js
+++ b/wp-content/themes/homeproz/src/main.js
@@ -8,6 +8,7 @@ import './main.scss';
// Import component JS
import '../template-parts/header/navigation.js';
+import '../template-parts/property/property-filters.js';
(function($) {
'use strict';
diff --git a/wp-content/themes/homeproz/template-parts/property/property-filters.js b/wp-content/themes/homeproz/template-parts/property/property-filters.js
new file mode 100644
index 00000000..70493dc4
--- /dev/null
+++ b/wp-content/themes/homeproz/template-parts/property/property-filters.js
@@ -0,0 +1,244 @@
+/**
+ * Property Filters JavaScript
+ *
+ * AJAX filtering for property archive
+ *
+ * @package HomeProz
+ */
+
+(function($) {
+ 'use strict';
+
+ var PropertyFilters = {
+ // Elements
+ $form: null,
+ $results: null,
+ $filters: null,
+
+ // State
+ isFirstLoad: true,
+ isLoading: false,
+
+ /**
+ * Initialize
+ */
+ init: function() {
+ this.$form = $('.filters-form');
+ this.$results = $('#property-results');
+ this.$filters = $('#property-filters');
+
+ if (!this.$form.length || !this.$results.length) {
+ return;
+ }
+
+ this.bindEvents();
+ this.initFromUrl();
+ },
+
+ /**
+ * Bind events
+ */
+ bindEvents: function() {
+ var self = this;
+
+ // Form submission (Search button)
+ this.$form.on('submit', function(e) {
+ e.preventDefault();
+ self.filterProperties(1);
+ });
+
+ // Filter changes (auto-submit on select change)
+ this.$form.find('select').on('change', function() {
+ self.filterProperties(1);
+ });
+
+ // Reset button
+ $('.filters-reset').on('click', function(e) {
+ e.preventDefault();
+ self.resetFilters();
+ });
+
+ // Pagination clicks (delegated)
+ this.$results.on('click', '.pagination a', function(e) {
+ e.preventDefault();
+ var page = self.getPageFromUrl($(this).attr('href'));
+ self.filterProperties(page);
+ });
+
+ // Handle browser back/forward
+ $(window).on('popstate', function(e) {
+ if (e.originalEvent.state && e.originalEvent.state.propertyFilters) {
+ self.setFormFromState(e.originalEvent.state.propertyFilters);
+ self.filterProperties(e.originalEvent.state.page || 1, false);
+ }
+ });
+ },
+
+ /**
+ * Initialize filters from URL params
+ */
+ initFromUrl: function() {
+ var params = new URLSearchParams(window.location.search);
+ var hasFilters = false;
+
+ // Set form values from URL
+ this.$form.find('select').each(function() {
+ var name = $(this).attr('name');
+ if (params.has(name)) {
+ $(this).val(params.get(name));
+ hasFilters = true;
+ }
+ });
+
+ // Save initial state
+ if (hasFilters) {
+ var state = this.getFormState();
+ state.page = parseInt(params.get('paged')) || 1;
+ history.replaceState({ propertyFilters: state, page: state.page }, '', window.location.href);
+ }
+ },
+
+ /**
+ * Filter properties via AJAX
+ */
+ filterProperties: function(page, updateHistory) {
+ if (this.isLoading) {
+ return;
+ }
+
+ updateHistory = updateHistory !== false;
+ page = page || 1;
+
+ var self = this;
+ var formData = this.getFormData();
+ formData.paged = page;
+
+ // Show loading state
+ this.isLoading = true;
+ this.$filters.addClass('is-loading');
+
+ // Show spinner only on first load
+ if (this.isFirstLoad) {
+ this.$results.html('');
+ }
+
+ $.ajax({
+ url: homeprozAjax.ajaxUrl,
+ type: 'POST',
+ data: {
+ action: 'homeproz_filter_properties',
+ nonce: homeprozAjax.nonce,
+ property_type: formData.property_type,
+ property_status: formData.property_status,
+ property_location: formData.property_location,
+ min_price: formData.min_price,
+ max_price: formData.max_price,
+ beds: formData.beds,
+ sort: formData.sort,
+ paged: page
+ },
+ success: function(response) {
+ if (response.success) {
+ self.$results.html(response.data.html);
+ self.isFirstLoad = false;
+
+ // Update URL
+ if (updateHistory) {
+ self.updateUrl(formData, page);
+ }
+
+ // Scroll to top of results on page change
+ if (page > 1) {
+ $('html, body').animate({
+ scrollTop: self.$filters.offset().top - 100
+ }, 300);
+ }
+ }
+ },
+ error: function() {
+ self.$results.html('Error
Something went wrong. Please try again.
');
+ },
+ complete: function() {
+ self.isLoading = false;
+ self.$filters.removeClass('is-loading');
+ }
+ });
+ },
+
+ /**
+ * Get form data as object
+ */
+ getFormData: function() {
+ return {
+ property_type: this.$form.find('[name="property_type"]').val() || '',
+ property_status: this.$form.find('[name="property_status"]').val() || '',
+ property_location: this.$form.find('[name="property_location"]').val() || '',
+ min_price: this.$form.find('[name="min_price"]').val() || '',
+ max_price: this.$form.find('[name="max_price"]').val() || '',
+ beds: this.$form.find('[name="beds"]').val() || '',
+ sort: this.$form.find('[name="sort"]').val() || 'newest'
+ };
+ },
+
+ /**
+ * Get form state for history
+ */
+ getFormState: function() {
+ return this.getFormData();
+ },
+
+ /**
+ * Set form from state
+ */
+ setFormFromState: function(state) {
+ for (var key in state) {
+ this.$form.find('[name="' + key + '"]').val(state[key]);
+ }
+ },
+
+ /**
+ * Update browser URL
+ */
+ updateUrl: function(formData, page) {
+ var url = new URL(homeprozAjax.archiveUrl);
+
+ // Add non-empty filters to URL
+ for (var key in formData) {
+ if (formData[key] && formData[key] !== 'newest') {
+ url.searchParams.set(key, formData[key]);
+ }
+ }
+
+ // Add page if > 1
+ if (page > 1) {
+ url.searchParams.set('paged', page);
+ }
+
+ var state = { propertyFilters: formData, page: page };
+ history.pushState(state, '', url.toString());
+ },
+
+ /**
+ * Get page number from pagination URL
+ */
+ getPageFromUrl: function(url) {
+ var match = url.match(/[?&]paged=(\d+)/);
+ return match ? parseInt(match[1]) : 1;
+ },
+
+ /**
+ * Reset filters
+ */
+ resetFilters: function() {
+ this.$form.find('select').val('');
+ this.$form.find('[name="sort"]').val('newest');
+ this.filterProperties(1);
+ }
+ };
+
+ // Initialize on document ready
+ $(function() {
+ PropertyFilters.init();
+ });
+
+})(jQuery);