PluginProbe ʕ •ᴥ•ʔ
Author Website Templates – Create Writer, Author & Publisher Websites Easily / 1.1.9
Author Website Templates – Create Writer, Author & Publisher Websites Easily v1.1.9
trunk 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9
author-website-templates / build / blocks / author-pro / book-gallery / render.php
author-website-templates / build / blocks / author-pro / book-gallery Last commit date
block.json 1 month ago index.asset.php 1 month ago index.js 1 month ago render.php 1 month ago style-index-rtl.css 1 month ago style-index.css 1 month ago view.asset.php 1 month ago view.js 1 month ago
render.php
659 lines
1 <?php
2 /**
3 * Render Book Gallery [Author Pro] Block
4 */
5
6 $items_per_page = isset($attributes['itemsPerPage']) ? $attributes['itemsPerPage'] : 12;
7 $book_page_url = isset($attributes['bookPageUrl']) ? $attributes['bookPageUrl'] : '';
8 $show_sidebar = isset($attributes['showSidebar']) ? $attributes['showSidebar'] : true;
9
10 $is_editor = (defined('REST_REQUEST') && REST_REQUEST) || (isset($_REQUEST['context']) && $_REQUEST['context'] === 'edit');
11
12 // Back Link Logic
13 $back_link = !empty($book_page_url) ? esc_url($book_page_url) : get_post_type_archive_link('book');
14
15 // Filter Visibility
16 $show_search = isset($attributes['showSearch']) ? $attributes['showSearch'] : true;
17 $show_genre = isset($attributes['showFilterGenre']) ? $attributes['showFilterGenre'] : true;
18 $show_author = isset($attributes['showFilterAuthor']) ? $attributes['showFilterAuthor'] : true;
19 $show_series = isset($attributes['showFilterSeries']) ? $attributes['showFilterSeries'] : true;
20 $show_format = isset($attributes['showFilterFormat']) ? $attributes['showFilterFormat'] : true;
21 $show_language = isset($attributes['showFilterLanguage']) ? $attributes['showFilterLanguage'] : true;
22 $show_publisher = isset($attributes['showFilterPublisher']) ? $attributes['showFilterPublisher'] : true;
23 $show_isbn = isset($attributes['showFilterISBN']) ? $attributes['showFilterISBN'] : true;
24 $show_price = isset($attributes['showFilterPrice']) ? $attributes['showFilterPrice'] : true;
25 $show_year = isset($attributes['showFilterYear']) ? $attributes['showFilterYear'] : true;
26 $show_age = isset($attributes['showFilterAge']) ? $attributes['showFilterAge'] : true;
27 $show_rating = isset($attributes['showFilterRating']) ? $attributes['showFilterRating'] : true;
28 $show_sorting = isset($attributes['showSorting']) ? $attributes['showSorting'] : true;
29 $pagination_type = isset($attributes['paginationType']) ? $attributes['paginationType'] : 'numbers';
30 $columns = isset($attributes['columns']) ? $attributes['columns'] : 3;
31
32 $block_id = isset($attributes['blockId']) ? $attributes['blockId'] : '';
33 $anchor = isset($attributes['anchor']) ? $attributes['anchor'] : '';
34 $element_id = !empty($anchor) ? $anchor : $block_id;
35 if (empty($element_id)) {
36 $element_id = 'awt-book-gallery-' . uniqid();
37 }
38
39 // Define SVGs
40 $icon_star = '<svg class="w-3 h-3 text-yellow-400" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M341.5 45.1C337.4 37.1 329.1 32 320.1 32C311.1 32 302.8 37.1 298.7 45.1L225.1 189.3L65.2 214.7C56.3 216.1 48.9 222.4 46.1 231C43.3 239.6 45.6 249 51.9 255.4L166.3 369.9L141.1 529.8C139.7 538.7 143.4 547.7 150.7 553C158 558.3 167.6 559.1 175.7 555L320.1 481.6L464.4 555C472.4 559.1 482.1 558.3 489.4 553C496.7 547.7 500.4 538.8 499 529.8L473.7 369.9L588.1 255.4C594.5 249 596.7 239.6 593.9 231C591.1 222.4 583.8 216.1 574.8 214.7L415 189.3L341.5 45.1z"/></svg>';
41 $icon_search = '<svg class="w-4 h-4 text-gray-400 absolute left-4 top-3.5" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M480 272C480 317.9 465.1 360.3 440 394.7L566.6 521.4C579.1 533.9 579.1 554.2 566.6 566.7C554.1 579.2 533.8 579.2 521.3 566.7L394.7 440C360.3 465.1 317.9 480 272 480C157.1 480 64 386.9 64 272C64 157.1 157.1 64 272 64C386.9 64 480 157.1 480 272zM272 416C351.5 416 416 351.5 416 272C416 192.5 351.5 128 272 128C192.5 128 128 192.5 128 272C128 351.5 192.5 416 272 416z"/></svg>';
42 $icon_chevron_up = '<svg class="w-3 h-3 text-gray-400 transition-transform duration-200" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M297.4 169.4C309.9 156.9 330.2 156.9 342.7 169.4L534.7 361.4C547.2 373.9 547.2 394.2 534.7 406.7C522.2 419.2 501.9 419.2 489.4 406.7L320 237.3L150.6 406.6C138.1 419.1 117.8 419.1 105.3 406.6C92.8 394.1 92.8 373.8 105.3 361.3L297.3 169.3z"/></svg>';
43 $icon_arrow_left = '<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l160 160c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L109.2 288 416 288c17.7 0 32-14.3 32-32s-14.3-32-32-32l-306.7 0L214.6 118.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-160 160z"/></svg>';
44 $icon_arrow_right = '<svg class="w-4 h-4" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M471.1 297.4C483.6 309.9 483.6 330.2 471.1 342.7L279.1 534.7C266.6 547.2 246.3 547.2 233.8 534.7C221.3 522.2 221.3 501.9 233.8 489.4L403.2 320L233.9 150.6C221.4 138.1 221.4 117.8 233.9 105.3C246.4 92.8 266.7 92.8 279.2 105.3L471.2 297.3z"/></svg>';
45
46 $icon_pen = '<svg class="w-3 h-3 text-gray-400" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path d="M432.5 82.3L382.4 132.4L507.7 257.7L557.8 207.6C579.7 185.7 579.7 150.3 557.8 128.4L511.7 82.3C489.8 60.4 454.4 60.4 432.5 82.3zM343.3 161.2L342.8 161.3L198.7 204.5C178.8 210.5 163 225.7 156.4 245.5L67.8 509.8C64.9 518.5 65.9 528 70.3 535.8L225.7 380.4C224.6 376.4 224.1 372.3 224.1 368C224.1 341.5 245.6 320 272.1 320C298.6 320 320.1 341.5 320.1 368C320.1 394.5 298.6 416 272.1 416C267.8 416 263.6 415.4 259.7 414.4L104.3 569.7C112.1 574.1 121.5 575.1 130.3 572.2L394.6 483.6C414.3 477 429.6 461.2 435.6 441.3L478.8 297.2L478.9 296.7L343.4 161.2z"/></svg>';
47 $icon_cart = '<svg class="w-3 h-3" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M0 24C0 10.7 10.7 0 24 0H69.5c22 0 41.5 12.8 50.6 32h411c26.3 0 45.5 25 38.6 50.4l-41 152.3c-8.5 31.4-37 53.3-69.5 53.3H170.7l5.4 28.5c2.2 11.3 12.1 19.5 23.6 19.5H488c13.3 0 24 10.7 24 24s-10.7 24-24 24H199.7c-34.6 0-64.3-24.6-70.7-58.5L77.4 54.5c-.7-3.8-4-6.5-7.9-6.5H24C10.7 48 0 37.3 0 24zM128 464a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zm336-48a48 48 0 1 1 0 96 48 48 0 1 1 0-96z"/></svg>';
48 $icon_sliders = '<svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="M0 416c0 17.7 14.3 32 32 32l54.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 448c17.7 0 32-14.3 32-32s-14.3-32-32-32l-246.7 0c-12.3-28.3-40.5-48-73.3-48s-61 19.7-73.3 48L32 384c-17.7 0-32 14.3-32 32zm192 0a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM384 256a32 32 0 1 0 -64 0 32 32 0 1 0 64 0zM512 128c0-17.7-14.3-32-32-32l-54.7 0c-12.3-28.3-40.5-48-73.3-48s-61 19.7-73.3 48L32 96C14.3 96 0 110.3 0 128s14.3 32 32 32l246.7 0c12.3 28.3 40.5 48 73.3 48s61-19.7 73.3-48L480 160c17.7 0 32-14.3 32-32zM160 256a32 32 0 1 0 0-64 32 32 0 1 0 0 64z"/></svg>';
49 $icon_x_mark = '<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 384 512" xmlns="http://www.w3.org/2000/svg"><path d="M342.6 150.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L192 210.7 86.6 105.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L146.7 256 41.4 361.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L192 301.3 297.4 406.6c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L237.3 256 342.6 150.6z"/></svg>';
50
51 // Context Detection
52 $current_tax = '';
53 $current_term_id = '';
54
55 $queried_object = get_queried_object();
56 if ($queried_object instanceof WP_Term) {
57 if ($queried_object->taxonomy === 'book-category') {
58 $current_tax = 'book-category';
59 $current_term_id = $queried_object->term_id;
60 } elseif ($queried_object->taxonomy === 'book-author') {
61 $current_tax = 'book-author';
62 $current_term_id = $queried_object->term_id;
63 } elseif ($queried_object->taxonomy === 'book-series') {
64 $current_tax = 'book-series';
65 $current_term_id = $queried_object->term_id;
66 }
67 }
68
69 // Initial Query for SEO
70 $paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
71 $args = array(
72 'post_type' => 'book',
73 'posts_per_page' => $items_per_page,
74 'post_status' => 'publish',
75 'paged' => $paged,
76 );
77
78 // Inject Context into Initial Query
79 if (!empty($current_tax) && !empty($current_term_id)) {
80 $args['tax_query'] = array(
81 array(
82 'taxonomy' => $current_tax,
83 'field' => 'term_id',
84 'terms' => $current_term_id,
85 )
86 );
87 }
88 $book_query = new WP_Query($args);
89 $total_books = $book_query->found_posts;
90 $start_result = ($paged - 1) * $items_per_page + 1;
91 $end_result = min($paged * $items_per_page, $total_books);
92
93 $wrapper_attributes = get_block_wrapper_attributes([
94 'class' => 'awt-book-gallery bg-white',
95 'id' => $element_id
96 ]);
97
98 // Helper to get Unique Meta Values (for filters)
99 if (!function_exists('awt_get_meta_options')) {
100 function awt_get_meta_options($key) {
101 global $wpdb;
102 $results = $wpdb->get_col($wpdb->prepare("
103 SELECT DISTINCT meta_value FROM $wpdb->postmeta
104 WHERE meta_key = %s AND meta_value != ''
105 ", $key));
106 return $results ? $results : [];
107 }
108 }
109
110
111 // Helper to Render Multi-Select Dropdown
112 if (!function_exists('awt_render_dropdown_filter')) {
113 function awt_render_dropdown_filter($label, $name, $options, $placeholder = 'Search...', $icon_chevron = '') {
114 $key = uniqid();
115 // Normalize options to [['value' =>, 'label' =>, 'count' => (optional)]]
116 $normalized_options = [];
117
118 if (!empty($options)) {
119 // Check if it's an array of objects (Terms) or array of arrays
120 $first = reset($options);
121 if (is_array($first) && isset($first['value']) && isset($first['label'])) {
122 // Already in correct format (e.g. Genre custom array from previous step)
123 $normalized_options = $options;
124 } elseif (is_object($first) && isset($first->term_id)) {
125 // WP Terms Object
126 foreach ($options as $term) {
127 $normalized_options[] = [
128 'value' => $term->term_id,
129 'label' => $term->name,
130 'count' => $term->count
131 ];
132 }
133 } elseif (!is_array($first) && !is_object($first)) {
134 // Simple Key-Value Pair (e.g. Price, Rating, Meta Unique Values)
135 // Note: awt_get_meta_options returns simple array of strings [val1, val2]
136 // But manual arrays are [key => label].
137 // If keys are indices (0,1,2), it's a simple list. If keys are string/meaningful, it's key=>label.
138
139 // Check if associative
140 $is_assoc = array_keys($options) !== range(0, count($options) - 1);
141
142 foreach ($options as $k => $v) {
143 if ($is_assoc) {
144 // Key => Label (Price: '0-10' => 'Under $10')
145 $normalized_options[] = ['value' => $k, 'label' => $v];
146 } else {
147 // Value only (Meta: 'Hardcover', 'Paperback')
148 $normalized_options[] = ['value' => $v, 'label' => $v];
149 }
150 }
151 }
152 }
153 ?>
154 <div class="awt-custom-dropdown relative mb-4 group" id="dropdown-<?php echo esc_attr($key); ?>">
155 <label class="block text-xs font-bold text-primary uppercase tracking-widest mb-2"><?php echo esc_html($label); ?></label>
156
157 <button type="button" class="awt-dropdown-trigger w-full bg-white border border-gray-200 rounded px-3 py-2 text-sm text-left flex justify-between items-center hover:border-accent transition group-focus-within:border-accent">
158 <span class="truncate text-secondary select-label font-medium">Select <?php echo esc_html($label); ?></span>
159 <span class="transform transition-transform duration-200 dropdown-icon origin-center">
160 <?php echo $icon_chevron; ?>
161 </span>
162 </button>
163
164 <div class="awt-dropdown-content hidden absolute top-full left-0 w-full bg-white border border-gray-200 shadow-xl rounded-b-lg z-50 mt-1 max-h-60 overflow-y-auto p-2">
165 <input type="text" class="awt-dropdown-search w-full text-xs border border-gray-200 rounded px-2 py-2 mb-2 focus:outline-none focus:border-accent" placeholder="<?php echo esc_attr($placeholder); ?>">
166
167 <div class="space-y-0.5 awt-dropdown-list">
168 <?php if (empty($normalized_options)): ?>
169 <div class="p-2 text-xs text-gray-400 italic">No options available</div>
170 <?php else: ?>
171 <?php foreach ($normalized_options as $opt) : ?>
172 <label class="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-1.5 rounded group transition w-full">
173 <input type="checkbox" name="<?php echo esc_attr($name); ?>[]" value="<?php echo esc_attr($opt['value']); ?>" data-label="<?php echo esc_attr($opt['label']); ?>" class="rounded border-gray-300 text-accent focus:ring-accent w-4 h-4">
174 <span class="text-xs text-secondary group-hover:text-accent transition font-medium">
175 <?php echo esc_html($opt['label']); ?>
176 <?php if (isset($opt['count']) && $opt['count'] !== ''): ?>
177 <span class="text-gray-400 font-normal ml-1">(<?php echo esc_html($opt['count']); ?>)</span>
178 <?php endif; ?>
179 </span>
180 </label>
181 <?php endforeach; ?>
182 <?php endif; ?>
183 </div>
184 </div>
185 </div>
186 <?php
187 }
188 }
189
190 $formats = awt_get_meta_options('_rsbs_book_format');
191 $languages = awt_get_meta_options('_rsbs_book_language');
192 $years = awt_get_meta_options('_rsbs_book_publish_year');
193 $ages = awt_get_meta_options('_rsbs_book_reading_age');
194 $publishers = awt_get_meta_options('_rsbs_book_publisher_name'); // New
195 ?>
196
197 <section <?php echo $wrapper_attributes; ?>>
198 <!-- Hidden inputs for JS -->
199 <input type="hidden" id="awt-ajax-url" value="<?php echo admin_url('admin-ajax.php'); ?>">
200 <input type="hidden" class="awt-items-per-page" value="<?php echo esc_attr($items_per_page); ?>">
201 <input type="hidden" id="awt-current-tax" value="<?php echo esc_attr($current_tax); ?>">
202 <input type="hidden" id="awt-current-term" value="<?php echo esc_attr($current_term_id); ?>">
203 <input type="hidden" class="awt-pagination-type" value="<?php echo esc_attr($pagination_type); ?>">
204
205 <div class="py-12">
206 <div class="awt-container">
207 <div class="grid grid-cols-12 md:grid-cols-12 gap-8 md:gap-12 items-start">
208
209 <?php if ($show_sidebar) : ?>
210 <!-- Mobile Filter Toggle -->
211 <?php if (!$is_editor) : ?>
212 <div class="block md:hidden w-full mb-6">
213 <button id="awt-mobile-filter-toggle" class="w-full flex items-center justify-center bg-white border border-gray-200 text-primary font-bold py-3 px-4 rounded-lg shadow-sm hover:border-accent hover:text-accent transition">
214 <?php echo $icon_sliders; ?>
215 <?php _e('Filters', 'author-website-templates'); ?>
216 </button>
217 <!-- Backdrop -->
218 <div id="awt-filter-backdrop" class="fixed inset-0 bg-black/50 z-40 hidden transition-opacity duration-300"></div>
219 </div>
220 <?php endif; ?>
221
222 <?php
223 $aside_classes = $is_editor
224 ? 'awt-book-filters w-full md:space-y-0 md:col-span-3 space-y-8 static z-auto bg-transparent translate-x-0 overflow-visible p-0 h-auto shadow-none'
225 : 'awt-book-filters w-full md:space-y-0 md:col-span-3 space-y-8 fixed inset-0 z-50 bg-white transform -translate-x-full transition-transform duration-300 md:static md:z-auto md:bg-transparent md:translate-x-0 overflow-y-auto md:overflow-visible p-6 md:p-0 h-full md:h-auto shadow-2xl md:shadow-none';
226 ?>
227 <aside class="<?php echo esc_attr($aside_classes); ?>">
228
229 <!-- Mobile Header with Close -->
230 <?php if (!$is_editor) : ?>
231 <div class="flex items-center justify-between mb-6 md:hidden">
232 <h2 class="text-xl font-bold text-primary font-serif"><?php _e('Filters', 'author-website-templates'); ?></h2>
233 <button id="awt-mobile-filter-close" class="text-gray-400 hover:text-accent p-2">
234 <?php echo $icon_x_mark; ?>
235 </button>
236 </div>
237 <?php endif; ?>
238
239 <!-- Search -->
240 <?php if($show_search): ?>
241 <div class="bg-white p-6 rounded-xl shadow-sm border border-gray-100">
242 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Search', 'author-website-templates'); ?></h3>
243 <div class="relative">
244 <input type="text" class="awt-filter-search w-full pl-10 pr-4 py-3 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent text-sm transition" placeholder="<?php _e('Title, keyword...', 'author-website-templates'); ?>">
245 <?php echo $icon_search; ?>
246 </div>
247 </div>
248 <?php endif; ?>
249
250 <div class="bg-white p-6 rounded-xl shadow-sm border border-gray-100">
251
252 <!-- Genre Filter -->
253 <?php if($show_genre): ?>
254 <div class="mb-8">
255 <?php
256 if ($current_tax === 'book-category' && !empty($current_term_id)) {
257 // Locked View
258 $current_term = get_term($current_term_id);
259 if ($current_term) {
260 ?>
261 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Genres', 'author-website-templates'); ?></h3>
262 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
263 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
264 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
265 </label>
266 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
267 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
268 </a>
269 <?php
270 }
271 } else {
272 // Dropdown View
273 $genres = get_terms(['taxonomy' => 'book-category', 'hide_empty' => true]);
274 awt_render_dropdown_filter(__('Genres', 'author-website-templates'), 'genre', $genres, 'Search genres...', $icon_chevron_up);
275 }
276 ?>
277 </div>
278 <?php endif; ?>
279
280 <!-- Authors Filter -->
281 <?php if($show_author): ?>
282 <div class="mb-8">
283 <?php
284 if ($current_tax === 'book-author' && !empty($current_term_id)) {
285 $current_term = get_term($current_term_id);
286 if ($current_term) {
287 ?>
288 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Authors', 'author-website-templates'); ?></h3>
289 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
290 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
291 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
292 </label>
293 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
294 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
295 </a>
296 <?php
297 }
298 } else {
299 $authors = get_terms(['taxonomy' => 'book-author', 'hide_empty' => true]);
300 awt_render_dropdown_filter(__('Authors', 'author-website-templates'), 'author', $authors, 'Search authors...', $icon_chevron_up);
301 }
302 ?>
303 </div>
304 <?php endif; ?>
305
306 <!-- Series Filter -->
307 <?php if($show_series): ?>
308 <div class="mb-8">
309 <?php
310 if ($current_tax === 'book-series' && !empty($current_term_id)) {
311 $current_term = get_term($current_term_id);
312 if ($current_term) {
313 ?>
314 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Series', 'author-website-templates'); ?></h3>
315 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
316 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
317 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
318 </label>
319 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
320 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
321 </a>
322 <?php
323 }
324 } else {
325 $series = get_terms(['taxonomy' => 'book-series', 'hide_empty' => true]);
326 awt_render_dropdown_filter(__('Series', 'author-website-templates'), 'series', $series, 'Search series...', $icon_chevron_up);
327 }
328 ?>
329 </div>
330 <?php endif; ?>
331
332 <!-- Format Filter (Meta) -->
333 <?php if($show_format && !empty($formats)): ?>
334 <div class="mb-8">
335 <?php awt_render_dropdown_filter(__('Format', 'author-website-templates'), 'format', $formats, 'Search format...', $icon_chevron_up); ?>
336 </div>
337 <?php endif; ?>
338
339 <!-- Language Filter (Meta) -->
340 <?php if($show_language && !empty($languages)): ?>
341 <div class="mb-8">
342 <?php awt_render_dropdown_filter(__('Language', 'author-website-templates'), 'language', $languages, 'Search language...', $icon_chevron_up); ?>
343 </div>
344 <?php endif; ?>
345
346 <!-- Publisher Filter (Meta) -->
347 <?php if($show_publisher && !empty($publishers)): ?>
348 <div class="mb-8">
349 <?php
350 awt_render_dropdown_filter(__('Publisher', 'author-website-templates'), 'publisher', $publishers, 'Search publishers...', $icon_chevron_up);
351 ?>
352 </div>
353 <?php endif; ?>
354
355 <!-- ISBN Filter (Meta Input) -->
356 <?php if($show_isbn): ?>
357 <div class="mb-8">
358 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4 flex justify-between cursor-pointer awt-accordion-trigger">
359 <?php _e('ISBN', 'author-website-templates'); ?> <?php echo $icon_chevron_up; ?>
360 </h3>
361 <div class="space-y-3 awt-accordion-content">
362 <div class="relative">
363 <input type="text" class="awt-filter-isbn w-full pl-10 pr-4 py-2 bg-paper border border-gray-200 rounded-lg focus:outline-none focus:border-accent text-sm transition" placeholder="<?php _e('ISBN-10 or ISBN-13', 'author-website-templates'); ?>">
364 <?php echo $icon_search; ?>
365 </div>
366 </div>
367 </div>
368 <?php endif; ?>
369
370 <!-- Price Filter (Range Logic) -->
371 <?php if($show_price): ?>
372 <div class="mb-8">
373 <?php
374 $price_ranges = [
375 '0-10' => 'Under $10',
376 '10-20' => '$10 - $20',
377 '20-30' => '$20 - $30',
378 '30-50' => '$30 - $50',
379 '50+' => '$50+'
380 ];
381 awt_render_dropdown_filter(__('Price', 'author-website-templates'), 'price', $price_ranges, 'Search prices...', $icon_chevron_up);
382 ?>
383 </div>
384 <?php endif; ?>
385
386 <!-- Year Filter (Meta) -->
387 <?php if($show_year && !empty($years)): ?>
388 <div class="mb-8">
389 <?php
390 // Sort years desc
391 rsort($years);
392 awt_render_dropdown_filter(__('Publish Year', 'author-website-templates'), 'year', $years, 'Search years...', $icon_chevron_up);
393 ?>
394 </div>
395 <?php endif; ?>
396
397 <!-- Age Filter (Meta) -->
398 <?php if($show_age && !empty($ages)): ?>
399 <div class="mb-8">
400 <?php
401 awt_render_dropdown_filter(__('Reading Age', 'author-website-templates'), 'age', $ages, 'Search reading age...', $icon_chevron_up);
402 ?>
403 </div>
404 <?php endif; ?>
405
406 <!-- Rating Filter (Meta Logic) -->
407 <?php if($show_rating): ?>
408 <div class="mb-8">
409 <?php
410 $rating_options = [
411 '5' => '5 Stars',
412 '4' => '4 Stars & Up',
413 '3' => '3 Stars & Up'
414 ];
415 awt_render_dropdown_filter(__('Rating', 'author-website-templates'), 'rating', $rating_options, 'Search ratings...', $icon_chevron_up);
416 ?>
417 </div>
418 <?php endif; ?>
419
420 <button class="awt-apply-filters w-full py-3 bg-primary text-white text-xs font-bold uppercase rounded hover:bg-slate-800 transition shadow-lg shadow-blue-900/10">
421 <?php _e('Apply Filters', 'author-website-templates'); ?>
422 </button>
423 <button class="awt-reset-filters w-full py-3 mt-2 text-gray-400 text-xs font-bold uppercase hover:text-accent transition text-white">
424 <?php _e('Reset All', 'author-website-templates'); ?>
425 </button>
426
427 </div>
428 </aside>
429 <?php endif; ?>
430
431 <div class="<?php echo $show_sidebar ? 'md:col-span-9' : 'md:col-span-12'; ?>">
432
433 <!-- Top Bar -->
434 <div class="flex flex-col sm:flex-row justify-between items-center mb-8 bg-white p-4 rounded-lg shadow-sm border border-gray-100">
435 <p class="text-sm text-secondary font-medium mb-3 sm:mb-0 awt-files-result-count">
436 Showing <span class="font-bold text-primary"><?php echo $start_result; ?> - <?php echo $end_result; ?></span> of <span class="font-bold text-primary"><?php echo $total_books; ?></span> Results
437 </p>
438 <?php if($show_sorting): ?>
439 <div class="flex items-center gap-3">
440 <span class="text-xs font-bold text-gray-400 uppercase"><?php _e('Sort By:', 'author-website-templates'); ?></span>
441 <select class="awt-sort-books bg-paper border border-gray-200 text-primary text-sm rounded px-3 py-2 focus:outline-none focus:border-accent cursor-pointer transition">
442 <option value="date_desc"><?php _e('Newest Arrivals', 'author-website-templates'); ?></option>
443 <option value="price_asc"><?php _e('Price: Low to High', 'author-website-templates'); ?></option>
444 <option value="price_desc"><?php _e('Price: High to Low', 'author-website-templates'); ?></option>
445 <option value="rating_desc"><?php _e('Top Rated', 'author-website-templates'); ?></option>
446 </select>
447 </div>
448 <?php endif; ?>
449 </div>
450
451 <!-- Book Grid -->
452 <div class="awt-book-grid-container grid gap-8" style="grid-template-columns: repeat(<?php echo intval($columns); ?>, minmax(0, 1fr));">
453 <?php
454 if ($book_query->have_posts()) :
455 while ($book_query->have_posts()) : $book_query->the_post();
456 $book_id = get_the_ID();
457
458 // --- 1. Get Initial Prices from Meta ---
459 $raw_price = get_post_meta($book_id, '_rsbs_book_price', true);
460 $raw_sale_price = get_post_meta($book_id, '_rsbs_book_sale_price', true);
461
462 // Clean data to ensure they are numbers
463 $regular_price = (float) preg_replace('/[^0-9.]/', '', $raw_price);
464 $sale_price = (float) preg_replace('/[^0-9.]/', '', $raw_sale_price);
465
466 // --- 2. Linked Product Override (Your Logic) ---
467 if(function_exists('rswpbs_get_linked_product')){
468 $linked_product = rswpbs_get_linked_product();
469 if ($linked_product) {
470 $regular_price = $linked_product->get_regular_price();
471 $sale_price = $linked_product->get_sale_price();
472 }
473 }
474
475 // --- 3. Calculate Logic ---
476 // Check if there is a valid sale
477 $has_sale = !empty($sale_price) && $sale_price < $regular_price && $sale_price > 0;
478
479 // Determine Price to show
480 $display_price = $has_sale ? $sale_price : $regular_price;
481
482 // Calculate Savings Percentage
483 $savings_pct = 0;
484 if ($has_sale && $regular_price > 0) {
485 $savings_pct = round((($regular_price - $sale_price) / $regular_price) * 100);
486 }
487
488 // Other Data
489 $rating = get_post_meta($book_id, '_rsbs_average_book_rating', true);
490 if (!is_numeric($rating)) $rating = 0;
491
492 $author_terms = get_the_terms($book_id, 'book-author');
493 $author_name = $author_terms ? $author_terms[0]->name : 'Unknown Author';
494 $cat_terms = get_the_terms($book_id, 'book-category');
495 $cat_name = $cat_terms ? $cat_terms[0]->name : '';
496
497 $img_url = get_the_post_thumbnail_url($book_id, 'large');
498 $short_desc = get_post_meta($book_id, '_rswpbs_short_description', true);
499 $permalink = get_permalink();
500 $buy_links = get_post_meta($book_id, 'rswpbs_also_available_website_list', true);
501 $buy_btn_text = get_post_meta($book_id, '_rsbs_buy_btn_text', true);
502 $buy_btn_link = get_post_meta($book_id, '_rsbs_buy_btn_link', true);
503 $format_val = get_post_meta($book_id, '_rsbs_book_format', true);
504 ?>
505 <div class="group bg-white rounded-xl shadow-sm hover:shadow-xl hover:-translate-y-1 transition duration-300 overflow-hidden border border-gray-100 flex flex-col">
506 <div class="relative p-6 bg-[#f1f5f9] flex justify-center items-center h-64 overflow-hidden">
507 <?php if($format_val): ?>
508 <span class="absolute top-4 left-4 bg-accent text-white text-[10px] font-bold px-2 py-1 rounded uppercase z-10"><?php echo esc_html($format_val); ?></span>
509 <?php endif; ?>
510
511 <?php if($img_url): ?>
512 <img src="<?php echo esc_url($img_url); ?>" class="h-48 shadow-lg rounded transform group-hover:scale-105 transition duration-500">
513 <?php else: ?>
514 <div class="h-48 w-32 bg-gray-200 shadow-lg rounded flex items-center justify-center text-gray-400 text-xs">No Image</div>
515 <?php endif; ?>
516 </div>
517
518 <div class="p-5 flex-1 flex flex-col">
519
520 <div class="mb-3 flex justify-between items-start">
521 <span class="text-[10px] font-bold text-accent uppercase tracking-widest px-1 py-0.5 rounded mt-1">
522 <?php echo esc_html($cat_name); ?>
523 </span>
524
525 <div class="flex flex-col items-end">
526 <?php if ($has_sale) : ?>
527 <span class="text-[10px] font-bold text-emerald-600 bg-emerald-50 px-1.5 py-0.5 rounded mb-1">
528 Save <?php echo $savings_pct; ?>%
529 </span>
530 <div class="flex items-center gap-1.5 leading-none">
531 <span class="text-xs text-gray-400 line-through decoration-gray-400">
532 $<?php echo number_format($regular_price, 2); ?>
533 </span>
534 <span class="text-sm font-bold text-primary">
535 $<?php echo number_format($sale_price, 2); ?>
536 </span>
537 </div>
538 <?php else : ?>
539 <span class="text-sm font-bold text-primary mt-1">
540 <?php echo $display_price > 0 ? '$' . number_format($display_price, 2) : 'Free'; ?>
541 </span>
542 <?php endif; ?>
543 </div>
544 </div>
545
546 <h3 class="text-xl font-serif font-bold text-primary mb-1 group-hover:text-accent transition">
547 <a href="<?php echo esc_url($permalink); ?>"><?php the_title(); ?></a>
548 </h3>
549
550 <div class="flex items-center mb-2">
551 <div class="flex text-yellow-400 text-xs gap-0.5">
552 <?php for($i=1; $i<=5; $i++) {
553 echo $i <= $rating ? $icon_star : str_replace('text-yellow-400', 'text-gray-300', $icon_star);
554 } ?>
555 </div>
556 <span class="text-[10px] text-gray-400 font-medium ml-1.5">(<?php echo esc_html($rating); ?>)</span>
557 </div>
558
559 <div class="flex items-center gap-2 mb-3">
560 <?php echo $icon_pen; ?>
561 <span class="text-xs font-bold text-secondary"><?php echo esc_html($author_name); ?></span>
562 </div>
563
564 <p class="text-xs text-secondary mb-4 line-clamp-3 leading-relaxed"><?php echo esc_html(wp_trim_words($short_desc, 20)); ?></p>
565
566 <div class="mt-auto space-y-3">
567 <div class="flex flex-wrap gap-2">
568 <?php
569 echo '<a target="_blank" href="'.esc_url($buy_btn_link).'"
570 class="flex-1 min-w-[110px] flex items-center justify-center gap-1 py-2
571 bg-gray-50 border border-gray-200 rounded text-xs font-bold text-primary
572 hover:bg-white hover:border-[#FF9900] hover:text-[#FF9900] transition">'
573 . esc_html($buy_btn_text) .
574 '</a>';
575
576 if (!empty($buy_links)) {
577 foreach (array_slice($buy_links, 0, 4) as $link) {
578 echo '<a target="_blank" href="'.esc_url($link['book_url']).'"
579 class="flex-1 min-w-[110px] flex items-center justify-center gap-1 py-2
580 bg-gray-50 border border-gray-200 rounded text-xs font-bold text-primary
581 hover:bg-white hover:border-[#FF9900] hover:text-[#FF9900] transition">'
582 . esc_html($link['website_name']) .
583 '</a>';
584 }
585 }
586 ?>
587 </div>
588
589 <div class="flex items-center gap-2 w-full">
590
591 <?php
592 // 1. Shortcode Check & Output
593 if ( shortcode_exists('rswpbs_book_loop_btn') ) {
594 echo do_shortcode( '[rswpbs_book_loop_btn]' );
595 }
596 ?>
597
598 <a href="<?php echo esc_url($permalink); ?>" class="flex-1 block py-2.5 border border-primary text-primary text-center text-xs font-bold uppercase rounded hover:bg-primary hover:text-white transition">
599 <?php _e('View Details', 'author-website-templates'); ?>
600 </a>
601 </div>
602
603 </div>
604 </div>
605 </div>
606 <?php endwhile; wp_reset_postdata(); ?>
607 <?php else: ?>
608 <p class="col-span-3 text-center text-gray-500 py-12"><?php _e('No books found matching your criteria.', 'author-website-templates'); ?></p>
609 <?php endif; ?>
610 </div>
611
612 <!-- Pagination -->
613 <!-- Note: Implementation simplified for View.js update -->
614 <div class="awt-pagination mt-16 flex justify-center gap-2">
615 <?php
616 $total_pages = $book_query->max_num_pages;
617
618 if ($pagination_type === 'load_more') {
619 if ($total_pages > 1) {
620 echo '<div class="text-center w-full">'; // Centering container
621 echo '<button id="awt-load-more-btn" data-page="1" class="px-8 py-3 bg-white border border-gray-200 text-primary font-bold uppercase text-xs rounded shadow-sm hover:border-accent hover:text-accent transition">';
622 _e('Load More Books', 'author-website-templates');
623 echo '</button>';
624 echo '</div>';
625 }
626 } else {
627 // Numbers
628 if ($total_pages > 1) {
629 $current = max(1, get_query_var('paged'));
630
631 // Prev
632 if ($current > 1) {
633 echo '<button data-page="'.($current-1).'" class="awt-page-link w-10 h-10 flex items-center justify-center rounded bg-white border border-gray-200 text-secondary hover:border-accent hover:text-accent transition font-bold text-sm">'.$icon_arrow_left.'</button>';
634 }
635
636 // Pages (Simplified range)
637 for ($i = 1; $i <= $total_pages; $i++) {
638 if ($i == $current) {
639 echo '<button class="w-10 h-10 flex items-center justify-center rounded bg-primary text-white font-bold text-sm">'.$i.'</button>';
640 } else {
641 echo '<button data-page="'.$i.'" class="awt-page-link w-10 h-10 flex items-center justify-center rounded bg-white border border-gray-200 text-secondary hover:border-accent hover:text-accent transition font-bold text-sm">'.$i.'</button>';
642 }
643 }
644
645 // Next
646 if ($current < $total_pages) {
647 echo '<button data-page="'.($current+1).'" class="awt-page-link w-10 h-10 flex items-center justify-center rounded bg-white border border-gray-200 hover:border-accent hover:text-white text-primary hover:bg-primary transition font-bold text-sm">'.$icon_arrow_right.'</button>';
648 }
649 }
650 }
651 ?>
652 </div>
653
654 </div>
655 </div>
656 </div>
657 </div>
658 </section>
659