anuragshas commited on
Commit
14ee8e9
·
1 Parent(s): a40e4c4

fix: ui improvements

Browse files
Files changed (4) hide show
  1. data-manager.js +13 -2
  2. index.html +124 -80
  3. script.js +38 -27
  4. style.css +0 -166
data-manager.js CHANGED
@@ -338,9 +338,10 @@ class QuotationDataManager {
338
  const storageInfoPanel = document.getElementById("storage-info-panel");
339
 
340
  if (showStorageInfoButton && storageInfoPanel) {
341
- showStorageInfoButton.addEventListener("click", () => {
 
342
  this.updateStorageStatus();
343
- storageInfoPanel.classList.remove("hidden");
344
  });
345
  }
346
 
@@ -349,6 +350,16 @@ class QuotationDataManager {
349
  storageInfoPanel.classList.add("hidden");
350
  });
351
  }
 
 
 
 
 
 
 
 
 
 
352
  }
353
 
354
  // Update storage status display
 
338
  const storageInfoPanel = document.getElementById("storage-info-panel");
339
 
340
  if (showStorageInfoButton && storageInfoPanel) {
341
+ showStorageInfoButton.addEventListener("click", (e) => {
342
+ e.stopPropagation();
343
  this.updateStorageStatus();
344
+ storageInfoPanel.classList.toggle("hidden");
345
  });
346
  }
347
 
 
350
  storageInfoPanel.classList.add("hidden");
351
  });
352
  }
353
+
354
+ // Hide popover when clicking outside
355
+ document.addEventListener("click", (e) => {
356
+ if (
357
+ !storageInfoPanel.contains(e.target) &&
358
+ e.target !== showStorageInfoButton
359
+ ) {
360
+ storageInfoPanel.classList.add("hidden");
361
+ }
362
+ });
363
  }
364
 
365
  // Update storage status display
index.html CHANGED
@@ -11,14 +11,14 @@
11
  <h1 class="text-3xl font-bold text-center my-8" id="top-header">
12
  Quotation Generator
13
  </h1>
14
- <div class="flex container mx-auto">
15
- <div id="form-container" class="w-1/2 pr-4">
16
  <form
17
  id="quotation-form"
18
  class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
19
  >
20
- <fieldset class="border border-gray-300 p-4 mb-4">
21
- <legend class="text-lg font-semibold mb-2">
22
  Your Company Details
23
  </legend>
24
  <input
@@ -27,39 +27,39 @@
27
  name="company-name"
28
  placeholder="Company Name"
29
  required
30
- class="w-full p-2 border border-gray-300 rounded mb-2"
31
  />
32
  <textarea
33
  id="company-address"
34
  name="company-address"
35
  placeholder="Address"
36
  required
37
- class="w-full p-2 border border-gray-300 rounded mb-2"
38
  ></textarea>
39
  <input
40
  type="text"
41
  id="company-phone"
42
  name="company-phone"
43
  placeholder="Phone"
44
- class="w-full p-2 border border-gray-300 rounded mb-2"
45
  />
46
  <input
47
  type="email"
48
  id="company-email"
49
  name="company-email"
50
  placeholder="Email"
51
- class="w-full p-2 border border-gray-300 rounded mb-2"
52
  />
53
  <input
54
  type="text"
55
  id="company-gstin"
56
  name="company-gstin"
57
  placeholder="GSTIN"
58
- class="w-full p-2 border border-gray-300 rounded"
59
  />
60
  </fieldset>
61
- <fieldset class="border border-gray-300 p-4 mb-4">
62
- <legend class="text-lg font-semibold mb-2">
63
  Customer Company Details
64
  </legend>
65
  <input
@@ -68,39 +68,39 @@
68
  name="customer-name"
69
  placeholder="Customer Name"
70
  required
71
- class="w-full p-2 border border-gray-300 rounded mb-2"
72
  />
73
  <textarea
74
  id="customer-address"
75
  name="customer-address"
76
  placeholder="Address"
77
  required
78
- class="w-full p-2 border border-gray-300 rounded mb-2"
79
  ></textarea>
80
  <input
81
  type="text"
82
  id="customer-phone"
83
  name="customer-phone"
84
  placeholder="Phone"
