lokesh341 commited on
Commit
34e95e1
·
verified ·
1 Parent(s): a1eea31

Update templates/search.html

Browse files
Files changed (1) hide show
  1. templates/search.html +193 -133
templates/search.html CHANGED
@@ -3,8 +3,7 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Search Menu</title>
7
- <!-- Bootstrap CSS -->
8
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
9
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
10
  <style>
@@ -12,112 +11,186 @@
12
  font-family: Arial, sans-serif;
13
  background-color: #fdf4e3;
14
  margin: 0;
15
- padding: 20px;
16
- }
17
- .container {
18
- max-width: 900px;
19
- margin: 0 auto;
20
  }
21
- .search-container {
22
- margin-bottom: 20px;
23
  position: relative;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  }
25
- .search-container input {
26
  width: 100%;
27
- padding: 10px 40px 10px 40px;
28
  font-size: 16px;
29
  border-radius: 25px;
30
- border: 1px solid #ddd;
 
31
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
32
  outline: none;
33
- background-color: #fff;
34
- }
35
- .search-container input::placeholder {
36
- color: #888;
37
  }
38
  .search-icon {
39
  position: absolute;
40
  left: 15px;
41
- top: 50%;
42
- transform: translateY(-50%);
43
  font-size: 18px;
44
  color: #888;
45
  }
46
- .item-card {
47
- display: flex;
48
- align-items: center;
 
 
 
 
 
 
 
 
 
 
 
49
  background-color: #fff;
50
- border-radius: 10px;
51
- padding: 10px;
52
- margin-bottom: 15px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  cursor: pointer;
54
- transition: background-color 0.3s ease, transform 0.2s ease;
55
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
56
  }
57
- .item-card:hover {
58
- background-color: #f8f9fa;
59
- transform: scale(1.02);
 
 
 
 
 
 
 
 
 
 
60
  }
61
- .item-image {
62
- width: 80px;
63
- height: 80px;
64
  object-fit: cover;
65
- border-radius: 8px;
66
- margin-right: 15px;
67
  }
68
- .item-name {
 
 
 
 
69
  font-size: 1.2rem;
70
  font-weight: 600;
71
- color: #333;
72
  margin: 0;
73
- }
74
- .no-results {
75
- text-align: center;
76
- color: #666;
77
- font-size: 1.1rem;
78
- margin-top: 20px;
79
- }
80
- @media (max-width: 576px) {
81
- body {
82
- padding: 15px;
83
- }
84
- .item-card {
85
- padding: 8px;
86
- }
87
- .item-image {
88
- width: 60px;
89
- height: 60px;
90
- }
91
- .item-name {
92
- font-size: 1rem;
93
- }
94
- .search-container input {
95
- padding: 8px 35px 8px 35px;
96
- font-size: 14px;
97
- }
98
- .search-icon {
99
- font-size: 16px;
100
- left: 12px;
101
- }
102
  }
103
  </style>
104
  </head>
105
  <body>
106
- <div class="container">
107
- <div class="search-container">
108
- <input type="text" id="searchBar" class="form-control" placeholder="Search items..." autocomplete="off">
109
- <i class="bi bi-search search-icon"></i>
110
  </div>
111
- <div id="searchResults">
112
- <!-- Results will be populated dynamically -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  </div>
114
  </div>
115
 
 
 
 
 
 
 
 
 
116
  <script>
117
- function redirectToMenu(itemName) {
118
- const encodedItemName = encodeURIComponent(itemName);
119
- window.location.href = `/menu?highlight=${encodedItemName}`;
120
- }
 
121
 
122
  function sanitizeInput(input) {
123
  const div = document.createElement('div');
@@ -125,75 +198,62 @@
125
  return div.innerHTML;
126
  }
127
 
