fc018ca604
Property Map: - Replace ACF-based property display with MLS database queries - Use real lat/lng coordinates from MLS (100% coverage) - Create property-card-mls.php template for MLS property cards - Update AJAX handler to filter MLS properties MLS Plugin Enhancements: - Add 'wp mls run' smart sync command (auto-detects full/incremental/resume) - Add database index migrations for lat/lng and composite search indexes - Add comprehensive README.md documentation Documentation: - Update site README.md with sysadmin quick reference - Add FEATURES_PENDING_12_15.md tracking client feature requests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
170 lines
7.4 KiB
PHP
Executable File
170 lines
7.4 KiB
PHP
Executable File
<?php
|
|
/**
|
|
* Property Archive Template
|
|
*
|
|
* Displays the properties listing page with optional map view
|
|
*
|
|
* @package HomeProz
|
|
*/
|
|
|
|
// Prevent direct access
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
get_header();
|
|
|
|
// Map view is default on desktop, grid view requires ?view=grid
|
|
$show_map = !isset($_GET['view']) || $_GET['view'] !== 'grid';
|
|
$view_class = $show_map ? 'is-map-view' : 'is-grid-view';
|
|
?>
|
|
|
|
<main id="primary" class="site-main property-archive-main <?php echo esc_attr($view_class); ?>">
|
|
<?php
|
|
// Get hero content from Theme Options
|
|
$hero_title = get_field('properties_hero_title', 'option') ?: 'Find Your Perfect Property';
|
|
$hero_subtitle = get_field('properties_hero_subtitle', 'option') ?: 'Browse our selection of homes, land, and commercial properties in southern Minnesota.';
|
|
$hero_bg = get_field('properties_hero_background', 'option');
|
|
$has_bg_class = $hero_bg ? 'has-background' : '';
|
|
$bg_style = $hero_bg ? 'style="background-image: url(' . esc_url($hero_bg) . ');"' : '';
|
|
?>
|
|
<!-- Archive Hero -->
|
|
<section class="archive-hero <?php echo esc_attr($has_bg_class); ?>" <?php echo $bg_style; ?>>
|
|
<?php if ($hero_bg) : ?>
|
|
<div class="archive-hero-overlay"></div>
|
|
<?php endif; ?>
|
|
<div class="container">
|
|
<h1 class="archive-hero-title"><?php echo esc_html($hero_title); ?></h1>
|
|
<p class="archive-hero-subtitle"><?php echo esc_html($hero_subtitle); ?></p>
|
|
</div>
|
|
</section>
|
|
|
|
<div class="container">
|
|
<!-- Filters -->
|
|
<?php get_template_part('template-parts/property/property-filters'); ?>
|
|
|
|
<!-- Map + List View (hidden below 1024px via CSS) -->
|
|
<div class="property-map-layout">
|
|
<div class="property-map-container">
|
|
<!-- View Toggle (inside map column) -->
|
|
<div class="view-toggle">
|
|
<a href="<?php echo esc_url(add_query_arg('view', 'grid')); ?>" class="view-toggle-btn view-toggle-grid">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
<rect x="3" y="3" width="7" height="7"/>
|
|
<rect x="14" y="3" width="7" height="7"/>
|
|
<rect x="3" y="14" width="7" height="7"/>
|
|
<rect x="14" y="14" width="7" height="7"/>
|
|
</svg>
|
|
<span>Grid</span>
|
|
</a>
|
|
<a href="<?php echo esc_url(remove_query_arg('view')); ?>" class="view-toggle-btn view-toggle-map active">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
<polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/>
|
|
<line x1="8" y1="2" x2="8" y2="18"/>
|
|
<line x1="16" y1="6" x2="16" y2="22"/>
|
|
</svg>
|
|
<span>Map</span>
|
|
</a>
|
|
</div>
|
|
<div id="property-map" class="property-map">
|
|
<!-- Leaflet map will be initialized here -->
|
|
</div>
|
|
</div>
|
|
<div class="property-list-container">
|
|
<div id="property-results" class="property-results-map">
|
|
<?php get_template_part('template-parts/property/property-results'); ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Grid View (shown below 1024px, or when grid selected above 1024px) -->
|
|
<div class="grid-view-container">
|
|
<div class="view-toggle">
|
|
<a href="<?php echo esc_url(add_query_arg('view', 'grid')); ?>" class="view-toggle-btn view-toggle-grid active">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
<rect x="3" y="3" width="7" height="7"/>
|
|
<rect x="14" y="3" width="7" height="7"/>
|
|
<rect x="3" y="14" width="7" height="7"/>
|
|
<rect x="14" y="14" width="7" height="7"/>
|
|
</svg>
|
|
<span>Grid</span>
|
|
</a>
|
|
<a href="<?php echo esc_url(remove_query_arg('view')); ?>" class="view-toggle-btn view-toggle-map">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
|
<polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/>
|
|
<line x1="8" y1="2" x2="8" y2="18"/>
|
|
<line x1="16" y1="6" x2="16" y2="22"/>
|
|
</svg>
|
|
<span>Map</span>
|
|
</a>
|
|
</div>
|
|
<div id="property-results-grid" class="property-results-grid">
|
|
<?php get_template_part('template-parts/property/property-results'); ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<?php
|
|
// Load MLS properties for map markers
|
|
$markers = array();
|
|
|
|
if (function_exists('mls_get_properties')) {
|
|
$mls_properties = mls_get_properties(array(
|
|
'status' => 'Active',
|
|
'limit' => 1000, // Reasonable limit for map performance
|
|
'orderby' => 'modification_timestamp',
|
|
'order' => 'DESC',
|
|
));
|
|
|
|
foreach ($mls_properties as $property) {
|
|
// Skip properties without coordinates
|
|
if (empty($property->latitude) || empty($property->longitude)) {
|
|
continue;
|
|
}
|
|
|
|
// Format address
|
|
$address_parts = array();
|
|
if ($property->street_number) {
|
|
$address_parts[] = $property->street_number;
|
|
}
|
|
if ($property->street_name) {
|
|
$address_parts[] = $property->street_name;
|
|
}
|
|
if ($property->street_suffix) {
|
|
$address_parts[] = $property->street_suffix;
|
|
}
|
|
$street = implode(' ', $address_parts);
|
|
$full_address = $street ? $street . ', ' . $property->city : $property->city;
|
|
|
|
$markers[] = array(
|
|
'id' => $property->listing_key,
|
|
'lat' => (float) $property->latitude,
|
|
'lng' => (float) $property->longitude,
|
|
'title' => $full_address,
|
|
'price' => '$' . number_format($property->list_price),
|
|
'address' => $full_address,
|
|
'url' => home_url('/properties/?listing=' . urlencode($property->listing_key)),
|
|
'beds' => $property->bedrooms_total,
|
|
'baths' => $property->bathrooms_total,
|
|
'sqft' => $property->living_area,
|
|
'status' => $property->standard_status,
|
|
'photo' => null, // Placeholder - photos will be added later
|
|
);
|
|
}
|
|
}
|
|
?>
|
|
<!-- Leaflet CSS -->
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
|
|
<!-- Leaflet JS -->
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
|
|
<script>
|
|
var homeprozMapData = {
|
|
properties: <?php echo json_encode($markers); ?>,
|
|
isMapView: <?php echo $show_map ? 'true' : 'false'; ?>
|
|
};
|
|
</script>
|
|
|
|
<?php
|
|
get_footer();
|