Eluza133 commited on
Commit
97e1a93
·
verified ·
1 Parent(s): 7432a3d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +612 -18
app.py CHANGED
@@ -287,6 +287,68 @@ BASE_STYLE = '''
287
  box-shadow: var(--shadow);
288
  transition: var(--transition);
289
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  @media (max-width: 768px) {
291
  .sidebar {
292
  transform: translateX(-100%);
@@ -310,6 +372,12 @@ BASE_STYLE = '''
310
  font-size: 1em;
311
  padding: 12px;
312
  }
 
 
 
 
 
 
313
  }
314
  '''
315
 
@@ -774,12 +842,25 @@ def feed():
774
  font-weight: 600;
775
  color: var(--primary);
776
  }
 
 
 
 
 
777
  </style>
778
  </head>
779
  <body>
780
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
781
  ''' + NAV_HTML + '''
782
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
783
  <div class="container">
784
  <h1>Лента публикаций</h1>
785
  <div class="search-container">
@@ -801,7 +882,8 @@ def feed():
801
  <p class="price">Цена: {{ post['price'] }} {{ post['currency'] }}</p>
802
  <p>Загрузил: <a href="{{ url_for('user_profile', username=post['uploader']) }}" class="username-link">{{ post['uploader'] }}</a> | {{ post['upload_date'] }}</p>
803
  <p class="stats">Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
804
- {% if is_authenticated %}
 
805
  <button class="btn cart-btn" onclick="addToCart('{{ post['id'] }}', '{{ post['title'] }}', '{{ post['price'] }}', '{{ post['currency'] }}', '{{ post['uploader'] }}')">В корзину</button>
806
  {% endif %}
807
  </div>
@@ -831,18 +913,81 @@ def feed():
831
  document.getElementById('imageModal').style.display = 'none';
832
  }
833
  }
 
 
 
 
 
834
  function addToCart(postId, title, price, currency, uploader) {
835
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
836
- if (!cart.some(item => item.postId === postId)) {
837
- cart.push({ postId, title, price, currency, uploader });
838
- localStorage.setItem('cart', JSON.stringify(cart));
839
- alert('Добавлено в корзину!');
840
  } else {
841
- alert('Этот товар уже в корзине!');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
842
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
843
  }
844
  window.onload = () => {
845
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
846
  const videos = document.querySelectorAll('.post-preview');
847
  videos.forEach(video => {
848
  video.addEventListener('loadedmetadata', () => {
@@ -879,6 +1024,7 @@ def post_page(post_id):
879
  else:
880
  post['likes'] = [user for user in post.get('likes', []) if user != username]
881
  save_data(data)
 
882
  elif 'comment' in request.form:
883
  comment_text = request.form.get('comment')
884
  if comment_text:
@@ -954,12 +1100,25 @@ def post_page(post_id):
954
  font-weight: 600;
955
  color: var(--primary);
956
  }
 
 
 
 
 
957
  </style>
958
  </head>
959
  <body>
960
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
961
  ''' + NAV_HTML + '''
962
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
963
  <div class="container">
964
  <h1>{{ post['title'] }}</h1>
965
  <video controls>
@@ -975,7 +1134,10 @@ def post_page(post_id):
975
  {% if username in post['likes'] %}Убрать лайк{% else %}Лайк{% endif %}
976
  </button>
977
  </form>
978
- <button class="btn cart-btn" onclick="addToCart('{{ post['id'] }}', '{{ post['title'] }}', '{{ post['price'] }}', '{{ post['currency'] }}', '{{ post['uploader'] }}')">В корзину</button>
 
 
 
979
  <form method="POST" class="comment-section">
980
  <textarea name="comment" placeholder="Оставьте комментарий" rows="4"></textarea>
981
  <button type="submit" class="btn">Отправить</button>
@@ -1000,18 +1162,81 @@ def post_page(post_id):
1000
  document.body.classList.toggle('dark');
1001
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
1002
  }
 
 
 
 
 
1003
  function addToCart(postId, title, price, currency, uploader) {
1004
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1005
- if (!cart.some(item => item.postId === postId)) {
1006
- cart.push({ postId, title, price, currency, uploader });
1007
- localStorage.setItem('cart', JSON.stringify(cart));
1008
- alert('Добавлено в корзину!');
1009
  } else {
1010
- alert('Этот товар уже в корзине!');
1011
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1012
  }
1013
  window.onload = () => {
1014
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
1015
  };
1016
  </script>
1017
  </body>
@@ -1105,6 +1330,7 @@ def profile():
1105
  'title': item['title'],
1106
  'price': item['price'],
1107
  'currency': item['currency'],
 
1108
  'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
1109
  'status': 'pending',
1110
  'buyer_phone': phone,
@@ -1231,6 +1457,14 @@ def profile():
1231
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1232
  ''' + NAV_HTML + '''
1233
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
1234
  <div class="container">
1235
  <div class="profile-header">
1236
  {% if avatar %}
@@ -1277,6 +1511,7 @@ def profile():
1277
  {% endif %}
1278
  <h2>Корзина</h2>
1279
  <div class="cart-grid" id="cartGrid"></div>
 
1280
  <button class="btn" onclick="checkout()" style="margin-top: 20px;">Оформить заказ</button>
1281
  {% with messages = get_flashed_messages(with_categories=true) %}
1282
  {% if messages %}
@@ -1323,26 +1558,43 @@ def profile():
1323
  alert('Ссылка скопирована!');
1324
  });
1325
  }
 
 
 
 
 
1326
  function renderCart() {
1327
  const cart = JSON.parse(localStorage.getItem('cart') || '[]');
 
 
1328
  const cartGrid = document.getElementById('cartGrid');
 
 
1329
  cartGrid.innerHTML = '';
 
1330
  cart.forEach(item => {
 
 
1331
  const div = document.createElement('div');
1332
  div.className = 'cart-item';
1333
  div.innerHTML = `
1334
  <h3>${item.title}</h3>
1335
- <p class="price">Цена: ${item.price} ${item.currency}</p>
1336
  <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
1337
  <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
1338
  `;
 
1339
  cartGrid.appendChild(div);
1340
  });
 
 
 
1341
  }
1342
  function removeFromCart(postId) {
1343
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1344
  cart = cart.filter(item => item.postId !== postId);
1345
  localStorage.setItem('cart', JSON.stringify(cart));
 
1346
  renderCart();
1347
  }
1348
  function checkout() {
@@ -1367,9 +1619,12 @@ def profile():
1367
  document.body.appendChild(form);
1368
  form.submit();
1369
  localStorage.removeItem('cart');
 
1370
  }
1371
  window.onload = () => {
1372
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
1373
  renderCart();
1374
  const videos = document.querySelectorAll('.post-preview');
1375
  videos.forEach(video => {
@@ -1508,6 +1763,14 @@ def user_profile(username):
1508
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1509
  ''' + NAV_HTML + '''
1510
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
1511
  <div class="container">
1512
  <div class="profile-header">
1513
  {% if avatar %}
@@ -1566,8 +1829,68 @@ def user_profile(username):
1566
  alert('Ссылка скопирована!');
1567
  });
1568
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1569
  window.onload = () => {
1570
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
1571
  const videos = document.querySelectorAll('.post-preview');
1572
  videos.forEach(video => {
1573
  video.addEventListener('loadedmetadata', () => {
@@ -1719,6 +2042,14 @@ def upload():
1719
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1720
  ''' + NAV_HTML + '''
1721
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
1722
  <div class="container">
1723
  <h1>Загрузить видео</h1>
1724
  {% with messages = get_flashed_messages(with_categories=true) %}
@@ -1756,6 +2087,64 @@ def upload():
1756
  document.body.classList.toggle('dark');
1757
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
1758
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1759
  document.getElementById('upload-form').onsubmit = async function(e) {
1760
  e.preventDefault();
1761
  const formData = new FormData(this);
@@ -1779,6 +2168,8 @@ def upload():
1779
  };
1780
  window.onload = () => {
1781
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
1782
  };
1783
  </script>
1784
  </body>
@@ -1892,6 +2283,14 @@ def seller_orders():
1892
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1893
  ''' + NAV_HTML + '''
1894
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
1895
  <div class="container">
1896
  <h1>Ваши заказы</h1>
1897
  <div class="order-grid">
@@ -1899,7 +2298,7 @@ def seller_orders():
1899
  {% for order in orders %}
1900
  <div class="order-item">
1901
  <h3>{{ order['title'] }}</h3>
1902
- <p class="price">Цена: {{ order['price'] }} {{ order['currency'] }}</p>
1903
  <p>Покупатель: <a href="{{ url_for('user_profile', username=order['buyer']) }}" class="username-link">{{ order['buyer'] }}</a></p>
1904
  <p>Телефон покупателя: {{ order['buyer_phone'] }}</p>
1905
  {% if order['buyer_address'] %}
@@ -1930,8 +2329,68 @@ def seller_orders():
1930
  document.body.classList.toggle('dark');
1931
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
1932
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1933
  window.onload = () => {
1934
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
1935
  };
1936
  </script>
1937
  </body>
@@ -1977,8 +2436,7 @@ def user_orders():
1977
  color: transparent;
1978
  }
1979
  .order-grid {
1980
- display: grid;
1981
- grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
1982
  gap: 30px;
1983
  }
1984
  .order-item {
@@ -2021,6 +2479,14 @@ def user_orders():
2021
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2022
  ''' + NAV_HTML + '''
2023
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
2024
  <div class="container">
2025
  <h1>Мои заказы</h1>
2026
  <div class="order-grid">
@@ -2028,7 +2494,7 @@ def user_orders():
2028
  {% for order in orders %}
2029
  <div class="order-item">
2030
  <h3>{{ order['title'] }}</h3>
2031
- <p class="price">Цена: {{ order['price'] }} {{ order['currency'] }}</p>
2032
  <p>Продавец: <a href="{{ url_for('user_profile', username=order['uploader']) }}" class="username-link">{{ order['uploader'] }}</a></p>
2033
  <p>Дата: {{ order['date'] }}</p>
2034
  <p>Статус: {{ 'В ожидании' if order['status'] == 'pending' else 'В обработке' if order['status'] == 'processing' else 'Завершено' }}</p>
@@ -2047,8 +2513,68 @@ def user_orders():
2047
  document.body.classList.toggle('dark');
2048
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2049
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2050
  window.onload = () => {
2051
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
2052
  };
2053
  </script>
2054
  </body>
@@ -2213,6 +2739,14 @@ def admin_panel():
2213
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2214
  ''' + NAV_HTML + '''
2215
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
 
 
 
 
 
 
 
 
2216
  <div class="container">
2217
  <h1>Админ-панель</h1>
2218
  <h2>Организации на проверке</h2>
@@ -2275,8 +2809,68 @@ def admin_panel():
2275
  document.body.classList.toggle('dark');
2276
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2277
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2278
  window.onload = () => {
2279
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
 
 
2280
  const videos = document.querySelectorAll('.post-preview');
2281
  videos.forEach(video => {
2282
  video.addEventListener('loadedmetadata', () => {
@@ -2293,4 +2887,4 @@ def admin_panel():
2293
  if __name__ == '__main__':
2294
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
2295
  backup_thread.start()
2296
- app.run(debug=True, host='0.0.0.0', port=7860)
 
287
  box-shadow: var(--shadow);
288
  transition: var(--transition);
289
  }
290
+ .cart-float {
291
+ position: fixed;
292
+ bottom: 20px;
293
+ right: 20px;
294
+ background: var(--cart-btn);
295
+ color: white;
296
+ border-radius: 50%;
297
+ width: 60px;
298
+ height: 60px;
299
+ display: flex;
300
+ align-items: center;
301
+ justify-content: center;
302
+ box-shadow: var(--shadow);
303
+ cursor: pointer;
304
+ z-index: 1000;
305
+ transition: var(--transition);
306
+ }
307
+ .cart-float:hover {
308
+ transform: scale(1.1);
309
+ background: #0d9f6e;
310
+ }
311
+ .cart-modal {
312
+ display: none;
313
+ position: fixed;
314
+ top: 50%;
315
+ left: 50%;
316
+ transform: translate(-50%, -50%);
317
+ background: var(--card-bg-light);
318
+ padding: 30px;
319
+ border-radius: 25px;
320
+ box-shadow: var(--shadow);
321
+ z-index: 2000;
322
+ max-width: 500px;
323
+ width: 90%;
324
+ max-height: 80vh;
325
+ overflow-y: auto;
326
+ }
327
+ body.dark .cart-modal {
328
+ background: var(--card-bg-dark);
329
+ }
330
+ .cart-modal h2 {
331
+ font-size: 1.8em;
332
+ margin-bottom: 20px;
333
+ background: linear-gradient(45deg, var(--primary), var(--secondary));
334
+ -webkit-background-clip: text;
335
+ color: transparent;
336
+ }
337
+ .cart-item {
338
+ background: var(--glass-bg);
339
+ padding: 15px;
340
+ border-radius: 15px;
341
+ margin-bottom: 15px;
342
+ }
343
+ .cart-item h3 {
344
+ font-size: 1.2em;
345
+ margin-bottom: 10px;
346
+ }
347
+ .cart-total {
348
+ font-size: 1.2em;
349
+ font-weight: 600;
350
+ margin-top: 20px;
351
+ }
352
  @media (max-width: 768px) {
353
  .sidebar {
354
  transform: translateX(-100%);
 
372
  font-size: 1em;
373
  padding: 12px;
374
  }
375
+ .cart-float {
376
+ bottom: 15px;
377
+ right: 15px;
378
+ width: 50px;
379
+ height: 50px;
380
+ }
381
  }
382
  '''
