Eluza133 commited on
Commit
7432a3d
·
verified ·
1 Parent(s): 0aa5a15

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +254 -29
app.py CHANGED
@@ -27,7 +27,7 @@ def load_data():
27
  data = json.load(file)
28
  if not isinstance(data, dict):
29
  logging.warning("Данные не в формате dict, инициализация пустой базы")
30
- return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}}
31
  if 'posts' not in data:
32
  data['posts'] = []
33
  if 'users' not in data:
@@ -36,11 +36,13 @@ def load_data():
36
  data['pending_organizations'] = []
37
  if 'orders' not in data:
38
  data['orders'] = {}
 
 
39
  logging.info("Данные успешно загружены")
40
  return data
41
  except Exception as e:
42
  logging.error(f"Ошибка загрузки данных: {e}")
43
- return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}}
44
 
45
  def save_data(data):
46
  try:
@@ -82,7 +84,7 @@ def download_db_from_hf():
82
  logging.error(f"Ошибка скачивания базы: {e}")
83
  if not os.path.exists(DATA_FILE):
84
  with open(DATA_FILE, 'w', encoding='utf-8') as f:
85
- json.dump({'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}}, f)
86
 
87
  def periodic_backup():
88
  while True:
@@ -157,6 +159,7 @@ BASE_STYLE = '''
157
  border-radius: 15px;
158
  font-size: 1.1em;
159
  transition: var(--transition);
 
160
  }
161
  body.dark .nav-link {
162
  background: var(--card-bg-dark);
@@ -174,6 +177,21 @@ BASE_STYLE = '''
174
  .logout-btn:hover {
175
  background: #e63970;
176
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  .menu-btn {
178
  display: none;
179
  font-size: 32px;
@@ -306,8 +324,9 @@ NAV_HTML = '''
306
  <a href="{{ url_for('profile') }}" class="nav-link"><span>👤</span> Профиль ({{ username }})</a>
307
  <a href="{{ url_for('upload') }}" class="nav-link"><span>⬆️</span> Загрузить</a>
308
  {% if user_type == 'seller' and verified %}
309
- <a href="{{ url_for('orders') }}" class="nav-link"><span>🛒</span> Заказы</a>
310
  {% endif %}
 
311
  <a href="{{ url_for('logout') }}" class="nav-link logout-btn"><span>🚪</span> Выйти</a>
312
  {% else %}
313
  <a href="{{ url_for('login') }}" class="nav-link"><span>🔑</span> Войти</a>
@@ -326,11 +345,13 @@ def register():
326
  username = request.form.get('username')
327
  password = request.form.get('password')
328
  user_type = request.form.get('user_type')
 
 
329
  data = load_data()
330
 
331
- if not username or not password:
332
- flash('Заполните логин и пароль!', 'error')
333
- logging.debug("Логин или пароль не заполнены")
334
  return redirect(url_for('register'))
335
 
336
  if username in data['users']:
@@ -356,7 +377,11 @@ def register():
356
  'link': '',
357
  'avatar': None,
358
  'type': 'seller',
359
- 'verified': False
 
 
 
 
360
  }
361
  data['pending_organizations'].append({
362
  'username': username,
@@ -379,7 +404,9 @@ def register():
379
  'link': '',
380
  'avatar': None,
381
  'type': 'buyer',
382
- 'verified': True
 
 
383
  }
384
  save_data(data)
385
  flash('Регистрация успешна! Войдите в систему.', 'success')
@@ -478,6 +505,8 @@ def register():
478
  <form method="POST">
479
  <input type="text" name="username" placeholder="Логин" required>
480
  <input type="password" name="password" placeholder="Пароль" required>
 
 
481
  <div id="seller-fields">
482
  <input type="text" name="org_name" placeholder="Название организации">
483
  <input type="text" name="org_phone" placeholder="Рабочий номер организации">
@@ -499,6 +528,7 @@ def register():
499
  }
500
  function toggleSellerFields(show) {
501
  document.getElementById('seller-fields').style.display = show ? 'block' : 'none';
 
502
  }
503
  function toggleAddress() {
504
  const isOnline = document.querySelector('input[name="is_online"]').checked;
@@ -636,6 +666,7 @@ def feed():
636
  username = session.get('username', None)
637
  user_type = data['users'].get(username, {}).get('type') if username else None
638
  verified = data['users'].get(username, {}).get('verified', False) if username else False
 
639
 
640
  search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' else request.args.get('search', '').strip().lower()
641
  if search_query:
@@ -823,7 +854,7 @@ def feed():
823
  </body>
824
  </html>
825
  '''
826
- return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified)
827
 
828
  # Страница публикации
829
  @app.route('/post/<post_id>', methods=['GET', 'POST'])
@@ -837,6 +868,7 @@ def post_page(post_id):
837
  username = session.get('username', None)
838
  user_type = data['users'].get(username, {}).get('type') if username else None
839
  verified = data['users'].get(username, {}).get('verified', False) if username else False
 
840
  post['views'] = post.get('views', 0) + 1
841
  save_data(data)
842
 
@@ -985,7 +1017,7 @@ def post_page(post_id):
985
  </body>
986
  </html>
987
  '''
988
- return render_template_string(html, post=post, repo_id=REPO_ID, is_authenticated=is_authenticated, username=username, user_type=user_type, verified=verified)
989
 
990
  # Профиль пользователя
991
  @app.route('/profile', methods=['GET', 'POST'])
@@ -1007,6 +1039,12 @@ def profile():
1007
  avatar = user_data.get('avatar', None)
1008
  user_type = user_data.get('type', 'buyer')
1009
  verified = user_data.get('verified', False)
 
 
 
 
 
 
1010
 
1011
  if request.method == 'POST':
1012
  if 'delete_post' in request.form:
@@ -1018,6 +1056,10 @@ def profile():
1018
  elif 'update_profile' in request.form:
1019
  bio = request.form.get('bio', '')
1020
  link = request.form.get('link', '')
 
 
 
 
1021
  avatar_file = request.files.get('avatar')
1022
  if avatar_file and avatar_file.filename:
1023
  filename = secure_filename(avatar_file.filename)
@@ -1039,17 +1081,24 @@ def profile():
1039
  os.remove(temp_path)
1040
  data['users'][username]['bio'] = bio
1041
  data['users'][username]['link'] = link
 
 
 
 
 
 
1042
  save_data(data)
1043
  return redirect(url_for('profile'))
1044
  elif 'checkout' in request.form:
1045
  cart = json.loads(request.form.get('cart_data', '[]'))
1046
  if cart:
 
 
 
1047
  for item in cart:
1048
  seller = item['uploader']
1049
- if seller not in data['orders']:
1050
- data['orders'][seller] = []
1051
- order_id = f"order_{len(data['orders'].get(seller, [])) + 1}_{int(time.time())}"
1052
- data['orders'][seller].append({
1053
  'order_id': order_id,
1054
  'buyer': username,
1055
  'post_id': item['postId'],
@@ -1057,11 +1106,19 @@ def profile():
1057
  'price': item['price'],
1058
  'currency': item['currency'],
1059
  'date': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
1060
- 'status': 'pending'
1061
- })
 
 
 
 
 
 
 
 
1062
  save_data(data)
1063
  flash('Заказ успешно оформлен!', 'success')
1064
- return redirect(url_for('profile'))
1065
 
1066
  html = '''
1067
  <!DOCTYPE html>
@@ -1186,6 +1243,14 @@ def profile():
1186
  <p><a href="{{ link }}" target="_blank">{{ link }}</a></p>
1187
  {% endif %}
1188
  <p>Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}</p>
 
 
 
 
 
 
 
 
1189
  <p>Просмотров: {{ total_views }} | Лайков: {{ total_likes }}</p>
1190
  <button class="btn share-btn" onclick="copyProfileLink()">Поделиться</button>
1191
  </div>
@@ -1194,6 +1259,16 @@ def profile():
1194
  <form method="POST" enctype="multipart/form-data">
1195
  <textarea name="bio" placeholder="Описание профиля" rows="4">{{ bio }}</textarea>
1196
  <input type="text" name="link" placeholder="Ссылка" value="{{ link }}">
 
 
 
 
 
 
 
 
 
 
1197
  <input type="file" name="avatar" accept="image/*">
1198
  <button type="submit" name="update_profile" class="btn">Сохранить</button>
1199
  </form>
@@ -1203,6 +1278,13 @@ def profile():
1203
  <h2>Корзина</h2>
1204
  <div class="cart-grid" id="cartGrid"></div>
1205
  <button class="btn" onclick="checkout()" style="margin-top: 20px;">Оформить заказ</button>
 
 
 
 
 
 
 
1206
  <h2>Ваши видео</h2>
1207
  <div class="post-grid">
1208
  {% if user_posts %}
@@ -1300,7 +1382,7 @@ def profile():
1300
  </body>
1301
  </html>
1302
  '''
1303
- return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified)
1304
 
1305
  # Профиль другого пользователя
1306
  @app.route('/profile/<username>')
@@ -1320,6 +1402,12 @@ def user_profile(username):
1320
  avatar = user_data.get('avatar', None)
1321
  user_type = user_data.get('type', 'buyer')
1322
  verified = user_data.get('verified', False)
 
 
 
 
 
 
1323
 
1324
  html = '''
1325
  <!DOCTYPE html>
@@ -1432,6 +1520,14 @@ def user_profile(username):
1432
  <p><a href="{{ link }}" target="_blank">{{ link }}</a></p>
1433
  {% endif %}
1434
  <p>Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}</p>
 
 
 
 
 
 
 
 
1435
  <p>Просмотров: {{ total_views }} | Лайков: {{ total_likes }}</p>
1436
  <button class="btn share-btn" onclick="copyProfileLink()">Поделиться</button>
1437
  </div>
@@ -1483,7 +1579,7 @@ def user_profile(username):
1483
  </body>
1484
  </html>
1485
  '''
1486
- return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified)
1487
 
1488
  # Загрузка контента
1489
  @app.route('/upload', methods=['GET', 'POST'])
@@ -1556,8 +1652,9 @@ def upload():
1556
 
1557
  is_authenticated = 'username' in session
1558
  username = session.get('username', None)
1559
- user_type = data['users'].get(username, {}).get('type')
1560
- verified = data['users'].get(username, {}).get('verified', False)
 
1561
  html = '''
1562
  <!DOCTYPE html>
1563
  <html lang="ru">
@@ -1687,11 +1784,11 @@ def upload():
1687
  </body>
1688
  </html>
1689
  '''
1690
- return render_template_string(html, username=username, is_authenticated=is_authenticated, user_type=user_type, verified=verified)
1691
 
1692
  # Заказы продавца
1693
- @app.route('/orders', methods=['GET', 'POST'])
1694
- def orders():
1695
  if 'username' not in session:
1696
  flash('Войдите, чтобы просмотреть заказы!', 'error')
1697
  return redirect(url_for('login'))
@@ -1707,6 +1804,7 @@ def orders():
1707
  is_authenticated = 'username' in session
1708
  user_type = user_data.get('type')
1709
  verified = user_data.get('verified', False)
 
1710
 
1711
  if request.method == 'POST':
1712
  if 'update_status' in request.form:
@@ -1715,9 +1813,14 @@ def orders():
1715
  for order in orders:
1716
  if order['order_id'] == order_id:
1717
  order['status'] = new_status
 
 
 
 
 
1718
  break
1719
  save_data(data)
1720
- return redirect(url_for('orders'))
1721
 
1722
  html = '''
1723
  <!DOCTYPE html>
@@ -1798,6 +1901,10 @@ def orders():
1798
  <h3>{{ order['title'] }}</h3>
1799
  <p class="price">Цена: {{ order['price'] }} {{ order['currency'] }}</p>
1800
  <p>Покупатель: <a href="{{ url_for('user_profile', username=order['buyer']) }}" class="username-link">{{ order['buyer'] }}</a></p>
 
 
 
 
1801
  <p>Дата: {{ order['date'] }}</p>
1802
  <form method="POST">
1803
  <input type="hidden" name="order_id" value="{{ order['order_id'] }}">
@@ -1830,7 +1937,124 @@ def orders():
1830
  </body>
1831
  </html>
1832
  '''
1833
- return render_template_string(html, username=username, orders=orders, is_authenticated=is_authenticated, user_type=user_type, verified=verified)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1834
 
1835
  # Админ-панель
1836
  @app.route('/admhosto', methods=['GET', 'POST'])
@@ -1842,6 +2066,7 @@ def admin_panel():
1842
  username = session.get('username', None)
1843
  user_type = data['users'].get(username, {}).get('type') if username else None
1844
  verified = data['users'].get(username, {}).get('verified', False) if username else False
 
1845
 
1846
  if request.method == 'POST':
1847
  if 'delete' in request.form:
@@ -1869,7 +2094,7 @@ def admin_panel():
1869
  posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()]
1870
 
1871
  html = '''
1872
- <!DOCTYPE html
1873
  <html lang="ru">
1874
  <head>
1875
  <meta charset="UTF-8">
@@ -2063,7 +2288,7 @@ def admin_panel():
2063
  </body>
2064
  </html>
2065
  '''
2066
- return render_template_string(html, posts=posts, pending_orgs=pending_orgs, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified)
2067
 
2068
  if __name__ == '__main__':
2069
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)
 
27
  data = json.load(file)
28
  if not isinstance(data, dict):
29
  logging.warning("Данные не в формате dict, инициализация пустой базы")
30
+ return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}}
31
  if 'posts' not in data:
32
  data['posts'] = []
33
  if 'users' not in data:
 
36
  data['pending_organizations'] = []
37
  if 'orders' not in data:
38
  data['orders'] = {}
39
+ if 'user_orders' not in data:
40
+ data['user_orders'] = {}
41
  logging.info("Данные успешно загружены")
42
  return data
43
  except Exception as e:
44
  logging.error(f"Ошибка загрузки данных: {e}")
45
+ return {'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}}
46
 
47
  def save_data(data):
48
  try:
 
84
  logging.error(f"Ошибка скачивания базы: {e}")
85
  if not os.path.exists(DATA_FILE):
86
  with open(DATA_FILE, 'w', encoding='utf-8') as f:
87
+ json.dump({'posts': [], 'users': {}, 'pending_organizations': [], 'orders': {}, 'user_orders': {}}, f)
88
 
89
  def periodic_backup():
90
  while True:
 
159
  border-radius: 15px;
160
  font-size: 1.1em;
161
  transition: var(--transition);
162
+ position: relative;
163
  }
164
  body.dark .nav-link {
165
  background: var(--card-bg-dark);
 
177
  .logout-btn:hover {
178
  background: #e63970;
179
  }
180
+ .order-count {
181
+ position: absolute;
182
+ right: 15px;
183
+ top: 50%;
184
+ transform: translateY(-50%);
185
+ background: var(--secondary);
186
+ color: white;
187
+ border-radius: 50%;
188
+ width: 20px;
189
+ height: 20px;
190
+ display: flex;
191
+ align-items: center;
192
+ justify-content: center;
193
+ font-size: 0.9em;
194
+ }
195
  .menu-btn {
196
  display: none;
197
  font-size: 32px;
 
324
  <a href="{{ url_for('profile') }}" class="nav-link"><span>👤</span> Профиль ({{ username }})</a>
325
  <a href="{{ url_for('upload') }}" class="nav-link"><span>⬆️</span> Загрузить</a>
326
  {% if user_type == 'seller' and verified %}
327
+ <a href="{{ url_for('seller_orders') }}" class="nav-link"><span>🛒</span> Заказы {% if order_count > 0 %}<span class="order-count">{{ order_count }}</span>{% endif %}</a>
328
  {% endif %}
329
+ <a href="{{ url_for('user_orders') }}" class="nav-link"><span>📦</span> Мои заказы</a>
330
  <a href="{{ url_for('logout') }}" class="nav-link logout-btn"><span>🚪</span> Выйти</a>
331
  {% else %}
332
  <a href="{{ url_for('login') }}" class="nav-link"><span>🔑</span> Войти</a>
 
345
  username = request.form.get('username')
346
  password = request.form.get('password')
347
  user_type = request.form.get('user_type')
348
+ phone = request.form.get('phone')
349
+ address = request.form.get('address')
350
  data = load_data()
351
 
352
+ if not username or not password or not phone or (user_type == 'buyer' and not address):
353
+ flash('Заполните все обязательные поля!', 'error')
354
+ logging.debug("Не все обязательные поля заполнены")
355
  return redirect(url_for('register'))
356
 
357
  if username in data['users']:
 
377
  'link': '',
378
  'avatar': None,
379
  'type': 'seller',
380
+ 'verified': False,
381
+ 'phone': phone,
382
+ 'org_phone': org_phone,
383
+ 'org_address': org_address,
384
+ 'is_online': is_online
385
  }
386
  data['pending_organizations'].append({
387
  'username': username,
 
404
  'link': '',
405
  'avatar': None,
406
  'type': 'buyer',
407
+ 'verified': True,
408
+ 'phone': phone,
409
+ 'address': address
410
  }
411
  save_data(data)
412
  flash('Регистрация успешна! Войдите в систему.', 'success')
 
505
  <form method="POST">
506
  <input type="text" name="username" placeholder="Логин" required>
507
  <input type="password" name="password" placeholder="Пароль" required>
508
+ <input type="text" name="phone" placeholder="Номер телефона (с кодом, например, +996)" required>
509
+ <input type="text" name="address" placeholder="Адрес доставки" id="address_field">
510
  <div id="seller-fields">
511
  <input type="text" name="org_name" placeholder="Название организации">
512
  <input type="text" name="org_phone" placeholder="Рабочий номер организации">
 
528
  }
529
  function toggleSellerFields(show) {
530
  document.getElementById('seller-fields').style.display = show ? 'block' : 'none';
531
+ document.getElementById('address_field').required = !show;
532
  }
533
  function toggleAddress() {
534
  const isOnline = document.querySelector('input[name="is_online"]').checked;
 
666
  username = session.get('username', None)
667
  user_type = data['users'].get(username, {}).get('type') if username else None
668
  verified = data['users'].get(username, {}).get('verified', False) if username else False
669
+ order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0
670
 
671
  search_query = request.form.get('search', '').strip().lower() if request.method == 'POST' else request.args.get('search', '').strip().lower()
672
  if search_query:
 
854
  </body>
855
  </html>
856
  '''
857
+ return render_template_string(html, posts=posts, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified, order_count=order_count)
858
 
859
  # Страница публикации
860
  @app.route('/post/<post_id>', methods=['GET', 'POST'])
 
868
  username = session.get('username', None)
869
  user_type = data['users'].get(username, {}).get('type') if username else None
870
  verified = data['users'].get(username, {}).get('verified', False) if username else False
871
+ order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0
872
  post['views'] = post.get('views', 0) + 1
873
  save_data(data)
874
 
 
1017
  </body>
1018
  </html>
1019
  '''
1020
+ return render_template_string(html, post=post, repo_id=REPO_ID, is_authenticated=is_authenticated, username=username, user_type=user_type, verified=verified, order_count=order_count)
1021
 
1022
  # Профиль пользователя
1023
  @app.route('/profile', methods=['GET', 'POST'])
 
1039
  avatar = user_data.get('avatar', None)
1040
  user_type = user_data.get('type', 'buyer')
1041
  verified = user_data.get('verified', False)
1042
+ phone = user_data.get('phone', '')
1043
+ address = user_data.get('address', '')
1044
+ org_phone = user_data.get('org_phone', '')
1045
+ org_address = user_data.get('org_address', '')
1046
+ is_online = user_data.get('is_online', False)
1047
+ order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0
1048
 
1049
  if request.method == 'POST':
1050
  if 'delete_post' in request.form:
 
1056
  elif 'update_profile' in request.form:
1057
  bio = request.form.get('bio', '')
1058
  link = request.form.get('link', '')
1059
+ phone = request.form.get('phone', '')
1060
+ address = request.form.get('address', '') if user_type == 'buyer' else address
1061
+ org_phone = request.form.get('org_phone', '') if user_type == 'seller' else org_phone
1062
+ org_address = request.form.get('org_address', '') if user_type == 'seller' and not is_online else None
1063
  avatar_file = request.files.get('avatar')
1064
  if avatar_file and avatar_file.filename:
1065
  filename = secure_filename(avatar_file.filename)
 
1081
  os.remove(temp_path)
1082
  data['users'][username]['bio'] = bio
1083
  data['users'][username]['link'] = link
1084
+ data['users'][username]['phone'] = phone
1085
+ if user_type == 'buyer':
1086
+ data['users'][username]['address'] = address
1087
+ if user_type == 'seller' and verified:
1088
+ data['users'][username]['org_phone'] = org_phone
1089
+ data['users'][username]['org_address'] = org_address
1090
  save_data(data)
1091
  return redirect(url_for('profile'))
1092
  elif 'checkout' in request.form:
1093
  cart = json.loads(request.form.get('cart_data', '[]'))
1094
  if cart:
1095
+ if not phone or (user_type == 'buyer' and not address):
1096
+ flash('Укажите номер телефона и адрес доставки в профиле перед оформлением заказа!', 'error')
1097
+ return redirect(url_for('profile'))
1098
  for item in cart:
1099
  seller = item['uploader']
1100
+ order_id = f"order_{int(time.time())}_{random.randint(1, 1000)}"
1101
+ order_data = {
 
 
1102
  'order_id': order_id,
1103
  'buyer': username,
1104
  'post_id': item['postId'],
 
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,
1111
+ 'buyer_address': address if user_type == 'buyer' else None
1112
+ }
1113
+ if seller not in data['orders']:
1114
+ data['orders'][seller] = []
1115
+ data['orders'][seller].append(order_data)
1116
+ if username not in data['user_orders']:
1117
+ data['user_orders'][username] = []
1118
+ data['user_orders'][username].append(order_data)
1119
  save_data(data)
1120
  flash('Заказ успешно оформлен!', 'success')
1121
+ return redirect(url_for('profile'))
1122
 
1123
  html = '''
1124
  <!DOCTYPE html>
 
1243
  <p><a href="{{ link }}" target="_blank">{{ link }}</a></p>
1244
  {% endif %}
1245
  <p>Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}</p>
