FEATURE Implkementing innersearch revues and refgactoring search results
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Nonimart 2025-10-16 16:19:22 +02:00
parent bc6f8ff7eb
commit d5f86028c1
13 changed files with 291 additions and 94 deletions

View File

@ -14,6 +14,13 @@ add_action('rest_api_init', function () {
'permission_callback' => '__return_true', 'permission_callback' => '__return_true',
)); ));
// ################ FILTER REVUES ################
register_rest_route('dynamiques-datas/v1/build', '/revues', array(
'methods' => 'GET',
'callback' => 'build_revues',
'permission_callback' => '__return_true',
));
/* ---------------- /* ----------------
INTERACTIONS ROUTES INTERACTIONS ROUTES
@ -124,6 +131,88 @@ function build_articles($request)
} }
// ################ FILTER REVUES ################
function build_revues($request)
{
$search = esc_html($request->get_param('search'));
$current_revue_id = intval($request->get_param('current_revue_id'));
// Récupérer les articles liés à la revue courante
$issue_related_articles = get_field('articles', $current_revue_id);
if (!$issue_related_articles) {
$response_data = array(
'html_template' => '<p>Aucun article trouvé.</p>',
'post_count' => 0,
'query_args' => array(),
);
return new WP_REST_Response($response_data, 200);
}
// Filtrer les articles selon la recherche
$filtered_articles = array();
if (!empty($search)) {
foreach ($issue_related_articles as $article) {
// Recherche dans le titre et le contenu
$title = get_the_title($article->ID);
$content = get_post_field('post_content', $article->ID);
if (stripos($title, $search) !== false || stripos($content, $search) !== false) {
$filtered_articles[] = $article;
}
}
} else {
$filtered_articles = $issue_related_articles;
}
$post_count = count($filtered_articles);
ob_start();
?>
<div class="search-results">
<h2 class="search-results__title">Recherche : <?php echo $search; ?>”</h2>
<h2 class="post-count">
<span class="post-count__count">
<?php echo $post_count; ?>
</span>
<span class="post-count__text">
résultats
</span>
</h2>
<div class="search-results__content">
<?php
if (!empty($filtered_articles)) :
foreach ($filtered_articles as $article) :
get_template_part('template-parts/search/search-results-card', null, array(
'post_type' => get_post_type($article->ID),
'post_id' => $article->ID,
'search' => $search,
'isInnerSearch' => true,
));
endforeach;
else :
echo '<p>Aucun article trouvé.</p>';
endif;
?>
</div>
</div>
<?php
$html_template = ob_get_clean();
$response_data = array(
'html_template' => $html_template,
'post_count' => $post_count,
'query_args' => array('search' => $search, 'revue_id' => $current_revue_id), // Pour debug
);
$response = new WP_REST_Response($response_data);
$response->set_status(200);
return $response;
}
function like_post($request) function like_post($request)
{ {

View File

@ -35,6 +35,7 @@
@import './components/article-informations.css'; @import './components/article-informations.css';
@import './components/search-module.css'; @import './components/search-module.css';
@import './components/post-count.css'; @import './components/post-count.css';
@import './components/search-results-card.css';
/* ########### PAGES ############ */ /* ########### PAGES ############ */
@import './pages/singles.css'; @import './pages/singles.css';

View File

