1069 lines
51 KiB
Plaintext
1069 lines
51 KiB
Plaintext
@using System.Text.Encodings.Web
|
|
@{
|
|
Layout = "_Root";
|
|
ViewBag.Title = "Rendelés";
|
|
}
|
|
|
|
<link rel="stylesheet" href="~/Plugins/Misc.FruitBankPlugin/css/quick-order.css" />
|
|
<link rel="stylesheet" href="~/Plugins/Misc.FruitBankPlugin/css/preorder.css" />
|
|
|
|
<div class="quick-order-page">
|
|
|
|
<!-- ── STEP 1: Delivery date + time ─────────────────────────────────── -->
|
|
<div id="deliveryStep" class="qo-delivery-step">
|
|
<div class="ds-header">
|
|
<i class="fa fa-calendar"></i>
|
|
<div>
|
|
<div class="ds-title">Mikor kéred a rendelést?</div>
|
|
<div class="ds-subtitle">Válassz szállítási napot — a rendszer megmutatja, mi érhető el</div>
|
|
</div>
|
|
<a href="@Url.Action("Index", "Help")" class="ds-help-link" title="Hogyan működik?">
|
|
<i class="fa fa-question-circle"></i> Segítség
|
|
</a>
|
|
</div>
|
|
|
|
<!-- Collapsible how-it-works panel -->
|
|
<div class="ds-howto" id="howToPanel">
|
|
<button type="button" class="ds-howto-toggle" id="howToToggle">
|
|
<i class="fa fa-info-circle"></i> Hogyan működik a rendelés?
|
|
<i class="fa fa-chevron-down ds-howto-chevron" id="howToChevron"></i>
|
|
</button>
|
|
<div class="ds-howto-body" id="howToBody" style="display:none;">
|
|
<div class="ds-howto-row">
|
|
<div class="ds-howto-item green">
|
|
<div class="ds-howto-icon"><i class="fa fa-shopping-basket"></i></div>
|
|
<div class="ds-howto-title">Rendelés (azonnali)</div>
|
|
<div class="ds-howto-desc">Ha a kiválasztott szállítási nap <strong>csütörtöktől vasárnapig</strong> van ÉS erre a hétre esik, a raktárkészletből azonnal teljesítjük. Keresés vagy hangos bevitel alapján add a termékeket a kosárba.</div>
|
|
</div>
|
|
<div class="ds-howto-item amber">
|
|
<div class="ds-howto-icon"><i class="fa fa-calendar-plus-o"></i></div>
|
|
<div class="ds-howto-title">Előrendelés (jövő heti áru)</div>
|
|
<div class="ds-howto-desc">Ha a szállítást <strong>jövő hétre</strong> kéred (csütörtöktől), az áru még úton van. Leadhatsz kívánságlistát — amint megérkezik a szállítmány, automatikusan rendelés lesz belőle és értesítünk.</div>
|
|
</div>
|
|
</div>
|
|
<div class="ds-howto-tip">
|
|
<i class="fa fa-lightbulb-o"></i>
|
|
<strong>Tipp:</strong> Válassz ki egy napot lent — a rendszer azonnal jelzi, melyik típusú rendelésre számíthatsz.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="ds-body">
|
|
<div class="ds-section-label">Szállítási nap</div>
|
|
<div class="ds-day-buttons" id="dayButtons"></div>
|
|
<div id="flowPreviewBadge" class="ds-flow-preview" style="display:none;"></div>
|
|
<div class="ds-section-label" style="margin-top:20px;">Szállítási időpont</div>
|
|
<div class="ds-time-wrapper">
|
|
<input type="time" id="deliveryTimePicker" class="ds-time-input" value="08:00" min="05:00" max="22:00" />
|
|
<span class="ds-time-hint">Válassz pontos időpontot</span>
|
|
</div>
|
|
</div>
|
|
<div class="ds-footer">
|
|
<button type="button" class="ds-confirm-btn" id="deliveryConfirmBtn" disabled>
|
|
<i class="fa fa-arrow-right"></i> Termékek mutatása
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ── Delivery chip ────────────────────────────────────────────────── -->
|
|
<div id="deliveryChip" class="qo-delivery-chip" style="display:none;">
|
|
<i class="fa fa-calendar-check-o"></i>
|
|
<span class="dc-label">Szállítás:</span>
|
|
<strong id="deliveryChipText"></strong>
|
|
<span id="flowTypeBadge" class="of-flow-badge"></span>
|
|
<button type="button" class="dc-change-btn" id="deliveryChangeBtn">
|
|
<i class="fa fa-pencil"></i> Módosítás
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ── MAIN CONTENT (shown after delivery confirmed) ────────────────── -->
|
|
<div id="mainContent" style="display:none;">
|
|
|
|
<!-- ══ QUICK ORDER SECTION ══════════════════════════════════════════ -->
|
|
<div id="sectionQuickOrder" style="display:none;">
|
|
|
|
<!-- Search bar -->
|
|
<div class="qo-search-bar-wrapper">
|
|
<div class="search-input-group">
|
|
<button id="recordBtn" class="mic-btn" title="Hangfelvétel indítása">
|
|
<i class="fa fa-microphone"></i>
|
|
</button>
|
|
<button id="stopBtn" class="mic-btn mic-btn-recording" style="display:none;" title="Leállítás">
|
|
<i class="fa fa-stop"></i>
|
|
</button>
|
|
<input type="text" id="searchInput" class="qo-input"
|
|
placeholder="Keress termékeket (pl. narancs 100, alma 50) vagy használd a mikrofont..."
|
|
onkeypress="if(event.key==='Enter') submitTextSearch()">
|
|
<button class="qo-search-btn" onclick="submitTextSearch()">
|
|
<i class="fa fa-search"></i> Keresés
|
|
</button>
|
|
<button type="button" class="qo-hint-toggle" id="searchHintToggle">
|
|
<i class="fa fa-question-circle"></i> <span class="hint-toggle-label">Hogyan keress?</span>
|
|
</button>
|
|
</div>
|
|
<div class="qo-hint-row" style="display:none;"></div>
|
|
<div class="qo-input-hint" id="searchHintBody" style="display:none;">
|
|
<div class="qo-hint-item">
|
|
<i class="fa fa-keyboard-o"></i>
|
|
<div><strong>Szöveg:</strong> írd be a termékeket és mennyiségeket (pl. „narancs 100 alma 50”), majd nyomj Entert</div>
|
|
</div>
|
|
<div class="qo-hint-item">
|
|
<i class="fa fa-microphone"></i>
|
|
<div><strong>Hang:</strong> nyomj a mikrofon gombra és mondd be hangosan — a rendszer automatikusan leáll, mikor befejezed</div>
|
|
</div>
|
|
</div>
|
|
<div id="recordingStatus" class="recording-status-bar" style="display:none;">
|
|
<span id="statusText">Figyelés...</span>
|
|
<div class="volume-bar-container">
|
|
<div class="volume-bar volume-bar-silent"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="qo-layout">
|
|
<!-- LEFT: products -->
|
|
<div class="qo-products-panel">
|
|
<div id="transcribedCard" class="result-card" style="display:none;">
|
|
<div class="result-label"><i class="fa fa-microphone"></i> Hallottam:</div>
|
|
<div id="transcribedText" class="result-text"></div>
|
|
</div>
|
|
<div id="noResultsCard" class="no-results-card" style="display:none;">
|
|
<i class="fa fa-search"></i><p>Nem találtunk termékeket.</p>
|
|
</div>
|
|
<div id="productsLoadingState" class="products-empty-state">
|
|
<i class="fa fa-spinner fa-spin"></i><p>Termékek betöltése...</p>
|
|
</div>
|
|
<div id="productMatchesCard" style="display:none;">
|
|
<div class="matches-label">
|
|
<i class="fa fa-cubes"></i>
|
|
<span id="matchesLabelText">Összes termék</span>
|
|
— állítsd be a mennyiséget, majd add a kosárhoz:
|
|
</div>
|
|
<div id="productButtons" class="product-grid"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RIGHT: cart -->
|
|
<div class="qo-cart-panel">
|
|
<div class="qo-section-title">
|
|
<i class="fa fa-shopping-basket"></i> Kosár
|
|
<span id="cartItemCount" class="cart-count-badge">0</span>
|
|
</div>
|
|
<div id="cartEmptyState" class="cart-empty">
|
|
<i class="fa fa-shopping-basket"></i>
|
|
<p>A kosár üres.<br>Keress termékeket és add hozzá őket.</p>
|
|
</div>
|
|
<div id="cartItemsList" class="cart-items-list" style="display:none;"></div>
|
|
<div id="cartTotalRow" class="cart-total-row" style="display:none;">
|
|
<div class="cart-total-note">
|
|
<i class="fa fa-info-circle"></i>
|
|
<small>A súlymérést igénylő tételeknél az ár a mérés után véglegesedik.</small>
|
|
</div>
|
|
<div class="cart-total">
|
|
<span>Becsült összeg:</span>
|
|
<strong id="cartTotalAmount">0 Ft</strong>
|
|
</div>
|
|
</div>
|
|
<div id="cartActions" style="display:none;">
|
|
<a href="@Url.Action("Cart", "ShoppingCart")" class="btn-checkout">
|
|
<i class="fa fa-shopping-cart"></i> Tovább a pénztárhoz
|
|
</a>
|
|
<a href="@Url.Action("Cart", "ShoppingCart")" class="btn-view-cart">
|
|
<i class="fa fa-eye"></i> Kosár megtekintése
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div><!-- /#sectionQuickOrder -->
|
|
|
|
<!-- ══ PREORDER SECTION ══════════════════════════════════════════════ -->
|
|
<div id="sectionPreorder" style="display:none;">
|
|
<div class="po-info-banner">
|
|
<i class="fa fa-info-circle"></i>
|
|
Az előrendelés egy kívánságlista — az áruk megerősítése a szállítmány beérkezésekor történik, és az esetleges változásokról értesítünk.
|
|
</div>
|
|
|
|
<div class="qo-layout">
|
|
<!-- LEFT: products + submit -->
|
|
<div class="qo-products-panel">
|
|
<div id="poLoadingState" class="products-empty-state">
|
|
<i class="fa fa-spinner fa-spin"></i><p>Elérhető termékek betöltése...</p>
|
|
</div>
|
|
<div id="poNoProducts" class="no-results-card" style="display:none;">
|
|
<i class="fa fa-calendar-times-o"></i>
|
|
<p>Jelenleg nincs előrendelhető termék. Kérjük, látogass vissza később.</p>
|
|
</div>
|
|
<div id="poProductSection" style="display:none;">
|
|
<div class="matches-label">
|
|
<i class="fa fa-cubes"></i>
|
|
<span>Előrendelhető termékek — add meg a mennyiségeket:</span>
|
|
</div>
|
|
<div id="poProductGrid" class="product-grid"></div>
|
|
|
|
<div class="po-note-section">
|
|
<label class="po-note-label" for="customerNote">
|
|
<i class="fa fa-comment-o"></i> Megjegyzés (nem kötelező)
|
|
</label>
|
|
<textarea id="customerNote" class="po-note-input"
|
|
placeholder="Esetleges megjegyzések az előrendeléssel kapcsolatban..."
|
|
rows="3" maxlength="1000"></textarea>
|
|
</div>
|
|
|
|
<div class="po-submit-row">
|
|
<div id="poSelectionSummary" class="po-selection-summary">Még nincs kiválasztott termék</div>
|
|
<button type="button" id="submitPreorderBtn" class="po-submit-btn" disabled>
|
|
<i class="fa fa-paper-plane"></i> Előrendelés leadása
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- RIGHT: summary -->
|
|
<div class="qo-cart-panel">
|
|
<div class="qo-section-title">
|
|
<i class="fa fa-list-ul"></i> Előrendelésed
|
|
<span id="poItemCountBadge" class="cart-count-badge">0</span>
|
|
</div>
|
|
<div id="poSummaryEmpty" class="cart-empty">
|
|
<i class="fa fa-list-ul"></i>
|
|
<p>Add meg a mennyiségeket a termékeknél.</p>
|
|
</div>
|
|
<div id="poSummaryList" class="cart-items-list" style="display:none;"></div>
|
|
<div id="poSummaryNote" class="cart-total-row" style="display:none;">
|
|
<div class="cart-total-note">
|
|
<i class="fa fa-info-circle"></i>
|
|
<small>A súlymérést igénylő tételeknél az ár a mérés után véglegesedik. A mennyiségek a tényleges szállítmánytól függően változhatnak.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div><!-- /#sectionPreorder -->
|
|
|
|
</div><!-- /#mainContent -->
|
|
|
|
<!-- ── Preorder success state ────────────────────────────────────────── -->
|
|
<div id="successState" style="display:none;" class="po-success-state">
|
|
<div class="po-success-icon"><i class="fa fa-check-circle"></i></div>
|
|
<h2>Előrendelés leadva!</h2>
|
|
<p id="successMessage"></p>
|
|
<a href="@Url.RouteUrl("Homepage")" class="po-back-btn">
|
|
<i class="fa fa-home"></i> Vissza a főoldalra
|
|
</a>
|
|
</div>
|
|
|
|
</div><!-- /.quick-order-page -->
|
|
|
|
@Html.AntiForgeryToken()
|
|
|
|
<style>
|
|
/* ── Flow type badge on delivery chip ─────────────────────── */
|
|
.of-flow-badge {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
border-radius: 4px;
|
|
padding: 2px 8px;
|
|
margin-left: 6px;
|
|
}
|
|
.of-flow-badge.quickorder {
|
|
background: rgba(140,182,60,0.25);
|
|
color: #8cb63c;
|
|
}
|
|
.of-flow-badge.preorder {
|
|
background: rgba(244,162,54,0.2);
|
|
color: #f4a236;
|
|
}
|
|
|
|
/* ── Help link in header ─────────────────────────────────── */
|
|
.ds-header {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 14px;
|
|
position: relative;
|
|
}
|
|
.ds-help-link {
|
|
margin-left: auto;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: #6b7c6e;
|
|
text-decoration: none;
|
|
white-space: nowrap;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
padding: 4px 10px;
|
|
border: 1px solid #dde8da;
|
|
border-radius: 6px;
|
|
transition: all 0.15s;
|
|
}
|
|
.ds-help-link:hover {
|
|
background: #f5f7f2;
|
|
color: #2d7a3a;
|
|
border-color: #2d7a3a;
|
|
}
|
|
|
|
/* ── How-it-works collapsible panel ────────────────────── */
|
|
.ds-howto {
|
|
margin: 14px 0 0;
|
|
border: 1px solid #dde8da;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
}
|
|
.ds-howto-toggle {
|
|
width: 100%;
|
|
background: #f5f7f2;
|
|
border: none;
|
|
padding: 12px 16px;
|
|
text-align: left;
|
|
font-family: 'DM Sans', sans-serif;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: #2d7a3a;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
.ds-howto-toggle:hover { background: #eaf3de; }
|
|
.ds-howto-chevron {
|
|
margin-left: auto;
|
|
transition: transform 0.2s;
|
|
font-size: 11px;
|
|
color: #6b7c6e;
|
|
}
|
|
.ds-howto-body {
|
|
padding: 16px;
|
|
background: #fff;
|
|
border-top: 1px solid #dde8da;
|
|
}
|
|
.ds-howto-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 12px;
|
|
margin-bottom: 14px;
|
|
}
|
|
.ds-howto-item {
|
|
padding: 14px;
|
|
border-radius: 8px;
|
|
border: 1px solid;
|
|
}
|
|
.ds-howto-item.green {
|
|
background: #eaf3de;
|
|
border-color: #a8d08d;
|
|
}
|
|
.ds-howto-item.amber {
|
|
background: #fff8ee;
|
|
border-color: #f4c87a;
|
|
}
|
|
.ds-howto-icon {
|
|
font-size: 20px;
|
|
margin-bottom: 6px;
|
|
}
|
|
.ds-howto-item.green .ds-howto-icon { color: #2d7a3a; }
|
|
.ds-howto-item.amber .ds-howto-icon { color: #c87500; }
|
|
.ds-howto-title {
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
margin-bottom: 6px;
|
|
}
|
|
.ds-howto-item.green .ds-howto-title { color: #1a3c22; }
|
|
.ds-howto-item.amber .ds-howto-title { color: #7a4200; }
|
|
.ds-howto-desc {
|
|
font-size: 12px;
|
|
line-height: 1.5;
|
|
color: #444;
|
|
}
|
|
.ds-howto-tip {
|
|
background: #f5f7f2;
|
|
border-radius: 6px;
|
|
padding: 10px 12px;
|
|
font-size: 12px;
|
|
color: #6b7c6e;
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 8px;
|
|
line-height: 1.5;
|
|
}
|
|
.ds-howto-tip .fa { color: #f4a236; flex-shrink: 0; margin-top: 1px; }
|
|
|
|
/* ── Flow preview badge below day buttons ──────────────────── */
|
|
.ds-flow-preview {
|
|
margin-top: 10px;
|
|
padding: 8px 14px;
|
|
border-radius: 6px;
|
|
font-size: 13px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
animation: fadeIn 0.2s ease;
|
|
}
|
|
.ds-flow-preview.flow-quick {
|
|
background: #eaf3de;
|
|
color: #1a3c22;
|
|
border: 1px solid #a8d08d;
|
|
}
|
|
.ds-flow-preview.flow-pre {
|
|
background: #fff8ee;
|
|
color: #7a4200;
|
|
border: 1px solid #f4c87a;
|
|
}
|
|
@@keyframes fadeIn { from { opacity:0; transform:translateY(-4px); } to { opacity:1; transform:translateY(0); } }
|
|
|
|
/* ── Preorder stock label variant ──────────────────────────── */
|
|
.pc-stock.stock-preorder {
|
|
color: #c87500;
|
|
font-style: italic;
|
|
font-size: 12px;
|
|
}
|
|
|
|
/* ── Search input hint strip ─────────────────────────────── */
|
|
.qo-search-bar-wrapper { position: relative; }
|
|
|
|
.qo-hint-row {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
.qo-hint-toggle {
|
|
background: none;
|
|
border: none;
|
|
border-left: 1px solid #dde8da;
|
|
border-radius: 0;
|
|
padding: 0 14px;
|
|
height: 100%;
|
|
font-family: 'DM Sans', sans-serif;
|
|
font-size: 12px;
|
|
font-weight: 600;
|
|
color: #6b7c6e;
|
|
cursor: pointer;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
transition: all 0.15s;
|
|
white-space: nowrap;
|
|
flex-shrink: 0;
|
|
}
|
|
.qo-hint-toggle:hover, .qo-hint-toggle.active {
|
|
background: #f5f7f2;
|
|
color: #2d7a3a;
|
|
}
|
|
|
|
/* On mobile: icon only, no text label */
|
|
@@media (max-width: 600px) {
|
|
.hint-toggle-label { display: none; }
|
|
.qo-hint-toggle { padding: 0 10px; }
|
|
}
|
|
|
|
.qo-input-hint {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
margin-top: 6px;
|
|
padding: 10px 14px;
|
|
background: #f5f7f2;
|
|
border: 1px solid #dde8da;
|
|
border-radius: 8px;
|
|
font-size: 12px;
|
|
color: #4a5e4d;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.qo-hint-item {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 8px;
|
|
}
|
|
|
|
.qo-hint-item .fa { color: #2d7a3a; flex-shrink: 0; margin-top: 2px; font-size: 13px; }
|
|
.qo-hint-item .fa-microphone { color: #f4a236; }
|
|
|
|
.qo-hint-sep {
|
|
font-size: 11px;
|
|
font-weight: 700;
|
|
text-transform: uppercase;
|
|
letter-spacing: .5px;
|
|
color: #aab8ac;
|
|
align-self: center;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
/* Desktop: pull toggle button into the search input row */
|
|
@@media (min-width: 601px) {
|
|
.qo-hint-row { display: none; }
|
|
}
|
|
</style>
|
|
|
|
<script asp-location="Footer">
|
|
// ── State ─────────────────────────────────────────────────────────────────
|
|
var selectedDeliveryDate = null;
|
|
var selectedDeliveryTime = null;
|
|
var selectedDayLabel = null;
|
|
var currentFlowType = null; // "quickorder" | "preorder"
|
|
|
|
// Preorder state
|
|
var poProducts = [];
|
|
var poQuantities = {};
|
|
|
|
// Quick Order VAD state
|
|
var mediaRecorder = null, audioChunks = [], isRecording = false;
|
|
var audioContext = null, analyser = null, volumeCheckInterval = null;
|
|
var recordingStartTime = null, baselineNoiseLevel = -60, volumeHistory = [];
|
|
var VAD_CONFIG = { silenceDuration:1500, minRecordingTime:800, volumeCheckInterval:100,
|
|
calibrationTime:500, noiseGateOffset:15, volumeHistorySize:10 };
|
|
|
|
var huDayNames = ['vasárnap','hétfő','kedd','szerda','csütörtök','péntek','szombat'];
|
|
|
|
// ── Init ──────────────────────────────────────────────────────────────────
|
|
$(document).ready(function () {
|
|
renderDayButtons();
|
|
|
|
$(document).on('click', '.ds-day-btn', function () {
|
|
$('.ds-day-btn').removeClass('selected');
|
|
$(this).addClass('selected');
|
|
selectedDeliveryDate = $(this).data('date');
|
|
selectedDayLabel = $(this).data('label');
|
|
checkDeliveryReady();
|
|
// Show flow preview badge immediately
|
|
var flow = computeFlowType(selectedDeliveryDate);
|
|
var badge = $('#flowPreviewBadge');
|
|
if (flow === 'quickorder') {
|
|
badge.html('<i class="fa fa-shopping-basket"></i> <strong>Rendelés</strong> — ez a nap raktárkészletből teljesíthető').attr('class','ds-flow-preview flow-quick').show();
|
|
} else {
|
|
badge.html('<i class="fa fa-calendar-plus-o"></i> <strong>Előrendelés</strong> — az áru még úton van, kívánságlistát adhat le').attr('class','ds-flow-preview flow-pre').show();
|
|
}
|
|
});
|
|
|
|
$('#deliveryTimePicker').on('input change', function () {
|
|
selectedDeliveryTime = $(this).val() || null;
|
|
checkDeliveryReady();
|
|
});
|
|
selectedDeliveryTime = $('#deliveryTimePicker').val() || null;
|
|
|
|
$('#deliveryConfirmBtn').click(confirmDelivery);
|
|
$('#deliveryChangeBtn').click(function () {
|
|
$('#deliveryChip, #mainContent').hide();
|
|
$('#deliveryStep').show();
|
|
});
|
|
|
|
$('#recordBtn').click(startRecording);
|
|
$('#stopBtn').click(function () { stopRecording(false); });
|
|
$('#submitPreorderBtn').click(submitPreorder);
|
|
|
|
// Restore saved datetime
|
|
$.ajax({
|
|
url: '@Url.Action("GetDeliveryDateTime", "Order")',
|
|
type: 'GET',
|
|
success: function (r) {
|
|
if (!r.success || !r.hasValue) return;
|
|
selectedDeliveryDate = r.date;
|
|
selectedDeliveryTime = r.time;
|
|
var $btn = $('.ds-day-btn[data-date="' + r.date + '"]');
|
|
if ($btn.length) { $btn.addClass('selected'); selectedDayLabel = $btn.data('label'); }
|
|
else { selectedDayLabel = r.date; }
|
|
$('#deliveryTimePicker').val(r.time);
|
|
activateFlow(r.flowType);
|
|
}
|
|
});
|
|
|
|
loadCart();
|
|
|
|
// How-to panel toggle
|
|
$('#howToToggle').click(function () {
|
|
var $body = $('#howToBody');
|
|
var open = $body.is(':visible');
|
|
$body.slideToggle(200);
|
|
$('#howToChevron').css('transform', open ? 'rotate(0deg)' : 'rotate(180deg)');
|
|
});
|
|
|
|
// Search hint toggle with 20-second auto-collapse
|
|
var hintTimer = null;
|
|
function openHint() {
|
|
$('#searchHintBody').slideDown(180);
|
|
$('#searchHintToggle').addClass('active');
|
|
clearTimeout(hintTimer);
|
|
hintTimer = setTimeout(closeHint, 20000);
|
|
}
|
|
function closeHint() {
|
|
$('#searchHintBody').slideUp(180);
|
|
$('#searchHintToggle').removeClass('active');
|
|
clearTimeout(hintTimer);
|
|
}
|
|
$('#searchHintToggle').click(function () {
|
|
if ($('#searchHintBody').is(':visible')) closeHint();
|
|
else openHint();
|
|
});
|
|
});
|
|
|
|
// ── Day buttons ───────────────────────────────────────────────────────────
|
|
function renderDayButtons() {
|
|
var c = $('#dayButtons').empty();
|
|
var today = new Date();
|
|
for (var i = 0; i < 14; i++) {
|
|
var d = new Date(today);
|
|
d.setDate(today.getDate() + i);
|
|
var iso = d.toISOString().split('T')[0];
|
|
var name = i === 0 ? 'Ma' : i === 1 ? 'Holnap' : huDayNames[d.getDay()];
|
|
var dateStr = (d.getMonth() + 1) + '. ' + d.getDate() + '.';
|
|
c.append($('<button type="button" class="ds-day-btn">')
|
|
.attr('data-date', iso).attr('data-label', name + ' ' + dateStr)
|
|
.html('<span class="ds-day-name">' + name + '</span><span class="ds-day-date">' + dateStr + '</span>'));
|
|
}
|
|
}
|
|
|
|
function checkDeliveryReady() {
|
|
$('#deliveryConfirmBtn').prop('disabled', !(selectedDeliveryDate && selectedDeliveryTime));
|
|
}
|
|
|
|
// ── Flow type determination (mirrors server-side logic) ───────────────────
|
|
function computeFlowType(isoDate) {
|
|
var today = new Date();
|
|
var todayDow = today.getDay(); // 0=Sun
|
|
|
|
var daysSinceMon = todayDow === 0 ? 6 : todayDow - 1;
|
|
var weekStart = new Date(today); weekStart.setDate(today.getDate() - daysSinceMon); weekStart.setHours(0,0,0,0);
|
|
var thisThursday = new Date(weekStart); thisThursday.setDate(weekStart.getDate() + 3); thisThursday.setHours(0,0,0,0);
|
|
var weekEnd = new Date(weekStart); weekEnd.setDate(weekStart.getDate() + 6); weekEnd.setHours(23,59,59,999);
|
|
|
|
var delivery = new Date(isoDate); delivery.setHours(12,0,0,0);
|
|
|
|
var deliveryBeforeThursday = delivery < thisThursday;
|
|
var isLateWeek = (todayDow === 0 || todayDow >= 4);
|
|
var deliveryThisWeek = delivery >= weekStart && delivery <= weekEnd;
|
|
|
|
return (deliveryBeforeThursday || (isLateWeek && deliveryThisWeek)) ? 'quickorder' : 'preorder';
|
|
}
|
|
|
|
// ── Confirm delivery ──────────────────────────────────────────────────────
|
|
function confirmDelivery() {
|
|
var btn = $('#deliveryConfirmBtn').prop('disabled', true)
|
|
.html('<i class="fa fa-spinner fa-spin"></i> Mentés...');
|
|
|
|
$.ajax({
|
|
url : '@Url.Action("SetDeliveryDateTime", "Order")',
|
|
type: 'POST',
|
|
data: { deliveryDateTime: selectedDeliveryDate + 'T' + selectedDeliveryTime,
|
|
__RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
|
|
success: function (r) {
|
|
if (!r.success) {
|
|
alert('Hiba: ' + (r.message || ''));
|
|
btn.prop('disabled', false).html('<i class="fa fa-arrow-right"></i> Termékek mutatása');
|
|
return;
|
|
}
|
|
activateFlow(r.flowType);
|
|
},
|
|
error: function () {
|
|
btn.prop('disabled', false).html('<i class="fa fa-arrow-right"></i> Termékek mutatása');
|
|
}
|
|
});
|
|
}
|
|
|
|
function activateFlow(flowType) {
|
|
currentFlowType = flowType;
|
|
var chipText = selectedDayLabel + ' \u2014 ' + selectedDeliveryTime;
|
|
$('#deliveryChipText').text(chipText);
|
|
|
|
var badge = $('#flowTypeBadge');
|
|
if (flowType === 'quickorder') {
|
|
badge.text('Rendelés').attr('class', 'of-flow-badge quickorder');
|
|
} else {
|
|
badge.text('Előrendelés').attr('class', 'of-flow-badge preorder');
|
|
}
|
|
|
|
$('#deliveryStep').hide();
|
|
$('#deliveryChip, #mainContent').show();
|
|
|
|
if (flowType === 'quickorder') {
|
|
$('#sectionQuickOrder').show();
|
|
$('#sectionPreorder').hide();
|
|
loadAllProducts();
|
|
} else {
|
|
$('#sectionPreorder').show();
|
|
$('#sectionQuickOrder').hide();
|
|
loadPreorderProducts();
|
|
}
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// QUICK ORDER FLOW
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
function loadAllProducts() {
|
|
$('#transcribedCard').hide();
|
|
$('#noResultsCard').hide();
|
|
$('#productMatchesCard').hide();
|
|
$('#productsLoadingState').show();
|
|
$('#matchesLabelText').text('Összes termék');
|
|
|
|
$.ajax({
|
|
url : '@Url.Action("GetAllProducts", "Order")',
|
|
type : 'GET',
|
|
data : { deliveryDate: selectedDeliveryDate, deliveryTime: selectedDeliveryTime },
|
|
success: function (r) {
|
|
$('#productsLoadingState').hide();
|
|
if (r.success && r.products && r.products.length > 0) displayQOProducts(r.products);
|
|
else $('#noResultsCard').show();
|
|
},
|
|
error : function () { $('#productsLoadingState').hide(); $('#noResultsCard').show(); }
|
|
});
|
|
}
|
|
|
|
function displayQOProducts(products) {
|
|
var container = $('#productButtons').empty();
|
|
var grouped = {};
|
|
for (var i = 0; i < products.length; i++) {
|
|
var key = products[i].searchTerm || '';
|
|
if (!grouped[key]) grouped[key] = [];
|
|
grouped[key].push(products[i]);
|
|
}
|
|
var keys = Object.keys(grouped);
|
|
var multiGroup = keys.length > 1 || (keys.length === 1 && keys[0] !== '');
|
|
|
|
for (var g = 0; g < keys.length; g++) {
|
|
var term = keys[g];
|
|
if (multiGroup && term) container.append('<div class="group-label"><i class="fa fa-tag"></i> ' + term + '</div>');
|
|
var group = grouped[term];
|
|
for (var p = 0; p < group.length; p++) {
|
|
(function (product) {
|
|
var maxQty = product.stockQuantity;
|
|
var defaultQty = product.quantity || 1;
|
|
var priceHtml = product.isMeasurable
|
|
? '<span class="measurable-badge"><i class="fa fa-balance-scale"></i> Súlymérést igényel</span>'
|
|
: '<span class="pm-price">' + fmt(product.unitPrice) + ' Ft/db</span>';
|
|
var warningHtml = product.isQuantityReduced
|
|
? '<div class="stock-warning-badge"><i class="fa fa-exclamation-triangle"></i> Csak ' + maxQty + ' db elérhető</div>' : '';
|
|
|
|
var card = $('<div>').addClass('product-card' + (product.isQuantityReduced ? ' has-warning' : ''));
|
|
card.html(
|
|
'<div class="pc-body">' +
|
|
'<div class="pc-name"><i class="fa fa-cube"></i> ' + product.name + '</div>' +
|
|
warningHtml +
|
|
'<div class="pc-meta">' +
|
|
'<span class="pc-stock' + (maxQty < 50 ? ' stock-low' : '') + '">Készlet: ' + maxQty + ' db</span>' +
|
|
priceHtml +
|
|
'</div>' +
|
|
'</div>' +
|
|
'<div class="pc-actions">' +
|
|
'<div class="qty-stepper">' +
|
|
'<button type="button" class="qty-btn qty-minus" tabindex="-1"><i class="fa fa-minus"></i></button>' +
|
|
'<input type="number" class="qty-input" value="' + defaultQty + '" min="1" max="' + maxQty + '">' +
|
|
'<button type="button" class="qty-btn qty-plus" tabindex="-1"><i class="fa fa-plus"></i></button>' +
|
|
'</div>' +
|
|
'<button type="button" class="pc-add-btn" title="Kosárba"><i class="fa fa-cart-arrow-down"></i></button>' +
|
|
'</div>'
|
|
);
|
|
card.find('.qty-minus').click(function () {
|
|
var inp = $(this).siblings('.qty-input'); var v = parseInt(inp.val()) || 1; if (v > 1) inp.val(v - 1);
|
|
});
|
|
card.find('.qty-plus').click(function () {
|
|
var inp = $(this).siblings('.qty-input'); var v = parseInt(inp.val()) || 1; if (v < maxQty) inp.val(v + 1);
|
|
});
|
|
card.find('.qty-input').on('change blur', function () {
|
|
var v = parseInt($(this).val()) || 1; v = Math.max(1, Math.min(maxQty, v)); $(this).val(v);
|
|
});
|
|
card.find('.pc-add-btn').click(function () {
|
|
addToCart(product.id, parseInt(card.find('.qty-input').val()) || 1, product.name, $(this));
|
|
});
|
|
container.append(card);
|
|
})(group[p]);
|
|
}
|
|
}
|
|
$('#productMatchesCard').show();
|
|
}
|
|
|
|
function addToCart(productId, quantity, name, btnEl) {
|
|
btnEl.prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i>');
|
|
$.ajax({
|
|
url : '@Url.Action("AddToCart", "Order")',
|
|
type: 'POST',
|
|
data: { productId: productId, quantity: quantity,
|
|
__RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
|
|
success: function (r) {
|
|
if (r.success) {
|
|
btnEl.html('<i class="fa fa-check"></i>').addClass('added');
|
|
renderCart(r.cartItems);
|
|
showCartToast(name, quantity);
|
|
setTimeout(function () { $('#searchInput').val(''); $('#transcribedCard').hide(); loadAllProducts(); }, 700);
|
|
} else {
|
|
alert('Hiba: ' + r.message);
|
|
btnEl.prop('disabled', false).html('<i class="fa fa-cart-arrow-down"></i>');
|
|
}
|
|
},
|
|
error: function () {
|
|
btnEl.prop('disabled', false).html('<i class="fa fa-cart-arrow-down"></i>');
|
|
}
|
|
});
|
|
}
|
|
|
|
function loadCart() {
|
|
$.ajax({ url: '@Url.Action("GetCartItems", "Order")', type: 'GET',
|
|
success: function (r) { if (r.success) renderCart(r.cartItems); } });
|
|
}
|
|
|
|
function renderCart(items) {
|
|
var list = $('#cartItemsList').empty();
|
|
var count = items.length;
|
|
$('#cartItemCount').text(count);
|
|
if (count === 0) {
|
|
$('#cartEmptyState').show(); $('#cartItemsList, #cartTotalRow, #cartActions').hide(); return;
|
|
}
|
|
$('#cartEmptyState').hide(); $('#cartItemsList, #cartTotalRow, #cartActions').show();
|
|
var total = 0, hasMeasurable = false;
|
|
for (var i = 0; i < items.length; i++) {
|
|
var item = items[i];
|
|
if (item.isMeasurable) hasMeasurable = true;
|
|
var lineTotal = item.isMeasurable ? null : item.unitPrice * item.quantity;
|
|
if (lineTotal) total += lineTotal;
|
|
var lineTotalHtml = item.isMeasurable
|
|
? '<span class="measurable-badge-sm"><i class="fa fa-balance-scale"></i></span>'
|
|
: '<strong class="line-total">' + fmt(lineTotal) + ' Ft</strong>';
|
|
var priceHtml = item.isMeasurable ? '' : '<span class="ci-price">' + fmt(item.unitPrice) + ' Ft/db</span>';
|
|
list.append('<div class="cart-item"><div class="ci-name">' + item.name + '</div>' +
|
|
'<div class="ci-details"><span class="ci-qty">' + item.quantity + ' db</span>' +
|
|
priceHtml + lineTotalHtml + '</div></div>');
|
|
}
|
|
$('#cartTotalAmount').text(fmt(total) + ' Ft');
|
|
if (hasMeasurable) $('#cartTotalRow .cart-total-note').show();
|
|
else $('#cartTotalRow .cart-total-note').hide();
|
|
}
|
|
|
|
function showCartToast(name, qty) {
|
|
var t = $('<div class="qo-toast"><i class="fa fa-check-circle"></i> <strong>' + name + '</strong> (' + qty + ' db) hozzáadva</div>');
|
|
$('body').append(t);
|
|
setTimeout(function () { t.addClass('show'); }, 10);
|
|
setTimeout(function () { t.removeClass('show'); setTimeout(function () { t.remove(); }, 400); }, 2500);
|
|
}
|
|
|
|
// Voice recording (same as QuickOrder page)
|
|
function getSupportedMimeType() {
|
|
var types = ['audio/webm','audio/webm;codecs=opus','audio/ogg;codecs=opus','audio/mp4'];
|
|
for (var i = 0; i < types.length; i++) if (MediaRecorder.isTypeSupported(types[i])) return types[i];
|
|
return 'audio/webm';
|
|
}
|
|
function startRecording() {
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) { alert('A böngésző nem támogatja a hangfelvételt.'); return; }
|
|
navigator.mediaDevices.getUserMedia({ audio: true }).then(function (stream) {
|
|
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
analyser = audioContext.createAnalyser();
|
|
audioContext.createMediaStreamSource(stream).connect(analyser);
|
|
analyser.fftSize = 512;
|
|
var mimeType = getSupportedMimeType();
|
|
mediaRecorder = new MediaRecorder(stream, { mimeType: mimeType });
|
|
audioChunks = []; recordingStartTime = Date.now(); isRecording = true;
|
|
mediaRecorder.addEventListener('dataavailable', function (e) { audioChunks.push(e.data); });
|
|
mediaRecorder.addEventListener('stop', function () {
|
|
var blob = new Blob(audioChunks, { type: mimeType });
|
|
stream.getTracks().forEach(function (t) { t.stop(); });
|
|
if (audioContext) { audioContext.close(); audioContext = null; }
|
|
analyser = null; isRecording = false;
|
|
if (blob.size === 0) { alert('Nem sikerült hangot rögzíteni.'); resetRecordingUI(); return; }
|
|
processAudio(blob, mimeType);
|
|
});
|
|
mediaRecorder.start();
|
|
$('#recordBtn').hide(); $('#stopBtn').show();
|
|
$('#searchInput').attr('placeholder', 'Figyelés... (kezdj el beszélni)');
|
|
showStatus('Figyelés...'); startVAD();
|
|
}).catch(function (err) { alert('Nem sikerült a mikrofon elérése: ' + err.message); });
|
|
}
|
|
function startVAD() {
|
|
var bufferLength = analyser.frequencyBinCount, dataArray = new Uint8Array(bufferLength);
|
|
if (volumeCheckInterval) clearInterval(volumeCheckInterval);
|
|
var silentChecks = 0, silentNeeded = Math.ceil(VAD_CONFIG.silenceDuration / VAD_CONFIG.volumeCheckInterval);
|
|
var calibrated = false, calibSamples = []; volumeHistory = [];
|
|
volumeCheckInterval = setInterval(function () {
|
|
if (!isRecording || !analyser) { clearInterval(volumeCheckInterval); return; }
|
|
analyser.getByteFrequencyData(dataArray);
|
|
var sum = 0; for (var i = 0; i < bufferLength; i++) sum += dataArray[i];
|
|
var volume = 20 * Math.log10((sum / bufferLength) / 255);
|
|
var elapsed = Date.now() - recordingStartTime;
|
|
if (!calibrated && elapsed < VAD_CONFIG.calibrationTime) { calibSamples.push(volume); return; }
|
|
if (!calibrated && calibSamples.length > 0) {
|
|
var tot = 0; for (var j = 0; j < calibSamples.length; j++) tot += calibSamples[j];
|
|
baselineNoiseLevel = tot / calibSamples.length; calibrated = true;
|
|
}
|
|
volumeHistory.push(volume);
|
|
if (volumeHistory.length > VAD_CONFIG.volumeHistorySize) volumeHistory.shift();
|
|
var vs = 0; for (var k = 0; k < volumeHistory.length; k++) vs += volumeHistory[k];
|
|
var avgVol = vs / volumeHistory.length;
|
|
var threshold = baselineNoiseLevel + VAD_CONFIG.noiseGateOffset;
|
|
var norm = Math.max(0, Math.min(100, ((volume - threshold + 10) / 40) * 100));
|
|
var text = 'Figyelés...', cls = 'volume-bar-silent';
|
|
if (norm > 60) { text = 'Hangos és érthető'; cls = 'volume-bar-high'; }
|
|
else if (norm > 30) { text = 'Beszél...'; cls = 'volume-bar-medium'; }
|
|
else if (norm > 10) { text = 'Hangosabban!'; cls = 'volume-bar-low'; }
|
|
$('#statusText').text(text);
|
|
$('#recordingStatus .volume-bar').removeClass('volume-bar-low volume-bar-medium volume-bar-high volume-bar-silent').addClass(cls).css('width', norm + '%');
|
|
if (elapsed < VAD_CONFIG.minRecordingTime) return;
|
|
if (avgVol < threshold) { silentChecks++; if (silentChecks >= silentNeeded) { clearInterval(volumeCheckInterval); stopRecording(true); } }
|
|
else { silentChecks = 0; }
|
|
}, VAD_CONFIG.volumeCheckInterval);
|
|
}
|
|
function stopRecording(auto) {
|
|
if (volumeCheckInterval) { clearInterval(volumeCheckInterval); volumeCheckInterval = null; }
|
|
if (mediaRecorder && mediaRecorder.state !== 'inactive') { showStatus('Feldolgozás...'); mediaRecorder.stop(); }
|
|
}
|
|
function processAudio(blob, mimeType) {
|
|
var formData = new FormData();
|
|
formData.append('audioFile', blob, 'recording.webm');
|
|
formData.append('deliveryDate', selectedDeliveryDate || '');
|
|
formData.append('deliveryTime', selectedDeliveryTime || '');
|
|
formData.append('__RequestVerificationToken', $('input[name="__RequestVerificationToken"]').val());
|
|
$.ajax({ url: '@Url.Action("TranscribeAndSearch", "Order")', type: 'POST', data: formData,
|
|
processData: false, contentType: false,
|
|
success: function (r) { resetRecordingUI(); handleSearchResult(r); },
|
|
error: function (e) { resetRecordingUI(); console.error(e); } });
|
|
}
|
|
function resetRecordingUI() {
|
|
$('#recordingStatus').hide(); $('#recordBtn').show(); $('#stopBtn').hide();
|
|
$('#searchInput').attr('placeholder', 'Keress termékeket (pl. narancs 100, alma 50) vagy használd a mikrofont...');
|
|
}
|
|
function showStatus(msg) { $('#statusText').text(msg); $('#recordingStatus').show(); }
|
|
|
|
function submitTextSearch() {
|
|
var text = $('#searchInput').val().trim();
|
|
if (!text) { alert('Kérem, add meg a termékeket!'); return; }
|
|
showStatus('Keresés...'); $('#recordingStatus').show();
|
|
$.ajax({ url: '@Url.Action("SearchProducts", "Order")', type: 'POST',
|
|
data: { text: text, deliveryDate: selectedDeliveryDate, deliveryTime: selectedDeliveryTime,
|
|
__RequestVerificationToken: $('input[name="__RequestVerificationToken"]').val() },
|
|
success: function (r) { $('#recordingStatus').hide(); handleSearchResult(r); },
|
|
error: function () { $('#recordingStatus').hide(); alert('Hiba a keresés során.'); } });
|
|
}
|
|
|
|
function handleSearchResult(result) {
|
|
$('#noResultsCard,#productMatchesCard,#transcribedCard,#productsLoadingState').hide();
|
|
if (!result.success) { alert('Hiba: ' + result.message); return; }
|
|
if (result.transcription) { $('#transcribedText').text(result.transcription); $('#transcribedCard').show(); }
|
|
if (!result.products || result.products.length === 0) { $('#noResultsCard').show(); return; }
|
|
$('#matchesLabelText').text('Találatok');
|
|
displayQOProducts(result.products);
|
|
}
|
|
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
// PREORDER FLOW
|
|
// ══════════════════════════════════════════════════════════════════════════
|
|
|
|
function loadPreorderProducts() {
|
|
$('#poLoadingState').show(); $('#poNoProducts, #poProductSection').hide();
|
|
|
|
$.ajax({ url: '@Url.Action("GetPreorderProducts", "Order")', type: 'GET',
|
|
success: function (r) {
|
|
$('#poLoadingState').hide();
|
|
if (!r.success || !r.products || r.products.length === 0) { $('#poNoProducts').show(); return; }
|
|
poProducts = r.products; poQuantities = {};
|
|
renderPreorderProducts(); $('#poProductSection').show();
|
|
},
|
|
error: function () { $('#poLoadingState').hide(); $('#poNoProducts').show(); }
|
|
});
|
|
}
|
|
|
|
function renderPreorderProducts() {
|
|
var grid = $('#poProductGrid').empty();
|
|
$.each(poProducts, function (_, p) {
|
|
poQuantities[p.id] = 0;
|
|
var priceHtml = p.isMeasurable
|
|
? '<span class="measurable-badge"><i class="fa fa-balance-scale"></i> Súlymérést igényel</span>'
|
|
: (p.unitPrice > 0 ? '<span class="pm-price">' + fmt(p.unitPrice) + ' Ft/db</span>' : '');
|
|
var stockLabel = p.stockQuantity > 0
|
|
? 'Várható készlet: ' + p.stockQuantity + ' db'
|
|
: 'Előrendelési cikk — a mennyiség a szállítmány után véglegesül';
|
|
var card = $('<div>').addClass('product-card po-product-card').attr('data-id', p.id);
|
|
card.html(
|
|
'<div class="pc-body">' +
|
|
'<div class="pc-name"><i class="fa fa-cube"></i> ' + p.name + '</div>' +
|
|
'<div class="pc-meta"><span class="pc-stock' + (p.stockQuantity === 0 ? ' stock-preorder' : '') + '">' + stockLabel + '</span>' + priceHtml + '</div>' +
|
|
'</div>' +
|
|
'<div class="pc-actions"><div class="qty-stepper">' +
|
|
'<button type="button" class="qty-btn qty-minus" tabindex="-1"><i class="fa fa-minus"></i></button>' +
|
|
'<input type="number" class="qty-input po-qty" value="0" min="0">' +
|
|
'<button type="button" class="qty-btn qty-plus" tabindex="-1"><i class="fa fa-plus"></i></button>' +
|
|
'</div></div>'
|
|
);
|
|
card.find('.qty-minus').click(function () {
|
|
var inp = $(this).siblings('.qty-input'); var v = parseInt(inp.val()) || 0;
|
|
if (v > 0) { inp.val(v - 1); onPoQtyChange(p.id, v - 1, card); }
|
|
});
|
|
card.find('.qty-plus').click(function () {
|
|
var inp = $(this).siblings('.qty-input'); var v = parseInt(inp.val()) || 0;
|
|
inp.val(v + 1); onPoQtyChange(p.id, v + 1, card);
|
|
});
|
|
card.find('.qty-input').on('input change blur', function () {
|
|
var v = parseInt($(this).val()); if (isNaN(v) || v < 0) v = 0;
|
|
$(this).val(v); onPoQtyChange(p.id, v, card);
|
|
});
|
|
grid.append(card);
|
|
});
|
|
}
|
|
|
|
function onPoQtyChange(productId, qty, $card) {
|
|
poQuantities[productId] = qty;
|
|
$card.toggleClass('po-selected', qty > 0);
|
|
updatePoSummary();
|
|
}
|
|
|
|
function updatePoSummary() {
|
|
var selected = poProducts.filter(function (p) { return (poQuantities[p.id] || 0) > 0; });
|
|
var count = selected.length;
|
|
$('#poItemCountBadge').text(count);
|
|
$('#submitPreorderBtn').prop('disabled', count === 0);
|
|
$('#poSelectionSummary').text(count === 0 ? 'Még nincs kiválasztott termék' : count + ' termék kiválasztva');
|
|
|
|
if (count === 0) { $('#poSummaryEmpty').show(); $('#poSummaryList, #poSummaryNote').hide(); return; }
|
|
$('#poSummaryEmpty').hide(); $('#poSummaryList, #poSummaryNote').show();
|
|
|
|
var list = $('#poSummaryList').empty(); var hasMeasurable = false;
|
|
$.each(selected, function (_, p) {
|
|
var qty = poQuantities[p.id]; if (p.isMeasurable) hasMeasurable = true;
|
|
var lineTotalHtml = p.isMeasurable
|
|
? '<span class="measurable-badge-sm"><i class="fa fa-balance-scale"></i></span>'
|
|
: '<strong class="line-total">' + fmt(p.unitPrice * qty) + ' Ft</strong>';
|
|
list.append('<div class="cart-item"><div class="ci-name">' + p.name + '</div>' +
|
|
'<div class="ci-details"><span class="ci-qty">' + qty + ' db</span>' + lineTotalHtml + '</div></div>');
|
|
});
|
|
if (hasMeasurable) $('#poSummaryNote').show(); else $('#poSummaryNote').hide();
|
|
}
|
|
|
|
function submitPreorder() {
|
|
var selected = poProducts.filter(function (p) { return (poQuantities[p.id] || 0) > 0; });
|
|
if (!selected.length) return;
|
|
var btn = $('#submitPreorderBtn').prop('disabled', true)
|
|
.html('<i class="fa fa-spinner fa-spin"></i> Előrendelés mentése...');
|
|
|
|
$.ajax({
|
|
url : '@Url.Action("PlacePreorder", "Order")',
|
|
type : 'POST',
|
|
contentType: 'application/json',
|
|
data : JSON.stringify({
|
|
deliveryDateTime : selectedDeliveryDate + 'T' + selectedDeliveryTime,
|
|
customerNote : $('#customerNote').val().trim(),
|
|
items : selected.map(function (p) { return { productId: p.id, quantity: poQuantities[p.id] }; })
|
|
}),
|
|
headers : { 'RequestVerificationToken': $('input[name="__RequestVerificationToken"]').val() },
|
|
success : function (r) {
|
|
if (r.success) {
|
|
$('#mainContent, #deliveryChip').hide();
|
|
var msg = '#' + r.preorderId + ' számú előrendelésed beérkezett.';
|
|
if (r.orderId) {
|
|
msg += ' Az azonnal elérhető tételek alapján #' + r.orderId + ' számon rendelés is készült — a többi tétel a szállítmány beérkezésekor kerül megerősítésre.';
|
|
} else {
|
|
msg += ' A szállítmány megerősítésekor értesítünk.';
|
|
}
|
|
$('#successMessage').text(msg);
|
|
$('#successState').show();
|
|
} else {
|
|
alert('Hiba: ' + (r.message || ''));
|
|
btn.prop('disabled', false).html('<i class="fa fa-paper-plane"></i> Előrendelés leadása');
|
|
}
|
|
},
|
|
error: function () {
|
|
btn.prop('disabled', false).html('<i class="fa fa-paper-plane"></i> Előrendelés leadása');
|
|
}
|
|
});
|
|
}
|
|
|
|
// ── Shared ───────────────────────────────────────────────────────────────
|
|
function fmt(val) {
|
|
if (!val && val !== 0) return '—';
|
|
return Math.round(val).toLocaleString('hu-HU');
|
|
}
|
|
</script>
|