Skip to content

Commit

Permalink
Merge pull request #24 from frontend-park-mail-ru/feature-advanced-se…
Browse files Browse the repository at this point in the history
…arch

Поиск по полям + категории
  • Loading branch information
let-robots-reign authored Nov 25, 2024
2 parents 725e7ad + 7038da8 commit 9fa5be2
Show file tree
Hide file tree
Showing 32 changed files with 403 additions and 66 deletions.
17 changes: 17 additions & 0 deletions src/Components/FormInputs/SelectInput/SelectInput.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Component } from '@/modules/Components/Component';
import { SelectInputModel } from './SelectInputModel';
import { SelectInputController } from './SelectInputController';
import { SelectInputView } from './SelectInputView';
import './select-input.scss';
export class SelectInput extends Component {
constructor({ name, elementClass, caption, options }, existingElement) {
super({
modelClass: SelectInputModel,
controllerClass: SelectInputController,
viewClass: SelectInputView,
viewParams: { name, elementClass, caption },
existingElement,
});
this._controller.loadOptions(options);
}
}
13 changes: 13 additions & 0 deletions src/Components/FormInputs/SelectInput/SelectInputController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ComponentController } from '@/modules/Components/Component';

export class SelectInputController extends ComponentController {
constructor(model, view, component) {
super(model, view, component);
}

loadOptions(options) {
options.forEach(({ value, caption }) => {
this._view.addOption({ value, caption });
});
}
}
3 changes: 3 additions & 0 deletions src/Components/FormInputs/SelectInput/SelectInputModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ComponentModel } from '@/modules/Components/Component';

export const SelectInputModel = ComponentModel;
35 changes: 35 additions & 0 deletions src/Components/FormInputs/SelectInput/SelectInputView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ComponentView } from '@/modules/Components/Component';
import SelectInputHbs from './select-input.hbs';
import eventBus from '@/modules/Events/EventBus';
import { SELECT_INPUT_CHANGE } from '@/modules/Events/Events';
import { addEventListeners } from '@/modules/Events/EventUtils';

