This commit is contained in:
Vladislav 2026-07-31 06:08:46 -04:00
parent b1135bc9ed
commit 93fa48c5a2
6 changed files with 291 additions and 246 deletions

View File

@ -33,13 +33,21 @@
{% macro style() -%}
<style type="text/css">
h2,p {
max-width: 100%;
overflow-wrap: break-word;
word-break: break-word;
hyphens: auto;
}
.c_qx7jk{margin: 100px 0;}
.c_h9bsw{width: 100%;object-fit: scale-down;}
section,.c_brfx5,.c_brfx5>a{box-sizing: unset;}
.c_brfx5>a{width: 335px;}
@media (min-width: 901px) {
.c_2e7ix { color: #5F1798; font-family: Inter; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_2e7ix { color: #5F1798; font-family: Inter; padding-left: 100px; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_h9bsw { align-self: stretch; border-radius: 5px; }
.c_124dx { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { display: flex; align-items: center; }
.c_124dx { max-width: 100%; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { max-width: 100%; display: flex; align-items: center; }
.c_66s36 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; color: #3A3A3A; text-overflow: ellipsis; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; }
.c_ju2ew { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; align-self: stretch; }
.c_mdq6e { align-self: stretch; color: #5F1798; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
@ -50,16 +58,15 @@
.c_rsgdz { display: flex; justify-content: center; align-items: center; }
.c_sqo80 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_3ppy5 { display: flex; justify-content: center; align-items: center; }
.c_brfx5 { display: flex; align-items: center; align-content: center; gap: 20px; align-self: stretch; flex-wrap: wrap; }
.c_brfx5>a{width: 335px;}
.c_qx7jk { display: flex; box-sizing: unset; padding-left: 100px; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
.c_brfx5 { padding-left: 100px; display: flex; align-items: center; align-content: center; gap: 20px; align-self: stretch; flex-wrap: wrap; }
.c_qx7jk { display: flex; box-sizing: unset; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
}
@media (min-width: 700px) and (max-width: 900px) {
.c_2e7ix { color: #5F1798; font-family: Inter; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_2e7ix { color: #5F1798; font-family: Inter; padding-left: 50px; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_h9bsw { align-self: stretch; border-radius: 5px; }
.c_124dx { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { display: flex; align-items: center; }
.c_124dx { max-width: 100%; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { max-width: 100%; display: flex; align-items: center; }
.c_66s36 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; overflow: hidden; color: #3A3A3A; text-overflow: ellipsis; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; }
.c_ju2ew { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; align-self: stretch; }
.c_mdq6e { align-self: stretch; color: #5F1798; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
@ -71,15 +78,15 @@
.c_sqo80 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_3ppy5 { display: flex; justify-content: center; align-items: center; }
.c_brfx5>a{width: calc(50% - 10px);}
.c_brfx5 { display: flex; align-items: center; align-content: center; gap: 20px; align-self: stretch; flex-wrap: wrap; }
.c_qx7jk { display: flex; box-sizing: unset; padding: 0 50px; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
.c_brfx5 { padding-left: 50px; display: flex; align-items: center; align-content: center; gap: 20px; align-self: stretch; flex-wrap: wrap; }
.c_qx7jk { display: flex; box-sizing: unset; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
}
@media (max-width: 699px) {
.c_2e7ix { color: #5F1798; font-family: Inter; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_2e7ix { color: #5F1798; font-family: Inter; padding-left: 20px; font-size: 42px; font-style: normal; font-weight: 700; line-height: normal; }
.c_h9bsw { align-self: stretch; border-radius: 5px; }
.c_124dx { color: #000; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { display: flex; align-items: center; }
.c_124dx { max-width: 100%; color: #000; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_38uav { max-width: 100%; display: flex; align-items: center; }
.c_66s36 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #3A3A3A; text-overflow: ellipsis; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; }
.c_ju2ew { display: flex; flex-direction: column; align-items: flex-start; gap: 5px; align-self: stretch; }
.c_mdq6e { align-self: stretch; color: #5F1798; font-family: Inter; font-size: 14px; font-style: normal; font-weight: 400; line-height: normal; }
@ -91,6 +98,6 @@
.c_sqo80 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; color: #000; text-overflow: ellipsis; font-family: Inter; font-size: 24px; font-style: normal; font-weight: 700; line-height: normal; }
.c_3ppy5 { display: flex; justify-content: center; align-items: center; }
.c_brfx5 { display: flex; justify-content: center; align-items: flex-start; align-content: flex-start; gap: 20px; align-self: stretch; flex-wrap: wrap; }
.c_qx7jk { display: flex; box-sizing: unset; padding: 0 20px; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
.c_qx7jk { display: flex; box-sizing: unset; flex-direction: column; justify-content: center; align-items: flex-start; gap: 20px; background: #FFF; }
}</style>
{%- endmacro %}

View File

@ -9,10 +9,17 @@
<link rel="icon" type="image/ico" href="/static/favicon.ico">
<link rel="icon" type="image/ico" sizes="256x256" href="/static/favicon.ico">
<link rel="apple-touch-icon" type="image/ico" href="/static/favicon.ico">
<meta name="theme-color" content="#5F1798"/>
<title>{% block title %}{% endblock %}</title>
{% block head %}{% endblock %}
<style>
<style type="text/css">
{% raw %}
h1,h2,h3,p {
max-width: 100%;
overflow-wrap: break-word;
word-break: break-word;
hyphens: auto;
}
html{display: flex;justify-content: center;}
input, button {touch-action: manipulation;}
picture{cursor: zoom-in;}
@ -404,7 +411,7 @@ shareBtns.forEach(btn => {
let promptTimeout = null;
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js').then(reg => {
navigator.serviceWorker.register('/sw.js').then(reg => {
reg.addEventListener('updatefound', () => {
const newWorker = reg.installing;
newWorker.addEventListener('statechange', () => {

View File

@ -7,15 +7,15 @@ function toggleMenu() {
line.classList.toggle('active');
});
}
document.addEventListener('DOMContentLoaded', () => {
const btn = document.getElementById('menu_button');
const menu = document.getElementById('menu');
const menu2 = document.getElementById('menu2');
const iconHamburger = document.getElementById('icon_hamburger');
const iconClose = document.getElementById('icon_close');
if (!btn) return;
btn.addEventListener('click', () => {
toggleMenu()
toggleMenu();
const isOpen = btn.getAttribute('aria-expanded') === 'true';
const newState = !isOpen;
btn.setAttribute('aria-expanded', String(newState));
@ -24,9 +24,145 @@ document.addEventListener('DOMContentLoaded', () => {
});
});
</script>
{% if user %}
{% if user.notify %}
<script>
async function removeShow() {
document.getElementById('notificationsDropdown').classList.remove('show');
document.getElementById('closeNotify').classList.remove('show');
document.getElementById('notificationsBtn').setAttribute('aria-expanded', 'false');
}
async function showNotify() {
const isOpen = document.getElementById('notificationsDropdown').classList.contains('show');
const newState = !isOpen;
document.getElementById('notificationsDropdown').classList.toggle('show', newState);
document.getElementById('closeNotify').classList.toggle('show', newState);
document.getElementById('notificationsBtn').setAttribute('aria-expanded', String(newState));
}
document.addEventListener('DOMContentLoaded', () => {
// Function to update notifications after marking them as read
function updateNotifications(updatedData) {
document.querySelectorAll('#notificationCount').forEach(elem => elem.style.display = 'none');
const notificationsList = document.getElementById('notificationsList');
notificationsList.innerHTML = '';
notificationsArray.forEach(item => {
addNotification(
item.title,
item.text,
item.dateStr,
item.link,
false
);
});
}
document.getElementById('markAsReadBtn').addEventListener('click', function() {
fetch('/api/read/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if (!response.ok) {
showToast({ message: 'Ошибка', status: 'error' });
throw new Error('Network response was not ok');
}
return response.json().then(data => {
notificationsArray.forEach(item => item.read = true);
updateNotifications();
});
})
.catch(error => {
const errorText = error.message || 'Произошла ошибка';
showToast({ message: errorText, status: 'error' });
});
});
// === Открытие уведомлений — так же, как меню ===
const notifyBtn = document.getElementById('notificationsBtn');
const dropdown = document.getElementById('notificationsDropdown');
const closeOverlay = document.getElementById('closeNotify');
// Клик по кнопке уведомлений
notifyBtn.addEventListener('click', (e) => {
e.stopPropagation();
// showNotify();
});
// Клик внутри дропдауна не закрывает
dropdown.addEventListener('click', (e) => {
e.stopPropagation();
});
function addNotification(title, text, time, link = '#', unread = true) {
const list = document.getElementById('notificationsList');
const itemLink = document.createElement('a');
itemLink.href = link + '#main';
const item = document.createElement('div');
item.className = `notification-item ${unread ? 'unread' : ''}`;
item.innerHTML = `
<div>
<strong>${title}</strong>
<p>${text}</p>
<small>${time}</small>
</div>
`;
itemLink.prepend(item);
list.prepend(itemLink);
}
// Initial load of notifications
const notificationsArray = [];
{% for item in user.notify %}
notificationsArray.push({
title: "{{ item.title | e }}",
text: "{{ item.text | e }}",
dateStr: "{{ (item._id.generation_time.strftime('%d.%m.%Y')) if item._id else '' }}",
link: "{{ item.link | e }}",
read: Boolean({{ 1 if item.read else 0 }})
});
{% endfor %}
function parseDate(dateStr) {
if (!dateStr) return null;
const [dd, mm, yyyy] = dateStr.split('.');
const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
return isNaN(d.getTime()) ? null : d;
}
notificationsArray.sort((a, b) => {
// 1) unread first
const aRead = a.read ? 1 : 0;
const bRead = b.read ? 1 : 0;
if (aRead !== bRead) return aRead - bRead;
// 2) newest first
const aTime = parseDate(a.dateStr)?.getTime() ?? 0;
const bTime = parseDate(b.dateStr)?.getTime() ?? 0;
return bTime - aTime;
});
notificationsArray.forEach(item => {
addNotification(item.title, item.text, item.dateStr, item.link, item.read);
});
});
</script>
{% endif %}
{% endif %}
<style>
.nav-icon {display: flex;flex-direction: column;justify-content: space-around;height: 24px;cursor: pointer;position: relative;width: 100%;}
.line {right: 0;display: block;width: 42px;height: 0;transition: all 0.3s ease;position: absolute;border: 1.5px solid;}
.line {right: 0;display: block;width: 42px;height: 0;transition: all 0.3s ease;position: absolute;border: 1px solid;}
.line1{top:3px}
.line2{width: 32px;top: 10px;}
.line3{top: 18px;}
@ -34,6 +170,7 @@ document.addEventListener('DOMContentLoaded', () => {
.line2.active {transform: translateX(-500px);}
.line3.active {max-width: 30px;top: 9px;transform: rotate(-135deg);}
</style>
<header class="c_xirl1">
<div class="c_uh9b6">
<a class="c_7dj6c" href="/">
@ -45,7 +182,7 @@ document.addEventListener('DOMContentLoaded', () => {
<img src="/a/{{user._id}}" class="b_e59wr" crossorigin="anonymous" fetchpriority="high">
</a>
{% endif %}
<button id="menu_button" class="c_pcz1l b_oxx99">
<button id="menu_button" class="c_pcz1l b_oxx99" aria-expanded="false">
<div class="nav-icon">
<span class="line line1"></span>
<span class="line line2"></span>
@ -54,6 +191,7 @@ document.addEventListener('DOMContentLoaded', () => {
</button>
</div>
</div>
<nav id="menu" class="c_olmk1">
<a class="c_qmp95 b_fokm1" href="/">Главная</a>
<a class="c_qmp95 b_fokm1" href="https://kultmost.ru/post">Маркетплейс</a>
@ -72,8 +210,7 @@ document.addEventListener('DOMContentLoaded', () => {
{% endif %}
{% if user and 'back' in user.get('scopes',[]) %}
<span id="backBtn" class="c_qmp95 b_fokm1 btn">Переключиться на Админа</span>
<script>
<script defer>
document.getElementById('backBtn').addEventListener('click', async () => {
try {
const resp = await fetch('/api/admin/back', { method: 'POST' });
@ -100,9 +237,8 @@ document.addEventListener('DOMContentLoaded', () => {
<a href="/login">Вход</a>
</div>
{% endif %}
</nav>
{% if user %}
<a class="c_n2zau" id="menu2" href="/profile">
<img src="/a/{{user._id}}" class="c_27foz b_e59wr" crossorigin="anonymous" fetchpriority="high">
@ -118,170 +254,53 @@ document.addEventListener('DOMContentLoaded', () => {
<a href="/login">Вход</a>
</div>
{% endif %}
{% if user %}
{% if user.notify %}
<div class="header-right">
<div class="notifications-wrapper">
<button class="notifications-btn" id="notificationsBtn">
<button class="notifications-btn" id="notificationsBtn" aria-expanded="false" onclick="showNotify()">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
<path d="M15 17H9C9 18.6569 10.3431 20 12 20C13.6569 20 15 18.6569 15 17Z" fill="#333"/>
<path d="M18 8C18 6.4087 17.3679 4.88258 16.2426 3.75736C15.1174 2.63214 13.5913 2 12 2C10.4087 2 8.88258 2.63214 7.75736 3.75736C6.63214 4.88258 6 6.4087 6 8C6 11.0902 5.22047 13.206 4.34966 14.6054C3.87894 15.4286 3.5 16.5 3.5 17.5H20.5C20.5 16.5 20.1211 15.4286 19.6503 14.6054C18.7795 13.206 18 11.0902 18 8Z" stroke="#333" stroke-width="2"/>
</svg>
{% set notify = user.notify | selectattr('read') | list %}
{% if notify | length > 0%}
{% if notify | length > 0 %}
<span class="notification-badge" id="notificationCount">{{ notify | length }}</span>
{%endif%}
{% endif %}
</button>
<div>
<div id="closeNotify" class="closeNotify" onclick="showNotify()"></div>
<div class="notifications-dropdown" id="notificationsDropdown">
<div class="dropdown-header">
<h3>Уведомления</h3>
<strong>Уведомления</strong>
<button class="c_qmp95 b_fokm1 btn" id="markAsReadBtn">Отметить все как прочитанные</button>
<script>
</script>
</div>
<div class="notifications-list" id="notificationsList">
</div>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
</header>
{% if user %}
{% if user.notify %}
<script>
// Function to update notifications after marking them as read
function updateNotifications(updatedData) {
// Hide notification count if no unread notifications
document.querySelectorAll('#notificationCount').forEach(elem=>elem.style.display = 'none');
// Clear existing notifications list
const notificationsList = document.getElementById('notificationsList');
notificationsList.innerHTML = ''; // Clear the existing list
// Re-add notifications to the list
notificationsArray.forEach(item => {
addNotification(
item.title,
item.text,
item.date,
item.link,
false
);
});
}
document.getElementById('markAsReadBtn').addEventListener('click', function() {
fetch('/api/read/notify', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => {
if (!response.ok) {
showToast({ message: 'Ошибка', status: 'error' });
throw new Error('Network response was not ok');
}
return response.json().then(data => {
updateNotifications();
});
})
.catch(error => {
const errorText = error.message || 'Произошла ошибка';
showToast({ message: errorText, status: 'error' });
});
});
// Handling dropdown for notifications
const btn = document.getElementById('notificationsBtn');
const dropdown = document.getElementById('notificationsDropdown');
btn.addEventListener('click', (e) => {
e.stopPropagation();
dropdown.classList.toggle('show');
});
document.addEventListener('click', () => {
dropdown.classList.remove('show');
});
function addNotification(title, text, time, link = '#', unread = true) {
const list = document.getElementById('notificationsList');
const itemLink = document.createElement('a');
itemLink.href = link + '#main';
const item = document.createElement('div');
item.className = `notification-item ${unread ? 'unread' : ''}`;
item.innerHTML = `
<div>
<strong>${title}</strong>
<p>${text}</p>
<small>${time}</small>
</div>
`;
itemLink.prepend(item);
list.prepend(itemLink);
}
// Initial load of notifications
const notificationsArray = [];
{% for item in user.notify %}
notificationsArray.push({
title: "{{ item.title }}",
text: "{{ item.text }}",
dateStr: "{{ (item._id.generation_time.strftime('%d.%m.%Y')) if item._id else '' }}",
link: "{{ item.link }}",
read: Boolean({{ 1 if item.read else 0 }})
});
{% endfor %}
// Parse dd.mm.YYYY -> Date (or null if missing/invalid)
function parseDate(dateStr) {
if (!dateStr) return null;
const [dd, mm, yyyy] = dateStr.split('.');
const d = new Date(Number(yyyy), Number(mm) - 1, Number(dd));
return isNaN(d.getTime()) ? null : d;
}
notificationsArray.sort((a, b) => {
// 1) unread first
const aRead = a.read ? 1 : 0;
const bRead = b.read ? 1 : 0;
if (aRead !== bRead) return aRead - bRead;
// 2) newest first (fallback to 0 for missing dates)
const aTime = parseDate(a.dateStr)?.getTime() ?? 0;
const bTime = parseDate(b.dateStr)?.getTime() ?? 0;
return aTime - bTime;
});
notificationsArray.forEach(item => {
addNotification(item.title, item.text, item.dateStr, item.link, item.read);
});
</script>
{% endif %}
{% endif %}
{%- endmacro %}
{% macro style() -%}
<style type="text/css">/* Base (common) styles */
.closeNotify{display: none;position: fixed;
width: 100vw;
height: 100vh;
top: 0;
left: 0;
}
.closeNotify.show {display: block;z-index: 2;}
.notifications-wrapper {position: relative;}
.notifications-btn {background: none;border: none;padding: 8px;cursor: pointer;position: relative}
.notification-badge {position: absolute;top: 0;right: 4px;background: #e74c3c;color: white;font-size: 11px;font-weight: bold;min-width: 16px;height: 16px;border-radius: 50%;display: flex;align-items: center;justify-content: center;padding: 0 4px;}
.notifications-dropdown {position: absolute;top: 100%;right: 0;width: 380px;background: white;border-radius: 12px;box-shadow: 0 10px 30px rgba(0,0,0,0.15);display: none;z-index: 2000;margin-top: 8px;overflow: hidden;}
.notifications-dropdown.show {display: block;}
.notifications-dropdown.show {display: block;z-index: 500;}
.dropdown-header {padding: 16px 20px;border-bottom: 1px solid #eee;display: flex;justify-content: space-between;align-items: center;gap: 15px;}
.notifications-list {max-height: 420px;overflow-y: auto;}
.notification-item {padding: 14px 20px;border-bottom: 1px solid #f0f0f0;transition: background 0.2s;color: #1F1F1F;}
@ -291,13 +310,12 @@ document.addEventListener('DOMContentLoaded', () => {
.b_2jukj { fill: #1F1F1F; height: 12px; width: 18px; }
.b_dhbqs { flex-shrink: 0; height: 24px; width: 24px; }
.b_oxx99 { align-items: center; display: flex; height: 48px; justify-content: center; width: 48px; }
.b_fokm1 { font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; text-decoration-skip-ink: auto; text-decoration-style: solid; text-decoration-thickness: auto; text-underline-offset: auto; text-underline-position: from-font; }
.b_fokm1 { display: flex; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; text-decoration-skip-ink: auto; text-decoration-style: solid; text-decoration-thickness: auto; text-underline-offset: auto; text-underline-position: from-font; }
.b_e59wr { border-radius: 1em; height: 70px; min-width: 70px; max-width: 170px; object-fit: cover; object-position: top; }
.b_zp47n { align-self: stretch; color: #5F1798; font-family: Inter; font-size: 16px; font-style: normal; font-weight: 400; line-height: normal; max-width: 210px; }
.b_qel18 { align-items: flex-start; display: flex; flex-direction: column; gap: 5px; justify-content: center; }
.avatar{display: flex;align-items: center;gap: 22px;}
nav>a{color: #111;}
.auth>a, .auth>span{color: #5f1798; font-size: 20px;}
.auth{display: flex;gap: 5px;}
.mob{display: none;}
@ -316,7 +334,6 @@ nav>a{color: #111;}
.c_n2zau { align-items: center; display: flex; flex: 1 0 0; gap: 20px; max-width: 345px;}
.c_xirl1 { align-content: center; align-items: center; align-self: stretch; background: #FFF; display: flex; flex-wrap: wrap; justify-content: space-between; padding: 20px 15px; row-gap: 20px; }
}
/* Tablet */
@media (min-width: 700px) and (max-width: 900px) {
#menu, #menu2 { display: none; }
@ -328,7 +345,6 @@ nav>a{color: #111;}
.c_n2zau { align-items: center; display: flex; flex: 1 0 0; gap: 20px; }
.c_xirl1 { align-content: center; align-items: center; align-self: stretch; background: #FFF; display: flex; flex-wrap: wrap; justify-content: space-between; padding: 20px; row-gap: 20px; }
}
/* Desktop */
@media (min-width: 901px) {
.avatar,#menu_button{display: none;}

View File

@ -15,31 +15,16 @@
{% if 'admin' not in user.get('roles', []) %}
{% if 'partner' in user.get('roles', [])%}
{% if 'partner' in user.get('profile', '') %}
<button class="c_6cfr8 b_m2ah9 b" id="switch-profile">
<button class="c_6cfr8 b_m2ah9 b" onclick="switchProfile()">
<span class="c_d2l0b b_al8e7">Личный кабинет галериста</span>
</button>
{% else %}
<button class="c_6cfr8 b_m2ah9 b" id="switch-profile">
<button class="c_6cfr8 b_m2ah9 b" onclick="switchProfile()">
<span class="c_d2l0b b_al8e7">Личный кабинет партнера</span>
</button>
{% endif %}
{% endif %}
{% endif %}
<script>
document.getElementById('switch-profile')?.addEventListener('click', async (e) => {
e.preventDefault();
try {
const resp = await fetch('/api/switch-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
if (!resp.ok) throw new Error('Network error');
window.location.href = '/profile';
} catch (err) {
console.error(err);
}
});
</script>
<!-- <a href="/profile" class="c_6cfr8 b_m2ah9"><span class="c_d2l0b b_al8e7">Кабинет
Автопост</span></a> -->
<p class="c_kpaav b_xsvl1">Профиль</p>
@ -58,12 +43,19 @@
<input class="c_ijkun b_jkzqx" type="file" accept="image/*" id="avatar" name="avatar">
</div>
<p class="c_kpaav b_xsvl1">{{user.username}}</p>
<button id="logoutBtn" class="c_ryjri b_yzw2z">
<button onclick="logout()" class="c_ryjri b_yzw2z">
<span class="c_d2l0b b_al8e7">Выйти</span>
</button>
<script>
document.getElementById('logoutBtn').addEventListener('click', async function () {
</div>
<div class="c_o5uzd b_h9dsc">
<p class="c_kpaav b_xsvl1">Нужна помощь?</p>
<a class="c_yveil b_v63fu" href="#">
<span class="c_z2tjg b_440jc">Поддержка</span>
</a>
</div>
</div>
<script defer>
async function logout() {
try {
const resp = await fetch('/logout', {
method: 'POST',
@ -78,18 +70,24 @@
} catch (err) {
console.error('Network error during logout', err);
}
}
</script>
<script defer>
async function switchProfile() {
try {
const resp = await fetch('/api/switch-profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
</script>
</div>
<div class="c_o5uzd b_h9dsc">
<p class="c_kpaav b_xsvl1">Нужна помощь?</p>
<a class="c_yveil b_v63fu" href="#">
<span class="c_z2tjg b_440jc">Поддержка</span>
</a>
</div>
</div>
<script>
if (!resp.ok) throw new Error('Network error');
window.location.href = '/profile';
window.location.reload()
} catch (err) {
console.error(err);
}
}
</script>
<script defer>
document.addEventListener('DOMContentLoaded', () => {
const avatarInput = document.getElementById('avatar');
const preview = document.getElementById('preview');

View File

@ -14,6 +14,7 @@
<meta hid="og:url" property="og:url" content="https://avtopost.kultmost.ru/">
<meta hid="description" name="description" content="Сервис создан для художников, скульпторов, искусствоведов, журналистов, галеристов, музеев и разных выставочных пространств с возможностью выложить пост картины, скульптуры, новостей, анонсов выставок или любую другую информацию, разместив сразу в нескольких Ваших социальных сетях интернета, арт-маркетплейсах и сообществах партнёров сервиса одним нажатием!">
<meta hid="og:site_name" property="og:site_name" content="KULTMOST.АВТОПОСТ">
<link rel="canonical" href="https://avtopost.kultmost.ru/"/>
{{ header.style() }}
{{ main.style() }}
{{ articles.style() }}

View File

@ -34,7 +34,9 @@
.c_2e7ix{ margin-bottom: 20px; text-transform: uppercase;}
/* Mobile */
@media (max-width: 699px) {
.c_j7mw1 { align-content: flex-start; align-items: flex-start; align-self: stretch; display: flex; flex-wrap: wrap; gap: 25px; justify-content: center; }
.b_f7c7g { height: 230px; }
.c_j7mw1 > * + * { margin-top: 25px; }
.c_j7mw1 { align-content: flex-start; align-items: flex-start; align-self: stretch; display: flex; flex-wrap: wrap; justify-content: center; }
.c_du9p7 { margin: auto;align-items: center; background: #FFF; display: flex; flex-direction: column; width: 375px; }
.c_y32j2 { align-items: flex-start; display: flex; flex-direction: column; width: 100%; }
@ -42,15 +44,29 @@
/* Tablet */
@media (min-width: 700px) and (max-width: 900px) {
.b_f7c7g { height: 208px; }
.c_j7mw1 > *:nth-child(4n+3),
.c_j7mw1 > *:nth-child(4n+4),
.c_j7mw1 > *:nth-child(n+5){
margin-top: 25px;
}
.c_j7mw1 > *:nth-child(4n+2),
.c_j7mw1 > *:nth-child(4n+4){
margin-left: 25px;
}
.c_tccnr { background: #D9D9D9; width: 340px; }
.c_j7mw1 { align-content: flex-start; align-items: flex-start; align-self: stretch; display: flex; flex-wrap: wrap; gap: 25px; }
.c_j7mw1 { align-content: flex-start; align-items: flex-start; align-self: stretch; display: flex; flex-wrap: wrap; }
.c_du9p7 { align-items: flex-start; background: #FFF; display: flex; flex-direction: column; padding-left: 50px; width: 800px; }
}
/* Desktop */
@media (min-width: 901px) {
.b_f7c7g { height: 275px; }
.c_j7mw1 > *:nth-child(n+4) { margin-top: 25px; }
.c_j7mw1 > *:nth-child(3n+2),
.c_j7mw1 > *:nth-child(3n+3) { margin-left: 25px; }
.c_y32j2 { align-items: flex-start; display: flex; flex-direction: column; width: 450px; }
.c_j7mw1 { align-content: center; align-items: center; align-self: stretch; display: flex; flex-wrap: wrap; gap: 25px; }
.c_j7mw1 { align-content: center; align-items: center; align-self: stretch; display: flex; flex-wrap: wrap; }
.c_du9p7 { align-items: flex-start; background: #FFF; display: flex; flex-direction: column; padding-left: 100px; width: 1600px; }
}</style>
{%- endmacro %}