@ -67,7 +67,7 @@
@apply text-white; @apply text-white;
} }
input::placeholder { input::placeholder {
@apply text-white; @apply !text-white;
} }
&__wrapper-container { &__wrapper-container {
@apply max-w-screen-xl mx-auto; @apply max-w-screen-xl mx-auto;
@ -82,9 +82,10 @@
@apply mt-2 mb-8 bg-neutral-500 border-none opacity-50 w-full; @apply mt-2 mb-8 bg-neutral-500 border-none opacity-50 w-full;
height: 1px; height: 1px;
} }
&__input { &__input {
box-sizing: border-box; box-sizing: border-box;
@apply block max-w-full w-full flex-grow !py-4 !border-white px-4 focus-visible:ring-primary focus-visible:ring-2; @apply block max-w-full w-full flex-grow !py-4 !border-white px-4 !pl-12 focus-visible:ring-primary focus-visible:ring-2;
@apply border rounded-none; @apply border rounded-none;
outline: none !important; outline: none !important;
/* border-right: none; /* border-right: none;
@ -105,7 +106,12 @@
} }
} }
&__searchbar-group { &__searchbar-group {
@apply w-full flex flex-col md:flex-row gap-y-4; @apply w-full flex flex-col md:flex-row gap-y-4 relative;
&:before {
@apply content-[''] absolute inset-0 bg-contain bg-center bg-no-repeat w-6 h-6 left-4 top-1/2 -translate-y-1/2;
background-image: url('../resources/img/icons/carhop-rechercher.svg');
filter: invert(1);
}
} }
&__suggestions { &__suggestions {
@apply pt-4; @apply pt-4;

View File

@ -0,0 +1,39 @@
.search-results-card {
@apply bg-white p-8 border border-primary;
&__title {
@apply !text-lg !font-normal !mb-2;
font-family: 'Nunito Sans', sans-serif !important;
line-height: 1.2;
}
&--inner-search {
@apply bg-transparent border-none px-0;
}
.content-meta {
}
&__type {
@apply inline-block mb-3 px-3 py-1 font-semibold;
@apply text-primary;
}
h2 {
@apply mb-4;
a {
@apply text-primary hover:underline;
}
}
&__link {
@apply inline-block mt-4 text-primary font-semibold;
@apply hover:underline;
}
&__parution-date {
@apply block text-lg font-normal text-primary !mb-4;
}
.search-highlight {
@apply text-primary bg-carhop-green-50 font-bold;
}
}

View File

@ -33,44 +33,6 @@
@apply mb-4; @apply mb-4;
} }
.search-results-card {
@apply bg-white p-8 border border-primary;
@apply transition-shadow hover:shadow-lg;
&__title {
@apply text-xl !mb-2;
line-height: 1.2;
}
.content-meta {
}
&__type {
@apply inline-block mb-3 px-3 py-1 font-semibold;
@apply text-primary;
}
h2 {
@apply mb-4;
a {
@apply text-primary hover:underline;
}
}
&__link {
@apply inline-block mt-4 text-primary font-semibold;
@apply hover:underline;
}
&__parution-date {
@apply block text-lg font-normal text-primary !mb-4;
}
.search-highlight {
@apply text-primary bg-carhop-green-50 font-bold;
}
}
.search-results-pagination { .search-results-pagination {
@apply mt-12 mb-8; @apply mt-12 mb-8;

View File

@ -0,0 +1,13 @@
.page--single-revue {
.search-results__title {
@apply mb-12;
}
.search-results-card {
@apply p-0 my-3;
}
.post-count {
@apply mb-12;
}
}

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="rechercher" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 25.71 26.71">
<defs>
<style>
.cls-1, .cls-2 {
fill: none;
stroke: #000;
stroke-width: 2px;
}
.cls-2 {
stroke-miterlimit: 10;
}
</style>
</defs>
<path class="cls-1" d="M18.84,19.83l6.16,6.17"/>
<ellipse class="cls-2" cx="11.52" cy="11.96" rx="10.52" ry="10.96"/>
</svg>

After

Width:  |  Height:  |  Size: 449 B

View File

@ -0,0 +1,43 @@
export default function handleSearchRevue() {
const searchRevue = document.querySelector(
'.page--single-revue .sidebar .search-field input'
) as HTMLInputElement;
const contentArea = document.querySelector('.page--single-revue .content-area') as HTMLElement;
const currentRevueId = document
.querySelector('.page--single-revue')
?.getAttribute('data-revue-id') as string;
if (!searchRevue || !contentArea) return;
// Sauvegarder le contenu original
const originalContent = contentArea.innerHTML;
searchRevue.addEventListener('input', async () => {
const searchValue = searchRevue.value.trim();
// Si la recherche est vide, restaurer le contenu original
if (searchValue === '') {
contentArea.innerHTML = originalContent;
return;
}
try {
const response = await fetch(
`/wp-json/dynamiques-datas/v1/build/revues?search=${encodeURIComponent(
searchValue
)}&current_revue_id=${currentRevueId}`
);
const data = await response.json();
// Afficher les résultats dans content-area
contentArea.innerHTML = data.html_template;
} catch (error) {
console.error('Erreur lors de la récupération des revues:', error);
contentArea.innerHTML = `
<div class="search-error">
<p>Une erreur est survenue lors de la recherche. Veuillez réessayer.</p>
</div>
`;
}
});
}

View File

@ -7,7 +7,7 @@ import handleArticleReader from './reader.ts';
import { handleArticleToolbar } from './article-toolbar.ts'; import { handleArticleToolbar } from './article-toolbar.ts';
import { handleRevueToolbar } from './revue-toolbar.ts'; import { handleRevueToolbar } from './revue-toolbar.ts';
import handleSearchRevue from './search-revue.ts';
export default function singles(): void { export default function singles(): void {
const isSingleRevue: HTMLElement | null = document.querySelector('.page--single-revue'); const isSingleRevue: HTMLElement | null = document.querySelector('.page--single-revue');
const isSingleArticle: HTMLElement | null = document.querySelector('.page--single-articles'); const isSingleArticle: HTMLElement | null = document.querySelector('.page--single-articles');
@ -21,4 +21,5 @@ export default function singles(): void {
handleRevueToolbar(); handleRevueToolbar();
handleShareButton(); handleShareButton();
handleArticleReader(); handleArticleReader();
handleSearchRevue();
} }

View File

@ -22,54 +22,11 @@
</div> </div>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?> <?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="search-results-card"> <?php get_template_part('template-parts/search/search-results-card', null, array(
<?php 'post_type' => get_post_type(),
$post_type = get_post_type(); 'post_id' => get_the_ID(),
$post_type_object = get_post_type_object($post_type); 'search' => get_search_query(),
$post_type_label = $post_type_object->labels->singular_name; )); ?>
?>
<div class="content-meta">
<span class="content-meta__type content-meta__type--<?php echo $post_type; ?>"><?php echo $post_type_label; ?></span>
</div>
<!-- <span class="search-results-card__type"><?php echo esc_html($post_type_label); ?></span> -->
<h2 class="search-results-card__title">
<a href="<?php the_permalink(); ?>">
<?php
$title = get_the_title();
$search_query = get_search_query();
if (!empty($search_query)) {
$search_terms = explode(' ', $search_query);
foreach ($search_terms as $term) {
if (strlen(trim($term)) > 2) {
$term_escaped = preg_quote(trim($term), '/');
$title = preg_replace(
'/(' . $term_escaped . ')/i',
'<mark class="search-highlight">$1</mark>',
$title
);
}
}
}
echo $title;
?>
</a>
</h2>
<date class="search-results-card__parution-date">
<?php echo get_the_date('F Y'); ?>
</date>
<div class="search-results-page__search-snippet">
<?php echo get_search_snippet(get_the_ID(), get_search_query()); ?>
</div>
<?php get_template_part('template-parts/components/cta--go', null, array(
'url' => get_the_permalink(),
'label' => 'Lire la suite',
'target' => '_self',
)); ?>
</div>
<?php endwhile; ?> <?php endwhile; ?>
<!-- Pagination --> <!-- Pagination -->

View File

@ -41,7 +41,6 @@ $articles = get_field('articles', $current_issue->ID);
</ul> </ul>
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>
<div class="content-area"> <div class="content-area">
@ -75,12 +74,9 @@ $articles = get_field('articles', $current_issue->ID);
'revueID' => get_the_ID() 'revueID' => get_the_ID()
)); ?> )); ?>
<?php get_template_part('template-parts/revues/table-matiere-revue', null, array( <?php get_template_part('template-parts/revues/table-matiere-revue', null, array(
'revueID' => get_the_ID() 'revueID' => get_the_ID()
)); ?> )); ?>
</div> </div>
</div> </div>

View File

@ -0,0 +1,15 @@
<?php
if ($articles->have_posts()) :
while ($articles->have_posts()) : $articles->the_post();
get_template_part('template-parts/articles/card-article', null, array(
'date' => get_the_date(),
'image' => get_the_post_thumbnail_url(),
'link' => get_the_permalink(),
'ID' => get_the_ID(),
'showAuthors' => true,
));
endwhile;
else :
echo '<p>Aucun article trouvé.</p>';
endif;

View File

@ -0,0 +1,57 @@
<?php
// Récupérer les paramètres
$post_id = $args['post_id'] ?? get_the_ID();
$post_type = $args['post_type'] ?? get_post_type($post_id);
$search = $args['search'] ?? get_search_query();
$isInnerSearch = $args['isInnerSearch'] ?? false;
// Récupérer les informations du post
$post_type_object = get_post_type_object($post_type);
$post_type_label = $post_type_object->labels->singular_name;
$title = get_the_title($post_id);
$permalink = get_the_permalink($post_id);
$date = get_the_date('F Y', $post_id);
// Mise en évidence des termes recherchés dans le titre
if (!empty($search)) {
$search_terms = explode(' ', $search);
foreach ($search_terms as $term) {
if (strlen(trim($term)) > 2) {
$term_escaped = preg_quote(trim($term), '/');
$title = preg_replace(
'/(' . $term_escaped . ')/i',
'<mark class="search-highlight">$1</mark>',
$title
);
}
}
}
?>
<div class="search-results-card <?php echo $isInnerSearch ? 'search-results-card--inner-search' : ''; ?>">
<?php if (!$isInnerSearch) : ?>
<div class="content-meta">
<span class="content-meta__type content-meta__type--<?php echo $post_type; ?>"><?php echo $post_type_label; ?></span>
</div>
<?php endif; ?>
<h2 class="search-results-card__title">
<a href="<?php echo $permalink; ?>">
<?php echo $title; ?>
</a>
</h2>
<date class="search-results-card__parution-date">
<?php echo $date; ?>
</date>
<div class="search-results-page__search-snippet">
<?php echo get_search_snippet($post_id, $search); ?>
</div>
<?php get_template_part('template-parts/components/cta--go', null, array(
'url' => $permalink,
'label' => 'Lire la suite',
'target' => '_self',
)); ?>
</div>