1246
+ <p>Телефон: {{ phone }}</p>
1247
+ {% if user_type == 'buyer' %}
1248
+ <p>Адрес доставки: {{ address }}</p>
1249
+ {% endif %}
1250
+ {% if user_type == 'seller' and verified %}
1251
+ <p>Рабочий номер: {{ org_phone }}</p>
1252
+ <p>Адрес организации: {{ org_address if org_address else 'Онлайн' }}</p>
1253
+ {% endif %}
1254
  <p>Просмотров: {{ total_views }} | Лайков: {{ total_likes }}</p>
1255
  <button class="btn share-btn" onclick="copyProfileLink()">Поделиться</button>
1256
  </div>
 
1259
  <form method="POST" enctype="multipart/form-data">
1260
  <textarea name="bio" placeholder="Описание профиля" rows="4">{{ bio }}</textarea>
1261
  <input type="text" name="link" placeholder="Ссылка" value="{{ link }}">
1262
+ <input type="text" name="phone" placeholder="Номер телефона" value="{{ phone }}" required>
1263
+ {% if user_type == 'buyer' %}
1264
+ <input type="text" name="address" placeholder="Адрес доставки" value="{{ address }}" required>
1265
+ {% endif %}
1266
+ {% if user_type == 'seller' and verified %}
1267
+ <input type="text" name="org_phone" placeholder="Рабочий номер" value="{{ org_phone }}" required>
1268
+ {% if not is_online %}
1269
+ <input type="text" name="org_address" placeholder="Адрес организации" value="{{ org_address }}">
1270
+ {% endif %}
1271
+ {% endif %}
1272
  <input type="file" name="avatar" accept="image/*">
