Digiator commited on
Commit
0a16caf
·
verified ·
1 Parent(s): 8e146cf

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +103 -81
index.html CHANGED
@@ -101,57 +101,7 @@
101
  </div>
102
 
103
  <div id="expensesList" class="space-y-3 sm:space-y-4">
104
- <!-- Default categories -->
105
- <div class="expense-item animate-fade-in">
106
- <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 sm:gap-0">
107
- <div class="flex items-center sm:w-2/5">
108
- <i class="fas fa-pills text-purple-500 mr-2 text-sm sm:text-base"></i>
109
- <span class="text-gray-700 text-sm sm:text-base">Vitamins</span>
110
- </div>
111
- <div class="flex items-center sm:w-3/5">
112
- <span class="expense-currency mr-2 text-gray-700 text-sm sm:text-base">$</span>
113
- <input type="number" placeholder="Amount"
114
- class="expense-input flex-1 border-b-2 border-gray-300 py-1 px-1 focus:border-indigo-500 focus:outline-none text-sm sm:text-base">
115
- <button class="delete-btn ml-2 sm:ml-3 text-red-500 hover:text-red-700 text-sm sm:text-base">
116
- <i class="fas fa-trash"></i>
117
- </button>
118
- </div>
119
- </div>
120
- </div>
121
-
122
- <div class="expense-item animate-fade-in">
123
- <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 sm:gap-0">
124
- <div class="flex items-center sm:w-2/5">
125
- <i class="fas fa-dumbbell text-blue-500 mr-2 text-sm sm:text-base"></i>
126
- <span class="text-gray-700 text-sm sm:text-base">Sports</span>
127
- </div>
128
- <div class="flex items-center sm:w-3/5">
129
- <span class="expense-currency mr-2 text-gray-700 text-sm sm:text-base">$</span>
130
- <input type="number" placeholder="Amount"
131
- class="expense-input flex-1 border-b-2 border-gray-300 py-1 px-1 focus:border-indigo-500 focus:outline-none text-sm sm:text-base">
132
- <button class="delete-btn ml-2 sm:ml-3 text-red-500 hover:text-red-700 text-sm sm:text-base">
133
- <i class="fas fa-trash"></i>
134
- </button>
135
- </div>
136
- </div>
137
- </div>
138
-
139
- <div class="expense-item animate-fade-in">
140
- <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 sm:gap-0">
141
- <div class="flex items-center sm:w-2/5">
142
- <i class="fas fa-utensils text-orange-500 mr-2 text-sm sm:text-base"></i>
143
- <span class="text-gray-700 text-sm sm:text-base">Food</span>
144
- </div>
145
- <div class="flex items-center sm:w-3/5">
146
- <span class="expense-currency mr-2 text-gray-700 text-sm sm:text-base">$</span>
147
- <input type="number" placeholder="Amount"
148
- class="expense-input flex-1 border-b-2 border-gray-300 py-1 px-1 focus:border-indigo-500 focus:outline-none text-sm sm:text-base">
149
- <button class="delete-btn ml-2 sm:ml-3 text-red-500 hover:text-red-700 text-sm sm:text-base">
150
- <i class="fas fa-trash"></i>
151
- </button>
152
- </div>
153
- </div>
154
- </div>
155
  </div>
156
  </div>
157
 
@@ -177,6 +127,9 @@
177
  <option value="fa-wifi">Utilities</option>
178
  <option value="fa-gift">Gifts</option>
179
  <option value="fa-plane">Travel</option>
 
 
 
180
  </select>
181
  </div>
182
  <div class="flex justify-end space-x-2 sm:space-x-3">
@@ -207,8 +160,78 @@
207
  const currencyPicker = document.getElementById('currencyPicker');
208
  const currencySymbol = document.getElementById('currencySymbol');
209
 
210
- let salary = 0;
211
- let currentCurrency = '$';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
  // Update currency symbols
214
  function updateCurrencySymbols() {
@@ -221,9 +244,28 @@
221
  updateSummaryDisplay();
222
  }
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  // Currency picker change handler
225
  currencyPicker.addEventListener('change', function() {
226
  currentCurrency = this.value;
 
227
  updateCurrencySymbols();
228
  });
229
 
@@ -232,6 +274,7 @@
232
  const value = parseFloat(salaryInput.value);
233
  if (!isNaN(value) && value > 0) {
234
  salary = value;
 
235
  updateSummaryDisplay();
236
  summarySection.classList.remove('hidden');
237
  expensesSection.classList.remove('hidden');
@@ -242,11 +285,6 @@
242
  }
