flpolprojects commited on
Commit
39a5053
·
verified ·
1 Parent(s): 5256584

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +56 -114
app.py CHANGED
@@ -12,15 +12,12 @@ from werkzeug.utils import secure_filename
12
  app = Flask(__name__)
13
  DATA_FILE = 'dataasdem.json'
14
 
15
- # Настройки Hugging Face
16
  REPO_ID = "flpolprojects/Clients"
17
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
18
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
19
 
20
- # Ссылка на логотип
21
  LOGO_URL = "https://cdn-avatars.huggingface.co/v1/production/uploads/67b22aaeae9b6a59f1cfb849/NQvBksXzJItYt6hfFjyaB.jpeg"
22
 
23
- # Настройка логирования
24
  logging.basicConfig(level=logging.DEBUG)
25
 
26
  def load_data():
@@ -96,7 +93,7 @@ def periodic_backup():
96
  @app.route('/')
97
  def catalog():
98
  data = load_data()
99
- products = data['products']
100
  categories = data['categories']
101
 
102
  catalog_html = '''
@@ -117,14 +114,9 @@ def catalog():
117
  }
118
  body {
119
  font-family: 'Poppins', sans-serif;
120
- background: linear-gradient(135deg, #f0f2f5, #e9ecef);
121
- color: #2d3748;
122
  line-height: 1.6;
123
- transition: background 0.3s, color 0.3s;
124
- }
125
- body.dark-mode {
126
- background: linear-gradient(135deg, #1a202c, #2d3748);
127
- color: #e2e8f0;
128
  }
129
  .container {
130
  max-width: 1300px;
@@ -136,7 +128,7 @@ def catalog():
136
  justify-content: space-between;
137
  align-items: center;
138
  padding: 15px 0;
139
- border-bottom: 1px solid #e2e8f0;
140
  }
141
  .header-logo {
142
  width: 60px;
@@ -155,17 +147,6 @@ def catalog():
155
  font-weight: 600;
156
  margin-left: 15px;
157
  }
158
- .theme-toggle {
159
- background: none;
160
- border: none;
161
- font-size: 1.5rem;
162
- cursor: pointer;
163
- color: #4a5568;
164
- transition: color 0.3s ease;
165
- }
166
- .theme-toggle:hover {
167
- color: #3b82f6;
168
- }
169
  .filters-container {
170
  margin: 20px 0;
171
  display: flex;
@@ -182,31 +163,32 @@ def catalog():
182
  max-width: 600px;
183
  padding: 12px 18px;
184
  font-size: 1rem;
185
- border: 1px solid #e2e8f0;
186
  border-radius: 8px;
187
  outline: none;
188
  box-shadow: 0 2px 5px rgba(0,0,0,0.05);
189
  transition: all 0.3s ease;
190
  }
191
  #search-input:focus {
192
- border-color: #3b82f6;
193
- box-shadow: 0 4px 15px rgba(59, 130, 246, 0.2);
194
  }
195
  .category-filter {
196
  padding: 8px 16px;
197
- border: 1px solid #e2e8f0;
198
  border-radius: 8px;
199
  background-color: #fff;
 
200
  cursor: pointer;
201
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
202
  font-size: 0.9rem;
203
  font-weight: 400;
204
  }
205
  .category-filter.active, .category-filter:hover {
206
- background-color: #3b82f6;
207
  color: white;
208
- border-color: #3b82f6;
209
- box-shadow: 0 2px 10px rgba(59, 130, 246, 0.3);
210
  }
211
  .products-grid {
212
  display: grid;
@@ -222,10 +204,6 @@ def catalog():
222
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;
223
  overflow: hidden;
224
  }
225
- body.dark-mode .product {
226
- background: #2d3748;
227
- color: #fff;
228
- }
229
  .product:hover {
230
  transform: translateY(-5px) scale(1.02);
231
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
@@ -260,30 +238,27 @@ def catalog():
260
  }
261
  .product-price {
262
  font-size: 1.1rem;
263
- color: #ef4444;
264
  font-weight: 700;
265
  text-align: center;
266
  margin: 5px 0;
267
  }
268
  .product-description {
269
  font-size: 0.8rem;
270
- color: #718096;
271
  text-align: center;
272
  margin-bottom: 15px;
273
  overflow: hidden;
274
  text-overflow: ellipsis;
275
  white-space: nowrap;
276
  }
277
- body.dark-mode .product-description {
278
- color: #a0aec0;
279
- }
280
  .product-button {
281
  display: block;
282
  width: 100%;
283
  padding: 8px;
284
  border: none;
285
  border-radius: 8px;
286
- background-color: #3b82f6;
287
  color: white;
288
  font-size: 0.8rem;
289
  font-weight: 500;
@@ -294,22 +269,22 @@ def catalog():
294
  text-decoration: none;
295
  }
296
  .product-button:hover {
297
- background-color: #2563eb;
298
- box-shadow: 0 4px 15px rgba(37, 99, 235, 0.4);
299
  transform: translateY(-2px);
300
  }
301
  .add-to-cart {
302
- background-color: #10b981;
303
  }
304
  .add-to-cart:hover {
305
- background-color: #059669;
306
- box-shadow: 0 4px 15px rgba(5, 150, 105, 0.4);
307
  }
308
  #cart-button {
309
  position: fixed;
310
  bottom: 20px;
311
  right: 20px;
312
- background-color: #ef4444;
313
  color: white;
314
  border: none;
315
  border-radius: 50%;
@@ -318,7 +293,7 @@ def catalog():
318
  font-size: 1.2rem;
319
  cursor: pointer;
320
  display: none;
321
- box-shadow: 0 4px 15px rgba(239, 68, 68, 0.4);
322
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
323
  z-index: 1000;
324
  }
@@ -343,10 +318,6 @@ def catalog():
343
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
344
  animation: slideIn 0.3s ease-out;
345
  }
346
- body.dark-mode .modal-content {
347
- background: #2d3748;
348
- color: #e2e8f0;
349
- }
350
  @keyframes slideIn {
351
  from { transform: translateY(-50px); opacity: 0; }
352
  to { transform: translateY(0); opacity: 1; }
@@ -354,58 +325,47 @@ def catalog():
354
  .close {
355
  float: right;
356
  font-size: 1.5rem;
357
- color: #718096;
358
  cursor: pointer;
359
  transition: color 0.3s;
360
  }
361
  .close:hover {
362
- color: #2d3748;
363
- }
364
- body.dark-mode .close {
365
- color: #a0aec0;
366
- }
367
- body.dark-mode .close:hover {
368
- color: #fff;
369
  }
370
  .cart-item {
371
  display: flex;
372
  justify-content: space-between;
373
  align-items: center;
374
  padding: 15px 0;
375
- border-bottom: 1px solid #e2e8f0;
376
- }
377
- body.dark-mode .cart-item {
378
- border-bottom: 1px solid #4a5568;
379
- }
380
- .cart-item img {
381
- width: 50px;
382
- height: 50px;
383
- object-fit: contain;
384
- border-radius: 8px;
385
- margin-right: 15px;
386
  }
387
  .quantity-input, .color-select {
388
  width: 100%;
389
  max-width: 150px;
390
  padding: 8px;
391
- border: 1px solid #e2e8f0;
392
  border-radius: 8px;
393
  font-size: 1rem;
394
  margin: 5px 0;
395
  }
396
  .clear-cart {
397
- background-color: #ef4444;
398
  }
399
  .clear-cart:hover {
400
- background-color: #dc2626;
401
- box-shadow: 0 4px 15px rgba(220, 38, 38, 0.4);
402
  }
403
  .order-button {
404
- background-color: #10b981;
405
  }
406
  .order-button:hover {
407
- background-color: #059669;
408
- box-shadow: 0 4px 15px rgba(5, 150, 105, 0.4);
 
 
 
 
 
409
  }
410
  </style>
411
  </head>
@@ -414,9 +374,6 @@ def catalog():
414
  <div class="header">
415
  <img src="''' + LOGO_URL + '''" alt="Logo" class="header-logo">
416
  <h1>Каталог</h1>
417
- <button class="theme-toggle" onclick="toggleTheme()">
418
- <i class="fas fa-moon"></i>
419
- </button>
420
  </div>
421
  <div class="filters-container">
422
  <button class="category-filter active" data-category="all">Все категории</button>
@@ -450,7 +407,6 @@ def catalog():
450
  </div>
451
  </div>
452
 
453
- <!-- Product Modal -->
454
  <div id="productModal" class="modal">
455
  <div class="modal-content">
456
  <span class="close" onclick="closeModal('productModal')">×</span>
@@ -458,7 +414,6 @@ def catalog():
458
  </div>
459
  </div>
460
 
461
- <!-- Quantity and Color Modal -->
462
  <div id="quantityModal" class="modal">
463
  <div class="modal-content">
464
  <span class="close" onclick="closeModal('quantityModal')">×</span>
@@ -469,7 +424,6 @@ def catalog():
469
  </div>
470
  </div>
471
 
472
- <!-- Cart Modal -->
473
  <div id="cartModal" class="modal">
474
  <div class="modal-content">
475
  <span class="close" onclick="closeModal('cartModal')">×</span>
@@ -492,19 +446,6 @@ def catalog():
492
  const products = {{ products|tojson }};
493
  let selectedProductIndex = null;
494
 
495
- function toggleTheme() {
496
- document.body.classList.toggle('dark-mode');
497
- const icon = document.querySelector('.theme-toggle i');
498
- icon.classList.toggle('fa-moon');
499
- icon.classList.toggle('fa-sun');
500
- localStorage.setItem('theme', document.body.classList.contains('dark-mode') ? 'dark' : 'light');
501
- }
502
-
503
- if (localStorage.getItem('theme') === 'dark') {
504
- document.body.classList.add('dark-mode');
505
- document.querySelector('.theme-toggle i').classList.replace('fa-moon', 'fa-sun');
506
- }
507
-
508
  function openModal(index) {
509
  loadProductDetails(index);
510
  document.getElementById('productModal').style.display = "block";
@@ -753,7 +694,7 @@ def admin():
753
  photos_list = []
754
 
755
  if photos_files:
756
- for photo in photos_files[:10]: # Ограничение до 10 фото
757
  if photo and photo.filename:
758
  photo_filename = secure_filename(photo.filename)
759
  uploads_dir = 'uploads'
@@ -783,7 +724,8 @@ def admin():
783
  'description': description,
784
  'category': category if category in categories else 'Без категории',
785
  'photos': photos_list,
786
- 'colors': colors if colors else []
 
787
  }
788
  products.append(new_product)
789
  save_data(data)
@@ -800,7 +742,7 @@ def admin():
800
 
801
  if photos_files and any(photo.filename for photo in photos_files):
802
  new_photos_list = []
803
- for photo in photos_files[:10]: # Ограничение до 10 фото
804
  if photo and photo.filename:
805
  photo_filename = secure_filename(photo.filename)
806
  uploads_dir = 'uploads'
@@ -846,8 +788,8 @@ def admin():
846
  <style>
847
  body {
848
  font-family: 'Poppins', sans-serif;
849
- background: linear-gradient(135deg, #f0f2f5, #e9ecef);
850
- color: #2d3748;
851
  padding: 20px;
852
  }
853
  .container {
@@ -858,7 +800,7 @@ def admin():
858
  display: flex;
859
  align-items: center;
860
  padding: 15px 0;
861
- border-bottom: 1px solid #e2e8f0;
862
  }
863
  .header-logo {
864
  width: 60px;
@@ -893,21 +835,21 @@ def admin():
893
  width: 100%;
894
  padding: 12px;
895
  margin-top: 5px;
896
- border: 1px solid #e2e8f0;
897
  border-radius: 8px;
898
  font-size: 1rem;
899
  transition: all 0.3s ease;
900
  }
901
  input:focus, textarea:focus, select:focus {
902
- border-color: #3b82f6;
903
- box-shadow: 0 0 5px rgba(59, 130, 246, 0.3);
904
  outline: none;
905
  }
906
  button {
907
  padding: 12px 20px;
908
  border: none;
909
  border-radius: 8px;
910
- background-color: #3b82f6;
911
  color: white;
912
  font-weight: 500;
913
  cursor: pointer;
@@ -915,16 +857,16 @@ def admin():
915
  margin-top: 15px;
916
  }
917
  button:hover {
918
- background-color: #2563eb;
919
- box-shadow: 0 4px 15px rgba(37, 99, 235, 0.4);
920
  transform: translateY(-2px);
921
  }
922
  .delete-button {
923
- background-color: #ef4444;
924
  }
925
  .delete-button:hover {
926
- background-color: #dc2626;
927
- box-shadow: 0 4px 15px rgba(220, 38, 38, 0.4);
928
  }
929
  .product-list, .category-list {
930
  display: grid;
@@ -939,7 +881,7 @@ def admin():
939
  .edit-form {
940
  margin-top: 15px;
941
  padding: 15px;
942
- background: #f7fafc;
943
  border-radius: 10px;
944
  }
945
  .color-input-group {
@@ -948,10 +890,10 @@ def admin():
948
  margin-top: 5px;
949
  }
950
  .add-color-btn {
951
- background-color: #10b981;
952
  }
953
  .add-color-btn:hover {
954
- background-color: #059669;
955
  }
956
  </style>
957
  </head>
 
12
  app = Flask(__name__)
13
  DATA_FILE = 'dataasdem.json'
14
 
 
15
  REPO_ID = "flpolprojects/Clients"
16
  HF_TOKEN_WRITE = os.getenv("HF_TOKEN")
17
  HF_TOKEN_READ = os.getenv("HF_TOKEN_READ")
18
 
 
19
  LOGO_URL = "https://cdn-avatars.huggingface.co/v1/production/uploads/67b22aaeae9b6a59f1cfb849/NQvBksXzJItYt6hfFjyaB.jpeg"
20
 
 
21
  logging.basicConfig(level=logging.DEBUG)
22
 
23
  def load_data():
 
93
  @app.route('/')
94
  def catalog():
95
  data = load_data()
96
+ products = sorted(data['products'], key=lambda x: x.get('added_at', ''), reverse=True)
97
  categories = data['categories']
98
 
99
  catalog_html = '''
 