1273
  <button type="submit" name="update_profile" class="btn">Сохранить</button>
1274
  </form>
 
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 %}
1283
+ {% for category, message in messages %}
1284
+ <div class="flash {{ category }}">{{ message }}</div>
1285
+ {% endfor %}
1286
+ {% endif %}
1287
+ {% endwith %}
1288
  <h2>Ваши видео</h2>
1289
  <div class="post-grid">
1290
  {% if user_posts %}
 
1382
  </body>
1383
  </html>
1384
  '''
1385
+ return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified, phone=phone, address=address, org_phone=org_phone, org_address=org_address, is_online=is_online, order_count=order_count)
1386
 
1387
  # Профиль другого пользователя
1388
  @app.route('/profile/<username>')
 
1402
  avatar = user_data.get('avatar', None)
1403
  user_type = user_data.get('type', 'buyer')
1404
  verified = user_data.get('verified', False)
1405
+ phone = user_data.get('phone', '')
1406
+ address = user_data.get('address', '')
1407
+ org_phone = user_data.get('org_phone', '')
1408
+ org_address = user_data.get('org_address', '')
1409
+ is_online = user_data.get('is_online', False)
1410
+ order_count = len(data['orders'].get(current_user, [])) if data['users'].get(current_user, {}).get('type') == 'seller' and data['users'].get(current_user, {}).get('verified', False) else 0
1411
 
1412
  html = '''
