viswanani commited on
Commit
05ba257
·
verified ·
1 Parent(s): beccaa3

build a virtual trion for clothing i am looking for a compleate application with logic for face detection posture face mesurements garment resizing everything that a virtual trion must have no place holders - Follow Up Deployment

Browse files
Files changed (1) hide show
  1. index.html +766 -456
index.html CHANGED
@@ -3,530 +3,840 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>QuickCart - Grocery Delivery in Minutes</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
 
9
  <style>
10
- .category-scroll::-webkit-scrollbar {
11
- display: none;
 
 
 
 
 
12
  }
13
 
14
- .product-scroll::-webkit-scrollbar {
15
- display: none;
 
16
  }
17
 
18
- .cart-slide {
19
- transform: translateX(100%);
20
- transition: transform 0.3s ease-in-out;
 
 
 
21
  }
22
 
23
- .cart-slide.open {
24
- transform: translateX(0);
 
 
 
 
 
 
 
25
  }
26
 
27
- .search-bar:focus {
28
- outline: none;
 
 
 
29
  }
30
 
31
- .offer-banner {
32
- background: linear-gradient(90deg, #ff5e62, #ff9966);
33
  }
34
 
35
- .discount-badge {
36
- background: linear-gradient(135deg, #ff5e62, #ff9966);
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
  </style>
39
  </head>
40
- <body class="bg-gray-50 font-sans">
41
- <!-- Header -->
42
- <header class="bg-white shadow-sm sticky top-0 z-50">
43
- <div class="container mx-auto px-4 py-3">
44
- <div class="flex items-center justify-between">
45
- <!-- Location and Delivery Time -->
46
- <div class="flex items-center space-x-2">
47
- <div class="text-orange-500">
48
- <i class="fas fa-map-marker-alt"></i>
49
- </div>
50
- <div>
51
- <p class="text-sm font-medium">Delivery to</p>
52
- <div class="flex items-center">
53
- <p class="text-xs font-semibold">Home</p>
54
- <i class="fas fa-chevron-down text-xs ml-1"></i>
 
 
 
 
 
 
55
  </div>
56
  </div>
57
  </div>
58
 
59
- <!-- Search Bar -->
60
- <div class="flex-1 mx-4">
61
- <div class="relative">
62
- <input type="text" placeholder="Search for products..."
63
- class="w-full bg-gray-100 rounded-full py-2 px-4 pl-10 text-sm focus:ring-2 focus:ring-orange-300 search-bar">
64
- <i class="fas fa-search absolute left-3 top-2.5 text-gray-400"></i>
65
- </div>
 
 
 
 
 
 
 
 
 
66
  </div>
67
 
68
- <!-- Cart and Profile -->
69
- <div class="flex items-center space-x-4">
70
- <div class="relative">
71
- <i class="fas fa-shopping-cart text-xl text-gray-700"></i>
72
- <span class="absolute -top-2 -right-2 bg-orange-500 text-white text-xs rounded-full h-5 w-5 flex items-center justify-center">3</span>
73
- </div>
74
- <div>
75
- <i class="fas fa-user-circle text-xl text-gray-700"></i>
76
  </div>
77
  </div>
78
  </div>
79
- </div>
80
- </header>
81
-
82
- <!-- Main Content -->
83
- <main class="container mx-auto px-4 pb-20">
84
- <!-- Offer Banner -->
85
- <div class="mt-3 rounded-xl overflow-hidden offer-banner text-white p-4">
86
- <div class="flex items-center justify-between">
87
- <div>
88
- <h3 class="font-bold text-lg">Get 50% OFF</h3>
89
- <p class="text-sm mt-1">On your first order</p>
90
- <button class="bg-white text-orange-500 px-3 py-1 rounded-full text-xs font-bold mt-2">ORDER NOW</button>
91
- </div>
92
- <div>
93
- <img src="https://via.placeholder.com/100x80" alt="Offer" class="h-20">
94
- </div>
95
- </div>
96
- </div>
97
-
98
- <!-- Delivery Time -->
99
- <div class="mt-4 bg-white rounded-lg shadow-sm p-3 flex items-center justify-between">
100
- <div class="flex items-center">
101
- <i class="fas fa-bolt text-orange-500 mr-2"></i>
102
- <p class="text-sm font-medium">Delivery in 10 minutes</p>
103
- </div>
104
- <div>
105
- <i class="fas fa-chevron-right text-gray-400"></i>
106
- </div>
107
- </div>
108
-
109
- <!-- Categories -->
110
- <div class="mt-4">
111
- <h2 class="text-lg font-bold mb-3">Categories</h2>
112
- <div class="flex space-x-4 overflow-x-auto pb-2 category-scroll">
113
- <div class="flex flex-col items-center">
114
- <div class="bg-white rounded-full p-3 shadow-sm">
115
- <img src="https://cdn.pixabay.com/photo/2016/04/13/22/21/banana-1327878_640.png" alt="Fruits" class="h-8 w-8">
116
- </div>
117
- <p class="text-xs mt-1">Fruits</p>
118
- </div>
119
- <div class="flex flex-col items-center">
120
- <div class="bg-white rounded-full p-3 shadow-sm">
121
- <img src="https://cdn.pixabay.com/photo/2016/03/05/19/02/tomato-1238255_640.jpg" alt="Vegetables" class="h-8 w-8">
122
- </div>
123
- <p class="text-xs mt-1">Vegetables</p>
124
- </div>
125
- <div class="flex flex-col items-center">
126
- <div class="bg-white rounded-full p-3 shadow-sm">
127
- <img src="https://cdn.pixabay.com/photo/2017/07/05/15/41/milk-2474993_640.png" alt="Dairy" class="h-8 w-8">
128
- </div>
129
- <p class="text-xs mt-1">Dairy</p>
130
- </div>
131
- <div class="flex flex-col items-center">
132
- <div class="bg-white rounded-full p-3 shadow-sm">
133
- <img src="https://cdn.pixabay.com/photo/2014/12/11/02/55/coke-563796_640.jpg" alt="Beverages" class="h-8 w-8">
134
- </div>
135
- <p class="text-xs mt-1">Beverages</p>
136
- </div>
137
- <div class="flex flex-col items-center">
138
- <div class="bg-white rounded-full p-3 shadow-sm">
139
- <img src="https://cdn.pixabay.com/photo/2016/03/05/20/00/chips-1239089_640.jpg" alt="Snacks" class="h-8 w-8">
140
- </div>
141
- <p class="text-xs mt-1">Snacks</p>
142
- </div>
143
- <div class="flex flex-col items-center">
144
- <div class="bg-white rounded-full p-3 shadow-sm">
145
- <img src="https://cdn.pixabay.com/photo/2018/02/25/07/15/meat-3179851_640.png" alt="Meat" class="h-8 w-8">
146
- </div>
147
- <p class="text-xs mt-1">Meat</p>
148
- </div>
149
- <div class="flex flex-col items-center">
150
- <div class="bg-white rounded-full p-3 shadow-sm">
151
- <img src="https://cdn.pixabay.com/photo/2014/07/12/14/42/bread-389622_640.jpg" alt="Bakery" class="h-8 w-8">
152
- </div>
153
- <p class="text-xs mt-1">Bakery</p>
154
- </div>
155
- </div>
156
- </div>
157
-
158
- <!-- Popular Products -->
159
- <div class="mt-6">
160
- <div class="flex items-center justify-between mb-3">
161
- <h2 class="text-lg font-bold">Popular Products</h2>
162
- <a href="#" class="text-orange-500 text-sm font-medium">See All</a>
163
- </div>
164
- <div class="grid grid-cols-2 gap-3">
165
- <!-- Product 1 -->
166
- <div class="bg-white rounded-lg shadow-sm p-3">
167
- <div class="relative">
168
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
169
- <div class="absolute top-2 left-2 bg-orange-500 text-white text-xs px-2 py-1 rounded-full discount-badge">20% OFF</div>
170
- </div>
171
- <h3 class="text-sm font-medium mt-2">Fresh Apples</h3>
172
- <p class="text-xs text-gray-500">1kg</p>
173
- <div class="flex items-center justify-between mt-2">
174
- <p class="text-sm font-bold">₹120</p>
175
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
176
- <i class="fas fa-plus text-xs"></i>
177
- </button>
178
- </div>
179
- </div>
180
 
181
- <!-- Product 2 -->
182
- <div class="bg-white rounded-lg shadow-sm p-3">
183
- <div class="relative">
184
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
185
- <div class="absolute top-2 left-2 bg-orange-500 text-white text-xs px-2 py-1 rounded-full discount-badge">15% OFF</div>
186
- </div>
187
- <h3 class="text-sm font-medium mt-2">Banana</h3>
188
- <p class="text-xs text-gray-500">6pcs</p>
189
- <div class="flex items-center justify-between mt-2">
190
- <p class="text-sm font-bold">₹45</p>
191
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
192
- <i class="fas fa-plus text-xs"></i>
193
- </button>
194
- </div>
195
  </div>
196
 
197
- <!-- Product 3 -->
198
- <div class="bg-white rounded-lg shadow-sm p-3">
199
- <div class="relative">
200
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
201
- </div>
202
- <h3 class="text-sm font-medium mt-2">Milk</h3>
203
- <p class="text-xs text-gray-500">1L</p>
204
- <div class="flex items-center justify-between mt-2">
205
- <p class="text-sm font-bold">₹60</p>
206
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
207
- <i class="fas fa-plus text-xs"></i>
208
- </button>
209
  </div>
210
  </div>
211
 
212
- <!-- Product 4 -->
213
- <div class="bg-white rounded-lg shadow-sm p-3">
214
- <div class="relative">
215
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
216
- <div class="absolute top-2 left-2 bg-orange-500 text-white text-xs px-2 py-1 rounded-full discount-badge">10% OFF</div>
217
- </div>
218
- <h3 class="text-sm font-medium mt-2">Bread</h3>
219
- <p class="text-xs text-gray-500">400g</p>
220
- <div class="flex items-center justify-between mt-2">
221
- <p class="text-sm font-bold">₹35</p>
222
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
223
- <i class="fas fa-plus text-xs"></i>
224
- </button>
225
- </div>
226
- </div>
227
- </div>
228
- </div>
229
-
230
- <!-- Deals of the Day -->
231
- <div class="mt-6">
232
- <div class="flex items-center justify-between mb-3">
233
- <h2 class="text-lg font-bold">Deals of the Day</h2>
234
- <a href="#" class="text-orange-500 text-sm font-medium">See All</a>
235
- </div>
236
- <div class="bg-white rounded-lg shadow-sm p-4">
237
- <div class="flex items-center justify-between">
238
- <div>
239
- <h3 class="font-bold">Flash Sale</h3>
240
- <p class="text-xs text-gray-500 mt-1">Ends in 4:32:15</p>
241
- </div>
242
- <div class="flex space-x-2">
243
- <div class="bg-orange-100 text-orange-500 text-xs px-2 py-1 rounded">04</div>
244
- <div class="bg-orange-100 text-orange-500 text-xs px-2 py-1 rounded">32</div>
245
- <div class="bg-orange-100 text-orange-500 text-xs px-2 py-1 rounded">15</div>
246
- </div>
247
- </div>
248
-
249
- <div class="flex overflow-x-auto space-x-4 mt-4 pb-2 product-scroll">
250
- <!-- Deal Product 1 -->
251
- <div class="flex-shrink-0 w-32">
252
- <img src="https://via.placeholder.com/120" alt="Deal Product" class="w-full rounded-lg">
253
- <h3 class="text-sm font-medium mt-2">Potato Chips</h3>
254
- <p class="text-xs text-gray-500">100g</p>
255
- <div class="flex items-center justify-between mt-2">
256
- <p class="text-sm font-bold">₹20</p>
257
- <p class="text-xs line-through text-gray-400">₹25</p>
258
- </div>
259
- </div>
260
-
261
- <!-- Deal Product 2 -->
262
- <div class="flex-shrink-0 w-32">
263
- <img src="https://via.placeholder.com/120" alt="Deal Product" class="w-full rounded-lg">
264
- <h3 class="text-sm font-medium mt-2">Soft Drink</h3>
265
- <p class="text-xs text-gray-500">250ml</p>
266
- <div class="flex items-center justify-between mt-2">
267
- <p class="text-sm font-bold">₹30</p>
268
- <p class="text-xs line-through text-gray-400">₹40</p>
269
- </div>
270
- </div>
271
-
272
- <!-- Deal Product 3 -->
273
- <div class="flex-shrink-0 w-32">
274
- <img src="https://via.placeholder.com/120" alt="Deal Product" class="w-full rounded-lg">
275
- <h3 class="text-sm font-medium mt-2">Chocolate</h3>
276
- <p class="text-xs text-gray-500">50g</p>
277
- <div class="flex items-center justify-between mt-2">
278
- <p class="text-sm font-bold">₹45</p>
279
- <p class="text-xs line-through text-gray-400">₹60</p>
280
- </div>
281
- </div>
282
-
283
- <!-- Deal Product 4 -->
284
- <div class="flex-shrink-0 w-32">
285
- <img src="https://via.placeholder.com/120" alt="Deal Product" class="w-full rounded-lg">
286
- <h3 class="text-sm font-medium mt-2">Biscuits</h3>
287
- <p class="text-xs text-gray-500">200g</p>
288
- <div class="flex items-center justify-between mt-2">
289
- <p class="text-sm font-bold">₹25</p>
290
- <p class="text-xs line-through text-gray-400">₹35</p>
291
  </div>
292
- </div>
293
- </div>
294
- </div>
295
- </div>
296
-
297
- <!-- Recommended for You -->
298
- <div class="mt-6">
299
- <div class="flex items-center justify-between mb-3">
300
- <h2 class="text-lg font-bold">Recommended for You</h2>
301
- <a href="#" class="text-orange-500 text-sm font-medium">See All</a>
302
- </div>
303
- <div class="grid grid-cols-2 gap-3">
304
- <!-- Recommended Product 1 -->
305
- <div class="bg-white rounded-lg shadow-sm p-3">
306
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
307
- <h3 class="text-sm font-medium mt-2">Tomatoes</h3>
308
- <p class="text-xs text-gray-500">500g</p>
309
- <div class="flex items-center justify-between mt-2">
310
- <p class="text-sm font-bold">₹30</p>
311
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
312
- <i class="fas fa-plus text-xs"></i>
313
- </button>
314
  </div>
315
  </div>
316
 
317
- <!-- Recommended Product 2 -->
318
- <div class="bg-white rounded-lg shadow-sm p-3">
319
- <img src="https://via.placeholder.com/150" alt="Product" class="w-full rounded-lg">
320
- <h3 class="text-sm font-medium mt-2">Onions</h3>
321
- <p class="text-xs text-gray-500">1kg</p>
322
- <div class="flex items-center justify-between mt-2">
323
- <p class="text-sm font-bold">₹40</p>
324
- <button class="bg-orange-500 text-white rounded-full h-6 w-6 flex items-center justify-center">
325
- <i class="fas fa-plus text-xs"></i>
326
- </button>
327
- </div>
328
- </div>
329
- </div>
330
- </div>
331
- </main>
332
-
333
- <!-- Bottom Navigation -->
334
- <nav class="fixed bottom-0 left-0 right-0 bg-white shadow-lg border-t border-gray-200 z-50">
335
- <div class="container mx-auto px-4">
336
- <div class="flex justify-around py-3">
337
- <a href="#" class="flex flex-col items-center text-orange-500">
338
- <i class="fas fa-home text-xl"></i>
339
- <span class="text-xs mt-1">Home</span>
340
- </a>
341
- <a href="#" class="flex flex-col items-center text-gray-500">
342
- <i class="fas fa-search text-xl"></i>
343
- <span class="text-xs mt-1">Search</span>
344
- </a>
345
- <a href="#" class="flex flex-col items-center text-gray-500">
346
- <i class="fas fa-shopping-bag text-xl"></i>
347
- <span class="text-xs mt-1">Orders</span>
348
- </a>
349
- <a href="#" class="flex flex-col items-center text-gray-500">
350
- <i class="fas fa-user text-xl"></i>
351
- <span class="text-xs mt-1">Account</span>
352
- </a>
353
- </div>
354
- </div>
355
- </nav>
356
-
357
- <!-- Cart Sidebar -->
358
- <div class="fixed inset-0 z-50 overflow-hidden cart-slide" id="cartSidebar">
359
- <div class="absolute inset-0 bg-black bg-opacity-50" id="cartOverlay"></div>
360
- <div class="absolute top-0 right-0 bottom-0 w-full max-w-md bg-white shadow-xl">
361
- <div class="h-full flex flex-col">
362
- <!-- Cart Header -->
363
- <div class="bg-white border-b border-gray-200 p-4">
364
- <div class="flex items-center justify-between">
365
- <h2 class="text-lg font-bold">Your Cart (3)</h2>
366
- <button class="text-gray-500" id="closeCart">
367
- <i class="fas fa-times"></i>
368
- </button>
369
- </div>
370
- <div class="flex items-center mt-2">
371
- <i class="fas fa-map-marker-alt text-orange-500 mr-2"></i>
372
- <p class="text-sm">Delivery to Home in 10 minutes</p>
373
  </div>
374
  </div>
375
 
376
- <!-- Cart Items -->
377
- <div class="flex-1 overflow-y-auto p-4">
378
- <!-- Cart Item 1 -->
379
- <div class="flex items-center justify-between py-3 border-b border-gray-100">
380
- <div class="flex items-center">
381
- <img src="https://via.placeholder.com/60" alt="Product" class="h-12 w-12 rounded-lg">
382
- <div class="ml-3">
383
- <h3 class="text-sm font-medium">Fresh Apples</h3>
384
- <p class="text-xs text-gray-500">1kg</p>
385
- <p class="text-sm font-bold mt-1">₹120</p>
386
- </div>
387
  </div>
388
- <div class="flex items-center bg-gray-100 rounded-full">
389
- <button class="px-3 py-1 text-gray-500">-</button>
390
- <span class="text-sm font-medium">1</span>
391
- <button class="px-3 py-1 text-orange-500">+</button>
392
  </div>
393
- </div>
394
-
395
- <!-- Cart Item 2 -->
396
- <div class="flex items-center justify-between py-3 border-b border-gray-100">
397
- <div class="flex items-center">
398
- <img src="https://via.placeholder.com/60" alt="Product" class="h-12 w-12 rounded-lg">
399
- <div class="ml-3">
400
- <h3 class="text-sm font-medium">Banana</h3>
401
- <p class="text-xs text-gray-500">6pcs</p>
402
- <p class="text-sm font-bold mt-1">₹45</p>
403
- </div>
404
- </div>
405
- <div class="flex items-center bg-gray-100 rounded-full">
406
- <button class="px-3 py-1 text-gray-500">-</button>
407
- <span class="text-sm font-medium">2</span>
408
- <button class="px-3 py-1 text-orange-500">+</button>
409
  </div>
410
- </div>
411
-
412
- <!-- Cart Item 3 -->
413
- <div class="flex items-center justify-between py-3 border-b border-gray-100">
414
- <div class="flex items-center">
415
- <img src="https://via.placeholder.com/60" alt="Product" class="h-12 w-12 rounded-lg">
416
- <div class="ml-3">
417
- <h3 class="text-sm font-medium">Milk</h3>
418
- <p class="text-xs text-gray-500">1L</p>
419
- <p class="text-sm font-bold mt-1">₹60</p>
420
- </div>
421
  </div>
422
- <div class="flex items-center bg-gray-100 rounded-full">
423
- <button class="px-3 py-1 text-gray-500">-</button>
424
- <span class="text-sm font-medium">1</span>
425
- <button class="px-3 py-1 text-orange-500">+</button>
426
  </div>
427
  </div>
428
  </div>
429
 
430
- <!-- Cart Summary -->
431
- <div class="border-t border-gray-200 p-4">
432
- <div class="flex justify-between mb-2">
433
- <p class="text-sm text-gray-600">Subtotal</p>
434
- <p class="text-sm font-bold">₹225</p>
435
- </div>
436
- <div class="flex justify-between mb-2">
437
- <p class="text-sm text-gray-600">Delivery Fee</p>
438
- <p class="text-sm font-bold">₹10</p>
439
- </div>
440
- <div class="flex justify-between mb-4">
441
- <p class="text-sm text-gray-600">Discount</p>
442
- <p class="text-sm font-bold text-green-500">-₹30</p>
443
- </div>
444
- <div class="flex justify-between font-bold text-lg">
445
- <p>Total</p>
446
- <p>₹205</p>
447
  </div>
448
- <button class="w-full bg-orange-500 text-white py-3 rounded-lg font-bold mt-4">
449
- Proceed to Checkout
450
- </button>
451
  </div>
452
  </div>
453
  </div>
454
  </div>
455
 
456
  <script>
457
- // Toggle cart sidebar
458
- const cartIcon = document.querySelector('.fa-shopping-cart').parentElement;
459
- const cartSidebar = document.getElementById('cartSidebar');
460
- const cartOverlay = document.getElementById('cartOverlay');
461
- const closeCart = document.getElementById('closeCart');
462
-
463
- cartIcon.addEventListener('click', () => {
464
- cartSidebar.classList.add('open');
465
- });
 
 
 
 
 
 
 
 
 
 
 
 
466
 
467
- closeCart.addEventListener('click', () => {
468
- cartSidebar.classList.remove('open');
469
- });
 
 
 
470
 
471
- cartOverlay.addEventListener('click', () => {
472
- cartSidebar.classList.remove('open');
473
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
474
 
475
- // Add to cart functionality
476
- const addButtons = document.querySelectorAll('[class*="fa-plus"]');
477
- addButtons.forEach(button => {
478
- button.addEventListener('click', (e) => {
479
- e.stopPropagation();
480
- const productCard = button.closest('.bg-white');
481
- const productName = productCard.querySelector('h3').textContent;
482
- const productPrice = productCard.querySelector('p.text-sm.font-bold').textContent;
483
 
484
- // In a real app, you would add this to your cart state
485
- alert(`Added ${productName} to cart for ${productPrice}`);
486
 
487
- // Update cart count
488
- const cartCount = document.querySelector('.fa-shopping-cart').nextElementSibling;
489
- let count = parseInt(cartCount.textContent);
490
- cartCount.textContent = count + 1;
491
 
492
- // Show cart sidebar
493
- cartSidebar.classList.add('open');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
494
  });
495
- });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
496
 
497
- // Quantity adjustment in cart
498
- const quantityButtons = document.querySelectorAll('.bg-gray-100 button');
499
- quantityButtons.forEach(button => {
500
- button.addEventListener('click', () => {
501
- const quantityDisplay = button.parentElement.querySelector('span');
502
- let quantity = parseInt(quantityDisplay.textContent);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
503
 
504
- if (button.textContent === '+' && quantity < 10) {
505
- quantityDisplay.textContent = quantity + 1;
506
- } else if (button.textContent === '-' && quantity > 1) {
507
- quantityDisplay.textContent = quantity - 1;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
508
  }
509
 
510
- // In a real app, you would update the cart total here
 
 
 
 
 
 
 
 
 
 
511
  });
 
 
 
 
 
 
 
 
 
 
 
 
512
  });
513
- </script>
514
-
515
- <!-- Simplified API Integration -->
516
- <script>
517
- // This would be where you'd implement your actual API integration
518
- // For now, we'll just log that the page loaded successfully
519
- document.addEventListener('DOMContentLoaded', () => {
520
- console.log('QuickCart loaded successfully');
521
-
522
- // Example: You would fetch products from your backend API here
523
- // fetch('/api/products')
524
- // .then(response => response.json())
525
- // .then(products => {
526
- // console.log('Products loaded:', products);
527
- // // Update the UI with the fetched products
528
- // });
529
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
530
  </script>
531
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=viswanani/clone-app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
532
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Virtual Fitting Room</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/face-landmarks-detection@0.0.1/dist/face-landmarks-detection.js"></script>
10
  <style>
11
+ .loading-spinner {
12
+ border: 4px solid rgba(255, 255, 255, 0.3);
13
+ border-radius: 50%;
14
+ border-top: 4px solid #6366f1;
15
+ width: 30px;
16
+ height: 30px;
17
+ animation: spin 1s linear infinite;
18
  }
19
 
20
+ @keyframes spin {
21
+ 0% { transform: rotate(0deg); }
22
+ 100% { transform: rotate(360deg); }
23
  }
24
 
25
+ .measurement-line {
26
+ position: absolute;
27
+ background-color: rgba(99, 102, 241, 0.7);
28
+ height: 2px;
29
+ transform-origin: left center;
30
+ z-index: 10;
31
  }
32
 
33
+ .measurement-label {
34
+ position: absolute;
35
+ background-color: rgba(99, 102, 241, 0.9);
36
+ color: white;
37
+ padding: 2px 5px;
38
+ border-radius: 4px;
39
+ font-size: 12px;
40
+ z-index: 11;
41
+ transform: translateY(-50%);
42
  }
43
 
44
+ .clothing-item {
45
+ position: absolute;
46
+ transition: all 0.3s ease;
47
+ cursor: move;
48
+ z-index: 5;
49
  }
50
 
51
+ .clothing-item.selected {
52
+ outline: 2px solid #6366f1;
53
  }
54
 
55
+ .posture-indicator {
56
+ position: absolute;
57
+ width: 10px;
58
+ height: 10px;
59
+ border-radius: 50%;
60
+ background-color: #10b981;
61
+ z-index: 10;
62
+ }
63
+
64
+ .posture-indicator.bad {
65
+ background-color: #ef4444;
66
+ }
67
+
68
+ #previewCanvas {
69
+ transform: scaleX(-1);
70
  }
71
  </style>
72
  </head>
73
+ <body class="bg-gray-100 min-h-screen">
74
+ <div class="container mx-auto px-4 py-8">
75
+ <header class="mb-8">
76
+ <h1 class="text-3xl font-bold text-indigo-700 text-center">Virtual Fitting Room</h1>
77
+ <p class="text-gray-600 text-center mt-2">Try on clothes virtually with real-time measurements</p>
78
+ </header>
79
+
80
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
81
+ <!-- Camera Feed Section -->
82
+ <div class="lg:col-span-2 bg-white rounded-lg shadow-md p-4">
83
+ <div class="relative">
84
+ <video id="video" width="100%" height="auto" autoplay muted playsinline class="rounded-lg hidden"></video>
85
+ <canvas id="previewCanvas" width="640" height="480" class="rounded-lg w-full"></canvas>
86
+ <div id="loadingIndicator" class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 rounded-lg">
87
+ <div class="loading-spinner"></div>
88
+ <span class="ml-2 text-white">Loading models...</span>
89
+ </div>
90
+ <div id="errorMessage" class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 rounded-lg hidden">
91
+ <div class="bg-red-500 text-white p-4 rounded-lg">
92
+ <p id="errorText">Error message</p>
93
+ <button id="retryButton" class="mt-2 bg-white text-red-500 px-4 py-1 rounded">Retry</button>
94
  </div>
95
  </div>
96
  </div>
97
 
98
+ <div class="mt-4 flex flex-wrap gap-2">
99
+ <button id="startCamera" class="bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700 transition">
100
+ Start Camera
101
+ </button>
102
+ <button id="takePhoto" class="bg-green-600 text-white px-4 py-2 rounded hover:bg-green-700 transition hidden">
103
+ Take Photo
104
+ </button>
105
+ <button id="toggleMeasurements" class="bg-purple-600 text-white px-4 py-2 rounded hover:bg-purple-700 transition">
106
+ Show Measurements
107
+ </button>
108
+ <button id="togglePosture" class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 transition">
109
+ Show Posture
110
+ </button>
111
+ <button id="resetClothing" class="bg-gray-600 text-white px-4 py-2 rounded hover:bg-gray-700 transition">
112
+ Reset Clothing
113
+ </button>
114
  </div>
115
 
116
+ <div class="mt-4 p-4 bg-gray-50 rounded-lg">
117
+ <h3 class="font-semibold text-lg mb-2">Posture Analysis</h3>
118
+ <div id="postureFeedback" class="text-sm">
119
+ <p>Stand in front of the camera to analyze your posture.</p>
 
 
 
 
120
  </div>
121
  </div>
122
  </div>
123
+
124
+ <!-- Clothing Selection Section -->
125
+ <div class="bg-white rounded-lg shadow-md p-4">
126
+ <h2 class="text-xl font-semibold mb-4">Select Clothing</h2>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
+ <div class="mb-4">
129
+ <label class="block text-sm font-medium text-gray-700 mb-1">Clothing Type</label>
130
+ <select id="clothingType" class="w-full p-2 border border-gray-300 rounded-md">
131
+ <option value="t-shirt">T-Shirt</option>
132
+ <option value="shirt">Shirt</option>
133
+ <option value="dress">Dress</option>
134
+ <option value="pants">Pants</option>
135
+ <option value="jacket">Jacket</option>
136
+ </select>
 
 
 
 
 
137
  </div>
138
 
139
+ <div class="mb-4">
140
+ <label class="block text-sm font-medium text-gray-700 mb-1">Color</label>
141
+ <div class="flex flex-wrap gap-2">
142
+ <div class="w-8 h-8 rounded-full bg-red-500 cursor-pointer border-2 border-transparent hover:border-gray-300" data-color="red"></div>
143
+ <div class="w-8 h-8 rounded-full bg-blue-500 cursor-pointer border-2 border-transparent hover:border-gray-300" data-color="blue"></div>
144
+ <div class="w-8 h-8 rounded-full bg-green-500 cursor-pointer border-2 border-transparent hover:border-gray-300" data-color="green"></div>
145
+ <div class="w-8 h-8 rounded-full bg-black cursor-pointer border-2 border-transparent hover:border-gray-300" data-color="black"></div>
146
+ <div class="w-8 h-8 rounded-full bg-white cursor-pointer border-2 border-gray-300 hover:border-gray-500" data-color="white"></div>
147
+ <div class="w-8 h-8 rounded-full bg-yellow-400 cursor-pointer border-2 border-transparent hover:border-gray-300" data-color="yellow"></div>
 
 
 
148
  </div>
149
  </div>
150
 
151
+ <div class="mb-4">
152
+ <label class="block text-sm font-medium text-gray-700 mb-1">Pattern</label>
153
+ <div class="flex flex-wrap gap-2">
154
+ <div class="w-12 h-12 bg-gray-200 cursor-pointer border-2 border-transparent hover:border-gray-300 flex items-center justify-center" data-pattern="solid">
155
+ <span class="text-xs">Solid</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  </div>
157
+ <div class="w-12 h-12 bg-gray-200 cursor-pointer border-2 border-transparent hover:border-gray-300" style="background-image: linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc), linear-gradient(45deg, #ccc 25%, transparent 25%, transparent 75%, #ccc 75%, #ccc); background-size: 10px 10px;" data-pattern="checkered"></div>
158
+ <div class="w-12 h-12 bg-gray-200 cursor-pointer border-2 border-transparent hover:border-gray-300" style="background-image: radial-gradient(circle, #999 1px, transparent 1px); background-size: 10px 10px;" data-pattern="polka"></div>
159
+ <div class="w-12 h-12 bg-gray-200 cursor-pointer border-2 border-transparent hover:border-gray-300" style="background-image: linear-gradient(0deg, #999, #999 50%, transparent 50%, transparent 100%); background-size: 10px 10px;" data-pattern="striped"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  </div>
161
  </div>
162
 
163
+ <div class="mb-4">
164
+ <label class="block text-sm font-medium text-gray-700 mb-1">Size Adjustment</label>
165
+ <div class="flex items-center gap-2">
166
+ <button id="decreaseSize" class="bg-gray-200 p-1 rounded-full w-8 h-8 flex items-center justify-center hover:bg-gray-300">-</button>
167
+ <span id="sizeValue" class="font-medium">100%</span>
168
+ <button id="increaseSize" class="bg-gray-200 p-1 rounded-full w-8 h-8 flex items-center justify-center hover:bg-gray-300">+</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
169
  </div>
170
  </div>
171
 
172
+ <button id="addClothing" class="w-full bg-indigo-600 text-white px-4 py-2 rounded hover:bg-indigo-700 transition">
173
+ Add to Fitting Room
174
+ </button>
175
+
176
+ <div class="mt-6">
177
+ <h3 class="font-semibold text-lg mb-2">Your Measurements</h3>
178
+ <div id="measurementsDisplay" class="text-sm space-y-1">
179
+ <div class="flex justify-between">
180
+ <span>Shoulder Width:</span>
181
+ <span id="shoulderWidth">-- cm</span>
 
182
  </div>
183
+ <div class="flex justify-between">
184
+ <span>Chest Width:</span>
185
+ <span id="chestWidth">-- cm</span>
 
186
  </div>
187
+ <div class="flex justify-between">
188
+ <span>Waist Width:</span>
189
+ <span id="waistWidth">-- cm</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  </div>
191
+ <div class="flex justify-between">
192
+ <span>Hip Width:</span>
193
+ <span id="hipWidth">-- cm</span>
 
 
 
 
 
 
 
 
194
  </div>
195
+ <div class="flex justify-between">
196
+ <span>Torso Length:</span>
197
+ <span id="torsoLength">-- cm</span>
 
198
  </div>
199
  </div>
200
  </div>
201
 
202
+ <div class="mt-6 p-4 bg-indigo-50 rounded-lg">
203
+ <h3 class="font-semibold text-lg mb-2 text-indigo-800">Fit Recommendation</h3>
204
+ <div id="fitRecommendation" class="text-sm text-indigo-700">
205
+ <p>Add clothing to see fit recommendations based on your measurements.</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  </div>
 
 
 
207
  </div>
208
  </div>
209
  </div>
210
  </div>
211
 
212
  <script>
213
+ // Global variables
214
+ let model = null;
215
+ let video = document.getElementById('video');
216
+ let canvas = document.getElementById('previewCanvas');
217
+ let ctx = canvas.getContext('2d');
218
+ let loadingIndicator = document.getElementById('loadingIndicator');
219
+ let errorMessage = document.getElementById('errorMessage');
220
+ let errorText = document.getElementById('errorText');
221
+ let retryButton = document.getElementById('retryButton');
222
+ let startCameraButton = document.getElementById('startCamera');
223
+ let takePhotoButton = document.getElementById('takePhoto');
224
+ let toggleMeasurementsButton = document.getElementById('toggleMeasurements');
225
+ let togglePostureButton = document.getElementById('togglePosture');
226
+ let resetClothingButton = document.getElementById('resetClothing');
227
+ let addClothingButton = document.getElementById('addClothing');
228
+ let clothingTypeSelect = document.getElementById('clothingType');
229
+ let decreaseSizeButton = document.getElementById('decreaseSize');
230
+ let increaseSizeButton = document.getElementById('increaseSize');
231
+ let sizeValueSpan = document.getElementById('sizeValue');
232
+ let postureFeedback = document.getElementById('postureFeedback');
233
+ let fitRecommendation = document.getElementById('fitRecommendation');
234
 
235
+ // Measurement display elements
236
+ let shoulderWidthSpan = document.getElementById('shoulderWidth');
237
+ let chestWidthSpan = document.getElementById('chestWidth');
238
+ let waistWidthSpan = document.getElementById('waistWidth');
239
+ let hipWidthSpan = document.getElementById('hipWidth');
240
+ let torsoLengthSpan = document.getElementById('torsoLength');
241
 
242
+ // State variables
243
+ let isCameraOn = false;
244
+ let showMeasurements = false;
245
+ let showPosture = false;
246
+ let currentSize = 100;
247
+ let selectedColor = 'blue';
248
+ let selectedPattern = 'solid';
249
+ let clothingItems = [];
250
+ let selectedClothingItem = null;
251
+ let isDragging = false;
252
+ let dragOffsetX = 0;
253
+ let dragOffsetY = 0;
254
+ let measurements = {
255
+ shoulderWidth: 0,
256
+ chestWidth: 0,
257
+ waistWidth: 0,
258
+ hipWidth: 0,
259
+ torsoLength: 0
260
+ };
261
+
262
+ // Constants
263
+ const PIXELS_PER_CM = 10; // This would need calibration in a real application
264
+ const GOOD_POSTURE_THRESHOLD = 5; // Degrees from vertical
265
 
266
+ // Initialize the application
267
+ async function init() {
268
+ try {
269
+ // Load the face and body detection model
270
+ model = await faceLandmarksDetection.load(
271
+ faceLandmarksDetection.SupportedPackages.mediapipeFacemesh,
272
+ { maxFaces: 1 }
273
+ );
274
 
275
+ loadingIndicator.classList.add('hidden');
276
+ startCameraButton.classList.remove('hidden');
277
 
278
+ // Set up event listeners
279
+ setupEventListeners();
 
 
280
 
281
+ } catch (error) {
282
+ console.error('Error loading model:', error);
283
+ showError('Failed to load the detection model. Please try again.');
284
+ }
285
+ }
286
+
287
+ // Set up all event listeners
288
+ function setupEventListeners() {
289
+ // Camera controls
290
+ startCameraButton.addEventListener('click', startCamera);
291
+ retryButton.addEventListener('click', init);
292
+ takePhotoButton.addEventListener('click', takePhoto);
293
+
294
+ // Display toggles
295
+ toggleMeasurementsButton.addEventListener('click', () => {
296
+ showMeasurements = !showMeasurements;
297
+ toggleMeasurementsButton.classList.toggle('bg-purple-600');
298
+ toggleMeasurementsButton.classList.toggle('bg-gray-600');
299
  });
300
+
301
+ togglePostureButton.addEventListener('click', () => {
302
+ showPosture = !showPosture;
303
+ togglePostureButton.classList.toggle('bg-blue-600');
304
+ togglePostureButton.classList.toggle('bg-gray-600');
305
+ });
306
+
307
+ resetClothingButton.addEventListener('click', resetClothing);
308
+
309
+ // Clothing selection
310
+ document.querySelectorAll('[data-color]').forEach(el => {
311
+ el.addEventListener('click', () => {
312
+ document.querySelectorAll('[data-color]').forEach(e => e.classList.remove('border-indigo-500'));
313
+ el.classList.add('border-indigo-500');
314
+ selectedColor = el.getAttribute('data-color');
315
+ });
316
+ });
317
+
318
+ document.querySelectorAll('[data-pattern]').forEach(el => {
319
+ el.addEventListener('click', () => {
320
+ document.querySelectorAll('[data-pattern]').forEach(e => e.classList.remove('border-indigo-500'));
321
+ el.classList.add('border-indigo-500');
322
+ selectedPattern = el.getAttribute('data-pattern');
323
+ });
324
+ });
325
+
326
+ // Size adjustment
327
+ decreaseSizeButton.addEventListener('click', () => {
328
+ if (currentSize > 50) {
329
+ currentSize -= 5;
330
+ sizeValueSpan.textContent = `${currentSize}%`;
331
+ if (selectedClothingItem) {
332
+ resizeClothing(selectedClothingItem, currentSize);
333
+ }
334
+ }
335
+ });
336
+
337
+ increaseSizeButton.addEventListener('click', () => {
338
+ if (currentSize < 150) {
339
+ currentSize += 5;
340
+ sizeValueSpan.textContent = `${currentSize}%`;
341
+ if (selectedClothingItem) {
342
+ resizeClothing(selectedClothingItem, currentSize);
343
+ }
344
+ }
345
+ });
346
+
347
+ // Add clothing
348
+ addClothingButton.addEventListener('click', addClothingItem);
349
+
350
+ // Default selections
351
+ document.querySelector('[data-color="blue"]').classList.add('border-indigo-500');
352
+ document.querySelector('[data-pattern="solid"]').classList.add('border-indigo-500');
353
+ }
354
+
355
+ // Start the camera
356
+ async function startCamera() {
357
+ try {
358
+ const stream = await navigator.mediaDevices.getUserMedia({
359
+ video: { width: 640, height: 480, facingMode: 'user' },
360
+ audio: false
361
+ });
362
+
363
+ video.srcObject = stream;
364
+ video.classList.remove('hidden');
365
+ startCameraButton.classList.add('hidden');
366
+ takePhotoButton.classList.remove('hidden');
367
+ isCameraOn = true;
368
+
369
+ // Start detection loop
370
+ detect();
371
+
372
+ } catch (error) {
373
+ console.error('Error accessing camera:', error);
374
+ showError('Could not access the camera. Please ensure you have granted camera permissions.');
375
+ }
376
+ }
377
+
378
+ // Main detection loop
379
+ async function detect() {
380
+ if (!isCameraOn || !model) return;
381
+
382
+ try {
383
+ // Get face landmarks
384
+ const faces = await model.estimateFaces({
385
+ input: video,
386
+ returnTensors: false,
387
+ flipHorizontal: false,
388
+ predictIrises: true
389
+ });
390
+
391
+ // Clear canvas
392
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
393
+
394
+ // Draw video frame (mirrored)
395
+ ctx.save();
396
+ ctx.scale(-1, 1);
397
+ ctx.drawImage(video, 0, 0, canvas.width * -1, canvas.height);
398
+ ctx.restore();
399
+
400
+ if (faces.length > 0) {
401
+ const face = faces[0];
402
+
403
+ // Calculate measurements based on face landmarks
404
+ calculateMeasurements(face);
405
+
406
+ // Update posture analysis
407
+ analyzePosture(face);
408
+
409
+ // Update fit recommendations
410
+ updateFitRecommendations();
411
+ }
412
+
413
+ // Draw clothing items
414
+ drawClothingItems();
415
+
416
+ // Show measurements if enabled
417
+ if (showMeasurements) {
418
+ drawMeasurements();
419
+ }
420
+
421
+ // Show posture indicators if enabled
422
+ if (showPosture) {
423
+ drawPostureIndicators();
424
+ }
425
+
426
+ } catch (error) {
427
+ console.error('Error during detection:', error);
428
+ }
429
+
430
+ // Continue the loop
431
+ requestAnimationFrame(detect);
432
+ }
433
+
434
+ // Calculate body measurements based on face landmarks
435
+ function calculateMeasurements(face) {
436
+ // These are simplified calculations - in a real app you'd need more precise logic
437
+ const landmarks = face.scaledMesh;
438
+
439
+ // Estimate shoulder width (distance between ears * 2.5)
440
+ const leftEar = landmarks[234]; // Approximate left ear position
441
+ const rightEar = landmarks[454]; // Approximate right ear position
442
+ const earDistance = Math.sqrt(
443
+ Math.pow(rightEar[0] - leftEar[0], 2) +
444
+ Math.pow(rightEar[1] - leftEar[1], 2)
445
+ );
446
+
447
+ measurements.shoulderWidth = earDistance * 2.5;
448
+ measurements.chestWidth = earDistance * 2.8;
449
+ measurements.waistWidth = earDistance * 2.6;
450
+ measurements.hipWidth = earDistance * 2.9;
451
+
452
+ // Estimate torso length (chin to waist)
453
+ const chin = landmarks[152]; // Approximate chin position
454
+ const waistY = chin[1] + earDistance * 4;
455
+ measurements.torsoLength = waistY - chin[1];
456
+
457
+ // Update measurement display
458
+ shoulderWidthSpan.textContent = `${Math.round(measurements.shoulderWidth / PIXELS_PER_CM)} cm`;
459
+ chestWidthSpan.textContent = `${Math.round(measurements.chestWidth / PIXELS_PER_CM)} cm`;
460
+ waistWidthSpan.textContent = `${Math.round(measurements.waistWidth / PIXELS_PER_CM)} cm`;
461
+ hipWidthSpan.textContent = `${Math.round(measurements.hipWidth / PIXELS_PER_CM)} cm`;
462
+ torsoLengthSpan.textContent = `${Math.round(measurements.torsoLength / PIXELS_PER_CM)} cm`;
463
+ }
464
+
465
+ // Analyze posture based on face landmarks
466
+ function analyzePosture(face) {
467
+ const landmarks = face.scaledMesh;
468
+
469
+ // Get nose and chin positions
470
+ const noseTip = landmarks[1];
471
+ const chin = landmarks[152];
472
+
473
+ // Calculate angle from vertical
474
+ const dx = chin[0] - noseTip[0];
475
+ const dy = chin[1] - noseTip[1];
476
+ const angle = Math.atan2(dy, dx) * 180 / Math.PI;
477
+ const deviationFromVertical = Math.abs(90 - angle);
478
+
479
+ // Update posture feedback
480
+ if (deviationFromVertical > GOOD_POSTURE_THRESHOLD) {
481
+ postureFeedback.innerHTML = `
482
+ <p class="text-red-600 font-medium">Poor Posture Detected</p>
483
+ <p class="mt-1">Your head is tilted by ${Math.round(deviationFromVertical)}° from vertical.</p>
484
+ <p class="mt-1">Try to straighten your back and align your head with your spine.</p>
485
+ `;
486
+ } else {
487
+ postureFeedback.innerHTML = `
488
+ <p class="text-green-600 font-medium">Good Posture</p>
489
+ <p class="mt-1">Your head alignment looks good!</p>
490
+ `;
491
+ }
492
+
493
+ // Store posture data for drawing
494
+ postureData = {
495
+ noseTip,
496
+ chin,
497
+ deviation: deviationFromVertical
498
+ };
499
+ }
500
+
501
+ // Update fit recommendations based on measurements
502
+ function updateFitRecommendations() {
503
+ if (clothingItems.length === 0) return;
504
+
505
+ let recommendations = [];
506
+
507
+ clothingItems.forEach(item => {
508
+ // Simple fit check - in a real app this would be more sophisticated
509
+ const shoulderFit = item.width / measurements.shoulderWidth;
510
+ const lengthFit = item.height / measurements.torsoLength;
511
+
512
+ if (shoulderFit < 0.9 || lengthFit < 0.9) {
513
+ recommendations.push(`The ${item.type} might be too small. Consider sizing up.`);
514
+ } else if (shoulderFit > 1.1 || lengthFit > 1.1) {
515
+ recommendations.push(`The ${item.type} might be too large. Consider sizing down.`);
516
+ } else {
517
+ recommendations.push(`The ${item.type} appears to be a good fit!`);
518
+ }
519
+ });
520
+
521
+ fitRecommendation.innerHTML = recommendations.map(r => `<p class="mt-1">${r}</p>`).join('');
522
+ }
523
+
524
+ // Draw measurement lines on the canvas
525
+ function drawMeasurements() {
526
+ // Clear previous measurements
527
+ document.querySelectorAll('.measurement-line, .measurement-label').forEach(el => el.remove());
528
+
529
+ // Draw shoulder width
530
+ const shoulderY = canvas.height / 3;
531
+ const shoulderLine = document.createElement('div');
532
+ shoulderLine.className = 'measurement-line';
533
+ shoulderLine.style.width = `${measurements.shoulderWidth}px`;
534
+ shoulderLine.style.left = `${(canvas.width - measurements.shoulderWidth) / 2}px`;
535
+ shoulderLine.style.top = `${shoulderY}px`;
536
+ document.body.appendChild(shoulderLine);
537
+
538
+ const shoulderLabel = document.createElement('div');
539
+ shoulderLabel.className = 'measurement-label';
540
+ shoulderLabel.textContent = `Shoulder: ${Math.round(measurements.shoulderWidth / PIXELS_PER_CM)} cm`;
541
+ shoulderLabel.style.left = `${(canvas.width - measurements.shoulderWidth) / 2 + measurements.shoulderWidth / 2 - 50}px`;
542
+ shoulderLabel.style.top = `${shoulderY - 20}px`;
543
+ document.body.appendChild(shoulderLabel);
544
+
545
+ // Draw chest width
546
+ const chestY = shoulderY + measurements.torsoLength * 0.2;
547
+ const chestLine = document.createElement('div');
548
+ chestLine.className = 'measurement-line';
549
+ chestLine.style.width = `${measurements.chestWidth}px`;
550
+ chestLine.style.left = `${(canvas.width - measurements.chestWidth) / 2}px`;
551
+ chestLine.style.top = `${chestY}px`;
552
+ document.body.appendChild(chestLine);
553
+
554
+ const chestLabel = document.createElement('div');
555
+ chestLabel.className = 'measurement-label';
556
+ chestLabel.textContent = `Chest: ${Math.round(measurements.chestWidth / PIXELS_PER_CM)} cm`;
557
+ chestLabel.style.left = `${(canvas.width - measurements.chestWidth) / 2 + measurements.chestWidth / 2 - 50}px`;
558
+ chestLabel.style.top = `${chestY - 20}px`;
559
+ document.body.appendChild(chestLabel);
560
+
561
+ // Draw waist width
562
+ const waistY = shoulderY + measurements.torsoLength * 0.5;
563
+ const waistLine = document.createElement('div');
564
+ waistLine.className = 'measurement-line';
565
+ waistLine.style.width = `${measurements.waistWidth}px`;
566
+ waistLine.style.left = `${(canvas.width - measurements.waistWidth) / 2}px`;
567
+ waistLine.style.top = `${waistY}px`;
568
+ document.body.appendChild(waistLine);
569
+
570
+ const waistLabel = document.createElement('div');
571
+ waistLabel.className = 'measurement-label';
572
+ waistLabel.textContent = `Waist: ${Math.round(measurements.waistWidth / PIXELS_PER_CM)} cm`;
573
+ waistLabel.style.left = `${(canvas.width - measurements.waistWidth) / 2 + measurements.waistWidth / 2 - 50}px`;
574
+ waistLabel.style.top = `${waistY - 20}px`;
575
+ document.body.appendChild(waistLabel);
576
+
577
+ // Draw hip width
578
+ const hipY = shoulderY + measurements.torsoLength * 0.8;
579
+ const hipLine = document.createElement('div');
580
+ hipLine.className = 'measurement-line';
581
+ hipLine.style.width = `${measurements.hipWidth}px`;
582
+ hipLine.style.left = `${(canvas.width - measurements.hipWidth) / 2}px`;
583
+ hipLine.style.top = `${hipY}px`;
584
+ document.body.appendChild(hipLine);
585
+
586
+ const hipLabel = document.createElement('div');
587
+ hipLabel.className = 'measurement-label';
588
+ hipLabel.textContent = `Hip: ${Math.round(measurements.hipWidth / PIXELS_PER_CM)} cm`;
589
+ hipLabel.style.left = `${(canvas.width - measurements.hipWidth) / 2 + measurements.hipWidth / 2 - 50}px`;
590
+ hipLabel.style.top = `${hipY - 20}px`;
591
+ document.body.appendChild(hipLabel);
592
+
593
+ // Draw torso length
594
+ const torsoLine = document.createElement('div');
595
+ torsoLine.className = 'measurement-line';
596
+ torsoLine.style.width = `${measurements.torsoLength}px`;
597
+ torsoLine.style.left = `${canvas.width / 2}px`;
598
+ torsoLine.style.top = `${shoulderY}px`;
599
+ torsoLine.style.transform = `rotate(90deg)`;
600
+ document.body.appendChild(torsoLine);
601
+
602
+ const torsoLabel = document.createElement('div');
603
+ torsoLabel.className = 'measurement-label';
604
+ torsoLabel.textContent = `Torso: ${Math.round(measurements.torsoLength / PIXELS_PER_CM)} cm`;
605
+ torsoLabel.style.left = `${canvas.width / 2 + 20}px`;
606
+ torsoLabel.style.top = `${shoulderY + measurements.torsoLength / 2}px`;
607
+ document.body.appendChild(torsoLabel);
608
+ }
609
+
610
+ // Draw posture indicators
611
+ function drawPostureIndicators() {
612
+ // Clear previous indicators
613
+ document.querySelectorAll('.posture-indicator').forEach(el => el.remove());
614
+
615
+ if (!postureData) return;
616
+
617
+ // Draw head position indicator
618
+ const headIndicator = document.createElement('div');
619
+ headIndicator.className = `posture-indicator ${postureData.deviation > GOOD_POSTURE_THRESHOLD ? 'bad' : ''}`;
620
+ headIndicator.style.left = `${postureData.noseTip[0]}px`;
621
+ headIndicator.style.top = `${postureData.noseTip[1]}px`;
622
+ document.body.appendChild(headIndicator);
623
+
624
+ // Draw chin position indicator
625
+ const chinIndicator = document.createElement('div');
626
+ chinIndicator.className = `posture-indicator ${postureData.deviation > GOOD_POSTURE_THRESHOLD ? 'bad' : ''}`;
627
+ chinIndicator.style.left = `${postureData.chin[0]}px`;
628
+ chinIndicator.style.top = `${postureData.chin[1]}px`;
629
+ document.body.appendChild(chinIndicator);
630
+ }
631
 
632
+ // Add a new clothing item
633
+ function addClothingItem() {
634
+ const type = clothingTypeSelect.value;
635
+ const baseWidth = measurements.shoulderWidth * 1.2;
636
+ const baseHeight = measurements.torsoLength * 1.1;
637
+
638
+ // Adjust dimensions based on clothing type
639
+ let width, height;
640
+ switch (type) {
641
+ case 't-shirt':
642
+ case 'shirt':
643
+ width = baseWidth;
644
+ height = baseHeight * 0.8;
645
+ break;
646
+ case 'dress':
647
+ width = baseWidth * 0.9;
648
+ height = baseHeight * 1.5;
649
+ break;
650
+ case 'pants':
651
+ width = baseWidth * 0.8;
652
+ height = baseHeight * 0.9;
653
+ break;
654
+ case 'jacket':
655
+ width = baseWidth * 1.1;
656
+ height = baseHeight * 0.9;
657
+ break;
658
+ default:
659
+ width = baseWidth;
660
+ height = baseHeight;
661
+ }
662
+
663
+ const clothingItem = {
664
+ id: Date.now(),
665
+ type,
666
+ color: selectedColor,
667
+ pattern: selectedPattern,
668
+ x: (canvas.width - width) / 2,
669
+ y: canvas.height / 3 - height * 0.2,
670
+ width,
671
+ height,
672
+ originalWidth: width,
673
+ originalHeight: height,
674
+ size: 100
675
+ };
676
+
677
+ clothingItems.push(clothingItem);
678
+ selectClothingItem(clothingItem);
679
+
680
+ // Update fit recommendations
681
+ updateFitRecommendations();
682
+ }
683
+
684
+ // Draw all clothing items
685
+ function drawClothingItems() {
686
+ // Clear previous clothing items
687
+ document.querySelectorAll('.clothing-item').forEach(el => el.remove());
688
+
689
+ clothingItems.forEach(item => {
690
+ const clothingElement = document.createElement('div');
691
+ clothingElement.className = 'clothing-item';
692
+ clothingElement.dataset.id = item.id;
693
 
694
+ // Set position and size
695
+ clothingElement.style.left = `${item.x}px`;
696
+ clothingElement.style.top = `${item.y}px`;
697
+ clothingElement.style.width = `${item.width}px`;
698
+ clothingElement.style.height = `${item.height}px`;
699
+
700
+ // Set appearance based on color and pattern
701
+ let bgStyle = '';
702
+ if (item.pattern === 'solid') {
703
+ bgStyle = `background-color: ${getColorValue(item.color)};`;
704
+ } else if (item.pattern === 'checkered') {
705
+ bgStyle = `background-image: linear-gradient(45deg, #999 25%, transparent 25%, transparent 75%, #999 75%, #999),
706
+ linear-gradient(45deg, #999 25%, transparent 25%, transparent 75%, #999 75%, #999);
707
+ background-size: 10px 10px;
708
+ background-color: ${getColorValue(item.color)};`;
709
+ } else if (item.pattern === 'polka') {
710
+ bgStyle = `background-image: radial-gradient(circle, #999 1px, transparent 1px);
711
+ background-size: 10px 10px;
712
+ background-color: ${getColorValue(item.color)};`;
713
+ } else if (item.pattern === 'striped') {
714
+ bgStyle = `background-image: linear-gradient(0deg, #999, #999 50%, transparent 50%, transparent 100%);
715
+ background-size: 10px 10px;
716
+ background-color: ${getColorValue(item.color)};`;
717
+ }
718
+
719
+ clothingElement.style.cssText += bgStyle;
720
+
721
+ // Add selection class if this is the selected item
722
+ if (selectedClothingItem && selectedClothingItem.id === item.id) {
723
+ clothingElement.classList.add('selected');
724
  }
725
 
726
+ // Add event listeners for selection and dragging
727
+ clothingElement.addEventListener('mousedown', (e) => {
728
+ selectClothingItem(item);
729
+
730
+ // Prepare for dragging
731
+ isDragging = true;
732
+ dragOffsetX = e.clientX - item.x;
733
+ dragOffsetY = e.clientY - item.y;
734
+ });
735
+
736
+ document.body.appendChild(clothingElement);
737
  });
738
+ }
739
+
740
+ // Handle mouse move for dragging clothing items
741
+ document.addEventListener('mousemove', (e) => {
742
+ if (isDragging && selectedClothingItem) {
743
+ selectedClothingItem.x = e.clientX - dragOffsetX;
744
+ selectedClothingItem.y = e.clientY - dragOffsetY;
745
+
746
+ // Constrain to canvas
747
+ selectedClothingItem.x = Math.max(0, Math.min(canvas.width - selectedClothingItem.width, selectedClothingItem.x));
748
+ selectedClothingItem.y = Math.max(0, Math.min(canvas.height - selectedClothingItem.height, selectedClothingItem.y));
749
+ }
750
  });
751
+
752
+ // Handle mouse up to stop dragging
753
+ document.addEventListener('mouseup', () => {
754
+ isDragging = false;
 
 
 
 
 
 
 
 
 
 
 
 
755
  });
756
+
757
+ // Select a clothing item
758
+ function selectClothingItem(item) {
759
+ selectedClothingItem = item;
760
+ currentSize = item.size;
761
+ sizeValueSpan.textContent = `${currentSize}%`;
762
+
763
+ // Update UI to reflect selected item
764
+ drawClothingItems();
765
+ }
766
+
767
+ // Resize a clothing item
768
+ function resizeClothing(item, newSize) {
769
+ const scaleFactor = newSize / 100;
770
+ item.width = item.originalWidth * scaleFactor;
771
+ item.height = item.originalHeight * scaleFactor;
772
+ item.size = newSize;
773
+
774
+ // Keep the center position
775
+ const centerX = item.x + item.width / 2;
776
+ const centerY = item.y + item.height / 2;
777
+
778
+ item.x = centerX - item.width / 2;
779
+ item.y = centerY - item.height / 2;
780
+ }
781
+
782
+ // Reset all clothing items
783
+ function resetClothing() {
784
+ clothingItems = [];
785
+ selectedClothingItem = null;
786
+ drawClothingItems();
787
+ fitRecommendation.innerHTML = '<p>Add clothing to see fit recommendations based on your measurements.</p>';
788
+ }
789
+
790
+ // Take a photo of the current view
791
+ function takePhoto() {
792
+ // Create a temporary canvas with the current view
793
+ const tempCanvas = document.createElement('canvas');
794
+ tempCanvas.width = canvas.width;
795
+ tempCanvas.height = canvas.height;
796
+ const tempCtx = tempCanvas.getContext('2d');
797
+
798
+ // Draw the current frame
799
+ tempCtx.save();
800
+ tempCtx.scale(-1, 1);
801
+ tempCtx.drawImage(video, 0, 0, canvas.width * -1, canvas.height);
802
+ tempCtx.restore();
803
+
804
+ // Draw clothing items
805
+ clothingItems.forEach(item => {
806
+ tempCtx.fillStyle = getColorValue(item.color);
807
+ tempCtx.fillRect(item.x, item.y, item.width, item.height);
808
+ });
809
+
810
+ // Convert to data URL and download
811
+ const dataUrl = tempCanvas.toDataURL('image/png');
812
+ const link = document.createElement('a');
813
+ link.download = 'virtual-fitting-room.png';
814
+ link.href = dataUrl;
815
+ link.click();
816
+ }
817
+
818
+ // Helper function to get color value
819
+ function getColorValue(colorName) {
820
+ const colors = {
821
+ 'red': '#ef4444',
822
+ 'blue': '#3b82f6',
823
+ 'green': '#10b981',
824
+ 'black': '#000000',
825
+ 'white': '#ffffff',
826
+ 'yellow': '#f59e0b'
827
+ };
828
+ return colors[colorName] || '#3b82f6';
829
+ }
830
+
831
+ // Show error message
832
+ function showError(message) {
833
+ errorText.textContent = message;
834
+ errorMessage.classList.remove('hidden');
835
+ loadingIndicator.classList.add('hidden');
836
+ }
837
+
838
+ // Initialize the app when the page loads
839
+ window.addEventListener('DOMContentLoaded', init);
840
  </script>
841
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=viswanani/clone-app" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
842
  </html>