Coots commited on
Commit
f4054a2
·
verified ·
1 Parent(s): 5d5165f

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +145 -114
index.html CHANGED
@@ -1,125 +1,156 @@
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>Tile Calculator AI</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <style>
9
- /* Your existing styles… */
10
- </style>
11
- </head>
12
- <body class="bg-gray-100">
13
- <!-- (Header + Chat Area + Input Area omitted for brevity) -->
14
- <div id="chat-area" class="chat-container p-4 overflow-y-auto">
15
- <div class="bot-message bg-gray-100 rounded-lg p-4 max-w-xs mb-3">
16
- <p>Hello! 👋 Floor or wall tiles?</p>
17
- <button onclick="selectTileType('floor')" class="quick-reply">Floor</button>
18
- <button onclick="selectTileType('wall')" class="quick-reply">Wall</button>
19
- </div>
20
- </div>
21
- <!-- Recommendations Section -->
22
- <div id="recommendations" class="grid grid-cols-2 md:grid-cols-4 gap-4 p-4 border-t bg-gray-50"></div>
23
-
24
- <script>
25
- const state = { step: 'tileType', tileType: null, length: null, width: null };
26
- const chatArea = document.getElementById('chat-area'),
27
- userInput = null, /* we won't use user text input here for simplicity */,
28
- recommendations = document.getElementById('recommendations');
29
-
30
- function selectTileType(type){
31
- state.tileType = type;
32
- state.step = 'length';
33
- appendBot(`Great. What's the length of the area in ft?`);
34
- }
35
 
36
- function appendBot(text) {
37
- chatArea.insertAdjacentHTML('beforeend', `
38
- <div class="bot-message bg-gray-100 rounded-lg p-4 mb-3">${text}</div>
39
- `);
40
- chatArea.scrollTop = chatArea.scrollHeight;
41
- }
42
 
43
- function appendUser(text) {
44
- chatArea.insertAdjacentHTML('beforeend', `
45
- <div class="user-message ml-auto bg-indigo-600 text-white rounded-lg p-4 mb-3">${text}</div>
46
- `);
47
- chatArea.scrollTop = chatArea.scrollHeight;
48
- }
49
 