85
- class="w-full p-2 border border-gray-300 rounded mb-2"
86
  />
87
  <input
88
  type="email"
89
  id="customer-email"
90
  name="customer-email"
91
  placeholder="Email"
92
- class="w-full p-2 border border-gray-300 rounded mb-2"
93
  />
94
  <input
95
  type="text"
96
  id="customer-gstin"
97
  name="customer-gstin"
98
  placeholder="GSTIN"
99
- class="w-full p-2 border border-gray-300 rounded"
100
  />
101
  </fieldset>
102
- <fieldset class="border border-gray-300 p-4 mb-4">
103
- <legend class="text-lg font-semibold mb-2">
104
  Quotation Details
105
  </legend>
106
  <input
@@ -109,18 +109,18 @@
109
  name="quotation-number"
110
  placeholder="Quotation Number"
111
  required
112
- class="w-full p-2 border border-gray-300 rounded mb-2"
113
  />
114
  <input
115
  type="date"
116
  id="quotation-date"
117
  name="quotation-date"
118
  required
119
- class="w-full p-2 border border-gray-300 rounded"
120
  />
121
  </fieldset>
122
- <fieldset class="border border-gray-300 p-4 mb-4">
123
- <legend class="text-lg font-semibold mb-2">
124
  Items
125
  </legend>
126
  <div
@@ -152,47 +152,73 @@
152
  </li>
153
  </ul>
154
  </div>
155
- <table id="items-table" class="w-full mb-2">
156
- <thead>
157
- <tr class="bg-gray-200">
158
- <th class="p-2 border border-gray-300">
159
- S.No
160
- </th>
161
- <th class="p-2 border border-gray-300">
162
- Description *
163
- </th>
164
- <th class="p-2 border border-gray-300">
165
- HSN Code
166
- </th>
167
- <th class="p-2 border border-gray-300">
168
- Qty *
169
- </th>
170
- <th class="p-2 border border-gray-300">
171
- Unit Price *
172
- </th>
173
- <th class="p-2 border border-gray-300">
174
- Discount (%)
175
- </th>
176
- <th class="p-2 border border-gray-300">
177
- Amount
178
- </th>
179
- <th class="p-2 border border-gray-300">
180
- Action
181
- </th>
182
- </tr>
183
- </thead>
184
- <tbody></tbody>
185
- </table>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  <button
187
  type="button"
188
  id="add-item"
189
- class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
190
  >
 
 
 
191
  Add Another Item
192
  </button>
193
  </fieldset>
194
- <fieldset class="border border-gray-300 p-4 mb-4">
195
- <legend class="text-lg font-semibold mb-2">
196
  Additional Charges
197
  </legend>
198
  <label class="block mb-2"
@@ -202,7 +228,7 @@
202
  name="igst-rate"
203
  value="0"
204
  min="0"
205
- class="w-full p-2 border border-gray-300 rounded"
206
  /></label>
207
  <label class="block"
208
  >Freight Charges<input
@@ -211,11 +237,11 @@
211
  name="freight-charges"
212
  value="0"
213
  min="0"
214
- class="w-full p-2 border border-gray-300 rounded"
215
  /></label>
216
  </fieldset>
217
- <fieldset class="border border-gray-300 p-4 mb-4">
218
- <legend class="text-lg font-semibold mb-2">
219
  Bank Details
220
  </legend>
221
  <input
@@ -224,7 +250,7 @@
224
  name="bank-name"
225
  placeholder="Bank Name"
226
  required
227
- class="w-full p-2 border border-gray-300 rounded mb-2"
228
  />
229
  <input
230
  type="text"
@@ -232,7 +258,7 @@
232
  name="bank-account"
233
  placeholder="Account Number"
234
  required
235
- class="w-full p-2 border border-gray-300 rounded mb-2"
236
  />
237
  <input
238
  type="text"
@@ -240,7 +266,7 @@
240
  name="bank-ifsc"
241
  placeholder="IFSC Code"
242
  required
243
- class="w-full p-2 border border-gray-300 rounded mb-2"
244
  />
245
  <input
246
  type="text"
@@ -248,13 +274,13 @@
248
  name="bank-branch"
249
  placeholder="Branch"
250
  required
251
- class="w-full p-2 border border-gray-300 rounded"
252
  />
