Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -16,7 +16,7 @@ import uuid
|
|
| 16 |
load_dotenv()
|
| 17 |
|
| 18 |
app = Flask(__name__)
|
| 19 |
-
app.secret_key = '
|
| 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': "
|
| 42 |
-
'brand_name': "
|
| 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': "Здравствуйте! Хочу подтвердить свой заказ на
|
| 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': 'Адрес
|
| 103 |
-
'address_1_detail': 'рынок Олжа,
|
| 104 |
-
'address_2_title': 'Адрес 2:',
|
| 105 |
-
'address_2_detail': 'рынок Олжа, VIP ряд, 56 бутик',
|
| 106 |
},
|
| 107 |
'kk': {
|
| 108 |
-
'site_title': "
|
| 109 |
-
'brand_name': "
|
| 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': "Сәлеметсіз бе! Мен
|
| 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': 'Мекенжай
|
| 170 |
-
'address_1_detail': 'Олжа базары, VIP қатары,
|
| 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: #
|
| 379 |
-
--primary-accent-hover: #
|
| 380 |
-
--secondary-accent: #
|
| 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(
|
| 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(
|
| 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(
|
| 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=+
|
| 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('
|
| 629 |
-
let favorites = JSON.parse(localStorage.getItem('
|
| 630 |
|
| 631 |
function openModal(modalId) {
|
| 632 |
const modal = document.getElementById(modalId);
|
|
@@ -750,7 +745,7 @@ CATALOG_TEMPLATE = '''
|
|
| 750 |
});
|
| 751 |
}
|
| 752 |
|
| 753 |
-
localStorage.setItem('
|
| 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('
|
| 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('
|
| 833 |
openCartModal();
|
| 834 |
updateCartButton();
|
| 835 |
}
|
|
@@ -858,7 +853,7 @@ CATALOG_TEMPLATE = '''
|
|
| 858 |
})
|
| 859 |
.then(data => {
|
| 860 |
if (data.order_id) {
|
| 861 |
-
localStorage.removeItem('
|
| 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('
|
| 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('
|
| 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 }} -
|
| 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: #
|
| 1106 |
-
--primary-accent-hover: #
|
| 1107 |
-
--secondary-accent: #
|
| 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(
|
| 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 = "+
|
| 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>Админ-панель -
|
| 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: #
|
| 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 #
|
| 1215 |
-
h1, h2, h3 { font-weight: 600; color: #
|
| 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: #
|
| 1219 |
-
.section { margin-bottom: 30px; padding: 20px; background-color: #
|
| 1220 |
form { margin-bottom: 20px; }
|
| 1221 |
-
label { font-weight: 500; margin-top: 10px; display: block; color: #
|
| 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 #
|
| 1223 |
-
input:focus, textarea:focus, select:focus { border-color: #
|
| 1224 |
textarea { min-height: 80px; resize: vertical; }
|
| 1225 |
-
input[type="file"] { padding: 8px; background-color: #
|
| 1226 |
-
input[type="file"]::file-selector-button { padding: 5px 10px; border-radius: 4px; background-color: #
|
| 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: #
|
| 1230 |
-
button:hover, .button:hover { background-color: #
|
| 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: #
|
| 1236 |
-
.add-button:hover { background-color: #
|
| 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 #
|
| 1239 |
-
.item p { margin: 5px 0; font-size: 0.9rem; color: #
|
| 1240 |
-
.item strong { color: #
|
| 1241 |
-
.item .description { font-size: 0.85rem; color: #
|
| 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: #
|
| 1244 |
-
.item-actions button:not(.delete-button):hover { background-color: #
|
| 1245 |
-
.edit-form-container { margin-top: 15px; padding: 20px; background: #
|
| 1246 |
-
details { background-color: #
|
| 1247 |
-
details > summary { cursor: pointer; font-weight: 600; color: #
|
| 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: #
|
| 1249 |
details[open] > summary::after { transform: translateY(-50%) rotate(180deg); }
|
| 1250 |
-
details[open] > summary { border-bottom: 1px solid #
|
| 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: #
|
| 1257 |
-
.add-color-btn:hover { background-color: #
|
| 1258 |
-
.photo-preview img { max-width: 70px; max-height: 70px; border-radius: 5px; margin: 5px 5px 0 0; border: 1px solid #
|
| 1259 |
.sync-buttons { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; }
|
| 1260 |
-
.download-hf-button { background-color: #
|
| 1261 |
-
.download-hf-button:hover { background-color: #
|
| 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: #
|
| 1279 |
-
<h1><i class="fas fa-tools"></i> Админ-панель
|
| 1280 |
</div>
|
| 1281 |
-
<a href="{{ url_for('catalog') }}" class="button" style="background-color: #
|
| 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: #
|
| 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>
|