383
 
 
842
  font-weight: 600;
843
  color: var(--primary);
844
  }
845
+ .quantity-input {
846
+ width: 60px;
847
+ display: inline-block;
848
+ margin-right: 10px;
849
+ }
850
  </style>
851
  </head>
852
  <body>
853
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
854
  ''' + NAV_HTML + '''
855
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
856
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
857
+ <div class="cart-modal" id="cartModal">
858
+ <h2>Корзина</h2>
859
+ <div id="cartItems"></div>
860
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
861
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
862
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
863
+ </div>
864
  <div class="container">
865
  <h1>Лента публикаций</h1>
866
  <div class="search-container">
 
882
  <p class="price">Цена: {{ post['price'] }} {{ post['currency'] }}</p>
883
  <p>Загрузил: <a href="{{ url_for('user_profile', username=post['uploader']) }}" class="username-link">{{ post['uploader'] }}</a> | {{ post['upload_date'] }}</p>
884
  <p class="stats">Просмотров: {{ post['views'] }} | Лайков: {{ post['likes']|length }}</p>
885
+ {% if is_authenticated and user_type == 'buyer' and verified %}
886
+ <input type="number" class="quantity-input" id="quantity_{{ post['id'] }}" min="1" value="1">
887
  <button class="btn cart-btn" onclick="addToCart('{{ post['id'] }}', '{{ post['title'] }}', '{{ post['price'] }}', '{{ post['currency'] }}', '{{ post['uploader'] }}')">В корзину</button>