253
  </fieldset>
254
  <div class="flex justify-between items-center">
255
  <button
256
  type="submit"
257
- class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded"
258
  >
259
  Generate Quotation
260
  </button>
@@ -262,14 +288,14 @@
262
  <button
263
  type="button"
264
  id="clear-data"
265
- class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded"
266
  >
267
  Clear Saved Data
268
  </button>
269
  <button
270
  type="button"
271
  id="show-storage-info"
272
- class="bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded"
273
  >
274
  Storage Info
275
  </button>
@@ -277,7 +303,7 @@
277
  </div>
278
  </form>
279
  </div>
280
- <div id="preview-container" class="w-1/2 pl-4">
281
  <div
282
  id="quotation-preview"
283
  class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
@@ -291,13 +317,17 @@
291
  <!-- Storage Information Panel -->
292
  <div
293
  id="storage-info-panel"
294
- class="bg-white shadow-md rounded px-6 pt-4 pb-6 mb-4 hidden"
 
295
  >
296
- <h3 class="text-lg font-bold mb-3">
297
- 💾 Storage Information
 
 
 
298
  </h3>
299
  <div class="text-sm space-y-2">
300
- <div class="bg-blue-50 p-3 rounded">
301
  <h4 class="font-semibold text-blue-800">
302
  Company Details
303
  </h4>
@@ -308,7 +338,7 @@
308
  Not saved
309
  </p>
310
  </div>
311
- <div class="bg-green-50 p-3 rounded">
312
  <h4 class="font-semibold text-green-800">
313
  Bank Details
314
  </h4>
@@ -316,7 +346,7 @@
316
  Not saved
317
  </p>
318
  </div>
319
- <div class="bg-yellow-50 p-3 rounded">
320
  <h4 class="font-semibold text-yellow-800">
321
  Customer Details
322
  </h4>
@@ -327,11 +357,14 @@
327
  Not saved (Session only)
328
  </p>
329
  </div>
330
- <div class="bg-gray-50 p-3 rounded mt-3">
331
- <h4 class="font-semibold text-gray-800">
332
- ⚠️ Security Notice
 
 
 
333
  </h4>
334
- <p class="text-gray-600 text-xs">
335
  Data is stored in your browser's localStorage.
336
  For maximum security:
337
  <br />• Use private/incognito browsing <br />•
@@ -349,12 +382,23 @@
349
  </div>
350
  </div>
351
  </div>
352
- <div id="quotation-output" style="display: none"></div>
 
 
 
 
 
 
 
 
 
 
 
353
 
354
  <!-- Data Management Status Modal -->
355
  <div
356
  id="status-modal"
357
- class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center"
358
  >
359
  <div class="bg-white p-6 rounded-lg shadow-lg max-w-sm mx-auto">
360
  <div id="modal-content" class="text-center">
 
11
  <h1 class="text-3xl font-bold text-center my-8" id="top-header">
12
  Quotation Generator
13
  </h1>
14
+ <div class="flex flex-col lg:flex-row container mx-auto gap-4">
15
+ <div id="form-container" class="w-full lg:w-1/2">
16
  <form
17
  id="quotation-form"
18
  class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
19
  >
20
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
21
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
22
  Your Company Details
23
  </legend>
24
  <input
 
27
  name="company-name"
28
  placeholder="Company Name"
29
  required
30
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
31
  />
32
  <textarea
33
  id="company-address"
34
  name="company-address"
35
  placeholder="Address"
36
  required
37
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
38
  ></textarea>
39
  <input
40
  type="text"
41
  id="company-phone"
42
  name="company-phone"
43
  placeholder="Phone"
44
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
45
  />
46
  <input
47
  type="email"
48
  id="company-email"
49
  name="company-email"
50
  placeholder="Email"
51
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
52
  />
53
  <input
54
  type="text"
55
  id="company-gstin"
56
  name="company-gstin"
57
  placeholder="GSTIN"
58
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
59
  />
60
  </fieldset>
61
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
62
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
63
  Customer Company Details
64
  </legend>
65
  <input
 
68
  name="customer-name"
69
  placeholder="Customer Name"
70
  required
71
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
72
  />
73
  <textarea
74
  id="customer-address"
75
  name="customer-address"
