Shveiauto commited on
Commit
ade9684
·
verified ·
1 Parent(s): 38414d6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -73
app.py CHANGED
@@ -16,7 +16,7 @@ import uuid
16
  load_dotenv()
17
 
18
  app = Flask(__name__)
19
- app.secret_key = 'dalarssi_secret_key_no_login'
20
  DATA_FILE = 'data.json'
21
 
22
 
@@ -26,7 +26,7 @@ REPO_ID = "Kgshop/manolisa"
26
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
27
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
28
 
29
- STORE_ADDRESS = ""
30
 
31
  CURRENCY_CODE = 'USD'
32
  CURRENCY_NAME = 'доллар'
@@ -38,8 +38,8 @@ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(
38
 
39
  translations = {
40
  'ru': {
41
- 'site_title': "dalarssi - Каталог",
42
- 'brand_name': "dalarssi",
43
  'our_address': "Наш адрес:",
44
  'all_categories': "Все категории",
45
  'search_placeholder': "Поиск по названию или описанию...",
@@ -86,7 +86,7 @@ translations = {
86
  'order_status_desc': "Этот заказ был оформлен без входа в систему. Пожалуйста, свяжитесь с нами по WhatsApp для подтверждения и уточнения деталей.",
87
  'send_order': "Отправить заказ",
88
  'back_to_catalog': "← Вернуться в каталог",
89
- 'whatsapp_greeting': "Здравствуйте! Хочу подтвердить свой заказ на dalarssi:",
90
  'whatsapp_order_number': "Номер заказа:",
91
  'whatsapp_order_link': "Ссылка на заказ:",
92
  'whatsapp_contact_me': "Пожалуйста, свяжитесь со мной для уточнения деталей оплаты и доставки.",
@@ -99,14 +99,12 @@ translations = {
99
  'favorites': 'Избранное',
100
  'employee': 'Сотрудник:',
101
  'online_order': 'Онлайн',
102
- 'address_1_title': 'Адрес 1:',
103
- 'address_1_detail': 'рынок Олжа, VIP ряд, 109 бутик',
104
- 'address_2_title': 'Адрес 2:',
105
- 'address_2_detail': 'рынок Олжа, VIP ряд, 56 бутик',
106
  },
107
  'kk': {
108
- 'site_title': "dalarssi - Каталог",
109
- 'brand_name': "dalarssi",
110
  'our_address': "Біздің мекенжайымыз:",
111
  'all_categories': "Барлық санаттар",
112
  'search_placeholder': "Аты немесе сипаттамасы бойынша іздеу...",
@@ -153,7 +151,7 @@ translations = {
153
  'order_status_desc': "Бұл тапсырыс жүйеге кірмей рәсімделді. Растау және мәліметтерді нақтылау үшін WhatsApp арқылы бізбен хабарласыңыз.",
154
  'send_order': "Тапсырысты жіберу",
155
  'back_to_catalog': "← Каталогқа оралу",
156
- 'whatsapp_greeting': "Сәлеметсіз бе! Мен dalarssi-дегі тапсырысымды растағым келеді:",
157
  'whatsapp_order_number': "Тапсырыс нөмірі:",
158
  'whatsapp_order_link': "Тапсырысқа сілтеме:",
159
  'whatsapp_contact_me': "Төлем және жеткізу мәліметтерін нақтылау үшін менімен хабарласыңыз.",
@@ -166,10 +164,8 @@ translations = {
166
  'favorites': 'Таңдаулылар',
167
  'employee': 'Қызметкер:',
168
  'online_order': 'Онлайн',
169
- 'address_1_title': 'Мекенжай 1:',
170
- 'address_1_detail': 'Олжа базары, VIP қатары, 109 бутик',
171
- 'address_2_title': 'Мекенжай 2:',
172
- 'address_2_detail': 'Олжа базары, VIP қатары, 56 бутик',
173
  }
174
  }
175
 
@@ -375,9 +371,9 @@ CATALOG_TEMPLATE = '''
375
  :root {
376
  --bg-color: #1a1a1a;
377
  --surface-color: #2b2b2b;
378
- --primary-accent: #D99ECB;
379
- --primary-accent-hover: #C874B2;
380
- --secondary-accent: #6f4e37;
381
  --text-color: #f0e6e6;
382
  --text-muted: #a09a9a;
383
  }
@@ -393,7 +389,7 @@ CATALOG_TEMPLATE = '''
393
  .filters-container { margin: 25px 0; display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
394
  .search-container { margin: 25px 0; text-align: center; }
395
  #search-input { width: 90%; max-width: 600px; padding: 14px 22px; font-size: 1rem; border: 1px solid var(--secondary-accent); border-radius: 30px; outline: none; transition: all 0.3s ease; background-color: var(--surface-color); color: var(--text-color); }
396
- #search-input:focus { border-color: var(--primary-accent); box-shadow: 0 0 0 4px rgba(217, 158, 203, 0.2); }
397
  .category-filter { padding: 10px 20px; border: 1px solid var(--secondary-accent); border-radius: 30px; background-color: transparent; cursor: pointer; transition: all 0.3s ease; font-size: 0.9rem; font-weight: 600; color: var(--text-muted); }
398
  .category-filter.active, .category-filter:hover { background-color: var(--primary-accent); color: var(--bg-color); border-color: var(--primary-accent); }
399
  .products-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; padding: 10px; }
@@ -415,7 +411,7 @@ CATALOG_TEMPLATE = '''
415
  .product-button { display: block; width: 100%; padding: 12px; border: none; border-radius: 8px; background-color: var(--primary-accent); color: var(--bg-color); font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; text-align: center; text-decoration: none; }
416
  .product-button:hover { background-color: var(--primary-accent-hover); }
417
  .product-button i { margin-right: 8px; }
418
- #cart-button { position: fixed; bottom: 90px; right: 30px; background-color: var(--primary-accent); color: var(--bg-color); border: none; border-radius: 50%; width: 60px; height: 60px; font-size: 1.6rem; cursor: pointer; display: none; align-items: center; justify-content: center; box-shadow: 0 5px 20px rgba(217, 158, 203, 0.3); transition: all 0.3s ease; z-index: 1000; }
419
  #cart-button:hover { transform: scale(1.1); }
420
  #cart-button span { position: absolute; top: 0px; right: 0px; background-color: var(--secondary-accent); color: var(--text-color); border-radius: 50%; padding: 3px 7px; font-size: 0.8rem; font-weight: bold; }
421
  .modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.7); backdrop-filter: blur(8px); overflow-y: auto; }
@@ -442,7 +438,7 @@ CATALOG_TEMPLATE = '''
442
  .notification { position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%); background-color: var(--primary-accent); color: var(--bg-color); padding: 12px 25px; border-radius: 30px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); z-index: 1002; opacity: 0; transition: opacity 0.5s ease; font-size: 1rem; font-weight: 600;}
443
  .notification.show { opacity: 1;}
444
  .no-results-message { grid-column: 1 / -1; text-align: center; padding: 50px; font-size: 1.2rem; color: var(--text-muted); }
445
- .top-product-indicator { position: absolute; top: 12px; right: 12px; background-color: rgba(217, 158, 203, 0.9); color: var(--bg-color); padding: 4px 10px; font-size: 0.8rem; border-radius: 20px; font-weight: bold; z-index: 10; backdrop-filter: blur(3px); }
446
  .favorite-button { position: absolute; top: 12px; left: 12px; background: none; border: none; color: var(--text-color); font-size: 1.5rem; cursor: pointer; z-index: 10; padding: 5px; line-height: 1; transition: color 0.3s, transform 0.3s; text-shadow: 0 0 5px rgba(0,0,0,0.5); }
447
  .favorite-button.favorited { color: #e91e63; transform: scale(1.1); }
448
  .favorite-button:hover { transform: scale(1.2); }
@@ -590,7 +586,6 @@ CATALOG_TEMPLATE = '''
590
  <h2><i class="fas fa-map-marker-alt"></i> {{ _('addresses') }}</h2>
591
  <div class="address-list">
592
  <p><strong>{{ _('address_1_title') }}</strong> {{ _('address_1_detail') }}</p>
593
- <p><strong>{{ _('address_2_title') }}</strong> {{ _('address_2_detail') }}</p>
594
  </div>
595
  </div>
596
  </div>
@@ -601,7 +596,7 @@ CATALOG_TEMPLATE = '''
601
  </button>
602
 
603
  <div class="bottom-nav">
604
- <a href="https://api.whatsapp.com/send?phone=+77073479416" target="_blank" class="nav-button">
605
  <i class="fab fa-whatsapp"></i>
606
  <span>{{ _('whatsapp') }}</span>
607
  </a>
@@ -625,8 +620,8 @@ CATALOG_TEMPLATE = '''
625
  const currencyCode = '{{ currency_code }}';
626
  const t = {{ translations[lang]|tojson|safe }};
627
  let selectedProductIndex = null;
628
- let cart = JSON.parse(localStorage.getItem('dalarssiCart') || '[]');
629
- let favorites = JSON.parse(localStorage.getItem('dalarssiFavorites') || '[]');
630
 
631
  function openModal(modalId) {
632
  const modal = document.getElementById(modalId);
@@ -750,7 +745,7 @@ CATALOG_TEMPLATE = '''
750
  });
751
  }
752
 
753
- localStorage.setItem('dalarssiCart', JSON.stringify(cart));
754
  closeModal('quantityModal');
755
  updateCartButton();
756
  showNotification(`${product.name} ${t.product_added_notification}`);
@@ -821,7 +816,7 @@ CATALOG_TEMPLATE = '''
821
 
822
  function removeFromCart(itemId) {
823
  cart = cart.filter(item => item.id !== itemId);
824
- localStorage.setItem('dalarssiCart', JSON.stringify(cart));
825
  openCartModal();
826
  updateCartButton();
827
  }
@@ -829,7 +824,7 @@ CATALOG_TEMPLATE = '''
829
  function clearCart() {
830
  if (confirm(t.confirm_clear_cart)) {
831
  cart = [];
832
- localStorage.removeItem('dalarssiCart');
833
  openCartModal();
834
  updateCartButton();
835
  }
@@ -858,7 +853,7 @@ CATALOG_TEMPLATE = '''
858
  })
859
  .then(data => {
860
  if (data.order_id) {
861
- localStorage.removeItem('dalarssiCart');
862
  cart = [];
863
  updateCartButton();
864
  closeModal('cartModal');
@@ -938,7 +933,7 @@ CATALOG_TEMPLATE = '''
938
  buttonElement.classList.add('favorited');
939
  buttonElement.innerHTML = '<i class="fas fa-heart"></i>';
940
  }
941
- localStorage.setItem('dalarssiFavorites', JSON.stringify(favorites));
942
  }
