fix(MultiSelect): enhance item handling and improve empty state display

- Update MultiSelect component to allow items to be optional or null, improving flexibility.
- Implement safe handling of items to prevent errors when items are not provided.
- Add a message to display when no items are available, enhancing user experience.
- Refactor rendering logic for selected items to maintain consistent styling.
This commit is contained in:
AmirReza Jamali
2026-03-07 10:53:12 +03:30
parent 992debb603
commit 26c092db4a
3 changed files with 46 additions and 38 deletions
+44 -36
View File
@@ -17,7 +17,7 @@ interface Option {
type MultiSelectProps<T extends FieldValues> = {
label: string;
items: { value: string; label: string }[];
items?: { value: string; label: string }[] | null;
value?: string[];
errors?: FieldErrors<T>;
required?: boolean;
@@ -54,13 +54,15 @@ function MultiSelect<T extends FieldValues>({
const trigger = useRef<HTMLDivElement | null>(null);
useEffect(() => {
const newOptions = items.map((item) => ({
const safeItems = Array.isArray(items) ? items : [];
const newOptions = safeItems.map((item) => ({
...item,
selected: value?.includes(item.value) ?? false,
}));
setOptions(newOptions);
const newSelectedIndices = items
const newSelectedIndices = safeItems
.map((item, index) => (value?.includes(item.value) ? index : -1))
.filter((index) => index !== -1);
setSelected(newSelectedIndices);
@@ -215,40 +217,46 @@ function MultiSelect<T extends FieldValues>({
ref={dropdownRef}
>
<div className="py-1">
{options.map((option, index) => (
<div
key={index}
className={cn(
"flex cursor-pointer items-center px-3 py-2 text-sm text-dark hover:bg-primary/5 dark:text-white dark:hover:bg-primary/5",
option.selected && "bg-primary/10 dark:bg-primary/20",
)}
onClick={() => handleSelect(index)}
>
<div
className={cn(
"mr-3 h-4 w-4 rounded border-2",
option.selected
? "border-primary bg-primary"
: "border-stroke dark:border-dark-3",
)}
>
{option.selected && (
<svg
className="h-full w-full text-white"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</div>
{option.label}
{options.length === 0 ? (
<div className="px-3 py-2 text-sm text-dark-6 dark:text-dark-6">
No items are available
</div>
))}
) : (
options.map((option, index) => (
<div
key={index}
className={cn(
"flex cursor-pointer items-center px-3 py-2 text-sm text-dark hover:bg-primary/5 dark:text-white dark:hover:bg-primary/5",
option.selected && "bg-primary/10 dark:bg-primary/20",
)}
onClick={() => handleSelect(index)}
>
<div
className={cn(
"mr-3 h-4 w-4 rounded border-2",
option.selected
? "border-primary bg-primary"
: "border-stroke dark:border-dark-3",
)}
>
{option.selected && (
<svg
className="h-full w-full text-white"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
clipRule="evenodd"
/>
</svg>
)}
</div>
{option.label}
</div>
))
)}
</div>
</div>
</div>
+1 -1
View File
@@ -14,7 +14,7 @@ import { Tooltip } from "react-tooltip";
import useTenderListPresenter from "./useTenderListPresenter";
import { ExclamationIcon, EyeIcon } from "@/assets/icons";
import EmptyListWrapper from "@/components/HOC/EmptyListWrapper";
import ListHeader from "@/components/ui/ListHeader";
import Modal from "@/components/ui/modal";
import Pagination from "@/components/ui/pagination";