114
  }
115
  body {
116
  font-family: 'Poppins', sans-serif;
117
+ background: linear-gradient(135deg, #fce4ec, #f8bbd0);
118
+ color: #880e4f;
119
  line-height: 1.6;
 
 
 
 
 
120
  }
121
  .container {
122
  max-width: 1300px;
 
128
  justify-content: space-between;
129
  align-items: center;
130
  padding: 15px 0;
131
+ border-bottom: 1px solid #f48fb1;
132
  }
133
  .header-logo {
134
  width: 60px;
 
147
  font-weight: 600;
148
  margin-left: 15px;
149
  }
 
 
 
 
 
 
 
 
 
 
 
150
  .filters-container {
151
  margin: 20px 0;
152
  display: flex;
 
163
  max-width: 600px;
164
  padding: 12px 18px;
165
  font-size: 1rem;
166
+ border: 1px solid #f48fb1;
167
  border-radius: 8px;
168
  outline: none;
169
  box-shadow: 0 2px 5px rgba(0,0,0,0.05);
170
  transition: all 0.3s ease;
171
  }
172
  #search-input:focus {
173
+ border-color: #e91e63;
174
+ box-shadow: 0 4px 15px rgba(233, 30, 99, 0.2);
175
  }
176
  .category-filter {
177
  padding: 8px 16px;
178
+ border: 1px solid #f48fb1;
179
  border-radius: 8px;
180
  background-color: #fff;
181
+ color: #880e4f;
182
  cursor: pointer;
183
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
184
  font-size: 0.9rem;
185
  font-weight: 400;
186
  }
