All files / src/store/slices/teacher TeacherThemes.js

100% Statements 55/55
91.66% Branches 22/24
100% Functions 17/17
100% Lines 55/55

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 126 127      7x   7x 3x 3x 1x   2x       7x 2x 2x 1x   1x       7x 2x 2x 1x   1x       7x 3x 3x 1x   2x       7x                             4x     4x 4x     7x 7x 7x 7x       5x 5x       7x 7x     7x   7x 3x   7x     7x 7x       3x 3x     4x   4x 2x   4x     4x 4x       7x 7x     6x 6x 6x 6x     7x 7x            
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { TeacherThemesAPI } from "@/api/teacher/TeacherThemesAPI";
 
const teacherThemesAPI = new TeacherThemesAPI();
 
export const _fetchTeacherTheme = createAsyncThunk("fetch/teacherTheme", async (_, { rejectWithValue }) => {
    try {
        const response = await teacherThemesAPI.getCurrentTheme();
        return response;
    } catch (error) {
        return rejectWithValue(error.response?.data || error.message);
    }
});
 
export const _applyTeacherTheme = createAsyncThunk("apply/teacherTheme", async (themeData, { rejectWithValue }) => {
    try {
        const response = await teacherThemesAPI.applyTheme(themeData);
        return { ...response, themeData };
    } catch (error) {
        return rejectWithValue(error.response?.data || error.message);
    }
});
 
export const _updateTeacherTheme = createAsyncThunk("update/teacherTheme", async (themeUpdate, { rejectWithValue }) => {
    try {
        const response = await teacherThemesAPI.updateTheme(themeUpdate);
        return { ...response, themeUpdate };
    } catch (error) {
        return rejectWithValue(error.response?.data || error.message);
    }
});
 
export const _deleteTeacherTheme = createAsyncThunk("delete/teacherTheme", async (_, { rejectWithValue }) => {
    try {
        const response = await teacherThemesAPI.deleteTheme();
        return response;
    } catch (error) {
        return rejectWithValue(error.response?.data || error.message);
    }
});
 
const TeacherThemes = createSlice({
    name: "TeacherThemes",
    initialState: {
        selectedTheme: null,
        colorMode: null,
        isLoading: false,
        isApplyingTheme: false,
        isUpdatingTheme: false,
        isDeletingTheme: false,
        hasErrors: null,
        applyThemeError: null,
        updateThemeError: null,
        deleteThemeError: null,
    },
    extraReducers: (builder) => {
        builder
            // Fetch Theme
            .addCase(_fetchTeacherTheme.pending, (state) => {
                state.isLoading = true;
                state.hasErrors = null;
            })
            .addCase(_fetchTeacherTheme.fulfilled, (state, action) => {
                state.isLoading = false;
                state.selectedTheme = action.payload.data.theme_details || null;
                state.colorMode = action.payload.data.theme_details?.color_mode || "light";
                state.hasErrors = null;
                // Theme data fetched successfully - will be applied by ThemeContext
            })
            .addCase(_fetchTeacherTheme.rejected, (state, action) => {
                state.isLoading = false;
                state.hasErrors = action.payload?.detail || action.error.message;
            })
            // Apply Theme
            .addCase(_applyTeacherTheme.pending, (state) => {
                state.isApplyingTheme = true;
                state.applyThemeError = null;
            })
            .addCase(_applyTeacherTheme.fulfilled, (state, action) => {
                state.isApplyingTheme = false;
                // Update selected theme if API returns theme details
                if (action.payload.data?.theme_details) {
                    state.selectedTheme = action.payload.data.theme_details;
                }
                state.applyThemeError = null;
            })
            .addCase(_applyTeacherTheme.rejected, (state, action) => {
                state.isApplyingTheme = false;
                state.applyThemeError = action.payload?.detail || action.error.message;
            })
            // Update Theme
            .addCase(_updateTeacherTheme.pending, (state) => {
                state.isUpdatingTheme = true;
                state.updateThemeError = null;
            })
            .addCase(_updateTeacherTheme.fulfilled, (state, action) => {
                state.isUpdatingTheme = false;
                // Update selected theme if API returns theme details
                if (action.payload.data?.theme_details) {
                    state.selectedTheme = action.payload.data.theme_details;
                }
                state.updateThemeError = null;
            })
            .addCase(_updateTeacherTheme.rejected, (state, action) => {
                state.isUpdatingTheme = false;
                state.updateThemeError = action.payload?.detail || action.error.message;
            })
            // Delete Theme — reverts to default (server-side); slice clears local cache so ThemeContext defaults
            .addCase(_deleteTeacherTheme.pending, (state) => {
                state.isDeletingTheme = true;
                state.deleteThemeError = null;
            })
            .addCase(_deleteTeacherTheme.fulfilled, (state) => {
                state.isDeletingTheme = false;
                state.selectedTheme = null;
                state.colorMode = null;
                state.deleteThemeError = null;
            })
            .addCase(_deleteTeacherTheme.rejected, (state, action) => {
                state.isDeletingTheme = false;
                state.deleteThemeError = action.payload?.detail || action.error.message;
            });
    },
});
 
export default TeacherThemes;