243
  });
244
 
245
- // Add event listeners to existing expense inputs
246
- document.querySelectorAll('.expense-input').forEach(input => {
247
- input.addEventListener('input', calculateRemaining);
248
- });
249
-
250
  // Delete expense item
251
  expensesList.addEventListener('click', function(e) {
252
  if (e.target.classList.contains('delete-btn') || e.target.closest('.delete-btn')) {
@@ -254,6 +292,7 @@
254
  item.classList.add('hidden');
255
  setTimeout(() => {
256
  item.remove();
 
257
  calculateRemaining();
258
  }, 300);
259
  }
@@ -277,28 +316,8 @@
277
  const icon = newCategoryIcon.value;
278
 
279
  if (name) {
280
- const newItem = document.createElement('div');
281
- newItem.className = 'expense-item animate-fade-in';
282
- newItem.innerHTML = `
283
- <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 sm:gap-0">
284
- <div class="flex items-center sm:w-2/5">
285
- <i class="fas ${icon} text-indigo-500 mr-2 text-sm sm:text-base"></i>
286
- <span class="text-gray-700 text-sm sm:text-base">${name}</span>
287
- </div>
288
- <div class="flex items-center sm:w-3/5">
289
- <span class="expense-currency mr-2 text-gray-700 text-sm sm:text-base">${currentCurrency}</span>
290
- <input type="number" placeholder="Amount"
291
- class="expense-input flex-1 border-b-2 border-gray-300 py-1 px-1 focus:border-indigo-500 focus:outline-none text-sm sm:text-base">
292
- <button class="delete-btn ml-2 sm:ml-3 text-red-500 hover:text-red-700 text-sm sm:text-base">
293
- <i class="fas fa-trash"></i>
294
- </button>
295
- </div>
296
- </div>
297
- `;
298
-
299
- expensesList.appendChild(newItem);
300
- newItem.querySelector('.expense-input').addEventListener('input', calculateRemaining);
301
-
302
  addCategoryModal.classList.add('hidden');
303
  newCategoryName.value = '';
304
  } else {
@@ -339,7 +358,10 @@
339
  remainingSalaryDisplay.classList.add('text-green-800');
340
  }
341
  }
 
 
 
342
  });
343
  </script>
344
- <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=Digiator/spend-planner" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
345
  </html>
 
101
  </div>
102
 
103
  <div id="expensesList" class="space-y-3 sm:space-y-4">
104
+ <!-- Items will be added here dynamically -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  </div>
106
  </div>
107
 
 
127
  <option value="fa-wifi">Utilities</option>
128
  <option value="fa-gift">Gifts</option>
129
  <option value="fa-plane">Travel</option>
130
+ <option value="fa-pills">Vitamins</option>
131
+ <option value="fa-dumbbell">Sports</option>
132
+ <option value="fa-utensils">Food</option>
133
  </select>
134
  </div>
135
  <div class="flex justify-end space-x-2 sm:space-x-3">
 
160
  const currencyPicker = document.getElementById('currencyPicker');
161
  const currencySymbol = document.getElementById('currencySymbol');
162
 