76
  placeholder="Address"
77
  required
78
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
79
  ></textarea>
80
  <input
81
  type="text"
82
  id="customer-phone"
83
  name="customer-phone"
84
  placeholder="Phone"
85
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
86
  />
87
  <input
88
  type="email"
89
  id="customer-email"
90
  name="customer-email"
91
  placeholder="Email"
92
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
93
  />
94
  <input
95
  type="text"
96
  id="customer-gstin"
97
  name="customer-gstin"
98
  placeholder="GSTIN"
99
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
100
  />
101
  </fieldset>
102
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
103
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
104
  Quotation Details
105
  </legend>
106
  <input
 
109
  name="quotation-number"
110
  placeholder="Quotation Number"
111
  required
112
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
113
  />
114
  <input
115
  type="date"
116
  id="quotation-date"
117
  name="quotation-date"
118
  required
119
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
120
  />
121
  </fieldset>
122
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
123
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
124
  Items
125
  </legend>
126
  <div
 
152
  </li>
153
  </ul>
154
  </div>
155
+ <div class="overflow-x-auto">
156
+ <table
157
+ id="items-table"
158
+ class="w-full mb-2 border-collapse"
159
+ >
160
+ <thead class="hidden lg:table-header-group">
161
+ <tr class="bg-gray-200">
162
+ <th
163
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-16"
164
+ >
165
+ S.No
166
+ </th>
167
+ <th
168
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-2/5"
169
+ >
170
+ Description *
171
+ </th>
172
+ <th
173
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-24"
174
+ >
175
+ HSN Code
176
+ </th>
177
+ <th
178
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-20"
179
+ >
180
+ Qty *
181
+ </th>
182
+ <th
183
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-32"
184
+ >
185
+ Unit Price *
186
+ </th>
187
+ <th
188
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-28"
189
+ >
190
+ Discount (%)
191
+ </th>
192
+ <th
193
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-32"
194
+ >
195
+ Amount
196
+ </th>
197
+ <th
198
+ class="p-2 border border-gray-300 text-left text-sm font-semibold text-gray-700 w-24"
199
+ >
200
+ Action
201
+ </th>
202
+ </tr>
203
+ </thead>
204
+ <tbody
205
+ class="divide-y divide-gray-200 lg:table-row-group"
206
+ ></tbody>
207
+ </table>
208
+ </div>
209
  <button
210
  type="button"
211
  id="add-item"
212
+ class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded flex items-center gap-2 mt-2"
213
  >
214
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
215
+ <path fill-rule="evenodd" d="M10 5a1 1 0 011 1v3h3a1 1 0 110 2h-3v3a1 1 0 11-2 0v-3H6a1 1 0 110-2h3V6a1 1 0 011-1z" clip-rule="evenodd" />
216
+ </svg>
217
  Add Another Item
218
  </button>
219
  </fieldset>
220
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
221
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
222
  Additional Charges
223
  </legend>
224
  <label class="block mb-2"
 
228
  name="igst-rate"
229
  value="0"
230
  min="0"
231
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
232
  /></label>
233
  <label class="block"
234
  >Freight Charges<input
 
237
  name="freight-charges"
238
  value="0"
239
  min="0"
240
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
241
  /></label>
242
  </fieldset>
243
+ <fieldset class="border border-gray-300 p-4 mb-4 rounded-lg">
244
+ <legend class="text-lg font-semibold mb-2 text-gray-700">
245
  Bank Details
246
  </legend>
247
  <input
 
250
  name="bank-name"
251
  placeholder="Bank Name"
252
  required
253
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
254
  />
255
  <input
256
  type="text"
 
258
  name="bank-account"
259
  placeholder="Account Number"
260
  required
261
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
262
  />
263
  <input
264
  type="text"
 
266
  name="bank-ifsc"
267
  placeholder="IFSC Code"
268
  required
269
+ class="w-full p-2 border border-gray-300 rounded mb-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
270
  />
271
  <input
272
  type="text"
 
274
  name="bank-branch"
275
  placeholder="Branch"
276
  required
277
+ class="w-full p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500"
278
  />
279
  </fieldset>
280
  <div class="flex justify-between items-center">
281
  <button
282
  type="submit"