50
- function askValue(val){
51
- const answer = prompt(val);
52
- if (!answer) return appendBot('Input canceled.');
53
- appendUser(answer);
54
- processValue(parseFloat(answer));
55
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
- function processValue(num){
58
- if (state.step === 'length'){
59
- state.length = num;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  state.step = 'width';
61
- appendBot("And the width (ft)?");
62
- askValue("Width in ft:");
63
- } else if (state.step === 'width'){
64
- state.width = num;
65
- calculate();
66
- }
67
- }
68
 
69
- function calculate(){
70
- const area = state.length * state.width;
71
- const coverage = 1; // tile covers 1 sq ft default
72
- const numTiles = Math.ceil(area * 1.1 / coverage);
73
- appendBot(`📐 Area: ${area.toFixed(2)} ft²<br>🧮 Tiles needed (incl. 10%): ${numTiles}`);
74
- fetchRecommendations(coverage, area);
75
- }
 
 
76
 
77
- function fetchRecommendations(coverage, area){
78
- fetch('/recommend', {
79
- method: 'POST',
80
- headers:{'Content-Type':'application/json'},
81
- body: JSON.stringify({
82
- tile_type: state.tileType,
83
- coverage,
84
- area,
85
- price_range: [3,10]
86
- })
87
- })
88
- .then(r=>r.json())
89
- .then(d=> {
90
- if (d.recommended_products?.length){
91
- showProducts(d.recommended_products);
92
- } else {
93
- appendBot("No recommendations found for your specs.");
94
  }
95
- });
96
- }
97
 
98
- function showProducts(products){
99
- recommendations.innerHTML = '';
100
- products.forEach(p => {
101
- recommendations.insertAdjacentHTML('beforeend', `
102
- <div class="bg-white shadow rounded-lg p-4">
103
- <h4 class="font-medium">${p.name}</h4>
104
- <p class="text-sm">₹${p.price}/box</p>
105
- <a href="${p.link}" target="_blank" class="text-indigo-600 hover:underline">View</a>
106
- </div>
107
- `);
108
- });
 
 
 
 
109
  }
 
 
110
 
111
- // start logic: after selecting tile type, ask length
112
- document.addEventListener('DOMContentLoaded', ()=> {
113
- if(state.step!=='tileType') return;
114
- document.querySelectorAll('.quick-reply').forEach(btn=>{
115
- btn.onclick = ()=> {
116
- const type = btn.getAttribute('onclick').match(/'(\w+)'/)[1];
117
- appendUser(type);
118
- selectTileType(type);
119
- askValue("Length in ft:");
120
- }
121
- });
122
- });
123
- </script>
124
- </body>
125
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script>
2
+ const state = {
3
+ step: 'tileType',
4
+ tileType: null,
5
+ length: null,
6
+ width: null,
7
+ tileSize: null
8
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ const chatArea = document.getElementById('chat-area');
11
+ const userInput = document.getElementById('user-input');
12
+ const recommendations = document.getElementById('recommendations');
13
+ const resetBtn = document.getElementById('reset-btn');
 
 
14
 
15
+ resetBtn.addEventListener('click', resetConversation);
16
+ userInput.addEventListener('keypress', (e) => {
17
+ if (e.key === 'Enter') sendMessage();
18
+ });
 
 
19
 
20
+ function resetConversation() {
21
+ state.step = 'tileType';
22
+ state.tileType = null;
23
+ state.length = null;
24
+ state.width = null;
25
+ state.tileSize = null;
26
+
27
+ chatArea.innerHTML = `
28
+ <div class="bot-message bg-gray-100 rounded-lg p-4 max-w-xs mb-3">
29
+ <p>Hello! 👋 I'm your Tile Calculator Assistant. Let's estimate how many tiles you need.</p>
30
+ <p class="mt-2">Are you looking for <span class="font-semibold">floor</span> or <span class="font-semibold">wall</span> tiles?</p>
31
+ <div class="flex gap-2 mt-3">
32
+ <button onclick="selectTileType('floor')" class="quick-reply bg-white text-indigo-600 border border-indigo-600 px-4 py-2 rounded-full font-medium hover:bg-indigo-50">Floor</button>
33
+ <button onclick="selectTileType('wall')" class="quick-reply bg-white text-indigo-600 border border-indigo-600 px-4 py-2 rounded-full font-medium hover:bg-indigo-50">Wall</button>
34
+ </div>
35
+ </div>
36
+ `;
37
+ recommendations.innerHTML = '';
38
+ }
39
+
40
+ function selectTileType(type) {
41
+ state.tileType = type;
42
+ state.step = 'length';
43
+
44
+ addMessage('user', type === 'floor' ? 'Floor tiles' : 'Wall tiles');
45
+ showTyping();
46
 
47
+ setTimeout(() => {
48
+ hideTyping();
49
+ addMessage('bot', `Great choice! Please enter the <strong>length</strong> of the area in feet (e.g. 10):`);
50
+ }, 800);
51
+ }
52
+
53
+ function sendMessage() {
54
+ const message = userInput.value.trim();
55
+ if (!message) return;
56
+
57
+ addMessage('user', message);
58
+ userInput.value = '';
59
+
60
+ processUserMessage(message);
61
+ }
62
+
63
+ function processUserMessage(message) {
64
+ showTyping();
65
+
66
+ setTimeout(() => {
67
+ hideTyping();
68
+
69
+ if (state.step === 'length') {
70
+ const length = parseFloat(message);
71
+ if (isNaN(length) || length <= 0) {
72
+ addMessage('bot', 'Please enter a valid number for the length in feet.');
73
+ return;
74
+ }
75
+ state.length = length;
76
  state.step = 'width';
77
+ addMessage('bot', 'Now enter the <strong>width</strong> of the area in feet (e.g. 12):');
 
 
 
 
 
 
78
 
79
+ } else if (state.step === 'width') {
80
+ const width = parseFloat(message);
81
+ if (isNaN(width) || width <= 0) {
82
+ addMessage('bot', 'Please enter a valid number for the width in feet.');
83
+ return;
84
+ }
85
+ state.width = width;
86
+ state.step = 'tileSize';
87
+ addMessage('bot', 'What is the tile size? (e.g. "2x2", "600x600", or "300*300")');
88
 
89
+ } else if (state.step === 'tileSize') {
90
+ const tileArea = parseTileSize(message);
91
+ if (!tileArea) {
92
+ addMessage('bot', 'I couldn\'t understand that tile size. Try: "2x2", "600x600 mm", or "200*200".');
93
+ return;
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
 
 
95
 
96
+ state.tileSize = tileArea;
97
+ calculateTiles();
98
+ }
99
+ }, 800);
100
+ }
101
+
102
+ function parseTileSize(input) {
103
+ input = input.toLowerCase().replace(/×|into|\*/g, 'x').replace(/ft|feet|mm/g, '').trim();
104
+ if (input.includes('x')) {
105
+ const [a, b] = input.split('x').map(s => parseFloat(s.replace(/[^\d.]/g, '')));
106
+ if (isNaN(a) || isNaN(b)) return null;
107
+ return (a > 20 ? (a * b) / 92903.04 : a * b);
108
+ } else if (/^\d+(\.\d+)?$/.test(input)) {
109
+ const val = parseFloat(input);
110
+ return val > 20 ? (val * val) / 92903.04 : val * val;
111
  }
112
+ return null;
113
+ }
114
 
115
+ function calculateTiles() {
116
+ const area = state.length * state.width;
117
+ const numTiles = Math.ceil((area / state.tileSize) * 1.1);
118
+ const numBoxes = Math.ceil(numTiles / 10);
119
+
120
+ chatArea.insertAdjacentHTML('beforeend', `
121
+ <div class="bot-message bg-gray-100 rounded-lg p-4 mb-3">
122
+ <p class="font-semibold">Calculation Results:</p>
123
+ <p>🧱 Tile Type: ${state.tileType}</p>
124
+ <p>📏 Length: ${state.length} ft</p>
125
+ <p>📐 Width: ${state.width} ft</p>
126
+ <p>📦 Area: ${area.toFixed(2)} sq.ft</p>
127
+ <p>🧮 Tile Size: ${state.tileSize.toFixed(2)} sq.ft per tile</p>
128
+ <p class="mt-2">🔢 <span class="font-bold">Tiles Needed:</span> ${numTiles} (${numBoxes} boxes)</p>
129
+ </div>
130
+ `);
131
+
132
+ state.step = 'complete';
133
+ }
134
+
135
+ function addMessage(sender, message) {
136
+ const messageDiv = document.createElement('div');
137
+ messageDiv.className = `${sender}-message ${sender === 'user' ? 'ml-auto bg-indigo-600 text-white' : 'bg-gray-100'} rounded-lg p-4 max-w-xs mb-3`;
138
+ messageDiv.innerHTML = message;
139
+ chatArea.appendChild(messageDiv);
140
+ chatArea.scrollTop = chatArea.scrollHeight;
141
+ }
142
+
143
+ function showTyping() {
144
+ const typingDiv = document.createElement('div');
145
+ typingDiv.className = 'typing-indicator bg-gray-100 rounded-lg p-4 max-w-xs mb-3 flex gap-1';
146
+ typingDiv.id = 'typing-indicator';
147
+ typingDiv.innerHTML = '<span class="w-2 h-2 bg-gray-400 rounded-full"></span><span class="w-2 h-2 bg-gray-400 rounded-full"></span><span class="w-2 h-2 bg-gray-400 rounded-full"></span>';
148
+ chatArea.appendChild(typingDiv);
149
+ chatArea.scrollTop = chatArea.scrollHeight;
150
+ }
151
+
152
+ function hideTyping() {
153
+ const typingIndicator = document.getElementById('typing-indicator');
154
+ if (typingIndicator) typingIndicator.remove();
155
+ }
156
+ </script>