40046-vm/app.js
2026-05-20 10:02:04 +00:00

145 lines
5.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const data = window.REPORT_DATA;
const cards = document.querySelector("#cards");
const rows = document.querySelector("#summaryRows");
const rate = document.querySelector("#rate");
const criteria = document.querySelector("#criteria");
const notes = document.querySelector("#notes");
const lightbox = document.querySelector("#lightbox");
const lightboxImage = document.querySelector("#lightboxImage");
const lightboxSource = document.querySelector("#lightboxSource");
rate.textContent = `${data.generated}. ${data.rate}`;
criteria.textContent = data.criteria;
notes.innerHTML = data.notes.map((note) => `<li>${note}</li>`).join("");
const labelByKind = {
hotel: "отель",
review: "отзыв",
"traveler-video": "видео"
};
function formatRub(value) {
return new Intl.NumberFormat("ru-RU").format(value);
}
function formatByn(value) {
return new Intl.NumberFormat("ru-RU").format(value);
}
function renderSummary(filter = "all") {
const visible = data.hotels.filter((hotel) => filter === "all" || hotel.segment === filter);
rows.innerHTML = visible.map((hotel) => `
<tr>
<td><strong>${hotel.name}</strong><br><span class="badge ${hotel.segment === "8-9" ? "" : "warn"}">${hotel.rank}</span></td>
<td>${hotel.dates}</td>
<td>${hotel.nights}</td>
<td class="price">${formatByn(hotel.price_byn)} BYN<br><span>${formatRub(hotel.price_rub)} RUB</span></td>
<td>${hotel.transfer}</td>
<td>${hotel.verdict}</td>
</tr>
`).join("");
}
function renderCards(filter = "all") {
const visible = data.hotels.filter((hotel) => filter === "all" || hotel.segment === filter);
cards.innerHTML = visible.map((hotel) => `
<article class="hotel-card" data-segment="${hotel.segment}">
<div class="gallery" aria-label="Фото ${hotel.name}">
${hotel.images.map((image, index) => `
<button class="shot" data-full="${image.file}" data-source="${image.source}" type="button">
<img src="${image.file}" loading="${index < 2 ? "eager" : "lazy"}" alt="${hotel.name}: ${labelByKind[image.kind] || "фото"}" />
<span class="tag">${labelByKind[image.kind] || image.kind}</span>
</button>
`).join("")}
</div>
<div class="hotel-info">
<div class="hotel-head">
<div class="hotel-title">
<h3>${hotel.name} ${hotel.stars}</h3>
<p>${hotel.rank}</p>
</div>
<div class="hotel-price">
<strong>${formatByn(hotel.price_byn)} BYN</strong>
<span>${formatRub(hotel.price_rub)} RUB. ${hotel.alt_price}</span>
</div>
</div>
<div class="facts">
<div class="fact"><span>Даты</span><strong>${hotel.dates}</strong></div>
<div class="fact"><span>Ночи</span><strong>${hotel.nights}</strong></div>
<div class="fact"><span>Питание</span><strong>${hotel.meal}</strong></div>
<div class="fact"><span>Трансфер</span><strong>${hotel.transfer}</strong></div>
<div class="fact"><span>Рейс</span><strong>${hotel.flight}</strong></div>
<div class="fact"><span>Пляж</span><strong>${hotel.line}, ${hotel.beach}</strong></div>
<div class="fact"><span>Рейтинг</span><strong>${hotel.rating}</strong></div>
<div class="fact"><span>Сегмент</span><strong>${hotel.segment === "near-9" ? "рядом с 9" : hotel.segment + " тыс."}</strong></div>
</div>
<p class="verdict">${hotel.verdict}</p>
<div class="columns">
<div>
<h4>Плюсы</h4>
<ul class="pros">${hotel.pros.map((item) => `<li>${item}</li>`).join("")}</ul>
</div>
<div>
<h4>Риски</h4>
<ul class="cons">${hotel.cons.map((item) => `<li>${item}</li>`).join("")}</ul>
</div>
</div>
<div class="review">
<h4>По фото и отзывам</h4>
<p>${hotel.review}</p>
</div>
<div class="links">
<h4>Источники</h4>
<a href="${hotel.top_source}" target="_blank" rel="noreferrer">TopHotels media</a>
<a href="${hotel.trip}" target="_blank" rel="noreferrer">Tripadvisor</a>
</div>
</div>
</article>
`).join("");
}
function setFilter(filter) {
document.querySelectorAll(".filter").forEach((button) => {
button.classList.toggle("active", button.dataset.filter === filter);
});
renderSummary(filter);
renderCards(filter);
}
document.querySelectorAll(".filter").forEach((button) => {
button.addEventListener("click", () => setFilter(button.dataset.filter));
});
cards.addEventListener("click", (event) => {
const shot = event.target.closest(".shot");
if (!shot) return;
lightboxImage.src = shot.dataset.full;
lightboxSource.href = shot.dataset.source;
lightbox.classList.add("open");
lightbox.setAttribute("aria-hidden", "false");
document.body.classList.add("lightbox-open");
});
document.querySelector("#closeLightbox").addEventListener("click", closeLightbox);
lightbox.addEventListener("click", (event) => {
if (event.target === lightbox) closeLightbox();
});
window.addEventListener("keydown", (event) => {
if (event.key === "Escape") closeLightbox();
});
function closeLightbox() {
lightbox.classList.remove("open");
lightbox.setAttribute("aria-hidden", "true");
document.body.classList.remove("lightbox-open");
lightboxImage.src = "";
}
setFilter("all");