283
+ class="bg-green-500 hover:bg-green-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-200 ease-in-out transform hover:scale-105"
284
  >
285
  Generate Quotation
286
  </button>
 
288
  <button
289
  type="button"
290
  id="clear-data"
291
+ class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-200 ease-in-out transform hover:scale-105"
292
  >
293
  Clear Saved Data
294
  </button>
295
  <button
296
  type="button"
297
  id="show-storage-info"
298
+ class="bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg shadow-md transition-all duration-200 ease-in-out transform hover:scale-105"
299
  >
300
  Storage Info
301
  </button>
 
303
  </div>
304
  </form>
305
  </div>
306
+ <div id="preview-container" class="w-full lg:w-1/2">
307
  <div
308
  id="quotation-preview"
309
  class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
 
317
  <!-- Storage Information Panel -->
318
  <div
319
  id="storage-info-panel"
320
+ class="absolute z-10 bg-white shadow-lg rounded-lg px-6 pt-4 pb-6 mb-4 hidden w-full max-w-md"
321
+ style="top: 50px; right: 0;"
322
  >
323
+ <h3 class="text-lg font-bold mb-3 flex items-center gap-2">
324
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
325
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.57-.588-3.756z" />
326
+ </svg>
327
+ Storage Information
328
  </h3>
329
  <div class="text-sm space-y-2">
330
+ <div class="bg-blue-50 p-3 rounded-lg">
331
  <h4 class="font-semibold text-blue-800">
332
  Company Details
333
  </h4>
 
338
  Not saved
339
  </p>
340
  </div>
341
+ <div class="bg-green-50 p-3 rounded-lg">
342
  <h4 class="font-semibold text-green-800">
343
  Bank Details
344
  </h4>
 
346
  Not saved
347
  </p>
348
  </div>
349
+ <div class="bg-yellow-50 p-3 rounded-lg">
350
  <h4 class="font-semibold text-yellow-800">
351
  Customer Details
352
  </h4>
 
357
  Not saved (Session only)
358
  </p>
359
  </div>
360
+ <div class="bg-gray-100 p-3 rounded-lg mt-3">
361
+ <h4 class="font-semibold text-gray-800 flex items-center gap-1">
362
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
363
+ <path fill-rule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 3.001-1.742 3.001H4.42c-1.53 0-2.493-1.667-1.743-3.001l5.58-9.92zM10 13a1 1 0 110-2 1 1 0 010 2zm-1-8a1 1 0 00-1 1v3a1 1 0 102 0V6a1 1 0 00-1-1z" clip-rule="evenodd" />
364
+ </svg>
365
+ Security Notice
366
  </h4>
367
+ <p class="text-gray-600 text-xs mt-1">
368
  Data is stored in your browser's localStorage.
369
  For maximum security:
370
  <br />• Use private/incognito browsing <br />•
 
382
  </div>
383
  </div>
384
  </div>
385
+ <div id="quotation-output" class="hidden fixed inset-0 bg-gray-900 bg-opacity-75 z-50 overflow-y-auto">
386
+ <div class="flex items-center justify-center min-h-screen">
387
+ <div class="bg-white p-8 rounded-lg shadow-2xl max-w-4xl w-full mx-auto my-8 relative">
388
+ <button id="close-quotation" class="absolute top-4 right-4 text-gray-500 hover:text-gray-800">
389
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
390
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
391
+ </svg>
392
+ </button>
393
+ <div id="quotation-content"></div>
394
+ </div>
395
+ </div>
396
+ </div>
397
 
398
  <!-- Data Management Status Modal -->
399
  <div
400
  id="status-modal"
401
+ class="fixed inset-0 bg-gray-600 bg-opacity-50 hidden items-center justify-center z-50"
402
  >
403
  <div class="bg-white p-6 rounded-lg shadow-lg max-w-sm mx-auto">
404
  <div id="modal-content" class="text-center">
