Sync property list with map viewport
Major changes: - Property list now updates when map pans/zooms - Properties sorted by distance from map center (closest first) - Shows "X properties in view" when viewport filtering active - Min 30 properties required before grouping kicks in - Added rule to CLAUDE.md: no commits unless asked Backend: - MLS_Query: Added bounds filtering and distance-based sorting - AJAX handler: Accepts bounds/center, sorts by distance when provided Frontend: - Map move triggers property list refresh with same viewport - Loop prevention flag to avoid map->filter->map recursion - Resets to page 1 when viewport changes Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,8 @@ class MLS_Query {
|
||||
'listing_key' => null,
|
||||
'listing_id' => null,
|
||||
'search' => null, // Search in address/remarks
|
||||
'bounds' => null, // Map bounds: array(sw_lat, sw_lng, ne_lat, ne_lng)
|
||||
'center' => null, // Map center for distance sort: array(lat, lng)
|
||||
'limit' => 20,
|
||||
'offset' => 0,
|
||||
'orderby' => 'modification_timestamp',
|
||||
@@ -166,24 +168,51 @@ class MLS_Query {
|
||||
$values[] = $search_term;
|
||||
}
|
||||
|
||||
// Map bounds filtering
|
||||
if ($args['bounds'] && is_array($args['bounds']) && count($args['bounds']) === 4) {
|
||||
list($sw_lat, $sw_lng, $ne_lat, $ne_lng) = $args['bounds'];
|
||||
$where[] = 'latitude BETWEEN %f AND %f';
|
||||
$where[] = 'longitude BETWEEN %f AND %f';
|
||||
$where[] = 'latitude IS NOT NULL';
|
||||
$where[] = 'longitude IS NOT NULL';
|
||||
$values[] = (float) $sw_lat;
|
||||
$values[] = (float) $ne_lat;
|
||||
$values[] = (float) $sw_lng;
|
||||
$values[] = (float) $ne_lng;
|
||||
}
|
||||
|
||||
$sql .= ' WHERE ' . implode(' AND ', $where);
|
||||
|
||||
// ORDER BY
|
||||
$allowed_orderby = array(
|
||||
'modification_timestamp',
|
||||
'list_price',
|
||||
'bedrooms_total',
|
||||
'bathrooms_total',
|
||||
'living_area',
|
||||
'year_built',
|
||||
'days_on_market',
|
||||
'city',
|
||||
'created_at',
|
||||
);
|
||||
// If center provided, sort by distance from center
|
||||
if ($args['center'] && is_array($args['center']) && count($args['center']) === 2) {
|
||||
list($center_lat, $center_lng) = $args['center'];
|
||||
// Haversine formula approximation for distance (good enough for sorting)
|
||||
// Using squared Euclidean distance with latitude adjustment for speed
|
||||
$lat_factor = cos(deg2rad((float) $center_lat));
|
||||
$sql .= $wpdb->prepare(
|
||||
" ORDER BY (POW(latitude - %f, 2) + POW((longitude - %f) * %f, 2)) ASC",
|
||||
(float) $center_lat,
|
||||
(float) $center_lng,
|
||||
$lat_factor
|
||||
);
|
||||
} else {
|
||||
$allowed_orderby = array(
|
||||
'modification_timestamp',
|
||||
'list_price',
|
||||
'bedrooms_total',
|
||||
'bathrooms_total',
|
||||
'living_area',
|
||||
'year_built',
|
||||
'days_on_market',
|
||||
'city',
|
||||
'created_at',
|
||||
);
|
||||
|
||||
$orderby = in_array($args['orderby'], $allowed_orderby) ? $args['orderby'] : 'modification_timestamp';
|
||||
$order = strtoupper($args['order']) === 'ASC' ? 'ASC' : 'DESC';
|
||||
$sql .= " ORDER BY {$orderby} {$order}";
|
||||
$orderby = in_array($args['orderby'], $allowed_orderby) ? $args['orderby'] : 'modification_timestamp';
|
||||
$order = strtoupper($args['order']) === 'ASC' ? 'ASC' : 'DESC';
|
||||
$sql .= " ORDER BY {$orderby} {$order}";
|
||||
}
|
||||
|
||||
// LIMIT/OFFSET
|
||||
$sql .= ' LIMIT %d OFFSET %d';
|
||||
@@ -378,6 +407,19 @@ class MLS_Query {
|
||||
$values[] = (int) $args['min_baths'];
|
||||
}
|
||||
|
||||
// Map bounds filtering
|
||||
if (!empty($args['bounds']) && is_array($args['bounds']) && count($args['bounds']) === 4) {
|
||||
list($sw_lat, $sw_lng, $ne_lat, $ne_lng) = $args['bounds'];
|
||||
$where[] = 'latitude BETWEEN %f AND %f';
|
||||
$where[] = 'longitude BETWEEN %f AND %f';
|
||||
$where[] = 'latitude IS NOT NULL';
|
||||
$where[] = 'longitude IS NOT NULL';
|
||||
$values[] = (float) $sw_lat;
|
||||
$values[] = (float) $ne_lat;
|
||||
$values[] = (float) $sw_lng;
|
||||
$values[] = (float) $ne_lng;
|
||||
}
|
||||
|
||||
$sql = "SELECT COUNT(*) FROM {$table} WHERE " . implode(' AND ', $where);
|
||||
|
||||
if (!empty($values)) {
|
||||
|
||||
Reference in New Issue
Block a user