888
  {% endif %}
889
  </div>
 
913
  document.getElementById('imageModal').style.display = 'none';
914
  }
915
  }
916
+ function toggleCart() {
917
+ const cartModal = document.getElementById('cartModal');
918
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
919
+ renderCart();
920
+ }
921
  function addToCart(postId, title, price, currency, uploader) {
922
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
923
+ const quantity = parseInt(document.getElementById('quantity_' + postId).value) || 1;
924
+ const existingItem = cart.find(item => item.postId === postId);
925
+ if (existingItem) {
926
+ existingItem.quantity += quantity;
927
  } else {
928
+ cart.push({ postId, title, price: parseFloat(price), currency, uploader, quantity });
929
+ }
930
+ localStorage.setItem('cart', JSON.stringify(cart));
931
+ document.getElementById('cartFloat').style.display = 'block';
932
+ alert('Добавлено в корзину!');
933
+ }
934
+ function renderCart() {
935
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
936
+ const cartItems = document.getElementById('cartItems');
937
+ const cartTotal = document.getElementById('cartTotal');
938
+ cartItems.innerHTML = '';
939
+ let total = 0;
940
+ cart.forEach(item => {
941
+ const div = document.createElement('div');
942
+ div.className = 'cart-item';
943
+ const itemTotal = item.price * item.quantity;
944
+ total += itemTotal;
945
+ div.innerHTML = `
946
+ <h3>${item.title}</h3>
947
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
948
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
949
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
950
+ `;
951
+ cartItems.appendChild(div);
952
+ });
953
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
954
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
955
+ }
956
+ function removeFromCart(postId) {
957
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
958
+ cart = cart.filter(item => item.postId !== postId);
959
+ localStorage.setItem('cart', JSON.stringify(cart));
960
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
961
+ renderCart();
962
+ }
963
+ function checkout() {
964
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
965
+ if (cart.length === 0) {
966
+ alert('Корзина пуста!');
967
+ return;
968
  }
969
+ const form = document.createElement('form');
970
+ form.method = 'POST';
971
+ form.action = '/profile';
972
+ const input = document.createElement('input');
973
+ input.type = 'hidden';
974
+ input.name = 'checkout';
975
+ input.value = 'true';
976
+ const cartData = document.createElement('input');
977
+ cartData.type = 'hidden';
978
+ cartData.name = 'cart_data';
979
+ cartData.value = JSON.stringify(cart);
980
+ form.appendChild(input);
981
+ form.appendChild(cartData);
982
+ document.body.appendChild(form);
983
+ form.submit();
984
+ localStorage.removeItem('cart');
985
+ document.getElementById('cartFloat').style.display = 'none';
986
  }