script.js CHANGED
@@ -277,22 +277,26 @@ if (typeof document !== "undefined") {
277
  const value = input.value;
278
  const type = input.type;
279
 
280
- input.classList.remove("input-error", "input-success");
 
 
 
 
281
 
282
  if (type === "number" && value !== "") {
283
  const num = parseFloat(value);
284
  if (isNaN(num) || num < 0) {
285
- input.classList.add("input-error");
286
  return false;
287
  } else {
288
- input.classList.add("input-success");
289
  }
290
  } else if (
291
  type === "text" &&
292
  input.hasAttribute("required") &&
293
  value.trim() === ""
294
  ) {
295
- input.classList.add("input-error");
296
  return false;
297
  }
298
 
@@ -337,41 +341,43 @@ if (typeof document !== "undefined") {
337
 
338
  function addItemRow() {
339
  const row = document.createElement("tr");
 
 
340
  row.innerHTML = `
341
- <td class="item-slno" data-label="S.No"></td>
342
- <td data-label="Description">
343
  <div class="tooltip">
344
- <input type="text" class="item-desc" placeholder="Enter item description" required>
345
  <span class="tooltiptext">Describe the item or service being quoted</span>
346
  </div>
347
  </td>
348
- <td data-label="HSN Code">
349
  <div class="tooltip">
350
- <input type="text" class="item-hsn" placeholder="HSN Code">
351
  <span class="tooltiptext">Harmonized System of Nomenclature code for tax purposes</span>
352
  </div>
353
  </td>
354
- <td data-label="Qty">
355
  <div class="tooltip">
356
- <input type="number" class="item-qty" value="1" min="0" step="0.01" required>
357
  <span class="tooltiptext">Quantity of items</span>
358
  </div>
359
  </td>
360
- <td data-label="Unit Price">
361
  <div class="tooltip">
362
- <input type="number" class="item-price" value="0" min="0" step="0.01" required>
363
  <span class="tooltiptext">Price per unit before discount</span>
364
  </div>
365
  </td>
366
- <td data-label="Discount (%)">
367
  <div class="tooltip">
368
- <input type="number" class="item-discount" value="0" min="0" max="100" step="0.01" placeholder="0">
369
  <span class="tooltiptext">Discount percentage (0-100)</span>
370
  </div>
371
  </td>
372
- <td class="item-amount" data-label="Amount">0.00</td>
373
- <td data-label="Action">
374
- <button type="button" class="remove-item" title="Remove this item">
375
  <span>×</span> Remove
376
  </button>
377
  </td>
@@ -448,8 +454,10 @@ if (typeof document !== "undefined") {
448
 
449
  // Add visual feedback for calculated amount
450
  const amountCell = row.querySelector(".item-amount");
451
- amountCell.style.backgroundColor =
452
- amount > 0 ? "#f0fdf4" : "#fef2f2";
 
 
453
  }
454
 
455
  // Enhanced Add Item button
@@ -458,10 +466,11 @@ if (typeof document !== "undefined") {
458
  updatePreview();
459
 
460
  // Focus the new row's first input
 
 
461
  setTimeout(() => {
462
- const newRow = itemsTableBody.lastElementChild;
463
  newRow.querySelector(".item-desc").focus();
464
- }, 50);
465
  });
466
 
467
  // Add keyboard shortcut for adding items (Ctrl+I)
@@ -491,12 +500,14 @@ if (typeof document !== "undefined") {
491
  return;
492
  }
493
 
 
494
  const html = generateQuotationHTML(form);
495
- output.innerHTML = html;
496
- output.style.display = "block";
497
- document.getElementById("form-container").style.display = "none";
498
- document.getElementById("preview-container").style.display = "none";
499
- document.getElementById("top-header").style.display = "none";
 
500
  });
501
 
502
  // Initial preview
 
277
  const value = input.value;
278
  const type = input.type;
279
 
280
+ input.classList.remove(
281
+ "border-red-500",
282
+ "bg-red-100",
283
+ "border-green-500",
284
+ );
285
 
286
  if (type === "number" && value !== "") {
287
  const num = parseFloat(value);
288
  if (isNaN(num) || num < 0) {
289
+ input.classList.add("border-red-500", "bg-red-100");
290
  return false;
291
  } else {
292
+ input.classList.add("border-green-500");
293
  }
294
  } else if (
295
  type === "text" &&
296
  input.hasAttribute("required") &&
297
  value.trim() === ""
298
  ) {
299
+ input.classList.add("border-red-500", "bg-red-100");
300
  return false;
301
  }
302
 
 
341
 
342
  function addItemRow() {
343
  const row = document.createElement("tr");
344
+ row.className =
345
+ "block lg:table-row border-b-2 lg:border-b-0 lg:border-gray-200";
346
  row.innerHTML = `
347
+ <td class="item-slno p-2 border border-gray-300 text-center font-semibold text-gray-600 bg-gray-50 w-16 hidden lg:table-cell" data-label="S.No"></td>
348
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="Description">
349
  <div class="tooltip">
350
+ <input type="text" class="item-desc w-full p-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="Enter item description" required>
351
  <span class="tooltiptext">Describe the item or service being quoted</span>
352
  </div>
353
  </td>
354
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="HSN Code">
355
  <div class="tooltip">
356
+ <input type="text" class="item-hsn w-full p-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" placeholder="HSN Code">
357
  <span class="tooltiptext">Harmonized System of Nomenclature code for tax purposes</span>
358
  </div>
359
  </td>
360
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="Qty">
361
  <div class="tooltip">
362
+ <input type="number" class="item-qty w-full p-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" value="1" min="0" step="0.01" required>
363
  <span class="tooltiptext">Quantity of items</span>
364
  </div>
365
  </td>
366
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="Unit Price">
367
  <div class="tooltip">
368
+ <input type="number" class="item-price w-full p-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" value="0" min="0" step="0.01" required>
369
  <span class="tooltiptext">Price per unit before discount</span>
370
  </div>
371
  </td>
372
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="Discount (%)">
373
  <div class="tooltip">
374
+ <input type="number" class="item-discount w-full p-2 border border-gray-300 rounded text-sm focus:outline-none focus:ring-2 focus:ring-blue-500" value="0" min="0" max="100" step="0.01" placeholder="0">
375
  <span class="tooltiptext">Discount percentage (0-100)</span>
376
  </div>
377
  </td>
378
+ <td class="item-amount p-2 border border-gray-300 text-right font-semibold text-green-700 bg-green-50 font-mono block lg:table-cell" data-label="Amount">0.00</td>
379
+ <td class="p-2 border border-gray-300 block lg:table-cell" data-label="Action">
380
+ <button type="button" class="remove-item bg-red-500 hover:bg-red-600 text-white text-xs font-bold py-1 px-2 rounded flex items-center gap-1" title="Remove this item">
381
  <span>×</span> Remove
382
  </button>
383
  </td>
 
454
 
455
  // Add visual feedback for calculated amount
456
  const amountCell = row.querySelector(".item-amount");
457
+ amountCell.classList.toggle("bg-green-50", amount > 0);
458
+ amountCell.classList.toggle("text-green-700", amount > 0);
459
+ amountCell.classList.toggle("bg-red-50", amount <= 0);
460
+ amountCell.classList.toggle("text-red-700", amount <= 0);
461
  }
462
 
463
  // Enhanced Add Item button
 
466
  updatePreview();
467
 
468
  // Focus the new row's first input
469
+ const newRow = itemsTableBody.lastElementChild;
470
+ newRow.scrollIntoView({ behavior: "smooth", block: "center" });
471
  setTimeout(() => {
 
472
  newRow.querySelector(".item-desc").focus();
473
+ }, 100);
474
  });
