diff --git a/js/app.d.ts.map b/js/app.d.ts.map
index 8f48be1..ed511fe 100644
--- a/js/app.d.ts.map
+++ b/js/app.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAIA,OAAO,EAA4C,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AASlG,UAAU,mBAAoB,SAAQ,WAAW;IAC7C,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,cAAM,WAAW;IACb,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3C,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,qBAAqB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5C,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9C,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAChD,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC7C,YAAY,EAAE,IAAI,CAAc;IAChC,aAAa,EAAE,OAAO,CAAS;IAC/B,MAAM,EAAE,MAAM,EAAE,CAqBd;;IAMF,IAAI,IAAI,IAAI;IAWZ,mBAAmB,IAAI,IAAI;IAoJ3B,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAiChC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBvC,eAAe,IAAI,IAAI;IA2EvB,oBAAoB,IAAI,IAAI;IA6C5B,qBAAqB,IAAI,IAAI;IA8B7B,cAAc,IAAI,IAAI;IAOtB,WAAW,IAAI,IAAI;IAKnB,WAAW,IAAI,IAAI;IAyFnB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IA4BlC,oBAAoB,IAAI,IAAI;IAU5B,aAAa,CAAC,MAAM,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IA6DjD,cAAc,IAAI,IAAI;IAUtB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI;IA4B5C,mBAAmB,IAAI,IAAI;IAO3B,QAAQ,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IA4CxB,UAAU,IAAI,IAAI;IAWlB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAwBhC,oBAAoB,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI;IAW1D,uBAAuB,CAAC,aAAa,EAAE,IAAI,GAAG,IAAI;IA6DlD,cAAc,IAAI,IAAI;IAkBtB,iBAAiB,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM;IA8BtG,gBAAgB,CAAC,SAAS,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAsBvD,iBAAiB,IAAI,IAAI;IAKzB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAoB3B,aAAa,IAAI,IAAI;IAUrB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAuB/C,uBAAuB,IAAI,IAAI;IAK/B,qBAAqB,IAAI,IAAI;IAM7B,wBAAwB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,IAAI;IA2C7C,YAAY,IAAI,IAAI;IA4BpB,eAAe,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM;IAmDrC,cAAc,CAAC,OAAO,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAkDnD,eAAe,IAAI,IAAI;IAKvB,SAAS,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IA0BzB,WAAW,IAAI,IAAI;IAUnB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAgBpC,eAAe,IAAI,IAAI;IAkBvB,gBAAgB,IAAI,IAAI;IAIxB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAShC,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IA4BxC,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAavD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmBrC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IASrC,wBAAwB,IAAI,IAAI;IAchC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAI/B,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,WAAW,GAAG,IAAI;IAmBvD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,WAAW,GAAG,IAAI;IAiBnF,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMtC,uBAAuB,IAAI,IAAI;IAkB/B,2BAA2B,IAAI,IAAI;IASnC,kBAAkB,IAAI,IAAI;IAK1B,mBAAmB,IAAI;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE;IAM7D,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,mBAAmB,EAAE;IAyBrE,cAAc,IAAI,IAAI;IAOtB,oBAAoB,IAAI,IAAI;IAe5B,cAAc,IAAI,IAAI;IAKtB,aAAa,IAAI,IAAI;IAKrB,aAAa,IAAI,IAAI;IAKrB,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,EAAE,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,OAAe,GAAG,IAAI;IAmCnH,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAwCrE,iBAAiB,IAAI,IAAI;IAMzB,WAAW,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAsC3B,aAAa,IAAI,IAAI;IAmBrB,UAAU,IAAI,IAAI;IA+DlB,eAAe,CAAC,QAAQ,GAAE,MAAM,GAAG,IAAW,GAAG,IAAI;IAyBrD,gBAAgB,IAAI,IAAI;IAKxB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAoB1B,YAAY,IAAI,IAAI;IAUpB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAoBtC,cAAc,IAAI,IAAI;IAMtB,YAAY,IAAI,IAAI;IAQpB,oBAAoB,IAAI,IAAI;IAiB5B,iBAAiB,IAAI,IAAI;IAczB,UAAU,IAAI,IAAI;IAalB,UAAU,CAAC,CAAC,EAAE,KAAK,GAAG,IAAI;IAuB1B,qBAAqB,IAAI,IAAI;IAQ7B,MAAM,IAAI,IAAI;IAYd,kBAAkB,IAAI,MAAM;IAI5B,mBAAmB,IAAI,OAAO;IAI9B,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAsBjC,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAMrC,mBAAmB,IAAI,IAAI;CAqB9B;AAOD,OAAO,EAAE,WAAW,EAAE,CAAC"}
\ No newline at end of file
+{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/js/app.js b/js/app.js
index ea63d7c..c6fa106 100644
--- a/js/app.js
+++ b/js/app.js
@@ -10,6 +10,8 @@ class TaskManager {
this.currentEditingFinanceId = null;
this.currentEditingFinanceType = null;
this.currentEditingRewardId = null;
+ this.currentEditingWishItemId = null;
+ this.dragSrcWishId = null;
this.selectedDate = new Date();
this.tasksExpanded = false;
this.emojis = [
@@ -102,6 +104,11 @@ class TaskManager {
document.getElementById('rewardForm').addEventListener('submit', (e) => this.saveReward(e));
document.getElementById('cancelRewardBtn').addEventListener('click', () => this.closeRewardModal());
document.getElementById('deleteRewardBtn').addEventListener('click', () => this.deleteReward());
+ // Wish List section
+ document.getElementById('addWishItemBtn').addEventListener('click', () => this.openWishItemModal());
+ document.getElementById('wishItemForm').addEventListener('submit', (e) => this.saveWishItem(e));
+ document.getElementById('cancelWishItemBtn').addEventListener('click', () => this.closeWishItemModal());
+ document.getElementById('deleteWishItemBtn').addEventListener('click', () => this.deleteWishItem());
// Modal close buttons
document.querySelectorAll('.close-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
@@ -210,6 +217,9 @@ class TaskManager {
else if (tabName === 'shop') {
this.renderShop();
}
+ else if (tabName === 'wishlist') {
+ this.renderWishList();
+ }
else if (tabName === 'settings') {
this.renderSettings();
}
@@ -1514,6 +1524,126 @@ class TaskManager {
}
}
// ========================
+ // Wish List
+ // ========================
+ renderWishList() {
+ const items = storage.getWishItems();
+ const container = document.getElementById('wishList');
+ if (items.length === 0) {
+ container.innerHTML = '
No items in your wish list. Add one to get started!
';
+ return;
+ }
+ container.innerHTML = items.map(item => this.renderWishItem(item)).join('');
+ container.querySelectorAll('.wish-item').forEach(el => {
+ el.addEventListener('dragstart', (e) => {
+ this.dragSrcWishId = el.dataset.wishId;
+ el.classList.add('dragging');
+ e.dataTransfer.effectAllowed = 'move';
+ });
+ el.addEventListener('dragend', () => {
+ this.dragSrcWishId = null;
+ el.classList.remove('dragging');
+ container.querySelectorAll('.wish-item').forEach(i => i.classList.remove('drag-over'));
+ });
+ el.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = 'move';
+ container.querySelectorAll('.wish-item').forEach(i => i.classList.remove('drag-over'));
+ el.classList.add('drag-over');
+ });
+ el.addEventListener('drop', (e) => {
+ e.preventDefault();
+ const targetId = el.dataset.wishId;
+ if (this.dragSrcWishId && this.dragSrcWishId !== targetId) {
+ const allItems = storage.getWishItems();
+ const srcIdx = allItems.findIndex(i => i.id === this.dragSrcWishId);
+ const tgtIdx = allItems.findIndex(i => i.id === targetId);
+ if (srcIdx !== -1 && tgtIdx !== -1) {
+ const reordered = [...allItems];
+ const [moved] = reordered.splice(srcIdx, 1);
+ reordered.splice(tgtIdx, 0, moved);
+ storage.reorderWishItems(reordered.map(i => i.id));
+ this.renderWishList();
+ }
+ }
+ });
+ el.querySelector('.edit-wish-btn').addEventListener('click', (e) => {
+ e.stopPropagation();
+ this.openWishItemModal(el.dataset.wishId);
+ });
+ });
+ }
+ renderWishItem(item) {
+ const priceStr = item.price !== undefined && item.price !== null
+ ? `
$${Number(item.price).toFixed(2)}`
+ : '';
+ const urlStr = item.url
+ ? `
🔗 View Listing`
+ : '';
+ return `
+
+
⠿
+
+
${item.title}
+
+ ${priceStr}
+ ${urlStr}
+
+
+
+
+ `;
+ }
+ openWishItemModal(itemId = null) {
+ this.currentEditingWishItemId = itemId;
+ const modal = document.getElementById('wishItemModal');
+ const form = document.getElementById('wishItemForm');
+ const deleteBtn = document.getElementById('deleteWishItemBtn');
+ form.reset();
+ deleteBtn.style.display = 'none';
+ document.getElementById('wishItemModalTitle').textContent = itemId ? 'Edit Wish List Item' : 'Add Wish List Item';
+ if (itemId) {
+ const item = storage.getWishItems().find(w => w.id === itemId);
+ if (item) {
+ document.getElementById('wishItemTitle').value = item.title;
+ document.getElementById('wishItemUrl').value = item.url || '';
+ document.getElementById('wishItemPrice').value =
+ item.price !== undefined && item.price !== null ? String(item.price) : '';
+ deleteBtn.style.display = 'block';
+ }
+ }
+ modal.classList.add('active');
+ }
+ closeWishItemModal() {
+ document.getElementById('wishItemModal').classList.remove('active');
+ this.currentEditingWishItemId = null;
+ }
+ saveWishItem(e) {
+ e.preventDefault();
+ const title = document.getElementById('wishItemTitle').value;
+ const url = document.getElementById('wishItemUrl').value.trim() || undefined;
+ const priceVal = document.getElementById('wishItemPrice').value;
+ const price = priceVal !== '' ? parseFloat(priceVal) : undefined;
+ const item = { title, url, price };
+ if (this.currentEditingWishItemId) {
+ storage.updateWishItem(this.currentEditingWishItemId, item);
+ }
+ else {
+ storage.addWishItem(item);
+ }
+ this.closeWishItemModal();
+ this.renderWishList();
+ }
+ deleteWishItem() {
+ if (this.currentEditingWishItemId) {
+ if (confirm('Are you sure you want to delete this wish list item?')) {
+ storage.deleteWishItem(this.currentEditingWishItemId);
+ this.closeWishItemModal();
+ this.renderWishList();
+ }
+ }
+ }
+ // ========================
// Settings
// ========================
renderSettings() {
diff --git a/js/storage.d.ts.map b/js/storage.d.ts.map
index 031aba3..326cdf2 100644
--- a/js/storage.d.ts.map
+++ b/js/storage.d.ts.map
@@ -1 +1 @@
-{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"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"}
\ No newline at end of file
diff --git a/js/storage.js b/js/storage.js
index 7a63718..36bfa6a 100644
--- a/js/storage.js
+++ b/js/storage.js
@@ -43,7 +43,8 @@ export class StorageManager {
},
settings: {
tasksPerLevel: 30
- }
+ },
+ wishList: []
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(initialData));
}
@@ -179,14 +180,46 @@ export class StorageManager {
date: dateStr,
timestamp: new Date().toISOString()
});
- // Update habit streak
+ // Update habit streak based on fully-completed consecutive days
const habit = data.habits.find(h => h.id === habitId);
if (habit) {
habit.lastCompletedDate = dateStr;
- habit.streak = (habit.streak || 0) + 1;
+ habit.streak = this.calculateHabitStreak(habitId, habit.targetGoal, data.dailyHabitLogs);
}
this.saveData(data);
}
+ calculateHabitStreak(habitId, targetGoal, logs) {
+ // Count completions per date for this habit
+ const habitLogs = logs.filter(l => l.habitId === habitId);
+ const countsByDate = {};
+ for (const log of habitLogs) {
+ countsByDate[log.date] = (countsByDate[log.date] || 0) + 1;
+ }
+ // Get dates where fully completed (>= targetGoal), sorted most recent first
+ const completedDates = Object.keys(countsByDate)
+ .filter(date => countsByDate[date] >= targetGoal)
+ .sort()
+ .reverse();
+ if (completedDates.length === 0)
+ return 0;
+ // Count consecutive days going backward from the most recent fully-completed day
+ let streak = 1;
+ let currentDate = completedDates[0];
+ for (let i = 1; i < completedDates.length; i++) {
+ const [year, month, day] = currentDate.split('-').map(Number);
+ const prevDay = new Date(year, month - 1, day);
+ prevDay.setDate(prevDay.getDate() - 1);
+ const expectedDate = this.formatDate(prevDay);
+ if (completedDates[i] === expectedDate) {
+ streak++;
+ currentDate = completedDates[i];
+ }
+ else {
+ break;
+ }
+ }
+ return streak;
+ }
isHabitCompletedToday(habitId) {
const data = this.getData();
const todayStr = this.formatDate(new Date());
@@ -391,6 +424,59 @@ export class StorageManager {
const data = this.getData();
return data.purchaseHistory || [];
}
+ // Wish List Management
+ addWishItem(item) {
+ const data = this.getData();
+ if (!data.wishList)
+ data.wishList = [];
+ const newItem = {
+ ...item,
+ id: this.generateId(),
+ createdDate: new Date().toISOString(),
+ title: item.title || '',
+ order: data.wishList.length,
+ };
+ data.wishList.push(newItem);
+ this.saveData(data);
+ return newItem;
+ }
+ updateWishItem(itemId, updates) {
+ const data = this.getData();
+ if (!data.wishList)
+ data.wishList = [];
+ const item = data.wishList.find(w => w.id === itemId);
+ if (item) {
+ Object.assign(item, updates);
+ this.saveData(data);
+ }
+ return item;
+ }
+ deleteWishItem(itemId) {
+ const data = this.getData();
+ if (!data.wishList)
+ data.wishList = [];
+ data.wishList = data.wishList.filter(w => w.id !== itemId);
+ // Re-index order values
+ data.wishList.forEach((w, idx) => { w.order = idx; });
+ this.saveData(data);
+ }
+ getWishItems() {
+ const data = this.getData();
+ if (!data.wishList)
+ return [];
+ return data.wishList.slice().sort((a, b) => a.order - b.order);
+ }
+ reorderWishItems(orderedIds) {
+ const data = this.getData();
+ if (!data.wishList)
+ return;
+ orderedIds.forEach((id, idx) => {
+ const item = data.wishList.find(w => w.id === id);
+ if (item)
+ item.order = idx;
+ });
+ this.saveData(data);
+ }
// Points Management
addPoints(amount, source) {
const data = this.getData();
diff --git a/src/app.ts b/src/app.ts
index c587ce5..040b66a 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -2,7 +2,7 @@
// Main Application Logic
// ========================
-import { StorageManager, storage, STORAGE_VERSION, Task, Habit, FinanceItem } from './storage.js';
+import { StorageManager, storage, STORAGE_VERSION, Task, Habit, FinanceItem, WishItem } from './storage.js';
interface Activity {
type: string;
@@ -22,6 +22,8 @@ class TaskManager {
currentEditingFinanceId: string | null = null;
currentEditingFinanceType: string | null = null;
currentEditingRewardId: string | null = null;
+ currentEditingWishItemId: string | null = null;
+ dragSrcWishId: string | null = null;
selectedDate: Date = new Date();
tasksExpanded: boolean = false;
emojis: string[] = [
@@ -126,6 +128,12 @@ class TaskManager {
document.getElementById('cancelRewardBtn')!.addEventListener('click', () => this.closeRewardModal());
document.getElementById('deleteRewardBtn')!.addEventListener('click', () => this.deleteReward());
+ // Wish List section
+ document.getElementById('addWishItemBtn')!.addEventListener('click', () => this.openWishItemModal());
+ document.getElementById('wishItemForm')!.addEventListener('submit', (e) => this.saveWishItem(e));
+ document.getElementById('cancelWishItemBtn')!.addEventListener('click', () => this.closeWishItemModal());
+ document.getElementById('deleteWishItemBtn')!.addEventListener('click', () => this.deleteWishItem());
+
// Modal close buttons
document.querySelectorAll('.close-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
@@ -238,6 +246,8 @@ class TaskManager {
this.renderFinances();
} else if (tabName === 'shop') {
this.renderShop();
+ } else if (tabName === 'wishlist') {
+ this.renderWishList();
} else if (tabName === 'settings') {
this.renderSettings();
}
@@ -1711,6 +1721,142 @@ class TaskManager {
}
}
+ // ========================
+ // Wish List
+ // ========================
+ renderWishList(): void {
+ const items = storage.getWishItems();
+ const container = document.getElementById('wishList')!;
+
+ if (items.length === 0) {
+ container.innerHTML = '
No items in your wish list. Add one to get started!
';
+ return;
+ }
+
+ container.innerHTML = items.map(item => this.renderWishItem(item)).join('');
+
+ container.querySelectorAll
('.wish-item').forEach(el => {
+ el.addEventListener('dragstart', (e) => {
+ this.dragSrcWishId = el.dataset.wishId!;
+ el.classList.add('dragging');
+ e.dataTransfer!.effectAllowed = 'move';
+ });
+ el.addEventListener('dragend', () => {
+ this.dragSrcWishId = null;
+ el.classList.remove('dragging');
+ container.querySelectorAll('.wish-item').forEach(i => i.classList.remove('drag-over'));
+ });
+ el.addEventListener('dragover', (e) => {
+ e.preventDefault();
+ e.dataTransfer!.dropEffect = 'move';
+ container.querySelectorAll('.wish-item').forEach(i => i.classList.remove('drag-over'));
+ el.classList.add('drag-over');
+ });
+ el.addEventListener('drop', (e) => {
+ e.preventDefault();
+ const targetId = el.dataset.wishId!;
+ if (this.dragSrcWishId && this.dragSrcWishId !== targetId) {
+ const allItems = storage.getWishItems();
+ const srcIdx = allItems.findIndex(i => i.id === this.dragSrcWishId);
+ const tgtIdx = allItems.findIndex(i => i.id === targetId);
+ if (srcIdx !== -1 && tgtIdx !== -1) {
+ const reordered = [...allItems];
+ const [moved] = reordered.splice(srcIdx, 1);
+ reordered.splice(tgtIdx, 0, moved);
+ storage.reorderWishItems(reordered.map(i => i.id));
+ this.renderWishList();
+ }
+ }
+ });
+ el.querySelector('.edit-wish-btn')!.addEventListener('click', (e) => {
+ e.stopPropagation();
+ this.openWishItemModal(el.dataset.wishId!);
+ });
+ });
+ }
+
+ renderWishItem(item: WishItem): string {
+ const priceStr = item.price !== undefined && item.price !== null
+ ? `$${Number(item.price).toFixed(2)}`
+ : '';
+ const urlStr = item.url
+ ? `🔗 View Listing`
+ : '';
+ return `
+
+
⠿
+
+
${item.title}
+
+ ${priceStr}
+ ${urlStr}
+
+
+
+
+ `;
+ }
+
+ openWishItemModal(itemId: string | null = null): void {
+ this.currentEditingWishItemId = itemId;
+ const modal = document.getElementById('wishItemModal')!;
+ const form = document.getElementById('wishItemForm') as HTMLFormElement;
+ const deleteBtn = document.getElementById('deleteWishItemBtn') as HTMLElement;
+
+ form.reset();
+ deleteBtn.style.display = 'none';
+
+ document.getElementById('wishItemModalTitle')!.textContent = itemId ? 'Edit Wish List Item' : 'Add Wish List Item';
+
+ if (itemId) {
+ const item = storage.getWishItems().find(w => w.id === itemId);
+ if (item) {
+ (document.getElementById('wishItemTitle') as HTMLInputElement).value = item.title;
+ (document.getElementById('wishItemUrl') as HTMLInputElement).value = item.url || '';
+ (document.getElementById('wishItemPrice') as HTMLInputElement).value =
+ item.price !== undefined && item.price !== null ? String(item.price) : '';
+ deleteBtn.style.display = 'block';
+ }
+ }
+
+ modal.classList.add('active');
+ }
+
+ closeWishItemModal(): void {
+ document.getElementById('wishItemModal')!.classList.remove('active');
+ this.currentEditingWishItemId = null;
+ }
+
+ saveWishItem(e: Event): void {
+ e.preventDefault();
+
+ const title = (document.getElementById('wishItemTitle') as HTMLInputElement).value;
+ const url = (document.getElementById('wishItemUrl') as HTMLInputElement).value.trim() || undefined;
+ const priceVal = (document.getElementById('wishItemPrice') as HTMLInputElement).value;
+ const price = priceVal !== '' ? parseFloat(priceVal) : undefined;
+
+ const item = { title, url, price };
+
+ if (this.currentEditingWishItemId) {
+ storage.updateWishItem(this.currentEditingWishItemId, item);
+ } else {
+ storage.addWishItem(item);
+ }
+
+ this.closeWishItemModal();
+ this.renderWishList();
+ }
+
+ deleteWishItem(): void {
+ if (this.currentEditingWishItemId) {
+ if (confirm('Are you sure you want to delete this wish list item?')) {
+ storage.deleteWishItem(this.currentEditingWishItemId);
+ this.closeWishItemModal();
+ this.renderWishList();
+ }
+ }
+ }
+
// ========================
// Settings
// ========================
diff --git a/src/storage.ts b/src/storage.ts
index d870247..2853b60 100644
--- a/src/storage.ts
+++ b/src/storage.ts
@@ -87,6 +87,15 @@ export interface Purchase {
purchaseDate: string;
}
+export interface WishItem {
+ id: string;
+ title: string;
+ url?: string;
+ price?: number;
+ order: number;
+ createdDate: string;
+}
+
export interface PointsBreakdown {
tasks: number;
projects: number;
@@ -123,6 +132,7 @@ export interface AppData {
categories: string[];
userStats: UserStats;
settings: Settings;
+ wishList: WishItem[];
}
export interface PurchaseResult {
@@ -172,7 +182,8 @@ export class StorageManager {
},
settings: {
tasksPerLevel: 30
- }
+ },
+ wishList: []
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(initialData));
@@ -603,6 +614,58 @@ export class StorageManager {
return data.purchaseHistory || [];
}
+ // Wish List Management
+ addWishItem(item: Partial): WishItem {
+ const data = this.getData();
+ if (!data.wishList) data.wishList = [];
+ const newItem: WishItem = {
+ ...item,
+ id: this.generateId(),
+ createdDate: new Date().toISOString(),
+ title: item.title || '',
+ order: data.wishList.length,
+ };
+ data.wishList.push(newItem);
+ this.saveData(data);
+ return newItem;
+ }
+
+ updateWishItem(itemId: string, updates: Partial): WishItem | undefined {
+ const data = this.getData();
+ if (!data.wishList) data.wishList = [];
+ const item = data.wishList.find(w => w.id === itemId);
+ if (item) {
+ Object.assign(item, updates);
+ this.saveData(data);
+ }
+ return item;
+ }
+
+ deleteWishItem(itemId: string): void {
+ const data = this.getData();
+ if (!data.wishList) data.wishList = [];
+ data.wishList = data.wishList.filter(w => w.id !== itemId);
+ // Re-index order values
+ data.wishList.forEach((w, idx) => { w.order = idx; });
+ this.saveData(data);
+ }
+
+ getWishItems(): WishItem[] {
+ const data = this.getData();
+ if (!data.wishList) return [];
+ return data.wishList.slice().sort((a, b) => a.order - b.order);
+ }
+
+ reorderWishItems(orderedIds: string[]): void {
+ const data = this.getData();
+ if (!data.wishList) return;
+ orderedIds.forEach((id, idx) => {
+ const item = data.wishList.find(w => w.id === id);
+ if (item) item.order = idx;
+ });
+ this.saveData(data);
+ }
+
// Points Management
addPoints(amount: number, source: string): void {
const data = this.getData();
diff --git a/tests/storage.test.ts b/tests/storage.test.ts
index 4d0fade..cb209cf 100644
--- a/tests/storage.test.ts
+++ b/tests/storage.test.ts
@@ -546,6 +546,72 @@ describe('StorageManager', () => {
});
});
+ // ========================
+ // Wish List
+ // ========================
+ describe('wish list management', () => {
+ it('should add a wish item', () => {
+ const item = storage.addWishItem({ title: 'New Laptop', url: 'https://example.com', price: 999.99 });
+ expect(item.id).toBeDefined();
+ expect(item.title).toBe('New Laptop');
+ expect(item.url).toBe('https://example.com');
+ expect(item.price).toBe(999.99);
+ expect(item.order).toBe(0);
+ expect(item.createdDate).toBeDefined();
+ });
+
+ it('should add a wish item with only title', () => {
+ const item = storage.addWishItem({ title: 'Guitar' });
+ expect(item.title).toBe('Guitar');
+ expect(item.url).toBeUndefined();
+ expect(item.price).toBeUndefined();
+ });
+
+ it('should get all wish items sorted by order', () => {
+ storage.addWishItem({ title: 'Item A' });
+ storage.addWishItem({ title: 'Item B' });
+ storage.addWishItem({ title: 'Item C' });
+ const items = storage.getWishItems();
+ expect(items.length).toBe(3);
+ expect(items[0].order).toBeLessThanOrEqual(items[1].order);
+ expect(items[1].order).toBeLessThanOrEqual(items[2].order);
+ });
+
+ it('should update a wish item', () => {
+ const item = storage.addWishItem({ title: 'Old Title', price: 50 });
+ const updated = storage.updateWishItem(item.id, { title: 'New Title', price: 75 });
+ expect(updated?.title).toBe('New Title');
+ expect(updated?.price).toBe(75);
+ });
+
+ it('should return undefined when updating non-existent wish item', () => {
+ const result = storage.updateWishItem('nonexistent', { title: 'Test' });
+ expect(result).toBeUndefined();
+ });
+
+ it('should delete a wish item and re-index order', () => {
+ storage.addWishItem({ title: 'Item A' });
+ const itemB = storage.addWishItem({ title: 'Item B' });
+ storage.addWishItem({ title: 'Item C' });
+ storage.deleteWishItem(itemB.id);
+ const items = storage.getWishItems();
+ expect(items.length).toBe(2);
+ expect(items[0].order).toBe(0);
+ expect(items[1].order).toBe(1);
+ });
+
+ it('should reorder wish items', () => {
+ const a = storage.addWishItem({ title: 'Item A' });
+ const b = storage.addWishItem({ title: 'Item B' });
+ const c = storage.addWishItem({ title: 'Item C' });
+ storage.reorderWishItems([c.id, a.id, b.id]);
+ const items = storage.getWishItems();
+ expect(items[0].title).toBe('Item C');
+ expect(items[1].title).toBe('Item A');
+ expect(items[2].title).toBe('Item B');
+ });
+ });
+
// ========================
// Clear All Data
// ========================