Index: components/Filters/AttributeValueFilter/AttributeValueFilter.component.tsx =================================================================== diff -u -rc9ac16c365bb8ed527371e5694d9b24a56959a80 -ra9a134538ec2a00ada5890cb60e7363ed2a90b29 --- components/Filters/AttributeValueFilter/AttributeValueFilter.component.tsx (.../AttributeValueFilter.component.tsx) (revision c9ac16c365bb8ed527371e5694d9b24a56959a80) +++ components/Filters/AttributeValueFilter/AttributeValueFilter.component.tsx (.../AttributeValueFilter.component.tsx) (revision a9a134538ec2a00ada5890cb60e7363ed2a90b29) @@ -1,54 +1,216 @@ import { Filter } from 'lemans-common'; -import { FilterGenerator, FilterUpdater, IFilterGeneratorProps } from 'lemans-common/components/FilterGroup/FilterGroup.types'; +import { FilterGenerator, FilterMode, FilterUpdater, IFilterGeneratorProps } from 'lemans-common/components/FilterGroup/FilterGroup.types'; import { service } from 'lemans-dashboard-common'; +import { useState, useEffect } from 'react'; import { addNoValue } from '../../Autocompletes/AttributeValueAutocomplete/AttributeValueAutocomplete.component'; import { AttributeValueFilterProps } from './AttributeValueFilter.types'; import { AttributeValueFilterElement } from './AttributeValueFilterElement'; import { IAttributeValueFilterElementState } from './AttributeValueFilterElement/AttributeValueFilterElement.types'; -const filterUpdate = (_id:string, updater:FilterUpdater) => (values:any) => { - updater({attribute: values}); -}; +// This function fetches the data needed for the breadcrumb display +const fetchBreadcrumbData = (state: IAttributeValueFilterElementState) => (_value: any) => () => { + // If state is undefined or doesn't have required properties, return empty data + if (!state || !state.attributeNameId) { + console.log("Missing required data for AttributeValue breadcrumb:", state); + return Promise.resolve({ body: { results: [] } }); + } -const fetchBreadcrumbData = (state:IAttributeValueFilterElementState) => (_value:any) => () => { + console.log("Fetching breadcrumb data for AttributeValueFilter:", state); + + // Fetch attribute name and values in parallel return Promise.all([ service.attribute.getAttrNameById(Number(state.attributeNameId)), - service.attribute.getAttrNameValuesRaw(Number(state.attributeNameId)) - ]).then( ([attributeName, attributeValueArray]) => { - // Add no value option to the response list - const valueResponse = addNoValue(attributeValueArray); - const attributeValue = valueResponse.body.results.find( - (item:any) => item.attributeValueId.toString() === state.attributeValueId!.toString() - ); + // Only fetch attribute values if we're not using "Any Value" or "No Value" + state.attributeValueId && state.attributeValueId !== '-1' && state.attributeValueId !== '0' + ? service.attribute.getAttrNameValuesRaw(Number(state.attributeNameId)) + : Promise.resolve({ body: { results: [] } }) + ]).then(([attributeName, attributeValueArray]) => { + let attributeValue: any; + + // Handle special cases for "Any Value" (-1) and "No Value" (0) + if (state.attributeValueId === '-1') { + attributeValue = { attributeValueId: -1, attributeValue: '--ANY-VALUE--' }; + } else if (state.attributeValueId === '0') { + attributeValue = { attributeValueId: 0, attributeValue: '--NO-VALUE--' }; + } else if (attributeValueArray && 'body' in attributeValueArray && attributeValueArray.body && attributeValueArray.body.results) { + // Add no value option to the response list + const valueResponse = addNoValue(attributeValueArray); + attributeValue = valueResponse.body.results.find( + (item: any) => item.attributeValueId.toString() === state.attributeValueId!.toString() + ); + } - // Combine results to a single result set that can be parsed by async value component - const data = { + // Format the response for the AsyncValue component to properly display + if (!attributeName || !attributeName.body || !attributeName.body.results || !attributeName.body.results.length || !attributeValue) { + console.error("Missing attribute data for breadcrumb", { attributeName, attributeValue }); + return { body: { results: [] } }; + } + + const result = { body: { - results: [attributeName.body.results, attributeValue] + results: [`${attributeName.body.results[0].attributeName} = ${attributeValue.attributeValue}`] } - } - return data; + }; + console.log("AttributeValueFilter breadcrumb result:", result); + return result; + }).catch(error => { + console.error('Error fetching breadcrumb data:', error); + return { body: { results: [] } }; }); }; -const generateBreadcrumb = (_state:IAttributeValueFilterElementState) => (results:any) => { - const [attributeName, attributeValue] = results; - return `${attributeName.attributeName} = ${attributeValue.attributeValue}`; +// This function extracts the breadcrumb string from the results +const generateBreadcrumb = (_state: IAttributeValueFilterElementState) => (results: any) => { + if (!results || !results.body || !results.body.results || !Array.isArray(results.body.results) || results.body.results.length === 0) { + return ''; + } + return results.body.results[0]; // Return the pre-formatted string }; -export const AttributeValueFilter = (props:AttributeValueFilterProps):FilterGenerator => (generatorProps:IFilterGeneratorProps):JSX.Element => - +export const AttributeValueFilter = (props: AttributeValueFilterProps): FilterGenerator => { + // Store selected values for breadcrumb display + const selectedValuesMap = new Map(); + + // Custom update function that prevents duplicate URL parameters + const filterUpdate = (id: string, updater: FilterUpdater) => (values: IAttributeValueFilterElementState | undefined) => { + if (values) { + // Update the filter with the component-specific values + updater({ + [id]: values, + // Clear the global URL parameters to prevent duplication + attributeNameId: undefined, + attributeValueId: undefined + }); + + // Also update the selectedValues for breadcrumb display + selectedValuesMap.set(id, values); + } else { + // If values is undefined, clear both component-specific and global values + updater({ + [id]: undefined, + attributeNameId: undefined, + attributeValueId: undefined + }); + + // Also clear from selectedValues + selectedValuesMap.delete(id); } - breadcrumbCustomFetch={fetchBreadcrumbData(generatorProps.values[props.id])} - breadcrumbField={generateBreadcrumb(generatorProps.values[props.id])} - breadcrumbLabel={'Attribute'} - generatorProps={generatorProps} - valueId={props.id} - />; - \ No newline at end of file + }; + + const filterFunc = (generatorProps: IFilterGeneratorProps): JSX.Element => { + // Use state to track if we've processed URL parameters + const [processedUrlParams, setProcessedUrlParams] = useState(false); + // Use state to track the current breadcrumb value + const [breadcrumbValue, setBreadcrumbValue] = useState(undefined); + + // Process URL parameters once on component mount + useEffect(() => { + // Only run once + if (processedUrlParams) return; + + // Check for URL parameters + const hasGlobalUrlParams = generatorProps.values.attributeNameId || + generatorProps.values.attributeValueId !== undefined; + const noComponentValues = !generatorProps.values[props.id]; + + // Only process if we have URL parameters and no component values yet + if (hasGlobalUrlParams && noComponentValues) { + // Handle special cases for "Any Value" (-1) and "No Value" (0) + let attributeValueId = generatorProps.values.attributeValueId; + + // Ensure special values are properly handled as strings + if (attributeValueId === 0 || attributeValueId === -1) { + attributeValueId = attributeValueId.toString(); + } + + // Create attribute values from URL parameters + const attributeValues: IAttributeValueFilterElementState = { + attributeNameId: generatorProps.values.attributeNameId, + attributeValueId: attributeValueId + }; + + // Update the filter values and clear global URL parameters + generatorProps.update({ + [props.id]: attributeValues, + // Clear the global URL parameters to prevent duplication + attributeNameId: undefined, + attributeValueId: undefined + }); + + // Also update the selectedValues for breadcrumb display + selectedValuesMap.set(props.id, attributeValues); + setBreadcrumbValue(attributeValues); + + setProcessedUrlParams(true); + } + }, [generatorProps.values, props.id, processedUrlParams]); + + // Update breadcrumb value when filter values change + useEffect(() => { + const currentValues = generatorProps.values[props.id]; + if (currentValues) { + setBreadcrumbValue(currentValues); + selectedValuesMap.set(props.id, currentValues); + } + }, [generatorProps.values[props.id]]); + + // Get the current filter values + const filterValues = generatorProps.values[props.id] || {}; + + // Check if we have global URL parameters that need to be merged + if (!filterValues.attributeNameId && generatorProps.values.attributeNameId) { + filterValues.attributeNameId = generatorProps.values.attributeNameId; + } + + // Handle special cases for attributeValueId + if (!filterValues.attributeValueId && generatorProps.values.attributeValueId !== undefined) { + // Convert numeric values to strings for special cases + if (generatorProps.values.attributeValueId === 0) { + filterValues.attributeValueId = '0'; + } else if (generatorProps.values.attributeValueId === -1) { + filterValues.attributeValueId = '-1'; + } else { + filterValues.attributeValueId = generatorProps.values.attributeValueId; + } + } + + // For breadcrumb mode, we need to ensure the values are passed correctly + let valueForBreadcrumb = filterValues; + + if (generatorProps.mode === FilterMode.Breadcrumb) { + // In breadcrumb mode, use the stored breadcrumb value + if (breadcrumbValue) { + valueForBreadcrumb = breadcrumbValue; + } else if (selectedValuesMap.has(props.id)) { + valueForBreadcrumb = selectedValuesMap.get(props.id) || {}; + } + + console.log("AttributeValueFilter in breadcrumb mode:", { + filterValues, + selectedOptions: generatorProps.values, + valueId: props.id, + valueForBreadcrumb, + breadcrumbValue + }); + } + + return ( + + } + breadcrumbCustomFetch={fetchBreadcrumbData(valueForBreadcrumb)} + breadcrumbField={generateBreadcrumb(valueForBreadcrumb)} + breadcrumbLabel={'Attribute'} + generatorProps={generatorProps} + valueId={props.id} + /> + ); + }; + + return filterFunc; +}; \ No newline at end of file Index: components/Filters/AttributeValueFilter/AttributeValueFilterElement/AttributeValueFilterElement.component.tsx =================================================================== diff -u -r02034861c5b797d7c6f46da206243f74aca3fefe -ra9a134538ec2a00ada5890cb60e7363ed2a90b29 --- components/Filters/AttributeValueFilter/AttributeValueFilterElement/AttributeValueFilterElement.component.tsx (.../AttributeValueFilterElement.component.tsx) (revision 02034861c5b797d7c6f46da206243f74aca3fefe) +++ components/Filters/AttributeValueFilter/AttributeValueFilterElement/AttributeValueFilterElement.component.tsx (.../AttributeValueFilterElement.component.tsx) (revision a9a134538ec2a00ada5890cb60e7363ed2a90b29) @@ -1,61 +1,84 @@ -import { AttributeNameAutocomplete } from 'lemans-dashboard-digital-services/components/Autocompletes/AttributeNameAutocomplete'; -import { AttributeValueAutocomplete } from 'lemans-dashboard-digital-services/components/Autocompletes/AttributeValueAutocomplete'; -import React from 'react'; -import './AttributeValueFilterElement.styles.less'; -import { IAttributeValueFilterElementProps, IAttributeValueFilterElementState } from './AttributeValueFilterElement.types'; - -export const AttributeValueFilterElement = (props:IAttributeValueFilterElementProps) => { - const startingState: IAttributeValueFilterElementState = { - attributeNameId: props.selected ? props.selected.attributeNameId : undefined, - attributeValueId: props.selected ? props.selected.attributeValueId : undefined, - }; - - const [state, setState] = React.useState(startingState); - - React.useEffect( () => { - if (props.selected) { - setState({ - attributeNameId: props.selected.attributeNameId, - attributeValueId: props.selected.attributeValueId - }); - } else { - setState(startingState); - } - }, [props.selected]); - - const onSelectName = (value:string | string[]) => { - if (value) { - props.onSelect({ - attributeNameId: parseInputValue(value), - attributeValueId: undefined - }); - } else { - props.onSelect(undefined); - } - } - - const onSelectValue = (value:string | string[]) => { - props.onSelect({ - attributeNameId: state.attributeNameId, - attributeValueId: parseInputValue(value) - }) - } - - const parseInputValue = (value:any) => Array.isArray(value) ? undefined : value; - const inputIsEmpty = (value:string|string[]|undefined) => Array.isArray(value) || value === undefined; - - return ( -
- - -
- ); +import { AttributeNameAutocomplete } from 'lemans-dashboard-digital-services/components/Autocompletes/AttributeNameAutocomplete'; +import { AttributeValueAutocomplete } from 'lemans-dashboard-digital-services/components/Autocompletes/AttributeValueAutocomplete'; +import React from 'react'; +import './AttributeValueFilterElement.styles.less'; +import { IAttributeValueFilterElementProps, IAttributeValueFilterElementState } from './AttributeValueFilterElement.types'; + +export const AttributeValueFilterElement = (props:IAttributeValueFilterElementProps) => { + // Initialize state from props + const [state, setState] = React.useState({ + attributeNameId: props.selected?.attributeNameId, + attributeValueId: props.selected?.attributeValueId + }); + + // Update local state when props change + React.useEffect(() => { + if (props.selected) { + setState({ + attributeNameId: props.selected.attributeNameId, + attributeValueId: props.selected.attributeValueId + }); + } else { + setState({ + attributeNameId: undefined, + attributeValueId: undefined + }); + } + }, [props.selected]); + + const onSelectName = (value:string | string[]) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + attributeNameId: parsedValue, + // Clear attribute value when name changes + attributeValueId: undefined + })); + + // Notify parent component + if (value) { + props.onSelect({ + attributeNameId: parsedValue, + attributeValueId: undefined + }); + } else { + props.onSelect(undefined); + } + } + + const onSelectValue = (value:string | string[]) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + attributeValueId: parsedValue + })); + + // Notify parent component + props.onSelect({ + attributeNameId: state.attributeNameId, + attributeValueId: parsedValue + }); + } + + const parseInputValue = (value:any) => Array.isArray(value) ? undefined : value; + const inputIsEmpty = (value:string|string[]|undefined) => Array.isArray(value) || value === undefined; + + return ( +
+ + +
+ ); } \ No newline at end of file Index: components/Filters/MMYFilter/MMYFilter.component.tsx =================================================================== diff -u -r65aa363d2b273f5bf482375f695c9847e79e44f5 -ra9a134538ec2a00ada5890cb60e7363ed2a90b29 --- components/Filters/MMYFilter/MMYFilter.component.tsx (.../MMYFilter.component.tsx) (revision 65aa363d2b273f5bf482375f695c9847e79e44f5) +++ components/Filters/MMYFilter/MMYFilter.component.tsx (.../MMYFilter.component.tsx) (revision a9a134538ec2a00ada5890cb60e7363ed2a90b29) @@ -1,53 +1,222 @@ import { Filter } from 'lemans-common'; -import { FilterGenerator, FilterUpdater, IFilterGeneratorProps } from 'lemans-common/components/FilterGroup/FilterGroup.types'; +import { FilterGenerator, FilterMode, FilterUpdater, IFilterGeneratorProps } from 'lemans-common/components/FilterGroup/FilterGroup.types'; import { service } from 'lemans-dashboard-common'; +import { useState, useEffect } from 'react'; -import { MMYFilterProps } from './MMYFilter.types'; import { MMYFilterElement } from './MMYFilterElement'; import { IMMYFilterState } from './MMYFilterElement/MMYFilterElement.types'; +import { MMYFilterProps } from './MMYFilter.types'; -const filterUpdate = (_id:string, updater:FilterUpdater) => (values:any) => { - updater({mmy: values}); -}; +// This function fetches the data needed for the breadcrumb display +const fetchBreadcrumbData = (state: IMMYFilterState) => (_value: any) => () => { + // If state is undefined or doesn't have required properties, return empty data + if (!state || !state.modelId) { + console.log("Missing required data for MMY breadcrumb:", state); + return Promise.resolve({ body: { results: [] } }); + } -const fetchBreadcrumbData = (state:IMMYFilterState) => (_value:any) => () => - service.fitment.model.search(state.makeId); + console.log("Fetching breadcrumb data for MMYFilter:", state); -const generateBreadcrumb = (state:IMMYFilterState) => (results:any[]) => { - const data = results.find( (item:any) => item.modelId.toString() === state.modelId!.toString()); - let output = `${data.makeName} ${data.modelName}`; + // Fetch model data using the make ID + return service.fitment.model.search(state.makeId) + .then((response: any) => { + // Ensure we have a valid response with results + if (!response || !Array.isArray(response)) { + console.error("Invalid response from model search:", response); + return { body: { results: [] } }; + } + + const result = { body: { results: response } }; + console.log("MMYFilter breadcrumb data:", result); + return result; + }) + .catch((error: Error) => { + console.error('Error fetching MMY breadcrumb data:', error); + return { body: { results: [] } }; + }); +}; - if (state.endYear !== undefined && state.startYear !== undefined) { - output += ` (${state.startYear} - ${state.endYear})`; - } - - if (state.startYear && state.endYear === undefined) { - output += ` (${state.startYear} and newer)`; +// This function generates the breadcrumb string from the results +const generateBreadcrumb = (state: IMMYFilterState) => (results: any) => { + // Ensure we have valid results and state + if (!results || !results.body || !results.body.results || !results.body.results.length || !state || !state.modelId) { + console.log("Missing data for generating MMY breadcrumb:", { results, state }); + return ''; } - - if (state.endYear && state.startYear === undefined) { - output += ` (${state.endYear} and older)`; - } - return output; + try { + // Find the matching model in the results + const data = results.body.results.find((item: any) => item.modelId.toString() === state.modelId!.toString()); + if (!data) { + console.error("Could not find matching model for breadcrumb:", { modelId: state.modelId, results: results.body.results }); + return ''; + } + + // Build the output string with make and model + let output = `${data.makeName} ${data.modelName}`; + + // Add year range if available + if (state.startYear && state.endYear) { + output += ` (${state.startYear}-${state.endYear})`; + } else if (state.startYear) { + output += ` (${state.startYear}+)`; + } else if (state.endYear) { + output += ` (Up to ${state.endYear})`; + } + + console.log("Generated MMY breadcrumb:", output); + return output; + } catch (error) { + console.error('Error generating MMY breadcrumb:', error); + return ''; + } }; -export const MMYFilter = (props:MMYFilterProps):FilterGenerator => (generatorProps:IFilterGeneratorProps):JSX.Element => { +export const MMYFilter = (props: MMYFilterProps): FilterGenerator => { + // Store selected values for breadcrumb display + const selectedValuesMap = new Map(); - return ( - + // Custom update function that prevents duplicate URL parameters + const filterUpdate = (id: string, updater: FilterUpdater) => (values: IMMYFilterState | undefined) => { + if (values) { + // Update the filter with the component-specific values + updater({ + [id]: values, + // Clear the global URL parameters to prevent duplication + makeId: undefined, + modelId: undefined, + startYear: undefined, + endYear: undefined + }); + + // Also update the selectedValues for breadcrumb display + selectedValuesMap.set(id, values); + } else { + // If values is undefined, clear both component-specific and global values + updater({ + [id]: undefined, + makeId: undefined, + modelId: undefined, + startYear: undefined, + endYear: undefined + }); + + // Also clear from selectedValues + selectedValuesMap.delete(id); + } + }; + + const filterFunc = (generatorProps: IFilterGeneratorProps): JSX.Element => { + // Use state to track if we've processed URL parameters + const [processedUrlParams, setProcessedUrlParams] = useState(false); + // Use state to track the current breadcrumb value + const [breadcrumbValue, setBreadcrumbValue] = useState(undefined); + + // Process URL parameters once on component mount + useEffect(() => { + // Only run once + if (processedUrlParams) return; + + // Check for URL parameters + const hasGlobalUrlParams = generatorProps.values.makeId || + generatorProps.values.modelId || + generatorProps.values.startYear !== undefined || + generatorProps.values.endYear !== undefined; + const noComponentValues = !generatorProps.values[props.id]; + + // Only process if we have URL parameters and no component values yet + if (hasGlobalUrlParams && noComponentValues) { + // Create MMY values from URL parameters + const mmyValues: IMMYFilterState = { + makeId: generatorProps.values.makeId, + modelId: generatorProps.values.modelId, + startYear: generatorProps.values.startYear, + endYear: generatorProps.values.endYear + }; + + // Update the filter values and clear global URL parameters + generatorProps.update({ + [props.id]: mmyValues, + // Clear the global URL parameters to prevent duplication + makeId: undefined, + modelId: undefined, + startYear: undefined, + endYear: undefined + }); + + // Also update the selectedValues for breadcrumb display + selectedValuesMap.set(props.id, mmyValues); + setBreadcrumbValue(mmyValues); + + setProcessedUrlParams(true); } - breadcrumbCustomFetch={fetchBreadcrumbData(generatorProps.values[props.id])} - breadcrumbField={generateBreadcrumb(generatorProps.values[props.id])} - breadcrumbLabel={'Fitment'} - generatorProps={generatorProps} - valueId={props.id} - /> - ); -} - \ No newline at end of file + }, [generatorProps.values, props.id, processedUrlParams]); + + // Update breadcrumb value when filter values change + useEffect(() => { + const currentValues = generatorProps.values[props.id]; + if (currentValues) { + setBreadcrumbValue(currentValues); + selectedValuesMap.set(props.id, currentValues); + } + }, [generatorProps.values[props.id]]); + + // Get the current filter values + const filterValues = generatorProps.values[props.id] || {}; + + // Check if we have global URL parameters that need to be merged + if (!filterValues.makeId && generatorProps.values.makeId) { + filterValues.makeId = generatorProps.values.makeId; + } + + if (!filterValues.modelId && generatorProps.values.modelId) { + filterValues.modelId = generatorProps.values.modelId; + } + + if (filterValues.startYear === undefined && generatorProps.values.startYear !== undefined) { + filterValues.startYear = generatorProps.values.startYear; + } + + if (filterValues.endYear === undefined && generatorProps.values.endYear !== undefined) { + filterValues.endYear = generatorProps.values.endYear; + } + + // For breadcrumb mode, we need to ensure the values are passed correctly + let valueForBreadcrumb = filterValues; + + if (generatorProps.mode === FilterMode.Breadcrumb) { + // In breadcrumb mode, use the stored breadcrumb value + if (breadcrumbValue) { + valueForBreadcrumb = breadcrumbValue; + } else if (selectedValuesMap.has(props.id)) { + valueForBreadcrumb = selectedValuesMap.get(props.id) || {}; + } + + console.log("MMYFilter in breadcrumb mode:", { + filterValues, + selectedOptions: generatorProps.values, + valueId: props.id, + valueForBreadcrumb, + breadcrumbValue + }); + } + + return ( + + } + breadcrumbCustomFetch={fetchBreadcrumbData(valueForBreadcrumb)} + breadcrumbField={generateBreadcrumb(valueForBreadcrumb)} + breadcrumbLabel={'Vehicle'} + generatorProps={generatorProps} + valueId={props.id} + /> + ); + }; + + return filterFunc; +}; \ No newline at end of file Index: components/Filters/MMYFilter/MMYFilterElement/MMYFilterElement.component.tsx =================================================================== diff -u -r02034861c5b797d7c6f46da206243f74aca3fefe -ra9a134538ec2a00ada5890cb60e7363ed2a90b29 --- components/Filters/MMYFilter/MMYFilterElement/MMYFilterElement.component.tsx (.../MMYFilterElement.component.tsx) (revision 02034861c5b797d7c6f46da206243f74aca3fefe) +++ components/Filters/MMYFilter/MMYFilterElement/MMYFilterElement.component.tsx (.../MMYFilterElement.component.tsx) (revision a9a134538ec2a00ada5890cb60e7363ed2a90b29) @@ -1,125 +1,195 @@ -import { Input, InputNumber } from 'antd'; -import React from 'react'; -import { MakeAutocomplete } from '../../../Autocompletes/MakeAutocomplete'; -import { ModelAutocomplete } from '../../../Autocompletes/ModelAutocomplete'; -import './MMYFilterElement.styles.less'; -import { IMMYFilterElementState, MMYFilterElementProps } from './MMYFilterElement.types'; - - -export const MMYFilterElement = (props:MMYFilterElementProps) => { - const startingState: IMMYFilterElementState = { - make: { - selectedId: props.selected ? props.selected.makeId : undefined - }, - model: { - disabled: true, - selectedId: props.selected ? props.selected.modelId : undefined - }, - year: { - disabled: true, - end: undefined, - start: undefined, - } - }; - - const [state, setState] = React.useState(startingState); - - React.useEffect( () => { - if (props.selected) { - setState({ - make: { - selectedId: props.selected.makeId - }, - model: { - disabled: inputIsEmpty(props.selected.makeId), - selectedId: props.selected.modelId - }, - year: { - disabled: inputIsEmpty(props.selected.modelId), - end: props.selected.endYear, - start: props.selected.startYear - } - }); - } else { - setState(startingState); - } - }, [props.selected]) - - const onSelectModel = (value:string | string[]) => { - props.onSelect({ - endYear: undefined, - makeId: state.make.selectedId, - modelId: parseInputValue(value), - startYear: undefined, - }); - } - - const onSelectMake = (value:string | string[]) => { - if (value) { - props.onSelect({ - endYear: undefined, - makeId: parseInputValue(value), - modelId: undefined, - startYear: undefined, - }); - } else { - props.onSelect(undefined); - } - } - - const onStartYearChange = (value:number|null) => { - props.onSelect({ - endYear: state.year.end, - makeId: state.make.selectedId, - modelId: state.model.selectedId, - startYear: parseInputValue(value), - }); - } - - const onEndYearChange = (value:number|null) => { - props.onSelect({ - endYear: parseInputValue(value), - makeId: state.make.selectedId, - modelId: state.model.selectedId, - startYear: state.year.start, - }); - } - - const parseInputValue = (value:any) => Array.isArray(value) || value === null ? undefined : value; - const inputIsEmpty = (value:string|string[]|undefined) => Array.isArray(value) || value === undefined; - - return ( -
- - - - - - - -
- ); -} - \ No newline at end of file +import { Input, InputNumber } from 'antd'; +import React from 'react'; +import { MakeAutocomplete } from '../../../Autocompletes/MakeAutocomplete'; +import { ModelAutocomplete } from '../../../Autocompletes/ModelAutocomplete'; +import './MMYFilterElement.styles.less'; +import { IMMYFilterElementState, MMYFilterElementProps } from './MMYFilterElement.types'; + +export const MMYFilterElement = (props: MMYFilterElementProps) => { + // Initialize state from props + const [state, setState] = React.useState({ + make: { + selectedId: props.selected?.makeId + }, + model: { + disabled: !props.selected?.makeId, + selectedId: props.selected?.modelId + }, + year: { + disabled: !props.selected?.modelId, + end: props.selected?.endYear, + start: props.selected?.startYear + } + }); + + // Update local state when props change + React.useEffect(() => { + if (props.selected) { + setState({ + make: { + selectedId: props.selected.makeId + }, + model: { + disabled: inputIsEmpty(props.selected.makeId), + selectedId: props.selected.modelId + }, + year: { + disabled: inputIsEmpty(props.selected.modelId), + end: props.selected.endYear, + start: props.selected.startYear + } + }); + } else { + setState({ + make: { + selectedId: undefined + }, + model: { + disabled: true, + selectedId: undefined + }, + year: { + disabled: true, + end: undefined, + start: undefined + } + }); + } + }, [props.selected]); + + const onSelectModel = (value: string | string[]) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + model: { + ...prevState.model, + selectedId: parsedValue + }, + year: { + ...prevState.year, + disabled: inputIsEmpty(parsedValue) + } + })); + + // Notify parent component + props.onSelect({ + endYear: undefined, + makeId: state.make.selectedId, + modelId: parsedValue, + startYear: undefined, + }); + } + + const onSelectMake = (value: string | string[]) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + make: { + selectedId: parsedValue + }, + model: { + disabled: inputIsEmpty(parsedValue), + selectedId: undefined + }, + year: { + ...prevState.year, + disabled: true + } + })); + + // Notify parent component + if (value) { + props.onSelect({ + endYear: undefined, + makeId: parsedValue, + modelId: undefined, + startYear: undefined, + }); + } else { + props.onSelect(undefined); + } + } + + const onStartYearChange = (value: number | null) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + year: { + ...prevState.year, + start: parsedValue + } + })); + + // Notify parent component + props.onSelect({ + endYear: state.year.end, + makeId: state.make.selectedId, + modelId: state.model.selectedId, + startYear: parsedValue, + }); + } + + const onEndYearChange = (value: number | null) => { + const parsedValue = parseInputValue(value); + + // Update local state + setState(prevState => ({ + ...prevState, + year: { + ...prevState.year, + end: parsedValue + } + })); + + // Notify parent component + props.onSelect({ + endYear: parsedValue, + makeId: state.make.selectedId, + modelId: state.model.selectedId, + startYear: state.year.start, + }); + } + + const parseInputValue = (value: any) => Array.isArray(value) || value === null ? undefined : value; + const inputIsEmpty = (value: string | string[] | undefined) => Array.isArray(value) || value === undefined; + + return ( +
+ + + + + + + +
+ ); +} \ No newline at end of file