source: interfejs/products.html

main
Last change on this file was 69f2a41, checked in by Klimentina Efremova <klimentina08642@…>, 7 months ago

Initial commit

  • Property mode set to 100644
File size: 9.4 KB
Line 
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Browse Products - Handcraft Marketplace</title>
7 <link rel="stylesheet" href="style.css">
8</head>
9<body>
10<header>
11 <div class="logo-container">
12 <img src="../images/administrative/logo.jpg" alt="Handcraft Marketplace Logo" onerror="this.style.display='none'">
13 <h1>🎨 Handcraft Marketplace</h1>
14 </div>
15 <nav>
16 <ul>
17 <li><a href="index.html">Home</a></li>
18 <li><a href="products.html" class="active">Products</a></li>
19 <li><a href="login.html">Login</a></li>
20 <li><a href="register.html">Register</a></li>
21 </ul>
22 </nav>
23</header>
24
25<main>
26 <div class="products-header">
27 <h2>Browse Products</h2>
28 <p>Discover unique handmade items from our artisans</p>
29 </div>
30
31 <div class="filters-section">
32 <div class="filters">
33 <div class="filter-group">
34 <label for="category-filter">Category:</label>
35 <select id="category-filter">
36 <option value="all">All Categories</option>
37 </select>
38 </div>
39
40 <div class="filter-group">
41 <label for="search-input">Search:</label>
42 <input type="text" id="search-input" placeholder="Search products...">
43 </div>
44
45 <div class="filter-group">
46 <label for="sort-filter">Sort by:</label>
47 <select id="sort-filter">
48 <option value="newest">Newest</option>
49 <option value="price-low">Price: Low to High</option>
50 <option value="price-high">Price: High to Low</option>
51 <option value="name">Name</option>
52 </select>
53 </div>
54
55 <button id="apply-filters" class="btn-primary">Apply Filters</button>
56 <button id="clear-filters" class="btn-secondary">Clear</button>
57 </div>
58 </div>
59
60 <div id="products-container" class="product-grid">
61 <div class="loading">Loading products...</div>
62 </div>
63
64 <div id="pagination" class="pagination">
65 <button id="prev-page" class="btn-small" disabled>Previous</button>
66 <span id="page-info">Page 1</span>
67 <button id="next-page" class="btn-small">Next</button>
68 </div>
69</main>
70
71<footer>
72 <div class="footer-content">
73 <div class="footer-section">
74 <h3>Handcraft Marketplace</h3>
75 <p>Connecting artisans with buyers worldwide</p>
76 </div>
77 <div class="footer-section">
78 <h3>Quick Links</h3>
79 <ul>
80 <li><a href="index.html">Home</a></li>
81 <li><a href="products.html">Products</a></li>
82 </ul>
83 </div>
84 <div class="footer-section">
85 <h3>For Sellers</h3>
86 <ul>
87 <li><a href="register-store.html">Open a Store</a></li>
88 </ul>
89 </div>
90 <div class="footer-section">
91 <h3>Contact</h3>
92 <p>Email: support@handcraft.com</p>
93 </div>
94 </div>
95 <div class="footer-bottom">
96 <p>&copy; 2025 Handcraft Marketplace. All rights reserved.</p>
97 </div>
98</footer>
99
100<script src="script.js"></script>
101<script>
102 document.addEventListener('DOMContentLoaded', () => {
103 const urlParams = new URLSearchParams(window.location.search);
104 const categoryParam = urlParams.get('category');
105 const searchParam = urlParams.get('search');
106
107 let currentPage = 1;
108 const itemsPerPage = 12;
109 let allProducts = [];
110 let filteredProducts = [];
111 let categories = [];
112
113 // Load categories
114 loadCategories();
115
116 // Set initial filter values
117 if (categoryParam) {
118 document.getElementById('category-filter').value = categoryParam;
119 }
120 if (searchParam) {
121 document.getElementById('search-input').value = searchParam;
122 }
123
124 // Load products
125 loadProducts();
126
127 // Event listeners
128 document.getElementById('apply-filters').addEventListener('click', applyFilters);
129 document.getElementById('clear-filters').addEventListener('click', clearFilters);
130 document.getElementById('search-input').addEventListener('keypress', (e) => {
131 if (e.key === 'Enter') {
132 applyFilters();
133 }
134 });
135 document.getElementById('prev-page').addEventListener('click', () => {
136 if (currentPage > 1) {
137 currentPage--;
138 displayProducts();
139 }
140 });
141 document.getElementById('next-page').addEventListener('click', () => {
142 const totalPages = Math.ceil(filteredProducts.length / itemsPerPage);
143 if (currentPage < totalPages) {
144 currentPage++;
145 displayProducts();
146 }
147 });
148
149 async function loadCategories() {
150 try {
151 const response = await fetch('/api/categories');
152 const data = await response.json();
153
154 if (data.success) {
155 categories = data.categories || [];
156 const select = document.getElementById('category-filter');
157 select.innerHTML = '<option value="all">All Categories</option>' +
158 categories.map(cat =>
159 `<option value="${cat.category_id}">${cat.name}</option>`
160 ).join('');
161
162 if (categoryParam) {
163 select.value = categoryParam;
164 }
165 }
166 } catch (error) {
167 console.error('Error loading categories:', error);
168 }
169 }
170
171 async function loadProducts() {
172 try {
173 const response = await fetch('/api/products');
174 const data = await response.json();
175
176 if (data.success) {
177 allProducts = data.products || [];
178 applyFilters();
179 } else {
180 document.getElementById('products-container').innerHTML = '<p>Error loading products</p>';
181 }
182 } catch (error) {
183 console.error('Error loading products:', error);
184 document.getElementById('products-container').innerHTML = '<p>Error loading products</p>';
185 }
186 }
187
188 function applyFilters() {
189 const category = document.getElementById('category-filter').value;
190 const search = document.getElementById('search-input').value.toLowerCase();
191 const sort = document.getElementById('sort-filter').value;
192
193 // Filter products
194 filteredProducts = allProducts.filter(product => {
195 // Category filter
196 if (category !== 'all' && product.category_id != category) {
197 return false;
198 }
199
200 // Search filter
201 if (search) {
202 const searchable = `${product.description} ${product.code} ${product.store_name}`.toLowerCase();
203 if (!searchable.includes(search)) {
204 return false;
205 }
206 }
207
208 return true;
209 });
210
211 // Sort products
212 switch(sort) {
213 case 'price-low':
214 filteredProducts.sort((a, b) => parseFloat(a.price) - parseFloat(b.price));
215 break;
216 case 'price-high':
217 filteredProducts.sort((a, b) => parseFloat(b.price) - parseFloat(a.price));
218 break;
219 case 'name':
220 filteredProducts.sort((a, b) => a.description.localeCompare(b.description));
221 break;
222 default:
223 // Newest first (by product code or ID)
224 filteredProducts.sort((a, b) => b.code.localeCompare(a.code));
225 }
226
227 currentPage = 1;
228 displayProducts();
229 }
230
231 function clearFilters() {
232 document.getElementById('category-filter').value = 'all';
233 document.getElementById('search-input').value = '';
234 document.getElementById('sort-filter').value = 'newest';
235 applyFilters();
236 }
237
238 function displayProducts() {
239 const container = document.getElementById('products-container');
240 const start = (currentPage - 1) * itemsPerPage;
241 const end = start + itemsPerPage;
242 const pageProducts = filteredProducts.slice(start, end);
243 const totalPages = Math.ceil(filteredProducts.length / itemsPerPage);
244
245 if (filteredProducts.length === 0) {
246 container.innerHTML = '<p class="no-results">No products found matching your criteria</p>';
247 } else {
248 container.innerHTML = pageProducts.map(product => `
249 <div class="product-card">
250 <div class="product-image">
251 <img src="../images/product-placeholder.jpg" alt="${product.description.substring(0, 30)}"
252 onerror="this.src='data:image/svg+xml;utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%22100%22 height=%22100%22 viewBox=%220 0 100 100%22><rect width=%22100%22 height=%22100%22 fill=%22%23f0f0f0%22/><text x=%2220%22 y=%2250%22 font-family=%22Arial%22 font-size=%2214%22 fill=%22%23999%22>No Image</text></svg>'">
253 </div>
254 <div class="product-info">
255 <h3>${product.description.substring(0, 40)}${product.description.length > 40 ? '...' : ''}</h3>
256 <p class="product-price">$${parseFloat(product.price).toFixed(2)}</p>
257 <p class="product-store">${product.store_name || 'Unknown Store'}</p>
258 <p class="product-availability">In Stock: ${product.availability}</p>
259 <a href="product-detail.html?code=${product.code}" class="btn-small">View Details</a>
260 </div>
261 </div>
262 `).join('');
263 }
264
265 // Update pagination
266 document.getElementById('page-info').textContent = `Page ${currentPage} of ${totalPages || 1}`;
267 document.getElementById('prev-page').disabled = currentPage <= 1;
268 document.getElementById('next-page').disabled = currentPage >= totalPages;
269 }
270 });
271</script>
272</body>
273</html>
Note: See TracBrowser for help on using the repository browser.