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 [copied, setCopied] = useState(false);
|
||||
|
||||
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 handleCopy = async () => {
|
||||
if (!googleMapUrl) return;
|
||||
|
||||
await navigator.clipboard.writeText(googleMapUrl);
|
||||
setCopied(true);
|
||||
|
||||
setTimeout(() => setCopied(false), 3000);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
if (isLoading) return <BranchDetailsSkeleton />;
|
||||
if (isError)
|
||||
return (
|
||||
<div>
|
||||
<Error error={error} />
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="d-flex mb-2">
|
||||
<span className="fs-6 fw-medium">
|
||||
<i className="bx bx-sm me-2 bx-buildings"></i>Branch Details
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-100">
|
||||
<div className="d-flex mb-2 align-items-center">
|
||||
<i className="bx bx-buildings bx-sm me-2 text-primary"></i>
|
||||
<span className="fw-semibold">Branch Details</span>
|
||||
</div>
|
||||
|
||||
<div className="row mb-1">
|
||||
<div className="col-4 text-secondary">Contact No:</div>
|
||||
<div className="col-8">{data?.contactInformation}</div>
|
||||
</div>
|
||||
<DetailRow label="Branch Name" value={data?.branchName} />
|
||||
|
||||
<div className="row mb-1">
|
||||
<div className="col-4 text-secondary">Type:</div>
|
||||
<div className="col-8">{data?.branchType}</div>
|
||||
</div>
|
||||
<DetailRow label="Type" value={data?.branchType} />
|
||||
|
||||
<div className="row mb-1">
|
||||
<div className="col-4 text-secondary">Email:</div>
|
||||
<div className="col-8">{data?.email}</div>
|
||||
</div>
|
||||
<DetailRow label="Address" value={data?.address} />
|
||||
|
||||
<div className="row mb-1">
|
||||
<div className="col-4 text-secondary">Address:</div>
|
||||
<div className="col-8">{data?.address}</div>
|
||||
</div>
|
||||
</>
|
||||
{/* Contact persons */}
|
||||
{contactInfo.map((person, index) => (
|
||||
<div key={index} className="mb-2">
|
||||
<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;
|
||||
|
||||
@ -26,8 +26,8 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
contactPerson: "",
|
||||
designation: "",
|
||||
contactEmails: [""],
|
||||
contactNumbers: [""]
|
||||
}
|
||||
contactNumbers: [""],
|
||||
},
|
||||
]);
|
||||
|
||||
const { projectId } = useParams();
|
||||
@ -73,7 +73,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
}
|
||||
}, [data, reset]);
|
||||
|
||||
|
||||
const { mutate: CreateServiceBranch, isPending: createPending } =
|
||||
useCreateBranch(() => {
|
||||
handleClose();
|
||||
@ -97,8 +96,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="container p-3">
|
||||
<h5 className="m-0">
|
||||
@ -138,8 +135,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
</div>
|
||||
|
||||
<div className="row my-2 text-start">
|
||||
|
||||
|
||||
<div className="col-md-6">
|
||||
<Label htmlFor="googleMapUrl" className="form-label">
|
||||
Google Map URL
|
||||
@ -160,17 +155,29 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
|
||||
<div className="row my-2 text-start">
|
||||
<div className="col-12">
|
||||
<Label className="form-label" required>Contact Persons</Label>
|
||||
<Label className="form-label" required>
|
||||
Contact Persons
|
||||
</Label>
|
||||
|
||||
{contacts.map((item, index) => (
|
||||
<div key={index} className="border rounded p-2 mb-3">
|
||||
|
||||
{/* Contact Person + Designation */}
|
||||
<div className="d-flex justify-content-end py-1">
|
||||
{" "}
|
||||
<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="col-md-4">
|
||||
<div className=" col-md-6">
|
||||
<Label className="form-label">Contact Name</Label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Contact Person"
|
||||
placeholder="Contact Name"
|
||||
className="form-control form-control-sm"
|
||||
value={item.contactPerson}
|
||||
onChange={(e) => {
|
||||
@ -181,7 +188,8 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="col-md-4">
|
||||
<div className="col-md-6">
|
||||
<Label className="form-label">Designation</Label>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Designation"
|
||||
@ -194,24 +202,16 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
}}
|
||||
/>
|
||||
</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>
|
||||
|
||||
{/* Numbers Section */}
|
||||
<Label className="form-label">Contact Numbers</Label>
|
||||
|
||||
{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
|
||||
type="text"
|
||||
placeholder="Number"
|
||||
@ -246,7 +246,6 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
|
||||
</div>
|
||||
))}
|
||||
|
||||
@ -256,8 +255,10 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
<Label className="form-label">Contact Emails</Label>
|
||||
|
||||
{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
|
||||
type="email"
|
||||
placeholder="Email"
|
||||
@ -290,15 +291,11 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
}}
|
||||
></i>
|
||||
)}
|
||||
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
||||
</div>
|
||||
))}
|
||||
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-sm btn-primary mt-2"
|
||||
@ -308,21 +305,18 @@ const ManageBranch = ({ closeModal, BranchToEdit = null }) => {
|
||||
{
|
||||
contactPerson: "",
|
||||
designation: "",
|
||||
contactEmails: [""], // ← important
|
||||
contactNumbers: [""], // ← important
|
||||
contactEmails: [""], // ← important
|
||||
contactNumbers: [""], // ← important
|
||||
},
|
||||
])
|
||||
}
|
||||
>
|
||||
<i className="bx bx-plus"></i> Add Contact
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="row my-2 text-start">
|
||||
|
||||
<div className="col-12">
|
||||
<Label htmlFor="address" className="form-label" required>
|
||||
Address
|
||||
|
||||
@ -27,7 +27,7 @@ const ServiceBranch = () => {
|
||||
const { data, isLoading, isError, error } = useBranches(
|
||||
projectId,
|
||||
!showInactive,
|
||||
ITEMS_PER_PAGE - 10,
|
||||
ITEMS_PER_PAGE - 12,
|
||||
currentPage,
|
||||
debouncedSearch
|
||||
);
|
||||
@ -86,25 +86,24 @@ const ServiceBranch = () => {
|
||||
|
||||
{/* Flex container for toggle + button */}
|
||||
<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="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>
|
||||
<div className="d-flex justify-content-end">
|
||||
<button
|
||||
<div className="d-flex justify-content-end gap-2">
|
||||
<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 text-xs"
|
||||
>
|
||||
Show Deleted Branches
|
||||
</label>
|
||||
</div>
|
||||
<div className="d-flex justify-content-end">
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
onClick={() =>
|
||||
@ -117,7 +116,7 @@ const ServiceBranch = () => {
|
||||
<i className="bx bx-sm bx-plus-circle me-2"></i>
|
||||
Add Branch
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -140,8 +140,8 @@ const ManageJobTicket = ({ Job }) => {
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
{/* {data?.projectBranch && (
|
||||
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} style={{ overflow: "visible" }}>
|
||||
{data?.projectBranch && (
|
||||
<div className="d-flex gap-3 my-2 position-relative" ref={drawerRef} >
|
||||
<span className="text-secondary">
|
||||
<i className="bx bx-buildings"></i> Branch Name:
|
||||
</span>
|
||||
@ -150,7 +150,7 @@ const ManageJobTicket = ({ Job }) => {
|
||||
id="BRANCH_DETAILS"
|
||||
Mode="click"
|
||||
align="auto"
|
||||
boundaryRef={drawerRef} // drawer has position-relative
|
||||
boundaryRef={drawerRef}
|
||||
content={<BranchDetails branch={data?.projectBranch?.id} />}
|
||||
>
|
||||
<span className="text-decoration-underline cursor-pointer">
|
||||
@ -158,9 +158,12 @@ const ManageJobTicket = ({ Job }) => {
|
||||
</span>
|
||||
</HoverPopup>
|
||||
</div>
|
||||
)} */}
|
||||
)}
|
||||
|
||||
<div className="border-top">
|
||||
|
||||
|
||||
|
||||
<div className="border-top my-1">
|
||||
<p className="m-0 py-1">
|
||||
<i className="bx bx-group"></i> Peoples
|
||||
</p>
|
||||
|
||||
@ -152,47 +152,46 @@ const HoverPopup = ({
|
||||
});
|
||||
}, [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
|
||||
className="d-inline-block "
|
||||
style={{
|
||||
maxWidth: "calc(700px - 100px)",
|
||||
width: "100%",
|
||||
wordWrap: "break-word",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
className="d-inline-block"
|
||||
ref={triggerRef}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onClick={handleClick}
|
||||
style={{ cursor: "pointer" }}
|
||||
>
|
||||
<div
|
||||
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>
|
||||
)}
|
||||
{children}
|
||||
</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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user