Kgshop commited on
Commit
4c95d7d
·
verified ·
1 Parent(s): dbe39d0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -8
app.py CHANGED
@@ -26,6 +26,7 @@ HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
26
 
27
  WHATSAPP_NUMBER = "+77011333885"
28
  CURRENCY_CODE = 'T'
 
29
 
30
  def download_db_from_hf(specific_file=None, retries=3, delay=5):
31
  token_to_use = HF_TOKEN_READ if HF_TOKEN_READ else HF_TOKEN_WRITE
@@ -167,7 +168,10 @@ CATALOG_TEMPLATE = '''
167
  * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -webkit-tap-highlight-color: transparent; }
168
  body { background-color: var(--bg); color: var(--text); padding-bottom: calc(90px + env(safe-area-inset-bottom)); }
169
 
170
- .header { display: flex; align-items: center; justify-content: space-between; padding: max(15px, env(safe-area-inset-top)) 20px 15px; background: var(--surface); box-shadow: 0 2px 10px rgba(0,0,0,0.03); position: sticky; top: 0; z-index: 100; }
 
 
 
171
  .header h1 { font-size: 1.4rem; font-weight: 700; letter-spacing: -0.5px; }
172
  .back-btn { display: none; font-size: 1.2rem; cursor: pointer; color: var(--text); margin-right: 15px; padding: 5px; }
173
 
@@ -211,6 +215,11 @@ CATALOG_TEMPLATE = '''
211
  .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; }
212
  .modal-header h2 { font-size: 1.3rem; font-weight: 700; }
