diff --git a/css/styles.css b/css/styles.css index 4fa700d..04170f3 100644 --- a/css/styles.css +++ b/css/styles.css @@ -1624,12 +1624,54 @@ html, body { border-bottom: 1px solid var(--border-color, #e0e0e0); } +.wish-list-group-title { + display: flex; + align-items: center; + gap: 0.5rem; +} + .wish-list-group-name { font-weight: 700; font-size: 1rem; color: var(--text-primary, #333); } +.wish-list-group-counter { + font-size: 0.75rem; + font-weight: 600; + color: var(--text-secondary, #666); + background: var(--bg-tertiary, #e8e8e8); + padding: 0.15rem 0.5rem; + border-radius: 999px; + white-space: nowrap; +} + +.wish-list-collapse-btn { + background: none; + border: none; + padding: 0.15rem 0.35rem; + cursor: pointer; + color: var(--text-secondary, #666); + font-size: 0.75rem; + line-height: 1; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; +} + +.wish-list-collapse-btn:hover { + background: var(--border-color, #e0e0e0); +} + +.wish-list-group.collapsed .wish-list { + display: none; +} + +.wish-list-group.collapsed .wish-list-group-header { + border-bottom: none; +} + .wish-list-group-actions { display: flex; gap: 0.5rem; diff --git a/src/app.ts b/src/app.ts index a112a84..41ebee1 100644 --- a/src/app.ts +++ b/src/app.ts @@ -28,6 +28,7 @@ class TaskManager { currentEditingNoteId: string | null = null; currentEditingShoppingItemId: string | null = null; dragSrcWishId: string | null = null; + expandedWishLists: Set = new Set(); selectedDate: Date = new Date(); tasksExpanded: boolean = false; hideCompleted: boolean = false; @@ -1889,13 +1890,14 @@ class TaskManager { // Render each named list group lists.forEach(list => { const listItems = allItems.filter(i => i.listId === list.id); - html += this.renderWishListGroup(list.id, list.name, listItems, true); + const isExpanded = this.expandedWishLists.has(list.id); + html += this.renderWishListGroup(list.id, list.name, listItems, true, isExpanded); }); // Render uncategorized items (no listId or listId is null) const uncategorized = allItems.filter(i => !i.listId); if (uncategorized.length > 0 || lists.length === 0) { - html += this.renderWishListGroup(null, 'Uncategorized', uncategorized, false); + html += this.renderWishListGroup(null, 'Uncategorized', uncategorized, false, true); } container.innerHTML = html; @@ -1914,6 +1916,19 @@ class TaskManager { if (editBtn) { editBtn.addEventListener('click', () => this.openWishListModal(list.id)); } + const collapseBtn = groupEl.querySelector('.wish-list-collapse-btn'); + if (collapseBtn) { + collapseBtn.addEventListener('click', () => { + const isNowCollapsed = groupEl.classList.toggle('collapsed'); + if (isNowCollapsed) { + this.expandedWishLists.delete(list.id); + } else { + this.expandedWishLists.add(list.id); + } + const icon = collapseBtn.querySelector('.wish-list-collapse-icon'); + if (icon) icon.textContent = isNowCollapsed ? '▶' : '▼'; + }); + } } }); @@ -1929,18 +1944,29 @@ class TaskManager { } } - renderWishListGroup(listId: string | null, name: string, items: WishItem[], hasEditBtn: boolean): string { + renderWishListGroup(listId: string | null, name: string, items: WishItem[], hasEditBtn: boolean, isExpanded: boolean = true): string { const dataAttr = listId ? `data-list-id="${listId}"` : 'data-list-id="uncategorized"'; const editBtnHtml = hasEditBtn ? `` : ''; + const unpurchasedCount = items.filter(i => !i.completed).length; + const counterHtml = `${unpurchasedCount} remaining`; + const collapsedClass = !isExpanded ? ' collapsed' : ''; + const toggleIcon = isExpanded ? '▼' : '▶'; + const toggleBtnHtml = hasEditBtn + ? `` + : ''; const itemsHtml = items.length > 0 ? items.map(item => this.renderWishItem(item)).join('') : `

No items yet. Click "+ Add" to add one.

`; return ` -
+
- ${name} +
+ ${toggleBtnHtml} + ${name} + ${counterHtml} +
${editBtnHtml}