187
  .category-filter.active, .category-filter:hover {
188
+ background-color: #e91e63;
189
  color: white;
190
+ border-color: #e91e63;
191
+ box-shadow: 0 2px 10px rgba(233, 30, 99, 0.3);
192
  }
193
  .products-grid {
194
  display: grid;
 
204
  transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.3s ease;
205
  overflow: hidden;
206
  }
 
 
 
 
207
  .product:hover {
208
  transform: translateY(-5px) scale(1.02);
209
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.15);
 
238
  }
239
  .product-price {
240
  font-size: 1.1rem;
241
+ color: #e91e63;
242
  font-weight: 700;
243
  text-align: center;
244
  margin: 5px 0;
245
  }
246
  .product-description {
247
  font-size: 0.8rem;
248
+ color: #880e4f;
249
  text-align: center;
250
  margin-bottom: 15px;
251
  overflow: hidden;
252
  text-overflow: ellipsis;
253
  white-space: nowrap;
254
  }
 
 
 
255
  .product-button {
256
  display: block;
257
  width: 100%;
258
  padding: 8px;
259
  border: none;
260
  border-radius: 8px;
261
+ background-color: #e91e63;
262
  color: white;
263
  font-size: 0.8rem;
264
  font-weight: 500;
 
269
  text-decoration: none;
270
  }
