- Add mobile hamburger toggle button and full-screen nav drawer (≤1024px) - Fix product tab styles: complete tab CSS without relying on WC parent selectors; explicit wc-single-product enqueue on product pages - Fix STOCK field: conditionally hide when get_stock_quantity() returns null instead of showing '— units' - Add page-designs.php template + template_include filter so /designs/ uses themed layout instead of raw WooCommerce output - Align nav/footer terminology: 'Canvas' → 'Wall Decor' in nav fallback; correct broken category URL slugs (mugs→drinkware, canvas→wall-decor, planners→stationery, blog→the-memo); add 'Bulk / HR' to mobile drawer Co-Authored-By: Paperclip <noreply@paperclip.ing>
396 lines
20 KiB
PHP
396 lines
20 KiB
PHP
<?php
|
|
/**
|
|
* RAR Storefront — Theme functions
|
|
* Reply All Regrets™ WooCommerce theme
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
// ─── Theme Setup ────────────────────────────────────────────────────────────
|
|
function rar_setup() {
|
|
add_theme_support('title-tag');
|
|
add_theme_support('post-thumbnails');
|
|
add_theme_support('html5', ['search-form','comment-form','comment-list','gallery','caption','style','script']);
|
|
add_theme_support('woocommerce');
|
|
add_theme_support('wc-product-gallery-zoom');
|
|
add_theme_support('wc-product-gallery-lightbox');
|
|
add_theme_support('wc-product-gallery-slider');
|
|
add_theme_support('custom-logo');
|
|
add_theme_support('automatic-feed-links');
|
|
add_theme_support('align-wide');
|
|
|
|
register_nav_menus([
|
|
'primary' => __('Primary Navigation', 'rar-storefront'),
|
|
'footer' => __('Footer Navigation', 'rar-storefront'),
|
|
]);
|
|
}
|
|
add_action('after_setup_theme', 'rar_setup');
|
|
|
|
// ─── Enqueue Assets ─────────────────────────────────────────────────────────
|
|
function rar_enqueue_assets() {
|
|
// Google Fonts
|
|
wp_enqueue_style(
|
|
'rar-fonts',
|
|
'https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,400;0,9..144,500;0,9..144,600;1,9..144,400;1,9..144,500&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600&display=swap',
|
|
[],
|
|
null
|
|
);
|
|
|
|
// Theme stylesheet
|
|
wp_enqueue_style('rar-style', get_stylesheet_uri(), ['rar-fonts'], '1.0.0');
|
|
|
|
// Theme JS
|
|
wp_enqueue_script('rar-main', get_template_directory_uri() . '/js/rar.js', [], '1.0.0', true);
|
|
|
|
// Pass data to JS
|
|
wp_localize_script('rar-main', 'rarData', [
|
|
'ajaxUrl' => admin_url('admin-ajax.php'),
|
|
'nonce' => wp_create_nonce('rar-nonce'),
|
|
'cartUrl' => wc_get_cart_url(),
|
|
'shopUrl' => get_permalink(wc_get_page_id('shop')),
|
|
]);
|
|
}
|
|
add_action('wp_enqueue_scripts', 'rar_enqueue_assets');
|
|
|
|
// ─── Remove default WC styles we override ───────────────────────────────────
|
|
add_filter('woocommerce_enqueue_styles', function($styles) {
|
|
// Keep WooCommerce core but remove some defaults we fully override
|
|
return $styles;
|
|
});
|
|
|
|
// ─── Widget Areas ────────────────────────────────────────────────────────────
|
|
function rar_register_sidebars() {
|
|
register_sidebar([
|
|
'name' => 'Shop Filter Sidebar',
|
|
'id' => 'shop-filter',
|
|
'before_widget' => '<div class="rar-filter-widget">',
|
|
'after_widget' => '</div>',
|
|
'before_title' => '<h4 class="rar-filter-widget__title">',
|
|
'after_title' => '</h4>',
|
|
]);
|
|
}
|
|
add_action('widgets_init', 'rar_register_sidebars');
|
|
|
|
// ─── WooCommerce: remove default wrappers ───────────────────────────────────
|
|
remove_action('woocommerce_before_main_content', 'woocommerce_output_content_wrapper', 10);
|
|
remove_action('woocommerce_after_main_content', 'woocommerce_output_content_wrapper_end', 10);
|
|
|
|
add_action('woocommerce_before_main_content', function() {
|
|
echo '<div class="rar-wc-wrap">';
|
|
});
|
|
add_action('woocommerce_after_main_content', function() {
|
|
echo '</div>';
|
|
});
|
|
|
|
// ─── Remove WC breadcrumb (we build our own) ────────────────────────────────
|
|
remove_action('woocommerce_before_main_content', 'woocommerce_breadcrumb', 20);
|
|
|
|
// ─── Product loop: 3 columns ────────────────────────────────────────────────
|
|
add_filter('loop_shop_columns', fn() => 3);
|
|
add_filter('loop_shop_per_page', fn() => 12, 20);
|
|
|
|
// ─── Custom product loop template ───────────────────────────────────────────
|
|
add_filter('woocommerce_product_loop_start', function($html) {
|
|
return '<ul class="rar-product-grid products">';
|
|
});
|
|
add_filter('woocommerce_product_loop_end', function($html) {
|
|
return '</ul>';
|
|
});
|
|
|
|
// ─── Helper: announcement bar ───────────────────────────────────────────────
|
|
function rar_announcement_bar() {
|
|
$msg = get_option('rar_announcement', 'FREE DESK-CHAIR DELIVERY ON ORDERS OVER $40 · CIRCULATE TO YOUR TEAM · DOC. REV. 04.26');
|
|
if ($msg) {
|
|
echo '<div class="rar-bar">' . esc_html($msg) . '</div>';
|
|
}
|
|
}
|
|
|
|
// ─── Helper: nav ────────────────────────────────────────────────────────────
|
|
function rar_nav() {
|
|
$cart_count = WC()->cart ? WC()->cart->get_cart_contents_count() : 0;
|
|
$cart_url = wc_get_cart_url();
|
|
$shop_url = get_permalink(wc_get_page_id('shop'));
|
|
?>
|
|
<nav class="rar-nav" id="rar-nav">
|
|
<div class="rar-nav__logo">
|
|
<a href="<?php echo esc_url(home_url('/')); ?>" class="rar-nav__logo-mark">Reply All Regrets™</a>
|
|
<span class="rar-nav__logo-sub">EST. 2024 · INTERNAL USE ONLY</span>
|
|
</div>
|
|
<div class="rar-nav__links">
|
|
<?php
|
|
wp_nav_menu([
|
|
'theme_location' => 'primary',
|
|
'container' => false,
|
|
'items_wrap' => '%3$s',
|
|
'fallback_cb' => function() use ($shop_url) {
|
|
$links = [
|
|
['Shop', $shop_url],
|
|
['Designs', home_url('/designs/')],
|
|
['Mugs', home_url('/product-category/drinkware/')],
|
|
['Wall Decor', home_url('/product-category/wall-decor/')],
|
|
['Planners', home_url('/product-category/stationery/')],
|
|
['Apparel', home_url('/product-category/apparel/')],
|
|
['The Memo', home_url('/the-memo/')],
|
|
['About', home_url('/about/')],
|
|
];
|
|
foreach ($links as [$label, $url]) {
|
|
echo '<a href="' . esc_url($url) . '">' . esc_html($label) . '</a>';
|
|
}
|
|
},
|
|
]);
|
|
?>
|
|
</div>
|
|
<div class="rar-nav__icons">
|
|
<button class="rar-nav__search-btn" id="rar-search-toggle" type="button"
|
|
onclick="rarToggleSearch()" aria-label="Search" aria-expanded="false">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="11" cy="11" r="7"></circle><path d="m20 20-3.5-3.5"></path>
|
|
</svg>
|
|
Search
|
|
</button>
|
|
<a href="<?php echo esc_url(get_permalink(wc_get_page_id('myaccount'))); ?>" aria-label="Account">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<circle cx="12" cy="8" r="4"></circle>
|
|
<path d="M4 21c1.5-4.5 5-7 8-7s6.5 2.5 8 7"></path>
|
|
</svg>
|
|
Account
|
|
</a>
|
|
<a href="<?php echo esc_url($cart_url); ?>" class="rar-nav__cart">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 4h2l2.5 12h11l2-8H6"></path>
|
|
<circle cx="9" cy="20" r="1.5"></circle><circle cx="17" cy="20" r="1.5"></circle>
|
|
</svg>
|
|
Cart (<?php echo esc_html($cart_count); ?>)
|
|
</a>
|
|
<button class="rar-nav__toggle" id="rar-nav-toggle" type="button"
|
|
onclick="rarToggleNav()" aria-label="Open navigation menu" aria-expanded="false" aria-controls="rar-nav-drawer">
|
|
<svg class="icon-open" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 6h18M3 12h18M3 18h18"></path>
|
|
</svg>
|
|
<svg class="icon-close" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M18 6L6 18M6 6l12 12"></path>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- Mobile navigation drawer -->
|
|
<div class="rar-nav__drawer" id="rar-nav-drawer" role="dialog" aria-label="Navigation menu" aria-modal="true">
|
|
<button class="rar-nav__drawer-close" onclick="rarToggleNav()" aria-label="Close navigation">✕</button>
|
|
<?php
|
|
wp_nav_menu([
|
|
'theme_location' => 'primary',
|
|
'container' => false,
|
|
'items_wrap' => '%3$s',
|
|
'fallback_cb' => function() use ($shop_url) {
|
|
$links = [
|
|
['Shop', $shop_url],
|
|
['Designs', home_url('/designs/')],
|
|
['Mugs', home_url('/product-category/drinkware/')],
|
|
['Wall Decor', home_url('/product-category/wall-decor/')],
|
|
['Planners', home_url('/product-category/stationery/')],
|
|
['Apparel', home_url('/product-category/apparel/')],
|
|
['The Memo', home_url('/the-memo/')],
|
|
['About', home_url('/about/')],
|
|
['Bulk / HR', home_url('/bulk/')],
|
|
];
|
|
foreach ($links as [$label, $url]) {
|
|
echo '<a href="' . esc_url($url) . '">' . esc_html($label) . '</a>';
|
|
}
|
|
},
|
|
]);
|
|
?>
|
|
</div>
|
|
<div class="rar-search-overlay" id="rar-search-overlay" hidden>
|
|
<form class="rar-search-form" action="<?php echo esc_url(home_url('/')); ?>" method="get">
|
|
<input type="hidden" name="post_type" value="product" />
|
|
<input class="rar-search-input" type="search" name="s" placeholder="Search products…"
|
|
aria-label="Search products" autocomplete="off" />
|
|
<button type="submit" class="rar-btn rar-btn--stamp">Search</button>
|
|
<button type="button" class="rar-search-close" onclick="rarToggleSearch()" aria-label="Close search">✕</button>
|
|
</form>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
// ─── Helper: footer ─────────────────────────────────────────────────────────
|
|
function rar_footer_content() {
|
|
$shop_url = get_permalink(wc_get_page_id('shop'));
|
|
?>
|
|
<footer class="rar-footer">
|
|
<div class="rar-footer__grid">
|
|
<div>
|
|
<div style="font-family:var(--serif);font-size:28px;margin-bottom:8px;">Reply All Regrets™</div>
|
|
<p style="font-family:var(--mono);font-size:11px;line-height:1.7;color:rgba(245,241,232,0.7);max-width:280px;margin:0;">
|
|
Deliverables for the chronically employed. Filed quarterly,<br>
|
|
shipped from a warehouse in Cleveland.
|
|
</p>
|
|
<div class="rar-footer__newsletter">
|
|
<form class="rar-newsletter-form" onsubmit="return rarNewsletterSubmit(event, this)">
|
|
<input type="email" name="EMAIL" placeholder="your.name@workplace.com"
|
|
aria-label="Email for newsletter" required />
|
|
<button type="submit" class="rar-btn rar-btn--stamp" style="padding:10px 16px;">CC: ME →</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<div class="rar-footer__col">
|
|
<div class="rar-footer__col-title">Departments</div>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url(home_url('/product-category/drinkware/')); ?>">Drinkware</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/product-category/apparel/')); ?>">Apparel</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/product-category/wall-decor/')); ?>">Wall Decor</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/product-category/stationery/')); ?>">Stationery</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/bulk/')); ?>">Bulk / HR</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="rar-footer__col">
|
|
<div class="rar-footer__col-title">Company</div>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url(home_url('/about/')); ?>">About</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/the-memo/')); ?>">The Memo (blog)</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/press/')); ?>">Press</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/careers/')); ?>">Careers</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/wholesale/')); ?>">Wholesale</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="rar-footer__col">
|
|
<div class="rar-footer__col-title">Form 9-A: Help</div>
|
|
<ul>
|
|
<li><a href="<?php echo esc_url(home_url('/shipping/')); ?>">Shipping</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/returns/')); ?>">Returns & Grievances</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/order-status/')); ?>">Order Status</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/contact/')); ?>">Contact (no calls)</a></li>
|
|
<li><a href="<?php echo esc_url(home_url('/faq/')); ?>">FAQ</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="rar-footer__legal">
|
|
<span>© <?php echo date('Y'); ?> RAR HOLDINGS LLC · ALL RIGHTS RESERVED</span>
|
|
<span>
|
|
<a href="<?php echo esc_url(home_url('/terms/')); ?>">TERMS</a> ·
|
|
<a href="<?php echo esc_url(get_privacy_policy_url()); ?>">PRIVACY</a> ·
|
|
<a href="<?php echo esc_url(home_url('/accessibility/')); ?>">ACCESSIBILITY</a>
|
|
</span>
|
|
</div>
|
|
</footer>
|
|
<?php
|
|
}
|
|
|
|
// ─── Helper: breadcrumb ─────────────────────────────────────────────────────
|
|
function rar_breadcrumb() {
|
|
echo '<div class="rar-breadcrumb">';
|
|
if (function_exists('woocommerce_breadcrumb')) {
|
|
woocommerce_breadcrumb(['wrap_before' => '', 'wrap_after' => '', 'before' => '', 'after' => '', 'delimiter' => ' / ']);
|
|
} else {
|
|
echo '<a href="' . esc_url(home_url('/')) . '">Home</a> / ';
|
|
if (is_singular()) {
|
|
echo '<span>' . get_the_title() . '</span>';
|
|
} elseif (is_archive()) {
|
|
echo '<span>' . get_the_archive_title() . '</span>';
|
|
}
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// ─── Helper: section header ──────────────────────────────────────────────────
|
|
function rar_section_head($form, $title, $meta = '') {
|
|
echo '<div class="rar-section-head">';
|
|
echo '<div>';
|
|
echo '<div class="rar-form-tag" style="margin-bottom:10px;">' . esc_html($form) . '</div>';
|
|
echo '<h2>' . esc_html($title) . '</h2>';
|
|
echo '</div>';
|
|
if ($meta) {
|
|
echo '<div class="rar-section-head__meta">' . wp_kses_post($meta) . '</div>';
|
|
}
|
|
echo '</div>';
|
|
}
|
|
|
|
// ─── Add WooCommerce cart fragment support ───────────────────────────────────
|
|
add_filter('woocommerce_add_to_cart_fragments', function($fragments) {
|
|
$cart_count = WC()->cart->get_cart_contents_count();
|
|
$fragments['.rar-nav__cart'] = '<a href="' . esc_url(wc_get_cart_url()) . '" class="rar-nav__cart">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M3 4h2l2.5 12h11l2-8H6"></path>
|
|
<circle cx="9" cy="20" r="1.5"></circle><circle cx="17" cy="20" r="1.5"></circle>
|
|
</svg>
|
|
Cart (' . $cart_count . ')
|
|
</a>';
|
|
return $fragments;
|
|
});
|
|
|
|
// ─── Custom image sizes ──────────────────────────────────────────────────────
|
|
add_image_size('rar-product-card', 600, 600, true);
|
|
add_image_size('rar-blog-thumb', 800, 450, true);
|
|
add_image_size('rar-hero', 900, 1125, true);
|
|
|
|
// ─── Page templates ──────────────────────────────────────────────────────────
|
|
add_filter('theme_page_templates', function($templates) {
|
|
$templates['page-designs.php'] = 'Designs Index';
|
|
$templates['page-design-detail.php'] = 'Design Detail';
|
|
$templates['page-about.php'] = 'About';
|
|
return $templates;
|
|
});
|
|
|
|
// ─── AJAX: add to cart from homepage ────────────────────────────────────────
|
|
add_action('wp_ajax_rar_add_to_cart', 'rar_ajax_add_to_cart');
|
|
add_action('wp_ajax_nopriv_rar_add_to_cart', 'rar_ajax_add_to_cart');
|
|
function rar_ajax_add_to_cart() {
|
|
check_ajax_referer('rar-nonce', 'nonce');
|
|
$product_id = absint($_POST['product_id'] ?? 0);
|
|
$qty = absint($_POST['qty'] ?? 1);
|
|
if ($product_id) {
|
|
WC()->cart->add_to_cart($product_id, $qty);
|
|
wp_send_json_success(['count' => WC()->cart->get_cart_contents_count()]);
|
|
}
|
|
wp_send_json_error();
|
|
}
|
|
|
|
// ─── Ensure WooCommerce single-product tab JS loads on product pages ─────────
|
|
add_action('wp_enqueue_scripts', function() {
|
|
if (is_singular('product')) {
|
|
wp_enqueue_script('wc-single-product');
|
|
}
|
|
}, 20);
|
|
|
|
// ─── Force designs page to use page-designs.php template ─────────────────────
|
|
add_filter('template_include', function($template) {
|
|
if (is_page('designs')) {
|
|
$custom = get_theme_file_path('page-designs.php');
|
|
if (file_exists($custom)) {
|
|
return $custom;
|
|
}
|
|
}
|
|
return $template;
|
|
});
|
|
|
|
// ─── Customizer settings ─────────────────────────────────────────────────────
|
|
add_action('customize_register', function($wp_customize) {
|
|
$wp_customize->add_section('rar_options', [
|
|
'title' => __('Reply All Regrets Settings', 'rar-storefront'),
|
|
'priority' => 30,
|
|
]);
|
|
$wp_customize->add_setting('rar_announcement', [
|
|
'default' => 'FREE DESK-CHAIR DELIVERY ON ORDERS OVER $40 · CIRCULATE TO YOUR TEAM · DOC. REV. 04.26',
|
|
'transport' => 'refresh',
|
|
]);
|
|
$wp_customize->add_control('rar_announcement', [
|
|
'label' => __('Announcement Bar Text', 'rar-storefront'),
|
|
'section' => 'rar_options',
|
|
'type' => 'text',
|
|
]);
|
|
$wp_customize->add_setting('rar_hero_tagline', [
|
|
'default' => 'Office supplies for people who hate the office.',
|
|
'transport' => 'postMessage',
|
|
]);
|
|
$wp_customize->add_control('rar_hero_tagline', [
|
|
'label' => __('Hero Tagline', 'rar-storefront'),
|
|
'section' => 'rar_options',
|
|
'type' => 'textarea',
|
|
]);
|
|
});
|
|
|
|
// ─── WooCommerce: disable Coming Soon mode ───────────────────────────────────
|
|
add_filter('pre_option_woocommerce_coming_soon', function() { return 'no'; }, 99);
|
|
|
|
|