1413
  <!DOCTYPE html>
 
1520
  <p><a href="{{ link }}" target="_blank">{{ link }}</a></p>
1521
  {% endif %}
1522
  <p>Тип: {{ 'Продавец' if user_type == 'seller' else 'Покупатель' }} {% if user_type == 'seller' and not verified %}(На проверке){% endif %}</p>
1523
+ <p>Телефон: {{ phone }}</p>
1524
+ {% if user_type == 'buyer' %}
1525
+ <p>Адрес доставки: {{ address }}</p>
1526
+ {% endif %}
1527
+ {% if user_type == 'seller' and verified %}
1528
+ <p>Рабочий номер: {{ org_phone }}</p>
1529
+ <p>Адрес организации: {{ org_address if org_address else 'Онлайн' }}</p>
1530
+ {% endif %}
1531
  <p>Просмотров: {{ total_views }} | Лайков: {{ total_likes }}</p>
1532
  <button class="btn share-btn" onclick="copyProfileLink()">Поделиться</button>
1533
  </div>
 
1579
  </body>
1580
  </html>
1581
  '''
1582
+ return render_template_string(html, username=username, user_posts=user_posts, total_views=total_views, total_likes=total_likes, bio=bio, link=link, avatar=avatar, repo_id=REPO_ID, is_authenticated=is_authenticated, user_type=user_type, verified=verified, phone=phone, address=address, org_phone=org_phone, org_address=org_address, is_online=is_online, order_count=order_count)
1583
 
1584
  # Загрузка контента
1585
  @app.route('/upload', methods=['GET', 'POST'])
 
1652
 
1653
  is_authenticated = 'username' in session
1654
  username = session.get('username', None)
1655
+ user_type = user_data.get('type')
1656
+ verified = user_data.get('verified', False)
1657
+ order_count = len(data['orders'].get(username, []))
1658
  html = '''
