added popup for branch view
This commit is contained in:
parent
bd43475d12
commit
fa923d4c3a
@ -6,56 +6,81 @@ import { BranchDetailsSkeleton } from "../ServiceProjectSeketon";
|
|||||||
|
|
||||||
const BranchDetails = ({ branch }) => {
|
const BranchDetails = ({ branch }) => {
|
||||||
const [copied, setCopied] = useState(false);
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
const { data, isLoading, isError, error } = useBranchDetails(branch);
|
const { data, isLoading, isError, error } = useBranchDetails(branch);
|
||||||
|
|
||||||
|
if (isLoading) return <BranchDetailsSkeleton />;
|
||||||
|
if (isError) return <Error error={error} />;
|
||||||
|
|
||||||
|
let contactInfo = [];
|
||||||
|
try {
|
||||||
|
contactInfo = JSON.parse(data?.contactInformation || "[]");
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
const googleMapUrl = data?.googleMapUrl || data?.locationLink;
|
const googleMapUrl = data?.googleMapUrl || data?.locationLink;
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
if (!googleMapUrl) return;
|
if (!googleMapUrl) return;
|
||||||
|
|
||||||
await navigator.clipboard.writeText(googleMapUrl);
|
await navigator.clipboard.writeText(googleMapUrl);
|
||||||
setCopied(true);
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2000);
|
||||||
setTimeout(() => setCopied(false), 3000);
|
|
||||||
};
|
};
|
||||||
if (isLoading) return <BranchDetailsSkeleton />;
|
|
||||||
if (isError)
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Error error={error} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div className="w-100">
|
||||||
<div className="d-flex mb-2">
|
<div className="d-flex mb-2 align-items-center">
|
||||||
<span className="fs-6 fw-medium">
|
<i className="bx bx-buildings bx-sm me-2 text-primary"></i>
|
||||||
<i className="bx bx-sm me-2 bx-buildings"></i>Branch Details
|
<span className="fw-semibold">Branch Details</span>
|
||||||
</span>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row mb-1">
|
<DetailRow label="Branch Name" value={data?.branchName} />
|
||||||
<div className="col-4 text-secondary">Contact No:</div>
|
|
||||||
<div className="col-8">{data?.contactInformation}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row mb-1">
|
<DetailRow label="Type" value={data?.branchType} />
|
||||||
<div className="col-4 text-secondary">Type:</div>
|
|
||||||
<div className="col-8">{data?.branchType}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row mb-1">
|
<DetailRow label="Address" value={data?.address} />
|
||||||
<div className="col-4 text-secondary">Email:</div>
|
|
||||||
<div className="col-8">{data?.email}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="row mb-1">
|
{/* Contact persons */}
|
||||||
<div className="col-4 text-secondary">Address:</div>
|
{contactInfo.map((person, index) => (
|
||||||
<div className="col-8">{data?.address}</div>
|
<div key={index} className="mb-2">
|
||||||
</div>
|
<div className="fw-medium text-primary">{person.contactPerson}</div>
|
||||||
</>
|
<DetailRow label="Role" value={person.designation} />
|
||||||
|
<DetailRow label="Emails" value={person.contactEmails.join(", ")} />
|
||||||
|
<DetailRow label="Phone" value={person.contactNumbers.join(", ")} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Map Link */}
|
||||||
|
{googleMapUrl && (
|
||||||
|
<div className="mt-2">
|
||||||
|
<a
|
||||||
|
href={googleMapUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-primary text-decoration-underline"
|
||||||
|
>
|
||||||
|
View on Google Maps
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-light border ms-2"
|
||||||
|
onClick={handleCopy}
|
||||||
|
>
|
||||||
|
{copied ? "Copied!" : "Copy"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DetailRow = ({ label, value }) => (
|
||||||
|
<div className="d-flex mb-1">
|
||||||
|
<div className="text-secondary" style={{ width: "90px", flexShrink: 0 }}>
|
||||||
|
{label}:
|
||||||
|
</div>
|
||||||
|
<div className="fw-medium" style={{ wordBreak: "break-word" }}>
|
||||||
|
{value || "N/A"}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
export default BranchDetails;
|
export default BranchDetails;
|
||||||
|
|||||||
@ -26,8 +26,8 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
contactPerson: "",
|
contactPerson: "",
|
||||||
designation: "",
|
designation: "",
|
||||||
contactEmails: [""],
|
contactEmails: [""],
|
||||||
contactNumbers: [""]
|
contactNumbers: [""],
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const { projectId } = useParams();
|
const { projectId } = useParams();
|
||||||
@ -73,7 +73,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
}
|
}
|
||||||
}, [data, reset]);
|
}, [data, reset]);
|
||||||
|
|
||||||
|
|
||||||
const { mutate: CreateServiceBranch, isPending: createPending } =
|
const { mutate: CreateServiceBranch, isPending: createPending } =
|
||||||
useCreateBranch(() => {
|
useCreateBranch(() => {
|
||||||
handleClose();
|
handleClose();
|
||||||
@ -97,8 +96,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container p-3">
|
<div className="container p-3">
|
||||||
<h5 className="m-0">
|
<h5 className="m-0">
|
||||||
@ -138,8 +135,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row my-2 text-start">
|
<div className="row my-2 text-start">
|
||||||
|
|
||||||
|
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<Label htmlFor="googleMapUrl" className="form-label">
|
<Label htmlFor="googleMapUrl" className="form-label">
|
||||||
Google Map URL
|
Google Map URL
|
||||||
@ -160,17 +155,29 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
|
|
||||||
<div className="row my-2 text-start">
|
<div className="row my-2 text-start">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<Label className="form-label" required>Contact Persons</Label>
|
<Label className="form-label" required>
|
||||||
|
Contact Persons
|
||||||
|
</Label>
|
||||||
|
|
||||||
{contacts.map((item, index) => (
|
{contacts.map((item, index) => (
|
||||||
<div key={index} className="border rounded p-2 mb-3">
|
<div key={index} className="border rounded p-2 mb-3">
|
||||||
|
<div className="d-flex justify-content-end py-1">
|
||||||
{/* Contact Person + Designation */}
|
{" "}
|
||||||
|
<div className="col-md-1 d-flex align-items-center">
|
||||||
|
<i
|
||||||
|
className="bx bx-trash text-danger cursor-pointer"
|
||||||
|
onClick={() =>
|
||||||
|
setContacts(contacts.filter((_, i) => i !== index))
|
||||||
|
}
|
||||||
|
></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div className="row mb-2">
|
<div className="row mb-2">
|
||||||
<div className="col-md-4">
|
<div className=" col-md-6">
|
||||||
|
<Label className="form-label">Contact Name</Label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Contact Person"
|
placeholder="Contact Name"
|
||||||
className="form-control form-control-sm"
|
className="form-control form-control-sm"
|
||||||
value={item.contactPerson}
|
value={item.contactPerson}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@ -181,7 +188,8 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-md-4">
|
<div className="col-md-6">
|
||||||
|
<Label className="form-label">Designation</Label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Designation"
|
placeholder="Designation"
|
||||||
@ -194,24 +202,16 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Remove entire contact */}
|
|
||||||
<div className="col-md-2 d-flex align-items-center">
|
|
||||||
<i
|
|
||||||
className="bx bx-trash text-danger cursor-pointer"
|
|
||||||
onClick={() =>
|
|
||||||
setContacts(contacts.filter((_, i) => i !== index))
|
|
||||||
}
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Numbers Section */}
|
{/* Numbers Section */}
|
||||||
<Label className="form-label">Contact Numbers</Label>
|
<Label className="form-label">Contact Numbers</Label>
|
||||||
|
|
||||||
{item.contactNumbers.map((num, numIndex) => (
|
{item.contactNumbers.map((num, numIndex) => (
|
||||||
<div key={numIndex} className="d-flex gap-2 mb-2 align-items-center">
|
<div
|
||||||
|
key={numIndex}
|
||||||
|
className="d-flex gap-2 mb-2 align-items-center"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Number"
|
placeholder="Number"
|
||||||
@ -246,7 +246,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
}}
|
}}
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
@ -256,8 +255,10 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
<Label className="form-label">Contact Emails</Label>
|
<Label className="form-label">Contact Emails</Label>
|
||||||
|
|
||||||
{item.contactEmails.map((email, emailIndex) => (
|
{item.contactEmails.map((email, emailIndex) => (
|
||||||
<div key={emailIndex} className="d-flex gap-2 mb-2 align-items-center">
|
<div
|
||||||
|
key={emailIndex}
|
||||||
|
className="d-flex gap-2 mb-2 align-items-center"
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="Email"
|
placeholder="Email"
|
||||||
@ -290,15 +291,11 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
}}
|
}}
|
||||||
></i>
|
></i>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="btn btn-sm btn-primary mt-2"
|
className="btn btn-sm btn-primary mt-2"
|
||||||
@ -308,21 +305,18 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
|||||||
{
|
{
|
||||||
contactPerson: "",
|
contactPerson: "",
|
||||||
designation: "",
|
designation: "",
|
||||||
contactEmails: [""], // ← important
|
contactEmails: [""], // ← important
|
||||||
contactNumbers: [""], // ← important
|
contactNumbers: [""], // ← important
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<i className="bx bx-plus"></i> Add Contact
|
<i className="bx bx-plus"></i> Add Contact
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="row my-2 text-start">
|
<div className="row my-2 text-start">
|
||||||
|
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<Label htmlFor="address" className="form-label" required>
|
<Label htmlFor="address" className="form-label" required>
|
||||||
Address
|
Address
|
||||||
|
|||||||
@ -27,7 +27,7 @@ const ServiceBranch = () => {
|
|||||||
const { data, isLoading, isError, error } = useBranches(
|
const { data, isLoading, isError, error } = useBranches(
|
||||||
projectId,
|
projectId,
|
||||||
!showInactive,
|
!showInactive,
|
||||||
ITEMS_PER_PAGE - 10,
|
ITEMS_PER_PAGE - 12,
|
||||||
currentPage,
|
currentPage,
|
||||||
debouncedSearch
|
debouncedSearch
|
||||||
);
|
);
|
||||||
@ -86,25 +86,24 @@ const ServiceBranch = () => {
|
|||||||
|
|
||||||
{/* Flex container for toggle + button */}
|
{/* Flex container for toggle + button */}
|
||||||
<div className="col-md-8 col-sm-12 text-end">
|
<div className="col-md-8 col-sm-12 text-end">
|
||||||
<div className="d-flex flex-column flex-md-row align-items-md-center gap-2">
|
<div className="d-flex justify-content-end gap-2">
|
||||||
|
<div className="form-check form-switch d-inline-flex align-items-center">
|
||||||
<div className="form-check form-switch d-inline-flex align-items-center">
|
<input
|
||||||
<input
|
type="checkbox"
|
||||||
type="checkbox"
|
className="form-check-input mt-1"
|
||||||
className="form-check-input mt-1"
|
id="inactiveEmployeesCheckbox"
|
||||||
id="inactiveEmployeesCheckbox"
|
checked={showInactive}
|
||||||
checked={showInactive}
|
onChange={() => setShowInactive(!showInactive)}
|
||||||
onChange={() => setShowInactive(!showInactive)}
|
/>
|
||||||
/>
|
<label
|
||||||
<label
|
htmlFor="inactiveEmployeesCheckbox"
|
||||||
htmlFor="inactiveEmployeesCheckbox"
|
className="ms-2 text-xs"
|
||||||
className="ms-2 mt-1"
|
>
|
||||||
>
|
Show Deleted Branches
|
||||||
Show Deleted Branches
|
</label>
|
||||||
</label>
|
</div>
|
||||||
</div>
|
<div className="d-flex justify-content-end">
|
||||||
<div className="d-flex justify-content-end">
|
<button
|
||||||
<button
|
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@ -117,7 +116,7 @@ const ServiceBranch = () => {
|
|||||||
<i className="bx bx-sm bx-plus-circle me-2"></i>
|
<i className="bx bx-sm bx-plus-circle me-2"></i>
|
||||||
Add Branch
|
Add Branch
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -140,8 +140,8 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
);
|
);
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
{/* {data?.projectBranch && (
|
{data?.projectBranch && (
|
||||||
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} style={{ overflow: "visible" }}>
|
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} >
|
||||||
<span className="text-secondary">
|
<span className="text-secondary">
|
||||||
<i className="bx bx-buildings"></i> Branch Name:
|
<i className="bx bx-buildings"></i> Branch Name:
|
||||||
</span>
|
</span>
|
||||||
@ -150,7 +150,7 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
id="BRANCH_DETAILS"
|
id="BRANCH_DETAILS"
|
||||||
Mode="click"
|
Mode="click"
|
||||||
align="auto"
|
align="auto"
|
||||||
boundaryRef={drawerRef} // drawer has position-relative
|
boundaryRef={drawerRef}
|
||||||
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
||||||
>
|
>
|
||||||
<span className="text-decoration-underline cursor-pointer">
|
<span className="text-decoration-underline cursor-pointer">
|
||||||
@ -158,9 +158,12 @@ const ManageJobTicket = ({ Job }) => {
|
|||||||
</span>
|
</span>
|
||||||
</HoverPopup>
|
</HoverPopup>
|
||||||
</div>
|
</div>
|
||||||
)} */}
|
)}
|
||||||
|
|
||||||
<div className="border-top">
|
|
||||||
|
|
||||||
|
|
||||||
|
<div className="border-top my-1">
|
||||||
<p className="m-0 py-1">
|
<p className="m-0 py-1">
|
||||||
<i className="bx bx-group"></i> Peoples
|
<i className="bx bx-group"></i> Peoples
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -152,47 +152,46 @@ const HoverPopup = ({
|
|||||||
});
|
});
|
||||||
}, [visible, align, boundaryRef]);
|
}, [visible, align, boundaryRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<div
|
||||||
|
className="d-inline-block position-relative" // <-- ADD THIS !!
|
||||||
|
style={{
|
||||||
|
maxWidth: "calc(700px - 100px)",
|
||||||
|
width: "100%",
|
||||||
|
wordWrap: "break-word",
|
||||||
|
overflow: "visible", // also make sure popup isn't clipped
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
className="d-inline-block "
|
className="d-inline-block"
|
||||||
style={{
|
ref={triggerRef}
|
||||||
maxWidth: "calc(700px - 100px)",
|
onMouseEnter={handleMouseEnter}
|
||||||
width: "100%",
|
onMouseLeave={handleMouseLeave}
|
||||||
wordWrap: "break-word",
|
onClick={handleClick}
|
||||||
overflow: "hidden",
|
style={{ cursor: "pointer" }}
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div
|
{children}
|
||||||
className="d-inline-block"
|
|
||||||
ref={triggerRef}
|
|
||||||
onMouseEnter={handleMouseEnter}
|
|
||||||
onMouseLeave={handleMouseLeave}
|
|
||||||
onClick={handleClick}
|
|
||||||
style={{ cursor: "pointer" }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{visible && (
|
|
||||||
<div
|
|
||||||
ref={popupRef}
|
|
||||||
// position absolute; it should be inside a positioned parent (the drawer)
|
|
||||||
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
|
||||||
style={{
|
|
||||||
zIndex: 2000,
|
|
||||||
top: "100%", // open below trigger
|
|
||||||
// left/right will be set by effect in parent coordinates
|
|
||||||
width: "max-content",
|
|
||||||
minWidth: "120px",
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
|
||||||
<div>{content}</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
|
{visible && (
|
||||||
|
<div
|
||||||
|
ref={popupRef}
|
||||||
|
className={`hover-popup bg-white border rounded shadow-sm p-3 position-absolute mt-2 ${className}`}
|
||||||
|
style={{
|
||||||
|
zIndex: 2000,
|
||||||
|
top: "100%",
|
||||||
|
width: "max-content",
|
||||||
|
minWidth: "120px",
|
||||||
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{title && <h6 className="fw-semibold mb-2">{title}</h6>}
|
||||||
|
<div>{content}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default HoverPopup;
|
export default HoverPopup;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user