Homepage structural enhancements from RHR analysis

Phase 8 P1 tasks completed:
- Added location search dropdown to hero section (html-98b)
- Added service cards section with Buy/Rent/Sell options (html-5bw)
- Separated Featured Homes and Commercial/Land into distinct sections (html-2fp)

Changes:
- hero-section.php: New show_location_search option with community dropdown
- service-cards.php/scss: New component with 3 service cards
- front-page.php: Hero with search, service cards, separate property sections
- Added community terms: Glenville, Emmons, Clarks Grove, Alden, Hartland, Geneva
This commit is contained in:
Hanson.xyz Dev
2025-11-30 02:33:25 -06:00
parent 5b629bdbab
commit 23a7155955
14 changed files with 395 additions and 18 deletions
View File
View File
View File
+1 -1
View File
File diff suppressed because one or more lines are too long
Vendored Executable → Regular
View File
+77 -13
View File
@@ -12,16 +12,43 @@ if (!defined('ABSPATH')) {
get_header();
// Get featured properties (3 most recent active listings)
$featured_properties = new WP_Query(array(
// Get featured residential properties (3 most recent active residential listings)
$featured_residential = 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' => 'residential',
),
),
'orderby' => 'date',
'order' => 'DESC',
));
// Get featured commercial/land properties (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',
@@ -31,31 +58,35 @@ $featured_properties = new WP_Query(array(
<main id="primary" class="site-main homepage-main">
<?php
// Hero Section
// Hero Section with Location Search
get_template_part('template-parts/components/hero-section', null, array(
'title' => 'Find Your Dream Home Today',
'subtitle' => 'Expert real estate services for buyers and sellers in Albert Lea and the surrounding Minnesota communities.',
'primary_cta_text' => 'View Properties',
'show_location_search' => true,
'primary_cta_text' => 'View All Properties',
'primary_cta_url' => home_url('/properties/'),
'secondary_cta_text' => 'Contact Us',
'secondary_cta_url' => home_url('/contact/'),
'size' => 'large',
));
// Service Cards Section (Buy/Rent/Sell)
get_template_part('template-parts/components/service-cards');
?>
<!-- Featured Properties Section -->
<!-- Featured Residential Properties Section -->
<section class="featured-properties-section">
<div class="container">
<header class="section-header">
<h2 class="section-title">Current Listings</h2>
<p class="section-subtitle">Browse our featured properties for sale</p>
<h2 class="section-title">Featured Homes</h2>
<p class="section-subtitle">Browse our residential properties for sale</p>
</header>
<?php if ($featured_properties->have_posts()) : ?>
<?php if ($featured_residential->have_posts()) : ?>
<div class="property-grid property-grid--3col">
<?php
while ($featured_properties->have_posts()) :
$featured_properties->the_post();
while ($featured_residential->have_posts()) :
$featured_residential->the_post();
get_template_part('template-parts/property/property-card');
endwhile;
wp_reset_postdata();
@@ -63,15 +94,48 @@ $featured_properties = new WP_Query(array(
</div>
<div class="section-footer">
<a href="<?php echo esc_url(home_url('/properties/')); ?>" class="btn btn-secondary">
View All Properties
<a href="<?php echo esc_url(home_url('/properties/?type=residential')); ?>" class="btn btn-secondary">
View All Residential
<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>
</a>
</div>
<?php else : ?>
<p class="no-properties-message">No properties currently available. Please check back soon.</p>
<p class="no-properties-message">No residential properties currently available. Please check back soon.</p>
<?php endif; ?>
</div>
</section>
<!-- Featured Commercial & Land Properties Section -->
<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>
</header>
<?php if ($featured_commercial->have_posts()) : ?>
<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();
?>
</div>
<div class="section-footer">
<a href="<?php echo esc_url(home_url('/properties/?type=commercial,land')); ?>" 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"/>
</svg>
</a>
</div>
<?php else : ?>
<p class="no-properties-message">No commercial properties currently available. Please check back soon.</p>
<?php endif; ?>
</div>
</section>
+1
View File
@@ -31,6 +31,7 @@
@import '../template-parts/components/testimonial.scss';
@import '../template-parts/components/agent-card.scss';
@import '../template-parts/components/feature-block.scss';
@import '../template-parts/components/service-cards.scss';
// ============================================
// CSS Custom Properties (Design Tokens)
@@ -13,6 +13,7 @@
* - secondary_cta_url (string): Secondary button URL
* - background_image (string): Background image URL
* - size (string): 'large' or 'small' (default: 'large')
* - show_location_search (bool): Show location search dropdown (default: false)
*/
// Prevent direct access
@@ -29,9 +30,21 @@ $secondary_cta_text = isset($args['secondary_cta_text']) ? $args['secondary_cta_
$secondary_cta_url = isset($args['secondary_cta_url']) ? $args['secondary_cta_url'] : '';
$background_image = isset($args['background_image']) ? $args['background_image'] : '';
$size = isset($args['size']) ? $args['size'] : 'large';
$show_location_search = isset($args['show_location_search']) ? $args['show_location_search'] : false;
$size_class = $size === 'small' ? 'hero-section--small' : 'hero-section--large';
$style = $background_image ? 'background-image: url(' . esc_url($background_image) . ');' : '';
// Get locations for dropdown if needed
$locations = array();
if ($show_location_search) {
$locations = get_terms(array(
'taxonomy' => 'property_location',
'hide_empty' => false,
'orderby' => 'name',
'order' => 'ASC',
));
}
?>
<section class="hero-section <?php echo esc_attr($size_class); ?>" <?php echo $style ? 'style="' . esc_attr($style) . '"' : ''; ?>>
@@ -46,6 +59,29 @@ $style = $background_image ? 'background-image: url(' . esc_url($background_imag
<p class="hero-section-subtitle"><?php echo esc_html($subtitle); ?></p>
<?php endif; ?>
<?php if ($show_location_search && !empty($locations) && !is_wp_error($locations)) : ?>
<form class="hero-location-search" action="<?php echo esc_url(home_url('/properties/')); ?>" method="get">
<div class="hero-location-search-inner">
<label for="hero-location-select" class="screen-reader-text">Select a community</label>
<select name="location" id="hero-location-select" class="hero-location-select">
<option value="">Select a Community</option>
<?php foreach ($locations as $location) : ?>
<option value="<?php echo esc_attr($location->slug); ?>">
<?php echo esc_html($location->name); ?>
</option>
<?php endforeach; ?>
</select>
<button type="submit" class="btn btn-primary hero-search-btn">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true">
<circle cx="11" cy="11" r="8"/>
<path d="M21 21l-4.35-4.35"/>
</svg>
<span>Search Properties</span>
</button>
</div>
</form>
<?php endif; ?>
<?php if ($primary_cta_text || $secondary_cta_text) : ?>
<div class="hero-section-actions">
<?php if ($primary_cta_text && $primary_cta_url) : ?>
@@ -98,3 +98,77 @@
gap: 1rem;
justify-content: center;
}
// Location Search Dropdown
.hero-location-search {
margin-bottom: 2rem;
max-width: 500px;
margin-left: auto;
margin-right: auto;
}
.hero-location-search-inner {
display: flex;
gap: 0;
background-color: var(--color-bg-card);
border-radius: 0.5rem;
overflow: hidden;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
@media (max-width: 480px) {
flex-direction: column;
border-radius: 0.5rem;
}
}
.hero-location-select {
flex: 1;
padding: 1rem 1.25rem;
font-size: 1rem;
font-family: var(--font-body);
color: var(--color-text);
background-color: var(--color-bg-card);
border: none;
outline: none;
cursor: pointer;
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23B0B0B0' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 1rem center;
padding-right: 2.5rem;
min-width: 200px;
&:focus {
box-shadow: inset 0 0 0 2px var(--color-accent);
}
option {
background-color: var(--color-bg-card);
color: var(--color-text);
}
@media (max-width: 480px) {
border-radius: 0.5rem 0.5rem 0 0;
text-align: center;
background-position: right 1.5rem center;
}
}
.hero-search-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 1rem 1.5rem;
border-radius: 0;
white-space: nowrap;
svg {
flex-shrink: 0;
}
@media (max-width: 480px) {
width: 100%;
justify-content: center;
border-radius: 0 0 0.5rem 0.5rem;
}
}
@@ -0,0 +1,82 @@
<?php
/**
* Service Cards Component
*
* Displays Buy/Rent/Sell service cards
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
// Service card data
$services = array(
array(
'icon' => 'home',
'title' => 'Find a Home',
'description' => 'Browse our selection of homes for sale in Albert Lea and surrounding Minnesota communities. Your dream home is waiting.',
'button_text' => 'Search Homes',
'button_url' => home_url('/properties/?type=residential'),
),
array(
'icon' => 'key',
'title' => 'Find a Rental',
'description' => 'Looking to rent? Discover available rental properties in your preferred location with flexible lease options.',
'button_text' => 'View Rentals',
'button_url' => home_url('/properties/?status=rental'),
),
array(
'icon' => 'sell',
'title' => 'Sell Your Home',
'description' => 'Ready to sell? Our experienced agents will help you get the best price for your property in today\'s market.',
'button_text' => 'Get Started',
'button_url' => home_url('/contact/?subject=selling'),
),
);
?>
<section class="service-cards-section">
<div class="container">
<header class="service-cards-header">
<h2 class="service-cards-title">How Can We Help?</h2>
<p class="service-cards-subtitle">Whether you're buying, renting, or selling, we're here to guide you every step of the way.</p>
</header>
<div class="service-cards-grid">
<?php foreach ($services as $service) : ?>
<div class="service-card">
<div class="service-card-icon">
<?php if ($service['icon'] === 'home') : ?>
<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>
<?php elseif ($service['icon'] === 'key') : ?>
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<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>
<?php elseif ($service['icon'] === 'sell') : ?>
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true">
<rect x="2" y="7" width="20" height="14" rx="2" ry="2"/>
<path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
<line x1="12" y1="11" x2="12" y2="17"/>
<line x1="9" y1="14" x2="15" y2="14"/>
</svg>
<?php endif; ?>
</div>
<h3 class="service-card-title"><?php echo esc_html($service['title']); ?></h3>
<p class="service-card-description"><?php echo esc_html($service['description']); ?></p>
<a href="<?php echo esc_url($service['button_url']); ?>" class="btn btn-outline service-card-btn">
<?php echo esc_html($service['button_text']); ?>
<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>
</a>
</div>
<?php endforeach; ?>
</div>
</div>
</section>
@@ -0,0 +1,114 @@
/**
* Service Cards Styles
*
* @package HomeProz
*/
.service-cards-section {
padding: 5rem 0;
background-color: var(--color-bg-card);
}
.service-cards-header {
text-align: center;
margin-bottom: 3rem;
}
.service-cards-title {
font-family: var(--font-display);
font-size: 2.5rem;
color: var(--color-text);
margin-bottom: 1rem;
@media (max-width: 768px) {
font-size: 2rem;
}
}
.service-cards-subtitle {
font-size: 1.125rem;
color: var(--color-text-muted);
max-width: 600px;
margin: 0 auto;
}
.service-cards-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 2rem;
@media (max-width: 992px) {
grid-template-columns: repeat(2, 1fr);
}
@media (max-width: 640px) {
grid-template-columns: 1fr;
gap: 1.5rem;
}
}
.service-card {
background-color: var(--color-bg-dark);
border: 1px solid var(--color-border);
border-radius: 0.5rem;
padding: 2rem;
text-align: center;
transition: border-color 0.2s ease, transform 0.2s ease;
&:hover {
border-color: var(--color-accent);
transform: translateY(-4px);
}
}
.service-card-icon {
display: flex;
align-items: center;
justify-content: center;
width: 80px;
height: 80px;
margin: 0 auto 1.5rem;
background-color: rgba(159, 55, 48, 0.1);
border-radius: 50%;
color: var(--color-accent);
}
.service-card-title {
font-family: var(--font-display);
font-size: 1.5rem;
color: var(--color-text);
margin-bottom: 1rem;
}
.service-card-description {
font-size: 1rem;
color: var(--color-text-muted);
margin-bottom: 1.5rem;
line-height: 1.6;
}
.service-card-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
svg {
transition: transform 0.2s ease;
}
&:hover svg {
transform: translateX(4px);
}
}
// Outline button variant (if not already defined)
.btn-outline {
background-color: transparent;
border: 2px solid var(--color-accent);
color: var(--color-accent);
&:hover {
background-color: var(--color-accent);
color: var(--color-text);
}
}
@@ -50,6 +50,11 @@
@media (max-width: 768px) {
padding: 3rem 0;
}
// Alternate background for Commercial section
&--alt {
background-color: var(--color-bg-dark);
}
}
.property-grid--3col {