987
  window.onload = () => {
988
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
989
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
990
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
991
  const videos = document.querySelectorAll('.post-preview');
992
  videos.forEach(video => {
993
  video.addEventListener('loadedmetadata', () => {
 
1024
  else:
1025
  post['likes'] = [user for user in post.get('likes', []) if user != username]
1026
  save_data(data)
1027
+
1028
  elif 'comment' in request.form:
1029
  comment_text = request.form.get('comment')
1030
  if comment_text:
 
1100
  font-weight: 600;
1101
  color: var(--primary);
1102
  }
1103
+ .quantity-input {
1104
+ width: 60px;
1105
+ display: inline-block;
1106
+ margin-right: 10px;
1107
+ }
1108
  </style>
1109
  </head>
1110
  <body>
1111
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1112
  ''' + NAV_HTML + '''
1113
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
1114
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
1115
+ <div class="cart-modal" id="cartModal">
1116
+ <h2>Корзина</h2>
1117
+ <div id="cartItems"></div>
1118
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
1119
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
1120
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
1121
+ </div>
1122
  <div class="container">
1123
  <h1>{{ post['title'] }}</h1>
1124
  <video controls>
 
1134
  {% if username in post['likes'] %}Убрать лайк{% else %}Лайк{% endif %}
1135
  </button>
1136
  </form>
1137
+ {% if user_type == 'buyer' and verified %}
1138
+ <input type="number" class="quantity-input" id="quantity_{{ post['id'] }}" min="1" value="1">
1139
+ <button class="btn cart-btn" onclick="addToCart('{{ post['id'] }}', '{{ post['title'] }}', '{{ post['price'] }}', '{{ post['currency'] }}', '{{ post['uploader'] }}')">В корзину</button>
1140
+ {% endif %}
1141
  <form method="POST" class="comment-section">
1142
  <textarea name="comment" placeholder="Оставьте комментарий" rows="4"></textarea>
1143
  <button type="submit" class="btn">Отправить</button>
 
1162
  document.body.classList.toggle('dark');
1163
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
1164
  }
1165
+ function toggleCart() {
1166
+ const cartModal = document.getElementById('cartModal');
1167
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
1168
+ renderCart();
1169
+ }
1170
  function addToCart(postId, title, price, currency, uploader) {
1171
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1172
+ const quantity = parseInt(document.getElementById('quantity_' + postId).value) || 1;
1173
+ const existingItem = cart.find(item => item.postId === postId);
1174
+ if (existingItem) {
1175
+ existingItem.quantity += quantity;
1176
  } else {
1177
+ cart.push({ postId, title, price: parseFloat(price), currency, uploader, quantity });
1178
  }
1179
+ localStorage.setItem('cart', JSON.stringify(cart));
1180
+ document.getElementById('cartFloat').style.display = 'block';
1181
+ alert('Добавлено в корзину!');
1182
+ }
1183
+ function renderCart() {
1184
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1185
+ const cartItems = document.getElementById('cartItems');
1186
+ const cartTotal = document.getElementById('cartTotal');
1187
+ cartItems.innerHTML = '';
1188
+ let total = 0;
1189
+ cart.forEach(item => {
1190
+ const div = document.createElement('div');
1191
+ div.className = 'cart-item';
1192
+ const itemTotal = item.price * item.quantity;
1193
+ total += itemTotal;
1194
+ div.innerHTML = `
1195
+ <h3>${item.title}</h3>
1196
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
1197
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
1198
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
1199
+ `;
1200
+ cartItems.appendChild(div);
1201
+ });
1202
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
1203
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
1204
+ }
1205
+ function removeFromCart(postId) {
1206
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1207
+ cart = cart.filter(item => item.postId !== postId);
1208
+ localStorage.setItem('cart', JSON.stringify(cart));
1209
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
1210
+ renderCart();
1211
+ }
1212
+ function checkout() {
1213
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1214
+ if (cart.length === 0) {
1215
+ alert('Корзина пуста!');
1216
+ return;
1217
+ }
1218
+ const form = document.createElement('form');
1219
+ form.method = 'POST';
1220
+ form.action = '/profile';
1221
+ const input = document.createElement('input');
1222
+ input.type = 'hidden';
1223
+ input.name = 'checkout';
1224
+ input.value = 'true';
1225
+ const cartData = document.createElement('input');
1226
+ cartData.type = 'hidden';
1227
+ cartData.name = 'cart_data';
1228
+ cartData.value = JSON.stringify(cart);
1229
+ form.appendChild(input);
1230
+ form.appendChild(cartData);
1231
+ document.body.appendChild(form);
1232
+ form.submit();
1233
+ localStorage.removeItem('cart');
1234
+ document.getElementById('cartFloat').style.display = 'none';
1235
  }
1236
  window.onload = () => {
1237
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
1238
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1239
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
1240
  };
1241
  </script>
1242
  </body>
 
1330
  'title': item['title'],
1331
  'price': item['price'],
1332
  'currency': item['currency'],
1333
+ 'quantity': item['quantity'],
1334
  'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
1335
  'status': 'pending',
1336
  'buyer_phone': phone,
 
1457
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1458
  ''' + NAV_HTML + '''
1459
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
1460
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
1461
+ <div class="cart-modal" id="cartModal">
1462
+ <h2>Корзина</h2>
1463
+ <div id="cartItems"></div>
1464
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
1465
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
1466
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
1467
+ </div>
1468
  <div class="container">
1469
  <div class="profile-header">
1470
  {% if avatar %}
 
1511
  {% endif %}
1512
  <h2>Корзина</h2>
1513
  <div class="cart-grid" id="cartGrid"></div>
1514
+ <p class="cart-total" id="cartTotalProfile">Итого: 0</p>
1515
  <button class="btn" onclick="checkout()" style="margin-top: 20px;">Оформить заказ</button>
1516
  {% with messages = get_flashed_messages(with_categories=true) %}
1517
  {% if messages %}
 
1558
  alert('Ссылка скопирована!');
1559
  });
1560
  }
