Add homepage section ordering and switch to MLS-only data source
Homepage Improvements: - Add Section Order tab with enable/disable toggles and order numbers - Support up to 2 custom WYSIWYG content areas with titles - All 4 sections (Service Cards, Property Types, Custom 1, Custom 2) can be reordered and toggled independently Property Type Boxes: - Convert to ACF repeater (remove MLS count queries) - Add red accent color to icons - Center-align icons, increase title size, add spacing MLS Data Source: - Remove property CPT and taxonomies (MLS Editor is now source of truth) - Commercial section now pulls from MLS with priority: 1. Featured (favorited) commercial properties 2. HomeProz-listed commercial properties 3. Random commercial/land/farm properties - Featured Homes section updated to same priority order 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
File diff suppressed because one or more lines are too long
@@ -12,74 +12,84 @@ if (!defined('ABSPATH')) {
|
||||
|
||||
get_header();
|
||||
|
||||
// Get homepage ACF fields (with fallbacks)
|
||||
$hero_title = get_field('home_hero_title') ?: 'Find Your Dream Home Today';
|
||||
$hero_subtitle = get_field('home_hero_subtitle') ?: 'Expert real estate services for buyers and sellers in Albert Lea and the surrounding Minnesota communities.';
|
||||
$hero_primary_cta_text = get_field('home_hero_primary_cta_text') ?: 'View All Properties';
|
||||
$hero_primary_cta_url = get_field('home_hero_primary_cta_url') ?: home_url('/properties/');
|
||||
$hero_secondary_cta_text = get_field('home_hero_secondary_cta_text') ?: 'Contact Us';
|
||||
$hero_secondary_cta_url = get_field('home_hero_secondary_cta_url') ?: home_url('/contact/');
|
||||
|
||||
$featured_homes_title = get_field('home_featured_homes_title') ?: 'Featured Homes';
|
||||
$featured_homes_subtitle = get_field('home_featured_homes_subtitle') ?: 'Browse our residential properties for sale';
|
||||
$commercial_title = get_field('home_commercial_title') ?: 'Commercial & Land';
|
||||
$commercial_subtitle = get_field('home_commercial_subtitle') ?: 'Explore commercial properties and land for sale';
|
||||
|
||||
$cta_title = get_field('home_cta_title') ?: 'Ready to Find Your Dream Home?';
|
||||
$cta_text = get_field('home_cta_text') ?: 'Whether you\'re buying or selling, our team is here to help you every step of the way.';
|
||||
$cta_button_text = get_field('home_cta_button_text') ?: 'Contact Us Today';
|
||||
$cta_button_url = get_field('home_cta_button_url') ?: home_url('/contact/');
|
||||
|
||||
// Get featured MLS listings for JSON data
|
||||
$featured_mls_listings = homeproz_get_featured_mls_listings(10); // Get more than needed for random selection
|
||||
|
||||
// Get featured commercial/land properties from WordPress (3 most recent active commercial or land listings)
|
||||
$featured_commercial = new WP_Query(array(
|
||||
'post_type' => 'property',
|
||||
'posts_per_page' => 3,
|
||||
'tax_query' => array(
|
||||
'relation' => 'AND',
|
||||
array(
|
||||
'taxonomy' => 'property_status',
|
||||
'field' => 'slug',
|
||||
'terms' => 'active',
|
||||
),
|
||||
array(
|
||||
'taxonomy' => 'property_type',
|
||||
'field' => 'slug',
|
||||
'terms' => array('commercial', 'land'),
|
||||
),
|
||||
),
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
));
|
||||
// Get featured commercial/land properties from MLS data
|
||||
$featured_commercial_listings = homeproz_get_featured_commercial_listings(3);
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main homepage-main">
|
||||
|
||||
<?php
|
||||
// Hero images
|
||||
$hero_image_split = homeproz_get_transformed_theme_image('assets/images/hero-original.png', 30, 2560, 90);
|
||||
$hero_image_card = homeproz_get_transformed_theme_image('assets/images/hero-original.png', 35, 2560, 90);
|
||||
$fallback_image = get_template_directory_uri() . '/assets/images/hero.webp';
|
||||
$logo_cropped = get_template_directory_uri() . '/assets/images/logo-cropped.webp';
|
||||
|
||||
// Build gallery images array for desktop hero rotation
|
||||
// Include the original hero plus the 5 additional gallery images
|
||||
$gallery_source_images = array(
|
||||
'assets/images/hero-original.png',
|
||||
'assets/images/hero-gallery/hero-2.png',
|
||||
'assets/images/hero-gallery/hero-3.png',
|
||||
'assets/images/hero-gallery/hero-4.jpg',
|
||||
'assets/images/hero-gallery/hero-5.png',
|
||||
'assets/images/hero-gallery/hero-6.png',
|
||||
);
|
||||
// Check for ACF gallery first, otherwise use default theme images
|
||||
$acf_gallery = get_field('home_hero_gallery');
|
||||
$use_acf_gallery = $acf_gallery && is_array($acf_gallery) && !empty($acf_gallery);
|
||||
|
||||
$gallery_images = array();
|
||||
foreach ($gallery_source_images as $source) {
|
||||
$transformed = homeproz_get_transformed_theme_image($source, 30, 2560, 90);
|
||||
if ($transformed) {
|
||||
$gallery_images[] = $transformed;
|
||||
if ($use_acf_gallery) {
|
||||
// Use ACF gallery images (already URLs from return_format)
|
||||
$gallery_images = $acf_gallery;
|
||||
} else {
|
||||
// Fallback to default theme images
|
||||
$gallery_source_images = array(
|
||||
'assets/images/hero-original.png',
|
||||
'assets/images/hero-gallery/hero-2.png',
|
||||
'assets/images/hero-gallery/hero-3.png',
|
||||
'assets/images/hero-gallery/hero-4.jpg',
|
||||
'assets/images/hero-gallery/hero-5.png',
|
||||
'assets/images/hero-gallery/hero-6.png',
|
||||
);
|
||||
|
||||
foreach ($gallery_source_images as $source) {
|
||||
$transformed = homeproz_get_transformed_theme_image($source, 30, 2560, 90);
|
||||
if ($transformed) {
|
||||
$gallery_images[] = $transformed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use first gallery image as initial background (whether from ACF or defaults)
|
||||
$initial_background = !empty($gallery_images) ? $gallery_images[0] : $fallback_image;
|
||||
|
||||
// Design 2: Two-column split (shown >= 1450px)
|
||||
?>
|
||||
<div class="hero-desktop-only">
|
||||
<?php
|
||||
get_template_part('template-parts/components/hero-section', null, array(
|
||||
'logo' => $logo_cropped,
|
||||
'title' => 'Find Your Dream Home Today',
|
||||
'subtitle' => 'Expert real estate services for buyers and sellers in Albert Lea and the surrounding Minnesota communities.',
|
||||
'title' => $hero_title,
|
||||
'subtitle' => $hero_subtitle,
|
||||
'show_location_search' => true,
|
||||
'primary_cta_text' => 'View All Properties',
|
||||
'primary_cta_url' => home_url('/properties/'),
|
||||
'primary_cta_text' => $hero_primary_cta_text,
|
||||
'primary_cta_url' => $hero_primary_cta_url,
|
||||
'primary_cta_icon' => 'map',
|
||||
'secondary_cta_text' => 'Contact Us',
|
||||
'secondary_cta_url' => home_url('/contact/'),
|
||||
'background_image' => $hero_image_split ?: $fallback_image,
|
||||
'secondary_cta_text' => $hero_secondary_cta_text,
|
||||
'secondary_cta_url' => $hero_secondary_cta_url,
|
||||
'background_image' => $initial_background,
|
||||
'gallery_images' => $gallery_images,
|
||||
'size' => 'large',
|
||||
));
|
||||
@@ -93,34 +103,97 @@ $featured_commercial = new WP_Query(array(
|
||||
<?php
|
||||
get_template_part('template-parts/components/hero-section-card', null, array(
|
||||
'logo' => $logo_cropped,
|
||||
'title' => 'Find Your Dream Home Today',
|
||||
'subtitle' => 'Expert real estate services for buyers and sellers in Albert Lea and the surrounding Minnesota communities.',
|
||||
'title' => $hero_title,
|
||||
'subtitle' => $hero_subtitle,
|
||||
'show_location_search' => true,
|
||||
'primary_cta_text' => 'View All Properties',
|
||||
'primary_cta_url' => home_url('/properties/'),
|
||||
'primary_cta_text' => $hero_primary_cta_text,
|
||||
'primary_cta_url' => $hero_primary_cta_url,
|
||||
'primary_cta_icon' => 'map',
|
||||
'secondary_cta_text' => 'Contact Us',
|
||||
'secondary_cta_url' => home_url('/contact/'),
|
||||
'background_image' => $hero_image_card ?: $fallback_image,
|
||||
'secondary_cta_text' => $hero_secondary_cta_text,
|
||||
'secondary_cta_url' => $hero_secondary_cta_url,
|
||||
'background_image' => $initial_background,
|
||||
'size' => 'large',
|
||||
));
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// Service Cards Section (Buy/Rent/Sell)
|
||||
get_template_part('template-parts/components/service-cards');
|
||||
// Build ordered sections array
|
||||
$homepage_sections = array();
|
||||
|
||||
// Property Type Showcase Boxes
|
||||
get_template_part('template-parts/components/property-type-boxes');
|
||||
// Service Cards Section
|
||||
$service_cards_enabled = get_field('home_service_cards_enabled');
|
||||
if ($service_cards_enabled === null) $service_cards_enabled = true; // Default to enabled
|
||||
if ($service_cards_enabled) {
|
||||
$homepage_sections[] = array(
|
||||
'type' => 'service_cards',
|
||||
'order' => get_field('home_service_cards_order') ?: 1,
|
||||
);
|
||||
}
|
||||
|
||||
// Property Types Section
|
||||
$property_types_enabled = get_field('home_property_types_enabled');
|
||||
if ($property_types_enabled === null) $property_types_enabled = true; // Default to enabled
|
||||
if ($property_types_enabled) {
|
||||
$homepage_sections[] = array(
|
||||
'type' => 'property_types',
|
||||
'order' => get_field('home_property_types_order') ?: 2,
|
||||
);
|
||||
}
|
||||
|
||||
// Custom Content 1
|
||||
$custom_1_enabled = get_field('home_custom_1_enabled');
|
||||
if ($custom_1_enabled) {
|
||||
$homepage_sections[] = array(
|
||||
'type' => 'custom_1',
|
||||
'order' => get_field('home_custom_1_order') ?: 3,
|
||||
'title' => get_field('home_custom_1_title'),
|
||||
'content' => get_field('home_custom_1_content'),
|
||||
);
|
||||
}
|
||||
|
||||
// Custom Content 2
|
||||
$custom_2_enabled = get_field('home_custom_2_enabled');
|
||||
if ($custom_2_enabled) {
|
||||
$homepage_sections[] = array(
|
||||
'type' => 'custom_2',
|
||||
'order' => get_field('home_custom_2_order') ?: 4,
|
||||
'title' => get_field('home_custom_2_title'),
|
||||
'content' => get_field('home_custom_2_content'),
|
||||
);
|
||||
}
|
||||
|
||||
// Sort sections by order
|
||||
usort($homepage_sections, function($a, $b) {
|
||||
return $a['order'] - $b['order'];
|
||||
});
|
||||
|
||||
// Render sections in order
|
||||
foreach ($homepage_sections as $section) {
|
||||
switch ($section['type']) {
|
||||
case 'service_cards':
|
||||
get_template_part('template-parts/components/service-cards');
|
||||
break;
|
||||
case 'property_types':
|
||||
get_template_part('template-parts/components/property-type-boxes');
|
||||
break;
|
||||
case 'custom_1':
|
||||
case 'custom_2':
|
||||
get_template_part('template-parts/components/custom-content-section', null, array(
|
||||
'title' => $section['title'],
|
||||
'content' => $section['content'],
|
||||
));
|
||||
break;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<!-- Featured Homes Section (MLS Listings) -->
|
||||
<section class="featured-properties-section">
|
||||
<div class="container">
|
||||
<header class="section-header">
|
||||
<h2 class="section-title">Featured Homes</h2>
|
||||
<p class="section-subtitle">Browse our residential properties for sale</p>
|
||||
<h2 class="section-title"><?php echo esc_html($featured_homes_title); ?></h2>
|
||||
<p class="section-subtitle"><?php echo esc_html($featured_homes_subtitle); ?></p>
|
||||
</header>
|
||||
|
||||
<div id="featured-listings-grid" class="property-grid property-grid--3col">
|
||||
@@ -151,23 +224,55 @@ $featured_commercial = new WP_Query(array(
|
||||
<section class="featured-properties-section featured-properties-section--alt">
|
||||
<div class="container">
|
||||
<header class="section-header">
|
||||
<h2 class="section-title">Commercial & Land</h2>
|
||||
<p class="section-subtitle">Explore commercial properties and land for sale</p>
|
||||
<h2 class="section-title"><?php echo esc_html($commercial_title); ?></h2>
|
||||
<p class="section-subtitle"><?php echo esc_html($commercial_subtitle); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if ($featured_commercial->have_posts()) : ?>
|
||||
<?php if (!empty($featured_commercial_listings)) : ?>
|
||||
<div class="property-grid property-grid--3col">
|
||||
<?php
|
||||
while ($featured_commercial->have_posts()) :
|
||||
$featured_commercial->the_post();
|
||||
get_template_part('template-parts/property/property-card');
|
||||
endwhile;
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
<?php foreach ($featured_commercial_listings as $listing) : ?>
|
||||
<article class="property-card card">
|
||||
<a href="<?php echo esc_url($listing['url']); ?>" class="property-card-link-overlay" aria-hidden="true" tabindex="-1"></a>
|
||||
<div class="property-card-image">
|
||||
<?php if (!empty($listing['image_url'])) : ?>
|
||||
<img src="<?php echo esc_url($listing['image_url']); ?>" alt="<?php echo esc_attr($listing['address']); ?>" loading="lazy">
|
||||
<?php else : ?>
|
||||
<div class="property-card-placeholder">
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
|
||||
<polyline points="9 22 9 12 15 12 15 22"/>
|
||||
</svg>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<span class="property-card-badge badge badge-active">Active</span>
|
||||
</div>
|
||||
<div class="property-card-content">
|
||||
<div class="property-card-price"><?php echo esc_html($listing['price_formatted']); ?></div>
|
||||
<h3 class="property-card-title"><?php echo esc_html($listing['address']); ?></h3>
|
||||
<?php if ($listing['sqft'] > 0) : ?>
|
||||
<ul class="property-card-specs">
|
||||
<li class="spec-item">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"/>
|
||||
<path d="M3 9h18M9 3v18"/>
|
||||
</svg>
|
||||
<span><?php echo esc_html(number_format($listing['sqft'])); ?> sqft</span>
|
||||
</li>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
<span class="property-card-link">
|
||||
View Details
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
|
||||
<div class="section-footer">
|
||||
<a href="<?php echo esc_url(home_url('/properties/?type=commercial,land')); ?>" class="btn btn-secondary">
|
||||
<a href="<?php echo esc_url(home_url('/properties/?property_type=Commercial+Sale,Land,Farm')); ?>" class="btn btn-secondary">
|
||||
View All Commercial
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
@@ -183,10 +288,10 @@ $featured_commercial = new WP_Query(array(
|
||||
<?php
|
||||
// Contact CTA Section
|
||||
get_template_part('template-parts/components/cta-section', null, array(
|
||||
'title' => 'Ready to Find Your Dream Home?',
|
||||
'text' => 'Whether you\'re buying or selling, our team is here to help you every step of the way.',
|
||||
'button_text' => 'Contact Us Today',
|
||||
'button_url' => home_url('/contact/'),
|
||||
'title' => $cta_title,
|
||||
'text' => $cta_text,
|
||||
'button_text' => $cta_button_text,
|
||||
'button_url' => $cta_button_url,
|
||||
'style' => 'accent',
|
||||
));
|
||||
?>
|
||||
|
||||
@@ -443,6 +443,51 @@ function homeproz_register_acf_fields() {
|
||||
'rows' => 2,
|
||||
'default_value' => 'Your trusted partner for buying and selling homes in Albert Lea, Minnesota and surrounding areas.',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_legal_links',
|
||||
'label' => 'Legal Links',
|
||||
'name' => 'theme_legal_links',
|
||||
'type' => 'repeater',
|
||||
'instructions' => 'Links displayed in footer legal section (Privacy Policy, Fair Housing, etc.)',
|
||||
'min' => 0,
|
||||
'max' => 10,
|
||||
'layout' => 'table',
|
||||
'button_label' => 'Add Legal Link',
|
||||
'sub_fields' => array(
|
||||
array(
|
||||
'key' => 'field_legal_link_label',
|
||||
'label' => 'Label',
|
||||
'name' => 'label',
|
||||
'type' => 'text',
|
||||
'required' => 1,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_legal_link_url',
|
||||
'label' => 'URL',
|
||||
'name' => 'url',
|
||||
'type' => 'url',
|
||||
'required' => 1,
|
||||
'wrapper' => array('width' => '40'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_legal_link_icon',
|
||||
'label' => 'Icon',
|
||||
'name' => 'icon',
|
||||
'type' => 'select',
|
||||
'choices' => array(
|
||||
'shield' => 'Shield (Privacy)',
|
||||
'home' => 'Home (Fair Housing)',
|
||||
'document' => 'Document (Disclaimer)',
|
||||
'clipboard' => 'Clipboard (Disclosure)',
|
||||
'info' => 'Info Circle',
|
||||
'none' => 'No Icon',
|
||||
),
|
||||
'default_value' => 'document',
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Office Hours
|
||||
array(
|
||||
@@ -518,6 +563,68 @@ function homeproz_register_acf_fields() {
|
||||
'instructions' => 'Paste the full iframe embed code from Google Maps. Get this from maps.google.com > Share > Embed a map.',
|
||||
'rows' => 4,
|
||||
),
|
||||
|
||||
// 404 Page Tab
|
||||
array(
|
||||
'key' => 'field_theme_tab_404',
|
||||
'label' => '404 Page',
|
||||
'name' => '',
|
||||
'type' => 'tab',
|
||||
'placement' => 'left',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_404_title',
|
||||
'label' => '404 Title',
|
||||
'name' => 'theme_404_title',
|
||||
'type' => 'text',
|
||||
'default_value' => '404',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_404_subtitle',
|
||||
'label' => '404 Subtitle',
|
||||
'name' => 'theme_404_subtitle',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Page Not Found',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_404_message',
|
||||
'label' => '404 Message',
|
||||
'name' => 'theme_404_message',
|
||||
'type' => 'textarea',
|
||||
'rows' => 2,
|
||||
'default_value' => 'The page you\'re looking for doesn\'t exist or has been moved.',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_404_primary_button',
|
||||
'label' => 'Primary Button Text',
|
||||
'name' => 'theme_404_primary_button',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Go Home',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_404_secondary_button',
|
||||
'label' => 'Secondary Button Text',
|
||||
'name' => 'theme_404_secondary_button',
|
||||
'type' => 'text',
|
||||
'default_value' => 'View Properties',
|
||||
),
|
||||
|
||||
// Footer Copyright Tab
|
||||
array(
|
||||
'key' => 'field_theme_tab_copyright',
|
||||
'label' => 'Footer Copyright',
|
||||
'name' => '',
|
||||
'type' => 'tab',
|
||||
'placement' => 'left',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_theme_footer_copyright',
|
||||
'label' => 'Copyright Text',
|
||||
'name' => 'theme_footer_copyright',
|
||||
'type' => 'text',
|
||||
'instructions' => 'Copyright text shown in footer. Year is added automatically.',
|
||||
'default_value' => 'HomeProz Real Estate LLC. All rights reserved.',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
@@ -567,6 +674,17 @@ function homeproz_register_acf_fields() {
|
||||
'library' => 'all',
|
||||
'mime_types' => 'jpg, jpeg, png, webp',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_page_enable_title_animations',
|
||||
'label' => 'Enable Section Title Animations',
|
||||
'name' => 'enable_title_animations',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Enable subtle hover animations on section titles (letter-spacing expansion).',
|
||||
'default_value' => 1,
|
||||
'ui' => 1,
|
||||
'ui_on_text' => 'Enabled',
|
||||
'ui_off_text' => 'Disabled',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
// All pages except front page
|
||||
@@ -697,13 +815,21 @@ function homeproz_register_acf_fields() {
|
||||
'type' => 'select',
|
||||
'choices' => array(
|
||||
'home' => 'Home',
|
||||
'key' => 'Key',
|
||||
'sell' => 'For Sale Sign',
|
||||
'book' => 'Book/Guide',
|
||||
'dollar-sign' => 'Dollar Sign',
|
||||
'users' => 'Users/Team',
|
||||
'map-pin' => 'Map Pin',
|
||||
'key' => 'Key',
|
||||
'building' => 'Building',
|
||||
'search' => 'Search',
|
||||
'handshake' => 'Handshake',
|
||||
'phone' => 'Phone',
|
||||
'mail' => 'Email',
|
||||
'star' => 'Star',
|
||||
'shield' => 'Shield',
|
||||
'clipboard' => 'Clipboard',
|
||||
'document' => 'Document',
|
||||
),
|
||||
'default_value' => 'home',
|
||||
),
|
||||
@@ -837,6 +963,253 @@ function homeproz_register_acf_fields() {
|
||||
'rows' => 2,
|
||||
'default_value' => 'Find the perfect property for your needs',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_property_type_boxes',
|
||||
'label' => 'Property Type Boxes',
|
||||
'name' => 'home_property_type_boxes',
|
||||
'type' => 'repeater',
|
||||
'instructions' => 'Configure the property type boxes displayed in this section',
|
||||
'min' => 1,
|
||||
'max' => 8,
|
||||
'layout' => 'block',
|
||||
'button_label' => 'Add Property Type',
|
||||
'sub_fields' => array(
|
||||
array(
|
||||
'key' => 'field_property_type_box_title',
|
||||
'label' => 'Title',
|
||||
'name' => 'title',
|
||||
'type' => 'text',
|
||||
'required' => 1,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_property_type_box_description',
|
||||
'label' => 'Description',
|
||||
'name' => 'description',
|
||||
'type' => 'text',
|
||||
'required' => 1,
|
||||
'wrapper' => array('width' => '40'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_property_type_box_url',
|
||||
'label' => 'Link URL',
|
||||
'name' => 'url',
|
||||
'type' => 'url',
|
||||
'required' => 1,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_property_type_box_icon',
|
||||
'label' => 'Icon',
|
||||
'name' => 'icon',
|
||||
'type' => 'select',
|
||||
'choices' => array(
|
||||
'home' => 'Home (Residential)',
|
||||
'land' => 'Land/Mountains',
|
||||
'building' => 'Building (Commercial)',
|
||||
'farm' => 'Farm/Barn',
|
||||
'multi-family' => 'Multi-Family',
|
||||
'key' => 'Key',
|
||||
'map-pin' => 'Map Pin',
|
||||
'dollar-sign' => 'Dollar Sign',
|
||||
),
|
||||
'default_value' => 'home',
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Hero Gallery Tab
|
||||
array(
|
||||
'key' => 'field_home_tab_gallery',
|
||||
'label' => 'Hero Gallery',
|
||||
'name' => '',
|
||||
'type' => 'tab',
|
||||
'placement' => 'left',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_hero_gallery',
|
||||
'label' => 'Hero Gallery Images',
|
||||
'name' => 'home_hero_gallery',
|
||||
'type' => 'gallery',
|
||||
'instructions' => 'Upload images for the rotating hero background. If empty, uses default images from theme.',
|
||||
'min' => 0,
|
||||
'max' => 10,
|
||||
'return_format' => 'url',
|
||||
'preview_size' => 'medium',
|
||||
'library' => 'all',
|
||||
'mime_types' => 'jpg, jpeg, png, webp',
|
||||
),
|
||||
|
||||
// Section Order Tab
|
||||
array(
|
||||
'key' => 'field_home_tab_section_order',
|
||||
'label' => 'Section Order',
|
||||
'name' => '',
|
||||
'type' => 'tab',
|
||||
'placement' => 'left',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_section_order_message',
|
||||
'label' => '',
|
||||
'name' => '',
|
||||
'type' => 'message',
|
||||
'message' => 'Configure which sections appear on the homepage and in what order. Lower order numbers appear first.',
|
||||
),
|
||||
|
||||
// Service Cards Section
|
||||
array(
|
||||
'key' => 'field_home_service_cards_enabled',
|
||||
'label' => 'Service Cards Section',
|
||||
'name' => 'home_service_cards_enabled',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Show the "Go with the Proz" service cards section',
|
||||
'default_value' => 1,
|
||||
'ui' => 1,
|
||||
'wrapper' => array('width' => '70'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_service_cards_order',
|
||||
'label' => 'Order',
|
||||
'name' => 'home_service_cards_order',
|
||||
'type' => 'number',
|
||||
'default_value' => 1,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
|
||||
// Property Types Section
|
||||
array(
|
||||
'key' => 'field_home_property_types_enabled',
|
||||
'label' => 'Property Types Section',
|
||||
'name' => 'home_property_types_enabled',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Show the "Browse by Property Type" boxes section',
|
||||
'default_value' => 1,
|
||||
'ui' => 1,
|
||||
'wrapper' => array('width' => '70'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_property_types_order',
|
||||
'label' => 'Order',
|
||||
'name' => 'home_property_types_order',
|
||||
'type' => 'number',
|
||||
'default_value' => 2,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
|
||||
// Custom Content 1
|
||||
array(
|
||||
'key' => 'field_home_custom_1_enabled',
|
||||
'label' => 'Custom Content Area 1',
|
||||
'name' => 'home_custom_1_enabled',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Show custom content area 1',
|
||||
'default_value' => 0,
|
||||
'ui' => 1,
|
||||
'wrapper' => array('width' => '70'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_1_order',
|
||||
'label' => 'Order',
|
||||
'name' => 'home_custom_1_order',
|
||||
'type' => 'number',
|
||||
'default_value' => 3,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_1_title',
|
||||
'label' => 'Title',
|
||||
'name' => 'home_custom_1_title',
|
||||
'type' => 'text',
|
||||
'conditional_logic' => array(
|
||||
array(
|
||||
array(
|
||||
'field' => 'field_home_custom_1_enabled',
|
||||
'operator' => '==',
|
||||
'value' => '1',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_1_content',
|
||||
'label' => 'Content',
|
||||
'name' => 'home_custom_1_content',
|
||||
'type' => 'wysiwyg',
|
||||
'tabs' => 'all',
|
||||
'toolbar' => 'full',
|
||||
'media_upload' => 1,
|
||||
'conditional_logic' => array(
|
||||
array(
|
||||
array(
|
||||
'field' => 'field_home_custom_1_enabled',
|
||||
'operator' => '==',
|
||||
'value' => '1',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Custom Content 2
|
||||
array(
|
||||
'key' => 'field_home_custom_2_enabled',
|
||||
'label' => 'Custom Content Area 2',
|
||||
'name' => 'home_custom_2_enabled',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Show custom content area 2',
|
||||
'default_value' => 0,
|
||||
'ui' => 1,
|
||||
'wrapper' => array('width' => '70'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_2_order',
|
||||
'label' => 'Order',
|
||||
'name' => 'home_custom_2_order',
|
||||
'type' => 'number',
|
||||
'default_value' => 4,
|
||||
'min' => 1,
|
||||
'max' => 10,
|
||||
'wrapper' => array('width' => '30'),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_2_title',
|
||||
'label' => 'Title',
|
||||
'name' => 'home_custom_2_title',
|
||||
'type' => 'text',
|
||||
'conditional_logic' => array(
|
||||
array(
|
||||
array(
|
||||
'field' => 'field_home_custom_2_enabled',
|
||||
'operator' => '==',
|
||||
'value' => '1',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'key' => 'field_home_custom_2_content',
|
||||
'label' => 'Content',
|
||||
'name' => 'home_custom_2_content',
|
||||
'type' => 'wysiwyg',
|
||||
'tabs' => 'all',
|
||||
'toolbar' => 'full',
|
||||
'media_upload' => 1,
|
||||
'conditional_logic' => array(
|
||||
array(
|
||||
array(
|
||||
'field' => 'field_home_custom_2_enabled',
|
||||
'operator' => '==',
|
||||
'value' => '1',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
@@ -910,6 +1283,15 @@ function homeproz_register_acf_fields() {
|
||||
'type' => 'text',
|
||||
'instructions' => 'NorthstarMLS agent ID (e.g., NST503517068)',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_agent_credentials',
|
||||
'label' => 'Professional Credentials',
|
||||
'name' => 'agent_credentials',
|
||||
'type' => 'textarea',
|
||||
'instructions' => 'Licenses, certifications, areas served, or other professional details. Displayed below contact buttons on profile.',
|
||||
'rows' => 3,
|
||||
'new_lines' => 'br',
|
||||
),
|
||||
|
||||
// Bio Tab
|
||||
array(
|
||||
@@ -1006,16 +1388,6 @@ function homeproz_register_acf_fields() {
|
||||
'type' => 'tab',
|
||||
'placement' => 'top',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_agent_order',
|
||||
'label' => 'Display Order',
|
||||
'name' => 'agent_order',
|
||||
'type' => 'number',
|
||||
'instructions' => 'Lower numbers appear first on the Agents page. Agents with the same order are sorted alphabetically.',
|
||||
'default_value' => 10,
|
||||
'min' => 0,
|
||||
'max' => 999,
|
||||
),
|
||||
array(
|
||||
'key' => 'field_agent_disabled',
|
||||
'label' => 'Disable Agent',
|
||||
@@ -1263,6 +1635,296 @@ function homeproz_register_acf_fields() {
|
||||
'position' => 'normal',
|
||||
'active' => true,
|
||||
));
|
||||
|
||||
// ===========================================
|
||||
// MLS OVERRIDE FIELD GROUP
|
||||
// ===========================================
|
||||
|
||||
// MLS Override Fields
|
||||
acf_add_local_field_group(array(
|
||||
'key' => 'group_mls_override',
|
||||
'title' => 'MLS Override Settings',
|
||||
'fields' => array(
|
||||
array(
|
||||
'key' => 'field_mls_override_id',
|
||||
'label' => 'MLS ID',
|
||||
'name' => 'mls_override_id',
|
||||
'type' => 'text',
|
||||
'instructions' => 'Enter the MLS listing ID (the number shown on the property, e.g., "12345678"). This is NOT the listing key.',
|
||||
'required' => 1,
|
||||
'placeholder' => 'e.g., 12345678',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_mls_override_featured_photo',
|
||||
'label' => 'Featured Photo',
|
||||
'name' => 'mls_override_featured_photo',
|
||||
'type' => 'image',
|
||||
'instructions' => 'Upload a custom featured photo to use instead of the MLS photo. This will appear on property cards and as the first image in the gallery.',
|
||||
'required' => 0,
|
||||
'return_format' => 'array',
|
||||
'preview_size' => 'medium',
|
||||
'library' => 'all',
|
||||
'mime_types' => 'jpg, jpeg, png, webp',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_mls_override_featured',
|
||||
'label' => 'Featured Property',
|
||||
'name' => 'mls_override_featured',
|
||||
'type' => 'true_false',
|
||||
'instructions' => 'Check to feature this property on the homepage rotation and prioritize it in property listings.',
|
||||
'required' => 0,
|
||||
'default_value' => 0,
|
||||
'ui' => 1,
|
||||
'ui_on_text' => 'Featured',
|
||||
'ui_off_text' => '',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
array(
|
||||
'param' => 'post_type',
|
||||
'operator' => '==',
|
||||
'value' => 'mls_override',
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => 0,
|
||||
'position' => 'normal',
|
||||
'style' => 'default',
|
||||
'label_placement' => 'top',
|
||||
'instruction_placement' => 'label',
|
||||
'active' => true,
|
||||
));
|
||||
|
||||
// ===========================================
|
||||
// PAGE-SPECIFIC FIELD GROUPS (CMS Migration)
|
||||
// ===========================================
|
||||
|
||||
// About Page Field Group
|
||||
acf_add_local_field_group(array(
|
||||
'key' => 'group_about_page',
|
||||
'title' => 'About Page Content',
|
||||
'fields' => array(
|
||||
// Team Section
|
||||
array(
|
||||
'key' => 'field_about_team_title',
|
||||
'label' => 'Team Section Title',
|
||||
'name' => 'about_team_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Meet Our Team',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_about_team_subtitle',
|
||||
'label' => 'Team Section Subtitle',
|
||||
'name' => 'about_team_subtitle',
|
||||
'type' => 'textarea',
|
||||
'rows' => 2,
|
||||
'default_value' => 'A dedicated group of real estate professionals committed to your success',
|
||||
),
|
||||
// Featured Image
|
||||
array(
|
||||
'key' => 'field_about_featured_image',
|
||||
'label' => 'Featured Image',
|
||||
'name' => 'about_featured_image',
|
||||
'type' => 'image',
|
||||
'instructions' => 'Image shown in the company story section. If empty, uses default about-us.webp.',
|
||||
'return_format' => 'url',
|
||||
'preview_size' => 'medium',
|
||||
),
|
||||
// Broker Information
|
||||
array(
|
||||
'key' => 'field_about_broker_title',
|
||||
'label' => 'Broker Section Title',
|
||||
'name' => 'about_broker_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Broker Information',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_about_broker_text',
|
||||
'label' => 'Broker Information Text',
|
||||
'name' => 'about_broker_text',
|
||||
'type' => 'wysiwyg',
|
||||
'instructions' => 'Legal/compliance broker information. Use line breaks for formatting.',
|
||||
'tabs' => 'all',
|
||||
'toolbar' => 'basic',
|
||||
'media_upload' => 0,
|
||||
'default_value' => "HomeProz Real Estate LLC DBA LandProz Real Estate, LLC<br>\n111 East Clark Street, Albert Lea, MN 56007<br>\nBroker Brian Haugen - MN | Broker/Auctioneer Greg Jensen - MN, IA - 24-21",
|
||||
),
|
||||
// CTA Section
|
||||
array(
|
||||
'key' => 'field_about_cta_title',
|
||||
'label' => 'CTA Title',
|
||||
'name' => 'about_cta_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Ready to Work With Us?',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_about_cta_text',
|
||||
'label' => 'CTA Text',
|
||||
'name' => 'about_cta_text',
|
||||
'type' => 'textarea',
|
||||
'rows' => 2,
|
||||
'default_value' => 'Contact our team today to start your real estate journey.',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_about_cta_button_text',
|
||||
'label' => 'CTA Button Text',
|
||||
'name' => 'about_cta_button_text',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Get in Touch',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_about_cta_button_url',
|
||||
'label' => 'CTA Button URL',
|
||||
'name' => 'about_cta_button_url',
|
||||
'type' => 'url',
|
||||
'instructions' => 'Leave empty to use /contact/',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
array(
|
||||
'param' => 'page_template',
|
||||
'operator' => '==',
|
||||
'value' => 'page-about.php',
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => 0,
|
||||
'position' => 'normal',
|
||||
'active' => true,
|
||||
));
|
||||
|
||||
// Contact Page Field Group
|
||||
acf_add_local_field_group(array(
|
||||
'key' => 'group_contact_page',
|
||||
'title' => 'Contact Page Content',
|
||||
'fields' => array(
|
||||
array(
|
||||
'key' => 'field_contact_form_title',
|
||||
'label' => 'Form Section Title',
|
||||
'name' => 'contact_form_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Send Us a Message',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_contact_info_title',
|
||||
'label' => 'Info Section Title',
|
||||
'name' => 'contact_info_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Contact Information',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
array(
|
||||
'param' => 'page_template',
|
||||
'operator' => '==',
|
||||
'value' => 'page-contact.php',
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => 0,
|
||||
'position' => 'normal',
|
||||
'active' => true,
|
||||
));
|
||||
|
||||
// Property Inquiry Page Field Group
|
||||
acf_add_local_field_group(array(
|
||||
'key' => 'group_property_inquiry',
|
||||
'title' => 'Property Inquiry Page Content',
|
||||
'fields' => array(
|
||||
array(
|
||||
'key' => 'field_inquiry_hero_title',
|
||||
'label' => 'Hero Title',
|
||||
'name' => 'inquiry_hero_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Request Property Information',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_inquiry_hero_subtitle',
|
||||
'label' => 'Hero Subtitle',
|
||||
'name' => 'inquiry_hero_subtitle',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Get more details about this listing',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_inquiry_preview_title',
|
||||
'label' => 'Preview Section Title',
|
||||
'name' => 'inquiry_preview_title',
|
||||
'type' => 'text',
|
||||
'default_value' => "Property You're Inquiring About",
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
array(
|
||||
'param' => 'page_template',
|
||||
'operator' => '==',
|
||||
'value' => 'page-property-inquiry.php',
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => 0,
|
||||
'position' => 'normal',
|
||||
'active' => true,
|
||||
));
|
||||
|
||||
// Thank You Page Field Group
|
||||
acf_add_local_field_group(array(
|
||||
'key' => 'group_thank_you_page',
|
||||
'title' => 'Thank You Page Content',
|
||||
'fields' => array(
|
||||
array(
|
||||
'key' => 'field_thankyou_hero_title',
|
||||
'label' => 'Hero Title',
|
||||
'name' => 'thankyou_hero_title',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Thank You!',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_thankyou_hero_subtitle',
|
||||
'label' => 'Hero Subtitle',
|
||||
'name' => 'thankyou_hero_subtitle',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Your inquiry has been submitted',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_thankyou_heading',
|
||||
'label' => 'Main Heading',
|
||||
'name' => 'thankyou_heading',
|
||||
'type' => 'text',
|
||||
'default_value' => "We've Received Your Request",
|
||||
),
|
||||
array(
|
||||
'key' => 'field_thankyou_message',
|
||||
'label' => 'Thank You Message',
|
||||
'name' => 'thankyou_message',
|
||||
'type' => 'textarea',
|
||||
'rows' => 2,
|
||||
'default_value' => 'One of our team members will review your inquiry and get back to you shortly. We typically respond within 24 hours during business days.',
|
||||
),
|
||||
array(
|
||||
'key' => 'field_thankyou_property_heading',
|
||||
'label' => 'Property Section Heading',
|
||||
'name' => 'thankyou_property_heading',
|
||||
'type' => 'text',
|
||||
'default_value' => 'Thank you for your interest in:',
|
||||
),
|
||||
),
|
||||
'location' => array(
|
||||
array(
|
||||
array(
|
||||
'param' => 'page_template',
|
||||
'operator' => '==',
|
||||
'value' => 'page-inquiry-thank-you.php',
|
||||
),
|
||||
),
|
||||
),
|
||||
'menu_order' => 0,
|
||||
'position' => 'normal',
|
||||
'active' => true,
|
||||
));
|
||||
}
|
||||
add_action('acf/init', 'homeproz_register_acf_fields');
|
||||
|
||||
@@ -1286,6 +1948,49 @@ function homeproz_register_acf_options_page() {
|
||||
}
|
||||
add_action('acf/init', 'homeproz_register_acf_options_page');
|
||||
|
||||
/**
|
||||
* Enable deep-linking to ACF tabs via URL parameter
|
||||
* Usage: /wp-admin/admin.php?page=theme-options&tab=properties_page
|
||||
*/
|
||||
function homeproz_acf_tab_deeplink() {
|
||||
$screen = get_current_screen();
|
||||
if (!$screen || $screen->id !== 'toplevel_page_theme-options') {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
(function() {
|
||||
var params = new URLSearchParams(window.location.search);
|
||||
var tab = params.get('tab');
|
||||
if (!tab) return;
|
||||
|
||||
// Map friendly tab names to ACF field keys
|
||||
var tabMap = {
|
||||
'contact': 'field_theme_tab_contact',
|
||||
'properties_page': 'field_theme_tab_properties',
|
||||
'social': 'field_theme_tab_social',
|
||||
'footer': 'field_theme_tab_footer',
|
||||
'location': 'field_theme_tab_location',
|
||||
'404': 'field_theme_tab_404'
|
||||
};
|
||||
|
||||
var fieldKey = tabMap[tab] || tab;
|
||||
|
||||
// Wait for ACF to initialize
|
||||
if (typeof acf !== 'undefined') {
|
||||
acf.addAction('ready', function() {
|
||||
var $tab = jQuery('.acf-tab-button[data-key="' + fieldKey + '"]');
|
||||
if ($tab.length) {
|
||||
$tab.trigger('click');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
add_action('admin_footer', 'homeproz_acf_tab_deeplink');
|
||||
|
||||
/**
|
||||
* Update homeproz_get_option to use ACF if available
|
||||
*/
|
||||
@@ -1309,6 +2014,14 @@ function homeproz_get_acf_option($key, $default = '') {
|
||||
'latitude' => 'theme_latitude',
|
||||
'longitude' => 'theme_longitude',
|
||||
'map_embed' => 'theme_map_embed',
|
||||
// 404 Page
|
||||
'404_title' => 'theme_404_title',
|
||||
'404_subtitle' => 'theme_404_subtitle',
|
||||
'404_message' => 'theme_404_message',
|
||||
'404_primary_button' => 'theme_404_primary_button',
|
||||
'404_secondary_button' => 'theme_404_secondary_button',
|
||||
// Footer Copyright
|
||||
'footer_copyright' => 'theme_footer_copyright',
|
||||
);
|
||||
|
||||
// If ACF is active and we have an options page
|
||||
|
||||
@@ -10,184 +10,6 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Property Custom Post Type
|
||||
*/
|
||||
function homeproz_register_property_cpt() {
|
||||
$labels = array(
|
||||
'name' => _x('Properties', 'Post type general name', 'homeproz'),
|
||||
'singular_name' => _x('Property', 'Post type singular name', 'homeproz'),
|
||||
'menu_name' => _x('Properties', 'Admin Menu text', 'homeproz'),
|
||||
'name_admin_bar' => _x('Property', 'Add New on Toolbar', 'homeproz'),
|
||||
'add_new' => __('Add New', 'homeproz'),
|
||||
'add_new_item' => __('Add New Property', 'homeproz'),
|
||||
'new_item' => __('New Property', 'homeproz'),
|
||||
'edit_item' => __('Edit Property', 'homeproz'),
|
||||
'view_item' => __('View Property', 'homeproz'),
|
||||
'all_items' => __('All Properties', 'homeproz'),
|
||||
'search_items' => __('Search Properties', 'homeproz'),
|
||||
'parent_item_colon' => __('Parent Properties:', 'homeproz'),
|
||||
'not_found' => __('No properties found.', 'homeproz'),
|
||||
'not_found_in_trash' => __('No properties found in Trash.', 'homeproz'),
|
||||
'featured_image' => _x('Property Featured Image', 'Overrides the "Featured Image" phrase', 'homeproz'),
|
||||
'set_featured_image' => _x('Set featured image', 'Overrides the "Set featured image" phrase', 'homeproz'),
|
||||
'remove_featured_image' => _x('Remove featured image', 'Overrides the "Remove featured image" phrase', 'homeproz'),
|
||||
'use_featured_image' => _x('Use as featured image', 'Overrides the "Use as featured image" phrase', 'homeproz'),
|
||||
'archives' => _x('Property archives', 'The post type archive label used in nav menus', 'homeproz'),
|
||||
'insert_into_item' => _x('Insert into property', 'Overrides the "Insert into post" phrase', 'homeproz'),
|
||||
'uploaded_to_this_item' => _x('Uploaded to this property', 'Overrides the "Uploaded to this post" phrase', 'homeproz'),
|
||||
'filter_items_list' => _x('Filter properties list', 'Screen reader text', 'homeproz'),
|
||||
'items_list_navigation' => _x('Properties list navigation', 'Screen reader text', 'homeproz'),
|
||||
'items_list' => _x('Properties list', 'Screen reader text', 'homeproz'),
|
||||
);
|
||||
|
||||
$args = array(
|
||||
'labels' => $labels,
|
||||
'public' => true,
|
||||
'publicly_queryable' => true,
|
||||
'show_ui' => true,
|
||||
'show_in_menu' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array('slug' => 'properties', 'with_front' => false),
|
||||
'capability_type' => 'post',
|
||||
'has_archive' => true,
|
||||
'hierarchical' => false,
|
||||
'menu_position' => 5,
|
||||
'menu_icon' => 'dashicons-building',
|
||||
'supports' => array('title', 'editor', 'thumbnail', 'excerpt'),
|
||||
'show_in_rest' => true,
|
||||
);
|
||||
|
||||
register_post_type('property', $args);
|
||||
}
|
||||
add_action('init', 'homeproz_register_property_cpt');
|
||||
|
||||
/**
|
||||
* Register Property Taxonomies
|
||||
*/
|
||||
function homeproz_register_property_taxonomies() {
|
||||
// Property Type (Residential, Commercial, Land, Multi-Family)
|
||||
$type_labels = array(
|
||||
'name' => _x('Property Types', 'Taxonomy general name', 'homeproz'),
|
||||
'singular_name' => _x('Property Type', 'Taxonomy singular name', 'homeproz'),
|
||||
'search_items' => __('Search Property Types', 'homeproz'),
|
||||
'popular_items' => __('Popular Property Types', 'homeproz'),
|
||||
'all_items' => __('All Property Types', 'homeproz'),
|
||||
'parent_item' => null,
|
||||
'parent_item_colon' => null,
|
||||
'edit_item' => __('Edit Property Type', 'homeproz'),
|
||||
'update_item' => __('Update Property Type', 'homeproz'),
|
||||
'add_new_item' => __('Add New Property Type', 'homeproz'),
|
||||
'new_item_name' => __('New Property Type Name', 'homeproz'),
|
||||
'separate_items_with_commas' => __('Separate property types with commas', 'homeproz'),
|
||||
'add_or_remove_items' => __('Add or remove property types', 'homeproz'),
|
||||
'choose_from_most_used' => __('Choose from the most used property types', 'homeproz'),
|
||||
'not_found' => __('No property types found.', 'homeproz'),
|
||||
'menu_name' => __('Property Types', 'homeproz'),
|
||||
);
|
||||
|
||||
register_taxonomy('property_type', array('property'), array(
|
||||
'hierarchical' => true,
|
||||
'labels' => $type_labels,
|
||||
'show_ui' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array('slug' => 'property-type'),
|
||||
));
|
||||
|
||||
// Property Status (Active, Pending, Sold)
|
||||
$status_labels = array(
|
||||
'name' => _x('Property Status', 'Taxonomy general name', 'homeproz'),
|
||||
'singular_name' => _x('Property Status', 'Taxonomy singular name', 'homeproz'),
|
||||
'search_items' => __('Search Property Statuses', 'homeproz'),
|
||||
'popular_items' => __('Popular Property Statuses', 'homeproz'),
|
||||
'all_items' => __('All Property Statuses', 'homeproz'),
|
||||
'parent_item' => null,
|
||||
'parent_item_colon' => null,
|
||||
'edit_item' => __('Edit Property Status', 'homeproz'),
|
||||
'update_item' => __('Update Property Status', 'homeproz'),
|
||||
'add_new_item' => __('Add New Property Status', 'homeproz'),
|
||||
'new_item_name' => __('New Property Status Name', 'homeproz'),
|
||||
'separate_items_with_commas' => __('Separate statuses with commas', 'homeproz'),
|
||||
'add_or_remove_items' => __('Add or remove statuses', 'homeproz'),
|
||||
'choose_from_most_used' => __('Choose from the most used statuses', 'homeproz'),
|
||||
'not_found' => __('No statuses found.', 'homeproz'),
|
||||
'menu_name' => __('Status', 'homeproz'),
|
||||
);
|
||||
|
||||
register_taxonomy('property_status', array('property'), array(
|
||||
'hierarchical' => true,
|
||||
'labels' => $status_labels,
|
||||
'show_ui' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array('slug' => 'property-status'),
|
||||
));
|
||||
|
||||
// Property Location (Cities/Areas)
|
||||
$location_labels = array(
|
||||
'name' => _x('Locations', 'Taxonomy general name', 'homeproz'),
|
||||
'singular_name' => _x('Location', 'Taxonomy singular name', 'homeproz'),
|
||||
'search_items' => __('Search Locations', 'homeproz'),
|
||||
'popular_items' => __('Popular Locations', 'homeproz'),
|
||||
'all_items' => __('All Locations', 'homeproz'),
|
||||
'parent_item' => __('Parent Location', 'homeproz'),
|
||||
'parent_item_colon' => __('Parent Location:', 'homeproz'),
|
||||
'edit_item' => __('Edit Location', 'homeproz'),
|
||||
'update_item' => __('Update Location', 'homeproz'),
|
||||
'add_new_item' => __('Add New Location', 'homeproz'),
|
||||
'new_item_name' => __('New Location Name', 'homeproz'),
|
||||
'separate_items_with_commas' => __('Separate locations with commas', 'homeproz'),
|
||||
'add_or_remove_items' => __('Add or remove locations', 'homeproz'),
|
||||
'choose_from_most_used' => __('Choose from the most used locations', 'homeproz'),
|
||||
'not_found' => __('No locations found.', 'homeproz'),
|
||||
'menu_name' => __('Locations', 'homeproz'),
|
||||
);
|
||||
|
||||
register_taxonomy('property_location', array('property'), array(
|
||||
'hierarchical' => true,
|
||||
'labels' => $location_labels,
|
||||
'show_ui' => true,
|
||||
'show_in_rest' => true,
|
||||
'show_admin_column' => true,
|
||||
'query_var' => true,
|
||||
'rewrite' => array('slug' => 'location'),
|
||||
));
|
||||
}
|
||||
add_action('init', 'homeproz_register_property_taxonomies');
|
||||
|
||||
/**
|
||||
* Add default taxonomy terms on theme activation
|
||||
*/
|
||||
function homeproz_add_default_terms() {
|
||||
// Default Property Types
|
||||
$property_types = array('Residential', 'Commercial', 'Land', 'Multi-Family');
|
||||
foreach ($property_types as $type) {
|
||||
if (!term_exists($type, 'property_type')) {
|
||||
wp_insert_term($type, 'property_type');
|
||||
}
|
||||
}
|
||||
|
||||
// Default Property Statuses
|
||||
$property_statuses = array('Active', 'Pending', 'Sold');
|
||||
foreach ($property_statuses as $status) {
|
||||
if (!term_exists($status, 'property_status')) {
|
||||
wp_insert_term($status, 'property_status');
|
||||
}
|
||||
}
|
||||
|
||||
// Default Locations (Minnesota cities near Albert Lea)
|
||||
$locations = array('Albert Lea', 'Austin', 'Owatonna', 'Faribault', 'Mankato', 'Rochester');
|
||||
foreach ($locations as $location) {
|
||||
if (!term_exists($location, 'property_location')) {
|
||||
wp_insert_term($location, 'property_location');
|
||||
}
|
||||
}
|
||||
}
|
||||
add_action('after_switch_theme', 'homeproz_add_default_terms');
|
||||
|
||||
/**
|
||||
* Register Agent Custom Post Type
|
||||
*/
|
||||
@@ -429,8 +251,6 @@ function homeproz_get_featured_mls_ids() {
|
||||
* Flush rewrite rules on theme activation
|
||||
*/
|
||||
function homeproz_rewrite_flush() {
|
||||
homeproz_register_property_cpt();
|
||||
homeproz_register_property_taxonomies();
|
||||
homeproz_register_agent_cpt();
|
||||
homeproz_register_mls_override_cpt();
|
||||
flush_rewrite_rules();
|
||||
|
||||
@@ -77,6 +77,15 @@ function homeproz_body_classes($classes) {
|
||||
$classes[] = 'no-sidebar';
|
||||
}
|
||||
|
||||
// Add title animations class if enabled (default true)
|
||||
if (is_page() && !is_front_page()) {
|
||||
$enable_animations = get_field('enable_title_animations');
|
||||
// Default to true if not set
|
||||
if ($enable_animations === null || $enable_animations === '' || $enable_animations) {
|
||||
$classes[] = 'has-title-animations';
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
add_filter('body_class', 'homeproz_body_classes');
|
||||
@@ -144,17 +153,6 @@ function homeproz_fallback_menu() {
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Fallback footer menu when no menu is assigned
|
||||
*/
|
||||
function homeproz_footer_fallback_menu() {
|
||||
echo '<ul class="footer-menu">';
|
||||
echo '<li class="menu-item"><a href="' . esc_url(home_url('/')) . '">Home</a></li>';
|
||||
echo '<li class="menu-item"><a href="' . esc_url(home_url('/properties/')) . '">Properties</a></li>';
|
||||
echo '<li class="menu-item"><a href="' . esc_url(get_post_type_archive_link('agent')) . '">Agents</a></li>';
|
||||
echo '<li class="menu-item"><a href="' . esc_url(home_url('/about/')) . '">About</a></li>';
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get status sort order value
|
||||
@@ -246,99 +244,227 @@ function homeproz_get_featured_mls_listings($count = 3) {
|
||||
}
|
||||
|
||||
$table = $wpdb->prefix . 'mls_properties';
|
||||
$residential_types = array('Residential', 'Residential Income');
|
||||
|
||||
// Albert Lea coordinates and 30-mile bounding box
|
||||
// 30 miles ~ 0.43 deg latitude, ~0.6 deg longitude at this latitude
|
||||
$albert_lea_lat = 43.679;
|
||||
$albert_lea_lon = -93.360;
|
||||
$lat_range = 0.43;
|
||||
$lon_range = 0.60;
|
||||
|
||||
$min_lat = $albert_lea_lat - $lat_range;
|
||||
$max_lat = $albert_lea_lat + $lat_range;
|
||||
$min_lon = $albert_lea_lon - $lon_range;
|
||||
$max_lon = $albert_lea_lon + $lon_range;
|
||||
|
||||
// Get all HomeProz listings (active only, exclude TBD addresses)
|
||||
// Uses \b word boundary for whole-word match, case-insensitive
|
||||
$homeproz_listings = $wpdb->get_results(
|
||||
"SELECT listing_key, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE is_homeproz = 1
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND COALESCE(street_name, '') NOT REGEXP '\\\\bTBD\\\\b'
|
||||
AND COALESCE(street_number, '') NOT REGEXP '\\\\bTBD\\\\b'
|
||||
AND photos_count > 0
|
||||
ORDER BY modification_timestamp DESC"
|
||||
);
|
||||
|
||||
// Track all listing keys we've added
|
||||
$added_keys = array();
|
||||
$listings = array();
|
||||
|
||||
// Add HomeProz listings first
|
||||
foreach ($homeproz_listings as $listing) {
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, true);
|
||||
// 1. Get featured MLS IDs from the override system (FIRST PRIORITY)
|
||||
$featured_mls_ids = function_exists('homeproz_get_featured_mls_ids')
|
||||
? homeproz_get_featured_mls_ids()
|
||||
: array();
|
||||
|
||||
// Add featured residential listings first
|
||||
if (!empty($featured_mls_ids)) {
|
||||
$id_placeholders = implode(',', array_fill(0, count($featured_mls_ids), '%s'));
|
||||
$type_placeholders = implode(',', array_fill(0, count($residential_types), '%s'));
|
||||
$featured_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE listing_id IN ({$id_placeholders})
|
||||
AND property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND photos_count > 0
|
||||
ORDER BY modification_timestamp DESC",
|
||||
...array_merge($featured_mls_ids, $residential_types)
|
||||
);
|
||||
$featured_listings = $wpdb->get_results($featured_query);
|
||||
|
||||
foreach ($featured_listings as $listing) {
|
||||
if (count($listings) >= $count) break;
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, false);
|
||||
$added_keys[] = $listing->listing_key;
|
||||
}
|
||||
}
|
||||
|
||||
// If we need padding, get nearby average-priced listings
|
||||
// 2. Add HomeProz residential listings (if we need more)
|
||||
if (count($listings) < $count) {
|
||||
$type_placeholders = implode(',', array_fill(0, count($residential_types), '%s'));
|
||||
$exclude_clause = '';
|
||||
if (!empty($added_keys)) {
|
||||
$key_placeholders = implode(',', array_fill(0, count($added_keys), '%s'));
|
||||
$exclude_clause = $wpdb->prepare(" AND listing_key NOT IN ({$key_placeholders})", ...$added_keys);
|
||||
}
|
||||
|
||||
$homeproz_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE is_homeproz = 1
|
||||
AND property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND COALESCE(street_name, '') NOT REGEXP '\\\\bTBD\\\\b'
|
||||
AND COALESCE(street_number, '') NOT REGEXP '\\\\bTBD\\\\b'
|
||||
AND photos_count > 0
|
||||
{$exclude_clause}
|
||||
ORDER BY modification_timestamp DESC",
|
||||
...$residential_types
|
||||
);
|
||||
$homeproz_listings = $wpdb->get_results($homeproz_query);
|
||||
|
||||
foreach ($homeproz_listings as $listing) {
|
||||
if (count($listings) >= $count) break;
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, true);
|
||||
$added_keys[] = $listing->listing_key;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Fill remaining slots with random residential listings
|
||||
if (count($listings) < $count) {
|
||||
$needed = $count - count($listings);
|
||||
$homeproz_keys = array_column($homeproz_listings, 'listing_key');
|
||||
$type_placeholders = implode(',', array_fill(0, count($residential_types), '%s'));
|
||||
|
||||
// Get average price for residential properties near Albert Lea
|
||||
$avg_price = $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT AVG(list_price)
|
||||
$exclude_clause = '';
|
||||
if (!empty($added_keys)) {
|
||||
$key_placeholders = implode(',', array_fill(0, count($added_keys), '%s'));
|
||||
$exclude_clause = $wpdb->prepare(" AND listing_key NOT IN ({$key_placeholders})", ...$added_keys);
|
||||
}
|
||||
|
||||
$random_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE standard_status = 'Active'
|
||||
WHERE property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND property_type = 'Residential'
|
||||
AND latitude BETWEEN %f AND %f
|
||||
AND longitude BETWEEN %f AND %f
|
||||
AND list_price > 0",
|
||||
$min_lat, $max_lat, $min_lon, $max_lon
|
||||
));
|
||||
AND photos_count > 0
|
||||
{$exclude_clause}
|
||||
ORDER BY RAND()
|
||||
LIMIT %d",
|
||||
...array_merge($residential_types, array($needed))
|
||||
);
|
||||
$random_listings = $wpdb->get_results($random_query);
|
||||
|
||||
if ($avg_price > 0) {
|
||||
// +/- 10% of average price
|
||||
$min_price = $avg_price * 0.9;
|
||||
$max_price = $avg_price * 1.1;
|
||||
foreach ($random_listings as $listing) {
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Build exclusion clause for HomeProz listings
|
||||
$exclude_clause = '';
|
||||
if (!empty($homeproz_keys)) {
|
||||
$placeholders = implode(',', array_fill(0, count($homeproz_keys), '%s'));
|
||||
$exclude_clause = $wpdb->prepare(
|
||||
" AND listing_key NOT IN ({$placeholders})",
|
||||
...$homeproz_keys
|
||||
);
|
||||
}
|
||||
return $listings;
|
||||
}
|
||||
|
||||
// Get random padding listings within price range and distance
|
||||
$padding_listings = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT listing_key, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND property_type = 'Residential'
|
||||
AND latitude BETWEEN %f AND %f
|
||||
AND longitude BETWEEN %f AND %f
|
||||
AND list_price BETWEEN %f AND %f
|
||||
AND photos_count > 0
|
||||
{$exclude_clause}
|
||||
ORDER BY RAND()
|
||||
LIMIT %d",
|
||||
$min_lat, $max_lat, $min_lon, $max_lon,
|
||||
$min_price, $max_price,
|
||||
$needed
|
||||
));
|
||||
/**
|
||||
* Get featured commercial/land MLS listings for homepage
|
||||
*
|
||||
* Priority order:
|
||||
* 1. Featured (favorited) commercial properties from MLS Editor
|
||||
* 2. HomeProz-listed commercial properties
|
||||
* 3. Random commercial/land properties to fill remaining slots
|
||||
*
|
||||
* @param int $count Number of listings to return (default 3)
|
||||
* @return array Array of formatted listing data
|
||||
*/
|
||||
function homeproz_get_featured_commercial_listings($count = 3) {
|
||||
global $wpdb;
|
||||
|
||||
foreach ($padding_listings as $listing) {
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, false);
|
||||
}
|
||||
if (!function_exists('mls_get_image_url')) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$table = $wpdb->prefix . 'mls_properties';
|
||||
$commercial_types = array('Commercial Sale', 'Land', 'Farm');
|
||||
$type_placeholders = implode(',', array_fill(0, count($commercial_types), '%s'));
|
||||
|
||||
// Track all listing keys we've added
|
||||
$added_keys = array();
|
||||
$listings = array();
|
||||
|
||||
// 1. Get featured MLS IDs from the override system
|
||||
$featured_mls_ids = function_exists('homeproz_get_featured_mls_ids')
|
||||
? homeproz_get_featured_mls_ids()
|
||||
: array();
|
||||
|
||||
// Add featured commercial listings first
|
||||
if (!empty($featured_mls_ids)) {
|
||||
$id_placeholders = implode(',', array_fill(0, count($featured_mls_ids), '%s'));
|
||||
$featured_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE listing_id IN ({$id_placeholders})
|
||||
AND property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND photos_count > 0
|
||||
ORDER BY modification_timestamp DESC",
|
||||
...array_merge($featured_mls_ids, $commercial_types)
|
||||
);
|
||||
$featured_listings = $wpdb->get_results($featured_query);
|
||||
|
||||
foreach ($featured_listings as $listing) {
|
||||
if (count($listings) >= $count) break;
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, false);
|
||||
$added_keys[] = $listing->listing_key;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Add HomeProz commercial listings (if we need more)
|
||||
if (count($listings) < $count) {
|
||||
$exclude_clause = '';
|
||||
if (!empty($added_keys)) {
|
||||
$key_placeholders = implode(',', array_fill(0, count($added_keys), '%s'));
|
||||
$exclude_clause = $wpdb->prepare(" AND listing_key NOT IN ({$key_placeholders})", ...$added_keys);
|
||||
}
|
||||
|
||||
$homeproz_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE is_homeproz = 1
|
||||
AND property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND photos_count > 0
|
||||
{$exclude_clause}
|
||||
ORDER BY modification_timestamp DESC",
|
||||
...$commercial_types
|
||||
);
|
||||
$homeproz_listings = $wpdb->get_results($homeproz_query);
|
||||
|
||||
foreach ($homeproz_listings as $listing) {
|
||||
if (count($listings) >= $count) break;
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, true);
|
||||
$added_keys[] = $listing->listing_key;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Fill remaining slots with random commercial/land listings
|
||||
if (count($listings) < $count) {
|
||||
$needed = $count - count($listings);
|
||||
|
||||
$exclude_clause = '';
|
||||
if (!empty($added_keys)) {
|
||||
$key_placeholders = implode(',', array_fill(0, count($added_keys), '%s'));
|
||||
$exclude_clause = $wpdb->prepare(" AND listing_key NOT IN ({$key_placeholders})", ...$added_keys);
|
||||
}
|
||||
|
||||
$random_query = $wpdb->prepare(
|
||||
"SELECT listing_key, listing_id, list_price, street_number, street_name, street_suffix,
|
||||
city, state_or_province, postal_code, bedrooms_total, bathrooms_total,
|
||||
living_area, standard_status, property_type, photos_count
|
||||
FROM {$table}
|
||||
WHERE property_type IN ({$type_placeholders})
|
||||
AND standard_status = 'Active'
|
||||
AND mlg_can_view = 1
|
||||
AND photos_count > 0
|
||||
{$exclude_clause}
|
||||
ORDER BY RAND()
|
||||
LIMIT %d",
|
||||
...array_merge($commercial_types, array($needed))
|
||||
);
|
||||
$random_listings = $wpdb->get_results($random_query);
|
||||
|
||||
foreach ($random_listings as $listing) {
|
||||
$listings[] = homeproz_format_mls_listing_for_json($listing, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,10 +495,23 @@ function homeproz_format_mls_listing_for_json($listing, $is_homeproz = false) {
|
||||
$full_address .= ', ' . $listing->state_or_province;
|
||||
}
|
||||
|
||||
// Check for MLS override (custom featured photo)
|
||||
$listing_id = isset($listing->listing_id) ? $listing->listing_id : null;
|
||||
$override = function_exists('homeproz_get_mls_override') ? homeproz_get_mls_override($listing_id) : null;
|
||||
|
||||
// Get image URL - use override if available, otherwise MLS image
|
||||
if ($override && !empty($override['featured_photo'])) {
|
||||
$image_url = isset($override['featured_photo']['sizes']['medium_large'])
|
||||
? $override['featured_photo']['sizes']['medium_large']
|
||||
: $override['featured_photo']['url'];
|
||||
} else {
|
||||
$image_url = mls_get_image_url($listing->listing_key, 1, 'thumb');
|
||||
}
|
||||
|
||||
return array(
|
||||
'listing_key' => $listing->listing_key,
|
||||
'url' => home_url('/properties/?listing=' . $listing->listing_key),
|
||||
'image_url' => mls_get_image_url($listing->listing_key, 1, 'thumb'),
|
||||
'image_url' => $image_url,
|
||||
'price' => (float) $listing->list_price,
|
||||
'price_formatted' => homeproz_format_price($listing->list_price),
|
||||
'address' => $full_address,
|
||||
@@ -438,13 +577,14 @@ function homeproz_get_mls_cities($min_listings = 5) {
|
||||
|
||||
// Get cities with at least $min_listings active properties
|
||||
// Also filter to MN and IA only
|
||||
$cities = $wpdb->get_col($wpdb->prepare(
|
||||
"SELECT city FROM {$table}
|
||||
// Returns objects with city and state_code for "City, SS" display
|
||||
$cities = $wpdb->get_results($wpdb->prepare(
|
||||
"SELECT city, state_or_province as state_code FROM {$table}
|
||||
WHERE mlg_can_view = 1
|
||||
AND standard_status = 'Active'
|
||||
AND city IS NOT NULL
|
||||
AND state_or_province IN ('MN', 'IA')
|
||||
GROUP BY city
|
||||
GROUP BY city, state_or_province
|
||||
HAVING COUNT(*) >= %d
|
||||
ORDER BY city ASC",
|
||||
$min_listings
|
||||
@@ -518,3 +658,43 @@ function homeproz_get_active_locations() {
|
||||
'order' => 'ASC',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "Edit Page" link to admin bar for archive pages with Theme Options
|
||||
*
|
||||
* Since archive pages don't have a traditional "Edit" link, this adds
|
||||
* a link to the relevant Theme Options tab for editing hero content, etc.
|
||||
*/
|
||||
function homeproz_admin_bar_edit_link($wp_admin_bar) {
|
||||
if (!is_user_logged_in() || !current_user_can('edit_posts')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$edit_link = null;
|
||||
$title = null;
|
||||
|
||||
// Properties archive
|
||||
if (is_post_type_archive('property')) {
|
||||
$edit_link = admin_url('admin.php?page=theme-options&tab=properties_page');
|
||||
$title = 'Edit Page';
|
||||
}
|
||||
|
||||
// Add more archive pages as needed:
|
||||
// if (is_post_type_archive('agent')) {
|
||||
// $edit_link = admin_url('admin.php?page=theme-options&tab=agents_page');
|
||||
// $title = 'Edit Page';
|
||||
// }
|
||||
|
||||
if ($edit_link) {
|
||||
$wp_admin_bar->add_node(array(
|
||||
'id' => 'edit-archive-page',
|
||||
'title' => $title,
|
||||
'href' => $edit_link,
|
||||
'meta' => array(
|
||||
'class' => 'ab-item',
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
add_action('admin_bar_menu', 'homeproz_admin_bar_edit_link', 80);
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
@import '../template-parts/content/content-join.scss';
|
||||
@import '../template-parts/content/content-contact.scss';
|
||||
@import '../template-parts/content/content-archive.scss';
|
||||
@import '../template-parts/content/content-property-inquiry.scss';
|
||||
@import '../template-parts/sidebar/blog-sidebar.scss';
|
||||
@import '../template-parts/content/content-templates.scss';
|
||||
@import '../template-parts/content/content-communities.scss';
|
||||
@@ -39,6 +40,7 @@
|
||||
@import '../template-parts/components/feature-block.scss';
|
||||
@import '../template-parts/components/service-cards.scss';
|
||||
@import '../template-parts/components/property-type-boxes.scss';
|
||||
@import '../template-parts/components/custom-content-section.scss';
|
||||
|
||||
// Import page templates
|
||||
@import '../page-templates/page-templates.scss';
|
||||
@@ -89,20 +91,6 @@ body {
|
||||
line-height: 1.6;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
// Subtle noise texture overlay for luxury feel
|
||||
&::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
opacity: 0.03;
|
||||
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E");
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================
|
||||
@@ -197,6 +185,12 @@ a {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&-sm {
|
||||
padding: 0.5rem 1rem;
|
||||
font-size: 0.75rem;
|
||||
gap: 0.375rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Status badges
|
||||
@@ -223,6 +217,28 @@ a {
|
||||
background-color: var(--color-sold);
|
||||
color: white;
|
||||
}
|
||||
|
||||
// Property type badge
|
||||
&-type {
|
||||
background-color: #1E40AF;
|
||||
color: #DBEAFE;
|
||||
}
|
||||
|
||||
// Status badges
|
||||
&-active {
|
||||
background-color: #065F46;
|
||||
color: #D1FAE5;
|
||||
}
|
||||
|
||||
&-pending {
|
||||
background-color: #92400E;
|
||||
color: #FEF3C7;
|
||||
}
|
||||
|
||||
&-sold {
|
||||
background-color: #374151;
|
||||
color: #D1D5DB;
|
||||
}
|
||||
}
|
||||
|
||||
// Cards
|
||||
@@ -262,6 +278,11 @@ select {
|
||||
}
|
||||
}
|
||||
|
||||
// Contact Form 7 - remove auto-inserted br tags
|
||||
.wpcf7 br {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Utility Classes
|
||||
// ============================================
|
||||
@@ -329,3 +350,31 @@ select {
|
||||
::view-transition-new(root) {
|
||||
animation: none;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// Section Title Hover Animations
|
||||
// ============================================
|
||||
|
||||
.has-title-animations {
|
||||
// Shared animated title styles
|
||||
.about-team-title,
|
||||
.about-broker-title,
|
||||
.about-story-content h2,
|
||||
.about-story-content h3,
|
||||
.contact-form-title,
|
||||
.contact-info-title,
|
||||
.join-team-title,
|
||||
.join-benefit-title,
|
||||
.section-title,
|
||||
.resource-featured-title,
|
||||
.resource-card-title {
|
||||
display: inline-block;
|
||||
transition: letter-spacing 0.2s ease, transform 0.2s ease;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
letter-spacing: 0.02em;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Custom Content Section
|
||||
*
|
||||
* Displays a WYSIWYG content area with optional title.
|
||||
*
|
||||
* @package HomeProz
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get passed arguments
|
||||
$title = $args['title'] ?? '';
|
||||
$content = $args['content'] ?? '';
|
||||
|
||||
// Don't render if no content
|
||||
if (empty($content)) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<section class="custom-content-section">
|
||||
<div class="container">
|
||||
<?php if (!empty($title)) : ?>
|
||||
<header class="section-header">
|
||||
<h2 class="section-title"><?php echo esc_html($title); ?></h2>
|
||||
</header>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="custom-content-body">
|
||||
<?php echo wp_kses_post($content); ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Custom Content Section Styles
|
||||
*
|
||||
* WYSIWYG content area for homepage.
|
||||
*
|
||||
* @package HomeProz
|
||||
*/
|
||||
|
||||
.custom-content-section {
|
||||
padding: 4rem 0;
|
||||
background-color: var(--color-bg);
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 3rem 0;
|
||||
}
|
||||
|
||||
// Alternate background for visual variety
|
||||
&:nth-of-type(even) {
|
||||
background-color: var(--color-bg-card);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-content-body {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
font-size: 1rem;
|
||||
line-height: 1.7;
|
||||
color: var(--color-text);
|
||||
|
||||
h2, h3, h4, h5, h6 {
|
||||
font-family: var(--font-display);
|
||||
color: var(--color-text);
|
||||
margin-top: 2rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1.25rem;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--color-accent);
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-accent-hover);
|
||||
}
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
margin-bottom: 1.25rem;
|
||||
padding-left: 1.5rem;
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
ol {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 4px solid var(--color-accent);
|
||||
padding-left: 1.5rem;
|
||||
margin: 1.5rem 0;
|
||||
font-style: italic;
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
// WordPress alignment classes
|
||||
.alignleft {
|
||||
float: left;
|
||||
margin-right: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.alignright {
|
||||
float: right;
|
||||
margin-left: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.aligncenter {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
// Clear floats
|
||||
&::after {
|
||||
content: '';
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
Regular → Executable
+62
-50
@@ -3,7 +3,7 @@
|
||||
* Property Type Showcase Boxes
|
||||
*
|
||||
* Displays category boxes for browsing properties by type.
|
||||
* Links to the property archive with type filter applied.
|
||||
* Fully configurable via ACF repeater on homepage.
|
||||
*
|
||||
* @package HomeProz
|
||||
*/
|
||||
@@ -13,72 +13,84 @@ if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get property types with counts from MLS
|
||||
$property_types = homeproz_get_mls_property_types();
|
||||
// Get section title/subtitle from ACF
|
||||
$section_title = get_field('home_property_types_title') ?: 'Browse by Property Type';
|
||||
$section_subtitle = get_field('home_property_types_subtitle') ?: 'Find the perfect property for your needs';
|
||||
|
||||
// Get property type boxes from ACF repeater
|
||||
$property_types = get_field('home_property_type_boxes');
|
||||
|
||||
// If no ACF data, use defaults
|
||||
if (empty($property_types)) {
|
||||
return;
|
||||
$property_types = array(
|
||||
array(
|
||||
'title' => 'Residential',
|
||||
'description' => 'Single family homes, condos & townhomes',
|
||||
'url' => home_url('/properties/?property_type=Residential'),
|
||||
'icon' => 'home',
|
||||
),
|
||||
array(
|
||||
'title' => 'Land',
|
||||
'description' => 'Vacant lots & acreages',
|
||||
'url' => home_url('/properties/?property_type=Land'),
|
||||
'icon' => 'land',
|
||||
),
|
||||
array(
|
||||
'title' => 'Commercial',
|
||||
'description' => 'Office, retail & industrial',
|
||||
'url' => home_url('/properties/?property_type=Commercial+Sale'),
|
||||
'icon' => 'building',
|
||||
),
|
||||
array(
|
||||
'title' => 'Farm',
|
||||
'description' => 'Agricultural & hobby farms',
|
||||
'url' => home_url('/properties/?property_type=Farm'),
|
||||
'icon' => 'farm',
|
||||
),
|
||||
array(
|
||||
'title' => 'Multi-Family',
|
||||
'description' => 'Duplexes, triplexes & apartments',
|
||||
'url' => home_url('/properties/?property_type=Residential+Income'),
|
||||
'icon' => 'multi-family',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Define display configuration for each type
|
||||
// Icons use Feather Icons (already in use throughout the site)
|
||||
$type_config = array(
|
||||
'Residential' => array(
|
||||
'icon' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>',
|
||||
'description' => 'Single family homes, condos & townhomes',
|
||||
),
|
||||
'Land' => array(
|
||||
'icon' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 22h20"/><path d="M6.36 17.4L4 22h16l-4.24-7.94a.5.5 0 0 0-.88 0L12.5 18.1l-2.5-4.5a.5.5 0 0 0-.88 0z"/><circle cx="13.5" cy="5.5" r="2.5"/></svg>',
|
||||
'description' => 'Vacant lots & acreages',
|
||||
),
|
||||
'Commercial Sale' => array(
|
||||
'icon' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="4" y="2" width="16" height="20" rx="2" ry="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01M12 6h.01M16 6h.01M8 10h.01M12 10h.01M16 10h.01M8 14h.01M12 14h.01M16 14h.01"/></svg>',
|
||||
'label' => 'Commercial',
|
||||
'description' => 'Office, retail & industrial',
|
||||
),
|
||||
'Farm' => array(
|
||||
'icon' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/><path d="M9 21v-6h6v6"/><path d="M10 9h4"/></svg>',
|
||||
'description' => 'Agricultural & hobby farms',
|
||||
),
|
||||
'Residential Income' => array(
|
||||
'icon' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 12h6"/><path d="M9 16h6"/></svg>',
|
||||
'label' => 'Multi-Family',
|
||||
'description' => 'Duplexes, triplexes & apartments',
|
||||
),
|
||||
);
|
||||
/**
|
||||
* Render icon SVG based on icon name
|
||||
*/
|
||||
function homeproz_render_property_type_icon($icon) {
|
||||
$icons = array(
|
||||
'home' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>',
|
||||
'land' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 22h20"/><path d="M6.36 17.4L4 22h16l-4.24-7.94a.5.5 0 0 0-.88 0L12.5 18.1l-2.5-4.5a.5.5 0 0 0-.88 0z"/><circle cx="13.5" cy="5.5" r="2.5"/></svg>',
|
||||
'building' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="4" y="2" width="16" height="20" rx="2" ry="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01M12 6h.01M16 6h.01M8 10h.01M12 10h.01M16 10h.01M8 14h.01M12 14h.01M16 14h.01"/></svg>',
|
||||
'farm' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 21h18"/><path d="M5 21V7l7-4 7 4v14"/><path d="M9 21v-6h6v6"/><path d="M10 9h4"/></svg>',
|
||||
'multi-family' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><path d="M9 12h6"/><path d="M9 16h6"/></svg>',
|
||||
'key' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4"/></svg>',
|
||||
'map-pin' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>',
|
||||
'dollar-sign' => '<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>',
|
||||
);
|
||||
|
||||
// Filter to only show configured types and sort by count
|
||||
$display_types = array();
|
||||
foreach ($property_types as $type) {
|
||||
if (isset($type_config[$type->property_type])) {
|
||||
$display_types[] = $type;
|
||||
}
|
||||
return isset($icons[$icon]) ? $icons[$icon] : $icons['home'];
|
||||
}
|
||||
?>
|
||||
|
||||
<section class="property-type-boxes">
|
||||
<div class="container">
|
||||
<header class="section-header">
|
||||
<h2 class="section-title">Browse by Property Type</h2>
|
||||
<p class="section-subtitle">Find the perfect property for your needs</p>
|
||||
<h2 class="section-title"><?php echo esc_html($section_title); ?></h2>
|
||||
<p class="section-subtitle"><?php echo esc_html($section_subtitle); ?></p>
|
||||
</header>
|
||||
|
||||
<div class="type-boxes-grid">
|
||||
<?php foreach ($display_types as $type) :
|
||||
$type_name = $type->property_type;
|
||||
$config = $type_config[$type_name];
|
||||
$label = isset($config['label']) ? $config['label'] : $type_name;
|
||||
$count = number_format($type->count);
|
||||
$url = add_query_arg('property_type', urlencode($type_name), home_url('/properties/'));
|
||||
?>
|
||||
<a href="<?php echo esc_url($url); ?>" class="type-box">
|
||||
<?php foreach ($property_types as $type) : ?>
|
||||
<a href="<?php echo esc_url($type['url']); ?>" class="type-box">
|
||||
<div class="type-box-icon">
|
||||
<?php echo $config['icon']; ?>
|
||||
<?php echo homeproz_render_property_type_icon($type['icon']); ?>
|
||||
</div>
|
||||
<div class="type-box-content">
|
||||
<h3 class="type-box-title"><?php echo esc_html($label); ?></h3>
|
||||
<p class="type-box-description"><?php echo esc_html($config['description']); ?></p>
|
||||
<span class="type-box-count"><?php echo esc_html($count); ?> listings</span>
|
||||
<h3 class="type-box-title"><?php echo esc_html($type['title']); ?></h3>
|
||||
<p class="type-box-description"><?php echo esc_html($type['description']); ?></p>
|
||||
</div>
|
||||
<div class="type-box-arrow">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
|
||||
Regular → Executable
+21
-27
@@ -37,7 +37,9 @@
|
||||
.type-box {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1.5rem;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 1.75rem 1.5rem;
|
||||
background-color: var(--color-bg-dark);
|
||||
border: 1px solid var(--color-border);
|
||||
border-radius: 0.5rem;
|
||||
@@ -48,10 +50,6 @@
|
||||
border-color: var(--color-accent);
|
||||
transform: translateY(-2px);
|
||||
|
||||
.type-box-icon {
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
.type-box-arrow {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
@@ -59,13 +57,15 @@
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
padding: 1.25rem;
|
||||
padding: 1.25rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.type-box-icon {
|
||||
color: var(--color-text-muted);
|
||||
margin-bottom: 1rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
color: var(--color-accent);
|
||||
margin-bottom: 1.25rem;
|
||||
transition: color 0.2s ease;
|
||||
|
||||
svg {
|
||||
@@ -73,7 +73,7 @@
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
margin-bottom: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
svg {
|
||||
width: 28px;
|
||||
@@ -84,48 +84,42 @@
|
||||
|
||||
.type-box-content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.type-box-title {
|
||||
font-family: var(--font-display);
|
||||
font-size: 1.125rem;
|
||||
font-weight: 600;
|
||||
font-size: 1.375rem;
|
||||
font-weight: 400;
|
||||
color: var(--color-text);
|
||||
margin-bottom: 0.25rem;
|
||||
margin-bottom: 0.625rem;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
font-size: 1rem;
|
||||
font-size: 1.125rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.type-box-description {
|
||||
font-size: 0.8125rem;
|
||||
color: var(--color-text-muted);
|
||||
line-height: 1.4;
|
||||
margin-bottom: 0.75rem;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 0;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
font-size: 0.75rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.type-box-count {
|
||||
display: inline-block;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-accent-light);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
|
||||
.type-box-arrow {
|
||||
align-self: flex-end;
|
||||
align-self: center;
|
||||
color: var(--color-accent);
|
||||
opacity: 0;
|
||||
transform: translateX(-8px);
|
||||
transition: all 0.2s ease;
|
||||
margin-top: 0.75rem;
|
||||
margin-top: 1rem;
|
||||
|
||||
@media (max-width: 768px) {
|
||||
display: none;
|
||||
|
||||
Reference in New Issue
Block a user