Scope folder rail counts to the page's visible items

Rail/chip/sheet counts now derive from the same item set the list renders
(archived routines excluded; skills scoped to category/search), per ux-spec
§5.3, instead of raw DB counts.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-15 17:13:24 +00:00
1 parent e82e8c6b15
commit 8fad2a654c
2 files changed
+49 -5

No files matched your search

+26 -2
View File
@@ -4583,6 +4583,30 @@ export function CompanySkills() {
: "Create an editable company skill in the Paperclip workspace.";
const skillFolderResult = skillFoldersQuery.data ?? null;
const showInstalledFolders = isDiscovery && discoveryTab === "installed";
// Rail counts reflect the current category/search scope, never the folder
// filter itself (ux-spec §5.3).
const railSkillFolderResult = useMemo(() => {
if (!skillFolderResult || discoveryTab !== "installed") return skillFolderResult;
const scoped = discoveryTabCards.filter((card) => {
if (discoveryCategory && !card.categories.includes(discoveryCategory)) return false;
return discoveryMatchesSearch(card, discoverySearch.trim());
});
const counts = new Map<string, number>();
let unfiled = 0;
for (const card of scoped) {
if (card.folderId) counts.set(card.folderId, (counts.get(card.folderId) ?? 0) + 1);
else unfiled += 1;
}
return {
...skillFolderResult,
allCount: scoped.length,
unfiledCount: unfiled,
folders: skillFolderResult.folders.map((folder) => ({
...folder,
itemCount: counts.get(folder.id) ?? 0,
})),
};
}, [skillFolderResult, discoveryTab, discoveryTabCards, discoveryCategory, discoverySearch]);
return (
<>
@@ -4777,7 +4801,7 @@ export function CompanySkills() {
<MobileFolderSheet
open={mobileFoldersOpen}
onOpenChange={setMobileFoldersOpen}
result={skillFolderResult}
result={railSkillFolderResult}
selection={folderSelection}
allLabel="All skills"
itemLabelPlural="Skills"
@@ -4840,7 +4864,7 @@ export function CompanySkills() {
onScan={() => scanProjects.mutate()}
scanPending={scanProjects.isPending}
scanStatus={scanStatusMessage}
folderResult={showInstalledFolders ? skillFolderResult : null}
folderResult={showInstalledFolders ? railSkillFolderResult : null}
folderSelection={folderSelection}
foldersLoading={skillFoldersQuery.isLoading}
selectMode={showInstalledFolders && selectMode}
+23 -3
View File
@@ -604,6 +604,26 @@ export function Routines() {
if (folderSelection === "unfiled") return visibleRoutines.filter((routine) => !routine.folderId);
return visibleRoutines.filter((routine) => routine.folderId === folderSelection);
}, [folderSelection, routineViewState.groupBy, visibleRoutines]);
// Rail counts reflect the page's visible scope (archived hidden), not raw DB
// counts (ux-spec §5.3).
const railFolderResult = useMemo(() => {
if (!routineFolders) return routineFolders;
const counts = new Map<string, number>();
let unfiled = 0;
for (const routine of visibleRoutines) {
if (routine.folderId) counts.set(routine.folderId, (counts.get(routine.folderId) ?? 0) + 1);
else unfiled += 1;
}
return {
...routineFolders,
allCount: visibleRoutines.length,
unfiledCount: unfiled,
folders: routineFolders.folders.map((folder) => ({
...folder,
itemCount: counts.get(folder.id) ?? 0,
})),
};
}, [routineFolders, visibleRoutines]);
const sortedRoutines = useMemo(
() => sortRoutines(folderFilteredRoutines, routineViewState.sortField, routineViewState.sortDir),
[folderFilteredRoutines, routineViewState.sortDir, routineViewState.sortField],
@@ -834,7 +854,7 @@ export function Routines() {
{routineViewState.groupBy === "folder" ? (
<div className="md:hidden">
<FolderChip
result={routineFolders}
result={railFolderResult}
selection={folderSelection}
allLabel="All routines"
onClick={() => setMobileFoldersOpen(true)}
@@ -1144,7 +1164,7 @@ export function Routines() {
<div className={cn(showFolderRail && "flex gap-4")}>
{showFolderRail ? (
<FolderRail
result={routineFolders}
result={railFolderResult}
selection={folderSelection}
allLabel="All routines"
itemLabelPlural="routines"
@@ -1320,7 +1340,7 @@ export function Routines() {
<MobileFolderSheet
open={mobileFoldersOpen}
onOpenChange={setMobileFoldersOpen}
result={routineFolders}
result={railFolderResult}
selection={folderSelection}
allLabel="All routines"
itemLabelPlural="Routines"