Implementing edit api for branches.

This commit is contained in:
Kartik Sharma 2025-11-20 09:51:23 +05:30
parent e7fddd41c2
commit dd716187da
4 changed files with 255 additions and 143 deletions

View File

@ -4,6 +4,7 @@ import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import Label from "../../common/Label";
import {
useBranchDetails,
useCreateBranch,
useServiceProjects,
useUpdateBranch,
@ -13,7 +14,13 @@ import { useParams } from "react-router-dom";
import { BranchSchema, defaultBranches } from "../ServiceProjectSchema";
const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
const { data } = {};
const {
data,
isLoading,
isError,
error: requestError,
} = useBranchDetails(BranchToEdit);
const { projectId } = useParams();
const schema = BranchSchema();
const {

View File

@ -1,19 +1,24 @@
import React, { useState } from "react";
import GlobalModel from "../../common/GlobalModel";
import ManageBranch from "./ManageBranch";
import { useBranches } from "../../../hooks/useServiceProject";
import { useBranches, useDeleteBranch } from "../../../hooks/useServiceProject";
import { ITEMS_PER_PAGE } from "../../../utils/constants";
import { useDebounce } from "../../../utils/appUtils";
import { useParams } from "react-router-dom";
import Pagination from "../../common/Pagination";
import ConfirmModal from "../../common/ConfirmModal";
import { SpinnerLoader } from "../../common/Loader";
const ServiceBranch = () => {
const { projectId } = useParams();
const [IsDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [showInactive, setShowInactive] = useState(false);
const [manageState, setManageState] = useState({
IsOpen: false,
branchId: null,
});
const { mutate: DeleteBranch, isPending } = useDeleteBranch();
const [deletingId, setDeletingId] = useState(null);
const [search, setSearch] = useState("");
const [currentPage, setCurrentPage] = useState(1);
@ -21,7 +26,8 @@ const ServiceBranch = () => {
const { data, isLoading, isError, error } = useBranches(
projectId,
true,
// true,
!showInactive,
ITEMS_PER_PAGE - 10,
currentPage,
debouncedSearch
@ -42,19 +48,62 @@ const ServiceBranch = () => {
},
];
const handleDelete = (id) => {
setDeletingId(id);
DeleteBranch(
{ id, isActive: false },
{
onSettled: () => {
setDeletingId(null);
setIsDeleteModalOpen(false);
},
}
);
};
return (
<>
{IsDeleteModalOpen && (
<ConfirmModal
isOpen={IsDeleteModalOpen}
type="delete"
header="Delete Expense"
message="Are you sure you want delete?"
onSubmit={handleDelete}
onClose={() => setIsDeleteModalOpen(false)}
loading={isPending}
paramData={deletingId}
/>
)}
<div className="card h-100 table-responsive px-sm-4">
<div className="card-datatable" id="payment-request-table">
{/* Header Section */}
<div className="row align-items-center justify-content-between mt-3 mx-1">
<div className="col-md-6 col-sm-12 text-start">
<div className="col-md-6 col-sm-12 ms-n3 text-start ">
<h5 className="mb-0">
<i className="bx bx-buildings text-primary me-2"></i>
Branches
<i className="bx bx-buildings text-primary"></i>
<span className="ms-2 fw-bold">Branch</span>
</h5>
</div>
<div className="col-md-3 col-sm-12 text-end">
{/* Flex container for toggle + button */}
<div className="col-md-6 col-sm-12 text-end">
<div className="d-flex flex-column flex-md-row align-items-md-center justify-content-md-end gap-2">
{/* Toggle Switch */}
<div className="form-check form-switch d-inline-flex align-items-center">
<input
type="checkbox"
className="form-check-input mt-1"
id="inactiveEmployeesCheckbox"
checked={showInactive}
onChange={() => setShowInactive(!showInactive)}
/>
<label htmlFor="inactiveEmployeesCheckbox" className="ms-2 mt-1">
Show Deleted Branches
</label>
</div>
{/* Add Branch Button */}
<button
className="btn btn-sm btn-primary"
type="button"
@ -68,9 +117,12 @@ const ServiceBranch = () => {
<i className="bx bx-sm bx-plus-circle me-2"></i>
<span className="d-none d-md-inline-block">Add Branch</span>
</button>
</div>
</div>
</div>
<div className="mx-2 mt-3">
<table className="table border-top text-nowrap align-middle table-borderless">
<thead>
@ -87,12 +139,22 @@ const ServiceBranch = () => {
<tbody>
{isLoading && (
<tr>
<td colSpan={columns.length + 1} className="text-center py-5">
Loading...
<td
colSpan={columns.length + 1}
className="text-center py-5"
style={{
height: "200px",
verticalAlign: "middle",
}}
>
<div className="d-flex justify-content-center align-items-center w-100 h-100">
<SpinnerLoader />
</div>
</td>
</tr>
)}
{isError && (
<tr>
<td
@ -115,16 +177,47 @@ const ServiceBranch = () => {
</td>
))}
<td className="text-center">
<i
className="bx bx-edit text-primary cursor-pointer"
<div className="dropdown z-2">
<button
type="button"
className="btn btn-xs btn-icon btn-text-secondary rounded-pill dropdown-toggle hide-arrow p-0 m-0"
data-bs-toggle="dropdown"
>
<i className="bx bx-dots-vertical-rounded text-muted p-0"></i>
</button>
<ul className="dropdown-menu dropdown-menu-end w-auto">
{/* Modify */}
<li
onClick={() =>
setManageState({
IsOpen: true,
branchId: branch.id,
})
}
/>
>
<a className="dropdown-item px-2 cursor-pointer py-1">
<i className="bx bx-edit text-primary bx-xs me-2"></i>
Modify
</a>
</li>
{/* Delete */}
<li
onClick={() => {
setIsDeleteModalOpen(true);
setDeletingId(branch.id);
}}
>
<a className="dropdown-item px-2 cursor-pointer py-1">
<i className="bx bx-trash text-danger bx-xs me-2"></i>
Delete
</a>
</li>
</ul>
</div>
</td>
</tr>
))}
@ -160,14 +253,17 @@ const ServiceBranch = () => {
>
<ManageBranch
key={manageState.branchId ?? "new"}
BranchToEdit={manageState.branchId}
closeModal={() =>
setManageState({ IsOpen: false, branchId: null })
}
/>
</GlobalModel>
)}
</div>
</div>
</>
);
};

View File

@ -315,12 +315,12 @@ export const useBranches = (
};
export const useBranch = (id)=>{
export const useBranchDetails = (id) => {
return useQuery({
queryKey: ["branch", id],
queryFn: async () => {
const resp = await ServiceProjectRepository.GetBranchDetail(id);
return resp.data ?? resp;
return resp.data;
},
enabled: !!id
})
@ -346,37 +346,42 @@ export const useCreateBranch = (onSuccessCallBack) => {
},
});
};
export const useUpdateBranch = () => {
export const useUpdateBranch = (onSuccessCallBack) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({ id, payload }) => await ServiceProjectRepository.UpdateBranch(id, payload),
mutationFn: async ({ id, payload }) =>
await ServiceProjectRepository.UpdateBranch(id, payload),
onSuccess: (_, variables) => {
// remove old single-branch cache
queryClient.removeQueries({ queryKey: ["branch", variables.id] });
// refresh list
queryClient.invalidateQueries({ queryKey: ["branches"] });
queryClient.invalidateQueries({ queryKey: ["branch", variables.id] });
if (onSuccessCallback) onSuccessCallback();
showToast("Branch Updated successfully", "success");
showToast("Branch updated successfully", "success");
onSuccessCallBack?.();
},
onError: (error) => {
showToast(
error?.response?.data?.message ||
error.message ||
"Failed to update branch",
"error"
);
onError: () => {
showToast("Something went wrong. Please try again later.", "error");
},
})
}
});
};
export const useDeleteBranch = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (id) => await ServiceProjectRepository.DeleteBranch(id),
onSuccess: (_, variables) => {
mutationFn: async ({ id, isActive}) =>
await ServiceProjectRepository.DeleteBranch(id, isActive),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["branches"] });
if (onSuccessCallback) onSuccessCallback();
showToast("Branch Deleted successfully", "success");
showToast("Branch deleted successfully", "success");
},
onError: (error) => {
showToast(
error?.response?.data?.message ||
@ -385,5 +390,5 @@ export const useDeleteBranch = () => {
"error"
);
},
})
}
});
};

View File

@ -1,3 +1,4 @@
import { isAction } from "@reduxjs/toolkit";
import { api } from "../utils/axiosClient";
export const ServiceProjectRepository = {
@ -43,7 +44,8 @@ export const ServiceProjectRepository = {
//#region Project Branch
CreateBranch: (data) => api.post(`/api/ServiceProject/branch/create`, data),
UpdateBranch: (id, data) =>
api.put("/api/ServiceProject/branch/edit/${id}", data),
api.put(`/api/ServiceProject/branch/edit/${id}`, data),
GetBranchList: (projectId, isActive, pageSize, pageNumber, searchString) => {
return api.get(
`/api/ServiceProject/branch/list/${projectId}?isActive=${isActive}&pageSize=${pageSize}&pageNumber=${pageNumber}&searchString=${searchString}`
@ -51,6 +53,8 @@ export const ServiceProjectRepository = {
},
GetBranchDetail: (id) => api.get(`/api/ServiceProject/branch/details/${id}`),
DeleteBranch: (id) => api.delete(`/api/ServiceProject/branch/delete/${id}`),
DeleteBranch: (id, isActive = false) =>
api.delete(`/api/ServiceProject/branch/delete/${id}?isActive=${isActive}`),
};