feat: allow merging of adjacent search results

This commit is contained in:
2025-08-15 20:25:02 +00:00
parent 109c877e5d
commit 316ea7bf86
2 changed files with 90 additions and 13 deletions

View File

@@ -243,3 +243,48 @@ h2 {
align-items: center;
color: white;
}
.search-result-row {
display: flex;
align-items: center;
position: relative;
}
.merge-button-wrapper {
flex-shrink: 0;
width: 2em;
position: relative;
align-self: stretch;
}
.merge-button {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%, 50%);
z-index: 10;
background-color: #888;
border: 1px solid #aaa;
border-radius: 50%;
color: white;
cursor: pointer;
font-size: 0.8rem;
line-height: 1;
height: 1.5em;
width: 1.5em;
padding: 0;
min-width: 0;
}
.merge-button:hover {
background-color: #999;
}
.search-result-button-wrapper {
flex-grow: 1;
}
.search-result-button-wrapper button {
width: 100%;
text-align: center;
}

View File

@@ -515,7 +515,8 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
);
setActiveSearchResult(null);
setSearchResults(res.data);
const sortedData = res.data.sort((a, b) => b.start - a.start);
setSearchResults(sortedData);
} catch (error) {
console.error('Error during area search:', error);
alert('An error occurred during the search.');
@@ -554,6 +555,20 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
setSubmenu(false);
};
const mergeSearchResults = (index) => {
const newResults = [...searchResults];
const item1 = newResults[index];
const item2 = newResults[index + 1];
const mergedItem = {
start: item2.start,
end: item1.end,
};
newResults.splice(index, 2, mergedItem);
setSearchResults(newResults);
};
const range = parseSlider(end, duration, slider);
const startDate = moment(end).subtract(...duration.delta);
@@ -722,9 +737,7 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
<div ref={scrollContainerRef} className="search-results-container">
{searchResults.length > 0 ? (
(() => {
const sortedResults = [...searchResults].sort((a, b) => b.start - a.start);
const groupedResults = sortedResults.reduce((acc, result) => {
const groupedResults = searchResults.reduce((acc, result) => {
const groupKey = moment.unix(result.start).format('YYYY');
if (!acc[groupKey]) {
acc[groupKey] = [];
@@ -747,15 +760,34 @@ function Menu({data, duration, setDuration, end, setEnd, slider, setSlider, subm
.map(([groupKey, results]) => (
<div key={groupKey}>
<h3 className="search-results-group-header">{groupKey}</h3>
{results.map((result, index) => (
<button
key={index}
onClick={() => selectSearchResult(result)}
className={activeSearchResult && activeSearchResult.start === result.start && activeSearchResult.end === result.end ? 'active' : ''}
>
{formatShortTime(result.start)} - {formatShortTime(result.end)}
</button>
))}
{results.map((result, indexInYear) => {
const absoluteIndex = searchResults.findIndex(r => r.start === result.start && r.end === result.end);
const isLastResultOverall = absoluteIndex === searchResults.length - 1;
return (
<div className="search-result-row" key={`${result.start}-${result.end}`}>
<div className="merge-button-wrapper">
{!isLastResultOverall && (
<button
className="merge-button"
title="Merge with next item"
onClick={() => mergeSearchResults(absoluteIndex)}
>
&darr;&uarr;
</button>
)}
</div>
<div className="search-result-button-wrapper">
<button
onClick={() => selectSearchResult(result)}
className={activeSearchResult && activeSearchResult.start === result.start && activeSearchResult.end === result.end ? 'active' : ''}
>
{formatShortTime(result.start)} - {formatShortTime(result.end)}
</button>
</div>
</div>
);
})}
</div>
));
})()