From 4caed2aa9eb76267fb77dbea560216beee269b57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 16:49:32 -0500 Subject: [PATCH 1/3] feat(tasks): add localStorage support for task view preference (#1817) Co-authored-by: Mariano Fuentes --- .../[orgId]/tasks/components/TaskList.tsx | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/apps/app/src/app/(app)/[orgId]/tasks/components/TaskList.tsx b/apps/app/src/app/(app)/[orgId]/tasks/components/TaskList.tsx index ab8fa7923..79d23ea54 100644 --- a/apps/app/src/app/(app)/[orgId]/tasks/components/TaskList.tsx +++ b/apps/app/src/app/(app)/[orgId]/tasks/components/TaskList.tsx @@ -7,7 +7,7 @@ import { Check, Circle, FolderTree, List, Plus, XCircle } from 'lucide-react'; import Image from 'next/image'; import { useParams } from 'next/navigation'; import { useQueryState } from 'nuqs'; -import { useMemo, useState } from 'react'; +import { useEffect, useMemo, useRef, useState } from 'react'; import { CreateTaskSheet } from './CreateTaskSheet'; import { ModernTaskList } from './ModernTaskList'; import { SearchInput } from './SearchInput'; @@ -51,7 +51,31 @@ export function TaskList({ const [statusFilter, setStatusFilter] = useQueryState('status'); const [assigneeFilter, setAssigneeFilter] = useQueryState('assignee'); const [createTaskOpen, setCreateTaskOpen] = useQueryState('create-task'); + + // Initialize with default, load from localStorage after hydration const [activeTab, setActiveTab] = useState<'categories' | 'list'>('categories'); + const lastLoadedOrgId = useRef(null); + + // Load saved preference from localStorage after client-side hydration + useEffect(() => { + // Reset and load preference when orgId changes or on initial load + if (lastLoadedOrgId.current !== orgId) { + const saved = localStorage.getItem(`task-view-preference-${orgId}`); + if (saved === 'categories' || saved === 'list') { + setActiveTab(saved); + } else { + // Reset to default if no saved preference exists for this org + setActiveTab('categories'); + } + lastLoadedOrgId.current = orgId; + } + }, [orgId]); + + // Save preference to localStorage when user changes it (not on initial load) + const handleTabChange = (tab: 'categories' | 'list') => { + setActiveTab(tab); + localStorage.setItem(`task-view-preference-${orgId}`, tab); + }; const eligibleAssignees = useMemo(() => { return members @@ -88,7 +112,9 @@ export function TaskList({ // Calculate overall stats from all tasks (not filtered) const overallStats = useMemo(() => { const total = initialTasks.length; - const done = initialTasks.filter((t) => t.status === 'done' || t.status === 'not_relevant').length; + const done = initialTasks.filter( + (t) => t.status === 'done' || t.status === 'not_relevant', + ).length; const inProgress = initialTasks.filter((t) => t.status === 'in_progress').length; const todo = initialTasks.filter((t) => t.status === 'todo').length; const completionRate = total > 0 ? Math.round((done / total) * 100) : 0; @@ -621,7 +647,7 @@ export function TaskList({ {/* View Toggle */}