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 GlobalModel from "../common/GlobalModel";
|
||||
import { SpinnerLoader } from "../common/Loader";
|
||||
import ServiceBranch from "./ServiceBranch";
|
||||
|
||||
const ServiceProjectProfile = () => {
|
||||
const { projectId } = useParams();
|
||||
@ -114,6 +115,10 @@ const ServiceProjectProfile = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="col-md-6 col-lg-8 order-2 mb-6">
|
||||
<ServiceBranch/>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -52,3 +52,5 @@ export const ServiceProjectRepository = {
|
||||
GetBranchDetail: (id) => api.get(`/api/ServiceProject/branch/details/${id}`),
|
||||
DeleteBranch: (id) => api.delete(`/api/ServiceProject/branch/delete/${id}`),
|
||||
};
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user