From fcaeb81319abb213f52fdd115d576a3cea9c9a37 Mon Sep 17 00:00:00 2001 From: Sergey Ivanov Date: Fri, 27 Sep 2024 15:28:40 +0300 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D1=82=20=D0=BF=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B8=20=D0=BE=D1=82=D1=81?= =?UTF-8?q?=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8=20=D1=82=D0=BE=D1=87?= =?UTF-8?q?=D0=B5=D0=BA=20=D0=BF=D1=83=D1=82=D0=B5=D1=88=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 19 +++++++++- src/framework/view/abstract-view.js | 1 + src/model/points-trip-model.js | 2 +- src/presenter/list-presenter.js | 33 ++++++++-------- src/view/add-new-point-view.js | 4 +- src/view/edit-poit-view.js | 10 ++--- src/view/event-item-view.js | 4 +- src/view/section-trip-info-view.js | 38 +++++++++++++++---- .../{sort-view.js => sort-button-view.js} | 0 src/view/trip-events-message-view.js | 15 ++++++-- 10 files changed, 87 insertions(+), 39 deletions(-) rename src/view/{sort-view.js => sort-button-view.js} (100%) diff --git a/src/const.js b/src/const.js index 8d29191..b95f1e1 100644 --- a/src/const.js +++ b/src/const.js @@ -1,4 +1,19 @@ -const EVENT_TYPES = ['taxi', 'bus', 'train', 'ship', 'drive', 'flight', 'check-in', 'sightseeing', 'restaurant']; +const EVENT_TYPES = [ + 'taxi' + , 'bus' + , 'train' + , 'ship' + , 'drive' + , 'flight' + , 'check-in' + , 'sightseeing' + , 'restaurant']; +const MESSAGE = { + EMPTY: 'Click New Event to create your first point', + LOADING: 'Loading...', + FAILED_LOAD: 'Failed to load latest route information', +}; -export {EVENT_TYPES}; + +export {EVENT_TYPES, MESSAGE}; diff --git a/src/framework/view/abstract-view.js b/src/framework/view/abstract-view.js index fa2a552..b527e82 100644 --- a/src/framework/view/abstract-view.js +++ b/src/framework/view/abstract-view.js @@ -14,6 +14,7 @@ export default class AbstractView { /** @type {HTMLElement|null} Элемент представления */ #element = null; + constructor() { if (new.target === AbstractView) { throw new Error('Can\'t instantiate AbstractView, only concrete one.'); diff --git a/src/model/points-trip-model.js b/src/model/points-trip-model.js index 130f96a..5213b39 100644 --- a/src/model/points-trip-model.js +++ b/src/model/points-trip-model.js @@ -6,7 +6,7 @@ export default class PointsTripModel { this.#points = points; } - get() { + get points() { return this.#points; } } diff --git a/src/presenter/list-presenter.js b/src/presenter/list-presenter.js index c55a814..7e7fa9b 100644 --- a/src/presenter/list-presenter.js +++ b/src/presenter/list-presenter.js @@ -1,10 +1,11 @@ import { render, RenderPosition, replace } from '../framework/render.js'; +import { MESSAGE } from '../const.js'; import SectionTripInfoView from '../view/section-trip-info-view.js'; import NewEventButtonView from '../view/new-event-button-view.js'; import TripFiltersFormView from '../view/trip-filters-form-view.js'; -import SortButtonView from '../view/sort-view.js'; +import SortButtonView from '../view/sort-button-view.js'; import TripEventListView from '../view/trip-events-list-view.js'; import EventItemView from '../view/event-item-view.js'; // import AddNewPointView from '../view/add-new-point-view.js'; @@ -16,10 +17,10 @@ const tripControlsFilters = document.querySelector('.trip-controls__filters'); export default class ListPresenter { - #listContainer; - #pointsTrip; - #destinations; - #offers; + #listContainer = null; + #pointsTrip = null; + #destinations = null; + #offers = null; #listComponent = new TripEventListView(); @@ -28,7 +29,7 @@ export default class ListPresenter { constructor({ listContainer, pointsTripModel, destinationsTripModel, offersTripModel }) { this.#listContainer = listContainer; - this.#pointsTrip = pointsTripModel.get(); + this.#pointsTrip = pointsTripModel.points; this.#destinations = destinationsTripModel; this.#offers = offersTripModel; } @@ -114,27 +115,27 @@ export default class ListPresenter { #renderList() { /** Отрисовка шапки сайта */ - render(new SectionTripInfoView({allDestinations: this.#destinations, allPoints: this.#listPoints}), tripMain, RenderPosition.AFTERBEGIN); // Заголовок, даты, общая цена + render(new SectionTripInfoView({allDestinations: this.#destinations , allPoints: this.#listPoints}), tripMain, RenderPosition.AFTERBEGIN); // Заголовок, даты, общая цена render(new NewEventButtonView(), tripMain); // Заголовок, кнопка добавить событие render (new TripFiltersFormView(), tripControlsFilters); // Кнопки сортировки + /** Рендерим кнопки сортировки */ + render(new SortButtonView(), this.#listContainer); /** Рендерим список для новых событий */ render(this.#listComponent, this.#listContainer); /** Если список событий пуст, то отрисовываем сообщение */ - if (this.#listPoints.length === 0) { - render(new TripEventsMessage, this.#listContainer); + render(new TripEventsMessage(MESSAGE.EMPTY), this.#listContainer); - } - /** Рендерим кнопки сортировки */ - render(new SortButtonView(), this.#listContainer); + if (this.#listPoints.length !== 0) { - /** Рендерим редактируемое событие */ - this.#rederTripEvent(this.#listPoints[0]); + /** Рендерим редактируемое событие */ + this.#rederTripEvent(this.#listPoints[0]); - /** Рендерим список событий */ - this.#renderAllTripEvents(); + /** Рендерим список событий */ + this.#renderAllTripEvents(); + } // Переделать логику отрисовки новой точки! diff --git a/src/view/add-new-point-view.js b/src/view/add-new-point-view.js index 31097b1..34fc5b5 100644 --- a/src/view/add-new-point-view.js +++ b/src/view/add-new-point-view.js @@ -165,8 +165,8 @@ function createAddNewPointTemplate() { export default class AddNewPointView extends AbstractView { - #pointsTrip; - #offers; + #pointsTrip = null; + #offers = null; constructor(pointsTrip, offers) { super(); diff --git a/src/view/edit-poit-view.js b/src/view/edit-poit-view.js index 6f72e08..b9b304a 100644 --- a/src/view/edit-poit-view.js +++ b/src/view/edit-poit-view.js @@ -154,12 +154,12 @@ function createEditPointTemplate(tripEventData, destinations, allDestinations) { export default class EditPointView extends AbstractView { - #tripEventData; - #destinations; - #allDestinations; + #tripEventData = null; + #destinations = null; + #allDestinations = null; - #handleFormSubmit; - #handleCloseFormClick; + #handleFormSubmit = null; + #handleCloseFormClick = null; constructor({tripEventData, destinations, allDestinations, onFormSubmit, onCloseFormClick}) { super(); diff --git a/src/view/event-item-view.js b/src/view/event-item-view.js index 465028d..cba4076 100644 --- a/src/view/event-item-view.js +++ b/src/view/event-item-view.js @@ -67,8 +67,8 @@ function createEventItemTemplate(tripEventData) { export default class EventItemView extends AbstractView { - #tripEventData; - #handleEditClick; + #tripEventData = null; + #handleEditClick = null; constructor(tripEventData, {onEditClick}) { super(); diff --git a/src/view/section-trip-info-view.js b/src/view/section-trip-info-view.js index 88d8523..2626165 100644 --- a/src/view/section-trip-info-view.js +++ b/src/view/section-trip-info-view.js @@ -3,20 +3,42 @@ import { humanizeEventDate } from '../utils.js'; function createSectionTripInfoTemplate(allDestinations, allPoints) { - const eventDateStart = allPoints[0].date_from; - const eventDateEnd = allPoints[allPoints.length - 1].date_to; - const allDestinationsStr = allDestinations.map((destination) => (destination.name)).join(' — '); + function getDateAllPoints() { + + let eventDateStart = ''; + let eventDateEnd = ''; + let allDestinationsStr = ''; + if (allPoints.length !== 0) { + eventDateStart = allPoints[0].date_from; + eventDateEnd = allPoints[allPoints.length - 1].date_to; + allDestinationsStr = allDestinations.map((destination) => (destination.name)).join(' — '); + return {eventDateStart, eventDateEnd, allDestinationsStr}; + } + + return {eventDateStart, eventDateEnd, allDestinationsStr}; + } + const date = getDateAllPoints(); /** Без учета выбранных предложений */ - const totalBasePrice = allPoints.reduce((acc, point) => acc + point.base_price, 0); + function getTotalBasePrice() { + + let totalBasePrice = 0; + if (allPoints.length !== 0) { + totalBasePrice = allPoints.reduce((acc, point) => acc + point.base_price, 0); + return totalBasePrice; + } + return totalBasePrice; + } + + const totalBasePrice = getTotalBasePrice(); return ( `
-

${allDestinationsStr}

+

${date.allDestinationsStr}

-

${humanizeEventDate(eventDateStart, 'headerDate')} — ${humanizeEventDate(eventDateEnd, 'headerDate')}

+

${humanizeEventDate(date.eventDateStart, 'headerDate')} — ${humanizeEventDate(date.eventDateEnd, 'headerDate')}

@@ -28,8 +50,8 @@ function createSectionTripInfoTemplate(allDestinations, allPoints) { export default class SectionTripInfoView extends AbstractView { - #allDestinations; - #allPoints; + #allDestinations = null; + #allPoints = null; constructor({allDestinations, allPoints}) { diff --git a/src/view/sort-view.js b/src/view/sort-button-view.js similarity index 100% rename from src/view/sort-view.js rename to src/view/sort-button-view.js diff --git a/src/view/trip-events-message-view.js b/src/view/trip-events-message-view.js index 061795c..720e3b3 100644 --- a/src/view/trip-events-message-view.js +++ b/src/view/trip-events-message-view.js @@ -1,12 +1,21 @@ import AbstractView from '../framework/view/abstract-view.js'; -function createTripEventsMessageTemplate() { - return '

Click New Event to create your first point

'; +function createTripEventsMessageTemplate(message) { + return `

${message}

`; } export default class TripEventsMessage extends AbstractView { + + #message = null; + + constructor(message) { + + super(); + this.#message = message; + } + get template() { - return createTripEventsMessageTemplate(); + return createTripEventsMessageTemplate(this.#message); } } From 58ed5025b6e4ae8c5a607ea1de0035c1fb5ea630 Mon Sep 17 00:00:00 2001 From: Sergey Ivanov Date: Fri, 27 Sep 2024 23:32:27 +0300 Subject: [PATCH 2/5] =?UTF-8?q?fix:=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D1=8F=D0=BB=D0=B5=D1=82=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80?= =?UTF-8?q?=D0=BA=D1=83=20=D0=BD=D0=B0=20=D0=BD=D0=B0=D0=BB=D0=B8=D1=87?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 14 ++++++++++++++ src/presenter/list-presenter.js | 8 +++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/const.js b/src/const.js index b95f1e1..7436e1b 100644 --- a/src/const.js +++ b/src/const.js @@ -15,5 +15,19 @@ const MESSAGE = { FAILED_LOAD: 'Failed to load latest route information', }; +const FiltersPoints = { + EVERYTHING: 'everything', + FUTURE: 'future', + PRESENT: 'present', + PAST: 'past' +}; + +const SortPoints = { + DAY: 'day', + EVENT: 'event', + TIME: 'time', + PRICE: 'price', + OFFERS: 'offers', +}; export {EVENT_TYPES, MESSAGE}; diff --git a/src/presenter/list-presenter.js b/src/presenter/list-presenter.js index 7e7fa9b..6a2f9b8 100644 --- a/src/presenter/list-presenter.js +++ b/src/presenter/list-presenter.js @@ -125,10 +125,12 @@ export default class ListPresenter { /** Рендерим список для новых событий */ render(this.#listComponent, this.#listContainer); - /** Если список событий пуст, то отрисовываем сообщение */ - render(new TripEventsMessage(MESSAGE.EMPTY), this.#listContainer); + if (this.#listPoints.length === 0) { + /** Если список событий пуст, то отрисовываем сообщение */ + render(new TripEventsMessage(MESSAGE.EMPTY), this.#listContainer); - if (this.#listPoints.length !== 0) { + } else { + /** Если список событий не пуст, то отрисовываем события */ /** Рендерим редактируемое событие */ this.#rederTripEvent(this.#listPoints[0]); From 1b1177b2ba20de5ac0bb03195b94e8f39c73b1c0 Mon Sep 17 00:00:00 2001 From: Sergey Ivanov Date: Sat, 28 Sep 2024 01:34:20 +0300 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D1=82=20=D0=BB=D0=BE=D0=B3=D0=B8=D0=BA=D1=83?= =?UTF-8?q?=20=D1=81=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8?= =?UTF-8?q?=20=D0=B8=20=D1=84=D0=B8=D0=BB=D1=8C=D1=82=D1=80=D0=B0=D1=86?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 8 ++-- src/main.js | 10 +++- src/mock/filter.js | 7 +++ src/presenter/list-presenter.js | 54 +++++++++++++++++++--- src/utils/filter.js | 53 ++++++++++++++++++++++ src/{ => utils}/utils.js | 11 +---- src/view/edit-poit-view.js | 2 +- src/view/event-item-view.js | 2 +- src/view/section-trip-info-view.js | 2 +- src/view/sort-button-view.js | 73 ++++++++++++++++++------------ src/view/trip-filters-form-view.js | 60 ++++++++++++++---------- 11 files changed, 204 insertions(+), 78 deletions(-) create mode 100644 src/mock/filter.js create mode 100644 src/utils/filter.js rename src/{ => utils}/utils.js (82%) diff --git a/src/const.js b/src/const.js index 7436e1b..988b7fe 100644 --- a/src/const.js +++ b/src/const.js @@ -15,14 +15,14 @@ const MESSAGE = { FAILED_LOAD: 'Failed to load latest route information', }; -const FiltersPoints = { +const FilterType = { EVERYTHING: 'everything', FUTURE: 'future', PRESENT: 'present', PAST: 'past' }; -const SortPoints = { +const SortType = { DAY: 'day', EVENT: 'event', TIME: 'time', @@ -30,4 +30,6 @@ const SortPoints = { OFFERS: 'offers', }; -export {EVENT_TYPES, MESSAGE}; +const DisabledSortType = [SortType.EVENT, SortType.OFFERS]; + +export {EVENT_TYPES, MESSAGE, FilterType, SortType, DisabledSortType}; diff --git a/src/main.js b/src/main.js index 0e90837..da1c788 100644 --- a/src/main.js +++ b/src/main.js @@ -1,10 +1,14 @@ -import ListPresenter from './presenter/list-presenter.js'; +import {render} from './framework/render.js'; +import ListPresenter from './presenter/list-presenter.js'; import PointsTripModel from './model/points-trip-model.js'; import OffersTripsModel from './model/offers-trip-model.js'; import DestinationsTripModel from './model/destinations-trip-model.js'; +import TripFiltersFormView from './view/trip-filters-form-view.js'; +import { generateFilter } from './mock/filter.js'; const tripEventsElement = document.querySelector('.trip-events'); +const tripFiltersElement = document.querySelector('.trip-controls__filters'); const pointsTripModel = new PointsTripModel(); const offersTripModel = new OffersTripsModel(); @@ -18,6 +22,10 @@ const listPresenter = new ListPresenter({ offersTripModel, }); +const filters = generateFilter(); + +render(new TripFiltersFormView({filters}), tripFiltersElement); + listPresenter.init(); diff --git a/src/mock/filter.js b/src/mock/filter.js new file mode 100644 index 0000000..08d3ec2 --- /dev/null +++ b/src/mock/filter.js @@ -0,0 +1,7 @@ +import { filter } from '../utils/filter.js'; + +function generateFilter() { + return Object.entries(filter).map(([filterType]) => ({type: filterType})); +} + +export { generateFilter }; diff --git a/src/presenter/list-presenter.js b/src/presenter/list-presenter.js index 6a2f9b8..24c9832 100644 --- a/src/presenter/list-presenter.js +++ b/src/presenter/list-presenter.js @@ -1,9 +1,10 @@ import { render, RenderPosition, replace } from '../framework/render.js'; import { MESSAGE } from '../const.js'; +import { SortType } from '../const.js'; +import { sortEventsByDay, sortEventsByTime, sortEventsByPrice } from '../utils/filter.js'; import SectionTripInfoView from '../view/section-trip-info-view.js'; import NewEventButtonView from '../view/new-event-button-view.js'; -import TripFiltersFormView from '../view/trip-filters-form-view.js'; import SortButtonView from '../view/sort-button-view.js'; import TripEventListView from '../view/trip-events-list-view.js'; @@ -13,7 +14,7 @@ import EditPointView from '../view/edit-poit-view.js'; import TripEventsMessage from '../view/trip-events-message-view.js'; const tripMain = document.querySelector('.trip-main'); -const tripControlsFilters = document.querySelector('.trip-controls__filters'); + export default class ListPresenter { @@ -25,7 +26,9 @@ export default class ListPresenter { #listComponent = new TripEventListView(); #listPoints = []; - + #sourcedTripPoints = []; + #sortComponent = null; + #currentSortType = SortType.DAY; constructor({ listContainer, pointsTripModel, destinationsTripModel, offersTripModel }) { this.#listContainer = listContainer; @@ -37,11 +40,13 @@ export default class ListPresenter { init() { this.#listPoints = [...this.#pointsTrip]; + this.#sourcedTripPoints = [...this.#pointsTrip]; + /** Отрисовка всех компонентов */ this.#renderList(); } - + /** Елемент события путешествия */ #tripEventData(item) { const destination = this.#destinations.getDestinationById(item); @@ -117,10 +122,9 @@ export default class ListPresenter { /** Отрисовка шапки сайта */ render(new SectionTripInfoView({allDestinations: this.#destinations , allPoints: this.#listPoints}), tripMain, RenderPosition.AFTERBEGIN); // Заголовок, даты, общая цена render(new NewEventButtonView(), tripMain); // Заголовок, кнопка добавить событие - render (new TripFiltersFormView(), tripControlsFilters); // Кнопки сортировки /** Рендерим кнопки сортировки */ - render(new SortButtonView(), this.#listContainer); + this.#renderSort(); /** Рендерим список для новых событий */ render(this.#listComponent, this.#listContainer); @@ -144,4 +148,42 @@ export default class ListPresenter { // render(new AddNewPointView({pointsTrip: this.#listPoints, offers: this.#offers}), this.#listContainer); } + /** Отрисовка cортировки событий путешествия */ + #renderSort() { + this.#sortComponent = new SortButtonView({ + onSortTypeChange: this.#handleSortTypeChange, + currentSortType: this.#currentSortType, + }); + + render(this.#sortComponent, this.#listContainer); + } + + /** Сортировка событий путешествия */ + #sortTripPoints(sortType) { + + switch (sortType) { + case SortType.DAY: + this.#pointsTrip.sort(sortEventsByDay); + break; + case SortType.TIME: + this.#pointsTrip.sort(sortEventsByTime); + break; + case SortType.PRICE: + this.#pointsTrip.sort(sortEventsByPrice); + break; + default: + this.#pointsTrip = [...this.#sourcedTripPoints]; + } + + this.#currentSortType = sortType; + } + + #handleSortTypeChange = (sortType) => { + if (this.#currentSortType === sortType) { + return; + } + + this.#sortTripPoints(sortType); + }; + } diff --git a/src/utils/filter.js b/src/utils/filter.js new file mode 100644 index 0000000..dd3f6a0 --- /dev/null +++ b/src/utils/filter.js @@ -0,0 +1,53 @@ +import { FilterType } from '../const.js'; +import dayjs from 'dayjs'; + +const filter = { + [FilterType.EVERYTHING]: (pointsTrip) => pointsTrip, + [FilterType.FUTURE]: (pointsTrip) => pointsTrip.filter((pointTrip) => new Date(pointTrip.date_from) > Date.now()), + [FilterType.PRESENT]: (pointsTrip) => pointsTrip.filter((pointTrip) => new Date(pointTrip.date_from) <= Date.now() && new Date(pointTrip.date_to) >= Date.now()), + [FilterType.PAST]: (pointsTrip) => pointsTrip.filter((pointTrip) => new Date(pointTrip.date_to) < Date.now()), +}; + + +function sortEventsByDay (eventA, eventB) { + + if (dayjs(eventA.date_from).diff(dayjs(eventB.date_from)) < 0) { + return -1; + } + + if (dayjs(eventA.date_from).diff(dayjs(eventB.date_from)) > 0) { + return 1; + } + + return 0; +} + +function sortEventsByTime (eventA, eventB) { + + if (dayjs(eventA.date_from).diff(dayjs(eventA.date_to)) < + dayjs(eventB.date_from).diff(dayjs(eventB.date_to))) { + return -1; + } + + if (dayjs(eventA.date_from).diff(dayjs(eventA.date_to)) > + dayjs(eventB.date_from).diff(dayjs(eventB.date_to))) { + return 1; + } + + return 0; +} + +function sortEventsByPrice (eventA, eventB) { + + if (eventA.base_price < eventB.base_price) { + return -1; + } + + if (eventA.base_price > eventB.base_price) { + return 1; + } + + return 0; +} + +export { filter, sortEventsByDay, sortEventsByTime, sortEventsByPrice }; diff --git a/src/utils.js b/src/utils/utils.js similarity index 82% rename from src/utils.js rename to src/utils/utils.js index 095ac86..98b4747 100644 --- a/src/utils.js +++ b/src/utils/utils.js @@ -1,14 +1,5 @@ import dayjs from 'dayjs'; -/** - * Returns a random element from the given array. - * @param {Array} items - Array of any type of elements. - * @returns {any} - Random element from the array. - */ -function getRandomArrayElement(items) { - return items[Math.floor(Math.random() * items.length)]; -} - const FORMATS = { 'headerDate': 'DD MMM', 'date': 'MMM D', @@ -62,4 +53,4 @@ function capitalizeFirstLetter(word) { return word[0].toUpperCase() + word.slice(1); } -export { getRandomArrayElement, humanizeEventDate, getDuration, capitalizeFirstLetter }; +export { humanizeEventDate, getDuration, capitalizeFirstLetter }; diff --git a/src/view/edit-poit-view.js b/src/view/edit-poit-view.js index b9b304a..27b0a18 100644 --- a/src/view/edit-poit-view.js +++ b/src/view/edit-poit-view.js @@ -1,5 +1,5 @@ import {EVENT_TYPES} from '../const.js'; -import { humanizeEventDate, capitalizeFirstLetter } from '../utils.js'; +import { humanizeEventDate, capitalizeFirstLetter } from '../utils/utils.js'; import AbstractView from '../framework/view/abstract-view.js'; function createOffersTemplate(tripEventData) { diff --git a/src/view/event-item-view.js b/src/view/event-item-view.js index cba4076..12deb90 100644 --- a/src/view/event-item-view.js +++ b/src/view/event-item-view.js @@ -1,4 +1,4 @@ -import {humanizeEventDate, getDuration} from '../utils.js'; +import {humanizeEventDate, getDuration} from '../utils/utils.js'; import AbstractView from '../framework/view/abstract-view.js'; function createOffersTemplate(offers) { diff --git a/src/view/section-trip-info-view.js b/src/view/section-trip-info-view.js index 2626165..f94643c 100644 --- a/src/view/section-trip-info-view.js +++ b/src/view/section-trip-info-view.js @@ -1,5 +1,5 @@ import AbstractView from '../framework/view/abstract-view.js'; -import { humanizeEventDate } from '../utils.js'; +import { humanizeEventDate } from '../utils/utils.js'; function createSectionTripInfoTemplate(allDestinations, allPoints) { diff --git a/src/view/sort-button-view.js b/src/view/sort-button-view.js index dad059c..0797394 100644 --- a/src/view/sort-button-view.js +++ b/src/view/sort-button-view.js @@ -1,38 +1,51 @@ import AbstractView from '../framework/view/abstract-view.js'; +import { SortType, DisabledSortType } from '../const.js'; -function createSortButtonTemplate() { - return ( - `
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
` - ); +function createSortButtonTemplate(currentSortType) { + + return (` +
+ + ${Object.values(SortType).map((type) => (` +
+ + +
+ `)).join('')} + +
+ `); } export default class SortButtonView extends AbstractView { + + #handleSortTypeChange = null; + #currentSortType = null; + + constructor({ onSortTypeChange, currentSortType }) { + super(); + this.#handleSortTypeChange = onSortTypeChange; + this.#currentSortType = currentSortType; + + this.element.addEventListener('change', this.#sortTypeChangeHandler); + } + + #sortTypeChangeHandler = (evt) => { + evt.preventDefault(); + this.#handleSortTypeChange(evt.target.dataset.sortType); + }; + get template() { - return createSortButtonTemplate(); + return createSortButtonTemplate(this.#currentSortType); } } diff --git a/src/view/trip-filters-form-view.js b/src/view/trip-filters-form-view.js index 5e023d3..d06361a 100644 --- a/src/view/trip-filters-form-view.js +++ b/src/view/trip-filters-form-view.js @@ -1,34 +1,44 @@ import AbstractView from '../framework/view/abstract-view.js'; -function createTripFiltersFormTemplate() { - return `
-
- - -
- -
- - -
- -
- - -
- -
- - -
- - -
`; +function createTripFiltersFormTemplate(filters) { + + return (` +
+
+

Filter events

+
+ + ${filters.map((filter) => (` +
+ + ${filter.count === 0 ? 'disabled' : ''} + +
+ `)).join('')} + + +
+
+
+ `); } export default class TripFiltersFormView extends AbstractView { + + #filters = null; + + constructor({ filters }) { + super(); + this.#filters = filters; + } + get template() { - return createTripFiltersFormTemplate(); + return createTripFiltersFormTemplate(this.#filters); } } From 576a3639a9b30f199f5b05ce925e4881d98a3826 Mon Sep 17 00:00:00 2001 From: Sergey Ivanov Date: Sat, 28 Sep 2024 02:09:13 +0300 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D1=8F=D0=B5=D1=82=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D1=83?= =?UTF-8?q?=20=D0=BE=D0=BA=D1=80=D1=83=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B9=D0=BC=D0=B8=D0=BD=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/section-trip-info-view.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/view/section-trip-info-view.js b/src/view/section-trip-info-view.js index f94643c..9344c85 100644 --- a/src/view/section-trip-info-view.js +++ b/src/view/section-trip-info-view.js @@ -22,12 +22,12 @@ function createSectionTripInfoTemplate(allDestinations, allPoints) { /** Без учета выбранных предложений */ function getTotalBasePrice() { - let totalBasePrice = 0; + let allBasePrice = 0; if (allPoints.length !== 0) { - totalBasePrice = allPoints.reduce((acc, point) => acc + point.base_price, 0); - return totalBasePrice; + allBasePrice = allPoints.reduce((acc, point) => acc + point.base_price, 0); + return allBasePrice; } - return totalBasePrice; + return allBasePrice; } const totalBasePrice = getTotalBasePrice(); From 9fee6d39f471faaf859610128cb2c38e340e234c Mon Sep 17 00:00:00 2001 From: Sergey Ivanov Date: Sun, 29 Sep 2024 12:44:56 +0300 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20=D0=A0=D0=B5=D0=BD=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B8=D1=82=20=D0=A1=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D1=83=20=D0=B8=20=D0=A4=D0=B8=D0=BB=D1=8C=D1=82=D1=80?= =?UTF-8?q?=D1=8B=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE.=20?= =?UTF-8?q?=D0=92=D1=8B=D0=BD=D0=BE=D1=81=D0=B8=D1=82=20=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D0=B5=D1=80=D0=B8=D0=BD=D0=B3=20=D1=88=D0=B0=D0=BF=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B2=20=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D0=BF=D1=80=D0=B5=D0=B7=D0=B5=D0=BD=D1=82=D0=B5?= =?UTF-8?q?=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main.js | 9 --- src/presenter/header-presenter.js | 34 ++++++++++++ src/presenter/list-presenter.js | 92 +++++++++++++++++++------------ 3 files changed, 90 insertions(+), 45 deletions(-) create mode 100644 src/presenter/header-presenter.js diff --git a/src/main.js b/src/main.js index da1c788..297796f 100644 --- a/src/main.js +++ b/src/main.js @@ -1,14 +1,9 @@ -import {render} from './framework/render.js'; - import ListPresenter from './presenter/list-presenter.js'; import PointsTripModel from './model/points-trip-model.js'; import OffersTripsModel from './model/offers-trip-model.js'; import DestinationsTripModel from './model/destinations-trip-model.js'; -import TripFiltersFormView from './view/trip-filters-form-view.js'; -import { generateFilter } from './mock/filter.js'; const tripEventsElement = document.querySelector('.trip-events'); -const tripFiltersElement = document.querySelector('.trip-controls__filters'); const pointsTripModel = new PointsTripModel(); const offersTripModel = new OffersTripsModel(); @@ -22,10 +17,6 @@ const listPresenter = new ListPresenter({ offersTripModel, }); -const filters = generateFilter(); - -render(new TripFiltersFormView({filters}), tripFiltersElement); - listPresenter.init(); diff --git a/src/presenter/header-presenter.js b/src/presenter/header-presenter.js new file mode 100644 index 0000000..8143efe --- /dev/null +++ b/src/presenter/header-presenter.js @@ -0,0 +1,34 @@ +import { render, RenderPosition } from '../framework/render.js'; + +import SectionTripInfoView from '../view/section-trip-info-view.js'; +import NewEventButtonView from '../view/new-event-button-view.js'; + +const tripMain = document.querySelector('.trip-main'); + + +export default class HeaderPresenter { + + #pointsTrip = null; + #destinations = null; + #listPoints = []; + + constructor({destinations, pointsTrip}) { + this.#pointsTrip = pointsTrip; + this.#destinations = destinations; + } + + init() { + this.#listPoints = [...this.#pointsTrip]; + + this.#renderTripHeader(); + + } + + + /** Создание шапки сайта */ + #renderTripHeader() { + render(new SectionTripInfoView({allDestinations: this.#destinations , allPoints: this.#listPoints}), tripMain, RenderPosition.AFTERBEGIN); // Заголовок, даты, общая цена + + render(new NewEventButtonView(), tripMain); // Заголовок, кнопка добавить событие + } +} diff --git a/src/presenter/list-presenter.js b/src/presenter/list-presenter.js index 24c9832..c06086e 100644 --- a/src/presenter/list-presenter.js +++ b/src/presenter/list-presenter.js @@ -1,19 +1,20 @@ -import { render, RenderPosition, replace } from '../framework/render.js'; +import { render, replace } from '../framework/render.js'; import { MESSAGE } from '../const.js'; import { SortType } from '../const.js'; import { sortEventsByDay, sortEventsByTime, sortEventsByPrice } from '../utils/filter.js'; - -import SectionTripInfoView from '../view/section-trip-info-view.js'; -import NewEventButtonView from '../view/new-event-button-view.js'; +import { generateFilter } from '../mock/filter.js'; import SortButtonView from '../view/sort-button-view.js'; +import TripFiltersFormView from '../view/trip-filters-form-view.js'; import TripEventListView from '../view/trip-events-list-view.js'; import EventItemView from '../view/event-item-view.js'; // import AddNewPointView from '../view/add-new-point-view.js'; import EditPointView from '../view/edit-poit-view.js'; import TripEventsMessage from '../view/trip-events-message-view.js'; -const tripMain = document.querySelector('.trip-main'); +import HeaderPresenter from './header-presenter.js'; + +const tripFiltersElement = document.querySelector('.trip-controls__filters'); export default class ListPresenter { @@ -42,8 +43,57 @@ export default class ListPresenter { this.#sourcedTripPoints = [...this.#pointsTrip]; - /** Отрисовка всех компонентов */ + + this.#headerPresenter({destinations:this.#destinations, pointsTrip: this.#pointsTrip}); + + /** Рендерим кнопки сортировки */ + this.#renderSort(); + + /** Рендерим форму фильтрации */ + this.#renderFilters(); + + /** Отрисовка всех компонентов путешествия */ this.#renderList(); + + } + + #renderList() { + + /** Рендерим список для новых событий */ + render(this.#listComponent, this.#listContainer); + + if (this.#listPoints.length === 0) { + /** Если список событий пуст, то отрисовываем сообщение */ + render(new TripEventsMessage(MESSAGE.EMPTY), this.#listContainer); + + } else { + /** Если список событий не пуст, то отрисовываем события */ + + /** Рендерим редактируемое событие */ + this.#rederTripEvent(this.#listPoints[0]); + + /** Рендерим список событий */ + this.#renderAllTripEvents(); + } + + + // Переделать логику отрисовки новой точки! + // render(new AddNewPointView({pointsTrip: this.#listPoints, offers: this.#offers}), this.#listContainer); + } + + #headerPresenter({destinations, pointsTrip}) { + const headerPresenter = new HeaderPresenter({ + destinations, + pointsTrip, + }); + + return headerPresenter.init(); + } + + #renderFilters() { + const filters = generateFilter(); + + render(new TripFiltersFormView({filters}), tripFiltersElement); } /** Елемент события путешествия */ @@ -118,36 +168,6 @@ export default class ListPresenter { }); } - #renderList() { - /** Отрисовка шапки сайта */ - render(new SectionTripInfoView({allDestinations: this.#destinations , allPoints: this.#listPoints}), tripMain, RenderPosition.AFTERBEGIN); // Заголовок, даты, общая цена - render(new NewEventButtonView(), tripMain); // Заголовок, кнопка добавить событие - - /** Рендерим кнопки сортировки */ - this.#renderSort(); - - /** Рендерим список для новых событий */ - render(this.#listComponent, this.#listContainer); - - if (this.#listPoints.length === 0) { - /** Если список событий пуст, то отрисовываем сообщение */ - render(new TripEventsMessage(MESSAGE.EMPTY), this.#listContainer); - - } else { - /** Если список событий не пуст, то отрисовываем события */ - - /** Рендерим редактируемое событие */ - this.#rederTripEvent(this.#listPoints[0]); - - /** Рендерим список событий */ - this.#renderAllTripEvents(); - } - - - // Переделать логику отрисовки новой точки! - // render(new AddNewPointView({pointsTrip: this.#listPoints, offers: this.#offers}), this.#listContainer); - } - /** Отрисовка cортировки событий путешествия */ #renderSort() { this.#sortComponent = new SortButtonView({