|
212 | 212 | </div> |
213 | 213 |
|
214 | 214 | <!-- Item Image --> |
215 | | - <div class="relative aspect-square bg-gray-100 rounded-md mb-1.5 sm:mb-2 flex items-center justify-center overflow-hidden"> |
216 | | - <img |
| 215 | + <div class="relative aspect-square bg-gray-100 rounded-md mb-1.5 sm:mb-2 overflow-hidden"> |
| 216 | + <LazyImage |
217 | 217 | v-if="item.image" |
218 | 218 | :src="item.image" |
219 | 219 | :alt="item.item_name" |
220 | | - loading="lazy" |
221 | | - width="100" |
222 | | - height="100" |
223 | | - decoding="async" |
224 | | - class="w-full h-full object-cover" |
225 | | - @error="handleImageError" |
226 | | - /> |
227 | | - <svg |
228 | | - v-else |
229 | | - class="h-8 w-8 sm:h-10 sm:w-10 text-gray-300" |
230 | | - fill="none" |
231 | | - stroke="currentColor" |
232 | | - viewBox="0 0 24 24" |
| 220 | + container-class="relative w-full h-full" |
| 221 | + img-class="w-full h-full object-cover" |
| 222 | + root-margin="100px" |
233 | 223 | > |
234 | | - <path |
235 | | - stroke-linecap="round" |
236 | | - stroke-linejoin="round" |
237 | | - stroke-width="2" |
238 | | - d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" |
239 | | - /> |
240 | | - </svg> |
| 224 | + <template #error> |
| 225 | + <svg |
| 226 | + class="h-8 w-8 sm:h-10 sm:w-10 text-gray-300" |
| 227 | + fill="none" |
| 228 | + stroke="currentColor" |
| 229 | + viewBox="0 0 24 24" |
| 230 | + > |
| 231 | + <path |
| 232 | + stroke-linecap="round" |
| 233 | + stroke-linejoin="round" |
| 234 | + stroke-width="2" |
| 235 | + d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" |
| 236 | + /> |
| 237 | + </svg> |
| 238 | + </template> |
| 239 | + </LazyImage> |
| 240 | + <div v-else class="w-full h-full flex items-center justify-center"> |
| 241 | + <svg |
| 242 | + class="h-8 w-8 sm:h-10 sm:w-10 text-gray-300" |
| 243 | + fill="none" |
| 244 | + stroke="currentColor" |
| 245 | + viewBox="0 0 24 24" |
| 246 | + > |
| 247 | + <path |
| 248 | + stroke-linecap="round" |
| 249 | + stroke-linejoin="round" |
| 250 | + stroke-width="2" |
| 251 | + d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" |
| 252 | + /> |
| 253 | + </svg> |
| 254 | + </div> |
241 | 255 | </div> |
242 | 256 |
|
243 | 257 | <!-- Item Details --> |
|
354 | 368 | > |
355 | 369 | <td class="px-2 sm:px-3 py-2 whitespace-nowrap"> |
356 | 370 | <div class="w-8 h-8 sm:w-10 sm:h-10 bg-gray-100 rounded flex items-center justify-center overflow-hidden"> |
357 | | - <img v-if="item.image" :src="item.image" :alt="item.item_name" loading="lazy" width="40" height="40" decoding="async" class="w-full h-full object-cover" @error="handleImageError" /> |
| 371 | + <LazyImage |
| 372 | + v-if="item.image" |
| 373 | + :src="item.image" |
| 374 | + :alt="item.item_name" |
| 375 | + container-class="relative w-full h-full" |
| 376 | + img-class="w-full h-full object-cover" |
| 377 | + root-margin="100px" |
| 378 | + > |
| 379 | + <template #error> |
| 380 | + <svg class="h-4 w-4 sm:h-5 sm:w-5 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 381 | + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" /> |
| 382 | + </svg> |
| 383 | + </template> |
| 384 | + </LazyImage> |
358 | 385 | <svg v-else class="h-4 w-4 sm:h-5 sm:w-5 text-gray-300" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
359 | 386 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" /> |
360 | 387 | </svg> |
|
458 | 485 | </template> |
459 | 486 |
|
460 | 487 | <script setup> |
| 488 | +import LazyImage from "@/components/common/LazyImage.vue" |
461 | 489 | import { useItemSearchStore } from "@/stores/itemSearch" |
462 | 490 | import { formatCurrency as formatCurrencyUtil } from "@/utils/currency" |
463 | 491 | import { toast } from "frappe-ui" |
@@ -920,10 +948,6 @@ defineExpose({ |
920 | 948 | loadMoreItems: () => itemStore.loadMoreItems(), |
921 | 949 | }) |
922 | 950 |
|
923 | | -function handleImageError(event) { |
924 | | - event.target.style.display = "none" |
925 | | -} |
926 | | -
|
927 | 951 | // View mode functions |
928 | 952 | function setViewMode(mode) { |
929 | 953 | viewMode.value = mode |
|
0 commit comments