diff --git a/src/app-bundles/product-filter-bundle.js b/src/app-bundles/product-filter-bundle.js index 41c2644..97be96c 100644 --- a/src/app-bundles/product-filter-bundle.js +++ b/src/app-bundles/product-filter-bundle.js @@ -12,6 +12,7 @@ const productFilterBundle = { dateFrom: new Date(), dateTo: new Date(), tags: [], + requiredTags: [], // Tags that products MUST have (AND logic) parameters: [], }; @@ -45,6 +46,10 @@ const productFilterBundle = { return state.productFilter.tags; }, + selectProductFilterRequiredTags: (state) => { + return state.productFilter.requiredTags; + }, + selectProductFilterParameters: (state) => { return state.productFilter.parameters; }, @@ -56,6 +61,7 @@ const productFilterBundle = { 'selectProductFilterDateFrom', 'selectProductFilterDateTo', 'selectProductFilterTags', + 'selectProductFilterRequiredTags', 'selectProductFilterParameters', ( items, @@ -64,8 +70,14 @@ const productFilterBundle = { dateFrom, dateTo, tags, + requiredTags, parameters ) => { + // Safety check - if items is not available yet, return empty array + if (!items || !Array.isArray(items)) { + return []; + } + return items.filter((product) => { let pass = true; @@ -96,7 +108,17 @@ const productFilterBundle = { } } - // apply tag filters + // apply required tag filters (must have ALL of these tags - AND logic) + if (pass && requiredTags.length > 0) { + for (var r = 0; r < requiredTags.length; r++) { + if (product.tags.indexOf(requiredTags[r]) === -1) { + pass = false; + break; + } + } + } + + // apply tag filters (must have ANY of these tags - OR logic) if (pass && tags.length > 0) { let matchFound = false; for (var t = 0; t < product.tags.length; t++) { @@ -174,6 +196,17 @@ const productFilterBundle = { }); }, + doProductFilterSetRequiredTags: + (requiredTags) => + ({ dispatch }) => { + dispatch({ + type: 'PRODUCT_FILTER_SET_VALUE', + payload: { + requiredTags, + }, + }); + }, + doProductFilterSetParameters: (parameters) => ({ dispatch }) => { diff --git a/src/app-pages/products/products.js b/src/app-pages/products/products.js index 0c09f64..c7b8d10 100644 --- a/src/app-pages/products/products.js +++ b/src/app-pages/products/products.js @@ -30,11 +30,13 @@ export default connect( 'selectProductDateRangeFrom', 'selectProductDateRangeTo', 'selectProductSelectSelected', + 'selectProductFilterRequiredTags', 'doModalOpen', 'doProductFilterSetFilterString', 'doProductFilterSetDateFrom', 'doProductFilterSetDateTo', 'doProductFilterSetApplyDateFilter', + 'doProductFilterSetRequiredTags', ({ authIsLoggedIn, productFilterResults: products, @@ -43,12 +45,17 @@ export default connect( productDateRangeFrom: rangeFrom, productDateRangeTo: rangeTo, productSelectSelected: selectedProducts, + productFilterRequiredTags: requiredTags, doModalOpen, doProductFilterSetFilterString: setFilterString, doProductFilterSetDateFrom: setFilterDateFrom, doProductFilterSetDateTo: setFilterDateTo, doProductFilterSetApplyDateFilter: setApplyDateFilter, + doProductFilterSetRequiredTags: setRequiredTags, }) => { + // Tab state - 'primary' or 'all' + const [activeTab, setActiveTab] = useState('primary'); + // show / hide the filter panel const [filtersActive, setFiltersActive] = useState(false); @@ -118,6 +125,31 @@ export default connect( doModalOpen(DownloadModal); }, [doModalOpen]); + // Handle tab switching and apply tag filter accordingly + const handleTabChange = useCallback((tab) => { + setActiveTab(tab); + const primarySourceTagId = '8a7f4e6b-3c2d-4a9f-b1e5-9d8c7a6f5e4d'; + + if (tab === 'primary') { + // Require "primary source" tag (exclusive filter) + if (!requiredTags.includes(primarySourceTagId)) { + setRequiredTags([...requiredTags, primarySourceTagId]); + } + } else { + // Remove "primary source" from required tags to show all sources + setRequiredTags(requiredTags.filter(tag => tag !== primarySourceTagId)); + } + }, [setRequiredTags, requiredTags]); + + // Apply the initial filter when component mounts + useEffect(() => { + const primarySourceTagId = '8a7f4e6b-3c2d-4a9f-b1e5-9d8c7a6f5e4d'; + // Only initialize once + if (activeTab === 'primary' && requiredTags.length === 0) { + setRequiredTags([primarySourceTagId]); + } + }, [activeTab, requiredTags, setRequiredTags]); + return ( <>