bulk-email/src/redux/slices/authSlice.ts
2025-02-13 11:14:14 +05:30

334 lines
8.1 KiB
TypeScript

import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";
import axios from "axios";
import { backendHttp, apiHttp } from "../../lib/https";
import { toast } from "react-toastify";
// Define types for state
//Eknoor singh
//date:- 12-Feb-2025
//Token for the user has been declared
interface User {
token: string | null;
map(
arg0: (
admin: { name: any; role: any; email: any; phone: any },
index: number
) => { srno: number; name: any; role: any; email: any; phone: any }
): unknown;
id: string;
name: string;
email: string;
role: string;
phone: string;
}
interface Admin {
id: string;
name: string;
role: string;
email: string;
}
interface AuthState {
user: User | null;
admins: Admin[];
isAuthenticated: boolean;
isLoading: boolean;
error: object | string | null;
token: string | null;
}
// Async thunk for login
export const loginUser = createAsyncThunk<
User,
{ email: string; password: string },
{ rejectValue: string }
>("auth/login", async ({ email, password }, { rejectWithValue }) => {
try {
const response = await apiHttp.post("auth/login", {
email,
password,
});
localStorage.setItem("authToken", response.data?.data?.token); // Save token
toast.success(response.data?.message);
return response.data;
} catch (error: any) {
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
});
// Async thunk for register
export const registerUser = createAsyncThunk<
User,
{
name: string;
email: string;
password: string;
phone: string;
role: string;
},
{ rejectValue: string }
>("auth/signup", async (data, { rejectWithValue }) => {
try {
const response = await apiHttp.post("auth/signup", data);
return response.data;
} catch (error: any) {
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
});
//created by Eknoor and jaanvi
//date: 10-Feb-2025
//Fetching list of admins
export const adminList = createAsyncThunk<
Admin[],
void,
{ rejectValue: string }
>("/auth", async (_, { rejectWithValue }) => {
try {
const response = await apiHttp.get("/auth");
console.log(response?.data?.data);
return response?.data?.data?.map(
(admin: {
id: string;
name: string;
role: string;
email: string;
}) => ({
id: admin?.id,
name: admin?.name,
role: admin?.role || "N/A",
email: admin?.email,
})
);
} catch (error: any) {
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
});
//created by Eknoor
//date: 11-Feb-2025
//function for deleting admin
export const deleteAdmin = createAsyncThunk<
string,
string,
{ rejectValue: string }
>("deleteAdmin", async (id, { rejectWithValue }) => {
try {
const response = await apiHttp.delete(`/auth/${id}`);
toast.success(response.data?.message);
return id;
} catch (error: any) {
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
});
export const updateAdmin = createAsyncThunk(
"/auth/id",
async (
{ id, name, role }: { id: any; name: string; role: string },
{ rejectWithValue }
) => {
try {
const response = await apiHttp.put(`/auth/${id}`, { name, role });
toast.success("Admin updated successfully");
console.log(response?.data);
return response?.data;
} catch (error: any) {
return rejectWithValue(
error.response?.data?.message || "An error occurred"
);
}
}
);
//Eknoor singh
//date:- 12-Feb-2025
//Function for fetching profile of a particular user has been implemented with Redux.
export const fetchAdminProfile = createAsyncThunk<
User,
void,
{ rejectValue: string }
>("auth/fetchAdminProfile", async (_, { rejectWithValue }) => {
try {
const token = localStorage?.getItem("authToken");
if (!token) throw new Error("No token found");
const response = await apiHttp?.get("/auth/profile", {
headers: { Authorization: `Bearer ${token}` }, // Ensure 'Bearer' prefix
});
console.log("API Response:", response?.data); // Debugging
if (!response.data?.data) {
throw new Error("Invalid API response");
}
return response?.data?.data; // Fix: Return only `data`, assuming it contains user info.
} catch (error: any) {
console.error(
"Profile Fetch Error:",
error?.response?.data || error?.message
);
return rejectWithValue(
error?.response?.data?.message || "An error occurred"
);
}
});
const initialState: AuthState = {
user: null,
admins: [],
isAuthenticated: false,
isLoading: false,
error: null,
//Eknoor singh
//date:- 12-Feb-2025
//initial state of token set to null
token: null,
};
const authSlice = createSlice({
name: "auth",
initialState,
reducers: {
logout: (state) => {
state.user = null;
state.isAuthenticated = false;
//Eknoor singh
//date:- 12-Feb-2025
//Token is removed from local storage and set to null
state.token = null;
localStorage.removeItem("authToken");
},
},
extraReducers: (builder) => {
builder
// Login
.addCase(loginUser.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(loginUser.fulfilled, (state, action) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload; // Fix: Extract correct payload
state.token = action.payload.token; // Store token in Redux
})
.addCase(
loginUser.rejected,
(state, action: PayloadAction<string | undefined>) => {
state.isLoading = false;
state.error = action.payload || "An error occurred";
}
)
// Register
.addCase(registerUser.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
registerUser.fulfilled,
(state, action: PayloadAction<User>) => {
state.isLoading = false;
state.isAuthenticated = true;
state.user = action.payload;
}
)
.addCase(
registerUser.rejected,
(state, action: PayloadAction<string | undefined>) => {
state.isLoading = false;
state.error = action.payload || "An error occurred";
}
)
// created by Jaanvi and Eknoor
//AdminList
.addCase(adminList.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(
adminList.fulfilled,
(state, action: PayloadAction<Admin[]>) => {
state.isLoading = false;
state.admins = action.payload;
}
)
.addCase(
adminList.rejected,
(state, action: PayloadAction<string | undefined>) => {
state.isLoading = false;
state.error = action.payload || "An error occurred";
}
)
//created by Eknoor
//date: 11-Feb-2025
//cases for deleting admin
.addCase(deleteAdmin.pending, (state) => {
state.isLoading = true;
})
.addCase(deleteAdmin.fulfilled, (state, action) => {
state.isLoading = false;
state.admins = state.admins.filter(
(admin) => String(admin.id) !== String(action.payload)
);
})
.addCase(deleteAdmin.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload || "Failed to delete admin";
})
.addCase(updateAdmin.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(updateAdmin.fulfilled, (state, action) => {
const updatedAdmin = action.payload;
state.admins = state?.admins?.map((admin) =>
admin?.id === updatedAdmin?.id ? updatedAdmin : admin
);
state.isLoading = false;
})
.addCase(updateAdmin.rejected, (state, action) => {
state.isLoading = false;
state.error =
action.payload ||
"Something went wrong while updating Admin!!";
})
//Eknoor singh
//date:- 12-Feb-2025
//Reducers for fetching profiles has been implemented
.addCase(fetchAdminProfile.pending, (state) => {
state.isLoading = true;
state.error = null;
})
.addCase(fetchAdminProfile.fulfilled, (state, action) => {
state.isLoading = false;
state.user = action.payload;
state.isAuthenticated = true;
})
.addCase(fetchAdminProfile.rejected, (state, action) => {
state.isLoading = false;
state.error = action.payload || "Failed to fetch admin profile";
});
},
});
export const { logout } = authSlice.actions;
export default authSlice.reducer;