diff --git a/package.json b/package.json index f44305f..848539e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "my-weekly-todo-list", - "version": "1.27.1", + "version": "1.27.2", "description": "A web-based weekly task management application that organizes to-dos and calendar events in a single, intuitive weekly view", "main": "index.js", "scripts": { diff --git a/src/components/WeeklyView.tsx b/src/components/WeeklyView.tsx index e1547da..355da9b 100644 --- a/src/components/WeeklyView.tsx +++ b/src/components/WeeklyView.tsx @@ -1471,19 +1471,30 @@ export default function WeeklyView() { const [creatingNewTab, setCreatingNewTab] = useState(false); const [creatingNewTabName, setCreatingNewTabName] = useState(""); const [dragOverTab, setDragOverTab] = useState(null); + const [customTabs, setCustomTabs] = useState([]); useEffect(() => { if (typeof window !== "undefined") { const saved = localStorage.getItem("weekly_active_someday_tab"); if (saved) setActiveSomedayTab(saved === "__all__" ? null : saved); + try { + const savedTabs = localStorage.getItem("weekly_custom_tabs"); + if (savedTabs) setCustomTabs(JSON.parse(savedTabs)); + } catch { /* ignore */ } } }, []); + const saveCustomTabs = (tabs: string[]) => { + setCustomTabs(tabs); + localStorage.setItem("weekly_custom_tabs", JSON.stringify(tabs)); + }; + const somedayTabs = useMemo(() => { const tabs = new Set(); somedayLists.forEach(l => { if (l.tab) tabs.add(l.tab); }); + customTabs.forEach(t => tabs.add(t)); return Array.from(tabs).sort(); - }, [somedayLists]); + }, [somedayLists, customTabs]); const setSomedayTab = (tab: string | null) => { setActiveSomedayTab(tab); @@ -1505,15 +1516,19 @@ export default function WeeklyView() { const renameTab = async (oldName: string, newName: string) => { if (!newName.trim() || newName === oldName) return; + const trimmed = newName.trim(); const listsToUpdate = somedayLists.filter(l => l.tab === oldName); - setSomedayLists(prev => prev.map(l => l.tab === oldName ? { ...l, tab: newName.trim() } : l)); - if (activeSomedayTab === oldName) setSomedayTab(newName.trim()); + setSomedayLists(prev => prev.map(l => l.tab === oldName ? { ...l, tab: trimmed } : l)); + if (customTabs.includes(oldName)) { + saveCustomTabs(customTabs.map(t => t === oldName ? trimmed : t)); + } + if (activeSomedayTab === oldName) setSomedayTab(trimmed); for (const list of listsToUpdate) { try { await fetch("/api/someday-lists", { method: "PATCH", headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ id: list.id, tab: newName.trim() }), + body: JSON.stringify({ id: list.id, tab: trimmed }), }); } catch (e) { console.error("Failed to rename tab for list:", e); @@ -1524,6 +1539,9 @@ export default function WeeklyView() { const dissolveTab = async (tabName: string) => { const listsToUpdate = somedayLists.filter(l => l.tab === tabName); setSomedayLists(prev => prev.map(l => l.tab === tabName ? { ...l, tab: null } : l)); + if (customTabs.includes(tabName)) { + saveCustomTabs(customTabs.filter(t => t !== tabName)); + } if (activeSomedayTab === tabName) setSomedayTab(null); for (const list of listsToUpdate) { try { @@ -6425,8 +6443,12 @@ export default function WeeklyView() { value={creatingNewTabName} onChange={(e) => setCreatingNewTabName(e.target.value)} onBlur={() => { - if (creatingNewTabName.trim()) { - setSomedayTab(creatingNewTabName.trim()); + const name = creatingNewTabName.trim(); + if (name && !somedayTabs.includes(name)) { + saveCustomTabs([...customTabs, name]); + setSomedayTab(name); + } else if (name) { + setSomedayTab(name); } setCreatingNewTab(false); }} @@ -6806,7 +6828,7 @@ export default function WeeklyView() { ) : iconContent; })()}
- +