213
  .modal-close { font-size: 1.5rem; cursor: pointer; border: none; background: #f1f2f6; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--text); }
 
 
 
 
 
214
  .cart-item-list { display: flex; flex-direction: column; gap: 15px; margin-bottom: 25px; }
215
  .cart-item { display: flex; justify-content: space-between; align-items: center; background: var(--bg); padding: 15px; border-radius: 12px; }
216
  .cart-item-name { flex-grow: 1; font-size: 0.95rem; font-weight: 500; line-height: 1.3; margin-right: 15px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
@@ -228,6 +237,13 @@ CATALOG_TEMPLATE = '''
228
  .gallery-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,0.3); transition: background 0.3s; }
229
  .gallery-dot.active { background: #fff; }
230
 
 
 
 
 
 
 
 
231
  @media (min-width: 768px) {
232
  .categories-container { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
233
  .products-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); }
@@ -238,6 +254,10 @@ CATALOG_TEMPLATE = '''
238
  </style>
239
  </head>
240
  <body>
 
 
 
 
241
  <div class="header">
242
  <div style="display: flex; align-items: center;">
243
  <i class="fas fa-arrow-left back-btn" id="backBtn" onclick="showCategories()"></i>
@@ -255,6 +275,12 @@ CATALOG_TEMPLATE = '''
255
  <div class="categories-container" id="categoriesContainer"></div>
256
  <div class="products-container" id="productsContainer"></div>
257
 
 
 
 
 
 
 
258
  <div class="cart-bar" id="cartBar">
259
  <div class="cart-info">
260
  <span style="font-size: 0.85rem; color: var(--text-muted); font-weight: 500;">Сумма заказа:</span>
@@ -270,6 +296,13 @@ CATALOG_TEMPLATE = '''
270
  <button class="modal-close" onclick="closeCartModal()"><i class="fas fa-times"></i></button>
271
  </div>
272
  <div class="cart-item-list" id="cartItemList"></div>
 
 
 
 
 
 
 
273
  <button class="confirm-btn" onclick="submitOrder()">Оформить заказ</button>
274
  </div>
275
  </div>
@@ -474,6 +507,16 @@ CATALOG_TEMPLATE = '''
474
  function submitOrder() {
475
  const cartArray = Object.values(cart);
476
  if(cartArray.length === 0) return;
 
 
 
 
 
 
 
 
 
 
477
  const btn = document.querySelector('.confirm-btn');
478
  btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Оформление...';
479
  btn.disabled = true;
@@ -481,7 +524,12 @@ CATALOG_TEMPLATE = '''
481
  fetch('/create_order', {
482
  method: 'POST',
483
  headers: { 'Content-Type': 'application/json' },
484
- body: JSON.stringify({ cart: cartArray })
 
 
 
 
 
485
  })
486
  .then(r => r.json())
487
  .then(data => {
@@ -575,7 +623,9 @@ ORDER_TEMPLATE = '''
575
  .invoice-box { background: var(--surface); width: 100%; max-width: 900px; padding: 30px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); border-radius: 16px; }
576
  .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; border-bottom: 2px solid var(--border); padding-bottom: 15px; flex-wrap: wrap; gap: 10px; }
577
  .header h1 { margin: 0; font-size: 1.8rem; font-weight: 800; }
578
- .info-row { display: flex; justify-content: space-between; margin-bottom: 15px; font-size: 1rem; font-weight: 600; flex-wrap: wrap; gap: 10px; }
 
 
579
 
580
  .table-responsive { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 20px; border-radius: 8px; border: 1px solid var(--border); }
581
  table { width: 100%; border-collapse: collapse; min-width: 500px; }
@@ -612,6 +662,10 @@ ORDER_TEMPLATE = '''
612
  </head>
613
  <body>
614
  <div class="invoice-box">
 
 
 
 
615
  <div class="header">
616
  <h1>Накладная</h1>
617
  <div style="text-align: right;">
@@ -621,8 +675,12 @@ ORDER_TEMPLATE = '''
621
  </div>
622
 
623
  <div class="info-row">
624
- <div>Покупатель: _________________</div>
625
- <div>Статус: <span style="color: #00b894;">Новый</span></div>
 
 
 
 
626
  </div>
627
 
628
  <div class="table-responsive">
@@ -956,7 +1014,8 @@ def catalog():
956
  products_json=json.dumps(all_products),
957
  categories_json=json.dumps(categories),
958
  repo_id=REPO_ID,
959
- currency_code=CURRENCY_CODE
 
960
  )
961
 
962
  @app.route('/create_order', methods=['POST'])
@@ -967,6 +1026,10 @@ def create_order():
967
 
968
  cart_items = order_data['cart']
969
  total_price = sum(float(item['price']) * int(item['quantity']) for item in cart_items)
 
 
 
 
970
 
971
  processed_cart = []
972
  for item in cart_items:
@@ -983,7 +1046,10 @@ def create_order():
983
  "id": order_id,
984
  "created_at": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
985
  "cart": processed_cart,
986
- "total_price": total_price
 
 
 
987
  }
988
 
989
  data = load_data()
@@ -1003,7 +1069,8 @@ def view_order(order_id):
1003
  ORDER_TEMPLATE,
1004
  order=order,
1005
  whatsapp_number=WHATSAPP_NUMBER,
1006
- currency_code=CURRENCY_CODE
 
1007
  )
1008
 
1009
  @app.route('/admin', methods=['GET', 'POST'])
 
26
 
27
  WHATSAPP_NUMBER = "+77011333885"
28
  CURRENCY_CODE = 'T'
29
+ LOGO_URL = "https://huggingface.co/spaces/Metapp/Tech/resolve/main/1776929812446-019db944-b5db-7524-8f44-73942d70a0f8.png"
30
 
31
  def download_db_from_hf(specific_file=None, retries=3, delay=5):
32
  token_to_use = HF_TOKEN_READ if HF_TOKEN_READ else HF_TOKEN_WRITE
 
168
  * { margin: 0; padding: 0; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; -webkit-tap-highlight-color: transparent; }
169
  body { background-color: var(--bg); color: var(--text); padding-bottom: calc(90px + env(safe-area-inset-bottom)); }
170
 
171
+ .top-logo-container { background: var(--surface); padding: max(15px, env(safe-area-inset-top)) 20px 10px; text-align: center; border-bottom: 1px solid var(--border); }
172
+ .top-logo { max-width: 100%; height: auto; max-height: 80px; object-fit: contain; }
173
+
174
+ .header { display: flex; align-items: center; justify-content: space-between; padding: 15px 20px; background: var(--surface); box-shadow: 0 2px 10px rgba(0,0,0,0.03); position: sticky; top: 0; z-index: 100; }
175
  .header h1 { font-size: 1.4rem; font-weight: 700; letter-spacing: -0.5px; }
176
  .back-btn { display: none; font-size: 1.2rem; cursor: pointer; color: var(--text); margin-right: 15px; padding: 5px; }
177
 
 
215
  .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; }
216
  .modal-header h2 { font-size: 1.3rem; font-weight: 700; }
217
  .modal-close { font-size: 1.5rem; cursor: pointer; border: none; background: #f1f2f6; width: 36px; height: 36px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: var(--text); }
218
+
219
+ .customer-form { display: flex; flex-direction: column; gap: 12px; margin-bottom: 25px; }
220
+ .customer-form input { padding: 14px; border: 1px solid var(--border); border-radius: 12px; font-size: 0.95rem; background: var(--bg); outline: none; transition: border-color 0.2s; }
221
+ .customer-form input:focus { border-color: var(--primary); background: var(--surface); }
222
+
223
  .cart-item-list { display: flex; flex-direction: column; gap: 15px; margin-bottom: 25px; }
224
  .cart-item { display: flex; justify-content: space-between; align-items: center; background: var(--bg); padding: 15px; border-radius: 12px; }
225
  .cart-item-name { flex-grow: 1; font-size: 0.95rem; font-weight: 500; line-height: 1.3; margin-right: 15px; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
 
237
  .gallery-dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,0.3); transition: background 0.3s; }
238
  .gallery-dot.active { background: #fff; }
239
 
240
+ .floating-socials { position: fixed; bottom: max(100px, calc(100px + env(safe-area-inset-bottom))); right: 15px; display: flex; flex-direction: column; gap: 12px; z-index: 90; }
241
+ .social-btn { width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: white; font-size: 1.6rem; text-decoration: none; box-shadow: 0 4px 12px rgba(0,0,0,0.25); transition: transform 0.2s; }
242
+ .social-btn:active { transform: scale(0.9); }
243
+ .btn-float-wa { background: #25D366; }
244
+ .btn-float-ig { background: radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%, #d6249f 60%, #285AEB 90%); }
245
+ .btn-float-tg { background: #0088cc; }
246
+
247
  @media (min-width: 768px) {
248
  .categories-container { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
249
  .products-container { display: grid; grid-template-columns: repeat(auto-fill, minmax(350px, 1fr)); }
 
254
  </style>
255
  </head>
256
  <body>
257
+ <div class="top-logo-container">
258
+ <img src="{{ logo_url }}" class="top-logo" alt="Логотип">
259
+ </div>
260
+
261
  <div class="header">
262
  <div style="display: flex; align-items: center;">
263
  <i class="fas fa-arrow-left back-btn" id="backBtn" onclick="showCategories()"></i>
 
275
  <div class="categories-container" id="categoriesContainer"></div>
276
  <div class="products-container" id="productsContainer"></div>
277
 
278
+ <div class="floating-socials">
279
+ <a href="https://wa.me/77011333885" class="social-btn btn-float-wa" target="_blank"><i class="fab fa-whatsapp"></i></a>
280
+ <a href="https://instagram.com/14sklad_baisat" class="social-btn btn-float-ig" target="_blank"><i class="fab fa-instagram"></i></a>
281
+ <a href="https://t.me/posuda15konteiner" class="social-btn btn-float-tg" target="_blank"><i class="fab fa-telegram-plane"></i></a>
282
+ </div>
283
+
284
  <div class="cart-bar" id="cartBar">
285
  <div class="cart-info">
286
  <span style="font-size: 0.85rem; color: var(--text-muted); font-weight: 500;">Сумма заказа:</span>
 
296
  <button class="modal-close" onclick="closeCartModal()"><i class="fas fa-times"></i></button>
297
  </div>
298
  <div class="cart-item-list" id="cartItemList"></div>
299
+
300
+ <div class="customer-form">
301
+ <input type="text" id="custName" placeholder="Ваше Имя" required>
302
+ <input type="text" id="custPhone" placeholder="Номер телефона" required>
303
+ <input type="text" id="custCity" placeholder="Город" required>
304
+ </div>
305
+
306
  <button class="confirm-btn" onclick="submitOrder()">Оформить заказ</button>
307
  </div>
308
  </div>
 
507
  function submitOrder() {
508
  const cartArray = Object.values(cart);
509
  if(cartArray.length === 0) return;
510
+
511
+ const name = document.getElementById('custName').value.trim();
512
+ const phone = document.getElementById('custPhone').value.trim();
513
+ const city = document.getElementById('custCity').value.trim();
514
+
515
+ if(!name || !phone || !city) {
516
+ alert('Пожалуйста, заполните все поля (Имя, Телефон, Город)');
517
+ return;
518
+ }
519
+
520
  const btn = document.querySelector('.confirm-btn');
521
  btn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Оформление...';
522
  btn.disabled = true;
 
524
  fetch('/create_order', {
525
  method: 'POST',
526
  headers: { 'Content-Type': 'application/json' },
527
+ body: JSON.stringify({
528
+ cart: cartArray,
529
+ customer_name: name,
530
+ customer_phone: phone,
531
+ customer_city: city
532
+ })
533
  })
534
  .then(r => r.json())
535
  .then(data => {
 
623
  .invoice-box { background: var(--surface); width: 100%; max-width: 900px; padding: 30px; box-shadow: 0 4px 20px rgba(0,0,0,0.05); border-radius: 16px; }
624
  .header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 25px; border-bottom: 2px solid var(--border); padding-bottom: 15px; flex-wrap: wrap; gap: 10px; }
625
  .header h1 { margin: 0; font-size: 1.8rem; font-weight: 800; }
626
+ .info-row { display: flex; justify-content: space-between; margin-bottom: 20px; font-size: 1rem; flex-wrap: wrap; gap: 15px; }
627
+ .customer-details { display: flex; flex-direction: column; gap: 6px; }
628
+ .customer-details span { font-weight: 600; color: #1a1a1a; }
629
 
630
  .table-responsive { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: 20px; border-radius: 8px; border: 1px solid var(--border); }
631
  table { width: 100%; border-collapse: collapse; min-width: 500px; }
 
662
  </head>
663
  <body>
664
  <div class="invoice-box">
665
+ <div style="text-align: center; margin-bottom: 25px;">
666
+ <img src="{{ logo_url }}" style="max-height: 80px; max-width: 100%; object-fit: contain;">
667
+ </div>
668
+
669
  <div class="header">
670
  <h1>Накладная</h1>
671
  <div style="text-align: right;">
 
675
  </div>
676
 
677
  <div class="info-row">
678
+ <div class="customer-details">
679
+ <div>Покупатель: <span>{{ order.customer_name }}</span></div>
680
+ <div>Телефон: <span>{{ order.customer_phone }}</span></div>
681
+ <div>Город: <span>{{ order.customer_city }}</span></div>
682
+ </div>
683
+ <div style="font-weight: 600;">Статус: <span style="color: #00b894;">Новый</span></div>
684
  </div>
685
 
686
  <div class="table-responsive">
 
1014
  products_json=json.dumps(all_products),
1015
  categories_json=json.dumps(categories),
1016
  repo_id=REPO_ID,
1017
+ currency_code=CURRENCY_CODE,
1018
+ logo_url=LOGO_URL
1019
  )
1020
 
1021
  @app.route('/create_order', methods=['POST'])
 
1026
 
1027
  cart_items = order_data['cart']
1028
  total_price = sum(float(item['price']) * int(item['quantity']) for item in cart_items)
1029
+
1030
+ customer_name = order_data.get('customer_name', 'Не указано')
1031
+ customer_phone = order_data.get('customer_phone', 'Не указано')
1032
+ customer_city = order_data.get('customer_city', 'Не указано')
1033
 
1034
  processed_cart = []
1035
  for item in cart_items:
 
1046
  "id": order_id,
1047
  "created_at": datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
1048
  "cart": processed_cart,
1049
+ "total_price": total_price,
1050
+ "customer_name": customer_name,
1051
+ "customer_phone": customer_phone,
1052
+ "customer_city": customer_city
1053
  }
1054
 
1055
  data = load_data()
 
1069
  ORDER_TEMPLATE,
1070
  order=order,
1071
  whatsapp_number=WHATSAPP_NUMBER,
1072
+ currency_code=CURRENCY_CODE,
1073
+ logo_url=LOGO_URL
1074
  )
1075
 
1076
  @app.route('/admin', methods=['GET', 'POST'])