All files / src/utils/hooks useFeatureFlag.js

100% Statements 34/34
100% Branches 36/36
100% Functions 12/12
100% Lines 31/31

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            18x   18x 388x 9x     18x 194x 194x 254x   194x                       18x 194x 194x 194x 194x   194x 198x 196x     194x   194x                   18x 2x 2x 3x           18x 2x 2x 4x           18x 2x 2x 3x              
import { useSelector } from "react-redux";
import {
    getFeatureMeta as getFeatureMetaFromList,
    isFeatureEnabled as isEnabledFromList,
} from "@/utils/features/featureAccess";
 
const DEFAULT_USER_TYPE = "teacher";
 
const resolveUserType = (value) => {
    if (value === "teacher" || value === "student") return value;
    return DEFAULT_USER_TYPE;
};
 
const useFeatureState = (userType) => {
    const scopedUserType = resolveUserType(userType);
    const state = useSelector((rootState) =>
        scopedUserType === "student" ? rootState.StudentFeatureFlags : rootState.TeacherFeatureFlags
    );
    return {
        userType: scopedUserType,
        features: state?.districtFeatures ?? [],
        loading: state?.isLoading ?? false,
        error: state?.hasErrors ?? null,
        currentPlan: state?.currentPlan ?? null,
        planName: state?.planName ?? null,
        districtId: state?.districtId ?? null,
        maintenanceMode: state?.maintenanceMode ?? false,
    };
};
 
export const useFeatureFlag = (featureOrUserType, _districtId, explicitUserType) => {
    const hasFeatureKey = typeof featureOrUserType === "string" && !["teacher", "student"].includes(featureOrUserType);
    const userType = hasFeatureKey ? resolveUserType(explicitUserType) : resolveUserType(featureOrUserType);
    const featureKey = hasFeatureKey ? featureOrUserType : null;
    const state = useFeatureState(userType);
 
    const isFeatureEnabled = (key) => {
        if (state.error) return true;
        return isEnabledFromList(state.features, key);
    };
 
    const getFeature = (key) => getFeatureMetaFromList(state.features, key);
 
    return {
        ...state,
        isLoading: state.loading,
        isEnabled: featureKey ? isFeatureEnabled(featureKey) : false,
        isFeatureEnabled,
        getFeature,
        features: state.features,
    };
};
 
export const useMultipleFeatureFlags = (features = [], _districtId, userType = DEFAULT_USER_TYPE) => {
    const featureFlag = useFeatureFlag(userType);
    return {
        features: Object.fromEntries(features.map((feature) => [feature, featureFlag.isFeatureEnabled(feature)])),
        loading: featureFlag.loading,
        error: featureFlag.error,
    };
};
 
export const useAnyFeatureFlag = (features = [], _districtId, userType = DEFAULT_USER_TYPE) => {
    const featureFlag = useFeatureFlag(userType);
    return {
        isAnyEnabled: features.some((feature) => featureFlag.isFeatureEnabled(feature)),
        loading: featureFlag.loading,
        error: featureFlag.error,
    };
};
 
export const useAllFeatureFlags = (features = [], _districtId, userType = DEFAULT_USER_TYPE) => {
    const featureFlag = useFeatureFlag(userType);
    return {
        areAllEnabled: features.every((feature) => featureFlag.isFeatureEnabled(feature)),
        loading: featureFlag.loading,
        error: featureFlag.error,
    };
};
 
export default useFeatureFlag;