Added delete user - Admin Section
This commit is contained in:
parent
7889c98f8d
commit
6a68d93308
@ -43,3 +43,48 @@ export async function PATCH(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function DELETE(
|
||||||
|
_request: Request,
|
||||||
|
{ params }: { params: { id: string } }
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
const { id } = params;
|
||||||
|
const { cookies } = await import("next/headers");
|
||||||
|
const cookieStore = await cookies();
|
||||||
|
const token = cookieStore.get(COOKIE_NAME)?.value;
|
||||||
|
|
||||||
|
if (!token) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "Missing Authorization header" },
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to swagger: /api/v1/users/{id}
|
||||||
|
const response = await fetch(`${BE_BASE_URL}/api/v1/users/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${token}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Some backends return empty body for DELETE; handle safely
|
||||||
|
let data: any = null;
|
||||||
|
try {
|
||||||
|
data = await response.json();
|
||||||
|
} catch {
|
||||||
|
data = { success: response.ok };
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.json(data ?? { success: response.ok }, {
|
||||||
|
status: response.status,
|
||||||
|
});
|
||||||
|
} catch (err: any) {
|
||||||
|
console.error("Proxy DELETE /api/v1/users/{id} error:", err);
|
||||||
|
return NextResponse.json(
|
||||||
|
{ message: "Internal server error", error: err.message },
|
||||||
|
{ status: 500 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -32,12 +32,7 @@ const Users: React.FC<UsersProps> = ({ users }) => {
|
|||||||
<Typography variant="h6">{user.username}</Typography>
|
<Typography variant="h6">{user.username}</Typography>
|
||||||
|
|
||||||
<Stack direction="row" spacing={1} mt={1}>
|
<Stack direction="row" spacing={1} mt={1}>
|
||||||
<UserRoleCard
|
<UserRoleCard user={user} />
|
||||||
user={user}
|
|
||||||
isAdmin={true}
|
|
||||||
lastLogin="small"
|
|
||||||
merchants={[]} // merchants={Numberuser.allowedMerchantIds}
|
|
||||||
/>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
126
app/features/UserRoles/DeleteUser/DeleteUser.scss
Normal file
126
app/features/UserRoles/DeleteUser/DeleteUser.scss
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
.delete-user__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1.5rem;
|
||||||
|
padding: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__warning {
|
||||||
|
background: #fff3cd;
|
||||||
|
border: 1px solid #ffc107;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 1rem;
|
||||||
|
|
||||||
|
.delete-user__warning-text {
|
||||||
|
margin: 0;
|
||||||
|
color: #856404;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__user-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
padding: 1rem;
|
||||||
|
background: #f7f7f8;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 0.4rem;
|
||||||
|
|
||||||
|
.delete-user__label {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #444;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__value {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
color: #222;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__error {
|
||||||
|
background: #f8d7da;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
border-radius: 6px;
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
color: #721c24;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__button {
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
transition: all 0.2s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
min-width: 120px;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--cancel {
|
||||||
|
background: #f5f5f5;
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #e8e8e8;
|
||||||
|
border-color: #bbb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--delete {
|
||||||
|
background: #dc3545;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background: #c82333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive tweak for smaller screens */
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.delete-user__content {
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-user__actions {
|
||||||
|
flex-direction: column-reverse;
|
||||||
|
|
||||||
|
.delete-user__button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
129
app/features/UserRoles/DeleteUser/DeleteUser.tsx
Normal file
129
app/features/UserRoles/DeleteUser/DeleteUser.tsx
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import toast from "react-hot-toast";
|
||||||
|
import Modal from "@/app/components/Modal/Modal";
|
||||||
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
import { AppDispatch } from "@/app/redux/store";
|
||||||
|
import { deleteUser, clearError } from "@/app/redux/user/userSlice";
|
||||||
|
import { IUser } from "../../Pages/Admin/Users/interfaces";
|
||||||
|
import Spinner from "@/app/components/Spinner/Spinner";
|
||||||
|
import { RootState } from "@/app/redux/store";
|
||||||
|
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import "./DeleteUser.scss";
|
||||||
|
|
||||||
|
interface DeleteUserProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
user: IUser | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DeleteUser: React.FC<DeleteUserProps> = ({ open, onClose, user }) => {
|
||||||
|
const dispatch = useDispatch<AppDispatch>();
|
||||||
|
const router = useRouter();
|
||||||
|
const { status, error } = useSelector((state: RootState) => state.user);
|
||||||
|
|
||||||
|
const loading = status === "loading";
|
||||||
|
|
||||||
|
const handleDelete = async () => {
|
||||||
|
if (!user?.id) {
|
||||||
|
toast.error("No user selected for deletion");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resultAction = await dispatch(deleteUser(user.id));
|
||||||
|
|
||||||
|
if (deleteUser.fulfilled.match(resultAction)) {
|
||||||
|
toast.success(
|
||||||
|
resultAction.payload.message || "User deleted successfully"
|
||||||
|
);
|
||||||
|
dispatch(clearError());
|
||||||
|
router.refresh();
|
||||||
|
onClose();
|
||||||
|
} else if (deleteUser.rejected.match(resultAction)) {
|
||||||
|
toast.error(
|
||||||
|
(resultAction.payload as string) || "Failed to delete user"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
toast.error(error.message || "An unexpected error occurred");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
if (!loading) {
|
||||||
|
dispatch(clearError());
|
||||||
|
onClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal open={open} onClose={handleClose} title="Delete User">
|
||||||
|
<div className="delete-user__content">
|
||||||
|
<div className="delete-user__warning">
|
||||||
|
<p className="delete-user__warning-text">
|
||||||
|
Are you sure you want to delete this user? This action cannot be
|
||||||
|
undone.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="delete-user__user-info">
|
||||||
|
<div className="delete-user__row">
|
||||||
|
<label className="delete-user__label">Username</label>
|
||||||
|
<div className="delete-user__value">{user.username}</div>
|
||||||
|
</div>
|
||||||
|
<div className="delete-user__row">
|
||||||
|
<label className="delete-user__label">Name</label>
|
||||||
|
<div className="delete-user__value">
|
||||||
|
{user.first_name} {user.last_name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="delete-user__row">
|
||||||
|
<label className="delete-user__label">Email</label>
|
||||||
|
<div className="delete-user__value">{user.email}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<div className="delete-user__error">
|
||||||
|
<span>{error}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="delete-user__actions">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleClose}
|
||||||
|
disabled={loading}
|
||||||
|
className="delete-user__button delete-user__button--cancel"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleDelete}
|
||||||
|
disabled={loading}
|
||||||
|
className="delete-user__button delete-user__button--delete"
|
||||||
|
>
|
||||||
|
{loading ? (
|
||||||
|
<>
|
||||||
|
<Spinner size="small" color="#fff" />
|
||||||
|
Deleting...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
"Delete User"
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteUser;
|
||||||
@ -22,6 +22,7 @@ import {
|
|||||||
import EditUser from "./EditUser/EditUser";
|
import EditUser from "./EditUser/EditUser";
|
||||||
import "./User.scss";
|
import "./User.scss";
|
||||||
import { IUser } from "../Pages/Admin/Users/interfaces";
|
import { IUser } from "../Pages/Admin/Users/interfaces";
|
||||||
|
import DeleteUser from "./DeleteUser/DeleteUser";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
user: IUser;
|
user: IUser;
|
||||||
@ -29,11 +30,16 @@ interface Props {
|
|||||||
|
|
||||||
export default function UserRoleCard({ user }: Props) {
|
export default function UserRoleCard({ user }: Props) {
|
||||||
const [isEditing, setIsEditing] = useState(false);
|
const [isEditing, setIsEditing] = useState(false);
|
||||||
|
const [openDeleteUser, setOpenDeleteUser] = useState(false);
|
||||||
const { username, first_name, last_name, email, groups } = user;
|
const { username, first_name, last_name, email, groups } = user;
|
||||||
const handleEditClick = () => {
|
const handleEditClick = () => {
|
||||||
setIsEditing(!isEditing);
|
setIsEditing(!isEditing);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleDeleteClick = () => {
|
||||||
|
setOpenDeleteUser(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card sx={{ mb: 2, minWidth: "100%" }}>
|
<Card sx={{ mb: 2, minWidth: "100%" }}>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
@ -69,7 +75,7 @@ export default function UserRoleCard({ user }: Props) {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Tooltip title="Delete">
|
<Tooltip title="Delete">
|
||||||
<IconButton>
|
<IconButton onClick={handleDeleteClick}>
|
||||||
<Delete />
|
<Delete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -98,7 +104,6 @@ export default function UserRoleCard({ user }: Props) {
|
|||||||
<Chip key={role} label={role} size="small" />
|
<Chip key={role} label={role} size="small" />
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
{/* {extraRolesCount && <Chip label={`+${extraRolesCount}`} />} */}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
<div
|
<div
|
||||||
@ -108,6 +113,13 @@ export default function UserRoleCard({ user }: Props) {
|
|||||||
>
|
>
|
||||||
{isEditing && <EditUser user={user} />}
|
{isEditing && <EditUser user={user} />}
|
||||||
</div>
|
</div>
|
||||||
|
{openDeleteUser && (
|
||||||
|
<DeleteUser
|
||||||
|
user={user}
|
||||||
|
open={openDeleteUser}
|
||||||
|
onClose={() => setOpenDeleteUser(false)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import advancedSearchReducer from "./advanedSearch/advancedSearchSlice";
|
|||||||
import authReducer from "./auth/authSlice";
|
import authReducer from "./auth/authSlice";
|
||||||
import uiReducer from "./ui/uiSlice";
|
import uiReducer from "./ui/uiSlice";
|
||||||
import metadataReducer from "./metadata/metadataSlice";
|
import metadataReducer from "./metadata/metadataSlice";
|
||||||
|
import userReducer from "./user/userSlice";
|
||||||
import userEpics from "./user/epic";
|
import userEpics from "./user/epic";
|
||||||
import authEpics from "./auth/epic";
|
import authEpics from "./auth/epic";
|
||||||
import uiEpics from "./ui/epic";
|
import uiEpics from "./ui/epic";
|
||||||
@ -41,6 +42,7 @@ const rootReducer = combineReducers({
|
|||||||
auth: authReducer,
|
auth: authReducer,
|
||||||
metadata: metadataReducer,
|
metadata: metadataReducer,
|
||||||
ui: uiReducer,
|
ui: uiReducer,
|
||||||
|
user: userReducer,
|
||||||
});
|
});
|
||||||
|
|
||||||
const rootEpic = combineEpics(...userEpics, ...authEpics, ...uiEpics);
|
const rootEpic = combineEpics(...userEpics, ...authEpics, ...uiEpics);
|
||||||
|
|||||||
200
app/redux/user/userSlice.ts
Normal file
200
app/redux/user/userSlice.ts
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
|
||||||
|
import { ThunkSuccess, ThunkError, IUserResponse } from "../types";
|
||||||
|
import { IEditUserForm } from "../../features/UserRoles/User.interfaces";
|
||||||
|
import { RootState } from "../store";
|
||||||
|
|
||||||
|
interface UserState {
|
||||||
|
status: "idle" | "loading" | "succeeded" | "failed";
|
||||||
|
error: string | null;
|
||||||
|
message: string;
|
||||||
|
addedUser: IUserResponse | null;
|
||||||
|
editedUser: IUserResponse | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: UserState = {
|
||||||
|
status: "idle",
|
||||||
|
error: null,
|
||||||
|
message: "",
|
||||||
|
addedUser: null,
|
||||||
|
editedUser: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------- Add User ----------------
|
||||||
|
export const addUser = createAsyncThunk<
|
||||||
|
ThunkSuccess<{ user: IUserResponse; success: boolean }>,
|
||||||
|
IEditUserForm,
|
||||||
|
{ rejectValue: ThunkError; state: RootState }
|
||||||
|
>("user/addUser", async (userData, { rejectWithValue, getState }) => {
|
||||||
|
try {
|
||||||
|
const state = getState();
|
||||||
|
const currentUserId = state.auth.user?.id;
|
||||||
|
console.log("[DEBUG] [ADD-USER] [currentUserId]: ", currentUserId);
|
||||||
|
const res = await fetch("/api/auth/register", {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ ...userData, creator: currentUserId || "" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
console.log("[DEBUG] [ADD-USER] [data]: ", data);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return rejectWithValue(data.message || "Failed to create user");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: data.success,
|
||||||
|
message: data.message || "User created successfully",
|
||||||
|
user: data.user,
|
||||||
|
} as ThunkSuccess<{ user: IUserResponse; success: boolean }>;
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return rejectWithValue(
|
||||||
|
(err as Error).message || "Network error during user creation"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------- Edit User ----------------
|
||||||
|
export const editUser = createAsyncThunk<
|
||||||
|
ThunkSuccess<{ user: IUserResponse }>,
|
||||||
|
{ id: string; updates: Partial<IUserResponse> },
|
||||||
|
{ rejectValue: ThunkError }
|
||||||
|
>("user/editUser", async ({ id, updates }, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/dashboard/admin/users/${id}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(updates),
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return rejectWithValue(data.message || "Failed to update user");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: data.message || "User updated successfully",
|
||||||
|
user: data.user,
|
||||||
|
};
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return rejectWithValue(
|
||||||
|
(err as Error).message || "Network error during user update"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------- Delete User ----------------
|
||||||
|
export const deleteUser = createAsyncThunk<
|
||||||
|
ThunkSuccess<{ id: string }>,
|
||||||
|
string,
|
||||||
|
{ rejectValue: ThunkError }
|
||||||
|
>("user/deleteUser", async (id, { rejectWithValue }) => {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/dashboard/admin/users/${id}`, {
|
||||||
|
method: "DELETE",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
return rejectWithValue(data.message || "Failed to delete user");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: data.message || "User deleted successfully",
|
||||||
|
id,
|
||||||
|
};
|
||||||
|
} catch (err: unknown) {
|
||||||
|
return rejectWithValue(
|
||||||
|
(err as Error).message || "Network error during user deletion"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ---------------- Slice ----------------
|
||||||
|
const userSlice = createSlice({
|
||||||
|
name: "user",
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
clearMessage: state => {
|
||||||
|
state.message = "";
|
||||||
|
},
|
||||||
|
clearAddedUser: state => {
|
||||||
|
state.addedUser = null;
|
||||||
|
},
|
||||||
|
clearEditedUser: state => {
|
||||||
|
state.editedUser = null;
|
||||||
|
},
|
||||||
|
clearError: state => {
|
||||||
|
state.error = null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extraReducers: builder => {
|
||||||
|
builder
|
||||||
|
// Add User
|
||||||
|
.addCase(addUser.pending, state => {
|
||||||
|
state.status = "loading";
|
||||||
|
state.message = "Creating user...";
|
||||||
|
state.addedUser = null;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(addUser.fulfilled, (state, action) => {
|
||||||
|
state.status = "succeeded";
|
||||||
|
state.message = action.payload.message;
|
||||||
|
state.addedUser = action.payload.user;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(addUser.rejected, (state, action) => {
|
||||||
|
state.status = "failed";
|
||||||
|
state.error = action.payload as string;
|
||||||
|
state.message = action.payload as string;
|
||||||
|
state.addedUser = null;
|
||||||
|
})
|
||||||
|
// Edit User
|
||||||
|
.addCase(editUser.pending, state => {
|
||||||
|
state.status = "loading";
|
||||||
|
state.message = "Updating user...";
|
||||||
|
state.editedUser = null;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(editUser.fulfilled, (state, action) => {
|
||||||
|
state.status = "succeeded";
|
||||||
|
state.message = action.payload.message;
|
||||||
|
state.editedUser = action.payload.user;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(editUser.rejected, (state, action) => {
|
||||||
|
state.status = "failed";
|
||||||
|
state.error = action.payload as string;
|
||||||
|
state.message = action.payload as string;
|
||||||
|
state.editedUser = null;
|
||||||
|
})
|
||||||
|
// Delete User
|
||||||
|
.addCase(deleteUser.pending, state => {
|
||||||
|
state.status = "loading";
|
||||||
|
state.message = "Deleting user...";
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(deleteUser.fulfilled, (state, action) => {
|
||||||
|
state.status = "succeeded";
|
||||||
|
state.message = action.payload.message;
|
||||||
|
state.error = null;
|
||||||
|
})
|
||||||
|
.addCase(deleteUser.rejected, (state, action) => {
|
||||||
|
state.status = "failed";
|
||||||
|
state.error = action.payload as string;
|
||||||
|
state.message = action.payload as string;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { clearMessage, clearAddedUser, clearEditedUser, clearError } =
|
||||||
|
userSlice.actions;
|
||||||
|
export default userSlice.reducer;
|
||||||
Loading…
x
Reference in New Issue
Block a user