From da7a0a01aed2ea38b05b4ea99bd5a4ec9e473e3d Mon Sep 17 00:00:00 2001 From: Forgotten Date: Fri, 27 Feb 2026 13:00:39 -0600 Subject: [PATCH] fix(ui): default issue filter to 'all' for new companies Previously, new companies with no saved view state defaulted to showing only 'Active' issues (todo, in_progress, in_review, blocked). This changes the default to show all issues, which is more useful when a company has few issues. Co-Authored-By: Claude Opus 4.6 --- ui/src/components/IssuesList.tsx | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/ui/src/components/IssuesList.tsx b/ui/src/components/IssuesList.tsx index 87fa148a..97c28899 100644 --- a/ui/src/components/IssuesList.tsx +++ b/ui/src/components/IssuesList.tsx @@ -1,5 +1,5 @@ -import { useDeferredValue, useMemo, useState, useCallback } from "react"; -import { Link } from "react-router-dom"; +import { useEffect, useDeferredValue, useMemo, useState, useCallback, useRef } from "react"; +import { Link } from "@/lib/router"; import { useQuery } from "@tanstack/react-query"; import { useDialog } from "../context/DialogContext"; import { useCompany } from "../context/CompanyContext"; @@ -11,6 +11,7 @@ import { StatusIcon } from "./StatusIcon"; import { PriorityIcon } from "./PriorityIcon"; import { EmptyState } from "./EmptyState"; import { Identity } from "./Identity"; +import { PageSkeleton } from "./PageSkeleton"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover"; @@ -44,7 +45,7 @@ export type IssueViewState = { }; const defaultViewState: IssueViewState = { - statuses: ["todo", "in_progress", "in_review", "blocked"], + statuses: [], priorities: [], assignees: [], labels: [], @@ -158,11 +159,14 @@ export function IssuesList({ const { selectedCompanyId } = useCompany(); const { openNewIssue } = useDialog(); + // Scope the storage key per company so folding/view state is independent across companies. + const scopedKey = selectedCompanyId ? `${viewStateKey}:${selectedCompanyId}` : viewStateKey; + const [viewState, setViewState] = useState(() => { if (initialAssignees) { return { ...defaultViewState, assignees: initialAssignees, statuses: [] }; } - return getViewState(viewStateKey); + return getViewState(scopedKey); }); const [assigneePickerIssueId, setAssigneePickerIssueId] = useState(null); const [assigneeSearch, setAssigneeSearch] = useState(""); @@ -170,13 +174,24 @@ export function IssuesList({ const deferredIssueSearch = useDeferredValue(issueSearch); const normalizedIssueSearch = deferredIssueSearch.trim(); + // Reload view state from localStorage when company changes (scopedKey changes). + const prevScopedKey = useRef(scopedKey); + useEffect(() => { + if (prevScopedKey.current !== scopedKey) { + prevScopedKey.current = scopedKey; + setViewState(initialAssignees + ? { ...defaultViewState, assignees: initialAssignees, statuses: [] } + : getViewState(scopedKey)); + } + }, [scopedKey, initialAssignees]); + const updateView = useCallback((patch: Partial) => { setViewState((prev) => { const next = { ...prev, ...patch }; - saveViewState(viewStateKey, next); + saveViewState(scopedKey, next); return next; }); - }, [viewStateKey]); + }, [scopedKey]); const { data: searchedIssues = [] } = useQuery({ queryKey: queryKeys.issues.search(selectedCompanyId!, normalizedIssueSearch, projectId), @@ -505,7 +520,7 @@ export function IssuesList({ - {isLoading &&

Loading...

} + {isLoading && } {error &&

{error.message}

} {!isLoading && filtered.length === 0 && viewState.viewMode === "list" && (