271
  .product-button:hover {
272
+ background-color: #d81b60;
273
+ box-shadow: 0 4px 15px rgba(233, 30, 99, 0.4);
274
  transform: translateY(-2px);
275
  }
276
  .add-to-cart {
277
+ background-color: #4caf50;
278
  }
279
  .add-to-cart:hover {
280
+ background-color: #43a047;
281
+ box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4);
282
  }
283
  #cart-button {
284
  position: fixed;
285
  bottom: 20px;
286
  right: 20px;
287
+ background-color: #e91e63;
288
  color: white;
289
  border: none;
290
  border-radius: 50%;
 
293
  font-size: 1.2rem;
294
  cursor: pointer;
295
  display: none;
296
+ box-shadow: 0 4px 15px rgba(233, 30, 99, 0.4);
297
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
298
  z-index: 1000;
299
  }
 
318
  box-shadow: 0 10px 30px rgba(0,0,0,0.2);
319
  animation: slideIn 0.3s ease-out;
320
  }
 
 
 
 
321
  @keyframes slideIn {
322
  from { transform: translateY(-50px); opacity: 0; }
323
  to { transform: translateY(0); opacity: 1; }
 
325
  .close {
326
  float: right;
327
  font-size: 1.5rem;
328
+ color: #880e4f;
329
  cursor: pointer;
330
  transition: color 0.3s;
331
  }
332
  .close:hover {
333
+ color: #e91e63;
 
 
 
 
 
 
334
  }
335
  .cart-item {
336
  display: flex;
337
  justify-content: space-between;
338
  align-items: center;
339
  padding: 15px 0;
340
+ border-bottom: 1px solid #f48fb1;
 
 
 
 
 
 
 
 
 
 
341
  }
342
  .quantity-input, .color-select {
343
  width: 100%;
344
  max-width: 150px;
345
  padding: 8px;
346
+ border: 1px solid #f48fb1;
347
  border-radius: 8px;
348
  font-size: 1rem;
349
  margin: 5px 0;
350
  }
351
  .clear-cart {
352
+ background-color: #e91e63;
353
  }
354
  .clear-cart:hover {
355
+ background-color: #d81b60;
356
+ box-shadow: 0 4px 15px rgba(233, 30, 99, 0.4);
357
  }
358
  .order-button {
359
+ background-color: #4caf50;
360
  }
361
  .order-button:hover {
362
+ background-color: #43a047;
363
+ box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4);
364
+ }
365
+ @media (max-width: 768px) {
366
+ .products-grid {
367
+ grid-template-columns: repeat(2, minmax(150px, 1fr));
368
+ }
369
  }
