Kgshop commited on
Commit
8d8ebcc
·
verified ·
1 Parent(s): 6a7469c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +262 -23
app.py CHANGED
@@ -11,9 +11,9 @@ from huggingface_hub.utils import RepositoryNotFoundError
11
  from werkzeug.utils import secure_filename
12
 
13
  app = Flask(__name__)
14
- DATA_FILE = 'data_kanc.json'
15
 
16
- REPO_ID = "Kgshop/clients"
17
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
18
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
19
 
@@ -105,7 +105,7 @@ def catalog():
105
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
106
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/10.2.0/swiper-bundle.min.css">
107
  <style>
108
- * {
109
  margin: 0;
110
  padding: 0;
111
  box-sizing: border-box;
@@ -480,7 +480,6 @@ def catalog():
480
  font-weight: 500;
481
  }
482
 
483
- /* Styles for Address and Schedule */
484
  .info-section {
485
  text-align: center;
486
  margin: 20px 0;
@@ -811,15 +810,218 @@ def catalog():
811
  </body>
812
  </html>
813
  '''
814
- return render_template_string(favorites_html, products=products, repo_id=REPO_ID)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
 
 
 
 
 
 
 
 
 
816
 
817
- @app.route('/discounts')
818
- def discounts_page():
819
  data = load_data()
820
- products = [p for p in data['products'] if p.get('discount')]
821
 
822
- discounts_html = '''
823
  <!DOCTYPE html>
824
  <html lang="ru">
825
  <head>
@@ -1277,10 +1479,11 @@ def discounts_page():
1277
  <i class="fas fa-heart"></i>
1278
  Избранное
1279
  </a>
1280
- <a href="/discounts" class="active">
1281
  <i class="fas fa-tag"></i>
1282
  Скидки
1283
  </a>
 
1284
  <a href="https://api.whatsapp.com/send?phone=996700666692">
1285
  <i class="fab fa-whatsapp"></i>
1286
  WhatsApp
@@ -1307,6 +1510,51 @@ def discounts_page():
1307
  document.querySelector('.theme-toggle i').classList.replace('fa-moon', 'fa-sun');
1308
  }
1309
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1310
  function openModal(index) {
1311
  loadProductDetails(index);
1312
  document.getElementById('productModal').style.display = "block";
@@ -1467,16 +1715,7 @@ def discounts_page():
1467
  favoriteButton.classList.add('favorited');
1468
  }
1469
  localStorage.setItem('favorites', JSON.stringify(favorites));
1470
- }
1471
-
1472
- function loadFavorites() {
1473
- const favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
1474
- document.querySelectorAll('.favorite-button').forEach(button => {
1475
- const index = button.getAttribute('onclick').match(/\d+/)[0];
1476
- if (favorites.includes(index)) {
1477
- button.classList.add('favorited');
1478
- }
1479
- });
1480
  }
1481
 
1482
  window.onclick = function(event) {
@@ -1484,7 +1723,7 @@ def discounts_page():
1484
  }
1485
 
1486
  updateCartButton();
1487
- loadFavorites();
1488
  </script>
1489
  </body>
1490
  </html>
@@ -1630,7 +1869,7 @@ def admin():
1630
  filename = secure_filename(photo.filename)
1631
  api = HfApi()
