Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
a65bc4f
7.1 Использует паттерн Наблюдатель
alisameta09 Mar 24, 2025
7edd7aa
7.2 Подготовит рендер-функции к модели
alisameta09 Mar 24, 2025
acd1616
7.3 Доработает модель и датабиндинг. WIP
alisameta09 Mar 26, 2025
2d7d430
7.4 Замкнет датабиндинг. WIP
alisameta09 Mar 26, 2025
c274f37
7.5 Доработает рендеринг доски
alisameta09 Mar 27, 2025
b25ba7a
7.6 Реализует удаление точки маршрута
alisameta09 Mar 27, 2025
a035c89
7.7 Добавит модель для фильтра. WIP
alisameta09 Mar 27, 2025
6ef2c57
7.8 Отрефакторит фильтрацию. WIP
alisameta09 Mar 27, 2025
0b2e095
7.9 Добавит презентер фильтров
alisameta09 Mar 28, 2025
489189d
7.10 Свяжет модель фильтров и презентер доски
alisameta09 Mar 28, 2025
e46bf57
7.11 Добавит форму создания новой точки и фотографии
alisameta09 Mar 28, 2025
2f03b81
7.12 Реализует изменение компонента-заглушки
alisameta09 Mar 28, 2025
55e6be2
7.13 Исправит ошибки
alisameta09 Mar 31, 2025
6fdc5db
7.14 Реализует добавление задачи
alisameta09 Mar 31, 2025
3287e6f
7.15 Правит ошибки в добавлении задачи
alisameta09 Apr 1, 2025
16be96b
7.16 Реализует безопасный ввод
alisameta09 Apr 1, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
},
"dependencies": {
"dayjs": "1.11.7",
"flatpickr": "4.6.13"
"flatpickr": "4.6.13",
"he": "1.2.0"
}
}
1 change: 0 additions & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ <h2 class="visually-hidden">Filter events</h2>
</div>
</div>

<button class="trip-main__event-add-btn btn btn--big btn--yellow" type="button">New event</button>
</div>
</div>
</header>
Expand Down
25 changes: 24 additions & 1 deletion src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@ const POINT_COUNT = 5;

const POINT_TYPES = ['taxi','bus','train','ship','drive','flight','check-in','sightseeing','restaurant'];

const NEW_EVENT = {
'id': '01',
'basePrice': 0,
'dateFrom': null,
'dateTo': null,
'destination': null,
'isFavorite': false,
'offers': [],
'type': 'flight'
};

