FEATURE introducing the like button feature
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
fe22d158c9
commit
bd9df55e64
|
|
@ -6,13 +6,6 @@ add_action('rest_api_init', function () {
|
|||
BUILDING ROUTES
|
||||
-----------------*/
|
||||
|
||||
// ################ Authors ################
|
||||
|
||||
register_rest_route('dynamiques-datas/v1/build', '/revue/authors', array(
|
||||
'methods' => 'GET',
|
||||
'callback' => 'build_revue_authors',
|
||||
'permission_callback' => '__return_true',
|
||||
));
|
||||
|
||||
// ################ FILTER ARTICLES ################
|
||||
register_rest_route('dynamiques-datas/v1/build', '/articles', array(
|
||||
|
|
@ -20,32 +13,22 @@ add_action('rest_api_init', function () {
|
|||
'callback' => 'build_articles',
|
||||
'permission_callback' => '__return_true',
|
||||
));
|
||||
|
||||
|
||||
/* ----------------
|
||||
INTERACTIONS ROUTES
|
||||
-----------------*/
|
||||
|
||||
// ################ LIKE POST ################
|
||||
|
||||
register_rest_route('dynamiques-datas/v1/build', '/articles/like', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => 'like_post',
|
||||
'permission_callback' => '__return_true',
|
||||
));
|
||||
});
|
||||
|
||||
|
||||
// ################ REVUE AUTHORS ################
|
||||
|
||||
function build_revue_authors($request)
|
||||
{
|
||||
$revueID = esc_html($request->get_param('revue-id'));
|
||||
|
||||
ob_start();
|
||||
get_template_part('template-parts/authors/revue-authors-list', null, array(
|
||||
'revueID' => $revueID,
|
||||
));
|
||||
|
||||
$html_template = ob_get_clean();
|
||||
|
||||
$response_data = array(
|
||||
'html_template' => $html_template,
|
||||
'message' => 'Hello World',
|
||||
);
|
||||
$response = new WP_REST_Response($response_data);
|
||||
|
||||
$response->set_status(200);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
// ################ FILTER ARTICLES ################
|
||||
|
||||
|
|
@ -139,3 +122,45 @@ function build_articles($request)
|
|||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
function like_post($request)
|
||||
{
|
||||
|
||||
$post_id = $request->get_param('post_id');
|
||||
write_log($request);
|
||||
write_log($post_id);
|
||||
if (!$post_id) {
|
||||
return new WP_Error('post_id_required', 'Post ID is required', array('status' => 400));
|
||||
}
|
||||
|
||||
|
||||
$post_id = intval($post_id);
|
||||
|
||||
// Vérifier que le post existe
|
||||
if (!get_post($post_id)) {
|
||||
return new WP_Error('post_not_found', 'Post non trouvé', array('status' => 404));
|
||||
}
|
||||
|
||||
|
||||
$likes_count = get_post_likes_count($post_id);
|
||||
|
||||
// Incrémenter le compteur
|
||||
$new_likes = $likes_count + 1;
|
||||
|
||||
// Mettre à jour la meta
|
||||
update_post_meta($post_id, 'likes_count', $new_likes);
|
||||
|
||||
$response_data = array(
|
||||
'success' => true,
|
||||
'post_id' => $post_id,
|
||||
'likes_count' => $new_likes,
|
||||
'message' => 'Like ajouté avec succès'
|
||||
);
|
||||
write_log($response_data);
|
||||
$response = new WP_REST_Response($response_data);
|
||||
|
||||
$response->set_status(200);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
|
|
|||
252
resources/js/singles/like-button.ts
Normal file
252
resources/js/singles/like-button.ts
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
// =============================================================================
|
||||
// TYPE DECLARATIONS
|
||||
// =============================================================================
|
||||
|
||||
declare var Notyf: any;
|
||||
|
||||
// =============================================================================
|
||||
// UTILITY FUNCTIONS
|
||||
// =============================================================================
|
||||
|
||||
function getPostType() {
|
||||
const isSingleArticle = document.querySelector('.page--single-articles');
|
||||
const isSingleRevue = document.querySelector('.page--single-revue');
|
||||
if (isSingleArticle) {
|
||||
return 'article';
|
||||
} else if (isSingleRevue) {
|
||||
return 'revue';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getPostId() {
|
||||
const postType = getPostType();
|
||||
if (!postType) return;
|
||||
const postId =
|
||||
postType === 'article'
|
||||
? document.querySelector('.page--single-articles')?.getAttribute('data-article-id')
|
||||
: document.querySelector('.page--single-revue')?.getAttribute('data-revue-id');
|
||||
return postId;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LIKE TRACKING FUNCTIONS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* Clé localStorage pour stocker les posts likés
|
||||
*/
|
||||
const LIKED_POSTS_KEY = 'dynamiques_liked_posts';
|
||||
|
||||
/**
|
||||
* Récupère la liste des posts likés depuis localStorage
|
||||
*/
|
||||
function getLikedPosts(): string[] {
|
||||
try {
|
||||
const likedPosts = localStorage.getItem(LIKED_POSTS_KEY);
|
||||
return likedPosts ? JSON.parse(likedPosts) : [];
|
||||
} catch (error) {
|
||||
console.error('Erreur lecture localStorage:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un post à la liste des posts likés
|
||||
*/
|
||||
function addLikedPost(postId: string): void {
|
||||
try {
|
||||
const likedPosts = getLikedPosts();
|
||||
if (!likedPosts.includes(postId)) {
|
||||
likedPosts.push(postId);
|
||||
localStorage.setItem(LIKED_POSTS_KEY, JSON.stringify(likedPosts));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur sauvegarde localStorage:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un post a déjà été liké
|
||||
*/
|
||||
function isPostLiked(postId: string): boolean {
|
||||
const likedPosts = getLikedPosts();
|
||||
return likedPosts.includes(postId);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LIKE API FUNCTIONS
|
||||
// =============================================================================
|
||||
|
||||
async function likePost(postId: string): Promise<boolean> {
|
||||
// Vérifier si le post a déjà été liké
|
||||
if (isPostLiked(postId)) {
|
||||
console.log(`Post ${postId} déjà liké !`);
|
||||
showAlreadyLikedMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/wp-json/dynamiques-datas/v1/build/articles/like`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
post_id: postId,
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
console.log(`Post ${postId} liké ! Nouveau total: ${data.likes_count} likes`);
|
||||
|
||||
// Sauvegarder le like dans localStorage
|
||||
addLikedPost(postId);
|
||||
|
||||
// Mettre à jour l'interface utilisateur
|
||||
updateLikeDisplay(data.likes_count);
|
||||
updateLikeButtonState();
|
||||
|
||||
// Afficher message de succès
|
||||
showLikeSuccessMessage(data.likes_count);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
console.error('Erreur API:', data);
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors du like:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UI UPDATE FUNCTIONS
|
||||
// =============================================================================
|
||||
|
||||
function updateLikeDisplay(likesCount: number) {
|
||||
// Mettre à jour l'affichage du compteur de likes dans l'interface
|
||||
const likeCountElement = document.querySelector('.socials-buttons .likes-count');
|
||||
const likeButton = document.querySelector('.socials-buttons__button--like');
|
||||
|
||||
if (likeCountElement && likeButton) {
|
||||
likeButton.setAttribute('data-likes-count', `${likesCount}`);
|
||||
likeButton.classList.add('is-disabled');
|
||||
likeCountElement.textContent = `${likesCount}`;
|
||||
}
|
||||
}
|
||||
|
||||
function updateLikeButtonState() {
|
||||
const postId = getPostId();
|
||||
const likeButton = document.querySelector('.socials-buttons__button--like');
|
||||
if (!postId || !likeButton) return;
|
||||
|
||||
const hasAlreadyLiked = isPostLiked(postId);
|
||||
if (hasAlreadyLiked) {
|
||||
const actionText = likeButton.querySelector('.button-action-text');
|
||||
if (actionText) {
|
||||
actionText.textContent = 'Déjà liké';
|
||||
}
|
||||
likeButton.setAttribute('title', 'Déjà liké !');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasAlreadyLiked) {
|
||||
likeButton.classList.remove('is-disabled');
|
||||
}
|
||||
}
|
||||
|
||||
function updateLikesCountIndicator() {
|
||||
const likesCountIndicator = likeButton.querySelector('.likes-count');
|
||||
const likesCount = likeButton.getAttribute('data-likes-count');
|
||||
|
||||
if (likesCount && likesCountIndicator) {
|
||||
likesCountIndicator.textContent = `${parseInt(likesCount) + 1}`;
|
||||
}
|
||||
}
|
||||
|
||||
function showAlreadyLikedMessage() {
|
||||
const notyf = new Notyf({
|
||||
duration: 3000,
|
||||
ripple: false,
|
||||
dismissible: true,
|
||||
types: [
|
||||
{
|
||||
type: 'error',
|
||||
background: '#ff6b6b',
|
||||
icon: {
|
||||
className: 'notyf__icon--error',
|
||||
tagName: 'i',
|
||||
// Pas de text personnalisé pour garder l'icône d'erreur par défaut
|
||||
},
|
||||
},
|
||||
],
|
||||
position: {
|
||||
x: 'right',
|
||||
y: 'top',
|
||||
},
|
||||
});
|
||||
|
||||
notyf.error(' Vous avez déjà liké ce post ! ❤️');
|
||||
}
|
||||
|
||||
function showLikeSuccessMessage(likesCount: number) {
|
||||
const notyf = new Notyf({
|
||||
duration: 2000,
|
||||
ripple: false,
|
||||
dismissible: true,
|
||||
types: [
|
||||
{
|
||||
type: 'success',
|
||||
background: '#10B981',
|
||||
icon: {
|
||||
className: 'notyf__icon--success',
|
||||
tagName: 'i',
|
||||
text: '❤️',
|
||||
},
|
||||
},
|
||||
],
|
||||
position: {
|
||||
x: 'right',
|
||||
y: 'top',
|
||||
},
|
||||
});
|
||||
|
||||
notyf.success(
|
||||
`Merci pour votre like ! <br>Total: ${likesCount} like${likesCount > 1 ? 's' : ''}`
|
||||
);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MAIN INITIALIZATION FUNCTION
|
||||
// =============================================================================
|
||||
|
||||
export default function handleLikeButton(): void {
|
||||
const likeButton: HTMLElement | null = document.querySelector(
|
||||
'.socials-buttons .socials-buttons__button--like'
|
||||
);
|
||||
const postType = getPostType();
|
||||
const postId = getPostId();
|
||||
if (!postType || !postId || !likeButton) return;
|
||||
|
||||
updateLikeButtonState();
|
||||
|
||||
// Ajouter l'événement click
|
||||
likeButton.addEventListener('click', async (e) => {
|
||||
e.preventDefault(); // Empêcher comportement par défaut
|
||||
|
||||
const hasAlreadyLiked = isPostLiked(postId);
|
||||
if (hasAlreadyLiked) return showAlreadyLikedMessage();
|
||||
// Désactiver temporairement le bouton pour éviter les clics multiples
|
||||
likeButton.style.pointerEvents = 'none';
|
||||
|
||||
const success = await likePost(postId);
|
||||
|
||||
// Réactiver le bouton
|
||||
setTimeout(() => {
|
||||
likeButton.style.pointerEvents = 'auto';
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import handleIndexPanel from './index-panel';
|
||||
import handleFootnoteFormat from './footnote-format';
|
||||
import handleCiteButton from './cite-button';
|
||||
import handleLikeButton from './like-button.ts';
|
||||
import { handleArticleToolbar } from './article-toolbar.ts';
|
||||
import { handleRevueToolbar } from './revue-toolbar.ts';
|
||||
|
||||
|
|
@ -12,6 +13,7 @@ export default function singles(): void {
|
|||
handleIndexPanel();
|
||||
handleFootnoteFormat();
|
||||
handleCiteButton();
|
||||
handleLikeButton();
|
||||
handleArticleToolbar();
|
||||
handleRevueToolbar();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user