Step 1.7: Create base page templates (page, single, 404, index, content parts)

This commit is contained in:
Hanson.xyz Dev
2025-11-28 16:12:52 -06:00
parent 43ad31df4c
commit a0ac37294f
14 changed files with 932 additions and 25 deletions
+1 -1
View File
@@ -407,4 +407,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2025-11-28 16:10:45
-- Dump completed on 2025-11-28 16:12:52
+43
View File
@@ -0,0 +1,43 @@
<?php
/**
* The template for displaying 404 pages (not found)
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
get_header();
?>
<main id="primary" class="site-main">
<div class="container">
<section class="error-404">
<header class="error-header">
<h1 class="error-title">404</h1>
<p class="error-subtitle">Page Not Found</p>
</header>
<div class="error-content">
<p>The page you're looking for doesn't exist or has been moved.</p>
<p>Let's get you back on track:</p>
<div class="error-actions">
<a href="<?php echo esc_url(home_url('/')); ?>" class="btn btn-primary">Go Home</a>
<a href="<?php echo esc_url(home_url('/properties/')); ?>" class="btn btn-secondary">View Properties</a>
</div>
</div>
<div class="error-search">
<p>Or try searching:</p>
<?php get_search_form(); ?>
</div>
</section>
</div>
</main>
<?php
get_footer();
File diff suppressed because one or more lines are too long
+33 -23
View File
@@ -2,38 +2,48 @@
/**
* Main template file
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* This is the most generic template file in a WordPress theme.
* Used for blog archive and as a fallback for other templates.
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
get_header();
?>
<main id="primary" class="site-main">
<?php
if (have_posts()) :
while (have_posts()) :
the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php the_title('<h1 class="entry-title">', '</h1>'); ?>
</header>
<div class="container">
<?php if (is_home() && !is_front_page()) : ?>
<header class="archive-header">
<h1 class="archive-title"><?php single_post_title(); ?></h1>
</header>
<?php endif; ?>
<div class="entry-content">
<?php the_content(); ?>
</div>
</article>
<?php
endwhile;
else :
?>
<p><?php esc_html_e('No content found.', 'homeproz'); ?></p>
<?php
endif;
?>
<?php if (have_posts()) : ?>
<div class="posts-grid">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content/content', 'card');
endwhile;
?>
</div>
<?php the_posts_pagination(array(
'prev_text' => '&larr; Previous',
'next_text' => 'Next &rarr;',
'mid_size' => 2,
)); ?>
<?php else : ?>
<p class="no-posts"><?php esc_html_e('No posts found.', 'homeproz'); ?></p>
<?php endif; ?>
</div>
</main>
<?php
+28
View File
@@ -0,0 +1,28 @@
<?php
/**
* The template for displaying all pages
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
get_header();
?>
<main id="primary" class="site-main">
<div class="container">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content/content', 'page');
endwhile;
?>
</div>
</main>
<?php
get_footer();
+39
View File
@@ -0,0 +1,39 @@
<?php
/**
* The template for displaying single posts
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
get_header();
?>
<main id="primary" class="site-main">
<div class="container">
<?php
while (have_posts()) :
the_post();
get_template_part('template-parts/content/content', 'single');
// Post navigation
the_post_navigation(array(
'prev_text' => '<span class="nav-subtitle">&larr; Previous</span><span class="nav-title">%title</span>',
'next_text' => '<span class="nav-subtitle">Next &rarr;</span><span class="nav-title">%title</span>',
));
// Comments
if (comments_open() || get_comments_number()) :
comments_template();
endif;
endwhile;
?>
</div>
</main>
<?php
get_footer();
+4
View File
@@ -10,6 +10,10 @@
// Import component styles
@import '../template-parts/header/site-header.scss';
@import '../template-parts/footer/site-footer.scss';
@import '../template-parts/content/content-page.scss';
@import '../template-parts/content/content-card.scss';
@import '../template-parts/content/content-single.scss';
@import '../template-parts/content/content-404.scss';
// ============================================
// CSS Custom Properties (Design Tokens)
@@ -0,0 +1,89 @@
/**
* 404 Error Page Styles
*
* @package HomeProz
*/
.error-404 {
text-align: center;
padding: 4rem 0;
max-width: 600px;
margin: 0 auto;
}
.error-header {
margin-bottom: 2rem;
}
.error-title {
font-size: 8rem;
line-height: 1;
color: var(--color-accent);
margin-bottom: 0.5rem;
@media (max-width: 640px) {
font-size: 5rem;
}
}
.error-subtitle {
font-size: 1.5rem;
font-weight: 500;
color: var(--color-text);
margin-bottom: 0;
}
.error-content {
margin-bottom: 2rem;
p {
font-size: 1rem;
color: var(--color-text-muted);
}
}
.error-actions {
display: flex;
justify-content: center;
gap: 1rem;
margin-top: 1.5rem;
flex-wrap: wrap;
}
.error-search {
margin-top: 2rem;
padding-top: 2rem;
border-top: 1px solid var(--color-border);
p {
margin-bottom: 1rem;
color: var(--color-text-muted);
}
}
// Search form on 404
.search-form {
display: flex;
max-width: 400px;
margin: 0 auto;
.search-field {
flex-grow: 1;
border-radius: 0.25rem 0 0 0.25rem;
}
.search-submit {
flex-shrink: 0;
padding: 0.75rem 1.25rem;
background-color: var(--color-accent);
color: white;
border: none;
border-radius: 0 0.25rem 0.25rem 0;
font-weight: 600;
cursor: pointer;
&:hover {
background-color: var(--color-accent-hover);
}
}
}
@@ -0,0 +1,45 @@
<?php
/**
* Template part for displaying post cards in archive views
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('post-card card'); ?>>
<?php if (has_post_thumbnail()) : ?>
<a href="<?php the_permalink(); ?>" class="post-card-image">
<?php the_post_thumbnail('property-card', array('loading' => 'lazy')); ?>
</a>
<?php endif; ?>
<div class="post-card-content">
<header class="post-card-header">
<?php if ('post' === get_post_type()) : ?>
<div class="post-card-meta">
<time datetime="<?php echo esc_attr(get_the_date('c')); ?>">
<?php echo esc_html(get_the_date()); ?>
</time>
</div>
<?php endif; ?>
<?php the_title('<h3 class="post-card-title"><a href="' . esc_url(get_permalink()) . '">', '</a></h3>'); ?>
</header>
<div class="post-card-excerpt">
<?php the_excerpt(); ?>
</div>
<a href="<?php the_permalink(); ?>" class="post-card-link">
Read More
<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>
</article>
@@ -0,0 +1,171 @@
/**
* Post Card Styles
*
* @package HomeProz
*/
// Archive Header
.archive-header {
margin-bottom: 2rem;
padding: 2rem 0;
border-bottom: 1px solid var(--color-border);
}
.archive-title {
margin-bottom: 0;
}
// Posts Grid
.posts-grid {
display: grid;
grid-template-columns: 1fr;
gap: 2rem;
padding: 2rem 0;
@media (min-width: 768px) {
grid-template-columns: repeat(2, 1fr);
}
@media (min-width: 1024px) {
grid-template-columns: repeat(3, 1fr);
}
}
// Post Card
.post-card {
display: flex;
flex-direction: column;
}
.post-card-image {
display: block;
aspect-ratio: 16 / 10;
overflow: hidden;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.post-card-content {
display: flex;
flex-direction: column;
flex-grow: 1;
padding: 1.25rem;
}
.post-card-header {
margin-bottom: 0.75rem;
}
.post-card-meta {
margin-bottom: 0.5rem;
time {
font-size: 0.8125rem;
color: var(--color-text-muted);
}
}
.post-card-title {
font-family: var(--font-body);
font-size: 1.125rem;
font-weight: 600;
line-height: 1.4;
margin-bottom: 0;
a {
color: var(--color-text);
text-decoration: none;
&:hover {
color: var(--color-accent-light);
}
}
}
.post-card-excerpt {
flex-grow: 1;
margin-bottom: 1rem;
p {
font-size: 0.9375rem;
color: var(--color-text-muted);
margin-bottom: 0;
line-height: 1.6;
}
}
.post-card-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.875rem;
font-weight: 600;
color: var(--color-accent-light);
text-decoration: none;
&:hover {
color: var(--color-accent-hover);
}
svg {
width: 16px;
height: 16px;
}
}
// Pagination
.pagination,
.nav-links {
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
padding: 2rem 0;
flex-wrap: wrap;
.page-numbers {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 40px;
height: 40px;
padding: 0 0.75rem;
background-color: var(--color-bg-card);
border-radius: 0.25rem;
color: var(--color-text-muted);
text-decoration: none;
font-size: 0.875rem;
font-weight: 500;
&.current {
background-color: var(--color-accent);
color: white;
}
&:hover:not(.current):not(.dots) {
background-color: var(--color-border);
color: var(--color-text);
}
&.dots {
background: none;
cursor: default;
}
}
.prev,
.next {
padding: 0 1rem;
}
}
// No posts message
.no-posts {
text-align: center;
padding: 4rem 0;
color: var(--color-text-muted);
}
@@ -0,0 +1,29 @@
<?php
/**
* Template part for displaying page content
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('page-content'); ?>>
<header class="page-header">
<?php the_title('<h1 class="page-title">', '</h1>'); ?>
</header>
<div class="entry-content">
<?php
the_content();
wp_link_pages(array(
'before' => '<div class="page-links">' . esc_html__('Pages:', 'homeproz'),
'after' => '</div>',
));
?>
</div>
</article>
@@ -0,0 +1,129 @@
/**
* Page Content Styles
*
* @package HomeProz
*/
.page-content {
padding: 2rem 0 4rem;
}
.page-header {
margin-bottom: 2rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--color-border);
}
.page-title {
margin-bottom: 0;
}
.entry-content {
max-width: 800px;
> *:first-child {
margin-top: 0;
}
> *:last-child {
margin-bottom: 0;
}
// Headings within content
h2, h3, h4, h5, h6 {
margin-top: 2rem;
}
// Lists
ul, ol {
margin-bottom: 1rem;
padding-left: 1.5rem;
li {
margin-bottom: 0.5rem;
}
}
// Blockquotes
blockquote {
margin: 1.5rem 0;
padding: 1rem 1.5rem;
border-left: 4px solid var(--color-accent);
background-color: var(--color-bg-card);
p:last-child {
margin-bottom: 0;
}
}
// Tables
table {
width: 100%;
margin-bottom: 1rem;
border-collapse: collapse;
th, td {
padding: 0.75rem;
border: 1px solid var(--color-border);
text-align: left;
}
th {
background-color: var(--color-bg-card);
font-weight: 600;
color: var(--color-text);
}
}
// Images
img {
max-width: 100%;
height: auto;
border-radius: 0.25rem;
}
// Code
code {
padding: 0.125rem 0.375rem;
background-color: var(--color-bg-card);
border-radius: 0.25rem;
font-size: 0.875em;
}
pre {
margin-bottom: 1rem;
padding: 1rem;
background-color: var(--color-bg-card);
border-radius: 0.25rem;
overflow-x: auto;
code {
padding: 0;
background: none;
}
}
}
// Page links (for paginated content)
.page-links {
margin-top: 2rem;
padding-top: 1rem;
border-top: 1px solid var(--color-border);
font-weight: 500;
.page-numbers {
display: inline-block;
padding: 0.25rem 0.5rem;
margin: 0 0.25rem;
background-color: var(--color-bg-card);
border-radius: 0.25rem;
color: var(--color-text-muted);
text-decoration: none;
&.current,
&:hover {
background-color: var(--color-accent);
color: white;
}
}
}
@@ -0,0 +1,72 @@
<?php
/**
* Template part for displaying single post content
*
* @package HomeProz
*/
// Prevent direct access
if (!defined('ABSPATH')) {
exit;
}
?>
<article id="post-<?php the_ID(); ?>" <?php post_class('single-post'); ?>>
<header class="post-header">
<div class="post-meta">
<time datetime="<?php echo esc_attr(get_the_date('c')); ?>">
<?php echo esc_html(get_the_date()); ?>
</time>
<?php
$categories = get_the_category();
if ($categories) :
?>
<span class="meta-separator">|</span>
<span class="post-categories">
<?php
$cat_links = array();
foreach ($categories as $category) {
$cat_links[] = '<a href="' . esc_url(get_category_link($category->term_id)) . '">' . esc_html($category->name) . '</a>';
}
echo implode(', ', $cat_links);
?>
</span>
<?php endif; ?>
</div>
<?php the_title('<h1 class="post-title">', '</h1>'); ?>
</header>
<?php if (has_post_thumbnail()) : ?>
<div class="post-featured-image">
<?php the_post_thumbnail('large'); ?>
</div>
<?php endif; ?>
<div class="entry-content">
<?php
the_content();
wp_link_pages(array(
'before' => '<div class="page-links">' . esc_html__('Pages:', 'homeproz'),
'after' => '</div>',
));
?>
</div>
<footer class="post-footer">
<?php
$tags = get_the_tags();
if ($tags) :
?>
<div class="post-tags">
<span class="tags-label">Tags:</span>
<?php
foreach ($tags as $tag) {
echo '<a href="' . esc_url(get_tag_link($tag->term_id)) . '" class="tag-link">' . esc_html($tag->name) . '</a>';
}
?>
</div>
<?php endif; ?>
</footer>
</article>
@@ -0,0 +1,248 @@
/**
* Single Post Styles
*
* @package HomeProz
*/
.single-post {
padding: 2rem 0 4rem;
max-width: 800px;
}
// Post Header
.post-header {
margin-bottom: 2rem;
}
.post-meta {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 1rem;
font-size: 0.875rem;
color: var(--color-text-muted);
time {
color: var(--color-text-muted);
}
.meta-separator {
color: var(--color-border);
}
.post-categories a {
color: var(--color-accent-light);
text-decoration: none;
&:hover {
color: var(--color-accent-hover);
}
}
}
.post-title {
font-size: 2.5rem;
margin-bottom: 0;
@media (max-width: 768px) {
font-size: 2rem;
}
}
// Featured Image
.post-featured-image {
margin-bottom: 2rem;
border-radius: 0.5rem;
overflow: hidden;
img {
width: 100%;
height: auto;
display: block;
}
}
// Post Footer
.post-footer {
margin-top: 3rem;
padding-top: 1.5rem;
border-top: 1px solid var(--color-border);
}
.post-tags {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5rem;
.tags-label {
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text-muted);
}
.tag-link {
display: inline-block;
padding: 0.25rem 0.75rem;
background-color: var(--color-bg-card);
border-radius: 0.25rem;
font-size: 0.8125rem;
color: var(--color-text-muted);
text-decoration: none;
&:hover {
background-color: var(--color-accent);
color: white;
}
}
}
// Post Navigation
.post-navigation {
margin-top: 3rem;
padding: 1.5rem 0;
border-top: 1px solid var(--color-border);
border-bottom: 1px solid var(--color-border);
.nav-links {
display: grid;
grid-template-columns: 1fr;
gap: 1.5rem;
@media (min-width: 640px) {
grid-template-columns: 1fr 1fr;
}
}
.nav-previous,
.nav-next {
a {
display: block;
text-decoration: none;
}
}
.nav-next {
text-align: right;
}
.nav-subtitle {
display: block;
font-size: 0.8125rem;
color: var(--color-text-muted);
margin-bottom: 0.25rem;
}
.nav-title {
display: block;
font-size: 1rem;
font-weight: 500;
color: var(--color-text);
line-height: 1.4;
}
a:hover {
.nav-title {
color: var(--color-accent-light);
}
}
}
// Comments area
.comments-area {
margin-top: 3rem;
padding-top: 2rem;
border-top: 1px solid var(--color-border);
}
.comments-title {
margin-bottom: 1.5rem;
}
.comment-list {
list-style: none;
margin: 0;
padding: 0;
.comment {
margin-bottom: 1.5rem;
padding-bottom: 1.5rem;
border-bottom: 1px solid var(--color-border);
&:last-child {
border-bottom: none;
}
}
.comment-body {
display: flex;
gap: 1rem;
}
.comment-author {
flex-shrink: 0;
img {
border-radius: 50%;
}
}
.comment-content {
flex-grow: 1;
}
.fn {
font-weight: 600;
color: var(--color-text);
}
.comment-metadata {
margin-bottom: 0.5rem;
font-size: 0.8125rem;
color: var(--color-text-muted);
a {
color: var(--color-text-muted);
text-decoration: none;
&:hover {
color: var(--color-accent-light);
}
}
}
}
// Comment form
.comment-respond {
margin-top: 2rem;
}
.comment-reply-title {
margin-bottom: 1rem;
}
.comment-form {
label {
display: block;
margin-bottom: 0.5rem;
font-size: 0.875rem;
font-weight: 500;
color: var(--color-text);
}
input[type="text"],
input[type="email"],
input[type="url"],
textarea {
margin-bottom: 1rem;
}
.form-submit {
margin-top: 1rem;
input[type="submit"] {
@extend .btn;
@extend .btn-primary;
}
}
}