fix(allocations): expand grouped rows by default
This commit is contained in:
@@ -22,6 +22,13 @@ import { useViewPrefs } from "~/hooks/useViewPrefs.js";
|
||||
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
|
||||
import { ALLOCATION_STATUS_BADGE as STATUS_BADGE } from "~/lib/status-styles.js";
|
||||
import { SuccessToast } from "~/components/ui/SuccessToast.js";
|
||||
import {
|
||||
collapseAllAllocationGroups,
|
||||
createInitialCollapsedAllocationGroups,
|
||||
expandAllAllocationGroups,
|
||||
toggleCollapsedAllocationGroup,
|
||||
type CollapsedAllocationGroups,
|
||||
} from "./allocationGroupState.js";
|
||||
|
||||
/** Left-border color by allocation status for instant visual scanning */
|
||||
const STATUS_LEFT_BORDER: Record<string, string> = {
|
||||
@@ -190,7 +197,9 @@ export function AllocationsClient() {
|
||||
if (typeof window === "undefined") return "grouped";
|
||||
return (localStorage.getItem("capakraken:allocations:viewMode") as "grouped" | "flat") ?? "grouped";
|
||||
});
|
||||
const [collapsedGroups, setCollapsedGroups] = useState<Set<string> | "all">("all");
|
||||
const [collapsedGroups, setCollapsedGroups] = useState<CollapsedAllocationGroups>(
|
||||
() => createInitialCollapsedAllocationGroups(),
|
||||
);
|
||||
// Track expanded project sub-groups: key = "resourceId::projectId"
|
||||
const [expandedSubGroups, setExpandedSubGroups] = useState<Set<string>>(new Set());
|
||||
|
||||
@@ -293,26 +302,15 @@ export function AllocationsClient() {
|
||||
const groupIds = useMemo(() => groups.map((g) => g.resourceId), [groups]);
|
||||
|
||||
const toggleGroup = useCallback((resourceId: string) => {
|
||||
setCollapsedGroups((prev) => {
|
||||
// "all" → expand just this one (materialize all IDs minus clicked)
|
||||
if (prev === "all") {
|
||||
const next = new Set(groupIds);
|
||||
next.delete(resourceId);
|
||||
return next;
|
||||
}
|
||||
const next = new Set(prev);
|
||||
if (next.has(resourceId)) next.delete(resourceId);
|
||||
else next.add(resourceId);
|
||||
return next;
|
||||
});
|
||||
setCollapsedGroups((prev) => toggleCollapsedAllocationGroup(prev, groupIds, resourceId));
|
||||
}, [groupIds]);
|
||||
|
||||
const collapseAll = useCallback(() => {
|
||||
setCollapsedGroups("all");
|
||||
setCollapsedGroups(collapseAllAllocationGroups());
|
||||
}, []);
|
||||
|
||||
const expandAll = useCallback(() => {
|
||||
setCollapsedGroups(new Set());
|
||||
setCollapsedGroups(expandAllAllocationGroups());
|
||||
}, []);
|
||||
|
||||
const toggleSubGroup = useCallback((resourceId: string, projectId: string) => {
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
collapseAllAllocationGroups,
|
||||
createInitialCollapsedAllocationGroups,
|
||||
expandAllAllocationGroups,
|
||||
toggleCollapsedAllocationGroup,
|
||||
} from "./allocationGroupState.js";
|
||||
|
||||
describe("allocationGroupState", () => {
|
||||
it("starts grouped allocations expanded so rows are visible on first load", () => {
|
||||
const initial = createInitialCollapsedAllocationGroups();
|
||||
|
||||
expect(initial).toBeInstanceOf(Set);
|
||||
expect([...initial]).toEqual([]);
|
||||
});
|
||||
|
||||
it("collapses and re-expands a single group from the expanded default", () => {
|
||||
const collapsed = toggleCollapsedAllocationGroup(createInitialCollapsedAllocationGroups(), ["r1", "r2"], "r1");
|
||||
expect(collapsed).toBeInstanceOf(Set);
|
||||
expect([...(collapsed as Set<string>)]).toEqual(["r1"]);
|
||||
|
||||
const expandedAgain = toggleCollapsedAllocationGroup(collapsed, ["r1", "r2"], "r1");
|
||||
expect(expandedAgain).toBeInstanceOf(Set);
|
||||
expect([...(expandedAgain as Set<string>)]).toEqual([]);
|
||||
});
|
||||
|
||||
it("keeps collapse-all behavior available for bulk controls", () => {
|
||||
expect(collapseAllAllocationGroups()).toBe("all");
|
||||
|
||||
const expandedOnlyR2 = toggleCollapsedAllocationGroup("all", ["r1", "r2"], "r2");
|
||||
expect(expandedOnlyR2).toBeInstanceOf(Set);
|
||||
expect([...(expandedOnlyR2 as Set<string>)].sort()).toEqual(["r1"]);
|
||||
|
||||
const expandedAll = expandAllAllocationGroups();
|
||||
expect(expandedAll).toBeInstanceOf(Set);
|
||||
expect([...(expandedAll as Set<string>)]).toEqual([]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
export type CollapsedAllocationGroups = Set<string> | "all";
|
||||
|
||||
export function createInitialCollapsedAllocationGroups(): CollapsedAllocationGroups {
|
||||
return new Set<string>();
|
||||
}
|
||||
|
||||
export function toggleCollapsedAllocationGroup(
|
||||
previous: CollapsedAllocationGroups,
|
||||
groupIds: string[],
|
||||
resourceId: string,
|
||||
): CollapsedAllocationGroups {
|
||||
if (previous === "all") {
|
||||
const next = new Set(groupIds);
|
||||
next.delete(resourceId);
|
||||
return next;
|
||||
}
|
||||
|
||||
const next = new Set(previous);
|
||||
if (next.has(resourceId)) {
|
||||
next.delete(resourceId);
|
||||
} else {
|
||||
next.add(resourceId);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
export function collapseAllAllocationGroups(): CollapsedAllocationGroups {
|
||||
return "all";
|
||||
}
|
||||
|
||||
export function expandAllAllocationGroups(): CollapsedAllocationGroups {
|
||||
return new Set<string>();
|
||||
}
|
||||
Reference in New Issue
Block a user