All files / src/components/lists useGroupByStatus.ts

96% Statements 24/25
100% Branches 5/5
100% Functions 7/7
96% Lines 24/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73        12x       156x 156x               59x 59x                                             243x 243x 243x   243x 59x 59x 59x 59x 51x 51x       243x 32x 32x 32x 32x 32x       243x 90x         243x    
import { useState } from "react";
 
/** localStorage key for the group-by-status toggle (separate from WorkspaceList's
 *  "grackle-group-by-status" key — each view has its own grouping preference). */
const STORAGE_KEY_GROUP_BY_STATUS: string = "grackle-task-group-by-status";
 
/** Read the persisted group-by-status preference. */
function getGroupByStatus(): boolean {
  try {
    return localStorage.getItem(STORAGE_KEY_GROUP_BY_STATUS) === "true";
  } catch {
    return false;
  }
}
 
/** Persist the group-by-status preference. */
function saveGroupByStatus(value: boolean): void {
  try {
    localStorage.setItem(STORAGE_KEY_GROUP_BY_STATUS, String(value));
  } catch {
    /* localStorage unavailable */
  }
}
 
/** Return type of the useGroupByStatus hook. */
export interface UseGroupByStatusResult {
  /** Whether tasks are grouped by status (vs. flat tree). */
  groupByStatus: boolean;
  /** Toggle the group-by-status mode and persist the preference. */
  toggleGroupByStatus: () => void;
  /** Whether a given status group accordion is expanded. */
  isGroupExpanded: (status: string) => boolean;
  /** Toggle a single status group accordion's expanded state. */
  toggleStatusGroup: (status: string) => void;
}
 
/**
 * Manages the group-by-status toggle and per-group accordion expansion state
 * for the task list sidebar. The toggle preference is persisted to localStorage.
 */
export function useGroupByStatus(): UseGroupByStatusResult {
  const [groupByStatus, setGroupByStatusState] = useState(getGroupByStatus);
  const [groupExpandDefault, setGroupExpandDefault] = useState(getGroupByStatus);
  const [groupExpandOverrides, setGroupExpandOverrides] = useState<Map<string, boolean>>(new Map());
 
  const toggleGroupByStatus = (): void => {
    const next = !groupByStatus;
    saveGroupByStatus(next);
    setGroupByStatusState(next);
    if (next) {
      setGroupExpandDefault(true);
      setGroupExpandOverrides(new Map());
    }
  };
 
  const toggleStatusGroup = (status: string): void => {
    setGroupExpandOverrides((prev) => {
      const next = new Map(prev);
      const current = next.has(status) ? next.get(status)! : groupExpandDefault;
      next.set(status, !current);
      return next;
    });
  };
 
  const isGroupExpanded = (status: string): boolean => {
    return groupExpandOverrides.has(status)
      ? groupExpandOverrides.get(status)!
      : groupExpandDefault;
  };
 
  return { groupByStatus, toggleGroupByStatus, isGroupExpanded, toggleStatusGroup };
}