194 lines
4.6 KiB
TypeScript
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;
|