1632
  api.upload_file(
1633
- path_or_fileobj=photo,
1634
  path_in_repo=f"photos/{filename}",
1635
  repo_id=REPO_ID,
1636
  repo_type="dataset",
@@ -1661,7 +1900,7 @@ def admin():
1661
  filename = secure_filename(photo.filename)
1662
  api = HfApi()
1663
  api.upload_file(
1664
- path_or_fileobj=photo,
1665
  path_in_repo=f"photos/{filename}",
1666
  repo_id=REPO_ID,
1667
  repo_type="dataset",
 
11
  from werkzeug.utils import secure_filename
12
 
13
  app = Flask(__name__)
14
+ DATA_FILE = 'data_firecollection.json'
15
 
16
+ REPO_ID = "Kgshop/Clients2"
17
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
18
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
19
 
 
105
  <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
106
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/10.2.0/swiper-bundle.min.css">
107
  <style>
108
+ * {
109
  margin: 0;
110
  padding: 0;
111
  box-sizing: border-box;
 
480
  font-weight: 500;
481
  }
482
 
 
483
  .info-section {
484
  text-align: center;
485
  margin: 20px 0;
 
810
  </body>
811
  </html>
812
  '''
813
+ return render_template_string(catalog_html, products=products, repo_id=REPO_ID)
814
+
815
+ @app.route('/categories')
816
+ def categories_page():
817
+ data = load_data()
818
+ categories = data['categories']
819
+
820
+ categories_html = '''
821
+ <!DOCTYPE html>
822
+ <html lang="ru">
823
+ <head>
824
+ <meta charset="UTF-8">
825
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
826
+ <title>Fire collection</title>
827
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
828
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
829
+ <style>
830
+ * {
831
+ margin: 0;
832
+ padding: 0;
833
+ box-sizing: border-box;
834
+ }
835
+ body {
836
+ font-family: 'Roboto', sans-serif;
837
+ background: linear-gradient(135deg, #f5f7fa, #e4e7eb);
838
+ color: #333;
839
+ line-height: 1.6;
840
+ transition: background 0.3s, color 0.3s;
841
+ padding-bottom: 60px;
842
+ }
843
+ body.dark-mode {
844
+ background: linear-gradient(135deg, #1a1a2e, #2a2a3e);
845
+ color: #e0e0e0;
846
+ }
847
+ .container {
848
+ max-width: 1400px;
849
+ margin: 0 auto;
850
+ padding: 20px;
851
+ }
852
+ .header {
853
+ display: flex;
854
+ justify-content: space-between;
855
+ align-items: center;
856
+ padding: 15px 0;
857
+ border-bottom: 1px solid rgba(0, 0, 0, 0.1);
858
+ }
859
+ .header h1 {
860
+ font-size: 2rem;
861
+ font-weight: 700;
862
+ letter-spacing: 1px;
863
+ background: linear-gradient(90deg, #526df2, #7a8ff5);
864
+ -webkit-background-clip: text;
865
+ -webkit-text-fill-color: transparent;
866
+ }
867
+ .theme-toggle {
868
+ background: none;
869
+ border: none;
870
+ font-size: 1.5rem;
871
+ cursor: pointer;
872
+ color: #666;
873
+ transition: color 0.3s ease;
874
+ }
875
+ .theme-toggle:hover {
876
+ color: #526df2;
877
+ }
878
+ body.dark-mode .theme-toggle {
879
+ color: #bbb;
880
+ }
881
+ .categories-grid {
882
+ display: grid;
883
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
884
+ gap: 20px;
885
+ padding: 10px;
886
+ }
887
+ .category-item {
888
+ background: rgba(255, 255, 255, 0.8);
889
+ border: 1px solid rgba(0, 0, 0, 0.05);
890
+ border-radius: 15px;
891
+ padding: 20px;
892
+ text-align: center;
893
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
894
+ transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease, background 0.3s ease;
895
+ text-decoration: none;
896
+ color: #333;
897
+ }
898
+ body.dark-mode .category-item {
899
+ background: rgba(42, 42, 62, 0.8);
900
+ border-color: rgba(255, 255, 255, 0.05);
901
+ color: #e0e0e0;
902
+ }
903
+ .category-item:hover {
904
+ transform: translateY(-5px);
905
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
906
+ background: rgba(255, 255, 255, 0.9);
907
+ background-color: #526df2;
908
+ color: white;
909
+ }
910
+ body.dark-mode .category-item:hover {
911
+ background: rgba(42, 42, 62, 0.9);
912
+ box-shadow: 0 8px 25px rgba(255, 255, 255, 0.1);
913
+ }
914
+ .category-item h2 {
915
+ font-size: 1.2rem;
916
+ font-weight: 500;
917
+ }
918
+ .navbar {
919
+ position: fixed;
920
+ bottom: 0;
921
+ left: 0;
922
+ width: 100%;
923
+ background-color: #fff;
924
+ box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
925
+ display: flex;
926
+ justify-content: space-around;
927
+ padding: 10px 0;
928
+ z-index: 1000;
929
+ }
930
+ body.dark-mode .navbar {
931
+ background-color: #2a2a3e;
932
+ }
933
+ .navbar a {
934
+ text-align: center;
935
+ color: #666;
936
+ text-decoration: none;
937
+ font-size: 0.9rem;
938
+ transition: color 0.3s ease;
939
+ }
940
+ .navbar a.active {
941
+ color: #526df2;
942
+ }
943
+ .navbar a i {
944
+ display: block;
945
+ font-size: 1.5rem;
946
+ margin-bottom: 5px;
947
+ }
948
+ body.dark-mode .navbar a {
949
+ color: #bbb;
950
+ }
951
+ .navbar a:hover {
952
+ color: #526df2;
953
+ }
954
+ </style>
955
+ </head>
956
+ <body>
957
+ <div class="container">
958
+ <div class="header">
959
+ <img src="https://huggingface.co/spaces/Kgshop/Fire-collection/resolve/main/Picsart_25-03-25_11-40-25-730.jpg" alt="Fire collection Logo" style="max-height: 50px;">
960
+ <button class="theme-toggle" onclick="toggleTheme()">
961
+ <i class="fas fa-moon"></i>
962
+ </button>
963
+ </div>
964
+ <div class="categories-grid">
965
+ {% for category in categories %}
966
+ <a href="{{ url_for('category_products', category=category) }}" class="category-item">
967
+ <h2>{{ category }}</h2>
968
+ </a>
969
+ {% endfor %}
970
+ </div>
971
+ </div>
972
+
973
+ <div class="navbar">
974
+ <a href="/">
975
+ <i class="fas fa-home"></i>
976
+ Главная
977
+ </a>
978
+ <a href="/categories" class="active">
979
+ <i class="fas fa-list"></i>
980
+ Каталог
981
+ </a>
982
+ <a href="/favorites">
983
+ <i class="fas fa-heart"></i>
984
+ Избранное
985
+ </a>
986
+ <a href="/discounts">
987
+ <i class="fas fa-tag"></i>
988
+ Скидки
989
+ </a>
990
+ <a href="https://api.whatsapp.com/send?phone=996700666692">
991
+ <i class="fab fa-whatsapp"></i>
992
+ WhatsApp
993
+ </a>
994
+ </div>
995
+
996
+ <script>
997
+ function toggleTheme() {
998
+ document.body.classList.toggle('dark-mode');
999
+ const icon = document.querySelector('.theme-toggle i');
1000
+ icon.classList.toggle('fa-moon');
1001
+ icon.classList.toggle('fa-sun');
1002
+ localStorage.setItem('theme', document.body.classList.contains('dark-mode') ? 'dark' : 'light');
1003
+ }
1004
+
1005
+ if (localStorage.getItem('theme') === 'dark') {
1006
+ document.body.classList.add('dark-mode');
1007
+ document.querySelector('.theme-toggle i').classList.replace('fa-moon', 'fa-sun');
1008
+ }
1009
 
1010
+ window.onclick = function(event) {
1011
+ if (event.target.className === 'modal') event.target.style.display = "none";
1012
+ }
1013
+ </script>
1014
+ </body>
1015
+ </html>
1016
+ '''
1017
+ return render_template_string(categories_html, categories=categories)
1018
 
1019
+ @app.route('/category/<category>')
1020
+ def category_products(category):
1021
  data = load_data()
1022
+ products = [p for p in data['products'] if p.get('category') == category]
1023
 
1024
+ category_html = '''
1025
  <!DOCTYPE html>
1026
  <html lang="ru">
1027
  <head>
 
1479
  <i class="fas fa-heart"></i>
1480
  Избранное
1481
  </a>
1482
+ <a href="/discounts">
1483
  <i class="fas fa-tag"></i>
1484
  Скидки
1485
  </a>
1486
+
1487
  <a href="https://api.whatsapp.com/send?phone=996700666692">
1488
  <i class="fab fa-whatsapp"></i>
1489
  WhatsApp
 
1510
  document.querySelector('.theme-toggle i').classList.replace('fa-moon', 'fa-sun');
1511
  }
1512
 
1513
+ function loadFavoritesPage() {
1514
+ const favorites = JSON.parse(localStorage.getItem('favorites') || '[]');
1515
+ const productsGrid = document.getElementById('products-grid');
1516
+ productsGrid.innerHTML = '';
1517
+
1518
+ if (favorites.length === 0) {
1519
+ productsGrid.innerHTML = '<p>Избранное пусто</p>';
1520
+ return;
1521
+ }
1522
+
1523
+ favorites.forEach(index => {
1524
+ const product = products[index];
1525
+ if (!product) return;
1526
+ const productElement = document.createElement('div');
1527
+ productElement.className = 'product';
1528
+ productElement.setAttribute('onclick', `openModal(${index})`);
1529
+ productElement.setAttribute('data-name', product.name.toLowerCase());
1530
+ productElement.setAttribute('data-description', product.description.toLowerCase());
1531
+ productElement.setAttribute('data-category', product.category || 'Без категории');
1532
+ productElement.innerHTML = `
1533
+ <button class="favorite-button favorited" onclick="event.stopPropagation(); toggleFavorite(${index})">
1534
+ <i class="fas fa-heart"></i>
1535
+ </button>
1536
+ ${product.photos && product.photos.length > 0 ? `
1537
+ <div class="product-image">
1538
+ <img src="https://huggingface.co/datasets/{{ repo_id }}/resolve/main/photos/${product.photos[0]}" alt="${product.name}" loading="lazy">
1539
+ </div>` : ''}
1540
+ ${product.discount ? `<span class="discount-badge">Скидка ${product.discount}%</span>` : ''}
1541
+ <h2>${product.name}</h2>
1542
+ <div class="product-price">
1543
+ {% if product.get('discount') %}
1544
+ <span style="text-decoration: line-through; color: #666;">{{ product['price'] }} с</span>
1545
+ <span>{{ (product['price'] * (1 - product.discount / 100)).toFixed(2)} с</span>
1546
+ <span class="discount">Скидка: {{ product['discount'] }}%</span>
1547
+ {% else %}
1548
+ <span>{{ product['price'] }} с</span>
1549
+ {% endif %}
1550
+ </div>
1551
+ <p class="product-description">${product.description.slice(0, 50)}${product.description.length > 50 ? '...' : ''}</p>
1552
+ <button class="product-button add-to-cart" onclick="event.stopPropagation(); openQuantityModal(${index})">В корзину</button>
1553
+ `;
1554
+ productsGrid.appendChild(productElement);
1555
+ });
1556
+ }
1557
+
1558
  function openModal(index) {
1559
  loadProductDetails(index);
1560
  document.getElementById('productModal').style.display = "block";
 
1715
  favoriteButton.classList.add('favorited');
1716
  }
1717
  localStorage.setItem('favorites', JSON.stringify(favorites));
1718
+ loadFavoritesPage();
 
 
 
 
 
 
 
 
 
1719
  }
1720
 
1721
  window.onclick = function(event) {
 
1723
  }
1724
 
1725
  updateCartButton();
1726
+ loadFavoritesPage();
1727
  </script>
1728
  </body>
1729
  </html>
 
1869
  filename = secure_filename(photo.filename)
1870
  api = HfApi()
1871
  api.upload_file(
1872
+ path_or_fileobj=photo.stream, # Use photo.stream instead of photo
1873
  path_in_repo=f"photos/{filename}",
1874
  repo_id=REPO_ID,
1875
  repo_type="dataset",
 
1900
  filename = secure_filename(photo.filename)
1901
  api = HfApi()
1902
  api.upload_file(
1903
+ path_or_fileobj=photo.stream, # Use photo.stream instead of photo
1904
  path_in_repo=f"photos/{filename}",
1905
  repo_id=REPO_ID,
1906
  repo_type="dataset",