943
 
944
  function updateFavoriteIcons() {
@@ -999,7 +994,7 @@ CATALOG_TEMPLATE = '''
999
  const index = favorites.indexOf(productId);
1000
  if (index > -1) {
1001
  favorites.splice(index, 1);
1002
- localStorage.setItem('dalarssiFavorites', JSON.stringify(favorites));
1003
  openFavoritesModal();
1004
  updateFavoriteIcons();
1005
  }
@@ -1095,16 +1090,16 @@ ORDER_TEMPLATE = '''
1095
  <head>
1096
  <meta charset="UTF-8">
1097
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1098
- <title>{{ _('order_title') }}{{ order.id }} - dalarssi</title>
1099
  <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;600;700&display=swap" rel="stylesheet">
1100
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
1101
  <style>
1102
  :root {
1103
  --bg-color: #1a1a1a;
1104
  --surface-color: #2b2b2b;
1105
- --primary-accent: #D99ECB;
1106
- --primary-accent-hover: #C874B2;
1107
- --secondary-accent: #6f4e37;
1108
  --text-color: #f0e6e6;
1109
  --text-muted: #a09a9a;
1110
  }
@@ -1126,7 +1121,7 @@ ORDER_TEMPLATE = '''
1126
  .customer-info p { margin-bottom: 8px; font-size: 1rem; }
1127
  .actions { margin-top: 35px; text-align: center; }
1128
  .button { padding: 14px 30px; border: none; border-radius: 8px; background-color: var(--primary-accent); color: var(--bg-color); font-weight: 600; cursor: pointer; transition: all 0.3s ease; font-size: 1.1rem; display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
1129
- .button:hover { background-color: var(--primary-accent-hover); transform: translateY(-2px); box-shadow: 0 4px 15px rgba(217, 158, 203, 0.2); }
1130
  .button i { font-size: 1.3rem; }
1131
  .catalog-link { display: block; text-align: center; margin-top: 30px; color: var(--primary-accent); text-decoration: none; font-size: 1rem; }
1132
  .catalog-link:hover { text-decoration: underline; }
@@ -1177,7 +1172,7 @@ ORDER_TEMPLATE = '''
1177
  function sendOrderViaWhatsApp() {
1178
  const orderId = '{{ order.id }}';
1179
  const orderUrl = `{{ request.url }}`;
1180
- const whatsappNumber = "+77073479416";
1181
 
1182
  let message = `{{ _('whatsapp_greeting') }}%0A%0A`;
1183
  message += `*{{ _('whatsapp_order_number') }}* ${orderId}%0A`;
@@ -1205,60 +1200,60 @@ ADMIN_TEMPLATE = '''
1205
  <head>
1206
  <meta charset="UTF-8">
1207
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1208
- <title>Админ-панель - dalarssi</title>
1209
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
1210
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
1211
  <style>
1212
- body { font-family: 'Poppins', sans-serif; background-color: #f0f2f5; color: #3d3522; padding: 20px; line-height: 1.6; }
1213
  .container { max-width: 1200px; margin: 0 auto; background-color: #fff; padding: 25px; border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.05); }
1214
- .header { padding-bottom: 15px; margin-bottom: 25px; border-bottom: 1px solid #dcd3b8; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;}
1215
- h1, h2, h3 { font-weight: 600; color: #556b2f; margin-bottom: 15px; }
1216
  h1 { font-size: 1.6rem; }
1217
  h2 { font-size: 1.5rem; margin-top: 30px; display: flex; align-items: center; gap: 8px; }
1218
- h3 { font-size: 1.2rem; color: #8b4513; margin-top: 20px; }
1219
- .section { margin-bottom: 30px; padding: 20px; background-color: #fcfaf5; border: 1px solid #dcd3b8; border-radius: 8px; }
1220
  form { margin-bottom: 20px; }
1221
- label { font-weight: 500; margin-top: 10px; display: block; color: #6f6a5b; font-size: 0.9rem;}
1222
- input[type="text"], input[type="number"], input[type="password"], input[type="tel"], textarea, select { width: 100%; padding: 10px 12px; margin-top: 5px; border: 1px solid #dcd3b8; border-radius: 6px; font-size: 0.95rem; box-sizing: border-box; transition: border-color 0.3s ease; background-color: #fff; }
1223
- input:focus, textarea:focus, select:focus { border-color: #556b2f; outline: none; box-shadow: 0 0 0 2px rgba(85, 107, 47, 0.1); }
1224
  textarea { min-height: 80px; resize: vertical; }
1225
- input[type="file"] { padding: 8px; background-color: #f5f0e1; cursor: pointer; border: 1px solid #dcd3b8;}
1226
- input[type="file"]::file-selector-button { padding: 5px 10px; border-radius: 4px; background-color: #e0dace; border: 1px solid #dcd3b8; cursor: pointer; margin-right: 10px;}
1227
  input[type="checkbox"] { margin-right: 5px; vertical-align: middle; }
1228
  label.inline-label { display: inline-block; margin-top: 10px; font-weight: normal; }
1229
- button, .button { padding: 10px 18px; border: none; border-radius: 6px; background-color: #556b2f; color: white; font-weight: 500; cursor: pointer; transition: background-color 0.3s ease, transform 0.1s ease; margin-top: 15px; font-size: 0.95rem; display: inline-flex; align-items: center; gap: 5px; text-decoration: none; line-height: 1.2;}
1230
- button:hover, .button:hover { background-color: #6b8e23; }
1231
  button:active, .button:active { transform: scale(0.98); }
1232
  button[type="submit"] { min-width: 120px; justify-content: center; }
1233
  .delete-button { background-color: #c04c4c; }
1234
  .delete-button:hover { background-color: #a03c3c; }
1235
- .add-button { background-color: #556b2f; }
1236
- .add-button:hover { background-color: #6b8e23; }
1237
  .item-list { display: grid; gap: 20px; }
1238
- .item { background: #fff; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.07); border: 1px solid #e5d9b7; }
1239
- .item p { margin: 5px 0; font-size: 0.9rem; color: #6f6a5b; }
1240
- .item strong { color: #3d3522; }
1241
- .item .description { font-size: 0.85rem; color: #8b8577; max-height: 60px; overflow: hidden; text-overflow: ellipsis; }
1242
  .item-actions { margin-top: 15px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
1243
- .item-actions button:not(.delete-button) { background-color: #556b2f; }
1244
- .item-actions button:not(.delete-button):hover { background-color: #6b8e23; }
1245
- .edit-form-container { margin-top: 15px; padding: 20px; background: #f5f0e1; border: 1px dashed #dcd3b8; border-radius: 6px; display: none; }
1246
- details { background-color: #fcfaf5; border: 1px solid #dcd3b8; border-radius: 8px; margin-bottom: 20px; }
1247
- details > summary { cursor: pointer; font-weight: 600; color: #8b4513; display: block; padding: 15px; border-bottom: 1px solid #dcd3b8; list-style: none; position: relative; }
1248
- details > summary::after { content: '\\f078'; font-family: 'Font Awesome 6 Free'; font-weight: 900; position: absolute; right: 20px; top: 50%; transform: translateY(-50%); transition: transform 0.2s ease; color: #556b2f; }
1249
  details[open] > summary::after { transform: translateY(-50%) rotate(180deg); }
1250
- details[open] > summary { border-bottom: 1px solid #dcd3b8; }
1251
  details .form-content { padding: 20px; }
1252
  .color-input-group { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
1253
  .color-input-group input { flex-grow: 1; margin: 0; }
1254
  .remove-color-btn { background-color: #c04c4c; padding: 6px 10px; font-size: 0.8rem; margin-top: 0; line-height: 1; }
1255
  .remove-color-btn:hover { background-color: #a03c3c; }
1256
- .add-color-btn { background-color: #b2c2a1; color: #3d3522; }
1257
- .add-color-btn:hover { background-color: #dcd3b8; }
1258
- .photo-preview img { max-width: 70px; max-height: 70px; border-radius: 5px; margin: 5px 5px 0 0; border: 1px solid #dcd3b8; object-fit: cover;}
1259
  .sync-buttons { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
1260
- .download-hf-button { background-color: #8b8577; }
1261
- .download-hf-button:hover { background-color: #6f6a5b; }
1262
  .flex-container { display: flex; flex-wrap: wrap; gap: 20px; }
1263
  .flex-item { flex: 1; min-width: 350px; }
1264
  .message { padding: 10px 15px; border-radius: 6px; margin-bottom: 15px; font-size: 0.9rem;}
@@ -1275,10 +1270,10 @@ ADMIN_TEMPLATE = '''
1275
  <div class="container">
1276
  <div class="header">
1277
  <div class="logo-title-container" style="display: flex; align-items: center; gap: 15px;">
1278
- <i class="fas fa-gem" style="font-size: 36px; color: #556b2f;"></i>
1279
- <h1><i class="fas fa-tools"></i> Админ-панель dalarssi</h1>
1280
  </div>
1281
- <a href="{{ url_for('catalog') }}" class="button" style="background-color: #6b8e23;"><i class="fas fa-store"></i> Перейти в каталог</a>
1282
  </div>
1283
 
1284
 
@@ -1438,7 +1433,7 @@ ADMIN_TEMPLATE = '''
1438
  {% endif %}
1439
  </div>
1440
  <div style="flex-grow: 1;">
1441
- <h3 style="margin-top: 0; margin-bottom: 5px; color: #3d3522;">
1442
  {{ product['name'] }}
1443
  {% if product.get('in_stock', True) %}
1444
  <span class="status-indicator in-stock">В наличии</span>
 
16
  load_dotenv()
17
 
18
  app = Flask(__name__)
19
+ app.secret_key = 'manolisa_secret_key_no_login'
20
  DATA_FILE = 'data.json'
21
 
22
 
 
26
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
27
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
28
 
29
+ STORE_ADDRESS = "Город Алматы, Рынок Олжа, ряд VIP, Бутик 7"
30
 
31
  CURRENCY_CODE = 'USD'
32
  CURRENCY_NAME = 'доллар'
 
38
 
39
  translations = {
40
  'ru': {
41
+ 'site_title': "Manolisa - Каталог",
42
+ 'brand_name': "Manolisa",
43
  'our_address': "Наш адрес:",
44
  'all_categories': "Все категории",
45
  'search_placeholder': "Поиск по названию или описанию...",
 
86
  'order_status_desc': "Этот заказ был оформлен без входа в систему. Пожалуйста, свяжитесь с нами по WhatsApp для подтверждения и уточнения деталей.",
87
  'send_order': "Отправить заказ",
88
  'back_to_catalog': "← Вернуться в каталог",
89
+ 'whatsapp_greeting': "Здравствуйте! Хочу подтвердить свой заказ на Manolisa:",
90
  'whatsapp_order_number': "Номер заказа:",
91
  'whatsapp_order_link': "Ссылка на заказ:",
92
  'whatsapp_contact_me': "Пожалуйста, свяжитесь со мной для уточнения деталей оплаты и доставки.",
 
99
  'favorites': 'Избранное',
100
  'employee': 'Сотрудник:',
101
  'online_order': 'Онлайн',
102
+ 'address_1_title': 'Адрес:',
103
+ 'address_1_detail': 'Город Алматы, Рынок Олжа, ряд VIP, Бутик 7',
 
 
104
  },
105
  'kk': {
106
+ 'site_title': "Manolisa - Каталог",
107
+ 'brand_name': "Manolisa",
108
  'our_address': "Біздің мекенжайымыз:",
109
  'all_categories': "Барлық санаттар",
110
  'search_placeholder': "Аты немесе сипаттамасы бойынша іздеу...",
 
151
  'order_status_desc': "Бұл тапсырыс жүйеге кірмей рәсімделді. Растау және мәліметтерді нақтылау үшін WhatsApp арқылы бізбен хабарласыңыз.",
152
  'send_order': "Тапсырысты жіберу",
153
  'back_to_catalog': "← Каталогқа оралу",
154
+ 'whatsapp_greeting': "Сәлеметсіз бе! Мен Manolisa-дегі тапсырысымды растағым келеді:",
155
  'whatsapp_order_number': "Тапсырыс нөмірі:",
156
  'whatsapp_order_link': "Тапсырысқа сілтеме:",
157
  'whatsapp_contact_me': "Төлем және жеткізу мәліметтерін нақтылау үшін менімен хабарласыңыз.",
 
164
  'favorites': 'Таңдаулылар',
165
  'employee': 'Қызметкер:',
166
  'online_order': 'Онлайн',
167
+ 'address_1_title': 'Мекенжай:',
168
+ 'address_1_detail': 'Алматы қаласы, Олжа базары, VIP қатары, 7 бутик',
 
 
169
  }
170
  }
171
 
 
371
  :root {
372
  --bg-color: #1a1a1a;
373
  --surface-color: #2b2b2b;
374
+ --primary-accent: #00CED1;
375
+ --primary-accent-hover: #20B2AA;
376
+ --secondary-accent: #005f6b;
377
  --text-color: #f0e6e6;
378
  --text-muted: #a09a9a;
379
  }
 
389
  .filters-container { margin: 25px 0; display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; }
390
  .search-container { margin: 25px 0; text-align: center; }
391
  #search-input { width: 90%; max-width: 600px; padding: 14px 22px; font-size: 1rem; border: 1px solid var(--secondary-accent); border-radius: 30px; outline: none; transition: all 0.3s ease; background-color: var(--surface-color); color: var(--text-color); }
392
+ #search-input:focus { border-color: var(--primary-accent); box-shadow: 0 0 0 4px rgba(0, 206, 209, 0.2); }
393
  .category-filter { padding: 10px 20px; border: 1px solid var(--secondary-accent); border-radius: 30px; background-color: transparent; cursor: pointer; transition: all 0.3s ease; font-size: 0.9rem; font-weight: 600; color: var(--text-muted); }
394
  .category-filter.active, .category-filter:hover { background-color: var(--primary-accent); color: var(--bg-color); border-color: var(--primary-accent); }
395
  .products-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; padding: 10px; }
 
411
  .product-button { display: block; width: 100%; padding: 12px; border: none; border-radius: 8px; background-color: var(--primary-accent); color: var(--bg-color); font-size: 1rem; font-weight: 600; cursor: pointer; transition: all 0.3s ease; text-align: center; text-decoration: none; }
412
  .product-button:hover { background-color: var(--primary-accent-hover); }
413
  .product-button i { margin-right: 8px; }
414
+ #cart-button { position: fixed; bottom: 90px; right: 30px; background-color: var(--primary-accent); color: var(--bg-color); border: none; border-radius: 50%; width: 60px; height: 60px; font-size: 1.6rem; cursor: pointer; display: none; align-items: center; justify-content: center; box-shadow: 0 5px 20px rgba(0, 206, 209, 0.3); transition: all 0.3s ease; z-index: 1000; }
415
  #cart-button:hover { transform: scale(1.1); }
416
  #cart-button span { position: absolute; top: 0px; right: 0px; background-color: var(--secondary-accent); color: var(--text-color); border-radius: 50%; padding: 3px 7px; font-size: 0.8rem; font-weight: bold; }
417
  .modal { display: none; position: fixed; z-index: 1001; left: 0; top: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.7); backdrop-filter: blur(8px); overflow-y: auto; }
 
438
  .notification { position: fixed; bottom: 90px; left: 50%; transform: translateX(-50%); background-color: var(--primary-accent); color: var(--bg-color); padding: 12px 25px; border-radius: 30px; box-shadow: 0 5px 15px rgba(0,0,0,0.3); z-index: 1002; opacity: 0; transition: opacity 0.5s ease; font-size: 1rem; font-weight: 600;}
439
  .notification.show { opacity: 1;}
440
  .no-results-message { grid-column: 1 / -1; text-align: center; padding: 50px; font-size: 1.2rem; color: var(--text-muted); }
441
+ .top-product-indicator { position: absolute; top: 12px; right: 12px; background-color: rgba(0, 206, 209, 0.9); color: var(--bg-color); padding: 4px 10px; font-size: 0.8rem; border-radius: 20px; font-weight: bold; z-index: 10; backdrop-filter: blur(3px); }
442
  .favorite-button { position: absolute; top: 12px; left: 12px; background: none; border: none; color: var(--text-color); font-size: 1.5rem; cursor: pointer; z-index: 10; padding: 5px; line-height: 1; transition: color 0.3s, transform 0.3s; text-shadow: 0 0 5px rgba(0,0,0,0.5); }
443
  .favorite-button.favorited { color: #e91e63; transform: scale(1.1); }
444
  .favorite-button:hover { transform: scale(1.2); }
 
586
  <h2><i class="fas fa-map-marker-alt"></i> {{ _('addresses') }}</h2>
587
  <div class="address-list">
588
  <p><strong>{{ _('address_1_title') }}</strong> {{ _('address_1_detail') }}</p>
 
589
  </div>
590
  </div>
591
  </div>
 
596
  </button>
597
 
598
  <div class="bottom-nav">
599
+ <a href="https://api.whatsapp.com/send?phone=+77773616116" target="_blank" class="nav-button">
600
  <i class="fab fa-whatsapp"></i>
601
  <span>{{ _('whatsapp') }}</span>
602
  </a>
 
620
  const currencyCode = '{{ currency_code }}';
621
  const t = {{ translations[lang]|tojson|safe }};
622
  let selectedProductIndex = null;
623
+ let cart = JSON.parse(localStorage.getItem('manolisaCart') || '[]');
624
+ let favorites = JSON.parse(localStorage.getItem('manolisaFavorites') || '[]');
625
 
626
  function openModal(modalId) {
627
  const modal = document.getElementById(modalId);
 
745
  });
746
  }
747
 
748
+ localStorage.setItem('manolisaCart', JSON.stringify(cart));
749
  closeModal('quantityModal');
750
  updateCartButton();
751
  showNotification(`${product.name} ${t.product_added_notification}`);
 
816
 
817
  function removeFromCart(itemId) {
818
  cart = cart.filter(item => item.id !== itemId);
819
+ localStorage.setItem('manolisaCart', JSON.stringify(cart));
820
  openCartModal();
821
  updateCartButton();
822
  }
 
824
  function clearCart() {
825
  if (confirm(t.confirm_clear_cart)) {
826
  cart = [];
827
+ localStorage.removeItem('manolisaCart');
828
  openCartModal();
829
  updateCartButton();
830
  }
 
853
  })
854
  .then(data => {
855
  if (data.order_id) {
856
+ localStorage.removeItem('manolisaCart');
857
  cart = [];
858
  updateCartButton();
859
  closeModal('cartModal');
 
933
  buttonElement.classList.add('favorited');
934
  buttonElement.innerHTML = '<i class="fas fa-heart"></i>';
935
  }
936
+ localStorage.setItem('manolisaFavorites', JSON.stringify(favorites));
937
  }
938
 
939
  function updateFavoriteIcons() {
 
994
  const index = favorites.indexOf(productId);
995
  if (index > -1) {
996
  favorites.splice(index, 1);
997
+ localStorage.setItem('manolisaFavorites', JSON.stringify(favorites));
998
  openFavoritesModal();
999
  updateFavoriteIcons();
1000
  }
 
1090
  <head>
1091
  <meta charset="UTF-8">
1092
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1093
+ <title>{{ _('order_title') }}{{ order.id }} - Manolisa</title>
1094
  <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;600;700&display=swap" rel="stylesheet">
1095
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
1096
  <style>
1097
  :root {
1098
  --bg-color: #1a1a1a;
1099
  --surface-color: #2b2b2b;
1100
+ --primary-accent: #00CED1;
1101
+ --primary-accent-hover: #20B2AA;
1102
+ --secondary-accent: #005f6b;
1103
  --text-color: #f0e6e6;
1104
  --text-muted: #a09a9a;
1105
  }
 
1121
  .customer-info p { margin-bottom: 8px; font-size: 1rem; }
1122
  .actions { margin-top: 35px; text-align: center; }
1123
  .button { padding: 14px 30px; border: none; border-radius: 8px; background-color: var(--primary-accent); color: var(--bg-color); font-weight: 600; cursor: pointer; transition: all 0.3s ease; font-size: 1.1rem; display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
1124
+ .button:hover { background-color: var(--primary-accent-hover); transform: translateY(-2px); box-shadow: 0 4px 15px rgba(0, 206, 209, 0.2); }
1125
  .button i { font-size: 1.3rem; }
1126
  .catalog-link { display: block; text-align: center; margin-top: 30px; color: var(--primary-accent); text-decoration: none; font-size: 1rem; }
1127
  .catalog-link:hover { text-decoration: underline; }
 
1172
  function sendOrderViaWhatsApp() {
1173
  const orderId = '{{ order.id }}';
1174
  const orderUrl = `{{ request.url }}`;
1175
+ const whatsappNumber = "+77773616116";
1176
 
1177
  let message = `{{ _('whatsapp_greeting') }}%0A%0A`;
1178
  message += `*{{ _('whatsapp_order_number') }}* ${orderId}%0A`;
 
1200
  <head>
1201
  <meta charset="UTF-8">
1202
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1203
+ <title>Админ-панель - Manolisa</title>
1204
  <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&display=swap" rel="stylesheet">
1205
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
1206
  <style>
1207
+ body { font-family: 'Poppins', sans-serif; background-color: #f0f8ff; color: #2f4f4f; padding: 20px; line-height: 1.6; }
1208
  .container { max-width: 1200px; margin: 0 auto; background-color: #fff; padding: 25px; border-radius: 10px; box-shadow: 0 3px 10px rgba(0,0,0,0.05); }
1209
+ .header { padding-bottom: 15px; margin-bottom: 25px; border-bottom: 1px solid #b0e0e6; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px;}
1210
+ h1, h2, h3 { font-weight: 600; color: #008B8B; margin-bottom: 15px; }
1211
  h1 { font-size: 1.6rem; }
1212
  h2 { font-size: 1.5rem; margin-top: 30px; display: flex; align-items: center; gap: 8px; }
1213
+ h3 { font-size: 1.2rem; color: #005f6b; margin-top: 20px; }
1214
+ .section { margin-bottom: 30px; padding: 20px; background-color: #f8ffff; border: 1px solid #b0e0e6; border-radius: 8px; }
1215
  form { margin-bottom: 20px; }
1216
+ label { font-weight: 500; margin-top: 10px; display: block; color: #5f7f7f; font-size: 0.9rem;}
1217
+ input[type="text"], input[type="number"], input[type="password"], input[type="tel"], textarea, select { width: 100%; padding: 10px 12px; margin-top: 5px; border: 1px solid #b0e0e6; border-radius: 6px; font-size: 0.95rem; box-sizing: border-box; transition: border-color 0.3s ease; background-color: #fff; }
1218
+ input:focus, textarea:focus, select:focus { border-color: #008B8B; outline: none; box-shadow: 0 0 0 2px rgba(0, 139, 139, 0.1); }
1219
  textarea { min-height: 80px; resize: vertical; }
1220
+ input[type="file"] { padding: 8px; background-color: #e0ffff; cursor: pointer; border: 1px solid #b0e0e6;}
1221
+ input[type="file"]::file-selector-button { padding: 5px 10px; border-radius: 4px; background-color: #b0e0e6; border: 1px solid #008B8B; cursor: pointer; margin-right: 10px;}
1222
  input[type="checkbox"] { margin-right: 5px; vertical-align: middle; }
1223
  label.inline-label { display: inline-block; margin-top: 10px; font-weight: normal; }
1224
+ button, .button { padding: 10px 18px; border: none; border-radius: 6px; background-color: #008B8B; color: white; font-weight: 500; cursor: pointer; transition: background-color 0.3s ease, transform 0.1s ease; margin-top: 15px; font-size: 0.95rem; display: inline-flex; align-items: center; gap: 5px; text-decoration: none; line-height: 1.2;}
1225
+ button:hover, .button:hover { background-color: #20B2AA; }
1226
  button:active, .button:active { transform: scale(0.98); }
1227
  button[type="submit"] { min-width: 120px; justify-content: center; }
1228
  .delete-button { background-color: #c04c4c; }
1229
  .delete-button:hover { background-color: #a03c3c; }
1230
+ .add-button { background-color: #008B8B; }
1231
+ .add-button:hover { background-color: #20B2AA; }
1232
  .item-list { display: grid; gap: 20px; }
1233
+ .item { background: #fff; padding: 15px 20px; border-radius: 8px; box-shadow: 0 2px 5px rgba(0,0,0,0.07); border: 1px solid #b0e0e6; }
1234
+ .item p { margin: 5px 0; font-size: 0.9rem; color: #5f7f7f; }
1235
+ .item strong { color: #2f4f4f; }
1236
+ .item .description { font-size: 0.85rem; color: #708090; max-height: 60px; overflow: hidden; text-overflow: ellipsis; }
1237
  .item-actions { margin-top: 15px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
1238
+ .item-actions button:not(.delete-button) { background-color: #008B8B; }
1239
+ .item-actions button:not(.delete-button):hover { background-color: #20B2AA; }
1240
+ .edit-form-container { margin-top: 15px; padding: 20px; background: #e0ffff; border: 1px dashed #008B8B; border-radius: 6px; display: none; }
1241
+ details { background-color: #f8ffff; border: 1px solid #b0e0e6; border-radius: 8px; margin-bottom: 20px; }
1242
+ details > summary { cursor: pointer; font-weight: 600; color: #005f6b; display: block; padding: 15px; border-bottom: 1px solid #b0e0e6; list-style: none; position: relative; }
1243
+ details > summary::after { content: '\\f078'; font-family: 'Font Awesome 6 Free'; font-weight: 900; position: absolute; right: 20px; top: 50%; transform: translateY(-50%); transition: transform 0.2s ease; color: #008B8B; }
1244
  details[open] > summary::after { transform: translateY(-50%) rotate(180deg); }
1245
+ details[open] > summary { border-bottom: 1px solid #b0e0e6; }
1246
  details .form-content { padding: 20px; }
1247
  .color-input-group { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
1248
  .color-input-group input { flex-grow: 1; margin: 0; }
1249
  .remove-color-btn { background-color: #c04c4c; padding: 6px 10px; font-size: 0.8rem; margin-top: 0; line-height: 1; }
1250
  .remove-color-btn:hover { background-color: #a03c3c; }
1251
+ .add-color-btn { background-color: #b0e0e6; color: #2f4f4f; }
1252
+ .add-color-btn:hover { background-color: #afeeee; }
1253
+ .photo-preview img { max-width: 70px; max-height: 70px; border-radius: 5px; margin: 5px 5px 0 0; border: 1px solid #b0e0e6; object-fit: cover;}
1254
  .sync-buttons { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
1255
+ .download-hf-button { background-color: #708090; }
1256
+ .download-hf-button:hover { background-color: #5f7f7f; }
1257
  .flex-container { display: flex; flex-wrap: wrap; gap: 20px; }
1258
  .flex-item { flex: 1; min-width: 350px; }
1259
  .message { padding: 10px 15px; border-radius: 6px; margin-bottom: 15px; font-size: 0.9rem;}
 
1270
  <div class="container">
1271
  <div class="header">
1272
  <div class="logo-title-container" style="display: flex; align-items: center; gap: 15px;">
1273
+ <i class="fas fa-gem" style="font-size: 36px; color: #008B8B;"></i>
1274
+ <h1><i class="fas fa-tools"></i> Админ-панель Manolisa</h1>
1275
  </div>
1276
+ <a href="{{ url_for('catalog') }}" class="button" style="background-color: #20B2AA;"><i class="fas fa-store"></i> Перейти в каталог</a>
1277
  </div>
1278
 
1279
 
 
1433
  {% endif %}
1434
  </div>
1435
  <div style="flex-grow: 1;">
1436
+ <h3 style="margin-top: 0; margin-bottom: 5px; color: #2f4f4f;">
1437
  {{ product['name'] }}
1438
  {% if product.get('in_stock', True) %}
1439
  <span class="status-indicator in-stock">В наличии</span>