1561
+ function toggleCart() {
1562
+ const cartModal = document.getElementById('cartModal');
1563
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
1564
+ renderCart();
1565
+ }
1566
  function renderCart() {
1567
  const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1568
+ const cartItems = document.getElementById('cartItems');
1569
+ const cartTotal = document.getElementById('cartTotal');
1570
  const cartGrid = document.getElementById('cartGrid');
1571
+ const cartTotalProfile = document.getElementById('cartTotalProfile');
1572
+ cartItems.innerHTML = '';
1573
  cartGrid.innerHTML = '';
1574
+ let total = 0;
1575
  cart.forEach(item => {
1576
+ const itemTotal = item.price * item.quantity;
1577
+ total += itemTotal;
1578
  const div = document.createElement('div');
1579
  div.className = 'cart-item';
1580
  div.innerHTML = `
1581
  <h3>${item.title}</h3>
1582
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
1583
  <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
1584
  <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
1585
  `;
1586
+ cartItems.appendChild(div.cloneNode(true));
1587
  cartGrid.appendChild(div);
1588
  });
1589
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
1590
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
1591
+ cartTotalProfile.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
1592
  }
1593
  function removeFromCart(postId) {
1594
  let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1595
  cart = cart.filter(item => item.postId !== postId);
1596
  localStorage.setItem('cart', JSON.stringify(cart));
1597
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
1598
  renderCart();
1599
  }
1600
  function checkout() {
 
1619
  document.body.appendChild(form);
1620
  form.submit();
1621
  localStorage.removeItem('cart');
1622
+ document.getElementById('cartFloat').style.display = 'none';
1623
  }
1624
  window.onload = () => {
1625
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
1626
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1627
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
1628
  renderCart();
1629
  const videos = document.querySelectorAll('.post-preview');
1630
  videos.forEach(video => {
 
1763
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
1764
  ''' + NAV_HTML + '''
1765
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
1766
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
1767
+ <div class="cart-modal" id="cartModal">
1768
+ <h2>Корзина</h2>
1769
+ <div id="cartItems"></div>
1770
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
1771
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
1772
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
1773
+ </div>
1774
  <div class="container">
1775
  <div class="profile-header">
1776
  {% if avatar %}
 
1829
  alert('Ссылка скопирована!');
1830
  });
1831
  }
