feat: Set time range and highlight selected search result

This commit is contained in:
2025-08-15 20:02:46 +00:00
parent 7ec2a638a2
commit 0c107f86b6

View File

@@ -316,6 +316,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
const [showRange, setShowRange] = useState(false); const [showRange, setShowRange] = useState(false);
const [isSearching, setIsSearching] = useState(false); const [isSearching, setIsSearching] = useState(false);
const [searchResults, setSearchResults] = useState(null); const [searchResults, setSearchResults] = useState(null);
const [activeSearchResult, setActiveSearchResult] = useState(null);
const scrollContainerRef = useRef(null); const scrollContainerRef = useRef(null);
const scrollPositionRef = useRef(0); const scrollPositionRef = useRef(0);
@@ -334,10 +335,16 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
}; };
}, [searchResults]); }, [searchResults]);
const handleSliderChange = (newSliderValue) => {
setActiveSearchResult(null);
setSlider(newSliderValue);
};
const chooseDuration = (x) => { const chooseDuration = (x) => {
setSubmenu(false); setSubmenu(false);
setSlider([0, x.num]); setSlider([0, x.num]);
setDuration(x); setDuration(x);
setActiveSearchResult(null);
}; };
const chooseEnd = (x) => { const chooseEnd = (x) => {
@@ -345,42 +352,49 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
const newEnd = x.add(...duration.delta); const newEnd = x.add(...duration.delta);
setSlider([0, duration.num]); setSlider([0, duration.num]);
setEnd(newEnd); setEnd(newEnd);
setActiveSearchResult(null);
}; };
const chooseNow = (x) => { const chooseNow = (x) => {
setSubmenu(false); setSubmenu(false);
setSlider([0, duration.num]); setSlider([0, duration.num]);
setEnd(moment()); setEnd(moment());
setActiveSearchResult(null);
}; };
const chooseMidnight = () => { const chooseMidnight = () => {
setSubmenu(false); setSubmenu(false);
setSlider([0, duration.num]); setSlider([0, duration.num]);
setEnd(prevEnd => moment(prevEnd).startOf('day')); setEnd(prevEnd => moment(prevEnd).startOf('day'));
setActiveSearchResult(null);
}; };
const rangeStart = (x) => { const rangeStart = (x) => {
setSubmenu(false); setSubmenu(false);
setEnd(moment(range[0]).add(...duration.delta)); setEnd(moment(range[0]).add(...duration.delta));
setSlider([0, duration.num]); setSlider([0, duration.num]);
setActiveSearchResult(null);
}; };
const rangeEnd = (x) => { const rangeEnd = (x) => {
setSubmenu(false); setSubmenu(false);
setEnd(moment(range[1])); setEnd(moment(range[1]));
setSlider([0, duration.num]); setSlider([0, duration.num]);
setActiveSearchResult(null);
}; };
const next = () => { const next = () => {
setSubmenu(false); setSubmenu(false);
setSlider([0, duration.num]); setSlider([0, duration.num]);
setEnd(prevEnd => moment(prevEnd).add(...duration.delta)); setEnd(prevEnd => moment(prevEnd).add(...duration.delta));
setActiveSearchResult(null);
} }
const prev = () => { const prev = () => {
setSubmenu(false); setSubmenu(false);
setSlider([0, duration.num]); setSlider([0, duration.num]);
setEnd(prevEnd => moment(prevEnd).subtract(...duration.delta)); setEnd(prevEnd => moment(prevEnd).subtract(...duration.delta));
setActiveSearchResult(null);
} }
const resetToDefaults = () => { const resetToDefaults = () => {
@@ -492,6 +506,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
{ params: params } { params: params }
); );
setActiveSearchResult(null);
setSearchResults(res.data); setSearchResults(res.data);
} catch (error) { } catch (error) {
console.error('Error during area search:', error); console.error('Error during area search:', error);
@@ -501,6 +516,35 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
} }
}; };
const selectSearchResult = (result) => {
const resultStart = moment.unix(result.start);
const resultEnd = moment.unix(result.end);
const resultDurationSeconds = result.end - result.start;
// Find the best duration that fits the search result
let bestDuration = durations.find(d => resultDurationSeconds <= moment.duration(...d.delta).asSeconds());
if (!bestDuration) {
bestDuration = durations[durations.length - 1]; // Default to the largest duration if none fit
}
setDuration(bestDuration);
// Set the end of the window to be the end of the search result for simplicity
const newEnd = resultEnd;
setEnd(newEnd);
// Calculate the new slider positions based on the new duration and end time
const newSliderStart = (resultStart.unix() - newEnd.unix()) / bestDuration.secs + bestDuration.num;
const newSliderEnd = (resultEnd.unix() - newEnd.unix()) / bestDuration.secs + bestDuration.num;
// Clamp values to be within the slider's bounds [0, duration.num]
const clampedStart = Math.max(0, Math.floor(newSliderStart));
const clampedEnd = Math.min(bestDuration.num, Math.ceil(newSliderEnd));
setSlider([clampedStart, clampedEnd]);
setActiveSearchResult({ start: result.start, end: result.end });
};
const range = parseSlider(end, duration, slider); const range = parseSlider(end, duration, slider);
const startDate = moment(end).subtract(...duration.delta); const startDate = moment(end).subtract(...duration.delta);
@@ -600,7 +644,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
min={0} min={0}
max={duration.num} max={duration.num}
value={slider} value={slider}
onInput={setSlider} onInput={handleSliderChange}
onThumbDragStart={() => setShowRange(true)} onThumbDragStart={() => setShowRange(true)}
onThumbDragEnd={() => setShowRange(false)} onThumbDragEnd={() => setShowRange(false)}
onRangeDragStart={() => setShowRange(true)} onRangeDragStart={() => setShowRange(true)}
@@ -660,7 +704,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
<div className='submenu-header'> <div className='submenu-header'>
<h2>{searchResults ? 'Search Results' : 'Misc'}</h2> <h2>{searchResults ? 'Search Results' : 'Misc'}</h2>
{searchResults ? ( {searchResults ? (
<button onClick={() => setSearchResults(null)}>&lt; Back</button> <button onClick={() => { setSearchResults(null); setActiveSearchResult(null); }}>&lt; Back</button>
) : ( ) : (
<button onClick={() => setSubmenu(false)}>×</button> <button onClick={() => setSubmenu(false)}>×</button>
)} )}
@@ -695,7 +739,11 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
<div key={groupKey}> <div key={groupKey}>
<h3 style={{ color: 'white', margin: '0.5em 0 0.25em', fontSize: '1em', fontWeight: 'normal', textAlign: 'center' }}>{groupKey}</h3> <h3 style={{ color: 'white', margin: '0.5em 0 0.25em', fontSize: '1em', fontWeight: 'normal', textAlign: 'center' }}>{groupKey}</h3>
{results.map((result, index) => ( {results.map((result, index) => (
<button key={index}> <button
key={index}
onClick={() => selectSearchResult(result)}
className={activeSearchResult && activeSearchResult.start === result.start && activeSearchResult.end === result.end ? 'active' : ''}
>
{formatShortTime(result.start)} - {formatShortTime(result.end)} {formatShortTime(result.start)} - {formatShortTime(result.end)}
</button> </button>
))} ))}