avtopost.kultmost.ru/templates/paintings/paint.html
2026-08-31 16:37:55 -04:00

341 lines
14 KiB
HTML
Raw 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.

{% extends "base.html" %}
{% import "/components/header.html" as header %}
{% import "/components/footer.html" as footer %}
{% import "components/share.html" as share %}
{% block title %}{{paint.title}}{% endblock %}
{% block head %}
<meta property="og:title" content="{{paint.title}}">
<meta property="og:description" content="{{description}}">
<meta property="og:type" content="product">
<meta property="og:image" content="https://avtopost.kultmost.ru/b/posts/{{paint.medias[0]}}">
<meta property="og:url" content="https://avtopost.kultmost.ru/paintings/{{paint._id}}">
<meta name="description" content="{{description}}">
<meta property="og:site_name" content="Картины | KULTMOST.АВТОПОСТ">
{{ header.style() }}
<style>
.swiper {
position: relative;
max-width: 900px;
margin: 0 auto;
overflow: hidden;
}
.swiper-wrapper {
display: flex;
max-height: 520px;
transition: transform 0.75s cubic-bezier(0.32, 0.72, 0, 1);
will-change: transform;
align-items: center;
}
.swiper-slide {
flex: 0 0 100%;
height: 100%;
position: relative;
transition: background-color 0.8s ease;
overflow: hidden;
display: flex;
}
.swiper-slide img {
max-height: 520px;
width: 100%;
object-fit: scale-down;
}
.caption {
position: absolute;
bottom: 40px;
left: 40px;
color: white;
font-size: 2.1rem;
font-weight: 700;
text-shadow: 0 4px 15px rgba(0,0,0,0.8);
z-index: 5;
}
.swiper-button {
position: absolute;
top: 50%;
transform: translateY(-50%);
background: rgba(255, 255, 255, 0);
color: #683185;
border: 1px solid #683185;
width: 58px;
height: 58px;
font-size: 2.2rem;
cursor: pointer;
border-radius: 50%;
z-index: 10;
text-align: center;
}
.swiper-button:hover { background: rgba(0,0,0,0.9); }
.swiper-button.prev { left: 25px; }
.swiper-button.next { right: 25px; }
.swiper-pagination {
position: absolute;
bottom: 25px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 12px;
z-index: 10;
}
.swiper-pagination-dot {
width: 8px;
height: 8px;
background: rgba(95,23,152,.4);
border-radius: 50%;
cursor: pointer;
}
.swiper-pagination-dot.active {
background: #683185;
transform: scale(1.35);
}
</style>
<style>/* Base (common) styles */
.b_mmlhf { border-radius: 1em;
height: 70px;
min-width: 70px;
object-fit: cover;
max-width: 170px;
object-position: top; }
.b_n91ga { color: #3A3A3A; font-family: Inter; font-size: 14px; font-style: italic; font-weight: 400; line-height: normal; }
.b_01urj { -webkit-box-orient: vertical; -webkit-line-clamp: 1; color: #000; display: -webkit-box; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 700; line-height: normal; overflow: hidden; text-overflow: ellipsis; }
.b_mxr38 { -webkit-box-orient: vertical; -webkit-line-clamp: 1; color: #000; display: -webkit-box; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; overflow: hidden; text-overflow: ellipsis; }
.b_x7dj6 { align-items: flex-start; display: flex; flex-direction: column; flex: 1 0 0; justify-content: center; }
.b_etnpf { align-items: center; align-self: stretch; display: flex; gap: 13px; }
.b_o7w2c { -webkit-box-orient: vertical; color: #000; display: -webkit-box; flex: 1 0 0; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; overflow: hidden; text-overflow: ellipsis; }
.b_4sh8z { align-items: center; align-self: stretch; display: flex; justify-content: center; }
.b_frv5u { -webkit-box-orient: vertical; -webkit-line-clamp: 3; align-self: stretch; color: rgba(58, 58, 58, 0.75); display: -webkit-box; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; overflow: hidden; text-overflow: ellipsis; }
.b_a1gdl { align-items: flex-start; align-self: stretch; display: flex; flex-direction: column; }
.b_mwej0 { align-self: stretch; color: rgba(58, 58, 58, 0.75); font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
.b_6atmo { color: #000; font-family: Inter; font-size: 20px; font-style: normal; font-weight: 700; height: 29px; line-height: normal; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.b_ik47g { align-items: flex-start; align-self: stretch; display: flex; flex-direction: column; padding: 5px 0; }
.b_7efyd { white-space: pre-line; align-self: stretch; color: rgba(58, 58, 58, 0.75); font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
.b_v0d1u { color: #FFF; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
.b_gk0ob { align-items: center; background: #5F1798; border-radius: 5px; display: flex; height: 51px; justify-content: center; padding: 19px 33px; }
.b_tssu9 { align-items: flex-start; max-width: 620px; background: #FFF; display: flex; flex-direction: column; flex: 1 0 0; gap: 10px; justify-content: center; min-width: 335px; padding: 10px 20px; }
.c_m3jeo{background: #fdfaff;margin: auto;
border-radius: 10px;margin-bottom: 111px;}
/* Mobile */
@media (max-width: 699px) {
.c_gnsfq { flex-shrink: 0; height: 400px; width: 355px; }
.c_m3jeo { align-content: flex-start; align-items: flex-start; background: #FFF; display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; width: 375px; }
}
/* Tablet */
@media (min-width: 700px) and (max-width: 900px) {
.c_gnsfq { flex-shrink: 0; height: 400px; width: 668px; }
.c_m3jeo { align-content: flex-start; align-items: flex-start; background: #FFF; display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; width: 800px; }
}
/* Desktop */
@media (min-width: 901px) {
.c_gnsfq { flex: 1 0 0; height: 400px; }
.c_la1ap { color: rgba(58, 58, 58, 0.75); font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
.c_w6ecf { -webkit-box-orient: vertical; -webkit-line-clamp: 1; align-self: stretch; color: #000; display: -webkit-box; font-family: Inter; font-size: 20px; font-style: normal; font-weight: 700; line-height: normal; overflow: hidden; text-overflow: ellipsis; }
.c_m3jeo { align-content: flex-start; align-items: flex-start; background: #FFF; display: flex; flex-wrap: wrap; gap: 30px; justify-content: center; width: 1600px; }
}
.b_gagrr { align-items: center; align-self: stretch; display: flex; justify-content: space-between; }
.b_rhbo8 { color: #5F1798; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
.c_eiyz0{cursor: pointer;}
</style>
{{ footer.style() }}
{% endblock %}
{% block content %}
{{ header.section(user) }}
<section class="c_m3jeo">
<div class="swiper" id="swiper">
<div class="swiper-wrapper" id="wrapper"></div>
{% if paint.medias|length > 1%}
<button class="swiper-button prev" id="prev">‹</button>
<button class="swiper-button next" id="next">›</button>
{% endif %}
<div class="swiper-pagination" id="pagination" {% if paint.medias_original|length == 1%}style="display: none;"{% endif %}></div>
</div>
<div class="c_kuvu7 b_tssu9">
<a class="c_068ki b_etnpf" href="/artists/{{paint.user._id}}"><img class="c_1qh64 b_mmlhf" src="/a/{{paint.user._id}}" crossorigin="anonymous" fetchpriority="high" loading="eager">
<div class="c_pjz1r b_x7dj6">
<p class="c_x2iws b_n91ga">{{paint.city or ''}}</p>
<p class="c_wqjcc b_01urj">{{paint.author or ''}}</p>
<p class="c_x2ptw b_mxr38">{{paint.grade or ''}}</p>
</div>
</a>
<header class="c_qt7dd b_4sh8z">
<h3 class="c_78gsr b_o7w2c">{{paint.title}}</h3>
</header>
<div class="c_wgfe6 b_a1gdl">
<p class="c_sbnel b_frv5u">{{paint.size or ''}}</p>
<p class="c_sbnel b_frv5u">{{paint.material or ''}}</p>
<p class="c_sbnel b_frv5u">{{paint.genre or ''}}</p>
</div>
<div class="c_4g9xz b_ik47g">
<p class="c_la1ap b_mwej0">Стоимость</p>
<h3 class="c_w6ecf b_6atmo">{{paint.price or ''}}</h3>
</div>
<p class="c_zlnpy b_7efyd">{{paint.description or ''}}</p>
<p class="c_sbnel b_frv5u">{{ (paint._id.generation_time.strftime('%d.%m.%Y')) if paint._id else ''}}</p>
{% if user and user._id == paint.user._id %}
<div class="c_ybfp2 b_gagrr">
<a class="c_eiyz0 b_rhbo8" href="/form/post/{{paint._id}}">Редактировать</a>
<button class="c_eiyz0 b_rhbo8" onclick="deletePost('{{paint._id}}')">Удалить</button>
</div>
{% else %}
<a class="c_75ykb b_gk0ob" href="https://telegram.me/gennadiy0605"><span class="c_dlut5 b_v0d1u">Обсудить покупку картины </span></a>
{% endif %}
<div class="c_sbnel b_frv5u">{{ share.share('/paintings/{}'.format(paint._id), paint.title, '/b/posts/{}'.format(paint.medias[0])) }}</div>
<p class="c_sbnel b_frv5u">👁 {{total_watch_count}} (+{{today_watch_count}} Сегодня)</p>
</div>
</section>
</div>
<script>
const images = [
{% for media in paint.medias_original %}
{ src: "/b/posts/{{media}}" },
{% endfor %}
];
const wrapper = document.getElementById('wrapper');
const swiper = document.getElementById('swiper');
const prevBtn = document.getElementById('prev');
const nextBtn = document.getElementById('next');
const pagination = document.getElementById('pagination');
let currentIndex = 0;
let isDragging = false;
let startX = 0;
function createSlides() {
wrapper.innerHTML = '';
pagination.innerHTML = '';
images.forEach((item, i) => {
const slide = document.createElement('div');
slide.className = 'swiper-slide';
const img = document.createElement('img');
img.crossOrigin = "anonymous";
img.src = item.src;
img.loading = "lazy";
slide.append(img);
wrapper.appendChild(slide);
// Пагинация
const dot = document.createElement('div');
dot.className = `swiper-pagination-dot ${i === 0 ? 'active' : ''}`;
dot.onclick = () => goToSlide(i);
pagination.appendChild(dot);
});
wrapper.style.width = `${100}%`;
}
function updateTransform() {
wrapper.style.transform = `translate3d(-${currentIndex * 100}%, 0, 0)`;
document.querySelectorAll('.swiper-pagination-dot').forEach((dot, i) => {
dot.classList.toggle('active', i === currentIndex);
});
}
function goToSlide(index) {
currentIndex = Math.max(0, Math.min(index, images.length - 1));
updateTransform();
}
function nextSlide() { currentIndex = (currentIndex + 1) % images.length; updateTransform(); }
function prevSlide() { currentIndex = (currentIndex - 1 + images.length) % images.length; updateTransform(); }
// Drag
function touchStart(e) {
isDragging = true;
startX = e.type.includes('mouse') ? e.pageX : e.touches[0].clientX;
wrapper.style.transition = 'none';
}
function touchMove(e) {
if (!isDragging) return;
const x = e.type.includes('mouse') ? e.pageX : e.touches[0].clientX;
const percentMoved = ((x - startX) / swiper.clientWidth) * 100;
wrapper.style.transform = `translate3d(${-currentIndex * 100 + percentMoved}%, 0, 0)`;
}
function touchEnd(e) {
if (!isDragging) return;
isDragging = false;
wrapper.style.transition = 'transform 0.75s cubic-bezier(0.32, 0.72, 0, 1)';
const movedPercent = ((e.type.includes('mouse') ? e.pageX : e.changedTouches[0].clientX) - startX) / swiper.clientWidth * 100;
if (movedPercent < -25) nextSlide();
else if (movedPercent > 25) prevSlide();
else updateTransform();
}
function init() {
prevBtn.onclick = prevSlide;
nextBtn.onclick = nextSlide;
swiper.addEventListener('touchstart', touchStart, { passive: true });
swiper.addEventListener('touchmove', touchMove, { passive: true });
swiper.addEventListener('touchend', touchEnd);
swiper.addEventListener('mousedown', touchStart);
window.addEventListener('mousemove', touchMove);
window.addEventListener('mouseup', touchEnd);
window.addEventListener('resize', updateTransform);
}
// Запуск
createSlides();
init();
setTimeout(updateTransform, 100); // даём браузеру время на рендер
</script>
<script>
function deletePost(postId) {
fetch(`/api/post/${postId}`, {
method: 'DELETE'
})
.then(response => {
if (response.ok) {
// Find and delete the parent figure
const postElement = document.querySelector(`figure[data-postId='${postId}']`);
if (postElement) {
postElement.remove();
}
} else {
showToast({
message: 'Ошибка соединения с сервером!',
status: 'error',
duration: 2500
});
}
})
.catch(error => {
// Handle network errors
showToast({
message: 'Ошибка соединения с сервером!',
status: 'error',
duration: 2500
});
});
}
</script>
{{ footer.section(user) }}
{% endblock %}