Skip to content

Commit

Permalink
Merge pull request #10 from TeaWithSalt/module7-task1
Browse files Browse the repository at this point in the history
  • Loading branch information
keksobot authored May 27, 2024
2 parents 5b68d27 + 9829822 commit a7b82d9
Show file tree
Hide file tree
Showing 15 changed files with 449 additions and 63 deletions.
22 changes: 17 additions & 5 deletions src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ const WAYPOINTS_COUNT = 3;
const PRICES = [100, 150, 200];

const DATES = [
{from: '2019-05-24T23:55:43.845Z', to: '2019-05-24T09:13:25.845Z'},
{from: '2020-09-05T13:34:15.845Z', to: '2020-09-05T22:05:34.845Z'},
{from: '2021-03-12T10:21:12.845Z', to: '2021-03-12T12:18:24.845Z'},
{from: '2024-01-24T23:55:43.845Z', to: '2024-03-24T09:13:25.845Z'},
{from: '2024-04-05T13:34:15.845Z', to: '2024-06-05T22:05:34.845Z'},
{from: '2025-03-12T10:21:12.845Z', to: '2025-03-12T12:18:24.845Z'},
{from: '2022-01-31T19:54:08.845Z', to: '2022-01-31T21:45:19.845Z'},
{from: '2023-06-17T16:15:14.845Z', to: '2023-06-19T02:06:08.845Z'}
{from: '2025-06-17T16:15:14.845Z', to: '2025-06-19T02:06:08.845Z'}
];

