bep40 commited on
Commit
44d9e7f
·
verified ·
1 Parent(s): dbec4e6

Upload ai-search-fix.js

Browse files
Files changed (1) hide show
  1. ai-search-fix.js +216 -0
ai-search-fix.js ADDED
@@ -0,0 +1,216 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * FIX: AI Search Button - doAISearch()
3
+ * =====================================
4
+ * Root cause: doAISearch() in index.html depended on window._vaiSearchContext
5
+ * from search-plus-boot.js?v=27 which DOES NOT EXIST in the repo (404).
6
+ *
7
+ * Fix: Rewrite doAISearch() to use window.aiSearch() from ai-search.js which is
8
+ * properly loaded and contains full NL search logic.
9
+ *
10
+ * Additional fix: Handle multi-product search (comma/semicolon separated codes).
11
+ */
12
+
13
+ window.doAISearch = function() {
14
+ var input = document.getElementById('aiSearch');
15
+ var resultsDiv = document.getElementById('aiResults');
16
+ if (!input || !resultsDiv) return;
17
+
18
+ var query = input.value.trim();
19
+ if (!query || query.length < 2) {
20
+ resultsDiv.style.display = 'block';
21
+ resultsDiv.innerHTML = '💡 Nhập mã SP hoặc mô tả: "bếp từ Grob dưới 10tr", "máy hút mùi Malloca"';
22
+ return;
23
+ }
24
+
25
+ resultsDiv.style.display = 'block';
26
+ resultsDiv.innerHTML = '⏳ Đang tìm...';
27
+
28
+ // Multi-product search: if query contains comma/semicolon, search by product codes
29
+ var queries = query.split(/[,;]+/).map(function(c) { return c.trim(); }).filter(function(c) { return c.length >= 2; });
30
+
31
+ if (queries.length > 1) {
32
+ // Multi-code search mode
33
+ var allResults = [];
34
+ var normFn = function(s) { return String(s || '').toLowerCase().replace(/[.\- _\/]/g, '').replace(/đ/g, 'd'); };
35
+
36
+ queries.forEach(function(q) {
37
+ var qNorm = normFn(q);
38
+ for (var i = 0; i < D.length && allResults.length < 30; i++) {
39
+ var p = D[i];
40
+ if (!p) continue;
41
+ var fields = [(p.sku || ''), (p.mod || ''), (p.model || ''), (p.slug || '')].map(normFn);
42
+ if (fields.some(function(f) {
43
+ return f === qNorm || (f && qNorm.length >= 3 && (f.indexOf(qNorm) !== -1 || qNorm.indexOf(f) !== -1));
44
+ })) {
45
+ allResults.push(p);
46
+ }
47
+ }
48
+ });
49
+
50
+ if (allResults.length > 0) {
51
+ _renderMultiCodeResults(allResults, resultsDiv, query);
52
+ return;
53
+ }
54
+ }
55
+
56
+ if (typeof window.aiSearch === 'function' && typeof window.D !== 'undefined' && D.length > 0) {
57
+ var aiToken = (window.huggingface && window.huggingface.variables && window.huggingface.variables.VAISTUDIO) || '';
58
+ window.aiSearch(query, D, aiToken).then(function(aiResult) {
59
+ if (!aiResult || (!aiResult.results.length && !aiResult.aiAnswer)) {
60
+ _fallbackAISearch(query, resultsDiv);
61
+ return;
62
+ }
63
+ _renderAIResultsToDiv(aiResult, resultsDiv, query);
64
+ }).catch(function(err) {
65
+ _fallbackAISearch(query, resultsDiv);
66
+ console.error('AI Search error:', err);
67
+ });
68
+ } else {
69
+ _fallbackAISearch(query, resultsDiv);
70
+ }
71
+ };
72
+
73
+ // Render results for multi-product code search
74
+ function _renderMultiCodeResults(products, container, query) {
75
+ var html = '<div style="font-size:.78rem;color:#64748b;margin-bottom:10px"><i class="fas fa-search" style="margin-right:4px"></i><strong>' + products.length + '</strong> sản phẩm tìm được cho "<strong>' + query + '</strong>"</div>';
76
+ html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px">';
77
+
78
+ products.forEach(function(p, i) {
79
+ var idx = window.D ? window.D.indexOf(p) : -1;
80
+ var brandColor = p.brand === 'Eurogold' ? '#c8102e' : (p.brand === 'Grob' ? '#2e7d32' : '#003f62');
81
+ var imgSrc = p.image || p.i || '';
82
+ var priceStr = p.price || (p.pn ? p.pn : 'Liên hệ');
83
+ var catStr = p.cat || '';
84
+ var catIcon = p.catIcon || 'fa-tag';
85
+
86
+ html += '<div class="pc fade" onclick="showDetail(' + idx + ')" style="cursor:pointer;transition-delay:' + Math.min(i * 20, 300) + 'ms">' +
87
+ '<div class="pi" style="height:150px"><img src="' + imgSrc + '" alt="' + p.name + '" loading="lazy" onerror="this.style.display=\'none\'">' +
88
+ '<span class="pi-badge"><i class="fas ' + catIcon + '"></i> ' + catStr + '</span>' +
89
+ '<span style="position:absolute;top:8px;right:8px;background:' + brandColor + ';color:#fff;padding:3px 7px;border-radius:5px;font-size:.55rem;font-weight:700">' + (p.brand || '') + '</span></div>' +
90
+ '<div class="pb" style="padding:10px"><div style="font-size:.62rem;font-weight:600;color:' + brandColor + ';letter-spacing:.5px;margin-bottom:3px">' + (p.sku || p.mod || p.model || '') + '</div>' +
91
+ '<div class="pn" style="font-size:.76rem">' + p.name + '</div>' +
92
+ '<div class="pf" style="margin-top:6px"><span class="pp" style="font-size:.92rem">' + priceStr + '</span><i class="fas fa-chevron-right"></i></div></div></div>';
93
+ });
94
+
95
+ html += '</div>';
96
+ container.innerHTML = html;
97
+ container.style.display = 'block';
98
+
99
+ if (window.requestAnimationFrame) {
100
+ requestAnimationFrame(function() {
101
+ var fadeEls = container.querySelectorAll('.fade');
102
+ for (var j = 0; j < fadeEls.length; j++) {
103
+ fadeEls[j].classList.add('vis');
104
+ }
105
+ });
106
+ }
107
+ }
108
+
109
+ function _renderAIResultsToDiv(aiResult, container, query) {
110
+ var badges = '';
111
+ if (aiResult.categories && aiResult.categories.length > 0) {
112
+ badges += '<span style="display:inline-block;background:rgba(0,63,98,.08);color:#003f62;padding:4px 10px;border-radius:20px;font-size:.7rem;font-weight:600;margin-right:6px;margin-bottom:6px"><i class="fas fa-layer-group" style="margin-right:4px"></i>' + aiResult.categories.map(function(c) { return c.replace(/_/g, ' '); }).join(', ') + '</span>';
113
+ }
114
+ if (aiResult.constraints && aiResult.constraints.length > 0) {
115
+ aiResult.constraints.forEach(function(c) {
116
+ badges += '<span style="display:inline-block;background:rgba(219,152,21,.15);color:#8a6d0e;padding:4px 10px;border-radius:20px;font-size:.7rem;font-weight:600;margin-right:6px;margin-bottom:6px"><i class="fas fa-sliders" style="margin-right:4px"></i>' + c.label + '</span>';
117
+ });
118
+ }
119
+ if (aiResult.budget && aiResult.budget > 0) {
120
+ badges += '<span style="display:inline-block;background:rgba(46,125,50,.1);color:#2e7d32;padding:4px 10px;border-radius:20px;font-size:.7rem;font-weight:600;margin-right:6px;margin-bottom:6px"><i class="fas fa-wallet" style="margin-right:4px"></i>Tối đa ' + (aiResult.budget / 1000000).toFixed(0) + ' triệu</span>';
121
+ }
122
+
123
+ var aiHtml = '';
124
+ if (aiResult.aiAnswer) {
125
+ aiHtml = '<div style="background:linear-gradient(135deg,rgba(0,63,98,.04),rgba(219,152,21,.06));border-radius:16px;padding:16px;margin-bottom:16px;border:2px solid #e2e8f0"><div style="display:flex;align-items:center;gap:8px;margin-bottom:10px"><div style="width:32px;height:32px;border-radius:50%;background:#003f62;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.8rem"><i class="fas fa-robot"></i></div><span style="font-weight:700;color:#003f62;font-size:.85rem">V.AI STUDIO trả lời</span></div><div style="font-size:.85rem;color:#0f172a;line-height:1.7">' + aiResult.aiAnswer + '</div></div>';
126
+ }
127
+
128
+ var comboHtml = '';
129
+ if (aiResult.combos && aiResult.combos.length > 0) {
130
+ comboHtml = '<div style="background:linear-gradient(135deg,rgba(219,152,21,.06),rgba(46,125,50,.04));border-radius:16px;padding:16px;margin-bottom:16px;border:2px solid rgba(219,152,21,.2)"><div style="display:flex;align-items:center;gap:8px;margin-bottom:12px"><div style="width:32px;height:32px;border-radius:50%;background:#db9815;display:flex;align-items:center;justify-content:center;color:#fff;font-size:.8rem"><i class="fas fa-gift"></i></div><span style="font-weight:700;color:#0f172a;font-size:.85rem">Gợi ý combo trong ngân sách</span></div>';
131
+ aiResult.combos.forEach(function(combo, i) {
132
+ var totalStr = combo.total > 0 ? (Number(combo.total).toLocaleString('vi-VN').replace(/,/g, '.') + 'đ') : 'Liên hệ';
133
+ comboHtml += '<div style="background:#fff;border-radius:12px;padding:12px;margin-bottom:8px;border:1px solid #e2e8f0"><div style="font-weight:600;font-size:.8rem;color:#003f62;margin-bottom:6px">Combo ' + (i + 1) + ' — Tổng: ' + totalStr + '</div>';
134
+ combo.items.forEach(function(item) {
135
+ var p = item.p;
136
+ comboHtml += '<div style="display:flex;align-items:center;gap:8px;padding:5px 0;font-size:.76rem;color:#64748b"><i class="fas fa-check-circle" style="color:#2e7d32;font-size:.6rem"></i>' + p.name + ' <span style="color:#003f62;font-weight:600;margin-left:auto">' + (p.price || 'LH') + '</span></div>';
137
+ });
138
+ comboHtml += '</div>';
139
+ });
140
+ comboHtml += '</div>';
141
+ }
142
+
143
+ var items = aiResult.results || [];
144
+ var html = '<div style="margin-bottom:12px">' + badges + '</div>' + aiHtml + comboHtml;
145
+
146
+ if (items.length > 0) {
147
+ html += '<div style="font-size:.78rem;color:#64748b;margin-bottom:10px"><i class="fas fa-search" style="margin-right:4px"></i><strong>' + items.length + '</strong> kết quả cho "<strong>' + query + '</strong>"</div>';
148
+ html += '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px">';
149
+ html += items.map(function(r, i) {
150
+ var p = r.p;
151
+ var idx = (r.idx !== undefined && r.idx >= 0) ? r.idx : (window.D ? window.D.indexOf(p) : -1);
152
+ var brandColor = p.brand === 'Eurogold' ? '#c8102e' : (p.brand === 'Grob' ? '#2e7d32' : '#003f62');
153
+ var labels = (r.labels || []).map(function(l) {
154
+ return '<span style="display:inline-block;background:rgba(0,63,98,.06);padding:2px 6px;border-radius:4px;font-size:.58rem;color:#003f62;margin-right:3px;margin-bottom:3px">' + l + '</span>';
155
+ }).join('');
156
+ var imgSrc = p.image || p.i || '';
157
+ var priceStr = p.price || (window.formatPrice ? window.formatPrice(p.priceNum || p.pn) : (p.pn ? p.pn : 'Liên hệ'));
158
+ var catStr = p.cat || '';
159
+ var catIcon = p.catIcon || 'fa-tag';
160
+
161
+ return '<div class="pc fade" onclick="showDetail(' + idx + ')" style="cursor:pointer;transition-delay:' + Math.min(i * 20, 300) + 'ms">' +
162
+ '<div class="pi" style="height:150px"><img src="' + imgSrc + '" alt="' + p.name + '" loading="lazy" onerror="this.style.display=\'none\'">' +
163
+ '<span class="pi-badge"><i class="fas ' + catIcon + '"></i> ' + catStr + '</span>' +
164
+ '<span style="position:absolute;top:8px;right:8px;background:' + brandColor + ';color:#fff;padding:3px 7px;border-radius:5px;font-size:.55rem;font-weight:700">' + (p.brand || '') + '</span></div>' +
165
+ '<div class="pb" style="padding:10px"><div style="font-size:.62rem;font-weight:600;color:' + brandColor + ';letter-spacing:.5px;margin-bottom:3px">' + (p.model || p.brand || '') + '</div>' +
166
+ '<div class="pn" style="font-size:.76rem">' + p.name + '</div>' +
167
+ (labels ? '<div style="margin-top:4px">' + labels + '</div>' : '') +
168
+ '<div class="pf" style="margin-top:6px"><span class="pp" style="font-size:.92rem">' + priceStr + '</span><i class="fas fa-chevron-right"></i></div></div></div>';
169
+ }).join('');
170
+ html += '</div>';
171
+ }
172
+
173
+ container.innerHTML = html;
174
+ container.style.display = 'block';
175
+
176
+ if (window.requestAnimationFrame) {
177
+ requestAnimationFrame(function() {
178
+ var fadeEls = container.querySelectorAll('.fade');
179
+ for (var j = 0; j < fadeEls.length; j++) {
180
+ fadeEls[j].classList.add('vis');
181
+ }
182
+ });
183
+ }
184
+ }
185
+
186
+ function _fallbackAISearch(query, container) {
187
+ if (typeof D === 'undefined' || !D.length) {
188
+ container.innerHTML = '⏳ Đang tải dữ liệu...';
189
+ return;
190
+ }
191
+ var qNorm = query.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
192
+ var results = [];
193
+ for (var i = 0; i < D.length && results.length < 20; i++) {
194
+ var p = D[i];
195
+ if (!p) continue;
196
+ var nameNorm = (p.name || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
197
+ var skuNorm = (p.sku || p.mod || '').toLowerCase();
198
+ if (nameNorm.indexOf(qNorm) !== -1 || (skuNorm && skuNorm.indexOf(qNorm) !== -1)) {
199
+ results.push(p);
200
+ }
201
+ }
202
+ if (!results.length) {
203
+ container.innerHTML = '❌ Không tìm thấy "' + query + '". Thử: "bếp từ", "máy hút mùi"';
204
+ return;
205
+ }
206
+ container.innerHTML = '<div style="font-size:.78rem;color:#64748b;margin-bottom:10px"><strong>' + results.length + '</strong> kết quả</div>' +
207
+ '<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px">' +
208
+ results.map(function(p, idx) {
209
+ var imgSrc = p.image || p.i || '';
210
+ var priceStr = p.price || (p.pn ? p.pn : 'Liên hệ');
211
+ return '<div class="pc fade" onclick="showDetail(' + idx + ')" style="cursor:pointer">' +
212
+ '<div class="pi" style="height:150px"><img src="' + imgSrc + '" alt="' + p.name + '" loading="lazy"></div>' +
213
+ '<div class="pb" style="padding:10px"><div class="pn" style="font-size:.76rem">' + p.name + '</div>' +
214
+ '<div class="pf" style="margin-top:6px"><span class="pp" style="font-size:.92rem">' + priceStr + '</span></div></div></div>';
215
+ }).join('') + '</div>';
216
+ }