Merge branch 'Project_Branch_Management' of https://git.marcoaiot.com/admin/marco.pms.web into Project_Branch_Management
This commit is contained in:
commit
f5d89f2bab
43
src/components/ServiceProject/BranchSchema.js
Normal file
43
src/components/ServiceProject/BranchSchema.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const BranchSchema = () =>
|
||||||
|
z.object({
|
||||||
|
projectId: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Project is required" }),
|
||||||
|
|
||||||
|
branchName: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Branch Name is required" }),
|
||||||
|
|
||||||
|
contactInformation: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Contact Information is required" }),
|
||||||
|
|
||||||
|
address: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Address is required" }),
|
||||||
|
|
||||||
|
branchType: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.min(1, { message: "Branch Type is required" }),
|
||||||
|
|
||||||
|
googleMapUrl: z
|
||||||
|
.string()
|
||||||
|
.trim()
|
||||||
|
.url({ message: "Enter a valid Google Map URL" }),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const defaultBranches = {
|
||||||
|
branchName: "",
|
||||||
|
projectId: "",
|
||||||
|
contactInformation: "",
|
||||||
|
address: "",
|
||||||
|
branchType: "",
|
||||||
|
googleMapUrl: "",
|
||||||
|
};
|
||||||
176
src/components/ServiceProject/ManageBranch.jsx
Normal file
176
src/components/ServiceProject/ManageBranch.jsx
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { useProjectName } from '../../hooks/useProjects';
|
||||||
|
import { BranchSchema, defaultBranches } from './BranchSchema';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import Label from '../common/Label';
|
||||||
|
|
||||||
|
const ManageBranch = ({ BranchToEdit = null }) => {
|
||||||
|
|
||||||
|
const schema = BranchSchema();
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
control,
|
||||||
|
watch,
|
||||||
|
handleSubmit,
|
||||||
|
setValue,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: defaultBranches,
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
projectNames,
|
||||||
|
loading: projectLoading,
|
||||||
|
error,
|
||||||
|
isError: isProjectError,
|
||||||
|
} = useProjectName();
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
reset();
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="container p-3">
|
||||||
|
<h5 className="m-0">
|
||||||
|
{BranchToEdit
|
||||||
|
? "Update Branch"
|
||||||
|
: "Create Branch"}
|
||||||
|
</h5>
|
||||||
|
<form onSubmit={handleSubmit(onsubmit)}>
|
||||||
|
<div className="row my-2 text-start">
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label className="form-label" required>
|
||||||
|
Select Project
|
||||||
|
</Label>
|
||||||
|
<select
|
||||||
|
className="form-select form-select-sm"
|
||||||
|
{...register("projectId")}
|
||||||
|
>
|
||||||
|
<option value="">Select Project</option>
|
||||||
|
{projectLoading ? (
|
||||||
|
<option>Loading...</option>
|
||||||
|
) : (
|
||||||
|
projectNames?.map((project) => (
|
||||||
|
<option key={project.id} value={project.id}>
|
||||||
|
{project.name}
|
||||||
|
</option>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</select>
|
||||||
|
{errors.projectId && (
|
||||||
|
<small className="danger-text">{errors.projectId.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label htmlFor="branchName" className="form-label" required>
|
||||||
|
Branch Name
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="branchName"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("branchName")}
|
||||||
|
placeholder="Enter Branch"
|
||||||
|
/>
|
||||||
|
{errors.branchName && (
|
||||||
|
<small className="danger-text">{errors.branchName.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="row my-2 text-start">
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label htmlFor="contactInformation" className="form-label" required>
|
||||||
|
Contact Information
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="contactInformation"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("contactInformation")}
|
||||||
|
|
||||||
|
/>
|
||||||
|
{errors.contactInformation && (
|
||||||
|
<small className="danger-text">{errors.contactInformation.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label htmlFor="address" className="form-label" required>
|
||||||
|
Address
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="address"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("address")}
|
||||||
|
|
||||||
|
/>
|
||||||
|
{errors.address && (
|
||||||
|
<small className="danger-text">{errors.address.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="row my-2 text-start">
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label htmlFor="branchType" className="form-label" required>
|
||||||
|
Branch Type
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="branchType"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("branchType")}
|
||||||
|
/>
|
||||||
|
{errors.branchType && (
|
||||||
|
<small className="danger-text">{errors.branchType.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6">
|
||||||
|
<Label htmlFor="googleMapUrl" className="form-label" required>
|
||||||
|
Google Map URL
|
||||||
|
</Label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="googleMapUrl"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("googleMapUrl")}
|
||||||
|
|
||||||
|
/>
|
||||||
|
{errors.googleMapUrl && (
|
||||||
|
<small className="danger-text">{errors.googleMapUrl.message}</small>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="d-flex justify-content-end gap-3">
|
||||||
|
<button
|
||||||
|
type="reset"
|
||||||
|
onClick={handleClose}
|
||||||
|
className="btn btn-label-secondary btn-sm mt-3"
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="submit" className="btn btn-primary btn-sm mt-3">
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ManageBranch
|
||||||
170
src/components/ServiceProject/ServiceBranch.jsx
Normal file
170
src/components/ServiceProject/ServiceBranch.jsx
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import GlobalModel from '../common/GlobalModel';
|
||||||
|
import ManageBranch from './ManageBranch';
|
||||||
|
|
||||||
|
const ServiceBranch = () => {
|
||||||
|
|
||||||
|
const [ManageServiceBranch, setManageServiceBranch] = useState({
|
||||||
|
IsOpen: null,
|
||||||
|
branchId: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ServiceBranch = [
|
||||||
|
{
|
||||||
|
key: "branchName",
|
||||||
|
label: "Branch Name",
|
||||||
|
align: "text-start",
|
||||||
|
getValue: (e) => e?.payee || "N/A",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div className="card h-100 table-responsive px-sm-4">
|
||||||
|
<div className="card-datatable" id="payment-request-table">
|
||||||
|
<div className="row align-items-center justify-content-end mt-3">
|
||||||
|
<div className="col-md-4 col-sm-12 text-md-end text-end">
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
setManageServiceBranch({
|
||||||
|
IsOpen: true,
|
||||||
|
branchId: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<i className="bx bx-plus-circle me-2"></i>
|
||||||
|
<span className="d-none d-md-inline-block">
|
||||||
|
Add Branch
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div className="mx-2">
|
||||||
|
{/* {Array.isArray(filteredData) && filteredData.length > 0 && ( */}
|
||||||
|
<table className="table border-top dataTable text-nowrap align-middle">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{ServiceBranch.map((col) => (
|
||||||
|
<th key={col.key} className={`sorting ${col.align}`}>
|
||||||
|
{col.label}
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
<th className="text-center">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
{/* <tbody>
|
||||||
|
{filteredData?.length > 0 ? (
|
||||||
|
filteredData?.map((recurringExpense) => (
|
||||||
|
<tr
|
||||||
|
key={recurringExpense.id}
|
||||||
|
className="align-middle"
|
||||||
|
style={{ height: "40px" }}
|
||||||
|
>
|
||||||
|
{recurringExpenseColumns.map((col) => (
|
||||||
|
<td
|
||||||
|
key={col.key}
|
||||||
|
className={`d-table-cell ${col.align ?? ""} py-3`}
|
||||||
|
>
|
||||||
|
{col?.customRender
|
||||||
|
? col?.customRender(recurringExpense)
|
||||||
|
: col?.getValue(recurringExpense)}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
<td className="sticky-action-column bg-white">
|
||||||
|
<div className="d-flex flex-row gap-2 gap-0">
|
||||||
|
<i
|
||||||
|
className="bx bx-show text-primary cursor-pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setViewRecurring({
|
||||||
|
recurringId: recurringExpense?.id,
|
||||||
|
view: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
></i>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
<li
|
||||||
|
onClick={() =>
|
||||||
|
setManageServiceBranch({
|
||||||
|
IsOpen: true,
|
||||||
|
RecurringId: recurringExpense?.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>
|
||||||
|
|
||||||
|
<li
|
||||||
|
onClick={() => {
|
||||||
|
setIsDeleteModalOpen(true);
|
||||||
|
setDeletingId(recurringExpense.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>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan={recurringExpenseColumns?.length + 1}
|
||||||
|
className="text-center border-0 py-8"
|
||||||
|
></td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody> */}
|
||||||
|
</table>
|
||||||
|
{/* )} */}
|
||||||
|
{/* {!filteredData ||
|
||||||
|
filteredData.length === 0
|
||||||
|
&& (
|
||||||
|
<div className="d-flex justify-content-center align-items-center h-64">
|
||||||
|
{isError ? (<p>{error.message}</p>) : (<p>No Recurring Expense Found</p>)}
|
||||||
|
</div>
|
||||||
|
)} */}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{ManageServiceBranch.IsOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
isOpen
|
||||||
|
size="lg"
|
||||||
|
closeModal={() =>
|
||||||
|
setManageServiceBranch({ IsOpen: null, branchId: null })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ManageBranch
|
||||||
|
key={ManageServiceBranch.branchId ?? "new"}
|
||||||
|
closeModal={() =>
|
||||||
|
setManageServiceBranch({ IsOpen: null, branchId: null })
|
||||||
|
}
|
||||||
|
// requestToEdit={ManageServiceBranch.branchId}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceBranch
|
||||||
@ -5,6 +5,7 @@ import { formatUTCToLocalTime } from "../../utils/dateUtils";
|
|||||||
import ManageServiceProject from "./ManageServiceProject";
|
import ManageServiceProject from "./ManageServiceProject";
|
||||||
import GlobalModel from "../common/GlobalModel";
|
import GlobalModel from "../common/GlobalModel";
|
||||||
import { SpinnerLoader } from "../common/Loader";
|
import { SpinnerLoader } from "../common/Loader";
|
||||||
|
import ServiceBranch from "./ServiceBranch";
|
||||||
|
|
||||||
const ServiceProjectProfile = () => {
|
const ServiceProjectProfile = () => {
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
@ -114,6 +115,10 @@ const ServiceProjectProfile = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-6 col-lg-8 order-2 mb-6">
|
||||||
|
<ServiceBranch/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -52,3 +52,5 @@ export const ServiceProjectRepository = {
|
|||||||
GetBranchDetail: (id) => api.get(`/api/ServiceProject/branch/details/${id}`),
|
GetBranchDetail: (id) => api.get(`/api/ServiceProject/branch/details/${id}`),
|
||||||
DeleteBranch: (id) => api.delete(`/api/ServiceProject/branch/delete/${id}`),
|
DeleteBranch: (id) => api.delete(`/api/ServiceProject/branch/delete/${id}`),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user