const FilterType = {
EVERYTHING: 'everything',
FUTURE: 'future',
Expand All @@ -15,4 +26,16 @@ const SortType = {
PRICE: 'price',
};

export {POINT_COUNT, POINT_TYPES, FilterType, SortType};
const UserAction = {
UPDATE_POINT: 'UPDATE_POINT',
ADD_POINT: 'ADD_POINT',
DELETE_POINT: 'DELETE_POINT',
};

const UpdateType = {
PATCH: 'PATCH',
MINOR: 'MINOR',
MAJOR: 'MAJOR',
};

export {POINT_COUNT, POINT_TYPES, FilterType, SortType, UserAction, UpdateType, NEW_EVENT};
37 changes: 30 additions & 7 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,46 @@
import FilterView from './view/filter-view.js';
import HeaderInfoView from './view/header-info-view.js';
import {render} from './framework/render.js';
import NewEventButtonView from './view/new-event-button-view.js';
import {render, RenderPosition} from './framework/render.js';
import TripPresenter from './presenter/trip-presenter.js';
import FilterPresenter from './presenter/filter-presenter.js';
import PointsModel from './model/points-model.js';
import {generateFilter} from './mock/filter.js';
import FilterModel from './model/filter-model.js';

const headerContainer = document.querySelector('.trip-main');
const filterContainer = headerContainer.querySelector('.trip-controls__filters');
const filtersContainer = headerContainer.querySelector('.trip-controls__filters');
const tripEventsContainer = document.querySelector('.trip-events');

const pointsModel = new PointsModel();
const filterModel = new FilterModel();

const tripPresenter = new TripPresenter({
container: tripEventsContainer,
pointsModel,
filterModel,
onNewEventDestroy: handleNewEventFormClose
});

const filterPresenter = new FilterPresenter({
filterContainer: filtersContainer,
filterModel,
pointsModel
});

const filters = generateFilter(pointsModel.points);
const newEventButtonElement = new NewEventButtonView({
onClick: handleNewEventButtonClick
});

function handleNewEventFormClose() {
newEventButtonElement.element.disabled = false;
}

function handleNewEventButtonClick() {
tripPresenter.createEvent();
newEventButtonElement.element.disabled = true;
}

render (new FilterView({filters}), filterContainer);
render (new HeaderInfoView(), headerContainer, 'afterbegin');
render(newEventButtonElement, headerContainer);
render (new HeaderInfoView(), headerContainer, RenderPosition.AFTERBEGIN);

tripPresenter.init();
filterPresenter.init();
12 changes: 0 additions & 12 deletions src/mock/filter.js

This file was deleted.

15 changes: 15 additions & 0 deletions src/model/filter-model.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Observable from '../framework/observable.js';
import {FilterType} from '../const.js';

export default class FilterModel extends Observable {
#filter = FilterType.EVERYTHING;

get filter() {
return this.#filter;
}

setFilter(updateType, filter) {
this.#filter = filter;
this._notify(updateType, filter);
}
}
43 changes: 42 additions & 1 deletion src/model/points-model.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Observable from '../framework/observable.js';
import {mockDestinations} from '../mock/destinations.js';
import {mockOffers} from '../mock/offers.js';
import {getRandomPoints} from '../mock/points.js';
import {POINT_COUNT} from '../const.js';

export default class PointsModel {
export default class PointsModel extends Observable {
#points = Array.from({length: POINT_COUNT}, getRandomPoints);
#offers = mockOffers;
#destinations = mockDestinations;
Expand All @@ -19,4 +20,44 @@ export default class PointsModel {
get destinations() {
return this.#destinations;
}

updatePoint(updateType, update) {
const index = this.#points.findIndex((point) => point.id === update.id);

if (index === -1) {
throw new Error('Can\'t update unexisting point');
}

this.#points = [
...this.#points.slice(0, index),
update,
...this.#points.slice(index + 1),
];

this._notify(updateType, update);
}

addPoint(updateType, update) {
this.#points = [
update,
...this.#points,
];

this._notify(updateType, update);
}

deletePoint(updateType, update) {
const index = this.#points.findIndex((point) => point.id === update.id);

if (index === -1) {
throw new Error('Can\'t update unexisting point');
}

this.#points = [
...this.#points.slice(0, index),
...this.#points.slice(index + 1),
];

this._notify(updateType);
}
}
60 changes: 60 additions & 0 deletions src/presenter/filter-presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {render, replace, remove} from '../framework/render.js';
import FilterView from '../view/filter-view.js';
import {filter} from '../utils/filter.js';
import {FilterType, UpdateType} from '../const.js';

export default class FilterPresenter {
#filterContainer = null;
#filterModel = null;
#pointsModel = null;
#filterElement = null;

constructor({filterContainer, filterModel, pointsModel}) {
this.#filterContainer = filterContainer;
this.#filterModel = filterModel;
this.#pointsModel = pointsModel;

this.#pointsModel.addObserver(this.#handleModelEvent);
this.#filterModel.addObserver(this.#handleModelEvent);
}

get filters() {
const points = this.#pointsModel.points;

return Object.values(FilterType).map((type) => ({
type,
count: filter[type](points).length
}));
}

init() {
const filters = this.filters;
const prevFilterElement = this.#filterElement;

this.#filterElement = new FilterView({
filters,
currentFilterType: this.#filterModel.filter,
onFilterTypeChange: this.#handleFilterTypeChange
});

