Skip to content
This repository has been archived by the owner on Jul 18, 2024. It is now read-only.

Commit

Permalink
Code Refactoring: Reviews (#234)
Browse files Browse the repository at this point in the history
## QA Steps

-  [ ] `pnpm i`
-  [ ] `pnpm dev`
-  [ ] visit any product page with reviews, and test it

## Note

Leave empty when you have nothing to say
  • Loading branch information
MohamedJamoun authored Mar 13, 2023
1 parent e414e4c commit 7f303f4
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 80 deletions.
173 changes: 107 additions & 66 deletions assets/reviews.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,130 @@
(async () => {
/**
* Converts date from yyyy-mm-dd to dd.mm.yyyy
*/
function convertDate() {
const createdAtDate = document.querySelectorAll('.created-at-date');

createdAtDate.forEach(date => {
const originalDateString = date.textContent;
const originalDate = new Date(originalDateString);
const day = originalDate.getDate().toString().padStart(2, '0');
const month = (originalDate.getMonth() + 1).toString().padStart(2, '0');
const year = originalDate.getFullYear().toString();
const formattedDate = `${day}.${month}.${year}`;
date.textContent = formattedDate;
});
}

/**
* Creates a review template
*
* @param {Object} review - Review object.
* @returns {String} - Review template.
*/
function reviewTemplate(review) {
return `
<div class='header'>
<div class="profil">
<img loading='lazy' class='image' src='${review.images_urls[0] || defaultAvatar}' />
<div class='info'>
<span class='name'>${review.first_name || ''} ${review.last_name || ''}</span>
<span class='created-at-date'>${review.created_at}</span>
</div>
</div>
<div class='yc-reviews-stars'
style='--rating: ${review.ratings}'
aria-label="Rating of this product is ${review.ratings} out of 5"
></div>
</div>
<div class='content'>
${review.content === null ? '' : review.content}
</div>
`;
}

const setupReviews = async () => {
const reviewsContainer = $('.yc-product-reviews');
const reviewsWrapper = $('.yc-reviews-wrapper');
const showMoreButton = $('#show-more');
let reviews = [];

const noDataSetter = (element) => {
if (reviewsContainer) {
reviewsContainer.remove();
}
};
/**
* This function is used to remove the reviews container if there is no data.
*
* @param {HTMLElement} element - The element you want to target
*/
const removeReviewsIfNone = () => {
if (reviewsContainer) {
reviewsContainer.remove();
}
};

/**
* Creates a review item.
*
* @param {Object} review - Review object.
* @returns {HTMLElement} - Review item.
*/
const createReviewItem = (review) => {
const reviewItem = document.createElement('li');

const reviewItem = document.createElement('li')
reviewItem.classList.add('review-item');
createElement(reviewItem, review);
reviewItem.innerHTML = reviewTemplate(review);

return reviewsWrapper.appendChild(reviewItem);
}

try {
const res = youcanjs.product.fetchReviews(productId, { limit: 3 });

reviews = await res.data();

reviewsWrapper.append(...reviews.map(review => createReviewItem(review)));
const pagination = res.pagination();
/**
* Handling pagination by showing the show more button if there is more than one page.
*
* @param {Array} reviews - Array of reviews
*/
const handelPagination = (data) => {
const pagination = data.pagination();

if (pagination.totalPages > 1) {
showMoreButton.style.display = 'block';
showMoreButton?.addEventListener('click', async () => {
const response = res.next();

reviews = await response.data();
reviewsWrapper.append(...reviews.map(review => createReviewItem(review)));
if (showMoreButton) {
showMoreButton.addEventListener('click', async () => {
const response = data.next();

reviews = await response.data();
addReviews(reviewsWrapper, reviews);

if (pagination.totalPages >= pagination.currentPage) {
showMoreButton.style.display = 'none';
}
});
};

if (pagination.totalPages >= pagination.currentPage) {
showMoreButton.style.display = 'none';
}
});
}
}

if(reviews) {
convertDate();
}
/**
* Append reviews to the reviewsWrapper.
*/
const addReviews = (reviewsWrapper, reviews) => {
reviewsWrapper.append(...reviews.map(review => createReviewItem(review)));
}

try {
const res = youcanjs.product.fetchReviews(productId, { limit: 3 });
reviews = await res.data();

if (reviews.length === 0) {
noDataSetter();
addReviews(reviewsWrapper, reviews);
handelPagination(res);

if(reviews && reviews.length) {
return convertDate();
}

return removeReviewsIfNone();

} catch (error) {
noDataSetter();
removeReviewsIfNone();
}
})();

function createElement(element, index) {
element.innerHTML = `
<div class='header'>
<div class="profil">
<img loading='lazy' class='image' src=${index.images_urls[0] || defaultAvatar} />
<div class='info'>
<span class='name'>${index.first_name || ''} ${index.last_name || ''}</span>
<span class='created-at-date'>${index.created_at}</span>
</div>
</div>
<div class='yc-reviews-stars'
style="--rating: ${index.ratings};"
aria-label="Rating of this product is ${index.ratings} out of 5"
>
</div>
</div>
<div class='content'>
${index.content === null ? '' : index.content}
</div>
`;
}
};

function convertDate() {
const createdAtDate = document.querySelectorAll('.created-at-date');

createdAtDate?.forEach(date => {
const originalDateString = date.textContent;
const originalDate = new Date(originalDateString);
const day = originalDate.getDate().toString().padStart(2, '0');
const month = (originalDate.getMonth() + 1).toString().padStart(2, '0');
const year = originalDate.getFullYear().toString();
const formattedDate = `${day}.${month}.${year}`;
date.textContent = formattedDate;
});
}
document.addEventListener('DOMContentLoaded', () => {
setupReviews();
});
7 changes: 5 additions & 2 deletions snippets/reviews.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@
<div class='yc-product-reviews container'>
<div class='head'>
<h1 class='yc-section-title'>{{ reviews_title }}</h1>

{%- render 'general-review' -%}
</div>

<ul class='yc-reviews-wrapper' id="reviews-wrapper"></ul>

<button class='yc-btn' id='show-more'>{{ 'general.show_more_button' | t }}</button>
</div>

<script>
{% javascript %}
const defaultAvatar = '{{ "avatar.png" | asset_url }}';
</script>
{% endjavascript %}

{{ 'reviews.js' | asset_url | script_tag_deferred }}
24 changes: 12 additions & 12 deletions styles/reviews.scss
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,18 @@
.info {
display: grid;
gap: 3px;
}

.info .name {
font-weight: 700;
font-size: 18px;
line-height: 120%;
}

.info .created-at-date {
font-weight: 400;
font-size: 12px;
line-height: 120%;

.name {
font-weight: 700;
font-size: 18px;
line-height: 120%;
}

.created-at-date {
font-weight: 400;
font-size: 12px;
line-height: 120%;
}
}
}
}
Expand Down

0 comments on commit 7f303f4

Please sign in to comment.