370
  </style>
371
  </head>
 
374
  <div class="header">
375
  <img src="''' + LOGO_URL + '''" alt="Logo" class="header-logo">
376
  <h1>Каталог</h1>
 
 
 
377
  </div>
378
  <div class="filters-container">
379
  <button class="category-filter active" data-category="all">Все категории</button>
 
407
  </div>
408
  </div>
409
 
 
410
  <div id="productModal" class="modal">
411
  <div class="modal-content">
412
  <span class="close" onclick="closeModal('productModal')">×</span>
 
414
  </div>
415
  </div>
416
 
 
417
  <div id="quantityModal" class="modal">
418
  <div class="modal-content">
419
  <span class="close" onclick="closeModal('quantityModal')">×</span>
 
424
  </div>
425
  </div>
426
 
 
427
  <div id="cartModal" class="modal">
428
  <div class="modal-content">
429
  <span class="close" onclick="closeModal('cartModal')">×</span>
 
446
  const products = {{ products|tojson }};
447
  let selectedProductIndex = null;
448
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  function openModal(index) {
450
  loadProductDetails(index);
451
  document.getElementById('productModal').style.display = "block";
 
694
  photos_list = []
695
 
696
  if photos_files:
697
+ for photo in photos_files[:10]:
698
  if photo and photo.filename:
699
  photo_filename = secure_filename(photo.filename)
700
  uploads_dir = 'uploads'
 
724
  'description': description,
725
  'category': category if category in categories else 'Без категории',
726
  'photos': photos_list,
727
+ 'colors': colors if colors else [],
728
+ 'added_at': datetime.now().isoformat()
729
  }
