source: interfejs/store-employee.html@ 69f2a41

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

Initial commit

  • Property mode set to 100644
File size: 19.5 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>Employee Dashboard - 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">Products</a></li>
19 <li><a href="#" id="dashboard-link" class="active">Employee</a></li>
20 </ul>
21 </nav>
22</header>
23
24<main>
25 <div class="dashboard-header">
26 <h2>Employee Dashboard</h2>
27 <p>Welcome, <span id="employee-name">Employee</span>!</p>
28 </div>
29
30 <div class="form-group">
31 <label for="store-select">Select Store:</label>
32 <select id="store-select" class="store-selector">
33 <option value="">Loading stores...</option>
34 </select>
35 </div>
36
37 <div id="store-dashboard" style="display: none;">
38 <div class="dashboard-stats">
39 <div class="stat-card pink">
40 <h3>Pending Orders</h3>
41 <div class="stat-number" id="pending-orders">0</div>
42 </div>
43 <div class="stat-card blue">
44 <h3>Pending Requests</h3>
45 <div class="stat-number" id="pending-requests">0</div>
46 </div>
47 <div class="stat-card">
48 <h3>Pending Refunds</h3>
49 <div class="stat-number" id="pending-refunds">0</div>
50 </div>
51 <div class="stat-card pink">
52 <h3>My Tasks</h3>
53 <div class="stat-number" id="my-tasks">0</div>
54 </div>
55 </div>
56
57 <div class="tabs">
58 <button class="tab-btn active" data-tab="orders">Orders</button>
59 <button class="tab-btn" data-tab="requests">Customer Requests</button>
60 <button class="tab-btn" data-tab="refunds">Refunds</button>
61 <button class="tab-btn" data-tab="products">Products</button>
62 <button class="tab-btn" data-tab="tasks">My Tasks</button>
63 </div>
64
65 <!-- Orders Tab -->
66 <div id="orders-tab" class="tab-content active">
67 <div class="dashboard-section">
68 <h3>Manage Orders</h3>
69 <div class="table-responsive">
70 <table id="orders-table">
71 <thead>
72 <tr>
73 <th>Order #</th>
74 <th>Client</th>
75 <th>Date</th>
76 <th>Status</th>
77 <th>Total</th>
78 <th>Actions</th>
79 </tr>
80 </thead>
81 <tbody id="orders-list">
82 <tr><td colspan="6" class="loading">Loading orders...</td></tr>
83 </tbody>
84 </table>
85 </div>
86 </div>
87 </div>
88
89 <!-- Requests Tab -->
90 <div id="requests-tab" class="tab-content">
91 <div class="dashboard-section">
92 <h3>Customer Requests</h3>
93 <div class="table-responsive">
94 <table id="requests-table">
95 <thead>
96 <tr>
97 <th>Request #</th>
98 <th>Client</th>
99 <th>Date</th>
100 <th>Problem</th>
101 <th>Status</th>
102 <th>Actions</th>
103 </tr>
104 </thead>
105 <tbody id="requests-list">
106 <tr><td colspan="6" class="loading">Loading requests...</td></tr>
107 </tbody>
108 </table>
109 </div>
110 </div>
111 </div>
112
113 <!-- Refunds Tab -->
114 <div id="refunds-tab" class="tab-content">
115 <div class="dashboard-section">
116 <h3>Refund Requests</h3>
117 <div class="table-responsive">
118 <table id="refunds-table">
119 <thead>
120 <tr>
121 <th>Refund ID</th>
122 <th>Order #</th>
123 <th>Amount</th>
124 <th>Reason</th>
125 <th>Status</th>
126 <th>Actions</th>
127 </tr>
128 </thead>
129 <tbody id="refunds-list">
130 <tr><td colspan="6" class="loading">Loading refunds...</td></tr>
131 </tbody>
132 </table>
133 </div>
134 </div>
135 </div>
136
137 <!-- Products Tab -->
138 <div id="products-tab" class="tab-content">
139 <div class="dashboard-section">
140 <h3>Store Products</h3>
141 <div class="table-responsive">
142 <table id="products-table">
143 <thead>
144 <tr>
145 <th>Code</th>
146 <th>Description</th>
147 <th>Price</th>
148 <th>Available</th>
149 <th>Actions</th>
150 </tr>
151 </thead>
152 <tbody id="products-list">
153 <tr><td colspan="5" class="loading">Loading products...</td></tr>
154 </tbody>
155 </table>
156 </div>
157 </div>
158 </div>
159
160 <!-- Tasks Tab -->
161 <div id="tasks-tab" class="tab-content">
162 <div class="dashboard-section">
163 <h3>My Assigned Tasks</h3>
164 <div id="tasks-list" class="task-list">
165 <div class="loading">Loading tasks...</div>
166 </div>
167 </div>
168 </div>
169 </div>
170</main>
171
172<div id="respond-request-modal" class="modal" style="display: none;">
173 <div class="modal-content">
174 <span class="close">&times;</span>
175 <h2>Respond to Request</h2>
176 <form id="respond-request-form" class="form">
177 <input type="hidden" id="respond-request-num">
178
179 <div class="form-group">
180 <label for="request-response">Your Response</label>
181 <textarea id="request-response" rows="4" required></textarea>
182 </div>
183
184 <div class="form-group">
185 <label for="request-status">Update Status</label>
186 <select id="request-status">
187 <option value="in_progress">In Progress</option>
188 <option value="resolved">Resolved</option>
189 <option value="closed">Closed</option>
190 </select>
191 </div>
192
193 <button type="submit" class="btn-primary">Submit Response</button>
194 </form>
195 </div>
196</div>
197
198<div id="process-refund-modal" class="modal" style="display: none;">
199 <div class="modal-content">
200 <span class="close">&times;</span>
201 <h2>Process Refund</h2>
202 <form id="process-refund-form" class="form">
203 <input type="hidden" id="process-refund-id">
204
205 <div class="form-group">
206 <label for="refund-action">Action</label>
207 <select id="refund-action" required>
208 <option value="approved">Approve Refund</option>
209 <option value="rejected">Reject Refund</option>
210 </select>
211 </div>
212
213 <div class="form-group">
214 <label for="refund-notes">Notes</label>
215 <textarea id="refund-notes" rows="3"></textarea>
216 </div>
217
218 <button type="submit" class="btn-primary">Process Refund</button>
219 </form>
220 </div>
221</div>
222
223<footer>
224 <div class="footer-content">
225 <div class="footer-section">
226 <h3>Handcraft Marketplace</h3>
227 <p>Employee Portal</p>
228 </div>
229 <div class="footer-section">
230 <h3>Quick Links</h3>
231 <ul>
232 <li><a href="index.html">Home</a></li>
233 <li><a href="products.html">Products</a></li>
234 </ul>
235 </div>
236 </div>
237 <div class="footer-bottom">
238 <p>&copy; 2025 Handcraft Marketplace. All rights reserved.</p>
239 </div>
240</footer>
241
242<script src="script.js"></script>
243<script>
244 document.addEventListener('DOMContentLoaded', async () => {
245 const user = await loadUserData();
246 if (!user || user.userType !== 'store_employee') {
247 window.location.href = 'index.html';
248 return;
249 }
250
251 document.getElementById('employee-name').textContent = `${user.firstName} ${user.lastName || ''}`;
252
253 // Load stores
254 const stores = user.stores || [];
255 const storeSelect = document.getElementById('store-select');
256
257 if (stores.length === 0) {
258 storeSelect.innerHTML = '<option value="">No stores assigned</option>';
259 } else {
260 storeSelect.innerHTML = stores.map(store =>
261 `<option value="${store.store_id}">${store.name} (${store.store_id})</option>`
262 ).join('');
263
264 // Load first store by default
265 loadStoreData(stores[0].store_id);
266 }
267
268 storeSelect.addEventListener('change', (e) => {
269 if (e.target.value) {
270 loadStoreData(e.target.value);
271 }
272 });
273
274 // Tab switching
275 document.querySelectorAll('.tab-btn').forEach(btn => {
276 btn.addEventListener('click', () => {
277 document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
278 document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
279 btn.classList.add('active');
280 document.getElementById(`${btn.dataset.tab}-tab`).classList.add('active');
281 });
282 });
283 });
284
285 async function loadStoreData(storeId) {
286 document.getElementById('store-dashboard').style.display = 'block';
287
288 // Load tasks and stats
289 await loadEmployeeTasks(storeId);
290
291 // Load orders
292 await loadStoreOrders(storeId);
293
294 // Load requests
295 await loadStoreRequests(storeId);
296
297 // Load refunds
298 await loadStoreRefunds(storeId);
299
300 // Load products
301 await loadStoreProducts(storeId);
302 }
303
304 async function loadEmployeeTasks(storeId) {
305 try {
306 const response = await fetch(`/api/employee-tasks?storeId=${storeId}`);
307 const data = await response.json();
308
309 if (data.success) {
310 document.getElementById('pending-orders').textContent = data.tasks.pending_orders.length;
311 document.getElementById('pending-requests').textContent = data.tasks.pending_requests.length;
312 document.getElementById('pending-refunds').textContent = data.tasks.pending_refunds.length;
313 document.getElementById('my-tasks').textContent =
314 data.tasks.pending_orders.length + data.tasks.pending_requests.length + data.tasks.pending_refunds.length;
315
316 // Display tasks
317 const tasksList = document.getElementById('tasks-list');
318 if (data.tasks.pending_orders.length > 0 || data.tasks.pending_requests.length > 0 || data.tasks.pending_refunds.length > 0) {
319 let tasksHtml = '<div class="task-items">';
320
321 if (data.tasks.pending_orders.length > 0) {
322 tasksHtml += '<h4>Pending Orders</h4>';
323 data.tasks.pending_orders.forEach(order => {
324 tasksHtml += `
325 <div class="task-item">
326 <p><strong>Order #${order.order_num}</strong> - ${order.first_name} ${order.last_name}</p>
327 <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update Status</button>
328 </div>
329 `;
330 });
331 }
332
333 if (data.tasks.pending_requests.length > 0) {
334 tasksHtml += '<h4>Pending Requests</h4>';
335 data.tasks.pending_requests.forEach(request => {
336 tasksHtml += `
337 <div class="task-item">
338 <p><strong>Request #${request.request_num}</strong> - ${request.first_name} ${request.last_name}</p>
339 <p>${request.problem.substring(0, 50)}${request.problem.length > 50 ? '...' : ''}</p>
340 <button class="btn-small" onclick="respondToRequest('${request.request_num}')">Respond</button>
341 </div>
342 `;
343 });
344 }
345
346 if (data.tasks.pending_refunds.length > 0) {
347 tasksHtml += '<h4>Pending Refunds</h4>';
348 data.tasks.pending_refunds.forEach(refund => {
349 tasksHtml += `
350 <div class="task-item">
351 <p><strong>Refund #${refund.refund_id}</strong> - Order #${refund.order_num}</p>
352 <p>Amount: $${parseFloat(refund.amount).toFixed(2)}</p>
353 <button class="btn-small" onclick="processRefund('${refund.refund_id}')">Process</button>
354 </div>
355 `;
356 });
357 }
358
359 tasksHtml += '</div>';
360 tasksList.innerHTML = tasksHtml;
361 } else {
362 tasksList.innerHTML = '<p>No pending tasks</p>';
363 }
364 }
365 } catch (error) {
366 console.error('Error loading tasks:', error);
367 }
368 }
369
370 async function loadStoreOrders(storeId) {
371 try {
372 const response = await fetch(`/api/store-orders?storeId=${storeId}`);
373 const data = await response.json();
374
375 const tbody = document.getElementById('orders-list');
376 if (data.success && data.orders.length > 0) {
377 tbody.innerHTML = data.orders.map(order => {
378 const total = order.items ? order.items.reduce((sum, item) =>
379 sum + (item.price * item.quantity), 0) : 0;
380 return `
381 <tr>
382 <td>${order.order_num}</td>
383 <td>${order.first_name} ${order.last_name}</td>
384 <td>${new Date(order.order_date).toLocaleDateString()}</td>
385 <td><span class="status-badge status-${order.status}">${order.status}</span></td>
386 <td>$${total.toFixed(2)}</td>
387 <td>
388 <button class="btn-small" onclick="updateOrderStatus('${order.order_num}')">Update</button>
389 <button class="btn-small" onclick="viewOrderDetails('${order.order_num}')">View</button>
390 </td>
391 </tr>
392 `;
393 }).join('');
394 } else {
395 tbody.innerHTML = '<tr><td colspan="6">No orders found</td></tr>';
396 }
397 } catch (error) {
398 console.error('Error loading orders:', error);
399 document.getElementById('orders-list').innerHTML = '<tr><td colspan="6">Error loading orders</td></tr>';
400 }
401 }
402
403 async function loadStoreRequests(storeId) {
404 // This would need a separate API endpoint
405 document.getElementById('requests-list').innerHTML = '<tr><td colspan="6">Requests feature coming soon</td></tr>';
406 }
407
408 async function loadStoreRefunds(storeId) {
409 // This would need a separate API endpoint
410 document.getElementById('refunds-list').innerHTML = '<tr><td colspan="6">Refunds feature coming soon</td></tr>';
411 }
412
413 async function loadStoreProducts(storeId) {
414 try {
415 const response = await fetch(`/api/store-products?storeId=${storeId}`);
416 const data = await response.json();
417
418 const tbody = document.getElementById('products-list');
419 if (data.success && data.products.length > 0) {
420 tbody.innerHTML = data.products.map(product => `
421 <tr>
422 <td>${product.code}</td>
423 <td>${product.description.substring(0, 30)}${product.description.length > 30 ? '...' : ''}</td>
424 <td>$${parseFloat(product.price).toFixed(2)}</td>
425 <td>${product.availability}</td>
426 <td>
427 <button class="btn-small" onclick="viewProduct('${product.code}')">View</button>
428 </td>
429 </tr>
430 `).join('');
431 } else {
432 tbody.innerHTML = '<tr><td colspan="5">No products found</td></tr>';
433 }
434 } catch (error) {
435 console.error('Error loading products:', error);
436 document.getElementById('products-list').innerHTML = '<tr><td colspan="5">Error loading products</td></tr>';
437 }
438 }
439
440 window.updateOrderStatus = (orderNum) => {
441 const newStatus = prompt('Enter new status (pending, processing, shipping, delivered, canceled):');
442 if (newStatus) {
443 alert(`Order ${orderNum} status updated to ${newStatus} - Feature coming soon`);
444 }
445 };
446
447 window.respondToRequest = (requestNum) => {
448 document.getElementById('respond-request-num').value = requestNum;
449 document.getElementById('respond-request-modal').style.display = 'block';
450 };
451
452 window.processRefund = (refundId) => {
453 document.getElementById('process-refund-id').value = refundId;
454 document.getElementById('process-refund-modal').style.display = 'block';
455 };
456
457 window.viewOrderDetails = (orderNum) => {
458 alert(`View order ${orderNum} details - Feature coming soon`);
459 };
460
461 window.viewProduct = (productCode) => {
462 window.location.href = `product-detail.html?code=${productCode}`;
463 };
464
465 // Form submissions
466 document.getElementById('respond-request-form').addEventListener('submit', (e) => {
467 e.preventDefault();
468 alert('Response submitted - Feature coming soon');
469 document.getElementById('respond-request-modal').style.display = 'none';
470 });
471
472 document.getElementById('process-refund-form').addEventListener('submit', (e) => {
473 e.preventDefault();
474 alert('Refund processed - Feature coming soon');
475 document.getElementById('process-refund-modal').style.display = 'none';
476 });
477
478 // Close modal functionality
479 document.querySelectorAll('.modal .close').forEach(closeBtn => {
480 closeBtn.addEventListener('click', () => {
481 closeBtn.closest('.modal').style.display = 'none';
482 });
483 });
484
485 window.addEventListener('click', (event) => {
486 if (event.target.classList.contains('modal')) {
487 event.target.style.display = 'none';
488 }
489 });
490</script>
491</body>
492</html>
Note: See TracBrowser for help on using the repository browser.