feat: added review block
This commit is contained in:
@@ -122,6 +122,119 @@
|
||||
});
|
||||
})();
|
||||
|
||||
(() => {
|
||||
const slider = document.querySelector("[data-reviews-slider]");
|
||||
if (!slider) return;
|
||||
|
||||
const viewport = slider.querySelector("[data-reviews-viewport]");
|
||||
const track = slider.querySelector("[data-reviews-track]");
|
||||
const prevButton = slider.querySelector("[data-reviews-prev]");
|
||||
const nextButton = slider.querySelector("[data-reviews-next]");
|
||||
const dotsContainer = document.querySelector("[data-reviews-dots]");
|
||||
const cards = Array.from(track?.querySelectorAll(".review-card") ?? []);
|
||||
|
||||
if (!viewport || !track || !prevButton || !nextButton || !dotsContainer || cards.length < 2) return;
|
||||
|
||||
let currentIndex = 0;
|
||||
let touchStartX = 0;
|
||||
|
||||
const readVisibleSlides = () => {
|
||||
const visibleValue = Number.parseInt(getComputedStyle(slider).getPropertyValue("--reviews-visible"), 10);
|
||||
return Number.isFinite(visibleValue) && visibleValue > 0 ? visibleValue : 1;
|
||||
};
|
||||
|
||||
const readTrackGap = () => {
|
||||
const styles = getComputedStyle(track);
|
||||
const gapValue = styles.gap || styles.columnGap || "0";
|
||||
const parsedGap = Number.parseFloat(gapValue);
|
||||
return Number.isFinite(parsedGap) ? parsedGap : 0;
|
||||
};
|
||||
|
||||
const maxIndex = () => Math.max(0, cards.length - readVisibleSlides());
|
||||
|
||||
const renderDots = () => {
|
||||
const total = maxIndex() + 1;
|
||||
dotsContainer.innerHTML = "";
|
||||
|
||||
for (let index = 0; index < total; index += 1) {
|
||||
const dot = document.createElement("button");
|
||||
dot.type = "button";
|
||||
dot.className = "reviews__dot";
|
||||
dot.setAttribute("aria-label", `Показать отзыв ${index + 1}`);
|
||||
dot.addEventListener("click", () => {
|
||||
currentIndex = index;
|
||||
update();
|
||||
});
|
||||
dotsContainer.appendChild(dot);
|
||||
}
|
||||
};
|
||||
|
||||
const update = () => {
|
||||
const max = maxIndex();
|
||||
currentIndex = Math.min(Math.max(currentIndex, 0), max);
|
||||
|
||||
const cardWidth = cards[0].getBoundingClientRect().width;
|
||||
const offset = (cardWidth + readTrackGap()) * currentIndex;
|
||||
track.style.transform = `translateX(${-offset}px)`;
|
||||
|
||||
prevButton.disabled = currentIndex === 0;
|
||||
nextButton.disabled = currentIndex === max;
|
||||
|
||||
const dots = Array.from(dotsContainer.querySelectorAll(".reviews__dot"));
|
||||
dots.forEach((dot, index) => {
|
||||
dot.classList.toggle("is-active", index === currentIndex);
|
||||
dot.setAttribute("aria-current", index === currentIndex ? "true" : "false");
|
||||
});
|
||||
};
|
||||
|
||||
prevButton.addEventListener("click", () => {
|
||||
currentIndex -= 1;
|
||||
update();
|
||||
});
|
||||
|
||||
nextButton.addEventListener("click", () => {
|
||||
currentIndex += 1;
|
||||
update();
|
||||
});
|
||||
|
||||
viewport.addEventListener("touchstart", (event) => {
|
||||
touchStartX = event.changedTouches[0].clientX;
|
||||
}, { passive: true });
|
||||
|
||||
viewport.addEventListener("touchend", (event) => {
|
||||
const deltaX = event.changedTouches[0].clientX - touchStartX;
|
||||
const threshold = 48;
|
||||
|
||||
if (deltaX > threshold) {
|
||||
currentIndex -= 1;
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (deltaX < -threshold) {
|
||||
currentIndex += 1;
|
||||
update();
|
||||
}
|
||||
}, { passive: true });
|
||||
|
||||
const handleResize = () => {
|
||||
renderDots();
|
||||
update();
|
||||
};
|
||||
|
||||
let resizeRaf = null;
|
||||
window.addEventListener("resize", () => {
|
||||
if (resizeRaf) return;
|
||||
resizeRaf = window.requestAnimationFrame(() => {
|
||||
resizeRaf = null;
|
||||
handleResize();
|
||||
});
|
||||
});
|
||||
|
||||
renderDots();
|
||||
update();
|
||||
})();
|
||||
|
||||
(() => {
|
||||
const bookingForm = document.getElementById("booking-form");
|
||||
const successModal = document.getElementById("booking-success-modal");
|
||||
|
||||
Reference in New Issue
Block a user