bulk-email/src/redux/slices/roleSlice.ts
2025-02-28 16:24:40 +05:30

194 lines
4.6 KiB
TypeScript

import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios";
import http from "../../lib/https";
import { toast } from "sonner";
// Define TypeScript types
interface Role {
id: string;
name: string;
resource: {
moduleName: string;
moduleId: string;
permissions: string[];
}[];
status: number;
}
interface RoleState {
roles: Role[];
loading: boolean;
error: string | null;
}
// Initial state
const initialState: RoleState = {
roles: [],
loading: false,
error: null,
};
export const roleList = createAsyncThunk<any, void, { rejectValue: string }>(
"fetchRoles",
async (_, { rejectWithValue }) => {
try {
const token = localStorage?.getItem("authToken");
if (!token) throw new Error("No token found");
const response = await http.get("get");
if (!response.data) throw new Error("Invalid API response");
// Return the full response to handle in the reducer
return response.data;
} catch (error: any) {
toast.error("Error Fetching Roles: " + error.message);
return rejectWithValue(
error?.response?.data?.message || "An error occurred"
);
}
}
);
// Create Role
export const createRole = createAsyncThunk<
any,
{
name: string;
resource: {
moduleName: string;
moduleId: string;
permissions: string[];
}[];
},
{ rejectValue: string }
>("role/createRole", async (data, { rejectWithValue }) => {
try {
const response = await http.post("create", data);
toast.success("Role created successfully");
return response.data;
} catch (error: any) {
toast.error(
"Failed to create role: " +
(error.response?.data?.message || "Unknown error")
);
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
});
export const toggleStatus = createAsyncThunk<
any,
{ id: string; status: number },
{ rejectValue: string }
>("role/toggleStatus", async ({ id, status }, { rejectWithValue }) => {
try {
const response = await http.patch(`${id}`, { status });
if (response.data.statusCode === 200) {
toast.success(
response.data.message || "Status updated successfully"
);
// Return both the response data and the requested status for reliable state updates
return {
responseData: response.data,
id,
status,
};
} else {
throw new Error(response.data.message || "Failed to update status");
}
} catch (error: any) {
toast.error(
"Error updating status: " + (error.message || "Unknown error")
);
return rejectWithValue(
error.response?.data?.message ||
error.message ||
"An error occurred"
);
}
});
const roleSlice = createSlice({
name: "roles",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(roleList.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(
roleList.fulfilled,
(state, action: PayloadAction<any>) => {
state.loading = false;
// Properly extract roles from the response data structure
state.roles =
action.payload.data?.results ||
action.payload.data ||
[];
}
)
.addCase(roleList.rejected, (state, action) => {
state.loading = false;
state.error = action.payload || "Failed to fetch roles";
})
.addCase(createRole.pending, (state) => {
state.loading = true;
})
.addCase(
createRole.fulfilled,
(state, action: PayloadAction<any>) => {
state.loading = false;
// Add the newly created role to the state if it exists in the response
if (action.payload.data) {
state.roles.push(action.payload.data);
}
}
)
.addCase(
createRole.rejected,
(state, action: PayloadAction<string | undefined>) => {
state.loading = false;
state.error = action.payload || "Failed to create role";
}
)
.addCase(toggleStatus.pending, (state) => {
state.loading = true;
})
.addCase(
toggleStatus.fulfilled,
(state, action: PayloadAction<any>) => {
state.loading = false;
// Get the id and updated status from the action payload
const { id, status } = action.payload;
// Find and update the role with the new status
const roleIndex = state.roles.findIndex(
(role) => role.id === id
);
if (roleIndex !== -1) {
state.roles[roleIndex] = {
...state.roles[roleIndex],
status: status,
};
}
}
)
.addCase(
toggleStatus.rejected,
(state, action: PayloadAction<string | undefined>) => {
state.loading = false;
state.error =
action.payload || "Failed to toggle role status";
}
);
},
});
export default roleSlice.reducer;