feat(search): add category search support and sync with chips

This commit is contained in:
2026-03-20 18:14:02 +04:00
parent 4008a8c883
commit b083c1d001
8 changed files with 67 additions and 17 deletions

View File

@@ -11,7 +11,11 @@ import CategoryChips from '#components/category-chips';
export default class AppHeaderComponent extends Component {
@service storage;
@tracked isUserMenuOpen = false;
@tracked hasQuery = false;
@tracked searchQuery = '';
get hasQuery() {
return !!this.searchQuery;
}
@action
toggleUserMenu() {
@@ -25,22 +29,21 @@ export default class AppHeaderComponent extends Component {
@action
handleQueryChange(query) {
this.hasQuery = !!query;
this.searchQuery = query;
}
@action
handleChipSelect() {
// When a chip is selected, we might want to ensure the search box is cleared visually,
// although the route transition will happen.
// The SearchBox component manages its own state, so we rely on the route transition.
// However, if we want to clear the search box input from here, we'd need to control it.
// For now, let's just let the route change happen.
handleChipSelect(category) {
this.searchQuery = category.label;
// The existing logic in CategoryChips triggers the route transition.
// This update simply fills the search box.
}
<template>
<header class="app-header">
<div class="header-left">
<SearchBox
@query={{this.searchQuery}}
@onToggleMenu={{@onToggleMenu}}
@onQueryChange={{this.handleQueryChange}}
/>

View File

@@ -7,6 +7,7 @@ import { fn } from '@ember/helper';
import { task, timeout } from 'ember-concurrency';
import Icon from '#components/icon';
import humanizeOsmTag from '../helpers/humanize-osm-tag';
import { POI_CATEGORIES } from '../utils/poi-categories';
import eq from 'ember-truth-helpers/helpers/eq';
export default class SearchBoxComponent extends Component {
@@ -15,11 +16,19 @@ export default class SearchBoxComponent extends Component {
@service mapUi;
@service map; // Assuming we might need map context, but mostly we use router
@tracked query = '';
@tracked _internalQuery = '';
@tracked results = [];
@tracked isFocused = false;
@tracked isLoading = false;
get query() {
return this.args.query ?? this._internalQuery;
}
set query(value) {
this._internalQuery = value;
}
get showPopover() {
return this.isFocused && this.results.length > 0;
}
@@ -51,8 +60,20 @@ export default class SearchBoxComponent extends Component {
if (this.mapUi.currentCenter) {
({ lat, lon } = this.mapUi.currentCenter);
}
// Filter categories
const q = this.query.toLowerCase();
const categoryMatches = POI_CATEGORIES.filter((c) =>
c.label.toLowerCase().includes(q)
).map((c) => ({
source: 'category',
title: c.label,
id: c.id,
icon: 'search',
}));
const results = await this.photon.search(this.query, lat, lon);
this.results = results;
this.results = [...categoryMatches, ...results];
} catch (e) {
console.error('Search failed', e);
this.results = [];
@@ -98,7 +119,29 @@ export default class SearchBoxComponent extends Component {
@action
selectResult(place) {
if (place.source === 'category') {
this.query = place.title;
if (this.args.onQueryChange) {
this.args.onQueryChange(place.title);
}
this.results = [];
this.router.transitionTo('search', {
queryParams: {
q: place.title,
category: place.id,
selected: null,
lat: null,
lon: null,
},
});
return;
}
this.query = place.title;
if (this.args.onQueryChange) {
this.args.onQueryChange(place.title);
}
this.results = []; // Hide popover
// If it has an OSM ID, go to place details
@@ -183,7 +226,11 @@ export default class SearchBoxComponent extends Component {
{{on "click" (fn this.selectResult result)}}
>
<div class="result-icon">
<Icon @name="map-pin" @size={{16}} @color="#666" />
<Icon
@name={{if result.icon result.icon "map-pin"}}
@size={{16}}
@color="#666"
/>
</div>
<div class="result-info">
<span class="result-title">{{result.title}}</span>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -39,8 +39,8 @@
<meta name="msapplication-TileColor" content="#F6E9A6">
<meta name="msapplication-TileImage" content="/icons/icon-144.png">
<script type="module" crossorigin src="/assets/main-gEUnNw-L.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-BOfcjRke.css">
<script type="module" crossorigin src="/assets/main-C4F17h3W.js"></script>
<link rel="stylesheet" crossorigin href="/assets/main-CKp1bFPU.css">
</head>
<body>
</body>