128
- function debounce(func, wait) {
129
- let timeout;
130
- return function (...args) {
131
- clearTimeout(timeout);
132
- timeout = setTimeout(() => func.apply(this, args), wait);
133
- };
134
- }
135
-
136
  document.addEventListener('DOMContentLoaded', function () {
137
  const searchBar = document.getElementById('searchBar');
 
138
  const searchResults = document.getElementById('searchResults');
139
 
140
- // Focus the search bar on page load
141
- searchBar.focus();
 
 
 
 
 
 
 
 
 
 
 
142
 
143
- // Debounced search function
144
- const debouncedSearch = debounce(function (query) {
145
- if (!query) {
146
- searchResults.innerHTML = '<p class="no-results">Please type to search for items.</p>';
147
- return;
148
  }
 
149
 
150
- // Fetch items from the server
151
- fetch(`/api/search-items?query=${encodeURIComponent(query)}`)
152
- .then(response => {
153
- if (!response.ok) throw new Error('Network response was not ok');
154
- return response.json();
155
- })
156
- .then(data => {
157
- searchResults.innerHTML = '';
158
- if (data.items && data.items.length > 0) {
159
- data.items.forEach(item => {
160
- const itemCard = document.createElement('div');
161
- itemCard.className = 'item-card';
162
- itemCard.setAttribute('data-item-name', sanitizeInput(item.Name));
163
- itemCard.setAttribute('data-item-section', sanitizeInput(item.Section__c || 'Unknown'));
164
- itemCard.onclick = () => redirectToMenu(item.Name);
165
-
166
- const itemImage = document.createElement('img');
167
- itemImage.src = item.Image2__c || '/static/placeholder.jpg';
168
- itemImage.alt = item.Name || 'Unnamed Item';
169
- itemImage.className = 'item-image';
170
-
171
- const itemNameDiv = document.createElement('div');
172
- itemNameDiv.className = 'item-name';
173
- itemNameDiv.textContent = item.Name || 'Unnamed Item';
174
 
175
- itemCard.appendChild(itemImage);
176
- itemCard.appendChild(itemNameDiv);
177
- searchResults.appendChild(itemCard);
 
 
 
 
 
 
 
 
 
 
178
  });
179
- } else {
180
- searchResults.innerHTML = '<p class="no-results">No items found.</p>';
181
- }
182
- })
183
- .catch(error => {
184
- console.error('Error fetching search results:', error);
185
- searchResults.innerHTML = '<p class="no-results">Error loading items. Please try again.</p>';
186
- });
187
- }, 300);
188
-
189
- // Trigger search on input
190
- searchBar.addEventListener('input', function () {
191
- const query = this.value.trim();
192
- debouncedSearch(query);
193
  });
194
 
195
- // Initial state when no items are present
196
- searchResults.innerHTML = '<p class="no-results">Please type to search for items.</p>';
 
 
 
197
  });
198
  </script>
199
  </body>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Search - Menu</title>
 
7
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
8
  <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
9
  <style>
 
11
  font-family: Arial, sans-serif;
12
  background-color: #fdf4e3;
13
  margin: 0;
14
+ padding: 0;
15
+ display: flex;
16
+ flex-direction: column;
17
+ padding-bottom: 70px;
 
18
  }
