File size: 7,935 Bytes
2f09e0e
 
b5e3a76
2f09e0e
 
 
 
 
 
4890167
 
2f09e0e
4890167
2f09e0e
 
4890167
2f09e0e
4890167
 
2f09e0e
 
 
4890167
2f09e0e
 
4890167
2f09e0e
 
4890167
 
b5e3a76
2f09e0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4890167
 
2f09e0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b5e3a76
 
 
2f09e0e
4890167
2f09e0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b5e3a76
2f09e0e
b5e3a76
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<!DOCTYPE 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/[email protected]/dist/vue.global.prod.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif;
        }
        .fade-enter-active, .fade-leave-active {
            transition: opacity 0.3s ease;
        }
        .fade-enter-from, .fade-leave-to {
            opacity: 0;
        }
        .product-card {
            transform: translateY(0);
            transition: all 0.3s ease;
        }
        .product-card:hover {
            transform: translateY(-5px);
        }
        .stock-badge {
            transition: all 0.3s ease;
        }
    </style>
</head>
<body class="bg-gray-50">
    <div id="app" class="min-h-screen">
        <!-- Header -->
        <header class="bg-white shadow-sm">
            <div class="container mx-auto px-4 py-6">
                <h1 class="text-4xl font-bold text-gray-900">Electronics Store</h1>
            </div>
        </header>

        <main class="container mx-auto px-4 py-8">
            <!-- Filters Section -->
            <div class="bg-white rounded-xl shadow-sm p-6 mb-8">
                <div class="flex flex-col md:flex-row gap-4 items-center justify-between">
                    <div class="flex gap-4 w-full md:w-auto">
                        <select v-model="selectedCategory" 
                                class="w-full md:w-48 p-2.5 border border-gray-200 rounded-lg bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
                            <option value="">All Categories</option>
                            <option v-for="category in categories" :key="category" :value="category">
                                {{ category }}
                            </option>
                        </select>
                        
                        <select v-model="sortBy" 
                                class="w-full md:w-48 p-2.5 border border-gray-200 rounded-lg bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
                            <option value="price-asc">Price: Low to High</option>
                            <option value="price-desc">Price: High to Low</option>
                            <option value="rating">Top Rated</option>
                        </select>
                    </div>
                    
                    <div class="text-sm text-gray-500">
                        {{ filteredProducts.length }} products found
                    </div>
                </div>
            </div>

            <!-- Products Grid -->
            <transition-group name="fade" tag="div" 
                            class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
                <div v-for="product in filteredProducts" 
                     :key="product.id"
                     class="product-card bg-white rounded-xl shadow-sm overflow-hidden">
                    
                    <div class="p-6">
                        <!-- Product Category Badge -->
                        <div class="inline-block px-3 py-1 rounded-full text-xs font-medium bg-blue-50 text-blue-600 mb-4">
                            {{ product.category }}
                        </div>

                        <!-- Product Name -->
                        <h2 class="text-xl font-semibold text-gray-900 mb-4">{{ product.name }}</h2>
                        
                        <!-- Specifications -->
                        <div class="space-y-3 mb-6">
                            <div v-for="(value, key) in product.specs" 
                                 :key="key" 
                                 class="flex justify-between text-sm">
                                <span class="text-gray-500">{{ key }}</span>
                                <span class="text-gray-900 font-medium">{{ value }}</span>
                            </div>
                        </div>

                        <!-- Price and Rating -->
                        <div class="flex items-center justify-between pt-4 border-t border-gray-100">
                            <div class="text-2xl font-bold text-gray-900">
                                ${{ product.price.toLocaleString() }}
                            </div>
                            <div class="flex items-center gap-1">
                                <span class="text-yellow-400 text-lg"></span>
                                <span class="font-medium">{{ product.rating }}</span>
                            </div>
                        </div>

                        <!-- Stock Status -->
                        <div class="mt-4">
                            <span class="stock-badge px-3 py-1 rounded-full text-sm font-medium"
                                  :class="{
                                      'bg-red-50 text-red-600': product.stock < 10,
                                      'bg-green-50 text-green-600': product.stock >= 10
                                  }">
                                {{ product.stock }} in stock
                            </span>
                        </div>
                    </div>
                </div>
            </transition-group>

            <!-- Empty State -->
            <div v-if="filteredProducts.length === 0" 
                 class="text-center py-12">
                <p class="text-gray-500">No products found matching your criteria</p>
            </div>
        </main>
    </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.products || []
                    })
                    .catch(error => {
                        console.error('Error fetching products:', error)
                    })

                const categories = computed(() => {
                    if (!products.value?.length) return []
                    return [...new Set(products.value.map(p => p.category))]
                })

                const filteredProducts = computed(() => {
                    if (!products.value?.length) return []
                    
                    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>