/* 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 ( <>
); } } 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;