19
+ .fixed-top-bar {
 
20
  position: relative;
21
+ top: 0;
22
+ left: 0;
23
+ width: 100%;
24
+ height: 54px;
25
+ background: linear-gradient(45deg, #FFA07A, #FFB347);
26
+ color: white;
27
+ padding: 15px;
28
+ display: flex;
29
+ align-items: center;
30
+ z-index: 1000;
31
+ }
32
+ .orange-label {
33
+ background-color: #FFA500;
34
+ padding: 5px 10px;
35
+ border-radius: 5px;
36
+ display: flex;
37
+ align-items: center;
38
+ position: absolute;
39
+ left: 10px;
40
+ top: 50%;
41
+ transform: translateY(-50%);
42
+ }
43
+ .back-button {
44
+ background-color: black;
45
+ color: white;
46
+ border: none;
47
+ border-radius: 50%;
48
+ width: 25px;
49
+ height: 25px;
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: center;
53
+ font-size: 16px;
54
+ cursor: pointer;
55
+ margin-right: 10px;
56
+ }
57
+ .search-bar-container {
58
+ position: fixed;
59
+ bottom: 10px;
60
+ left: 50%;
61
+ transform: translateX(-50%);
62
+ display: flex;
63
+ align-items: center;
64
+ width: 300px;
65
+ max-width: 90%;
66
+ z-index: 1000;
67
  }
68
+ .search-bar-container input {
69
  width: 100%;
70
+ padding: 8px 40px 8px 40px;
71
  font-size: 16px;
72
  border-radius: 25px;
73
+ border: none;
74
+ background-color: #fff;
75
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
76
  outline: none;
 
 
 
 
77
  }
78
  .search-icon {
79
  position: absolute;
80
  left: 15px;
 
 
81
  font-size: 18px;
82
  color: #888;
83
  }
84
+ .mic-icon {
85
+ position: absolute;
86
+ right: 15px;
87
+ font-size: 18px;
88
+ color: #888;
89
+ cursor: pointer;
90
+ }
91
+ .autocomplete-suggestions {
92
+ position: absolute;
93
+ bottom: 100%;
94
+ left: 0;
95
+ width: 100%;
96
+ max-height: 200px;
97
+ overflow-y: auto;
98
  background-color: #fff;
99
+ border: 1px solid #ddd;
100
+ border-radius: 5px;
101
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
102
+ z-index: 1000;
103
+ display: none;
104
+ }
105
+ .autocomplete-suggestions .suggestion-item {
106
+ padding: 8px 15px;
107
+ cursor: pointer;
108
+ font-size: 14px;
109
+ color: #333;
110
+ }
111
+ .autocomplete-suggestions .suggestion-item:hover {
112
+ background-color: #f1f1f1;
113
+ }
114
+ .container {
115
+ max-width: 900px;
116
+ margin-top: 20px;
117
+ margin-bottom: 70px;
118
+ }
119
+ .search-item {
120
  cursor: pointer;
 
 
121
  }
122
+ .menu-card {
123
+ max-width: 350px;
124
+ border-radius: 15px;
125
+ overflow: hidden;
126
+ background-color: #fff;
127
+ margin: auto;
128
+ display: flex;
129
+ flex-direction: column;
130
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
131
+ transition: transform 0.2s;
132
+ }
133
+ .menu-card:hover {
134
+ transform: scale(1.05);
135
  }
136
+ .menu-video {
137
+ height: 200px;
138
+ width: 100%;
139
  object-fit: cover;
140
+ border-radius: 15px 15px 0 0;
 
141
  }
142
+ .card-body {
143
+ padding: 10px;
144
+ text-align: center;
145
+ }
146
+ .card-title {
147
  font-size: 1.2rem;
148
  font-weight: 600;
 
149
  margin: 0;
150
+ color: #333333;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
  </style>
153
  </head>
154
  <body>
155
+ <div class="fixed-top-bar">
156
+ <div class="orange-label">
157
+ <button class="back-button" onclick="window.location.href='/menu'"><</button>
158
+ <span>Search</span>
159
  </div>
160
+ </div>
161
+
162
+ <div class="container">
163
+ <h2>Search Results</h2>
164
+ <div id="searchResults" class="row">
165
+ {% for item in all_items %}
166
+ <div class="col-md-6 mb-4 search-item" data-name="{{ item.Name | lower }}" data-section="{{ item.Section__c | lower }}"
167
+ onclick="window.location.href='/menu?highlight={{ item.Name | urlencode }}'">
168
+ <div class="card menu-card">
169
+ <img src="{{ item.Image2__c | default(item.Image1__c) | default('/static/placeholder.jpg') }}"
170
+ class="card-img-top menu-video" alt="{{ item.Name }}" style="height: 200px; object-fit: cover;">
171
+ <div class="card-body">
172
+ <h5 class="card-title">{{ item.Name }}</h5>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ {% endfor %}
177
  </div>
178
  </div>
179
 
180
+ <div class="search-bar-container">
181
+ <input type="text" id="searchBar" class="form-control" placeholder="Search items or sections..." autocomplete="off">
182
+ <i class="bi bi-search search-icon"></i>
183
+ <i class="bi bi-mic mic-icon" id="micIcon"></i>
184
+ <div id="autocompleteSuggestions" class="autocomplete-suggestions"></div>
185
+ </div>
186
+
187
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
188
  <script>
189
+ const menuItems = [
190
+ {% for item in all_items %}
191
+ "{{ item.Name | e }}",
192
+ {% endfor %}
193
+ ];
194
 
195
  function sanitizeInput(input) {
196
  const div = document.createElement('div');
 
198
  return div.innerHTML;
199
  }
200
 
 
 
 
 
 
 
 
 
201
  document.addEventListener('DOMContentLoaded', function () {
202
  const searchBar = document.getElementById('searchBar');
203
+ const suggestionsContainer = document.getElementById('autocompleteSuggestions');
204
  const searchResults = document.getElementById('searchResults');
205
 
206
+ function filterSearch() {
207
+ const input = sanitizeInput(searchBar.value.trim().toLowerCase());
208
+ const items = document.querySelectorAll('.search-item');
209
+
210
+ items.forEach(item => {
211
+ const itemName = item.getAttribute('data-name');
212
+ const itemSection = item.getAttribute('data-section');
213
+ if (itemName.includes(input) || itemSection.includes(input)) {
214
+ item.style.display = 'block';
215
+ } else {
216
+ item.style.display = 'none';
217
+ }
218
+ });
219
 
220
+ if (!input) {
221
+ items.forEach(item => item.style.display = 'block');
 
 
 
222
  }
223
+ }
224
 
225
+ searchBar.addEventListener('input', function () {
226
+ const input = sanitizeInput(this.value.trim().toLowerCase());
227
+ suggestionsContainer.innerHTML = '';
228
+ suggestionsContainer.style.display = 'none';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
+ if (input) {
231
+ const filteredItems = menuItems.filter(item =>
232
+ item.toLowerCase().includes(input)
233
+ );
234
+ if (filteredItems.length > 0) {
235
+ filteredItems.forEach(item => {
236
+ const suggestionDiv = document.createElement('div');
237
+ suggestionDiv.classList.add('suggestion-item');
238
+ suggestionDiv.innerText = item;
239
+ suggestionDiv.addEventListener('click', function () {
240
+ searchBar.value = item;
241
+ suggestionsContainer.style.display = 'none';
242
+ filterSearch();
243
  });
244
+ suggestionsContainer.appendChild(suggestionDiv);
245
+ });
246
+ suggestionsContainer.style.display = 'block';
247
+ }
248
+ }
249
+ filterSearch();
 
 
 
 
 
 
 
 
250
  });
251
 
252
+ document.addEventListener('click', function (event) {
253
+ if (!searchBar.contains(event.target) && !suggestionsContainer.contains(event.target)) {
254
+ suggestionsContainer.style.display = 'none';
255
+ }
256
+ });
257
  });
258
  </script>
259
  </body>