Dwinzo_dev/app/src/components/ui/inputs/MultiLevelDropDown.tsx

281 lines
7.8 KiB
TypeScript
Raw Normal View History

2025-03-26 12:57:58 +00:00
// import React, { useState, useRef, useEffect } from "react";
// // Dropdown Item Component
// const DropdownItem = ({
// label,
// href,
// onClick,
// }: {
// label: string;
// href?: string;
// onClick?: () => void;
// }) => (
// <a
// href={href || "#"}
// className="dropdown-item"
// onClick={(e) => {
// e.preventDefault();
// onClick?.();
// }}
// >
// {label}
// </a>
// );
// // Nested Dropdown Component
// const NestedDropdown = ({
// label,
// children,
// onSelect,
// }: {
// label: string;
// children: React.ReactNode;
// onSelect: (selectedLabel: string) => void;
// }) => {
// const [open, setOpen] = useState(false);
// return (
// <div className="nested-dropdown">
// {/* Dropdown Trigger */}
// <div
// className={`dropdown-trigger ${open ? "open" : ""}`}
// onClick={() => setOpen(!open)} // Toggle submenu on click
// >
// {label} <span className="icon">{open ? "▼" : "▶"}</span>
// </div>
// {/* Submenu */}
// {open && (
// <div className="submenu">
// {React.Children.map(children, (child) => {
// if (React.isValidElement(child)) {
// // Clone the element and pass the `onSelect` prop only if it's expected
// return React.cloneElement(child as React.ReactElement<any>, { onSelect });
// }
// return child; // Return non-element children as-is
// })}
// </div>
// )}
// </div>
// );
// };
// // Recursive Function to Render Nested Data
// const renderNestedData = (
// data: Record<string, any>,
// onSelect: (selectedLabel: string) => void
// ) => {
// return Object.entries(data).map(([key, value]) => {
// if (typeof value === "object" && !Array.isArray(value)) {
// // If the value is an object, render it as a nested dropdown
// return (
// <NestedDropdown key={key} label={key} onSelect={onSelect}>
// {renderNestedData(value, onSelect)}
// </NestedDropdown>
// );
// } else if (Array.isArray(value)) {
// // If the value is an array, render each item as a dropdown item
// return value.map((item, index) => (
// <DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
// ));
// } else {
// // If the value is a simple string, render it as a dropdown item
// return (
// <DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
// );
// }
// });
// };
// // Main Multi-Level Dropdown Component
// const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
// const [open, setOpen] = useState(false);
// const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
// const dropdownRef = useRef<HTMLDivElement>(null);
// // Handle outer click to close the dropdown
// useEffect(() => {
// const handleClickOutside = (event: MouseEvent) => {
// if (
// dropdownRef.current &&
// !dropdownRef.current.contains(event.target as Node)
// ) {
// setOpen(false);
// }
// };
// document.addEventListener("mousedown", handleClickOutside);
// return () => {
// document.removeEventListener("mousedown", handleClickOutside);
// };
// }, []);
// // Handle selection of an item
// const handleSelect = (selectedLabel: string) => {
// setSelectedLabel(selectedLabel); // Update the dropdown trigger text
// setOpen(false); // Close the dropdown
// };
// return (
// <div className="multi-level-dropdown" ref={dropdownRef}>
// {/* Dropdown Trigger Button */}
// <button
// className={`dropdown-button ${open ? "open" : ""}`}
// onClick={() => setOpen(!open)} // Toggle main menu on click
// >
// {selectedLabel} <span className="icon">▾</span>
// </button>
// {/* Dropdown Menu */}
// {open && (
// <div className="dropdown-menu">
// <div className="dropdown-content">
// {renderNestedData(data, handleSelect)}
// </div>
// </div>
// )}
// </div>
// );
// };
// export default MultiLevelDropdown;
2025-03-25 12:04:20 +00:00
import React, { useState, useRef, useEffect } from "react";
import { ArrowIcon } from "../../icons/ExportCommonIcons";
2025-03-25 12:04:20 +00:00
// Dropdown Item Component
const DropdownItem = ({
label,
onClick,
}: {
label: string;
2025-03-26 12:57:58 +00:00
onClick: () => void;
2025-03-25 12:04:20 +00:00
}) => (
2025-03-26 12:57:58 +00:00
<div className="dropdown-item" onClick={onClick}>
2025-03-25 12:04:20 +00:00
{label}
2025-03-26 12:57:58 +00:00
</div>
2025-03-25 12:04:20 +00:00
);
// Nested Dropdown Component
const NestedDropdown = ({
label,
2025-03-26 12:57:58 +00:00
fields,
2025-03-25 12:04:20 +00:00
onSelect,
}: {
label: string;
2025-03-26 12:57:58 +00:00
fields: string[];
onSelect: (selectedData: { name: string; fields: string }) => void;
2025-03-25 12:04:20 +00:00
}) => {
const [open, setOpen] = useState(false);
return (
<div className="nested-dropdown">
<div
className={`dropdown-trigger ${open ? "open" : ""}`}
2025-03-26 12:57:58 +00:00
onClick={() => setOpen(!open)}
2025-03-25 12:04:20 +00:00
>
{label}
<div
className="arrow-container"
style={{ rotate: open ? "" : "-90deg" }}
>
<ArrowIcon />
</div>
2025-03-25 12:04:20 +00:00
</div>
{open && (
<div className="submenu">
2025-03-26 12:57:58 +00:00
{fields.map((field) => (
<DropdownItem
key={field}
label={field}
onClick={() => onSelect({ name: label, fields: field })}
/>
))}
2025-03-25 12:04:20 +00:00
</div>
)}
</div>
);
};
2025-03-26 12:57:58 +00:00
// Props type for MultiLevelDropdown
interface MultiLevelDropdownProps {
data: Record<string, any>;
onSelect: (selectedData: { name: string; fields: string }) => void;
onUnselect: () => void;
selectedValue?: { name: string; fields: string };
}
2025-03-25 12:04:20 +00:00
// Main Multi-Level Dropdown Component
const MultiLevelDropdown = ({
data,
onSelect,
2025-03-26 12:57:58 +00:00
onUnselect,
selectedValue,
2025-03-26 12:57:58 +00:00
}: MultiLevelDropdownProps) => {
2025-03-25 12:04:20 +00:00
const [open, setOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
2025-03-26 12:57:58 +00:00
// Handle item selection
const handleItemSelect = (selectedData: { name: string; fields: string }) => {
onSelect(selectedData);
setOpen(false);
2025-03-25 12:04:20 +00:00
};
2025-03-26 12:57:58 +00:00
// Handle unselect
const handleItemUnselect = () => {
onUnselect();
setOpen(false);
2025-03-25 12:04:20 +00:00
};
2025-03-26 12:57:58 +00:00
// Determine the display label
const displayLabel = selectedValue
2025-03-26 12:57:58 +00:00
? `${selectedValue.name} - ${selectedValue.fields}`
: "Dropdown trigger";
2025-03-25 12:04:20 +00:00
return (
<div className="multi-level-dropdown" ref={dropdownRef}>
<button
className={`dropdown-button ${open ? "open" : ""}`}
2025-03-26 12:57:58 +00:00
onClick={() => setOpen(!open)}
2025-03-25 12:04:20 +00:00
>
<div className="label">{displayLabel}</div>
<span className="icon"></span>
2025-03-25 12:04:20 +00:00
</button>
{open && (
<div className="dropdown-menu">
<div className="dropdown-content">
2025-03-26 12:57:58 +00:00
{/* Unselect Option */}
<DropdownItem label="Unselect" onClick={handleItemUnselect} />
{/* Nested Dropdown Items */}
{Object.entries(data).map(([key, value]) => (
<NestedDropdown
key={key}
label={key}
fields={Object.keys(value)}
onSelect={handleItemSelect}
/>
))}
2025-03-25 12:04:20 +00:00
</div>
</div>
)}
</div>
);
};
2025-03-26 12:57:58 +00:00
export default MultiLevelDropdown;