730
  products.append(new_product)
731
  save_data(data)
 
742
 
743
  if photos_files and any(photo.filename for photo in photos_files):
744
  new_photos_list = []
745
+ for photo in photos_files[:10]:
746
  if photo and photo.filename:
747
  photo_filename = secure_filename(photo.filename)
748
  uploads_dir = 'uploads'
 
788
  <style>
789
  body {
790
  font-family: 'Poppins', sans-serif;
791
+ background: linear-gradient(135deg, #fce4ec, #f8bbd0);
792
+ color: #880e4f;
793
  padding: 20px;
794
  }
795
  .container {
 
800
  display: flex;
801
  align-items: center;
802
  padding: 15px 0;
803
+ border-bottom: 1px solid #f48fb1;
804
  }
805
  .header-logo {
806
  width: 60px;
 
835
  width: 100%;
836
  padding: 12px;
837
  margin-top: 5px;
838
+ border: 1px solid #f48fb1;
839
  border-radius: 8px;
840
  font-size: 1rem;
841
  transition: all 0.3s ease;
842
  }
843
  input:focus, textarea:focus, select:focus {
844
+ border-color: #e91e63;
845
+ box-shadow: 0 0 5px rgba(233, 30, 99, 0.3);
846
  outline: none;
847
  }
848
  button {
849
  padding: 12px 20px;
850
  border: none;
851
  border-radius: 8px;
852
+ background-color: #e91e63;
853
  color: white;
854
  font-weight: 500;
855
  cursor: pointer;
 
857
  margin-top: 15px;
858
  }
859
  button:hover {
860
+ background-color: #d81b60;
861
+ box-shadow: 0 4px 15px rgba(233, 30, 99, 0.4);
862
  transform: translateY(-2px);
863
  }
864
  .delete-button {
865
+ background-color: #ef5350;
866
  }
867
  .delete-button:hover {
868
+ background-color: #e53935;
869
+ box-shadow: 0 4px 15px rgba(229, 57, 53, 0.4);
870
  }
871
  .product-list, .category-list {
872
  display: grid;
 
881
  .edit-form {
882
  margin-top: 15px;
883
  padding: 15px;
884
+ background: #fce4ec;
885
  border-radius: 10px;
886
  }
887
  .color-input-group {
 
890
  margin-top: 5px;
891
  }
892
  .add-color-btn {
893
+ background-color: #4caf50;
894
  }
895
  .add-color-btn:hover {
896
+ background-color: #43a047;
897
  }
898
  </style>
899
  </head>