475
 
476
  // Add keyboard shortcut for adding items (Ctrl+I)
 
500
  return;
501
  }
502
 
503
+ const quotationContent = document.getElementById("quotation-content");
504
  const html = generateQuotationHTML(form);
505
+ quotationContent.innerHTML = html;
506
+ output.classList.remove("hidden");
507
+ });
508
+
509
+ document.getElementById("close-quotation").addEventListener("click", () => {
510
+ output.classList.add("hidden");
511
  });
512
 
513
  // Initial preview
style.css CHANGED
@@ -1,171 +1,5 @@
1
  @import "tailwindcss";
2
 
3
- /* Enhanced Items Table Styling */
4
- #items-table {
5
- border-collapse: collapse;
6
- margin-bottom: 1rem;
7
- }
8
-
9
- #items-table th {
10
- background-color: #f8fafc;
11
- font-weight: 600;
12
- font-size: 0.875rem;
13
- color: #374151;
14
- border: 1px solid #d1d5db;
15
- padding: 0.75rem 0.5rem;
16
- text-align: left;
17
- }
18
-
19
- #items-table td {
20
- border: 1px solid #d1d5db;
21
- padding: 0.25rem;
22
- vertical-align: middle;
23
- }
24
-
25
- #items-table input {
26
- width: 100%;
27
- padding: 0.5rem;
28
- border: 1px solid #d1d5db;
29
- border-radius: 0.375rem;
30
- font-size: 0.875rem;
31
- transition:
32
- border-color 0.2s,
33
- box-shadow 0.2s;
34
- }
35
-
36
- #items-table input:focus {
37
- outline: none;
38
- border-color: #3b82f6;
39
- box-shadow: 0 0 0 3px rgb(59 130 246 / 10%);
40
- }
41
-
42
- #items-table input:invalid {
43
- border-color: #ef4444;
44
- }
45
-
46
- #items-table .item-slno {
47
- text-align: center;
48
- font-weight: 600;
49
- color: #6b7280;
50
- background-color: #f9fafb;
51
- width: 3rem;
52
- }
53
-
54
- #items-table .item-amount {
55
- text-align: right;
56
- font-weight: 600;
57
- color: #059669;
58
- background-color: #f0fdf4;
59
- font-family: "Courier New", monospace;
60
- padding: 0.5rem;
61
- border: 2px solid #d1fae5;
62
- }
63
-
64
- #items-table .remove-item {
65
- background-color: #ef4444;
66
- color: white;
67
- border: none;
68
- padding: 0.375rem 0.75rem;
69
- border-radius: 0.375rem;
70
- font-size: 0.75rem;
71
- cursor: pointer;
72
- transition: background-color 0.2s;
73
- display: flex;
74
- align-items: center;
75
- gap: 0.25rem;
76
- }
77
-
78
- #items-table .remove-item:hover {
79
- background-color: #dc2626;
80
- }
81
-
82
- #items-table .remove-item:focus {
83
- outline: none;
84
- box-shadow: 0 0 0 2px rgb(239 68 68 / 50%);
85
- }
86
-
87
- /* Column widths for better UX */
88
- #items-table th:nth-child(1) {
89
- width: 4rem;
90
- }
91
-
92
- /* S.No */
93
- #items-table th:nth-child(2) {
94
- width: 30%;
95
- }
96
-
97
- /* Description */
98
- #items-table th:nth-child(3) {
99
- width: 8rem;
100
- }
101
-
102
- /* HSN Code */
103
- #items-table th:nth-child(4) {
104
- width: 5rem;
105
- }
106
-
107
- /* Qty */
108
- #items-table th:nth-child(5) {
109
- width: 8rem;
110
- }
111
-
112
- /* Unit Price */
113
- #items-table th:nth-child(6) {
114
- width: 7rem;
115
- }
116
-
117
- /* Discount */
118
- #items-table th:nth-child(7) {
119
- width: 8rem;
120
- }
121
-
122
- /* Amount */
123
- #items-table th:nth-child(8) {
124
- width: 6rem;
125
- }
126
-
127
- /* Action */
128
-
129
- /* Add Item Button Enhancement */
130
- #add-item {
131
- display: flex;
132
- align-items: center;
133
- gap: 0.5rem;
134
- margin-top: 0.5rem;
135
- }
136
-
137
- #add-item::before {
138
- content: "+";
139
- font-size: 1.25rem;
140
- font-weight: bold;
141
- }
142
-
143
- /* Empty state styling */
144
- .items-empty-state {
145
- text-align: center;
146
- color: #6b7280;
147
- font-style: italic;
148
- padding: 2rem;
149
- background-color: #f9fafb;
150
- border: 2px dashed #d1d5db;
151
- margin-bottom: 1rem;
152
- }
153
-
154
- /* Row highlighting on hover */
155
- #items-table tbody tr:hover {
156
- background-color: #f8fafc;
157
- }
158
-
159
- /* Input error states */
160
- .input-error {
161
- border-color: #ef4444 !important;
162
- background-color: #fef2f2;
163
- }
164
-
165
- .input-success {
166
- border-color: #10b981 !important;
167
- }
168
-
169
  /* Tooltips */
170
  .tooltip {
171
  position: relative;
 
1
  @import "tailwindcss";
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
  /* Tooltips */
4
  .tooltip {
5
  position: relative;