1659
  <!DOCTYPE html>
1660
  <html lang="ru">
 
1784
  </body>
1785
  </html>
1786
  '''
1787
+ return render_template_string(html, username=username, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count)
1788
 
1789
  # Заказы продавца
1790
+ @app.route('/seller_orders', methods=['GET', 'POST'])
1791
+ def seller_orders():
1792
  if 'username' not in session:
1793
  flash('Войдите, чтобы просмотреть заказы!', 'error')
1794
  return redirect(url_for('login'))
 
1804
  is_authenticated = 'username' in session
1805
  user_type = user_data.get('type')
1806
  verified = user_data.get('verified', False)
1807
+ order_count = len(orders)
1808
 
1809
  if request.method == 'POST':
1810
  if 'update_status' in request.form:
 
1813
  for order in orders:
1814
  if order['order_id'] == order_id:
1815
  order['status'] = new_status
1816
+ # Обновляем статус в заказах пользователя
1817
+ for user_order in data['user_orders'].get(order['buyer'], []):
1818
+ if user_order['order_id'] == order_id:
1819
+ user_order['status'] = new_status
1820
+ break
1821
  break
1822
  save_data(data)
1823
+ return redirect(url_for('seller_orders'))
1824
 
1825
  html = '''
1826
  <!DOCTYPE html>
 
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'] %}
1906
+ <p>Адрес доставки: {{ order['buyer_address'] }}</p>
1907
+ {% endif %}
1908
  <p>Дата: {{ order['date'] }}</p>
