Kgshop commited on
Commit
464718f
·
verified ·
1 Parent(s): 5c5394b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -25
app.py CHANGED
@@ -1782,6 +1782,7 @@ SALES_SCREEN_CONTENT = """
1782
  <button id="stop-scan-btn" class="btn btn-danger btn-sm mt-2">Остановить</button>
1783
  </div>
1784
  <input type="text" id="product-search" class="form-control mb-3" placeholder="Поиск по названию или штрих-коду...">
 
1785
 
1786
  <div id="product-accordion" class="accordion">
1787
  {% for letter, products in grouped_inventory %}
@@ -1896,7 +1897,6 @@ SALES_SCREEN_SCRIPTS = """
1896
  <script>
1897
  document.addEventListener('DOMContentLoaded', () => {
1898
  const cart = {};
1899
- const productGrid = document.getElementById('product-accordion');
1900
  const cartItemsEl = document.getElementById('cart-items');
1901
  const cartTotalEl = document.getElementById('cart-total');
1902
  let audioCtx;
@@ -1907,6 +1907,7 @@ document.addEventListener('DOMContentLoaded', () => {
1907
  const cashierLoginModal = new bootstrap.Modal(document.getElementById('cashierLoginModal'));
1908
  const startShiftModal = new bootstrap.Modal(document.getElementById('startShiftModal'));
1909
  const customItemModal = new bootstrap.Modal(document.getElementById('customItemModal'));
 
1910
 
1911
  const session = {
1912
  cashier: null,
@@ -2026,7 +2027,8 @@ document.addEventListener('DOMContentLoaded', () => {
2026
  });
2027
  }
2028
 
2029
- productGrid.addEventListener('click', e => {
 
2030
  const card = e.target.closest('.product-card');
2031
  if (card) {
2032
  fetchAndHandleProduct(card.dataset.barcode);
@@ -2048,9 +2050,10 @@ document.addEventListener('DOMContentLoaded', () => {
2048
  cartItemsEl.addEventListener('click', e => {
2049
  if (e.target.classList.contains('cart-qty-btn')) {
2050
  const id = e.target.dataset.id;
2051
- const op = parseInt(e.target.dataset.op);
2052
  if (cart[id]) {
2053
- const newQuantity = cart[id].quantity + op;
 
2054
  updateCartItemQuantity(id, newQuantity);
2055
  }
2056
  }
@@ -2075,30 +2078,75 @@ document.addEventListener('DOMContentLoaded', () => {
2075
  updateCartView();
2076
  });
2077
 
2078
- document.getElementById('product-search').addEventListener('input', e => {
2079
- const term = e.target.value.toLowerCase();
2080
- const productCards = document.querySelectorAll('#product-accordion .product-card');
2081
- productCards.forEach(card => {
2082
- const productName = card.querySelector('.card-title').textContent.toLowerCase();
2083
- const barcode = card.dataset.barcode.toLowerCase();
2084
- const show = productName.includes(term) || barcode.includes(term);
2085
- card.style.display = show ? '' : 'none';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2086
  });
2087
- document.querySelectorAll('#product-accordion .accordion-item').forEach(accordionItem => {
2088
- const collapseElement = accordionItem.querySelector('.accordion-collapse');
2089
- const matchingCardsInGroup = accordionItem.querySelectorAll('.product-card:not([style*="display: none"])');
2090
- const bsCollapse = bootstrap.Collapse.getOrCreateInstance(collapseElement, { toggle: false });
2091
 
2092
- if (term === '') {
2093
- bsCollapse.hide();
2094
- } else {
2095
- if (matchingCardsInGroup.length > 0) {
2096
- bsCollapse.show();
2097
- } else {
2098
- bsCollapse.hide();
 
 
 
 
2099
  }
2100
  }
2101
- });
 
 
 
 
 
 
 
2102
  });
2103
 
2104
  const completeSale = (paymentMethod) => {
@@ -3424,4 +3472,3 @@ if __name__ == '__main__':
3424
  for key in DATA_FILES.keys():
3425
  load_json_data(key)
3426
  app.run(debug=False, host='0.0.0.0', port=7860, use_reloader=False)
3427
-
 
1782
  <button id="stop-scan-btn" class="btn btn-danger btn-sm mt-2">Остановить</button>
1783
  </div>
1784
  <input type="text" id="product-search" class="form-control mb-3" placeholder="Поиск по названию или штрих-коду...">
1785
+ <div id="product-search-results" class="d-grid gap-2" style="display: none; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));"></div>
1786
 
1787
  <div id="product-accordion" class="accordion">
1788
  {% for letter, products in grouped_inventory %}
 
1897
  <script>
1898
  document.addEventListener('DOMContentLoaded', () => {
1899
  const cart = {};
 
1900
  const cartItemsEl = document.getElementById('cart-items');
1901
  const cartTotalEl = document.getElementById('cart-total');
1902
  let audioCtx;
 
1907
  const cashierLoginModal = new bootstrap.Modal(document.getElementById('cashierLoginModal'));
1908
  const startShiftModal = new bootstrap.Modal(document.getElementById('startShiftModal'));
1909
  const customItemModal = new bootstrap.Modal(document.getElementById('customItemModal'));
1910
+ const allProducts = {{ inventory|tojson|safe }};
1911
 
1912
  const session = {
1913
  cashier: null,
 
2027
  });
2028
  }
2029
 
2030
+ const productsContainer = document.querySelector('.col-lg-7 .card .card-body');
2031
+ productsContainer.addEventListener('click', e => {
2032
  const card = e.target.closest('.product-card');
2033
  if (card) {
2034
  fetchAndHandleProduct(card.dataset.barcode);
 
2050
  cartItemsEl.addEventListener('click', e => {
2051
  if (e.target.classList.contains('cart-qty-btn')) {
2052
  const id = e.target.dataset.id;
2053
+ const op = parseInt(e.target.dataset.op, 10);
2054
  if (cart[id]) {
2055
+ const itemsPerPack = cart[id].items_per_pack || 1;
2056
+ let newQuantity = cart[id].quantity + (op * itemsPerPack);
2057
  updateCartItemQuantity(id, newQuantity);
2058
  }
2059
  }
 
2078
  updateCartView();
2079
  });
2080
 
2081
+ const formatCurrencyJS = (value) => {
2082
+ try {
2083
+ const number = parseFloat(String(value).replace(/\\s/g, '').replace(',', '.'));
2084
+ if (isNaN(number)) return '0,00';
2085
+ return number.toLocaleString('ru-RU', {minimumFractionDigits: 2, maximumFractionDigits: 2});
2086
+ } catch (e) {
2087
+ return '0,00';
2088
+ }
2089
+ };
2090
+
2091
+ const productSearchInput = document.getElementById('product-search');
2092
+ const productAccordionEl = document.getElementById('product-accordion');
2093
+ const productSearchResultsEl = document.getElementById('product-search-results');
2094
+
2095
+ productSearchInput.addEventListener('input', e => {
2096
+ const term = e.target.value.toLowerCase().trim();
2097
+
2098
+ if (term === '') {
2099
+ productAccordionEl.style.display = '';
2100
+ productSearchResultsEl.style.display = 'none';
2101
+ productSearchResultsEl.innerHTML = '';
2102
+ document.querySelectorAll('#product-accordion .accordion-collapse.show').forEach(el => {
2103
+ bootstrap.Collapse.getOrCreateInstance(el).hide();
2104
+ });
2105
+ return;
2106
+ }
2107
+
2108
+ productAccordionEl.style.display = 'none';
2109
+ productSearchResultsEl.style.display = 'grid';
2110
+
2111
+ const filtered = allProducts.filter(p => p.name.toLowerCase().includes(term) || p.barcode.toLowerCase().includes(term));
2112
+
2113
+ filtered.sort((a, b) => {
2114
+ const aName = a.name.toLowerCase();
2115
+ const bName = b.name.toLowerCase();
2116
+ const aStarts = aName.startsWith(term);
2117
+ const bStarts = bName.startsWith(term);
2118
+ const aBarcode = a.barcode.toLowerCase() === term;
2119
+ const bBarcode = b.barcode.toLowerCase() === term;
2120
+
2121
+ if (aBarcode && !bBarcode) return -1;
2122
+ if (!aBarcode && bBarcode) return 1;
2123
+ if (aStarts && !bStarts) return -1;
2124
+ if (!aStarts && bStarts) return 1;
2125
+
2126
+ return aName.localeCompare(bName);
2127
  });
 
 
 
 
2128
 
2129
+ productSearchResultsEl.innerHTML = filtered.length > 0 ? filtered.map(p => {
2130
+ let priceText = 'Нет в наличии';
2131
+ if (p.variants && p.variants.length > 0) {
2132
+ const activeVariants = p.variants.filter(v => v.stock > 0);
2133
+ if (activeVariants.length > 0) {
2134
+ if (activeVariants.length === 1) {
2135
+ priceText = `${formatCurrencyJS(activeVariants[0].price)} ₸`;
2136
+ } else {
2137
+ const prices = activeVariants.map(v => parseFloat(v.price));
2138
+ priceText = `от ${formatCurrencyJS(Math.min(...prices))} ₸`;
2139
+ }
2140
  }
2141
  }
2142
+ return `
2143
+ <div class="card text-center product-card" data-barcode="${p.barcode}">
2144
+ <div class="card-body p-2">
2145
+ <h6 class="card-title small mb-1">${p.name}</h6>
2146
+ <p class="card-text fw-bold mb-0">${priceText}</p>
2147
+ </div>
2148
+ </div>`;
2149
+ }).join('') : '<p class="text-muted text-center col-12">Товары не найдены.</p>';
2150
  });
2151
 
2152
  const completeSale = (paymentMethod) => {
 
3472
  for key in DATA_FILES.keys():
3473
  load_json_data(key)
3474
  app.run(debug=False, host='0.0.0.0', port=7860, use_reloader=False)