if (prevFilterElement === null) {
render(this.#filterElement, this.#filterContainer);
return;
}

replace(this.#filterElement, prevFilterElement);
remove(prevFilterElement);
}

#handleModelEvent = () => {
this.init();
};

#handleFilterTypeChange = (filterType) => {
if (this.#filterModel.filter === filterType) {
return;
}

this.#filterModel.setFilter(UpdateType.MAJOR, filterType);
};
}
68 changes: 68 additions & 0 deletions src/presenter/new-event-presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {render, remove, RenderPosition} from '../framework/render.js';
import {UserAction, UpdateType} from '../const.js';
import EditFormView from '../view/edit-form-view.js';

export default class NewEventPresenter {
#pointListContainer = null;
#handleDataChange = null;
#handleDestroy = null;
#editFormElement = null;

constructor({pointListContainer, onDataChange, onDestroy}) {
this.#pointListContainer = pointListContainer;
this.#handleDataChange = onDataChange;
this.#handleDestroy = onDestroy;
}

init(pointsModel) {
if (this.#editFormElement !== null) {
return;
}

this.#editFormElement = new EditFormView({
newEvent: true,
offers: pointsModel.offers,
destinations: pointsModel.destinations,
onFormSubmit: this.#handleFormSubmit,
onDeleteClick: this.#handleDeleteClick
});

render(this.#editFormElement, this.#pointListContainer, RenderPosition.AFTERBEGIN);

document.addEventListener('keydown', this.#escKeyDownHandler);
}

destroy() {
if (this.#editFormElement === null) {
return;
}

this.#handleDestroy();

remove(this.#editFormElement);
this.#editFormElement = null;

document.removeEventListener('keydown', this.#escKeyDownHandler);
}

#handleFormSubmit = (point) => {
this.#handleDataChange(
UserAction.ADD_POINT,
UpdateType.MINOR,
point
);

this.destroy();
};

#handleDeleteClick = () => {
this.destroy();
};

#escKeyDownHandler = (evt) => {
if (evt.key === 'Escape' || evt.key === 'Esc') {
evt.preventDefault();
this.destroy();
}
};
}
23 changes: 21 additions & 2 deletions src/presenter/route-point-presenter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import EditFormView from '../view/edit-form-view.js';
import RoutePointView from '../view/route-point-view.js';
import {render, replace, remove} from '../framework/render.js';
import {UserAction, UpdateType} from '../const.js';

const Mode = {
DEFAULT: 'DEFAULT',
Expand Down Expand Up @@ -41,11 +42,13 @@ export default class RoutePointPresenter {
});

this.#editFormElement = new EditFormView({
newEvent: false,
point: this.#point,
offers: this.#offers,
destinations: this.#destinations,
onRollupBtnClick: this.#rollupBtnClick,
onFormSubmit: this.#handleFormSubmit,
onDeleteClick: this.#handleDeleteClick
});

if (prevRoutePointElement === null || prevEditFormElement === null) {
Expand Down Expand Up @@ -108,11 +111,27 @@ export default class RoutePointPresenter {
};

#handleFavoriteClick = () => {
this.#handleDataChange({...this.#point, isFavorite: !this.#point.isFavorite});
this.#handleDataChange(
UserAction.UPDATE_POINT,
UpdateType.MINOR,
{...this.#point, isFavorite: !this.#point.isFavorite},
);
};

#handleFormSubmit = (point) => {
this.#handleDataChange(point);
this.#handleDataChange(
UserAction.UPDATE_POINT,
UpdateType.MINOR,
point,
);
this.#replaceEditFormToRoutePoint();
};

#handleDeleteClick = (point) => {
this.#handleDataChange(
UserAction.DELETE_POINT,
UpdateType.MINOR,
point,
);
};
}
Loading