export class SelectInputView extends ComponentView {
#select;
constructor({ name, elementClass, caption }, existingElement) {
super({
renderParams: { name, elementClass, caption },
template: SelectInputHbs,
existingElement,
});
this.#select = this._html.querySelector('.select-input__select');
this._eventListeners.push({
event: 'input',
object: this.#select,
listener: this.handleSelect,
});
addEventListeners(this._eventListeners);
}

handleSelect = (ev) => {
ev.preventDefault();
eventBus.emit(SELECT_INPUT_CHANGE, { caller: this, value: this.#select.value });
};

addOption({ value, caption }) {
const option = document.createElement('option');
option.value = value;
option.innerText = caption;
this.#select.appendChild(option);
}
}
5 changes: 5 additions & 0 deletions src/Components/FormInputs/SelectInput/select-input.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="{{elementClass}} select-input">
<label for='{{name}}' class='select-input__label'>{{caption}}</label>
<select name="{{name}}" class='{{elementClass}}-select select-input__select select_main'>
</select>
</div>
19 changes: 19 additions & 0 deletions src/Components/FormInputs/SelectInput/select-input.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.select-input {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: baseline;
&__label {
font-size: var(--text-size-4);
}
}

.select_main {
width: 50%;
border-radius: 4px;
padding: 8px;
border: none;
font-size: var(--text-size-3);
color: var(--color-background-1000);
background-color: var(--color-main-100);
}
10 changes: 4 additions & 6 deletions src/Components/SearchBar/SearchBarView.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import searchIconSvg from '@static/img/search-icon.svg';
import clearIconSvg from '@static/img/clear-icon.svg';
import { addEventListeners } from '@/modules/Events/EventUtils';
import EventBus from '@/modules/Events/EventBus';
import { SUBMIT_SEARCH } from '@/modules/Events/Events';
import { SEARCH_INPUT_CHANGE } from '@/modules/Events/Events';

export class SearchBarView extends ComponentView {
#searchInput;
#clearButton;
#searchForm;
#isInputEmpty;
constructor(renderParams, existingElement) {
super({
Expand All @@ -24,13 +23,12 @@ export class SearchBarView extends ComponentView {

this.#searchInput = this._html.querySelector('.search-bar__input');
this.#clearButton = this._html.querySelector('.search-bar__clear-icon');
this.#searchForm = this._html.querySelector('.search-container__search-bar');
this.#isInputEmpty = true;

this._eventListeners.push(
{
event: 'submit',
object: this.#searchForm,
object: this._html,
listener: this.#handleSubmit,
},
{
Expand Down Expand Up @@ -58,13 +56,13 @@ export class SearchBarView extends ComponentView {

#handleSubmit = (ev) => {
ev.preventDefault();
EventBus.emit(SUBMIT_SEARCH, { searchInput: this.#searchInput.value });
EventBus.emit(SEARCH_INPUT_CHANGE, { searchInput: this.#searchInput.value });
};

#handleClear = () => {
this.clearSearch();
this.toggleClearButton();
EventBus.emit(SUBMIT_SEARCH, { searchInput: '' });
EventBus.emit(SEARCH_INPUT_CHANGE, { searchInput: '' });
};

#handleInput = () => {
Expand Down
13 changes: 5 additions & 8 deletions src/Components/SearchBar/search-bar.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
<div class="{{elementClass}} search-container search-container_theme-inside-ruler">
<h3 class="search-container__header">Поиск</h3>
<form class="search-container__search-bar search-bar search-bar_theme-main" id="search-form" novalidate>
<img class="search-bar__search-icon" src="{{searchIcon}}"/>
<input class="search-bar__input" type="text"/>
<img class="search-bar__clear-icon hidden" src="{{clearIcon}}"/>
</form>
</div>
<form class="{{elementClass}} search-bar search-bar_theme-main" id="search-form" novalidate>
<img class="search-bar__search-icon" src="{{searchIcon}}"/>
<input class="search-bar__input" type="text"/>
<img class="search-bar__clear-icon hidden" src="{{clearIcon}}"/>
</form>
24 changes: 1 addition & 23 deletions src/Components/SearchBar/search_bar.scss
Original file line number Diff line number Diff line change
@@ -1,26 +1,3 @@
.search-container {
display: flex;
flex-direction: column;
align-items: stretch;

&__header {
margin: 0;
font-size: var(--text-size-5);
margin-bottom: 8px;
}
&__search-bar {
border-radius: 25px;
height: 32px;
color: var(--color-background-1000);
}

&_theme-inside-ruler {
background-color: var(--color-background-800);
border-radius: 14px;
padding: 12px;
}
}

.search-bar {
display: flex;
flex-direction: row;
Expand Down Expand Up @@ -48,6 +25,7 @@
border: none;
width: 100%;
border-radius: 25px;
font-size: var(--text-size-3);
outline: none;
}
}
32 changes: 32 additions & 0 deletions src/Components/SearchContainer/SearchContainer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Component } from '@/modules/Components/Component';
import { SearchContainerModel } from './SearchContainerModel';
import { SearchContainerView } from './SearchContainerView';
import { SearchContainerController } from './SearchContainerController';
import { SearchBar } from '../SearchBar/SearchBar';
import { SelectInput } from '../FormInputs/SelectInput/SelectInput';
import './search-container.scss';

export class SearchContainer extends Component {
constructor({ elementClass, existingElement, searchByOptions, searchGroupOptions }) {
super({
modelClass: SearchContainerModel,
viewClass: SearchContainerView,
controllerClass: SearchContainerController,
viewParams: { elementClass },
existingElement,
});
this._searchBar = new SearchBar({ elementClass: 'search-container__search-bar' });
this._view.renderSearchBar(this._searchBar.render());
this._children.push(this._searchBar);
if (searchByOptions) {
this._searchBy = new SelectInput(searchByOptions);
this._view.renderSearchBy(this._searchBy.render());
this._children.push(this._searchBy);
}
if (searchGroupOptions) {
this._searchGroup = new SelectInput(searchGroupOptions);
this._view.renderSearchGroup(this._searchGroup.render());
this._children.push(this._searchGroup);
}
}
}
45 changes: 45 additions & 0 deletions src/Components/SearchContainer/SearchContainerController.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { ComponentController } from '@/modules/Components/Component';
import eventBus from '@/modules/Events/EventBus';
import {
SEARCH_INPUT_CHANGE,
SELECT_INPUT_CHANGE,
SUBMIT_SEARCH_QUERY,
} from '@/modules/Events/Events';

export class SearchContainerController extends ComponentController {
constructor(model, view, component) {
super(model, view, component);
this.setHandlers([
{
event: SELECT_INPUT_CHANGE,
handler: this.handleSelectInputChange.bind(this),
},
{
event: SEARCH_INPUT_CHANGE,
handler: this.handleSearchInputChange.bind(this),
},
]);
}

handleSelectInputChange({ caller, value }) {
switch (caller.render()) {
case this._view.searchBy: {
this._model.searchBy = value;
if (this._model.getFullQuery().searchQuery) {
eventBus.emit(SUBMIT_SEARCH_QUERY, { query: this._model.getFullQuery() });
}
break;
}
case this._view.searchGroup: {
this._model.searchGroup = value;
eventBus.emit(SUBMIT_SEARCH_QUERY, { query: this._model.getFullQuery() });
break;
}
}
}

handleSearchInputChange({ searchInput }) {
this._model.searchQuery = searchInput;
eventBus.emit(SUBMIT_SEARCH_QUERY, { query: this._model.getFullQuery() });
}
}
33 changes: 33 additions & 0 deletions src/Components/SearchContainer/SearchContainerModel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ComponentModel } from '@/modules/Components/Component';

export class SearchContainerModel extends ComponentModel {
#searchBy;
#searchGroup;
#searchQuery;
constructor() {
super();
this.#searchBy = '';
this.#searchGroup = '';
this.#searchQuery = '';
}

set searchBy(value) {
this.#searchBy = value;
}

set searchGroup(value) {
this.#searchGroup = value;
}

set searchQuery(value) {
this.#searchQuery = value;
}

getFullQuery() {
return {
searchQuery: this.#searchQuery,
searchBy: this.#searchBy,
searchGroup: this.#searchGroup,
};
}
}
33 changes: 33 additions & 0 deletions src/Components/SearchContainer/SearchContainerView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ComponentView } from '@/modules/Components/Component';
import SearchContainerHbs from './search-container.hbs';

export class SearchContainerView extends ComponentView {
#searchInput;
constructor(renderParams, existingElement) {
super({
renderParams,
existingElement,
template: SearchContainerHbs,
viewParams: renderParams,
});
this.#searchInput = this._html.querySelector('.search-container__input-box');
this.searchBy = undefined;
this.searchBar = undefined;
this.searchGroup = undefined;
}

renderSearchBar(searchBarRender) {
this.#searchInput.appendChild(searchBarRender);
this.searchBar = searchBarRender;
}

renderSearchBy(searchByRender) {
this.#searchInput.appendChild(searchByRender);
this.searchBy = searchByRender;
}

renderSearchGroup(searchGroupRender) {
this.#searchInput.appendChild(searchGroupRender);
this.searchGroup = searchGroupRender;
}
}
5 changes: 5 additions & 0 deletions src/Components/SearchContainer/search-container.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="{{elementClass}} search-container search-container_theme-inside-ruler">
<h3 class="search-container__header">Поиск</h3>
<div class="search-container__input-box">
</div>
</div>
30 changes: 30 additions & 0 deletions src/Components/SearchContainer/search-container.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.search-container {
display: flex;
flex-direction: column;
align-items: stretch;

&__input-box {
display: flex;
flex-direction: column;
gap: 16px;
}

&__header {
margin: 0;
font-size: var(--text-size-5);
font-weight: var(--text-weight-regular);
margin-bottom: 8px;
}

&__search-bar {
border-radius: 25px;
height: 32px;
color: var(--color-background-1000);
}

&_theme-inside-ruler {
background-color: var(--color-background-800);
border-radius: 14px;
padding: 12px;
}
}
Loading

0 comments on commit 9fa5be2

Please sign in to comment.