added pre-fill updating
This commit is contained in:
parent
742337a3d0
commit
4d8af5da91
@ -3,6 +3,7 @@ import Label from "../Label";
|
||||
import { useDebounce } from "../../../utils/appUtils";
|
||||
import { useEmployeesName } from "../../../hooks/useEmployees";
|
||||
import { useProjectBothName } from "../../../hooks/useProjects";
|
||||
import EmployeeRepository from "../../../repositories/EmployeeRepository";
|
||||
|
||||
const SelectEmployeeServerSide = ({
|
||||
label = "Select",
|
||||
@ -18,6 +19,7 @@ const SelectEmployeeServerSide = ({
|
||||
}) => {
|
||||
const [searchText, setSearchText] = useState("");
|
||||
const debounce = useDebounce(searchText, 300);
|
||||
const [forcedSelected, setForcedSelected] = useState(null);
|
||||
|
||||
const { data, isLoading } = useEmployeesName(
|
||||
projectId,
|
||||
@ -34,22 +36,15 @@ const SelectEmployeeServerSide = ({
|
||||
return `${emp.firstName || ""} ${emp.lastName || ""}`.trim();
|
||||
};
|
||||
|
||||
/** -----------------------------
|
||||
* SELECTED OPTION (SINGLE)
|
||||
* ----------------------------- */
|
||||
let selectedSingle = null;
|
||||
|
||||
if (!isMultiple) {
|
||||
if (isFullObject && value) selectedSingle = value;
|
||||
else if (!isFullObject && value)
|
||||
selectedSingle = options.find((o) => o[valueKey] === value);
|
||||
selectedSingle =
|
||||
options.find((o) => o[valueKey] === value) || forcedSelected;
|
||||
}
|
||||
|
||||
/** -----------------------------
|
||||
* SELECTED OPTION (MULTIPLE)
|
||||
* ----------------------------- */
|
||||
let selectedList = [];
|
||||
|
||||
if (isMultiple && Array.isArray(value)) {
|
||||
if (isFullObject) selectedList = value;
|
||||
else {
|
||||
@ -57,54 +52,61 @@ const SelectEmployeeServerSide = ({
|
||||
}
|
||||
}
|
||||
|
||||
/** Main button label */
|
||||
const displayText = !isMultiple
|
||||
? getDisplayName(selectedSingle) || placeholder
|
||||
: selectedList.length > 0
|
||||
? selectedList.map((e) => getDisplayName(e)).join(", ")
|
||||
: placeholder;
|
||||
|
||||
/** -----------------------------
|
||||
* HANDLE OUTSIDE CLICK
|
||||
* ----------------------------- */
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (e) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("mousedown", handleClickOutside);
|
||||
return () => document.removeEventListener("mousedown", handleClickOutside);
|
||||
}, []);
|
||||
|
||||
/** -----------------------------
|
||||
* HANDLE SELECT
|
||||
* ----------------------------- */
|
||||
const handleSelect = (option) => {
|
||||
if (!isMultiple) {
|
||||
// SINGLE SELECT
|
||||
if (isFullObject) onChange(option);
|
||||
else onChange(option[valueKey]);
|
||||
setOpen(false);
|
||||
} else {
|
||||
// MULTIPLE SELECT
|
||||
let updated = [];
|
||||
|
||||
const exists = selectedList.some((e) => e[valueKey] === option[valueKey]);
|
||||
|
||||
if (exists) {
|
||||
// remove
|
||||
updated = selectedList.filter((e) => e[valueKey] !== option[valueKey]);
|
||||
} else {
|
||||
// add
|
||||
updated = [...selectedList, option];
|
||||
}
|
||||
|
||||
updated = exists
|
||||
? selectedList.filter((e) => e[valueKey] !== option[valueKey])
|
||||
: [...selectedList, option];
|
||||
if (isFullObject) onChange(updated);
|
||||
else onChange(updated.map((x) => x[valueKey]));
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!value || isFullObject) return;
|
||||
|
||||
const exists = options.some((o) => o[valueKey] === value);
|
||||
if (exists) return;
|
||||
|
||||
const loadSingleEmployee = async () => {
|
||||
try {
|
||||
const emp = await EmployeeRepository.getEmployeeName(
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
value
|
||||
);
|
||||
setForcedSelected(emp.data[0]);
|
||||
} catch (err) {
|
||||
console.error("Failed to load selected employee", err);
|
||||
}
|
||||
};
|
||||
|
||||
loadSingleEmployee();
|
||||
}, [value, options, isFullObject, valueKey]);
|
||||
|
||||
return (
|
||||
<div className="mb-3 position-relative" ref={dropdownRef}>
|
||||
{label && (
|
||||
@ -126,7 +128,6 @@ const SelectEmployeeServerSide = ({
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{/* DROPDOWN */}
|
||||
{open && (
|
||||
<ul
|
||||
className="dropdown-menu w-100 shadow-sm show animate__fadeIn h-64 overflow-auto rounded"
|
||||
@ -137,10 +138,10 @@ const SelectEmployeeServerSide = ({
|
||||
zIndex: 1050,
|
||||
marginTop: "4px",
|
||||
borderRadius: "0.375rem",
|
||||
overflow: "hidden",
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<div className="p-1">
|
||||
<li className="p-1 sticky-top bg-white" style={{ zIndex: 10 }}>
|
||||
<input
|
||||
type="search"
|
||||
value={searchText}
|
||||
@ -148,7 +149,7 @@ const SelectEmployeeServerSide = ({
|
||||
className="form-control form-control-sm"
|
||||
placeholder="Search..."
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
{isLoading && (
|
||||
<li className="dropdown-item text-muted text-center">Loading...</li>
|
||||
@ -168,10 +169,12 @@ const SelectEmployeeServerSide = ({
|
||||
selectedSingle[valueKey] === option[valueKey];
|
||||
|
||||
return (
|
||||
<li key={option[valueKey]}>
|
||||
<li key={option[valueKey]} className="px-1 rounded">
|
||||
<button
|
||||
type="button"
|
||||
className={`dropdown-item ${isActive ? "active" : ""}`}
|
||||
className={`dropdown-item rounded ${
|
||||
isActive ? "active" : ""
|
||||
}`}
|
||||
onClick={() => handleSelect(option)}
|
||||
>
|
||||
{getDisplayName(option)}
|
||||
@ -184,6 +187,7 @@ const SelectEmployeeServerSide = ({
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectEmployeeServerSide;
|
||||
|
||||
export const SelectProjectField = ({
|
||||
@ -211,9 +215,6 @@ export const SelectProjectField = ({
|
||||
return `${project.name || ""}`.trim();
|
||||
};
|
||||
|
||||
/** -----------------------------
|
||||
* SELECTED OPTION (SINGLE)
|
||||
* ----------------------------- */
|
||||
let selectedSingle = null;
|
||||
|
||||
if (!isMultiple) {
|
||||
@ -222,9 +223,6 @@ export const SelectProjectField = ({
|
||||
selectedSingle = options.find((o) => o[valueKey] === value);
|
||||
}
|
||||
|
||||
/** -----------------------------
|
||||
* SELECTED OPTION (MULTIPLE)
|
||||
* ----------------------------- */
|
||||
let selectedList = [];
|
||||
|
||||
if (isMultiple && Array.isArray(value)) {
|
||||
@ -345,10 +343,12 @@ export const SelectProjectField = ({
|
||||
selectedSingle[valueKey] === option[valueKey];
|
||||
|
||||
return (
|
||||
<li key={option[valueKey]}>
|
||||
<li key={option[valueKey]} className="px-1 rounded w-full">
|
||||
<button
|
||||
type="button"
|
||||
className={`dropdown-item ${isActive ? "active" : ""}`}
|
||||
className={`dropdown-item rounded d-block text-truncate w-100 ${
|
||||
isActive ? "active" : ""
|
||||
}`}
|
||||
onClick={() => handleSelect(option)}
|
||||
>
|
||||
{getDisplayName(option)}
|
||||
@ -514,7 +514,7 @@ export const SelectFieldSearch = ({
|
||||
{/* DROPDOWN */}
|
||||
{open && (
|
||||
<ul
|
||||
className="dropdown-menu w-100 shadow-sm show animate__fadeIn h-64 overflow-auto rounded"
|
||||
className="dropdown-menu w-100 shadow-sm show animate__fadeIn h-64 overflow-auto rounded overflow-x-hidden"
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "100%",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user