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 | 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 8x 8x 8x 8x 8x 8x 8x 8x 8x 1x 1x 1x 1x 3x 3x 3x 3x 1x 3x 1x 3x 1x 2x 2x 2x | import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { StudentFeaturesAPI } from "@/api/student/StudentFeaturesAPI";
import { normalizeFeatureList } from "@/utils/features/featureAccess";
// Async thunk to fetch student's district features
export const fetchStudentDistrictFeatures = createAsyncThunk(
"student/features/fetchDistrictFeatures",
async (_, { rejectWithValue }) => {
try {
const response = await StudentFeaturesAPI.getEffectiveFeatures();
return response;
} catch (error) {
return rejectWithValue(error.response?.data || error);
}
}
);
export const fetchStudentOrganization = createAsyncThunk(
"student/features/fetchOrganization",
async (_, { rejectWithValue }) => {
try {
const response = await StudentFeaturesAPI.getOrganization();
return response;
} catch (error) {
return rejectWithValue(error.response?.data || error);
}
}
);
const StudentFeatureFlags = createSlice({
name: "StudentFeatureFlags",
initialState: {
districtId: null,
currentPlan: null,
planName: null,
districtFeatures: [],
maintenanceMode: false,
organization: null,
organizationLoading: false,
organizationError: null,
isLoading: false,
hasErrors: null,
lastFetched: null,
},
reducers: {
clearErrors: (state) => {
state.hasErrors = null;
},
resetFeatures: (state) => {
state.districtId = null;
state.currentPlan = null;
state.planName = null;
state.districtFeatures = [];
state.maintenanceMode = false;
state.organization = null;
state.organizationError = null;
state.lastFetched = null;
},
},
extraReducers: (builder) => {
builder
.addCase(fetchStudentDistrictFeatures.pending, (state) => {
state.isLoading = true;
state.hasErrors = null;
})
.addCase(fetchStudentDistrictFeatures.fulfilled, (state, action) => {
const payload = action.payload || {};
state.isLoading = false;
state.districtId = payload.district_id ?? null;
state.currentPlan = payload.current_plan ?? null;
state.planName = payload.plan_name ?? null;
state.districtFeatures = normalizeFeatureList(payload.features || payload.results || []);
state.maintenanceMode = Boolean(payload.maintenance_mode);
state.lastFetched = new Date().toISOString();
state.hasErrors = null;
})
.addCase(fetchStudentDistrictFeatures.rejected, (state, action) => {
state.isLoading = false;
state.hasErrors = action.payload?.detail || action.error.message;
})
.addCase(fetchStudentOrganization.pending, (state) => {
state.organizationLoading = true;
state.organizationError = null;
})
.addCase(fetchStudentOrganization.fulfilled, (state, action) => {
state.organizationLoading = false;
state.organization = action.payload || null;
state.organizationError = null;
if (action.payload?.district_id) {
state.districtId = action.payload.district_id;
}
if (action.payload?.current_plan) {
state.currentPlan = action.payload.current_plan;
}
if (action.payload?.plan_name) {
state.planName = action.payload.plan_name;
}
})
.addCase(fetchStudentOrganization.rejected, (state, action) => {
state.organizationLoading = false;
state.organizationError = action.payload?.detail || action.error.message;
});
},
});
export const { clearErrors, resetFeatures } = StudentFeatureFlags.actions;
export default StudentFeatureFlags;
|