1832
+ function toggleCart() {
1833
+ const cartModal = document.getElementById('cartModal');
1834
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
1835
+ renderCart();
1836
+ }
1837
+ function renderCart() {
1838
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1839
+ const cartItems = document.getElementById('cartItems');
1840
+ const cartTotal = document.getElementById('cartTotal');
1841
+ cartItems.innerHTML = '';
1842
+ let total = 0;
1843
+ cart.forEach(item => {
1844
+ const itemTotal = item.price * item.quantity;
1845
+ total += itemTotal;
1846
+ const div = document.createElement('div');
1847
+ div.className = 'cart-item';
1848
+ div.innerHTML = `
1849
+ <h3>${item.title}</h3>
1850
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
1851
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
1852
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
1853
+ `;
1854
+ cartItems.appendChild(div);
1855
+ });
1856
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
1857
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
1858
+ }
1859
+ function removeFromCart(postId) {
1860
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
1861
+ cart = cart.filter(item => item.postId !== postId);
1862
+ localStorage.setItem('cart', JSON.stringify(cart));
1863
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
1864
+ renderCart();
1865
+ }
1866
+ function checkout() {
1867
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1868
+ if (cart.length === 0) {
1869
+ alert('Корзина пуста!');
1870
+ return;
1871
+ }
1872
+ const form = document.createElement('form');
1873
+ form.method = 'POST';
1874
+ form.action = '/profile';
1875
+ const input = document.createElement('input');
1876
+ input.type = 'hidden';
1877
+ input.name = 'checkout';
1878
+ input.value = 'true';
1879
+ const cartData = document.createElement('input');
1880
+ cartData.type = 'hidden';
1881
+ cartData.name = 'cart_data';
1882
+ cartData.value = JSON.stringify(cart);
1883
+ form.appendChild(input);
1884
+ form.appendChild(cartData);
1885
+ document.body.appendChild(form);
1886
+ form.submit();
1887
+ localStorage.removeItem('cart');
1888
+ document.getElementById('cartFloat').style.display = 'none';
1889
+ }
1890
  window.onload = () => {
1891
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
1892
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
1893
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
1894
  const videos = document.querySelectorAll('.post-preview');
1895
  videos.forEach(video => {
1896
  video.addEventListener('loadedmetadata', () => {
 
2042
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2043
  ''' + NAV_HTML + '''
2044
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
2045
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
2046
+ <div class="cart-modal" id="cartModal">
2047
+ <h2>Корзина</h2>
2048
+ <div id="cartItems"></div>
2049
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
2050
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
2051
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
2052
+ </div>
2053
  <div class="container">
2054
  <h1>Загрузить видео</h1>
2055
  {% with messages = get_flashed_messages(with_categories=true) %}
 
2087
  document.body.classList.toggle('dark');
2088
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2089
  }
2090
+ function toggleCart() {
2091
+ const cartModal = document.getElementById('cartModal');
2092
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
2093
+ renderCart();
2094
+ }
2095
+ function renderCart() {
2096
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2097
+ const cartItems = document.getElementById('cartItems');
2098
+ const cartTotal = document.getElementById('cartTotal');
2099
+ cartItems.innerHTML = '';
2100
+ let total = 0;
2101
+ cart.forEach(item => {
2102
+ const itemTotal = item.price * item.quantity;
2103
+ total += itemTotal;
2104
+ const div = document.createElement('div');
2105
+ div.className = 'cart-item';
2106
+ div.innerHTML = `
2107
+ <h3>${item.title}</h3>
2108
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
2109
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
2110
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
2111
+ `;
2112
+ cartItems.appendChild(div);
2113
+ });
2114
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
2115
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
2116
+ }
2117
+ function removeFromCart(postId) {
2118
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
2119
+ cart = cart.filter(item => item.postId !== postId);
2120
+ localStorage.setItem('cart', JSON.stringify(cart));
2121
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
2122
+ renderCart();
2123
+ }
2124
+ function checkout() {
2125
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2126
+ if (cart.length === 0) {
2127
+ alert('Корзина пуста!');
2128
+ return;
2129
+ }
2130
+ const form = document.createElement('form');
2131
+ form.method = 'POST';
2132
+ form.action = '/profile';
2133
+ const input = document.createElement('input');
2134
+ input.type = 'hidden';
2135
+ input.name = 'checkout';
2136
+ input.value = 'true';
2137
+ const cartData = document.createElement('input');
2138
+ cartData.type = 'hidden';
2139
+ cartData.name = 'cart_data';
2140
+ cartData.value = JSON.stringify(cart);
2141
+ form.appendChild(input);
2142
+ form.appendChild(cartData);
2143
+ document.body.appendChild(form);
2144
+ form.submit();
2145
+ localStorage.removeItem('cart');
2146
+ document.getElementById('cartFloat').style.display = 'none';
2147
+ }
2148
  document.getElementById('upload-form').onsubmit = async function(e) {
2149
  e.preventDefault();
2150
  const formData = new FormData(this);
 
2168
  };
2169
  window.onload = () => {
2170
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
2171
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2172
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
2173
  };
2174
  </script>
2175
  </body>
 
2283
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2284
  ''' + NAV_HTML + '''
2285
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
2286
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
2287
+ <div class="cart-modal" id="cartModal">
2288
+ <h2>Корзина</h2>
2289
+ <div id="cartItems"></div>
2290
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
2291
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
2292
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
2293
+ </div>
2294
  <div class="container">
2295
  <h1>Ваши заказы</h1>
2296
  <div class="order-grid">
 
2298
  {% for order in orders %}
2299
  <div class="order-item">
2300
  <h3>{{ order['title'] }}</h3>
2301
+ <p class="price">Цена: {{ order['price'] }} {{ order['currency'] }} x {{ order['quantity'] }} = {{ (order['price']|float * order['quantity'])|round(2) }} {{ order['currency'] }}</p>
2302
  <p>Покупатель: <a href="{{ url_for('user_profile', username=order['buyer']) }}" class="username-link">{{ order['buyer'] }}</a></p>
2303
  <p>Телефон покупателя: {{ order['buyer_phone'] }}</p>
2304
  {% if order['buyer_address'] %}
 
2329
  document.body.classList.toggle('dark');
2330
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2331
  }
2332
+ function toggleCart() {
2333
+ const cartModal = document.getElementById('cartModal');
2334
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
2335
+ renderCart();
2336
+ }
2337
+ function renderCart() {
2338
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2339
+ const cartItems = document.getElementById('cartItems');
2340
+ const cartTotal = document.getElementById('cartTotal');
2341
+ cartItems.innerHTML = '';
2342
+ let total = 0;
2343
+ cart.forEach(item => {
2344
+ const itemTotal = item.price * item.quantity;
2345
+ total += itemTotal;
2346
+ const div = document.createElement('div');
2347
+ div.className = 'cart-item';
2348
+ div.innerHTML = `
2349
+ <h3>${item.title}</h3>
2350
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
2351
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
2352
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
2353
+ `;
2354
+ cartItems.appendChild(div);
2355
+ });
2356
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
2357
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
2358
+ }
2359
+ function removeFromCart(postId) {
2360
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
2361
+ cart = cart.filter(item => item.postId !== postId);
2362
+ localStorage.setItem('cart', JSON.stringify(cart));
2363
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
2364
+ renderCart();
2365
+ }
2366
+ function checkout() {
2367
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2368
+ if (cart.length === 0) {
2369
+ alert('Корзина пуста!');
2370
+ return;
2371
+ }
2372
+ const form = document.createElement('form');
2373
+ form.method = 'POST';
2374
+ form.action = '/profile';
2375
+ const input = document.createElement('input');
2376
+ input.type = 'hidden';
2377
+ input.name = 'checkout';
2378
+ input.value = 'true';
2379
+ const cartData = document.createElement('input');
2380
+ cartData.type = 'hidden';
2381
+ cartData.name = 'cart_data';
2382
+ cartData.value = JSON.stringify(cart);
2383
+ form.appendChild(input);
2384
+ form.appendChild(cartData);
2385
+ document.body.appendChild(form);
2386
+ form.submit();
2387
+ localStorage.removeItem('cart');
2388
+ document.getElementById('cartFloat').style.display = 'none';
2389
+ }
2390
  window.onload = () => {
2391
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
2392
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2393
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
2394
  };
2395
  </script>
2396
  </body>
 
2436
  color: transparent;
2437
  }
2438
  .order-grid {
2439
+ display grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
 
2440
  gap: 30px;
2441
  }
2442
  .order-item {
 
2479
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2480
  ''' + NAV_HTML + '''
2481
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
2482
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
2483
+ <div class="cart-modal" id="cartModal">
2484
+ <h2>Корзина</h2>
2485
+ <div id="cartItems"></div>
2486
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
2487
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
2488
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
2489
+ </div>
2490
  <div class="container">
2491
  <h1>Мои заказы</h1>
2492
  <div class="order-grid">
 
2494
  {% for order in orders %}
2495
  <div class="order-item">
2496
  <h3>{{ order['title'] }}</h3>
2497
+ <p class="price">Цена: {{ order['price'] }} {{ order['currency'] }} x {{ order['quantity'] }} = {{ (order['price']|float * order['quantity'])|round(2) }} {{ order['currency'] }}</p>
2498
  <p>Продавец: <a href="{{ url_for('user_profile', username=order['uploader']) }}" class="username-link">{{ order['uploader'] }}</a></p>
2499
  <p>Дата: {{ order['date'] }}</p>
2500
  <p>Статус: {{ 'В ожидании' if order['status'] == 'pending' else 'В обработке' if order['status'] == 'processing' else 'Завершено' }}</p>
 
2513
  document.body.classList.toggle('dark');
2514
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2515
  }
2516
+ function toggleCart() {
2517
+ const cartModal = document.getElementById('cartModal');
2518
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
2519
+ renderCart();
2520
+ }
2521
+ function renderCart() {
2522
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2523
+ const cartItems = document.getElementById('cartItems');
2524
+ const cartTotal = document.getElementById('cartTotal');
2525
+ cartItems.innerHTML = '';
2526
+ let total = 0;
2527
+ cart.forEach(item => {
2528
+ const itemTotal = item.price * item.quantity;
2529
+ total += itemTotal;
2530
+ const div = document.createElement('div');
2531
+ div.className = 'cart-item';
2532
+ div.innerHTML = `
2533
+ <h3>${item.title}</h3>
2534
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
2535
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
2536
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
2537
+ `;
2538
+ cartItems.appendChild(div);
2539
+ });
2540
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
2541
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
2542
+ }
2543
+ function removeFromCart(postId) {
2544
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
2545
+ cart = cart.filter(item => item.postId !== postId);
2546
+ localStorage.setItem('cart', JSON.stringify(cart));
2547
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
2548
+ renderCart();
2549
+ }
2550
+ function checkout() {
2551
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2552
+ if (cart.length === 0) {
2553
+ alert('Корзина пуста!');
2554
+ return;
2555
+ }
2556
+ const form = document.createElement('form');
2557
+ form.method = 'POST';
2558
+ form.action = '/profile';
2559
+ const input = document.createElement('input');
2560
+ input.type = 'hidden';
2561
+ input.name = 'checkout';
2562
+ input.value = 'true';
2563
+ const cartData = document.createElement('input');
2564
+ cartData.type = 'hidden';
2565
+ cartData.name = 'cart_data';
2566
+ cartData.value = JSON.stringify(cart);
2567
+ form.appendChild(input);
2568
+ form.appendChild(cartData);
2569
+ document.body.appendChild(form);
2570
+ form.submit();
2571
+ localStorage.removeItem('cart');
2572
+ document.getElementById('cartFloat').style.display = 'none';
2573
+ }
2574
  window.onload = () => {
2575
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
2576
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2577
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
2578
  };
2579
  </script>
2580
  </body>
 
2739
  <button class="menu-btn" onclick="toggleSidebar()">☰</button>
2740
  ''' + NAV_HTML + '''
2741
  <button class="theme-toggle" onclick="toggleTheme()">🌙</button>
2742
+ <div class="cart-float" onclick="toggleCart()" style="display: none;" id="cartFloat">🛒</div>
2743
+ <div class="cart-modal" id="cartModal">
2744
+ <h2>Корзина</h2>
2745
+ <div id="cartItems"></div>
2746
+ <p class="cart-total" id="cartTotal">Итого: 0</p>
2747
+ <button class="btn" onclick="checkout()">Оформить заказ</button>
2748
+ <button class="btn" onclick="toggleCart()">Закрыть</button>
2749
+ </div>
2750
  <div class="container">
2751
  <h1>Админ-панель</h1>
2752
  <h2>Организации на проверке</h2>
 
2809
  document.body.classList.toggle('dark');
2810
  localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
2811
  }
2812
+ function toggleCart() {
2813
+ const cartModal = document.getElementById('cartModal');
2814
+ cartModal.style.display = cartModal.style.display === 'block' ? 'none' : 'block';
2815
+ renderCart();
2816
+ }
2817
+ function renderCart() {
2818
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2819
+ const cartItems = document.getElementById('cartItems');
2820
+ const cartTotal = document.getElementById('cartTotal');
2821
+ cartItems.innerHTML = '';
2822
+ let total = 0;
2823
+ cart.forEach(item => {
2824
+ const itemTotal = item.price * item.quantity;
2825
+ total += itemTotal;
2826
+ const div = document.createElement('div');
2827
+ div.className = 'cart-item';
2828
+ div.innerHTML = `
2829
+ <h3>${item.title}</h3>
2830
+ <p>Цена: ${item.price} ${item.currency} x ${item.quantity} = ${itemTotal.toFixed(2)} ${item.currency}</p>
2831
+ <p>Продавец: <a href="/profile/${item.uploader}" class="username-link">${item.uploader}</a></p>
2832
+ <button class="btn remove-cart-btn" onclick="removeFromCart('${item.postId}')">Удалить</button>
2833
+ `;
2834
+ cartItems.appendChild(div);
2835
+ });
2836
+ const totalCurrency = cart.length > 0 ? cart[0].currency : '';
2837
+ cartTotal.textContent = `Итого: ${total.toFixed(2)} ${totalCurrency}`;
2838
+ }
2839
+ function removeFromCart(postId) {
2840
+ let cart = JSON.parse(localStorage.getItem('cart') || '[]');
2841
+ cart = cart.filter(item => item.postId !== postId);
2842
+ localStorage.setItem('cart', JSON.stringify(cart));
2843
+ if (cart.length === 0) document.getElementById('cartFloat').style.display = 'none';
2844
+ renderCart();
2845
+ }
2846
+ function checkout() {
2847
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2848
+ if (cart.length === 0) {
2849
+ alert('Корзина пуста!');
2850
+ return;
2851
+ }
2852
+ const form = document.createElement('form');
2853
+ form.method = 'POST';
2854
+ form.action = '/profile';
2855
+ const input = document.createElement('input');
2856
+ input.type = 'hidden';
2857
+ input.name = 'checkout';
2858
+ input.value = 'true';
2859
+ const cartData = document.createElement('input');
2860
+ cartData.type = 'hidden';
2861
+ cartData.name = 'cart_data';
2862
+ cartData.value = JSON.stringify(cart);
2863
+ form.appendChild(input);
2864
+ form.appendChild(cartData);
2865
+ document.body.appendChild(form);
2866
+ form.submit();
2867
+ localStorage.removeItem('cart');
2868
+ document.getElementById('cartFloat').style.display = 'none';
2869
+ }
2870
  window.onload = () => {
2871
  if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
2872
+ const cart = JSON.parse(localStorage.getItem('cart') || '[]');
2873
+ if (cart.length > 0) document.getElementById('cartFloat').style.display = 'block';
2874
  const videos = document.querySelectorAll('.post-preview');
2875
  videos.forEach(video => {
2876
  video.addEventListener('loadedmetadata', () => {
 
2887
  if __name__ == '__main__':
2888
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
2889
  backup_thread.start()
2890
+ app.run(debug=True, host='0.0.0.0', port=7860)