const DESTINATIONS = [
Expand Down Expand Up @@ -91,6 +91,18 @@ const EDITING_FORM = {
offers: [ '1', '2' ],
};

const ACTIONS = {
UPDATE_POINT: 'update',
ADD_POINT: 'add',
DELETE_POINT: 'delete',
};

const UPDATE_TYPE = {
MINOR: 'MINOR',
MAJOR: 'MAJOR',
};


const DATE_FORMAT_EDIT = 'DD/MM/YY hh:mm';
const DATE_FORMAT_DAY = 'MMM DD';
const DATE_FORMAT_HOURS = 'hh:mm';
Expand All @@ -116,4 +128,4 @@ export { DESTINATIONS };
export { OFFERS };
export { DATE_FORMAT_EDIT, DATE_FORMAT_DAY, DATE_FORMAT_HOURS };
export { EDITING_FORM };
export { FILTER_TYPE, SORTING_TYPES };
export { FILTER_TYPE, SORTING_TYPES, ACTIONS, UPDATE_TYPE };
46 changes: 40 additions & 6 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { render, RenderPosition } from './framework/render.js';
import FilterView from './view/filter-view.js';
import {render, RenderPosition} from './framework/render.js';
import InfoView from './view/info-view.js';
import EventPresenter from './presenter/event-presenter.js';
import WaypointsModel from './model/waypoint-model.js';
import { getMockFilters } from './mock/filter.js';
import { getMockSorts } from './mock/sort.js';
import {getMockFilters} from './mock/filter.js';
import {getMockSorts} from './mock/sort.js';
import FilterPresenter from './presenter/filter-presenter';
import FilterModel from './model/filter-model';
import NewPointButtonView from './view/new-point-button-view';

const mainContainer = document.querySelector('.trip-main');
const filterContainer = document.querySelector('.trip-controls__filters');
Expand All @@ -13,10 +15,42 @@ const eventContainer = document.querySelector('.trip-events');
const mockFilters = getMockFilters();
const mockSorts = getMockSorts();


const waypointsModel = new WaypointsModel();
const eventPresenter = new EventPresenter({eventContainer, waypointsModel, sorts: mockSorts});
const filterModel = new FilterModel();

const filterPresenter = new FilterPresenter({
filterContainer,
filterModel,
filters: mockFilters
});

const newPointButtonComponent = new NewPointButtonView({
onClick: handleNewPointButtonClick
});

function handleNewPointFormClose() {
newPointButtonComponent.element.disabled = false;
}

const eventPresenter = new EventPresenter({
eventContainer,
waypointsModel,
filterModel,
sorts: mockSorts,
filters: mockFilters,
onNewPointDestroy: handleNewPointFormClose
});


function handleNewPointButtonClick() {
eventPresenter.createWaypoint();
newPointButtonComponent.element.disabled = true;
}


render(new InfoView(), mainContainer, RenderPosition.AFTERBEGIN);
render(new FilterView({filters: mockFilters}), filterContainer);
render(newPointButtonComponent, mainContainer, RenderPosition.BEFOREEND);

filterPresenter.init();
eventPresenter.init();
4 changes: 2 additions & 2 deletions src/mock/waypoint.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {BOOL, DATES, OFFERS, PRICES, TYPES} from '../const.js';
import {getRandomArrayElement, getRandomArrayElements, getRandomInt} from '../utils.js';
import {getId, getRandomArrayElement, getRandomArrayElements, getRandomInt} from '../utils.js';

function getMockWaypoint() {
const type = getRandomArrayElement(TYPES);
Expand All @@ -25,7 +25,7 @@ const mockWaypoints = [
function getRandomWaypoint() {
return {
...getRandomArrayElement(mockWaypoints),
id: Date.now().toString(36) + Math.random().toString(36).slice(2)
id: getId()
};
}

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


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

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

setFilter(filter) {
this.#filter = filter;
this._notify(UPDATE_TYPE.MAJOR, filter);
}
}
58 changes: 55 additions & 3 deletions src/model/waypoint-model.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,62 @@
import { getRandomWaypoint } from '../mock/waypoint.js';
import { WAYPOINTS_COUNT } from '../const.js';
import {getRandomWaypoint} from '../mock/waypoint.js';
import {UPDATE_TYPE, WAYPOINTS_COUNT} from '../const.js';
import Observable from '../framework/observable';

export default class WaypointsModel {
export default class WaypointsModel extends Observable {
waypoints = Array.from({length: WAYPOINTS_COUNT}, getRandomWaypoint);

getWaypoints() {
return this.waypoints;
}

getWaypoint(id) {
return this.waypoints.find((waypoint) => waypoint.id === id);
}

setWaypoints(waypoints) {
this.waypoints = waypoints;
}

setWaypoint(waypoint, id) {
this.waypoints = [...this.waypoints.filter((other) => other.id !== id), waypoint];
}

addPoint(updateType, update) {
this.waypoints = [
update,
...this.waypoints,
];
this._notify(updateType, update);
}

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

if (index === -1) {
throw new Error('The point doesn\'t exist!');
}

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

this._notify(updateType, update);
}

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

if (index === -1) {
throw new Error('The point doesn\'t exist!');
}

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

this._notify(UPDATE_TYPE.MINOR, update);
}
}
103 changes: 90 additions & 13 deletions src/presenter/event-presenter.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,97 @@
import {render} from '../framework/render.js';
import {remove, render, RenderPosition} from '../framework/render.js';
import SortView from '../view/sort-view.js';
import EventListView from '../view/event-list-view.js';
import WaypointPresenter from './waypoint-presenter';
import {ACTIONS as USER_ACTION, SORTING_TYPES, UPDATE_TYPE} from '../const';
import NewWaypointPresenter from './new-waypoint-presenter';

export default class EventPresenter {
#eventListContainer = new EventListView();
#waypointPresenters = [];
#eventContainer;
#sorts;
#filters;
#currentSortType;
#emptyComponent;
#filterModel;
#newPointPresenter;
#onNewPointDestroy;

constructor({eventContainer, waypointsModel, sorts}) {
constructor({eventContainer, waypointsModel, filterModel, sorts, filters, onNewPointDestroy}) {
this.#eventContainer = eventContainer;
this.#sorts = sorts;
this.waypoints = waypointsModel.getWaypoints();
this.#filters = filters;
this.waypointsModel = waypointsModel;
this.#filterModel = filterModel;
this.#onNewPointDestroy = onNewPointDestroy;
this.#currentSortType = sorts[0].name;
this.#sortWaypoints(sorts[0].name);
}

init() {
render(new SortView({sorts: this.#sorts, onChange: this.#handleSortTypeChange}), this.#eventContainer);
render(
new SortView({sorts: this.#sorts, currentSort: this.#currentSortType, onChange: this.#handleSortTypeChange}),
this.#eventContainer,
RenderPosition.BEFOREEND
);
this.renderWaypoints();
this.#filterModel.addObserver(this.#handleFilterTypeChange.bind(this));
this.waypointsModel.addObserver(this.#handleModelEvent);
}

createWaypoint() {
this.#newPointPresenter = new NewWaypointPresenter({
pointListContainer: this.#eventListContainer.element,
onDataChange: this.#handleWaypointChange,
onDestroy: this.#onNewPointDestroy,
closeAllEditForms: () => this.#closeAllEditForms(),
});

this.#newPointPresenter.init();
}

renderWaypoints() {
render(this.#eventListContainer, this.#eventContainer);
this.waypoints.forEach((waypoint) => this.#renderWaypoint(waypoint));
const filteredPoints = this.#getFilteredWaypoints(this.waypointsModel.getWaypoints());
filteredPoints.forEach((waypoint) => this.#renderWaypoint(waypoint));
}

reset() {
this.#waypointPresenters.forEach((waypointPresenter) => waypointPresenter.destroy());
this.#waypointPresenters = [];

if (this.#emptyComponent) {
remove(this.#emptyComponent);
}
}

#closeAllEditForms() {
if (this.#newPointPresenter) {
this.#newPointPresenter.destroy();
}

this.#waypointPresenters.forEach((waypoint) => waypoint.closeForm());
}

#handleWaypointChange = (updatedWaypoint) => {
this.waypoints = this.waypoints.map((waypoint) => waypoint.id === updatedWaypoint.id ? updatedWaypoint : waypoint);
this.#waypointPresenters
.find((waypointPresenter) => waypointPresenter.id === updatedWaypoint.id)
.init(updatedWaypoint);
#handleWaypointChange = (action, type, waypoint) => {
switch (action) {
case USER_ACTION.ADD_POINT:
this.#sortWaypoints(SORTING_TYPES.DAY);
this.waypointsModel.addPoint(type, waypoint);
break;
case USER_ACTION.DELETE_POINT:
this.waypointsModel.deletePoint(type, waypoint);
break;
case USER_ACTION.UPDATE_POINT:
this.waypointsModel.updatePoint(type, waypoint);
break;
}
};

#renderWaypoint(waypoint) {
const waypointPresenter = new WaypointPresenter({
waypoint,
containerElement: this.#eventContainer,
containerElement: this.#eventListContainer.element,
closeAllEditForms: () => this.#closeAllEditForms(),
onChange: this.#handleWaypointChange
});
Expand All @@ -52,16 +105,40 @@ export default class EventPresenter {
}
this.#sortWaypoints(sortType);
this.#deleteWaypoints();
this.waypoints.forEach((waypoint) => this.#renderWaypoint(waypoint));
this.waypointsModel.getWaypoints().forEach((waypoint) => this.#renderWaypoint(waypoint));
};

#sortWaypoints(sortType) {
this.#sorts.find((sort) => sort.name === sortType).getPoints(this.waypoints);
this.#sorts.find((sort) => sort.name === sortType).getPoints(this.waypointsModel.getWaypoints());
this.#currentSortType = sortType;
}

#getFilteredWaypoints(waypoints) {
return this.#filters.find((filter) => filter.name === this.#filterModel.filter).getPoints(waypoints);
}

#deleteWaypoints() {
this.#waypointPresenters.forEach((waypoint) => waypoint.destroy());
this.#waypointPresenters = [];
}

#handleFilterTypeChange() {
this.reset();
this.#currentSortType = SORTING_TYPES.DAY;
this.renderWaypoints();
}

#handleModelEvent = (updateType) => {
switch (updateType) {
case UPDATE_TYPE.MINOR:
this.reset();
this.renderWaypoints();
break;
case UPDATE_TYPE.MAJOR:
this.reset();
this.renderWaypoints();
this.#currentSortType = SORTING_TYPES.DAY;
break;
}
};
}
45 changes: 45 additions & 0 deletions src/presenter/filter-presenter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {remove, render, replace} from '../framework/render';
import FilterView from '../view/filter-view';

export default class FilterPresenter {
#filterContainer;
#filters;
#filterComponent = null;
#filterModel;

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

this.#filterModel.addObserver(this.init.bind(this));
}

init() {
const prevFilterComponent = this.#filterComponent;

this.#filterComponent = new FilterView({
filters: this.#filters,
type: this.#filterModel.filter,
onChange: this.#handleTypeChange
});

if (prevFilterComponent === null) {
render(this.#filterComponent, this.#filterContainer);
return;
}

replace(this.#filterComponent, prevFilterComponent);
remove(prevFilterComponent);

render(this.#filterComponent, this.#filterContainer);
}

#handleTypeChange = (type) => {
if (this.#filterModel.filter === type) {
return;
}

this.#filterModel.setFilter(type);
};
}
Loading

0 comments on commit a7b82d9

Please sign in to comment.