feat: allow custom nearby radius

This commit is contained in:
zv
2026-06-23 20:02:43 +02:00
parent 970df9daeb
commit 940e294b3a
2 changed files with 55 additions and 12 deletions

View File

@@ -48,9 +48,11 @@ const namedAreas = [
const radiusOptions = [50, 100, 250, 500, 1000]; const radiusOptions = [50, 100, 250, 500, 1000];
const customChoice = 'custom'; const customChoice = 'custom';
const noNearbyChoice = 'none'; const noNearbyChoice = 'none';
const customRadiusChoice = 'custom-radius';
type RequestStatus = 'idle' | 'loading' | 'success' | 'error'; type RequestStatus = 'idle' | 'loading' | 'success' | 'error';
type NearbyChoice = typeof noNearbyChoice | typeof customChoice | string; type NearbyChoice = typeof noNearbyChoice | typeof customChoice | string;
type RadiusChoice = number | typeof customRadiusChoice;
export function App() { export function App() {
const [category, setCategory] = useState(searchPresetCategories[0]); const [category, setCategory] = useState(searchPresetCategories[0]);
@@ -64,6 +66,7 @@ export function App() {
const [nearbyChoice, setNearbyChoice] = useState<NearbyChoice>(noNearbyChoice); const [nearbyChoice, setNearbyChoice] = useState<NearbyChoice>(noNearbyChoice);
const [nearbyCustomKey, setNearbyCustomKey] = useState(''); const [nearbyCustomKey, setNearbyCustomKey] = useState('');
const [nearbyCustomValue, setNearbyCustomValue] = useState(''); const [nearbyCustomValue, setNearbyCustomValue] = useState('');
const [radiusChoice, setRadiusChoice] = useState<RadiusChoice>(100);
const [nearbyRadius, setNearbyRadius] = useState(100); const [nearbyRadius, setNearbyRadius] = useState(100);
const [areaMode, setAreaMode] = useState<SearchArea['mode']>('bbox'); const [areaMode, setAreaMode] = useState<SearchArea['mode']>('bbox');
const [bbox, setBBox] = useState<BBox>(DEFAULT_BBOX); const [bbox, setBBox] = useState<BBox>(DEFAULT_BBOX);
@@ -238,6 +241,25 @@ export function App() {
setNearbyCustomValue(''); setNearbyCustomValue('');
} }
function handleRadiusChoiceChange(value: string) {
if (value === customRadiusChoice) {
setRadiusChoice(customRadiusChoice);
return;
}
const radius = Number(value);
setRadiusChoice(radius);
setNearbyRadius(radius);
}
function handleCustomRadiusChange(value: string) {
const radius = Number(value);
if (Number.isFinite(radius)) {
setNearbyRadius(radius);
}
}
function handleClearResults() { function handleClearResults() {
setResults([]); setResults([]);
setSelectedResultId(null); setSelectedResultId(null);
@@ -462,18 +484,32 @@ export function App() {
<div className="control-group"> <div className="control-group">
<label htmlFor="nearby-radius">Radius</label> <label htmlFor="nearby-radius">Radius</label>
<div className="radius-controls">
<select <select
id="nearby-radius" id="nearby-radius"
value={nearbyRadius} value={radiusChoice}
disabled={nearbyChoice === noNearbyChoice} disabled={nearbyChoice === noNearbyChoice}
onChange={(event) => setNearbyRadius(Number(event.target.value))} onChange={(event) => handleRadiusChoiceChange(event.target.value)}
> >
{radiusOptions.map((radius) => ( {radiusOptions.map((radius) => (
<option key={radius} value={radius}> <option key={radius} value={radius}>
{radius} meters {radius} meters
</option> </option>
))} ))}
<option value={customRadiusChoice}>Custom</option>
</select> </select>
{radiusChoice === customRadiusChoice ? (
<input
aria-label="Custom radius in meters"
type="number"
min="1"
step="1"
value={nearbyRadius}
disabled={nearbyChoice === noNearbyChoice}
onChange={(event) => handleCustomRadiusChange(event.target.value)}
/>
) : null}
</div>
</div> </div>
</section> </section>

View File

@@ -161,6 +161,12 @@ a {
gap: 0.75rem; gap: 0.75rem;
} }
.radius-controls {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(96px, 0.55fr);
gap: 0.5rem;
}
.checkbox-grid { .checkbox-grid {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
@@ -457,6 +463,7 @@ a {
} }
.custom-fields, .custom-fields,
.radius-controls,
.segmented-control, .segmented-control,
.checkbox-grid { .checkbox-grid {
grid-template-columns: 1fr; grid-template-columns: 1fr;