All files / web/src/providers skill-optimization-arms.tsx

95.77% Statements 68/71
100% Branches 17/17
100% Functions 5/5
95.77% Lines 68/71

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 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125      1x 1x 1x   1x                 1x 1x 1x 1x 25x 1x                                         1x   1x 23x 23x   23x 23x 23x   23x 23x     23x 23x 23x 23x 23x 23x 23x 23x 23x 23x     23x 23x 2x 23x     23x 23x 3x 23x     23x 23x 2x 2x 23x 23x   23x       23x   23x   23x 23x 23x 23x 23x     23x 23x 23x 23x     23x 23x 23x   23x 23x   23x   1x 25x 25x 2x 2x 23x 23x  
'use client';
 
import type { SkillOptimizationArm } from '@shared/types/data/skill-optimization-arm';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { getSkillArms } from '@web/api/v1/super-agents/skills';
import { useNavigation } from '@web/providers/navigation';
import type React from 'react';
import {
  createContext,
  useCallback,
  useContext,
  useMemo,
  useState,
} from 'react';
 
// Query keys for React Query caching
export const armQueryKeys = {
  all: ['skillOptimizationArms'] as const,
  lists: () => [...armQueryKeys.all, 'list'] as const,
  list: (skillId: string | null, clusterId: string | null) =>
    [...armQueryKeys.lists(), skillId, clusterId] as const,
};
 
interface ArmsContextType {
  // Query state
  arms: SkillOptimizationArm[];
  selectedArm?: SkillOptimizationArm;
  isLoading: boolean;
  error: Error | null;
  refetch: () => void;
 
  // Skill and Cluster IDs
  skillId: string | null;
  clusterId: string | null;
  setSkillId: (skillId: string | null) => void;
  setClusterId: (clusterId: string | null) => void;
 
  // Helper functions
  getArmById: (id: string) => SkillOptimizationArm | undefined;
  refreshArms: () => void;
}
 
const ArmsContext = createContext<ArmsContextType | undefined>(undefined);
 
export const SkillOptimizationArmsProvider = ({
  children,
}: {
  children: React.ReactNode;
}): React.ReactElement => {
  const queryClient = useQueryClient();
  const { navigationState } = useNavigation();
 
  const [skillId, setSkillId] = useState<string | null>(null);
  const [clusterId, setClusterId] = useState<string | null>(null);
 
  // Arms query
  const {
    data: allArms = [],
    isLoading,
    error,
    refetch,
  } = useQuery({
    queryKey: armQueryKeys.list(skillId, clusterId),
    queryFn: () => getSkillArms(skillId!),
    enabled: !!skillId, // Only fetch when we have skillId
  });
 
  // Filter arms by clusterId if specified
  const arms = useMemo(() => {
    if (!clusterId) return allArms;
    return allArms.filter((arm) => arm.cluster_id === clusterId);
  }, [allArms, clusterId]);
 
  // Resolve selectedArm from navigationState.selectedArmName
  const selectedArm = useMemo(() => {
    if (!navigationState.selectedArmName) return undefined;
    return arms.find((arm) => arm.name === navigationState.selectedArmName);
  }, [navigationState.selectedArmName, arms]);
 
  // Helper functions
  const getArmById = useCallback(
    (id: string): SkillOptimizationArm | undefined => {
      return arms?.find((arm: SkillOptimizationArm) => arm.id === id);
    },
    [arms],
  );
 
  const refreshArms = useCallback(() => {
    queryClient.invalidateQueries({
      queryKey: armQueryKeys.all,
    });
  }, [queryClient]);
 
  const contextValue: ArmsContextType = {
    // Query state
    arms,
    selectedArm,
    isLoading,
    error,
    refetch,
 
    // Skill and Cluster IDs
    skillId,
    clusterId,
    setSkillId,
    setClusterId,
 
    // Helper functions
    getArmById,
    refreshArms,
  };
 
  return (
    <ArmsContext.Provider value={contextValue}>{children}</ArmsContext.Provider>
  );
};
 
export const useSkillOptimizationArms = (): ArmsContextType => {
  const context = useContext(ArmsContext);
  if (!context) {
    throw new Error('useArms must be used within an ArmsProvider');
  }
  return context;
};