163
+ // Load data from localStorage
164
+ let salary = parseFloat(localStorage.getItem('salary')) || 0;
165
+ let currentCurrency = localStorage.getItem('currency') || '$';
166
+ let expenses = JSON.parse(localStorage.getItem('expenses')) || [];
167
+
168
+ // Initialize the app with saved data
169
+ function initApp() {
170
+ // Set currency
171
+ currencyPicker.value = currentCurrency;
172
+ currencySymbol.textContent = currentCurrency;
173
+
174
+ // Set salary if exists
175
+ if (salary > 0) {
176
+ salaryInput.value = salary;
177
+ updateSummaryDisplay();
178
+ summarySection.classList.remove('hidden');
179
+ expensesSection.classList.remove('hidden');
180
+ }
181
+
182
+ // Load expenses
183
+ if (expenses.length > 0) {
184
+ expenses.forEach(expense => {
185
+ addExpenseItem(expense.name, expense.amount, expense.icon);
186
+ });
187
+ } else {
188
+ // Add default categories if no expenses exist
189
+ addDefaultCategories();
190
+ }
191
+
192
+ calculateRemaining();
193
+ }
194
+
195
+ // Add default categories if no expenses exist
196
+ function addDefaultCategories() {
197
+ const defaultCategories = [
198
+ { name: 'Vitamins', icon: 'fa-pills', color: 'purple' },
199
+ { name: 'Sports', icon: 'fa-dumbbell', color: 'blue' },
200
+ { name: 'Food', icon: 'fa-utensils', color: 'orange' }
201
+ ];
202
+
203
+ defaultCategories.forEach(category => {
204
+ addExpenseItem(category.name, 0, category.icon, category.color);
205
+ });
206
+ }
207
+
208
+ // Add an expense item to the DOM
209
+ function addExpenseItem(name, amount, icon, color = 'indigo') {
210
+ const newItem = document.createElement('div');
211
+ newItem.className = 'expense-item animate-fade-in';
212
+ newItem.innerHTML = `
213
+ <div class="flex flex-col sm:flex-row sm:items-center justify-between gap-2 sm:gap-0">
214
+ <div class="flex items-center sm:w-2/5">
215
+ <i class="fas ${icon} text-${color}-500 mr-2 text-sm sm:text-base"></i>
216
+ <span class="text-gray-700 text-sm sm:text-base">${name}</span>
217
+ </div>
218
+ <div class="flex items-center sm:w-3/5">
219
+ <span class="expense-currency mr-2 text-gray-700 text-sm sm:text-base">${currentCurrency}</span>
220
+ <input type="number" placeholder="Amount" value="${amount || ''}"
221
+ class="expense-input flex-1 border-b-2 border-gray-300 py-1 px-1 focus:border-indigo-500 focus:outline-none text-sm sm:text-base">
222
+ <button class="delete-btn ml-2 sm:ml-3 text-red-500 hover:text-red-700 text-sm sm:text-base">
223
+ <i class="fas fa-trash"></i>
224
+ </button>
225
+ </div>
226
+ </div>
227
+ `;
228
+
229
+ expensesList.appendChild(newItem);
230
+ newItem.querySelector('.expense-input').addEventListener('input', function() {
231
+ updateExpensesInStorage();
232
+ calculateRemaining();
233
+ });
234
+ }
235
 
236
  // Update currency symbols
237
  function updateCurrencySymbols() {
 
244
  updateSummaryDisplay();
245
  }
246
 
247
+ // Save expenses to localStorage
248
+ function updateExpensesInStorage() {
249
+ expenses = [];
250
+ document.querySelectorAll('.expense-item').forEach(item => {
251
+ const name = item.querySelector('span').textContent;
252
+ const icon = item.querySelector('i').className.match(/fa-[a-z-]+/)[0];
253
+ const amount = parseFloat(item.querySelector('.expense-input').value) || 0;
254
+
255
+ expenses.push({
256
+ name: name,
257
+ amount: amount,
258
+ icon: icon
259
+ });
260
+ });
261
+
262
+ localStorage.setItem('expenses', JSON.stringify(expenses));
263
+ }
264
+
265
  // Currency picker change handler
266
  currencyPicker.addEventListener('change', function() {
267
  currentCurrency = this.value;
268
+ localStorage.setItem('currency', currentCurrency);
269
  updateCurrencySymbols();
270
  });
271
 
 
274
  const value = parseFloat(salaryInput.value);
275
  if (!isNaN(value) && value > 0) {
276
  salary = value;
277
+ localStorage.setItem('salary', salary.toString());
278
  updateSummaryDisplay();
279
  summarySection.classList.remove('hidden');
280
  expensesSection.classList.remove('hidden');
 
285
  }
286
  });
287
 
 
 
 
 
 
288
  // Delete expense item
289
  expensesList.addEventListener('click', function(e) {
290
  if (e.target.classList.contains('delete-btn') || e.target.closest('.delete-btn')) {
 
292
  item.classList.add('hidden');
293
  setTimeout(() => {
294
  item.remove();
295
+ updateExpensesInStorage();
296
  calculateRemaining();
297
  }, 300);
298
  }
 
316
  const icon = newCategoryIcon.value;
317
 
318
  if (name) {
319
+ addExpenseItem(name, 0, icon);
320
+ updateExpensesInStorage();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
  addCategoryModal.classList.add('hidden');
322
  newCategoryName.value = '';
323
  } else {
 
358
  remainingSalaryDisplay.classList.add('text-green-800');
359
  }
360
  }
361
+
362
+ // Initialize the app
363
+ initApp();
364
  });
365
  </script>
366
+ </body>
367
  </html>