source: interfejs/checkout.html@ 2d1ec46

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

Initial commit

  • Property mode set to 100644
File size: 19.1 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>Checkout - 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">Dashboard</a></li>
20 </ul>
21 </nav>
22</header>
23
24<main>
25 <div class="checkout-header">
26 <h2>Checkout</h2>
27 <p>Complete your purchase</p>
28 </div>
29
30 <div class="checkout-container">
31 <div class="checkout-progress">
32 <div class="progress-step active">
33 <span class="step-number">1</span>
34 <span class="step-label">Cart</span>
35 </div>
36 <div class="progress-step">
37 <span class="step-number">2</span>
38 <span class="step-label">Delivery</span>
39 </div>
40 <div class="progress-step">
41 <span class="step-number">3</span>
42 <span class="step-label">Payment</span>
43 </div>
44 <div class="progress-step">
45 <span class="step-number">4</span>
46 <span class="step-label">Confirm</span>
47 </div>
48 </div>
49
50 <div id="step-1" class="checkout-step active">
51 <h3>Review Your Cart</h3>
52 <div id="cart-items" class="cart-items">
53 <div class="loading">Loading cart...</div>
54 </div>
55
56 <div class="cart-summary">
57 <div class="summary-row">
58 <span>Subtotal:</span>
59 <span id="subtotal">$0.00</span>
60 </div>
61 <div class="summary-row">
62 <span>Shipping:</span>
63 <span id="shipping">$0.00</span>
64 </div>
65 <div class="summary-row total">
66 <span>Total:</span>
67 <span id="total">$0.00</span>
68 </div>
69 </div>
70
71 <div class="checkout-actions">
72 <button id="continue-to-delivery" class="btn-primary">Continue to Delivery</button>
73 <a href="products.html" class="btn-secondary">Continue Shopping</a>
74 </div>
75 </div>
76
77 <div id="step-2" class="checkout-step" style="display: none;">
78 <h3>Delivery Address</h3>
79
80 <div id="saved-addresses" class="address-list">
81 <div class="loading">Loading addresses...</div>
82 </div>
83
84 <div class="form-group">
85 <label>
86 <input type="checkbox" id="use-new-address"> Use a different address
87 </label>
88 </div>
89
90 <div id="new-address-form" style="display: none;">
91 <h4>New Delivery Address</h4>
92 <form class="form">
93 <div class="form-group">
94 <label for="address">Street Address *</label>
95 <input type="text" id="address" required>
96 </div>
97
98 <div class="form-row">
99 <div class="form-group">
100 <label for="city">City *</label>
101 <input type="text" id="city" required>
102 </div>
103 <div class="form-group">
104 <label for="postcode">Postcode *</label>
105 <input type="text" id="postcode" required>
106 </div>
107 </div>
108
109 <div class="form-group">
110 <label for="country">Country *</label>
111 <input type="text" id="country" required>
112 </div>
113
114 <div class="form-group checkbox">
115 <input type="checkbox" id="save-address">
116 <label for="save-address">Save this address for future orders</label>
117 </div>
118 </form>
119 </div>
120
121 <div class="checkout-actions">
122 <button id="back-to-cart" class="btn-secondary">Back to Cart</button>
123 <button id="continue-to-payment" class="btn-primary">Continue to Payment</button>
124 </div>
125 </div>
126
127 <div id="step-3" class="checkout-step" style="display: none;">
128 <h3>Payment Method</h3>
129
130 <div class="payment-methods">
131 <div class="payment-method">
132 <label>
133 <input type="radio" name="payment" value="credit" checked>
134 <div class="payment-details">
135 <strong>Credit Card</strong>
136 <p>Pay securely with your credit card</p>
137 </div>
138 </label>
139 </div>
140
141 <div class="payment-method">
142 <label>
143 <input type="radio" name="payment" value="paypal">
144 <div class="payment-details">
145 <strong>PayPal</strong>
146 <p>Pay with your PayPal account</p>
147 </div>
148 </label>
149 </div>
150
151 <div class="payment-method">
152 <label>
153 <input type="radio" name="payment" value="cash">
154 <div class="payment-details">
155 <strong>Cash on Delivery</strong>
156 <p>Pay when you receive your order</p>
157 </div>
158 </label>
159 </div>
160 </div>
161
162 <div id="credit-card-form" class="credit-card-form">
163 <h4>Credit Card Details</h4>
164 <form class="form">
165 <div class="form-group">
166 <label for="card-number">Card Number</label>
167 <input type="text" id="card-number" placeholder="**** **** **** ****">
168 </div>
169
170 <div class="form-row">
171 <div class="form-group">
172 <label for="card-expiry">Expiry Date</label>
173 <input type="text" id="card-expiry" placeholder="MM/YY">
174 </div>
175 <div class="form-group">
176 <label for="card-cvv">CVV</label>
177 <input type="text" id="card-cvv" placeholder="***">
178 </div>
179 </div>
180
181 <div class="form-group">
182 <label for="card-name">Name on Card</label>
183 <input type="text" id="card-name">
184 </div>
185 </form>
186 </div>
187
188 <div class="checkout-actions">
189 <button id="back-to-delivery" class="btn-secondary">Back to Delivery</button>
190 <button id="continue-to-confirm" class="btn-primary">Review Order</button>
191 </div>
192 </div>
193
194 <div id="step-4" class="checkout-step" style="display: none;">
195 <h3>Order Confirmation</h3>
196
197 <div class="order-summary">
198 <h4>Order Summary</h4>
199 <div id="confirm-items"></div>
200
201 <div class="summary-details">
202 <p><strong>Delivery Address:</strong> <span id="confirm-address"></span></p>
203 <p><strong>Payment Method:</strong> <span id="confirm-payment"></span></p>
204 </div>
205
206 <div class="summary-row total">
207 <span>Total to Pay:</span>
208 <span id="confirm-total">$0.00</span>
209 </div>
210 </div>
211
212 <div class="terms-checkbox">
213 <label>
214 <input type="checkbox" id="accept-terms">
215 I agree to the Terms and Conditions and Privacy Policy
216 </label>
217 </div>
218
219 <div class="checkout-actions">
220 <button id="back-to-payment" class="btn-secondary">Back to Payment</button>
221 <button id="place-order" class="btn-primary" disabled>Place Order</button>
222 </div>
223 </div>
224 </div>
225</main>
226
227<div id="order-success-modal" class="modal" style="display: none;">
228 <div class="modal-content">
229 <span class="close">&times;</span>
230 <h2>Order Placed Successfully!</h2>
231 <p>Your order has been placed. Order number: <strong id="order-number"></strong></p>
232 <p>You will receive a confirmation email shortly.</p>
233 <div style="display: flex; gap: 1rem; justify-content: center; margin-top: 2rem;">
234 <a href="products.html" class="btn-primary">Continue Shopping</a>
235 <a href="client-dashboard.html" class="btn-secondary">View Orders</a>
236 </div>
237 </div>
238</div>
239
240<footer>
241 <div class="footer-content">
242 <div class="footer-section">
243 <h3>Handcraft Marketplace</h3>
244 <p>Secure checkout</p>
245 </div>
246 <div class="footer-section">
247 <h3>Quick Links</h3>
248 <ul>
249 <li><a href="index.html">Home</a></li>
250 <li><a href="products.html">Products</a></li>
251 </ul>
252 </div>
253 </div>
254 <div class="footer-bottom">
255 <p>&copy; 2025 Handcraft Marketplace. All rights reserved.</p>
256 </div>
257</footer>
258
259<script src="script.js"></script>
260<script>
261 document.addEventListener('DOMContentLoaded', async () => {
262 const auth = await checkAuth();
263
264 if (!auth.success) {
265 window.location.href = 'login.html';
266 return;
267 }
268
269 if (auth.user.userType !== 'client') {
270 alert('Only clients can place orders');
271 window.location.href = 'index.html';
272 return;
273 }
274
275 let cart = JSON.parse(sessionStorage.getItem('cart') || '[]');
276 let selectedAddress = null;
277 let paymentMethod = 'credit';
278
279 if (cart.length === 0) {
280 window.location.href = 'products.html';
281 return;
282 }
283
284 // Display cart items
285 displayCart();
286
287 // Load saved addresses
288 loadAddresses();
289
290 // Event listeners for navigation
291 document.getElementById('continue-to-delivery').addEventListener('click', goToDelivery);
292 document.getElementById('back-to-cart').addEventListener('click', backToCart);
293 document.getElementById('continue-to-payment').addEventListener('click', goToPayment);
294 document.getElementById('back-to-delivery').addEventListener('click', backToDelivery);
295 document.getElementById('continue-to-confirm').addEventListener('click', goToConfirm);
296 document.getElementById('back-to-payment').addEventListener('click', backToPayment);
297 document.getElementById('place-order').addEventListener('click', placeOrder);
298
299 // Payment method toggle
300 document.querySelectorAll('input[name="payment"]').forEach(radio => {
301 radio.addEventListener('change', (e) => {
302 paymentMethod = e.target.value;
303 document.getElementById('credit-card-form').style.display =
304 paymentMethod === 'credit' ? 'block' : 'none';
305 });
306 });
307
308 // New address toggle
309 document.getElementById('use-new-address').addEventListener('change', (e) => {
310 document.getElementById('new-address-form').style.display =
311 e.target.checked ? 'block' : 'none';
312 });
313
314 // Terms checkbox
315 document.getElementById('accept-terms').addEventListener('change', (e) => {
316 document.getElementById('place-order').disabled = !e.target.checked;
317 });
318
319 function displayCart() {
320 const cartContainer = document.getElementById('cart-items');
321 let subtotal = 0;
322
323 if (cart.length === 0) {
324 cartContainer.innerHTML = '<p>Your cart is empty</p>';
325 } else {
326 cartContainer.innerHTML = cart.map((item, index) => {
327 const itemTotal = item.price * item.quantity;
328 subtotal += itemTotal;
329 return `
330 <div class="cart-item">
331 <div class="cart-item-image">
332 <img src="${item.image || '../images/product-placeholder.jpg'}" alt="${item.description}"
333 onerror="this.src='data:image/svg+xml;utf8,<svg xmlns=%22http://www.w3.org/2000/svg%22 width=%2280%22 height=%2280%22 viewBox=%220 0 80 80%22><rect width=%2280%22 height=%2280%22 fill=%22%23f0f0f0%22/></svg>'">
334 </div>
335 <div class="cart-item-details">
336 <h4>${item.description}</h4>
337 <p>Store: ${item.storeName}</p>
338 <p>Price: $${item.price.toFixed(2)}</p>
339 </div>
340 <div class="cart-item-quantity">
341 <label>Qty:</label>
342 <input type="number" min="1" value="${item.quantity}" onchange="updateQuantity(${index}, this.value)">
343 </div>
344 <div class="cart-item-total">
345 $${itemTotal.toFixed(2)}
346 </div>
347 <button class="remove-item" onclick="removeItem(${index})">&times;</button>
348 </div>
349 `;
350 }).join('');
351 }
352
353 const shipping = subtotal > 0 ? 5.00 : 0;
354 const total = subtotal + shipping;
355
356 document.getElementById('subtotal').textContent = `$${subtotal.toFixed(2)}`;
357 document.getElementById('shipping').textContent = `$${shipping.toFixed(2)}`;
358 document.getElementById('total').textContent = `$${total.toFixed(2)}`;
359 document.getElementById('confirm-total').textContent = `$${total.toFixed(2)}`;
360 }
361
362 async function loadAddresses() {
363 // This would need a separate API endpoint
364 setTimeout(() => {
365 const addressesDiv = document.getElementById('saved-addresses');
366 addressesDiv.innerHTML = `
367 <div class="address-option">
368 <label>
369 <input type="radio" name="address" value="default" checked>
370 <div class="address-details">
371 <strong>Default Address</strong>
372 <p>st. Center num.10, Skopje 1000, North Macedonia</p>
373 </div>
374 </label>
375 </div>
376 `;
377 }, 500);
378 }
379
380 function goToDelivery() {
381 document.getElementById('step-1').classList.remove('active');
382 document.getElementById('step-1').style.display = 'none';
383 document.getElementById('step-2').style.display = 'block';
384 document.getElementById('step-2').classList.add('active');
385
386 document.querySelectorAll('.progress-step')[0].classList.remove('active');
387 document.querySelectorAll('.progress-step')[1].classList.add('active');
388 }
389
390 function backToCart() {
391 document.getElementById('step-2').classList.remove('active');
392 document.getElementById('step-2').style.display = 'none';
393 document.getElementById('step-1').style.display = 'block';
394 document.getElementById('step-1').classList.add('active');
395
396 document.querySelectorAll('.progress-step')[1].classList.remove('active');
397 document.querySelectorAll('.progress-step')[0].classList.add('active');
398 }
399
400 function goToPayment() {
401 // Get selected address
402 const addressRadio = document.querySelector('input[name="address"]:checked');
403 if (!addressRadio) {
404 alert('Please select a delivery address');
405 return;
406 }
407
408 selectedAddress = 'Selected Address'; // In real app, get actual address
409
410 document.getElementById('step-2').classList.remove('active');
411 document.getElementById('step-2').style.display = 'none';
412 document.getElementById('step-3').style.display = 'block';
413 document.getElementById('step-3').classList.add('active');
414
415 document.querySelectorAll('.progress-step')[1].classList.remove('active');
416 document.querySelectorAll('.progress-step')[2].classList.add('active');
417 }
418
419 function backToDelivery() {
420 document.getElementById('step-3').classList.remove('active');
421 document.getElementById('step-3').style.display = 'none';
422 document.getElementById('step-2').style.display = 'block';
423 document.getElementById('step-2').classList.add('active');
424
425 document.querySelectorAll('.progress-step')[2].classList.remove('active');
426 document.querySelectorAll('.progress-step')[1].classList.add('active');
427 }
428
429 function goToConfirm() {
430 // Validate payment info
431 if (paymentMethod === 'credit') {
432 const cardNumber = document.getElementById('card-number').value;
433 if (!cardNumber) {
434 alert('Please enter your card details');
435 return;
436 }
437 }
438
439 // Display confirmation
440 const confirmItems = document.getElementById('confirm-items');
441 confirmItems.innerHTML = cart.map(item => `
442 <p>${item.quantity}x ${item.description.substring(0, 30)} - $${(item.price * item.quantity).toFixed(2)}</p>
443 `).join('');
444
445 document.getElementById('confirm-address').textContent = selectedAddress;
446 document.getElementById('confirm-payment').textContent =
447 paymentMethod === 'credit' ? 'Credit Card' :
448 paymentMethod === 'paypal' ? 'PayPal' : 'Cash on Delivery';
449
450 document.getElementById('step-3').classList.remove('active');
451 document.getElementById('step-3').style.display = 'none';
452 document.getElementById('step-4').style.display = 'block';
453 document.getElementById('step-4').classList.add('active');
454
455 document.querySelectorAll('.progress-step')[2].classList.remove('active');
456 document.querySelectorAll('.progress-step')[3].classList.add('active');
457 }
458
459 function backToPayment() {
460 document.getElementById('step-4').classList.remove('active');
461 document.getElementById('step-4').style.display = 'none';
462 document.getElementById('step-3').style.display = 'block';
463 document.getElementById('step-3').classList.add('active');
464
465 document.querySelectorAll('.progress-step')[3].classList.remove('active');
466 document.querySelectorAll('.progress-step')[2].classList.add('active');
467 }
468
469 async function placeOrder() {
470 // Create order
471 const orderData = {
472 storeId: cart[0].storeId, // Assuming all items from same store for simplicity
473 items: cart.map(item => ({
474 productCode: item.code,
475 quantity: item.quantity,
476 price: item.price
477 })),
478 paymentMethod: paymentMethod === 'credit' ? 'credit card, **** **** **** 6750' : paymentMethod,
479 deliveryAddress: selectedAddress,
480 discount: 0
481 };
482
483 try {
484 const response = await fetch('/api/create-order', {
485 method: 'POST',
486 headers: { 'Content-Type': 'application/json' },
487 body: JSON.stringify(orderData)
488 });
489
490 const data = await response.json();
491
492 if (data.success) {
493 // Clear cart
494 sessionStorage.removeItem('cart');
495
496 document.getElementById('order-number').textContent = data.orderId;
497 document.getElementById('order-success-modal').style.display = 'block';
498 } else {
499 alert(data.message || 'Failed to place order');
500 }
501 } catch (error) {
502 console.error('Error placing order:', error);
503 alert('An error occurred while placing your order');
504 }
505 }
506
507 window.updateQuantity = (index, quantity) => {
508 quantity = parseInt(quantity);
509 if (quantity < 1) {
510 quantity = 1;
511 }
512 cart[index].quantity = quantity;
513 sessionStorage.setItem('cart', JSON.stringify(cart));
514 displayCart();
515 };
516
517 window.removeItem = (index) => {
518 cart.splice(index, 1);
519 sessionStorage.setItem('cart', JSON.stringify(cart));
520 displayCart();
521
522 if (cart.length === 0) {
523 setTimeout(() => {
524 window.location.href = 'products.html';
525 }, 1000);
526 }
527 };
528 });
529
530 // Close modal functionality
531 document.querySelectorAll('.modal .close').forEach(closeBtn => {
532 closeBtn.addEventListener('click', () => {
533 closeBtn.closest('.modal').style.display = 'none';
534 });
535 });
536
537 window.addEventListener('click', (event) => {
538 if (event.target.classList.contains('modal')) {
539 event.target.style.display = 'none';
540 }
541 });
542</script>
543</body>
544</html>
Note: See TracBrowser for help on using the repository browser.