added branch for projects
This commit is contained in:
parent
7e4dffff34
commit
e7fddd41c2
@ -40,7 +40,6 @@ const ActionPaymentRequest = ({ requestId }) => {
|
|||||||
error: PaymentModeError,
|
error: PaymentModeError,
|
||||||
} = usePaymentMode();
|
} = usePaymentMode();
|
||||||
|
|
||||||
console.log("Kartik", data)
|
|
||||||
|
|
||||||
const IsReview = useHasUserPermission(REVIEW_EXPENSE);
|
const IsReview = useHasUserPermission(REVIEW_EXPENSE);
|
||||||
const [imageLoaded, setImageLoaded] = useState({});
|
const [imageLoaded, setImageLoaded] = useState({});
|
||||||
|
|||||||
@ -82,7 +82,6 @@ const EditActivityModal = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!workItem) return;
|
if (!workItem) return;
|
||||||
console.log(workItem)
|
|
||||||
reset({
|
reset({
|
||||||
activityID: String(
|
activityID: String(
|
||||||
workItem?.workItem?.activityId || workItem?.activityMaster?.id
|
workItem?.workItem?.activityId || workItem?.activityMaster?.id
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
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: "",
|
|
||||||
};
|
|
||||||
@ -1,186 +0,0 @@
|
|||||||
import React, { useEffect } 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';
|
|
||||||
import { useCreateBranch, useServiceProjects, useUpdateBranch } from '../../hooks/useServiceProject';
|
|
||||||
import { useAppForm } from '../../hooks/appHooks/useAppForm';
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|
||||||
const { data } = {}
|
|
||||||
const { projectId } = useParams();
|
|
||||||
const schema = BranchSchema();
|
|
||||||
const {
|
|
||||||
register,
|
|
||||||
control,
|
|
||||||
watch,
|
|
||||||
handleSubmit,
|
|
||||||
setValue,
|
|
||||||
reset,
|
|
||||||
formState: { errors },
|
|
||||||
} = useAppForm({
|
|
||||||
resolver: zodResolver(schema),
|
|
||||||
defaultValues: {
|
|
||||||
...defaultBranches,
|
|
||||||
projectId: projectId || ""
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
reset();
|
|
||||||
closeModal();
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (BranchToEdit && data) {
|
|
||||||
reset({
|
|
||||||
branchName: data.branchName || "",
|
|
||||||
projectId: data.project?.id || projectId || "",
|
|
||||||
contactInformation: data.contactInformation || "",
|
|
||||||
address: data.address || "",
|
|
||||||
branchType: data.branchType || "",
|
|
||||||
googleMapUrl: data.googleMapUrl || "",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [data, reset]);
|
|
||||||
|
|
||||||
const { mutate: CreateServiceBranch, isPending: createPending } =
|
|
||||||
useCreateBranch(() => {
|
|
||||||
handleClose();
|
|
||||||
});
|
|
||||||
const { mutate: ServiceBranchUpdate, isPending } =
|
|
||||||
useUpdateBranch(() => handleClose());
|
|
||||||
|
|
||||||
const onSubmit = (fromdata) => {
|
|
||||||
let payload = {
|
|
||||||
...fromdata, projectId,
|
|
||||||
};
|
|
||||||
if (BranchToEdit) {
|
|
||||||
const editPayload = { ...payload, id: data.id };
|
|
||||||
ServiceBranchUpdate({ id: data.id, payload: editPayload });
|
|
||||||
} else {
|
|
||||||
CreateServiceBranch(payload);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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 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 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>
|
|
||||||
|
|
||||||
<div className="row my-2 text-start">
|
|
||||||
|
|
||||||
|
|
||||||
<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 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>
|
|
||||||
|
|
||||||
|
|
||||||
<div className="row my-2 text-start">
|
|
||||||
|
|
||||||
|
|
||||||
<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
|
|
||||||
@ -41,7 +41,8 @@ const ManageJob = ({ Job }) => {
|
|||||||
control,
|
control,
|
||||||
watch,
|
watch,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
reset,setValue,
|
reset,
|
||||||
|
setValue,
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = methods;
|
} = methods;
|
||||||
|
|
||||||
@ -164,6 +165,7 @@ const ManageJob = ({ Job }) => {
|
|||||||
dueDate: JobData.dueDate ?? null,
|
dueDate: JobData.dueDate ?? null,
|
||||||
tags: JobData.tags ?? [],
|
tags: JobData.tags ?? [],
|
||||||
statusId: JobData.status.id,
|
statusId: JobData.status.id,
|
||||||
|
branchId : JobData?.projectBranch?.id
|
||||||
});
|
});
|
||||||
}, [JobData, Job, projectId]);
|
}, [JobData, Job, projectId]);
|
||||||
return (
|
return (
|
||||||
@ -201,7 +203,7 @@ const ManageJob = ({ Job }) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 mb-2 mb-md-4">
|
<div className="col-12 col-md-6 mb-2 mb-md-4">
|
||||||
<Label >Select Employee</Label>
|
<Label>Select Employee</Label>
|
||||||
<PmsEmployeeInputTag
|
<PmsEmployeeInputTag
|
||||||
control={control}
|
control={control}
|
||||||
name="assignees"
|
name="assignees"
|
||||||
@ -240,21 +242,20 @@ const ManageJob = ({ Job }) => {
|
|||||||
name="tags"
|
name="tags"
|
||||||
label="Tag"
|
label="Tag"
|
||||||
placeholder="Enter Tag"
|
placeholder="Enter Tag"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12 col-md-6 mb-2 mb-md-4">
|
<div className="col-12 col-md-6 mb-2 mb-md-4">
|
||||||
<SelectFieldSearch
|
<SelectFieldSearch
|
||||||
label="Select Branch"
|
label="Select Branch"
|
||||||
placeholder="Select Branch"
|
placeholder="Select Branch"
|
||||||
required
|
|
||||||
value={watch("branchId")}
|
value={watch("branchId")}
|
||||||
onChange={(val) => setValue("branchId", val)}
|
onChange={(val) => setValue("branchId", val)}
|
||||||
valueKey="id"
|
valueKey="id"
|
||||||
labelKey="branchName"
|
labelKey="branchName"
|
||||||
hookParams={[projectId,true,10,1]}
|
hookParams={[projectId, true, 10, 1]}
|
||||||
useFetchHook={useBranches}
|
useFetchHook={useBranches}
|
||||||
isMultiple={false}
|
isMultiple={false}
|
||||||
|
disabled={Job}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
|
|||||||
@ -124,10 +124,16 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="d-flex my-2">
|
||||||
|
<span className="fw-semibold">
|
||||||
|
{" "}
|
||||||
|
<i className="bx bx-buildings me-1"></i>Branch Name :
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div className="d-block mt-4 mb-3">
|
<div className="d-block mt-4 mb-3">
|
||||||
<div className="row align-items-start align-items-md-start gap-2 mb-1">
|
<div className="row align-items-start align-items-md-start gap-2 mb-1">
|
||||||
<div className="col-12 col-md-auto">
|
<div className="col-12 col-md-auto">
|
||||||
<small className="fs-6 fw-medium">Created By</small>
|
<small className="fs-6 ">Created By</small>
|
||||||
</div>
|
</div>
|
||||||
<div className="col d-flex flex-row align-items-center ">
|
<div className="col d-flex flex-row align-items-center ">
|
||||||
<Avatar
|
<Avatar
|
||||||
@ -147,7 +153,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
{data?.assignees?.length > 0 && (
|
{data?.assignees?.length > 0 && (
|
||||||
<div className="row align-items-start align-items-md-start gap-2">
|
<div className="row align-items-start align-items-md-start gap-2">
|
||||||
<div className="col-12 col-md-auto">
|
<div className="col-12 col-md-auto">
|
||||||
<small className="fs-6 fw-medium">Assigned To</small>
|
<small className="fs-6">Assigned To</small>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col">
|
<div className="col">
|
||||||
|
|||||||
@ -1,162 +0,0 @@
|
|||||||
import React, { useState } from 'react'
|
|
||||||
import GlobalModel from '../common/GlobalModel';
|
|
||||||
import ManageBranch from './ManageBranch';
|
|
||||||
import { Pagination } from 'swiper/modules';
|
|
||||||
import { useBranches } from '../../hooks/useServiceProject';
|
|
||||||
import { ITEMS_PER_PAGE } from '../../utils/constants';
|
|
||||||
import { useDebounce } from '../../utils/appUtils';
|
|
||||||
import { useParams } from 'react-router-dom';
|
|
||||||
|
|
||||||
const ServiceBranch = () => {
|
|
||||||
|
|
||||||
const [ManageServiceBranch, setManageServiceBranch] = useState({
|
|
||||||
IsOpen: null,
|
|
||||||
branchId: null,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { projectId } = useParams();
|
|
||||||
|
|
||||||
const [search, setSearch] = useState("");
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
|
||||||
const debouncedSearch = useDebounce(search, 500);
|
|
||||||
|
|
||||||
const { data, isLoading, isError, error } = useBranches(
|
|
||||||
projectId,
|
|
||||||
true,
|
|
||||||
ITEMS_PER_PAGE,
|
|
||||||
currentPage,
|
|
||||||
debouncedSearch,
|
|
||||||
);
|
|
||||||
const paginate = (page) => {
|
|
||||||
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
|
|
||||||
setCurrentPage(page);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const ServiceBranch = [
|
|
||||||
{
|
|
||||||
key: "branchName",
|
|
||||||
label: "Branch Name",
|
|
||||||
align: "text-start",
|
|
||||||
getValue: (e) => e?.branchName || "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 text-nowrap align-middle">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
{ServiceBranch.map((col) => (
|
|
||||||
<th key={col.key} className={col.align}>
|
|
||||||
{col.label}
|
|
||||||
</th>
|
|
||||||
))}
|
|
||||||
<th className="text-center">Action</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{isLoading ? (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={ServiceBranch.length + 1} className="text-center py-5">
|
|
||||||
Loading...
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : isError ? (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={ServiceBranch.length + 1} className="text-center py-5">
|
|
||||||
{error?.message || "Error loading branches"}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
) : data?.data?.length > 0 ? (
|
|
||||||
data.data.map((branch) => (
|
|
||||||
<tr key={branch.id}>
|
|
||||||
{ServiceBranch.map((col) => (
|
|
||||||
<td key={col.key} className={col.align}>
|
|
||||||
{col.getValue(branch)}
|
|
||||||
</td>
|
|
||||||
))}
|
|
||||||
<td className="text-center">
|
|
||||||
<i
|
|
||||||
className="bx bx-edit text-primary cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setManageServiceBranch({
|
|
||||||
IsOpen: true,
|
|
||||||
branchId: branch.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<tr>
|
|
||||||
<td colSpan={ServiceBranch.length + 1} className="text-center py-5">
|
|
||||||
No Branch Found
|
|
||||||
</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>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* <Pagination
|
|
||||||
currentPage={currentPage}
|
|
||||||
totalPages={data?.totalPages}
|
|
||||||
onPageChange={paginate}
|
|
||||||
/> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default ServiceBranch
|
|
||||||
95
src/components/ServiceProject/ServiceProfile.jsx
Normal file
95
src/components/ServiceProject/ServiceProfile.jsx
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { formatUTCToLocalTime } from '../../utils/dateUtils'
|
||||||
|
|
||||||
|
const ServiceProfile = ({data,setIsOpenModal}) => {
|
||||||
|
return (
|
||||||
|
<div className="card mb-4 h-100">
|
||||||
|
<div className="card-header text-start">
|
||||||
|
<h5 className="card-action-title mb-0 ps-1">
|
||||||
|
{" "}
|
||||||
|
<i className="fa fa-building rounded-circle text-primary"></i>
|
||||||
|
<span className="ms-2 fw-bold">Project Profile</span>
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<ul className="list-unstyled my-3 ps-0 text-start">
|
||||||
|
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
<div className="d-flex align-items-start" style={{ minWidth: "150px" }}>
|
||||||
|
<i className="bx bx-cog"></i>
|
||||||
|
<span className="fw-medium mx-2 text-nowrap">Name:</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex-grow-1 text-start text-wrap">
|
||||||
|
{data.name}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
||||||
|
<i className="bx bx-fingerprint"></i>
|
||||||
|
<span className="fw-medium mx-2">Nick Name:</span>
|
||||||
|
</div>
|
||||||
|
<span>{data.shortName}</span>
|
||||||
|
</li>
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
||||||
|
<i className="bx bx-check"></i>
|
||||||
|
<span className="fw-medium mx-2">Assign Date:</span>
|
||||||
|
</div>
|
||||||
|
<span>
|
||||||
|
{data.assignedDate ? formatUTCToLocalTime(data.assignedDate) : "NA"}
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
||||||
|
<i className="bx bx-trophy"></i>
|
||||||
|
<span className="fw-medium mx-2">Status:</span>
|
||||||
|
</div>
|
||||||
|
<span>{data?.status.status}</span>
|
||||||
|
</li>
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
||||||
|
<i className="bx bx-user"></i>
|
||||||
|
<span className="fw-medium mx-2">Contact:</span>
|
||||||
|
</div>
|
||||||
|
<span>{data.contactName}</span>
|
||||||
|
</li>
|
||||||
|
<li className="d-flex mb-3">
|
||||||
|
{/* Label section with icon */}
|
||||||
|
<div className="d-flex align-items-start" style={{ minWidth: "150px" }}>
|
||||||
|
<i className="bx bx-flag mt-1"></i>
|
||||||
|
<span className="fw-medium mx-2 text-nowrap">Address:</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Content section that wraps nicely */}
|
||||||
|
<div className="flex-grow-1 text-start text-wrap">
|
||||||
|
{data.address}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li className="d-flex justify-content-center mt-4">
|
||||||
|
|
||||||
|
<a className="d-flex justify-content-center mt-4">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
data-bs-toggle="modal"
|
||||||
|
data-bs-target="#edit-project-modal"
|
||||||
|
onClick={() => setIsOpenModal(true)}
|
||||||
|
>
|
||||||
|
Modify Details
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ServiceProfile
|
||||||
@ -0,0 +1,183 @@
|
|||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { useProjectName } from "../../../hooks/useProjects";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import Label from "../../common/Label";
|
||||||
|
import {
|
||||||
|
useCreateBranch,
|
||||||
|
useServiceProjects,
|
||||||
|
useUpdateBranch,
|
||||||
|
} from "../../../hooks/useServiceProject";
|
||||||
|
import { useAppForm } from "../../../hooks/appHooks/useAppForm";
|
||||||
|
import { useParams } from "react-router-dom";
|
||||||
|
import { BranchSchema, defaultBranches } from "../ServiceProjectSchema";
|
||||||
|
|
||||||
|
const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||||
|
const { data } = {};
|
||||||
|
const { projectId } = useParams();
|
||||||
|
const schema = BranchSchema();
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
control,
|
||||||
|
watch,
|
||||||
|
handleSubmit,
|
||||||
|
setValue,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useAppForm({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {
|
||||||
|
...defaultBranches,
|
||||||
|
projectId: projectId || "",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
reset();
|
||||||
|
closeModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (BranchToEdit && data) {
|
||||||
|
reset({
|
||||||
|
branchName: data.branchName || "",
|
||||||
|
projectId: data.project?.id || projectId || "",
|
||||||
|
contactInformation: data.contactInformation || "",
|
||||||
|
address: data.address || "",
|
||||||
|
branchType: data.branchType || "",
|
||||||
|
googleMapUrl: data.googleMapUrl || "",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [data, reset]);
|
||||||
|
|
||||||
|
const { mutate: CreateServiceBranch, isPending: createPending } =
|
||||||
|
useCreateBranch(() => {
|
||||||
|
handleClose();
|
||||||
|
});
|
||||||
|
const { mutate: ServiceBranchUpdate, isPending } = useUpdateBranch(() =>
|
||||||
|
handleClose()
|
||||||
|
);
|
||||||
|
|
||||||
|
const onSubmit = (fromdata) => {
|
||||||
|
let payload = {
|
||||||
|
...fromdata,
|
||||||
|
projectId,
|
||||||
|
};
|
||||||
|
if (BranchToEdit) {
|
||||||
|
const editPayload = { ...payload, id: data.id };
|
||||||
|
ServiceBranchUpdate({ id: data.id, payload: editPayload });
|
||||||
|
} else {
|
||||||
|
CreateServiceBranch(payload);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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 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 className="col-md-6">
|
||||||
|
<Label htmlFor="contactInformation" className="form-label" required>
|
||||||
|
Contact Number
|
||||||
|
</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>
|
||||||
|
|
||||||
|
<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="row my-2 text-start">
|
||||||
|
|
||||||
|
<div className="col-12">
|
||||||
|
<Label htmlFor="address" className="form-label" required>
|
||||||
|
Address
|
||||||
|
</Label>
|
||||||
|
<textarea
|
||||||
|
id="address"
|
||||||
|
className="form-control form-control-sm"
|
||||||
|
{...register("address")}
|
||||||
|
/>
|
||||||
|
{errors.address && (
|
||||||
|
<small className="danger-text">{errors.address.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">
|
||||||
|
{isPending ? "Please wait...":"Submit"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ManageBranch;
|
||||||
@ -0,0 +1,174 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import GlobalModel from "../../common/GlobalModel";
|
||||||
|
import ManageBranch from "./ManageBranch";
|
||||||
|
import { useBranches } 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";
|
||||||
|
|
||||||
|
const ServiceBranch = () => {
|
||||||
|
const { projectId } = useParams();
|
||||||
|
|
||||||
|
const [manageState, setManageState] = useState({
|
||||||
|
IsOpen: false,
|
||||||
|
branchId: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const [search, setSearch] = useState("");
|
||||||
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
|
const debouncedSearch = useDebounce(search, 500);
|
||||||
|
|
||||||
|
const { data, isLoading, isError, error } = useBranches(
|
||||||
|
projectId,
|
||||||
|
true,
|
||||||
|
ITEMS_PER_PAGE - 10,
|
||||||
|
currentPage,
|
||||||
|
debouncedSearch
|
||||||
|
);
|
||||||
|
|
||||||
|
const paginate = (page) => {
|
||||||
|
if (page >= 1 && page <= (data?.totalPages ?? 1)) {
|
||||||
|
setCurrentPage(page);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
key: "branchName",
|
||||||
|
label: "Name",
|
||||||
|
align: "text-start",
|
||||||
|
getValue: (e) => e?.branchName || "N/A",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<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">
|
||||||
|
<h5 className="mb-0">
|
||||||
|
<i className="bx bx-buildings text-primary me-2"></i>
|
||||||
|
Branches
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="col-md-3 col-sm-12 text-end">
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
setManageState({
|
||||||
|
IsOpen: true,
|
||||||
|
branchId: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<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 className="mx-2 mt-3">
|
||||||
|
<table className="table border-top text-nowrap align-middle table-borderless">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
{columns.map((col) => (
|
||||||
|
<th key={col.key} className={col.align}>
|
||||||
|
{col.label}
|
||||||
|
</th>
|
||||||
|
))}
|
||||||
|
<th className="text-center">Action</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
{isLoading && (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={columns.length + 1} className="text-center py-5">
|
||||||
|
Loading...
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{isError && (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan={columns.length + 1}
|
||||||
|
className="text-center text-danger py-5"
|
||||||
|
>
|
||||||
|
{error?.message || "Error loading branches"}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!isLoading &&
|
||||||
|
!isError &&
|
||||||
|
data?.data?.length > 0 &&
|
||||||
|
data.data.map((branch) => (
|
||||||
|
<tr key={branch.id}>
|
||||||
|
{columns.map((col) => (
|
||||||
|
<td key={col.key} className={`${col.align} py-3`}>
|
||||||
|
{col.getValue(branch)}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
<td className="text-center">
|
||||||
|
<i
|
||||||
|
className="bx bx-edit text-primary cursor-pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setManageState({
|
||||||
|
IsOpen: true,
|
||||||
|
branchId: branch.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{!isLoading &&
|
||||||
|
!isError &&
|
||||||
|
(!data?.data || data.data.length === 0) && (
|
||||||
|
<tr>
|
||||||
|
<td
|
||||||
|
colSpan={columns.length + 1}
|
||||||
|
className="text-center py-12"
|
||||||
|
>
|
||||||
|
No Branch Found
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{data?.data?.length > 0 && (
|
||||||
|
<Pagination
|
||||||
|
currentPage={currentPage}
|
||||||
|
totalPages={data.totalPages}
|
||||||
|
onPageChange={paginate}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{manageState.IsOpen && (
|
||||||
|
<GlobalModel
|
||||||
|
isOpen
|
||||||
|
size="md"
|
||||||
|
closeModal={() => setManageState({ IsOpen: false, branchId: null })}
|
||||||
|
>
|
||||||
|
<ManageBranch
|
||||||
|
key={manageState.branchId ?? "new"}
|
||||||
|
closeModal={() =>
|
||||||
|
setManageState({ IsOpen: false, branchId: null })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</GlobalModel>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ServiceBranch;
|
||||||
@ -5,17 +5,26 @@ 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";
|
import ServiceBranch from "./ServiceProjectBranch/ServiceBranch";
|
||||||
|
import ServiceProfile from "./ServiceProfile";
|
||||||
|
|
||||||
const ServiceProjectProfile = () => {
|
const ServiceProjectProfile = () => {
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
const [IsOpenModal, setIsOpenModal] = useState(false);
|
const [IsOpenModal, setIsOpenModal] = useState(false);
|
||||||
const { data, isLoading, isError, error } = useServiceProject(projectId);
|
const { data, isLoading, isError, error } = useServiceProject(projectId);
|
||||||
if (isLoading) return <div className="py-8"><SpinnerLoader/></div>
|
if (isLoading)
|
||||||
|
return (
|
||||||
|
<div className="py-8">
|
||||||
|
<SpinnerLoader />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{IsOpenModal && (
|
{IsOpenModal && (
|
||||||
<GlobalModel isOpen={IsOpenModal} closeModal={() => setIsOpenModal(false)}>
|
<GlobalModel
|
||||||
|
isOpen={IsOpenModal}
|
||||||
|
closeModal={() => setIsOpenModal(false)}
|
||||||
|
>
|
||||||
<ManageServiceProject
|
<ManageServiceProject
|
||||||
serviceProjectId={projectId}
|
serviceProjectId={projectId}
|
||||||
onClose={() => setIsOpenModal(false)}
|
onClose={() => setIsOpenModal(false)}
|
||||||
@ -25,101 +34,12 @@ const ServiceProjectProfile = () => {
|
|||||||
|
|
||||||
<div className="row py-2">
|
<div className="row py-2">
|
||||||
<div className="col-md-6 col-lg-4 order-2 mb-6">
|
<div className="col-md-6 col-lg-4 order-2 mb-6">
|
||||||
<div className="card mb-4">
|
<ServiceProfile data={data} setIsOpenModal={setIsOpenModal}/>
|
||||||
<div className="card-header text-start">
|
|
||||||
<h5 className="card-action-title mb-0 ps-1">
|
|
||||||
{" "}
|
|
||||||
<i className="fa fa-building rounded-circle text-primary"></i>
|
|
||||||
<span className="ms-2 fw-bold">Project Profile</span>
|
|
||||||
</h5>
|
|
||||||
</div>
|
|
||||||
<div className="card-body">
|
|
||||||
<ul className="list-unstyled my-3 ps-0 text-start">
|
|
||||||
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
<div className="d-flex align-items-start" style={{ minWidth: "150px" }}>
|
|
||||||
<i className="bx bx-cog"></i>
|
|
||||||
<span className="fw-medium mx-2 text-nowrap">Name:</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content section that wraps nicely */}
|
|
||||||
<div className="flex-grow-1 text-start text-wrap">
|
|
||||||
{data.name}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
|
||||||
<i className="bx bx-fingerprint"></i>
|
|
||||||
<span className="fw-medium mx-2">Nick Name:</span>
|
|
||||||
</div>
|
|
||||||
<span>{data.shortName}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
|
||||||
<i className="bx bx-check"></i>
|
|
||||||
<span className="fw-medium mx-2">Assign Date:</span>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
{data.assignedDate ? formatUTCToLocalTime(data.assignedDate) : "NA"}
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
|
||||||
<i className="bx bx-trophy"></i>
|
|
||||||
<span className="fw-medium mx-2">Status:</span>
|
|
||||||
</div>
|
|
||||||
<span>{data?.status.status}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
<div className="d-flex align-items-center" style={{ width: '150px' }}>
|
|
||||||
<i className="bx bx-user"></i>
|
|
||||||
<span className="fw-medium mx-2">Contact:</span>
|
|
||||||
</div>
|
|
||||||
<span>{data.contactName}</span>
|
|
||||||
</li>
|
|
||||||
<li className="d-flex mb-3">
|
|
||||||
{/* Label section with icon */}
|
|
||||||
<div className="d-flex align-items-start" style={{ minWidth: "150px" }}>
|
|
||||||
<i className="bx bx-flag mt-1"></i>
|
|
||||||
<span className="fw-medium mx-2 text-nowrap">Address:</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Content section that wraps nicely */}
|
|
||||||
<div className="flex-grow-1 text-start text-wrap">
|
|
||||||
{data.address}
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li className="d-flex justify-content-center mt-4"> {/* Added mt-4 for some top margin */}
|
|
||||||
|
|
||||||
<a className="d-flex justify-content-center mt-4"> {/* Added mt-4 for some top margin */}
|
|
||||||
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="btn btn-sm btn-primary"
|
|
||||||
data-bs-toggle="modal"
|
|
||||||
data-bs-target="#edit-project-modal"
|
|
||||||
onClick={() => setIsOpenModal(true)}
|
|
||||||
>
|
|
||||||
Modify Details
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-md-6 col-lg-8 order-2 mb-6">
|
<div className="col-md-6 col-lg-8 order-2 mb-6">
|
||||||
<ServiceBranch/>
|
<ServiceBranch />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -50,6 +50,10 @@ export const defaultProjectValues = {
|
|||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//#region JobSchema
|
//#region JobSchema
|
||||||
|
|
||||||
export const TagSchema = z.object({
|
export const TagSchema = z.object({
|
||||||
@ -115,3 +119,54 @@ export const defaultJobValue = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//#region Branch
|
||||||
|
|
||||||
|
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: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//#endregion
|
||||||
@ -104,8 +104,7 @@ const SubScriptionHistory = ({ tenantId }) => {
|
|||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="dropdown-item py-1"
|
className="dropdown-item py-1"
|
||||||
onClick={() =>
|
onClick={() =>{}
|
||||||
console.log("Download clicked for", item.id)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i className="bx bx-cloud-download bx-sm"></i> Download
|
<i className="bx bx-cloud-download bx-sm"></i> Download
|
||||||
|
|||||||
@ -93,11 +93,9 @@ const TenantForm = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const onSubmitTenant = (data) => {
|
const onSubmitTenant = (data) => {
|
||||||
console.log("Tenant Data:", data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSubmitSubScription = (data) => {
|
const onSubmitSubScription = (data) => {
|
||||||
console.log("Subscription Data:", data);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const newTenantConfig = [
|
const newTenantConfig = [
|
||||||
|
|||||||
@ -362,8 +362,6 @@ export const SelectProjectField = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export const SelectFieldSearch = ({
|
export const SelectFieldSearch = ({
|
||||||
label = "Select",
|
label = "Select",
|
||||||
placeholder = "Select ",
|
placeholder = "Select ",
|
||||||
@ -372,7 +370,7 @@ export const SelectFieldSearch = ({
|
|||||||
onChange,
|
onChange,
|
||||||
valueKey = "id",
|
valueKey = "id",
|
||||||
labelKey = "name",
|
labelKey = "name",
|
||||||
|
disabled = false,
|
||||||
isFullObject = false,
|
isFullObject = false,
|
||||||
isMultiple = false,
|
isMultiple = false,
|
||||||
hookParams,
|
hookParams,
|
||||||
@ -381,7 +379,7 @@ export const SelectFieldSearch = ({
|
|||||||
const [searchText, setSearchText] = useState("");
|
const [searchText, setSearchText] = useState("");
|
||||||
const debounce = useDebounce(searchText, 300);
|
const debounce = useDebounce(searchText, 300);
|
||||||
|
|
||||||
const { data, isLoading } = useFetchHook(...hookParams,debounce);
|
const { data, isLoading } = useFetchHook(...hookParams, debounce);
|
||||||
const options = data?.data ?? [];
|
const options = data?.data ?? [];
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const dropdownRef = useRef(null);
|
const dropdownRef = useRef(null);
|
||||||
@ -434,6 +432,36 @@ export const SelectFieldSearch = ({
|
|||||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// MERGED OPTIONS TO ENSURE SELECTED VALUE APPEARS EVEN IF NOT IN SEARCH RESULT
|
||||||
|
const [mergedOptions, setMergedOptions] = useState([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let finalList = [...options];
|
||||||
|
|
||||||
|
if (!isMultiple && value && !isFullObject) {
|
||||||
|
// already selected option inside options?
|
||||||
|
const exists = options.some((o) => o[valueKey] === value);
|
||||||
|
|
||||||
|
// if selected item not found, try to get from props (value) as fallback
|
||||||
|
if (!exists && typeof value === "object") {
|
||||||
|
finalList.unshift(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isMultiple && Array.isArray(value)) {
|
||||||
|
value.forEach((val) => {
|
||||||
|
const id = isFullObject ? val[valueKey] : val;
|
||||||
|
const exists = options.some((o) => o[valueKey] === id);
|
||||||
|
|
||||||
|
if (!exists && typeof val === "object") {
|
||||||
|
finalList.unshift(val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setMergedOptions(finalList);
|
||||||
|
}, [options, value]);
|
||||||
|
|
||||||
/** -----------------------------
|
/** -----------------------------
|
||||||
* HANDLE SELECT
|
* HANDLE SELECT
|
||||||
* ----------------------------- */
|
* ----------------------------- */
|
||||||
@ -472,9 +500,10 @@ export const SelectFieldSearch = ({
|
|||||||
{/* MAIN BUTTON */}
|
{/* MAIN BUTTON */}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={`select2-icons form-select d-flex align-items-center justify-content-between ${
|
className={`select2-icons form-select d-flex align-items-center justify-content-between ${
|
||||||
open ? "show" : ""
|
open ? "show" : ""
|
||||||
}`}
|
}`}
|
||||||
|
disabled={disabled}
|
||||||
onClick={() => setOpen((prev) => !prev)}
|
onClick={() => setOpen((prev) => !prev)}
|
||||||
>
|
>
|
||||||
<span className={`text-truncate ${!displayText ? "text-muted" : ""}`}>
|
<span className={`text-truncate ${!displayText ? "text-muted" : ""}`}>
|
||||||
@ -503,6 +532,7 @@ export const SelectFieldSearch = ({
|
|||||||
onChange={(e) => setSearchText(e.target.value)}
|
onChange={(e) => setSearchText(e.target.value)}
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,6 @@ const CommentEditor = () => {
|
|||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
|
|
||||||
const handleSubmit = () => {
|
const handleSubmit = () => {
|
||||||
console.log("Comment:", value);
|
|
||||||
// Submit or handle content
|
// Submit or handle content
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -411,7 +411,6 @@ export const useUpdateProject = (onSuccessCallback) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.log(error);
|
|
||||||
showToast(error?.message || "Error while updating project", "error");
|
showToast(error?.message || "Error while updating project", "error");
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -308,7 +308,6 @@ export const useBranches = (
|
|||||||
pageNumber,
|
pageNumber,
|
||||||
searchString
|
searchString
|
||||||
);
|
);
|
||||||
console.log(resp)
|
|
||||||
return resp.data;
|
return resp.data;
|
||||||
},
|
},
|
||||||
enabled: !!projectId,
|
enabled: !!projectId,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user