marco.pms.web/src/components/common/EmployeeSearchInput.jsx

102 lines
2.8 KiB
JavaScript

import { useState, useEffect } from "react";
import { useEmployeesName } from "../../hooks/useEmployees";
import { useDebounce } from "../../utils/appUtils";
import { useController } from "react-hook-form";
import Avatar from "./Avatar";
const EmployeeSearchInput = ({
control,
name,
projectId,
placeholder,
forAll,
}) => {
const {
field: { onChange, value, ref },
fieldState: { error },
} = useController({ name, control });
const [search, setSearch] = useState("");
const [showDropdown, setShowDropdown] = useState(false);
const debouncedSearch = useDebounce(search, 500);
const { data: employees, isLoading } = useEmployeesName(
projectId,
debouncedSearch,
forAll
);
useEffect(() => {
if (value && employees?.data) {
const found = employees.data.find((emp) => emp.id === value);
if (found && forAll) {
setSearch(found.firstName + " " + found.lastName);
}
}
}, [value, employees?.data]);
const handleSelect = (employee) => {
onChange(employee.id);
setSearch(employee.firstName + " " + employee.lastName);
setShowDropdown(false);
};
return (
<div className="position-relative">
<input
type="text"
ref={ref}
className={`form-control form-control-sm`}
placeholder={placeholder}
value={search}
onChange={(e) => {
setSearch(e.target.value);
setShowDropdown(true);
onChange("");
}}
onFocus={() => {
if (search) setShowDropdown(true);
}}
/>
{showDropdown && (employees?.data?.length > 0 || isLoading) && (
<ul
className="list-group position-absolute bg-white w-100 shadow z-3 rounded-none px-0"
style={{ maxHeight: 200, overflowY: "auto" }}
>
{isLoading ? (
<li className="list-group-item">
<a>Searching...</a>
</li>
) : (
employees?.data?.map((emp) => (
<li
key={emp.id}
className="list-group-item list-group-item-action py-1 px-1"
style={{ cursor: "pointer" }}
onClick={() => handleSelect(emp)}
>
<div className="d-flex align-items-center px-0">
<Avatar
size="xs"
classAvatar="m-0 me-2"
firstName={emp.firstName}
lastName={emp.lastName}
/>
<span className="text-muted">
{`${emp?.firstName} ${emp?.lastName}`.trim()}
</span>
</div>
</li>
))
)}
</ul>
)}
{error && <small className="danger-text">{error.message}</small>}
</div>
);
};
export default EmployeeSearchInput;