Spaces:
Sleeping
Sleeping
<!-- static/ui/index.html --> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Electronics Store</title> | |
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script> | |
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet"> | |
<link href="https://cdn.jsdelivr.net/npm/@tailwindcss/typography/dist/typography.min.css" rel="stylesheet"> | |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet"> | |
</head> | |
<body class="bg-gray-100"> | |
<div id="app" class="container mx-auto px-4 py-8"> | |
<h1 class="text-4xl font-bold mb-8 text-gray-800">Electronics Store</h1> | |
<!-- Filters --> | |
<div class="mb-6 flex gap-4"> | |
<select v-model="selectedCategory" class="p-2 border rounded-lg"> | |
<option value="">All Categories</option> | |
<option v-for="category in categories" :value="category">{{ category }}</option> | |
</select> | |
<select v-model="sortBy" class="p-2 border rounded-lg"> | |
<option value="price-asc">Price: Low to High</option> | |
<option value="price-desc">Price: High to Low</option> | |
<option value="rating">Rating</option> | |
</select> | |
</div> | |
<!-- Products Grid --> | |
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> | |
<div v-for="product in filteredProducts" | |
class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow"> | |
<h2 class="text-xl font-semibold mb-2">{{ product.name }}</h2> | |
<div class="text-sm text-gray-600 mb-4">Category: {{ product.category }}</div> | |
<div class="mb-4"> | |
<h3 class="font-semibold mb-2">Specifications:</h3> | |
<ul class="text-sm"> | |
<li v-for="(value, key) in product.specs" class="mb-1"> | |
{{ key }}: {{ value }} | |
</li> | |
</ul> | |
</div> | |
<div class="flex justify-between items-center mt-4"> | |
<div class="text-2xl font-bold text-green-600">${{ product.price }}</div> | |
<div class="text-sm"> | |
<span class="text-yellow-500">β </span> | |
{{ product.rating }} | |
</div> | |
</div> | |
<div class="mt-4 text-sm" :class="{'text-red-500': product.stock < 10, 'text-green-500': product.stock >= 10}"> | |
{{ product.stock }} in stock | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
const { createApp, ref, computed } = Vue | |
createApp({ | |
setup() { | |
const products = ref([]) | |
const selectedCategory = ref('') | |
const sortBy = ref('price-asc') | |
// Fetch products from API | |
fetch('/api/electronics/products') | |
.then(response => response.json()) | |
.then(data => products.value = data) | |
const categories = computed(() => { | |
return [...new Set(products.value.map(p => p.category))] | |
}) | |
const filteredProducts = computed(() => { | |
let filtered = [...products.value] | |
if (selectedCategory.value) { | |
filtered = filtered.filter(p => p.category === selectedCategory.value) | |
} | |
switch (sortBy.value) { | |
case 'price-asc': | |
filtered.sort((a, b) => a.price - b.price) | |
break | |
case 'price-desc': | |
filtered.sort((a, b) => b.price - a.price) | |
break | |
case 'rating': | |
filtered.sort((a, b) => b.rating - a.rating) | |
break | |
} | |
return filtered | |
}) | |
return { | |
products, | |
categories, | |
selectedCategory, | |
sortBy, | |
filteredProducts | |
} | |
} | |
}).mount('#app') | |
</script> | |
</body> | |
</html> |