Shopping.html
Shopping.html
html
1 <!DOCTYPE html>
2 <html lang="en">
3
4 <head>
5 <meta charset="UTF-8" />
6 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7 <title>Shopping</title>
8 <link rel="stylesheet" href="../node_modules/bootstrap-icons/font/bootstrap-icons.css">
9 <link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.css">
10 <style>
11 body {
12 font-family: 'Segoe UI', sans-serif;
13 background-color: #f8f9fa;
14 }
15
16 .card-title {
17 white-space: nowrap;
18 overflow: hidden;
19 text-overflow: ellipsis;
20 font-weight: bold;
21 font-size: 0.95rem;
22 }
23
24 .product-card {
25 width: 100%;
26 max-width: 260px;
27 flex: 1 1 auto;
28 transition: transform 0.2s ease-in-out;
29 }
30
31 .product-card:hover {
32 transform: scale(1.03);
33 }
34
35 .card-img-top {
36 height: 180px;
37 object-fit: contain;
38 padding: 10px;
39 }
40
41 main {
42 display: flex;
43 flex-wrap: wrap;
44 gap: 1rem;
45 padding: 10px;
46 overflow-y: auto;
47 height: 500px;
48 }
49
50 .card-body {
51 display: flex;
52 flex-direction: column;
53 justify-content: space-between;
54 }
55
56 .modal-body img {
57 border-radius: 4px;
58 }
59
60 #cart .modal-body table {
61 margin-bottom: 0;
62 }
63
64 .total-amount {
65 font-weight: bold;
66 font-size: 1rem;
67 text-align: right;
68 padding: 10px;
69 }
70
71 @media (max-width: 768px) {
72 main {
73 flex-direction: column;
74 align-items: center;
75 }
76
77 nav,
78 aside {
79 margin-bottom: 1rem;
80 }
81 }
82 </style>
83 </head>
84
85 <body class="container-fluid" onload="bodyLoad()">
86 <header class="bg-danger text-white text-center p-3">
87 <h1><i class="bi bi-cart4"></i> Shopping</h1>
88 </header>
89
90 <section class="row mt-3">
91 <!-- Category Filter -->
92 <nav class="col-md-2">
93 <label for="lstcategory" class="form-label">Select Category</label>
94 <select id="lstcategory" class="form-select" onchange="CategoryChange()"></select>
95 </nav>
96
97 <!-- Product Listing -->
98 <main class="col-md-8 bg-light rounded shadow-sm"></main>
99
100 <!-- Cart Button and Modal -->
101 <aside class="col-md-2">
102 <button onclick="ShowCartItems()" class="btn btn-danger w-100 mb-3" data-bs-toggle="modal"
103 data-bs-target="#cart">
104 <i class="bi bi-cart"></i> [<span id="lblcount">0</span>] Your Cart
105 </button>
106
107 <div class="modal fade" id="cart">
108 <div class="modal-dialog modal-dialog-scrollable">
109 <div class="modal-content">
110 <div class="modal-header">
111 <h5 class="modal-title">Your Cart Items</h5>
112 <button class="btn-close" data-bs-dismiss="modal"></button>
113 </div>
114 <div class="modal-body">
115 <table class="table table-striped table-hover">
116 <thead>
117 <tr>
118 <th>Title</th>
119 <th>Price</th>
120 <th>Preview</th>
121 </tr>
122 </thead>
123 <tbody></tbody>
124 </table>
125 </div>
126 <div class="modal-footer d-flex justify-content-between">
127 <div class="total-amount" id="totalAmount">Total: $0.00</div>
128 <button class="btn btn-primary" data-bs-dismiss="modal">Close</button>
129 </div>
130 </div>
131 </div>
132 </div>
133 </aside>
134 </section>
135
136 <script src="../node_modules/jquery/dist/jquery.js"></script>
137 <script src="../node_modules/bootstrap/dist/js/bootstrap.bundle.js"></script>
138 <script>
139 let cartitems = [];
140
141 function bodyLoad() {
142 loadCategories();
143 loadProducts("https://fakestoreapi.com/products");
144 GetItemsCount();
145 }
146
147 function loadCategories() {
148 fetch("https://fakestoreapi.com/products/categories")
149 .then(res => res.json())
150 .then(categories => {
151 categories.unshift("ALL");
152 const select = document.querySelector("#lstcategory");
153 categories.forEach(cat => {
154 const opt = document.createElement("option");
155 opt.value = cat;
156 opt.textContent = cat.toUpperCase();
157 select.appendChild(opt);
158 });
159 });
160 }
161
162 function loadProducts(url) {
163 const main = document.querySelector("main");
164 main.innerHTML = "<p class='text-center w-100'>Loading...</p>";
165
166 fetch(url)
167 .then(res => res.json())
168 .then(products => {
169 main.innerHTML = "";
170 products.forEach(product => {
171 const cardWrapper = document.createElement("div");
172 cardWrapper.className = "product-card";
173
174 cardWrapper.innerHTML = `
175 <div class="card h-100 shadow-sm">
176 <img src="${product.image}" class="card-img-top" alt="${product.title}">
177 <div class="card-body d-flex flex-column">
178 <h6 class="card-title" title="${product.title}">${product.title}</h6>
179 <p class="text-muted small mb-2 flex-grow-1">${product.description.substring(0, 60)}...</p>
180 <dl class="row mb-2">
181 <dt class="col-sm-5">Price:</dt>
182 <dd class="col-sm-7">$${product.price.toFixed(2)}</dd>
183 <dt class="col-sm-5">Rating:</dt>
184 <dd class="col-sm-7"><i class="bi bi-star-fill text-success"></i> ${product.rating.rate}
(${product.rating.count})</dd>
185 </dl>
186 </div>
187 <div class="card-footer bg-transparent border-0">
188 <button class="btn btn-danger w-100" onclick="AddClick(${product.id})">
189 <i class="bi bi-cart2"></i> Add to Cart
190 </button>
191 </div>
192 </div>
193 `;
194
195 main.appendChild(cardWrapper);
196 });
197 });
198 }
199
200 function CategoryChange() {
201 const category = document.querySelector("#lstcategory").value;
202 const url = category === "ALL"
203 ? "https://fakestoreapi.com/products"
204 : `https://fakestoreapi.com/products/category/${category}`;
205 loadProducts(url);
206 }
207
208 function AddClick(id) {
209 fetch(`https://fakestoreapi.com/products/${id}`)
210 .then(res => res.json())
211 .then(product => {
212 cartitems.push(product);
213 alert(`${product.title} added to cart.`);
214 GetItemsCount();
215 });
216 }
217
218 function GetItemsCount() {
219 document.querySelector("#lblcount").textContent = cartitems.length;
220 }
221
222 function ShowCartItems() {
223 const tbody = document.querySelector("tbody");
224 const totalDiv = document.querySelector("#totalAmount");
225 tbody.innerHTML = "";
226
227 let total = 0;
228 cartitems.forEach(item => {
229 total += item.price;
230 const row = document.createElement("tr");
231 row.innerHTML = `
232 <td>${item.title}</td>
233 <td>$${item.price.toFixed(2)}</td>
234 <td><img src="${item.image}" width="50" height="50" alt=""></td>
235 `;
236 tbody.appendChild(row);
237 });
238
239 totalDiv.textContent = `Total: $${total.toFixed(2)}`;
240 }
241 </script>
242 </body>
243
244 </html>