diff --git a/src/components/BMDashboard/ItemList/ItemListView.module.css b/src/components/BMDashboard/ItemList/ItemListView.module.css index 21335b697f..d885a1b9b1 100644 --- a/src/components/BMDashboard/ItemList/ItemListView.module.css +++ b/src/components/BMDashboard/ItemList/ItemListView.module.css @@ -41,10 +41,11 @@ .selectInput { display: grid; - grid-template-columns: auto 1fr auto 1fr auto 1fr; + grid-template-columns: auto 1fr auto 1fr; align-items: center; gap: 15px; width: 100%; + min-width: 400px; max-width: 1200px; margin: 0 auto 10px auto; overflow: visible; @@ -62,14 +63,20 @@ .selectInput select { height: 38px; width: 100%; - min-width: 220px; - max-width: 240px; + min-width: 400px; + max-width: 1200px; padding: 5px; border: 1px solid #ccc; border-radius: 4px; margin-bottom: 8px; } +.selectInput :global(.react-select__control) { + width: 100%; + max-width: 1200px; + min-width: 400px; +} + .selectInput input[type='text'] { padding: 5px; margin-bottom: 8px; diff --git a/src/components/BMDashboard/ItemList/SelectForm.jsx b/src/components/BMDashboard/ItemList/SelectForm.jsx index 27f62b6848..226c47bc60 100644 --- a/src/components/BMDashboard/ItemList/SelectForm.jsx +++ b/src/components/BMDashboard/ItemList/SelectForm.jsx @@ -1,43 +1,61 @@ -import { Form, FormGroup, Label, Input } from 'reactstrap'; +import { useEffect, useMemo, useState } from 'react'; +import { Form, FormGroup, Label } from 'reactstrap'; +import Select from 'react-select'; import styles from './ItemListView.module.css'; +const PROJECT_KEY = 'tool_selected_projects'; + export default function SelectForm({ items, setSelectedProject, setSelectedItem }) { - let projectsSet = []; - if (items.length) { - projectsSet = [...new Set(items.map(el => el.project?.name))]; - } + const [selectedProjects, setSelectedProjects] = useState([]); + + // Build project list + const projectOptions = useMemo(() => { + if (!items?.length) return []; + const unique = [...new Set(items.map(i => i.project?.name).filter(Boolean))]; + return unique.map(name => ({ + label: name, + value: name, + })); + }, [items]); + + // Restore saved values + useEffect(() => { + const saved = JSON.parse(localStorage.getItem(PROJECT_KEY)); + + if (Array.isArray(saved)) { + setSelectedProjects(saved); + setSelectedProject(saved.map(p => p.value)); + } + }, []); - const handleChange = event => { + const handleChange = selected => { + const values = selected || []; + + setSelectedProjects(values); setSelectedItem('all'); - setSelectedProject(event.target.value); + setSelectedProject(values.length ? values.map(v => v.value) : 'all'); + + localStorage.setItem(PROJECT_KEY, JSON.stringify(values)); }; return (
); diff --git a/src/components/BMDashboard/ItemList/SelectItem.jsx b/src/components/BMDashboard/ItemList/SelectItem.jsx index 88901967ed..4ff303f428 100644 --- a/src/components/BMDashboard/ItemList/SelectItem.jsx +++ b/src/components/BMDashboard/ItemList/SelectItem.jsx @@ -1,6 +1,10 @@ -import { Form, FormGroup, Label, Input } from 'reactstrap'; +import { useEffect, useMemo, useState } from 'react'; +import { Form, FormGroup, Label } from 'reactstrap'; +import Select from 'react-select'; import styles from './ItemListView.module.css'; +const ITEM_KEY = 'tool_selected_items'; + export default function SelectItem({ items, selectedProject, @@ -8,56 +12,81 @@ export default function SelectItem({ setSelectedItem, label, }) { - let itemSet = []; - if (items?.length) { - if (selectedProject === 'all') { - itemSet = [ - ...new Set( - items - .filter(m => m.itemType?.name) // Filter out items with null/undefined names - .map(m => m.itemType.name), - ), - ]; + const [localValues, setLocalValues] = useState([]); + + // ✅ Build filtered tool options + const itemOptions = useMemo(() => { + if (!items?.length) return []; + + let list = items; + + if (Array.isArray(selectedProject)) { + list = items.filter(i => selectedProject.includes(i.project?.name) && i.itemType?.name); + } else if (selectedProject !== 'all') { + list = items.filter(i => i.project?.name === selectedProject && i.itemType?.name); } else { - itemSet = [ - ...new Set( - items - .filter(mat => mat.project?.name === selectedProject && mat.itemType?.name) - .map(m => m.itemType.name), - ), - ]; + list = items.filter(i => i.itemType?.name); + } + + const names = [...new Set(list.map(i => i.itemType.name))]; + + return names.map(name => ({ + label: name, + value: name, + })); + }, [items, selectedProject]); + + // ✅ Restore saved selections + useEffect(() => { + const saved = JSON.parse(localStorage.getItem(ITEM_KEY)); + + if (Array.isArray(saved)) { + setLocalValues(saved); + setSelectedItem(saved.map(s => s.value)); } - } + }, []); + + // ✅ Sync reset from parent + useEffect(() => { + const isMulti = Array.isArray(selectedItem); + + if (selectedItem === 'all' || (isMulti && selectedItem.length === 0)) { + setLocalValues([]); + } + }, [selectedItem]); + + const handleChange = selected => { + const values = selected || []; + + setLocalValues(values); + setSelectedItem(values.length ? values.map(v => v.value) : 'all'); + + localStorage.setItem(ITEM_KEY, JSON.stringify(values)); + }; return ( ); diff --git a/src/components/BMDashboard/ToolItemList/ToolItemListView.jsx b/src/components/BMDashboard/ToolItemList/ToolItemListView.jsx index 4278d478d8..3950b55338 100644 --- a/src/components/BMDashboard/ToolItemList/ToolItemListView.jsx +++ b/src/components/BMDashboard/ToolItemList/ToolItemListView.jsx @@ -13,49 +13,65 @@ export function ToolItemListView({ UpdateItemModal, dynamicColumns, }) { - const [filteredItems, setFilteredItems] = useState(items); + const [filteredItems, setFilteredItems] = useState([]); const [selectedProject, setSelectedProject] = useState('all'); const [selectedItem, setSelectedItem] = useState('all'); const [isError, setIsError] = useState(false); + // Load initial items useEffect(() => { - if (items) setFilteredItems([...items]); + if (Array.isArray(items)) { + setFilteredItems([...items]); + } }, [items]); + // ✅ FULL multi-select compatible filtering useEffect(() => { - let filterItems; - if (!items) return; - if (selectedProject === 'all' && selectedItem === 'all') { - setFilteredItems([...items]); - } else if (selectedProject !== 'all' && selectedItem === 'all') { - filterItems = items.filter(item => item.project?.name === selectedProject); - setFilteredItems([...filterItems]); - } else if (selectedProject === 'all' && selectedItem !== 'all') { - filterItems = items.filter(item => item.itemType?.name === selectedItem); - setFilteredItems([...filterItems]); - } else { - filterItems = items.filter( - item => item.project?.name === selectedProject && item.itemType?.name === selectedItem, - ); - setFilteredItems([...filterItems]); + if (!Array.isArray(items)) return; + + const projectIsMulti = Array.isArray(selectedProject); + const itemIsMulti = Array.isArray(selectedItem); + + const hasProjects = projectIsMulti && selectedProject.length > 0; + const hasItems = itemIsMulti && selectedItem.length > 0; + + let result = [...items]; + + // ✅ Project filter (single + multi) + if (hasProjects) { + result = result.filter(item => selectedProject.includes(item.project?.name)); + } else if (!projectIsMulti && selectedProject !== 'all') { + result = result.filter(item => item.project?.name === selectedProject); } + + // ✅ Item / Tool filter (single + multi) + if (hasItems) { + result = result.filter(item => selectedItem.includes(item.itemType?.name)); + } else if (!itemIsMulti && selectedItem !== 'all') { + result = result.filter(item => item.itemType?.name === selectedItem); + } + + setFilteredItems(result); }, [selectedProject, selectedItem, items]); + // Error handling useEffect(() => { setIsError(Object.entries(errors).length > 0); }, [errors]); if (isError) { return ( -