PluginProbe ʕ •ᴥ•ʔ
Author Website Templates – Create Writer, Author & Publisher Websites Easily / 1.1.5
Author Website Templates – Create Writer, Author & Publisher Websites Easily v1.1.5
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 4 months ago index.asset.php 4 months ago index.js 4 months ago render.php 4 months ago style-index-rtl.css 4 months ago style-index.css 4 months ago view.asset.php 4 months ago view.js 4 months ago
render.php
595 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 $section_title = isset($attributes['sectionTitle']) ? $attributes['sectionTitle'] : 'Browse Collection';
10 $section_desc = isset($attributes['sectionDesc']) ? $attributes['sectionDesc'] : 'Find your next favorite read from our curated selection.';
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
112 // Helper to Render Multi-Select Dropdown
113 if (!function_exists('awt_render_dropdown_filter')) {
114 function awt_render_dropdown_filter($label, $name, $options, $placeholder = 'Search...', $icon_chevron) {
115 $key = uniqid();
116 // Normalize options to [['value' =>, 'label' =>, 'count' => (optional)]]
117 $normalized_options = [];
118
119 if (!empty($options)) {
120 // Check if it's an array of objects (Terms) or array of arrays
121 $first = reset($options);
122 if (is_array($first) && isset($first['value']) && isset($first['label'])) {
123 // Already in correct format (e.g. Genre custom array from previous step)
124 $normalized_options = $options;
125 } elseif (is_object($first) && isset($first->term_id)) {
126 // WP Terms Object
127 foreach ($options as $term) {
128 $normalized_options[] = [
129 'value' => $term->term_id,
130 'label' => $term->name,
131 'count' => $term->count
132 ];
133 }
134 } elseif (!is_array($first) && !is_object($first)) {
135 // Simple Key-Value Pair (e.g. Price, Rating, Meta Unique Values)
136 // Note: awt_get_meta_options returns simple array of strings [val1, val2]
137 // But manual arrays are [key => label].
138 // If keys are indices (0,1,2), it's a simple list. If keys are string/meaningful, it's key=>label.
139
140 // Check if associative
141 $is_assoc = array_keys($options) !== range(0, count($options) - 1);
142
143 foreach ($options as $k => $v) {
144 if ($is_assoc) {
145 // Key => Label (Price: '0-10' => 'Under $10')
146 $normalized_options[] = ['value' => $k, 'label' => $v];
147 } else {
148 // Value only (Meta: 'Hardcover', 'Paperback')
149 $normalized_options[] = ['value' => $v, 'label' => $v];
150 }
151 }
152 }
153 }
154 ?>
155 <div class="awt-custom-dropdown relative mb-4 group" id="dropdown-<?php echo esc_attr($key); ?>">
156 <label class="block text-xs font-bold text-primary uppercase tracking-widest mb-2"><?php echo esc_html($label); ?></label>
157
158 <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">
159 <span class="truncate text-secondary select-label font-medium">Select <?php echo esc_html($label); ?></span>
160 <span class="transform transition-transform duration-200 dropdown-icon origin-center">
161 <?php echo $icon_chevron; ?>
162 </span>
163 </button>
164
165 <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">
166 <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); ?>">
167
168 <div class="space-y-0.5 awt-dropdown-list">
169 <?php if (empty($normalized_options)): ?>
170 <div class="p-2 text-xs text-gray-400 italic">No options available</div>
171 <?php else: ?>
172 <?php foreach ($normalized_options as $opt) : ?>
173 <label class="flex items-center gap-2 cursor-pointer hover:bg-gray-50 p-1.5 rounded group transition w-full">
174 <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">
175 <span class="text-xs text-secondary group-hover:text-accent transition font-medium">
176 <?php echo esc_html($opt['label']); ?>
177 <?php if (isset($opt['count']) && $opt['count'] !== ''): ?>
178 <span class="text-gray-400 font-normal ml-1">(<?php echo esc_html($opt['count']); ?>)</span>
179 <?php endif; ?>
180 </span>
181 </label>
182 <?php endforeach; ?>
183 <?php endif; ?>
184 </div>
185 </div>
186 </div>
187 <?php
188 }
189 }
190
191 $formats = awt_get_meta_options('_rsbs_book_format');
192 $languages = awt_get_meta_options('_rsbs_book_language');
193 $years = awt_get_meta_options('_rsbs_book_publish_year');
194 $ages = awt_get_meta_options('_rsbs_book_reading_age');
195 $publishers = awt_get_meta_options('_rsbs_book_publisher_name'); // New
196 ?>
197
198 <section <?php echo $wrapper_attributes; ?>>
199 <!-- Hidden inputs for JS -->
200 <input type="hidden" id="awt-ajax-url" value="<?php echo admin_url('admin-ajax.php'); ?>">
201 <input type="hidden" class="awt-items-per-page" value="<?php echo esc_attr($items_per_page); ?>">
202 <input type="hidden" id="awt-current-tax" value="<?php echo esc_attr($current_tax); ?>">
203 <input type="hidden" id="awt-current-term" value="<?php echo esc_attr($current_term_id); ?>">
204 <input type="hidden" class="awt-pagination-type" value="<?php echo esc_attr($pagination_type); ?>">
205
206 <div class="py-12 bg-white border-b border-gray-100">
207 <div class="awt-container">
208 <h1 class="text-3xl md:text-4xl font-serif font-bold text-primary mb-3"><?php echo esc_html($section_title); ?></h1>
209 <p class="text-secondary max-w-2xl"><?php echo esc_html($section_desc); ?></p>
210 </div>
211 </div>
212
213 <div class="py-12">
214 <div class="awt-container">
215 <div class="flex flex-col lg:flex-row gap-12">
216
217 <?php if ($show_sidebar) : ?>
218 <!-- Mobile Filter Toggle -->
219 <div class="block lg:hidden w-full mb-6">
220 <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">
221 <?php echo $icon_sliders; ?>
222 <?php _e('Filters', 'author-website-templates'); ?>
223 </button>
224 <!-- Backdrop -->
225 <div id="awt-filter-backdrop" class="fixed inset-0 bg-black/50 z-40 hidden transition-opacity duration-300"></div>
226 </div>
227
228 <aside class="awt-book-filters w-full lg:space-y-0 lg:w-1/4 space-y-8 fixed inset-0 z-50 bg-white transform -translate-x-full transition-transform duration-300 lg:static lg:z-auto lg:bg-transparent lg:translate-x-0 overflow-y-auto lg:overflow-visible p-6 lg:p-0 h-full lg:h-auto shadow-2xl lg:shadow-none">
229
230 <!-- Mobile Header with Close -->
231 <div class="flex items-center justify-between mb-6 lg: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
238 <!-- Search -->
239 <?php if($show_search): ?>
240 <div class="bg-white p-6 rounded-xl shadow-sm border border-gray-100">
241 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Search', 'author-website-templates'); ?></h3>
242 <div class="relative">
243 <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'); ?>">
244 <?php echo $icon_search; ?>
245 </div>
246 </div>
247 <?php endif; ?>
248
249 <div class="bg-white p-6 rounded-xl shadow-sm border border-gray-100">
250
251 <!-- Genre Filter -->
252 <?php if($show_genre): ?>
253 <div class="mb-8">
254 <?php
255 if ($current_tax === 'book-category' && !empty($current_term_id)) {
256 // Locked View
257 $current_term = get_term($current_term_id);
258 if ($current_term) {
259 ?>
260 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Genres', 'author-website-templates'); ?></h3>
261 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
262 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
263 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
264 </label>
265 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
266 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
267 </a>
268 <?php
269 }
270 } else {
271 // Dropdown View
272 $genres = get_terms(['taxonomy' => 'book-category', 'hide_empty' => true]);
273 awt_render_dropdown_filter(__('Genres', 'author-website-templates'), 'genre', $genres, 'Search genres...', $icon_chevron_up);
274 }
275 ?>
276 </div>
277 <?php endif; ?>
278
279 <!-- Authors Filter -->
280 <?php if($show_author): ?>
281 <div class="mb-8">
282 <?php
283 if ($current_tax === 'book-author' && !empty($current_term_id)) {
284 $current_term = get_term($current_term_id);
285 if ($current_term) {
286 ?>
287 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Authors', 'author-website-templates'); ?></h3>
288 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
289 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
290 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
291 </label>
292 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
293 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
294 </a>
295 <?php
296 }
297 } else {
298 $authors = get_terms(['taxonomy' => 'book-author', 'hide_empty' => true]);
299 awt_render_dropdown_filter(__('Authors', 'author-website-templates'), 'author', $authors, 'Search authors...', $icon_chevron_up);
300 }
301 ?>
302 </div>
303 <?php endif; ?>
304
305 <!-- Series Filter -->
306 <?php if($show_series): ?>
307 <div class="mb-8">
308 <?php
309 if ($current_tax === 'book-series' && !empty($current_term_id)) {
310 $current_term = get_term($current_term_id);
311 if ($current_term) {
312 ?>
313 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4"><?php _e('Series', 'author-website-templates'); ?></h3>
314 <label class="flex items-center gap-3 cursor-not-allowed opacity-75">
315 <input type="checkbox" checked disabled class="w-4 h-4 text-accent border-gray-300 rounded">
316 <span class="text-sm text-secondary font-bold"><?php echo esc_html($current_term->name); ?></span>
317 </label>
318 <a href="<?php echo $back_link; ?>" class="text-xs font-bold text-accent hover:underline mt-2 inline-flex items-center gap-1">
319 <?php echo $icon_arrow_left; ?> <?php _e('Back to All Books', 'author-website-templates'); ?>
320 </a>
321 <?php
322 }
323 } else {
324 $series = get_terms(['taxonomy' => 'book-series', 'hide_empty' => true]);
325 awt_render_dropdown_filter(__('Series', 'author-website-templates'), 'series', $series, 'Search series...', $icon_chevron_up);
326 }
327 ?>
328 </div>
329 <?php endif; ?>
330
331 <!-- Format Filter (Meta) -->
332 <?php if($show_format && !empty($formats)): ?>
333 <div class="mb-8">
334 <?php awt_render_dropdown_filter(__('Format', 'author-website-templates'), 'format', $formats, 'Search format...', $icon_chevron_up); ?>
335 </div>
336 <?php endif; ?>
337
338 <!-- Language Filter (Meta) -->
339 <?php if($show_language && !empty($languages)): ?>
340 <div class="mb-8">
341 <?php awt_render_dropdown_filter(__('Language', 'author-website-templates'), 'language', $languages, 'Search language...', $icon_chevron_up); ?>
342 </div>
343 <?php endif; ?>
344
345 <!-- Publisher Filter (Meta) -->
346 <?php if($show_publisher && !empty($publishers)): ?>
347 <div class="mb-8">
348 <?php
349 awt_render_dropdown_filter(__('Publisher', 'author-website-templates'), 'publisher', $publishers, 'Search publishers...', $icon_chevron_up);
350 ?>
351 </div>
352 <?php endif; ?>
353
354 <!-- ISBN Filter (Meta Input) -->
355 <?php if($show_isbn): ?>
356 <div class="mb-8">
357 <h3 class="font-bold text-primary text-sm uppercase tracking-wider mb-4 flex justify-between cursor-pointer awt-accordion-trigger">
358 <?php _e('ISBN', 'author-website-templates'); ?> <?php echo $icon_chevron_up; ?>
359 </h3>
360 <div class="space-y-3 awt-accordion-content">
361 <div class="relative">
362 <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'); ?>">
363 <?php echo $icon_search; ?>
364 </div>
365 </div>
366 </div>
367 <?php endif; ?>
368
369 <!-- Price Filter (Range Logic) -->
370 <?php if($show_price): ?>
371 <div class="mb-8">
372 <?php
373 $price_ranges = [
374 '0-10' => 'Under $10',
375 '10-20' => '$10 - $20',
376 '20-30' => '$20 - $30',
377 '30-50' => '$30 - $50',
378 '50+' => '$50+'
379 ];
380 awt_render_dropdown_filter(__('Price', 'author-website-templates'), 'price', $price_ranges, 'Search prices...', $icon_chevron_up);
381 ?>
382 </div>
383 <?php endif; ?>
384
385 <!-- Year Filter (Meta) -->
386 <?php if($show_year && !empty($years)): ?>
387 <div class="mb-8">
388 <?php
389 // Sort years desc
390 rsort($years);
391 awt_render_dropdown_filter(__('Publish Year', 'author-website-templates'), 'year', $years, 'Search years...', $icon_chevron_up);
392 ?>
393 </div>
394 <?php endif; ?>
395
396 <!-- Age Filter (Meta) -->
397 <?php if($show_age && !empty($ages)): ?>
398 <div class="mb-8">
399 <?php
400 awt_render_dropdown_filter(__('Reading Age', 'author-website-templates'), 'age', $ages, 'Search reading age...', $icon_chevron_up);
401 ?>
402 </div>
403 <?php endif; ?>
404
405 <!-- Rating Filter (Meta Logic) -->
406 <?php if($show_rating): ?>
407 <div class="mb-8">
408 <?php
409 $rating_options = [
410 '5' => '5 Stars',
411 '4' => '4 Stars & Up',
412 '3' => '3 Stars & Up'
413 ];
414 awt_render_dropdown_filter(__('Rating', 'author-website-templates'), 'rating', $rating_options, 'Search ratings...', $icon_chevron_up);
415 ?>
416 </div>
417 <?php endif; ?>
418
419 <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">
420 <?php _e('Apply Filters', 'author-website-templates'); ?>
421 </button>
422 <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">
423 <?php _e('Reset All', 'author-website-templates'); ?>
424 </button>
425
426 </div>
427 </aside>
428 <?php endif; ?>
429
430 <div class="w-full <?php echo $show_sidebar ? 'lg:w-3/4' : 'lg:w-full'; ?>">
431
432 <!-- Top Bar -->
433 <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">
434 <p class="text-sm text-secondary font-medium mb-3 sm:mb-0 awt-files-result-count">
435 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
436 </p>
437 <?php if($show_sorting): ?>
438 <div class="flex items-center gap-3">
439 <span class="text-xs font-bold text-gray-400 uppercase"><?php _e('Sort By:', 'author-website-templates'); ?></span>
440 <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">
441 <option value="date_desc"><?php _e('Newest Arrivals', 'author-website-templates'); ?></option>
442 <option value="price_asc"><?php _e('Price: Low to High', 'author-website-templates'); ?></option>
443 <option value="price_desc"><?php _e('Price: High to Low', 'author-website-templates'); ?></option>
444 <option value="rating_desc"><?php _e('Top Rated', 'author-website-templates'); ?></option>
445 </select>
446 </div>
447 <?php endif; ?>
448 </div>
449
450 <!-- Book Grid -->
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 $price = get_post_meta($book_id, '_rsbs_book_price', true);
458 $sale_price = get_post_meta($book_id, '_rsbs_book_sale_price', true);
459 $display_price = $sale_price ? $sale_price : $price;
460 $rating = get_post_meta($book_id, '_rsbs_average_book_rating', true);
461 if (!is_numeric($rating)) $rating = 0;
462
463 $author_terms = get_the_terms($book_id, 'book-author');
464 $author_name = $author_terms ? $author_terms[0]->name : 'Unknown Author';
465 $cat_terms = get_the_terms($book_id, 'book-category');
466 $cat_name = $cat_terms ? $cat_terms[0]->name : '';
467
468 $img_url = get_the_post_thumbnail_url($book_id, 'large');
469 $short_desc = get_post_meta($book_id, '_rswpbs_short_description', true);
470 $permalink = get_permalink();
471 $buy_links = get_post_meta($book_id, 'rswpbs_also_available_website_list', true);
472 $buy_btn_text = get_post_meta($book_id, '_rsbs_buy_btn_text', true);
473 $buy_btn_link = get_post_meta($book_id, '_rsbs_buy_btn_link', true);
474 // Format Badge
475 $format_val = get_post_meta($book_id, '_rsbs_book_format', true);
476
477 $display_price = str_replace('$', '', $display_price);
478 ?>
479 <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">
480 <div class="relative p-6 bg-[#f1f5f9] flex justify-center items-center h-64 overflow-hidden">
481 <?php if($format_val): ?>
482 <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>
483 <?php endif; ?>
484
485 <?php if($img_url): ?>
486 <img src="<?php echo esc_url($img_url); ?>" class="h-48 shadow-lg rounded transform group-hover:scale-105 transition duration-500">
487 <?php else: ?>
488 <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>
489 <?php endif; ?>
490 </div>
491 <div class="p-5 flex-1 flex flex-col">
492 <div class="mb-2 flex justify-between items-center">
493 <span class="text-[10px] font-bold text-accent uppercase tracking-widest px-1 py-0.5 rounded"><?php echo esc_html($cat_name); ?></span>
494 <span class="text-sm font-bold text-primary"><?php echo $display_price ? '$' . esc_html($display_price) : 'Free'; ?></span>
495 </div>
496 <h3 class="text-xl font-serif font-bold text-primary mb-1 group-hover:text-accent transition">
497 <a href="<?php echo esc_url($permalink); ?>"><?php the_title(); ?></a>
498 </h3>
499 <div class="flex items-center mb-2">
500 <div class="flex text-yellow-400 text-xs gap-0.5">
501 <?php for($i=1; $i<=5; $i++) {
502 echo $i <= $rating ? $icon_star : str_replace('text-yellow-400', 'text-gray-300', $icon_star);
503 } ?>
504 </div>
505 <span class="text-[10px] text-gray-400 font-medium ml-1.5">(<?php echo esc_html($rating); ?>)</span>
506 </div>
507 <div class="flex items-center gap-2 mb-3">
508 <?php echo $icon_pen; ?>
509 <span class="text-xs font-bold text-secondary"><?php echo esc_html($author_name); ?></span>
510 </div>
511 <p class="text-xs text-secondary mb-4 line-clamp-3 leading-relaxed"><?php echo esc_html(wp_trim_words($short_desc, 20)); ?></p>
512
513 <div class="mt-auto space-y-3">
514 <div class="flex flex-wrap gap-2">
515 <?php
516 echo '<a href="'.esc_url($buy_btn_link).'"
517 class="flex-1 min-w-[110px] flex items-center justify-center gap-1 py-2
518 bg-gray-50 border border-gray-200 rounded text-xs font-bold text-primary
519 hover:bg-white hover:border-[#FF9900] hover:text-[#FF9900] transition">'
520 . esc_html($buy_btn_text) .
521 '</a>';
522
523 if (!empty($buy_links)) {
524 foreach (array_slice($buy_links, 0, 4) as $link) {
525 echo '<a href="'.esc_url($link['book_url']).'"
526 class="flex-1 min-w-[110px] flex items-center justify-center gap-1 py-2
527 bg-gray-50 border border-gray-200 rounded text-xs font-bold text-primary
528 hover:bg-white hover:border-[#FF9900] hover:text-[#FF9900] transition">'
529 . esc_html($link['website_name']) .
530 '</a>';
531 }
532 }
533 ?>
534 </div>
535
536 <a href="<?php echo esc_url($permalink); ?>" class="block w-full py-2.5 border border-primary text-primary text-center text-xs font-bold uppercase rounded hover:bg-primary hover:text-white transition">
537 <?php _e('View Details', 'author-website-templates'); ?>
538 </a>
539 </div>
540 </div>
541 </div>
542 <?php endwhile; wp_reset_postdata(); ?>
543 <?php else: ?>
544 <p class="col-span-3 text-center text-gray-500 py-12"><?php _e('No books found matching your criteria.', 'author-website-templates'); ?></p>
545 <?php endif; ?>
546 </div>
547
548 <!-- Pagination -->
549 <!-- Note: Implementation simplified for View.js update -->
550 <div class="awt-pagination mt-16 flex justify-center gap-2">
551 <?php
552 $total_pages = $book_query->max_num_pages;
553
554 if ($pagination_type === 'load_more') {
555 if ($total_pages > 1) {
556 echo '<div class="text-center w-full">'; // Centering container
557 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">';
558 _e('Load More Books', 'author-website-templates');
559 echo '</button>';
560 echo '</div>';
561 }
562 } else {
563 // Numbers
564 if ($total_pages > 1) {
565 $current = max(1, get_query_var('paged'));
566
567 // Prev
568 if ($current > 1) {
569 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>';
570 }
571
572 // Pages (Simplified range)
573 for ($i = 1; $i <= $total_pages; $i++) {
574 if ($i == $current) {
575 echo '<button class="w-10 h-10 flex items-center justify-center rounded bg-primary text-white font-bold text-sm">'.$i.'</button>';
576 } else {
577 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>';
578 }
579 }
580
581 // Next
582 if ($current < $total_pages) {
583 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>';
584 }
585 }
586 }
587 ?>
588 </div>
589
590 </div>
591 </div>
592 </div>
593 </div>
594 </section>
595