1909
  <form method="POST">
1910
  <input type="hidden" name="order_id" value="{{ order['order_id'] }}">
 
1937
  </body>
1938
  </html>
1939
  '''
1940
+ return render_template_string(html, username=username, orders=orders, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count)
1941
+
1942
+ # Мои заказы пользователя
1943
+ @app.route('/user_orders', methods=['GET'])
1944
+ def user_orders():
1945
+ if 'username' not in session:
1946
+ flash('Войдите, чтобы просмотреть свои заказы!', 'error')
1947
+ return redirect(url_for('login'))
1948
+
1949
+ data = load_data()
1950
+ username = session['username']
1951
+ user_data = data['users'].get(username, {})
1952
+ orders = data['user_orders'].get(username, [])
1953
+ is_authenticated = 'username' in session
1954
+ user_type = user_data.get('type')
1955
+ verified = user_data.get('verified', False)
1956
+ order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0
1957
+
1958
+ html = '''
1959
+ <!DOCTYPE html>
1960
+ <html lang="ru">
1961
+ <head>
1962
+ <meta charset="UTF-8">
1963
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1964
+ <title>Мои заказы - {{ username }}</title>
1965
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&display=swap" rel="stylesheet">
1966
+ <style>
1967
+ ''' + BASE_STYLE + '''
1968
+ .container {
1969
+ max-width: 950px;
1970
+ }
1971
+ h1 {
1972
+ font-size: 2.5em;
1973
+ font-weight: 700;
1974
+ margin-bottom: 40px;
1975
+ background: linear-gradient(45deg, var(--primary), var(--secondary));
1976
+ -webkit-background-clip: text;
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 {
1985
+ background: var(--card-bg-light);
1986
+ backdrop-filter: blur(20px);
1987
+ padding: 25px;
1988
+ border-radius: 20px;
1989
+ box-shadow: var(--shadow);
1990
+ transition: var(--transition);
1991
+ }
1992
+ body.dark .order-item {
1993
+ background: var(--card-bg-dark);
1994
+ }
1995
+ .order-item:hover {
1996
+ transform: translateY(-15px);
1997
+ }
1998
+ .order-item h3 {
1999
+ font-size: 1.5em;
2000
+ margin-bottom: 15px;
2001
+ }
2002
+ .order-item p {
2003
+ margin-bottom: 15px;
2004
+ font-size: 1.1em;
2005
+ }
2006
+ .price {
2007
+ font-weight: 600;
2008
+ color: var(--primary);
2009
+ }
2010
+ .username-link {
2011
+ color: var(--primary);
2012
+ font-weight: 600;
2013
+ text-decoration: none;
2014
+ }
2015
+ .username-link:hover {
2016
+ text-decoration: underline;
2017
+ }
2018
+ </style>
2019
+ </head>
2020
+ <body>
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">
2027
+ {% if 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>
2035
+ </div>
2036
+ {% endfor %}
2037
+ {% else %}
2038
+ <p style="font-size: 1.2em;">У вас пока нет заказов.</p>
2039
+ {% endif %}
2040
+ </div>
2041
+ </div>
2042
+ <script>
2043
+ function toggleSidebar() {
2044
+ document.getElementById('sidebar').classList.toggle('active');
2045
+ }
2046
+ function toggleTheme() {
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>
2055
+ </html>
2056
+ '''
2057
+ return render_template_string(html, username=username, orders=orders, is_authenticated=is_authenticated, user_type=user_type, verified=verified, order_count=order_count)
2058
 
2059
  # Админ-панель
2060
  @app.route('/admhosto', methods=['GET', 'POST'])
 
2066
  username = session.get('username', None)
2067
  user_type = data['users'].get(username, {}).get('type') if username else None
2068
  verified = data['users'].get(username, {}).get('verified', False) if username else False
2069
+ order_count = len(data['orders'].get(username, [])) if user_type == 'seller' and verified else 0
2070
 
2071
  if request.method == 'POST':
2072
  if 'delete' in request.form:
 
2094
  posts = [post for post in posts if search_query in post['title'].lower() or search_query in post['description'].lower()]
2095
 
2096
  html = '''
2097
+ <!DOCTYPE html>
2098
  <html lang="ru">
2099
  <head>
2100
  <meta charset="UTF-8">
 
2288
  </body>
2289
  </html>
2290
  '''
2291
+ return render_template_string(html, posts=posts, pending_orgs=pending_orgs, is_authenticated=is_authenticated, username=username, repo_id=REPO_ID, search_query=search_query, user_type=user_type, verified=verified, order_count=order_count)
2292
 
2293
  if __name__ == '__main__':
2294
  backup_thread = threading.Thread(target=periodic_backup, daemon=True)