/* eslint-disable @typescript-eslint/no-explicit-any */
// CustomizedSelect: Proper select box component styled like SelectField
import React, { useState, useRef, useEffect } from "react";
import ThreeDotsLoader from "../Loader/ThreeDotsLoader";
import { createBuilding, createRoad } from "../../Api/CustomerApi";
interface Options {
id: string;
name: string;
code: string;
}
interface Option {
id: string;
name: string;
code: string;
}
interface CustomizedSelectProps {
options: Options[];
value: string | Option | null;
onChange: (value: string | Option | null) => void;
errors?: string;
placeholder?: string;
className?: string;
width?: string;
icon?: React.ReactNode;
label?: string;
allowNewOption?: boolean;
isCreatable?: boolean;
isCreatableModal?: boolean;
isLoading?: boolean;
name?: string;
otherInfo?:
| {
road?: { id: number; name: string; code?: string };
block?: { id: number; name: string; code?: string };
}
| any;
}
export const CustomizedSelect: React.FC = ({
options = [],
value,
onChange,
errors,
placeholder = "Select an option",
className = "",
width = "",
icon,
label,
allowNewOption = false,
isCreatable = false,
isCreatableModal = false,
isLoading = false,
name = "",
otherInfo
}) => {
const [showDropdown, setShowDropdown] = useState(false);
const [searchQuery, setSearchQuery] = useState("");
const selectRef = useRef(null);
const [localOptions, setLocalOptions] = useState(options);
useEffect(() => {
setLocalOptions(options);
}, [options]);
useEffect(() => {
if (!showDropdown) return;
const handleClickOutside = (event: MouseEvent) => {
if (
selectRef.current &&
!selectRef.current.contains(event.target as Node)
) {
setShowDropdown(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, [showDropdown]);
const handleOptionSelect = (option: Option) => {
onChange(option);
setShowDropdown(false);
setSearchQuery(option.code);
};
const handleToggleDropdown = () => {
if (!isLoading) {
setShowDropdown(!showDropdown);
if (!showDropdown)
setSearchQuery(
typeof value === "object" && value !== null ? value.code : value || ""
);
}
};
const handleClearSelection = () => {
onChange(null);
setSearchQuery("");
};
const isOptionSelected = typeof value === "object" && value !== null;
// Filter options by search query (code or name, case-insensitive)
const filteredOptions = localOptions.filter((option) => {
const q = searchQuery ? searchQuery.trim().toLowerCase() : "";
if (!q) return true;
return (
option.name.toLowerCase().includes(q) ||
(option.code && option.code.toLowerCase().includes(q))
);
});
const handleRoadSave = async (newRoad: Option ) => {
try {
const response = await createRoad({...newRoad, block_id: otherInfo?.block?.id});
console.log(response?.status,'response>>>>>>>>>>>>>>>>>>>>>>>')
if (response && response.status) {
const {id = "", name = "", code = ""} = response?.data;
const newOption: Option = {
id: id ||newRoad?.id,
name: name || newRoad?.name,
code: code || newRoad?.code,
};
const updatedOptions = [...localOptions, newOption];
setLocalOptions(updatedOptions);
onChange(newOption);
setShowDropdown(false);
setSearchQuery(newOption.name);
}
// else {
// const updatedOptions = [...localOptions, newRoad];
// setLocalOptions(updatedOptions);
// onChange(newRoad);
// setShowDropdown(false);
// setSearchQuery(newRoad.name);
// }
} catch (error: any) {
console.log(error)
// const updatedOptions = [...localOptions, newRoad];
// setLocalOptions(updatedOptions);
// onChange(newRoad);
// setShowDropdown(false);
// setSearchQuery(newRoad.name);
}
};
const handleBuildingSave = async (newRoad: any ) => {
try {
const response = await createBuilding({...newRoad, block_id: otherInfo?.block?.id, road_id: otherInfo?.road?.id});
console.log(response?.status,'response>>>>>>>>>>>>>>>>>>>>>>>')
if (response && response.status) {
const {id = "", name = "", code = ""} = response?.data;
const newOption: Option = {
id: id ||newRoad?.id,
name: name || newRoad?.name,
code: code || newRoad?.code,
};
const updatedOptions = [...localOptions, newOption];
setLocalOptions(updatedOptions);
onChange(newOption);
setShowDropdown(false);
setSearchQuery(newOption.name);
}
// else {
// const updatedOptions = [...localOptions, newRoad];
// setLocalOptions(updatedOptions);
// onChange(newRoad);
// setShowDropdown(false);
// setSearchQuery(newRoad.name);
// }
} catch (error: any) {
console.log(error)
// const updatedOptions = [...localOptions, newRoad];
// setLocalOptions(updatedOptions);
// onChange(newRoad);
// setShowDropdown(false);
// setSearchQuery(newRoad.name);
}
};
const handleAddNewOption = () => {
const trimmedQuery = searchQuery ? searchQuery.trim() : '';
if (!trimmedQuery) return;
// Prevent duplicate
const exists = localOptions.some(
(option) => option.name.toLowerCase() === trimmedQuery.toLowerCase()
);
if (exists) return;
const newOption = {
id: trimmedQuery,
name: trimmedQuery,
code: trimmedQuery,
};
if(name === 'Road No' && typeof trimmedQuery === 'string') {
handleRoadSave(newOption)
}
else if(name === 'Building No' && typeof trimmedQuery === 'string') {
handleBuildingSave({...newOption, road_id: 1})
}
else {
const updatedOptions = [...localOptions, newOption];
setLocalOptions(updatedOptions);
onChange(newOption);
setShowDropdown(false);
setSearchQuery(newOption.name);
}
};
const handleInputChange = (e: React.ChangeEvent) => {
setSearchQuery(e.target.value);
setShowDropdown(true);
if (allowNewOption) {
onChange(e.target.value);
}
};
const handleInputKeyDown = (e: React.KeyboardEvent) => {
if (
e.key === "Enter" &&
isCreatable &&
searchQuery && searchQuery.trim() !== "" &&
!localOptions.some(
(option) =>
option.name.toLowerCase() === searchQuery.trim().toLowerCase()
)
) {
e.preventDefault();
handleAddNewOption();
}
};
// const getDisplayValue = () => {
// if (typeof value === 'object' && value !== null) {
// return value.name;
// }
// return value || placeholder;
// };
function formatCreateLabel(inputValue: string): React.ReactNode {
if (inputValue.trim() === "") {
return Add;
} else {
return (
<>
*/}
{/* {name === 'buildingNo' && referenceData?.road?.name && referenceData?.block?.name && (
Road - {referenceData?.road?.code}{(referenceData?.road?.name && referenceData?.road?.name !== referenceData?.road?.code) ? `, ${referenceData?.road?.name}` : ''}, Block - {referenceData?.block?.code}{(referenceData?.block?.name && referenceData?.block?.name !== referenceData?.block?.code) ? `, ${referenceData?.block?.name}` : ''}
)} */}
>
);
}
}
return (
<>
{/* Icon */}
{icon && (
)}
setShowDropdown(true)}
/>
{/* Actions: clear, loader, arrow */}
{isOptionSelected && (
)}
{isLoading && (
)}
▼
{/* Dropdown */}
{showDropdown && (
{isCreatable &&
searchQuery &&
searchQuery.trim() !== "" &&
!localOptions.some(
(option) =>
option.name.toLowerCase() === searchQuery.trim().toLowerCase()
) ? (
<>{formatCreateLabel(searchQuery)}>
) : null}
{filteredOptions.length > 0 && (
<>
{filteredOptions.map((option) => (
handleOptionSelect(option)}
>
{option?.id === "add-new" ? (
<>
Add
{name}
{" "}
>
) : (
<>
{option?.code ? `${option?.code} - ` : ""}
{option.name}
>
)}
))}
>
)}
{!allowNewOption && filteredOptions.length === 0 && (
<>
{isCreatableModal ? (
<>
handleOptionSelect({ id: "add-new", name: "", code: "" })
}
>
Add
{name}
No options available
>
) : (
<>
No options available
>
)}
>
)}
)}
{/* Label */}
{label && (
)}
>
);
};
export default CustomizedSelect;