From 1b0ab5aabc9efc6fcbe8ff7048904656edfaa84c Mon Sep 17 00:00:00 2001 From: Rudovsky Egor Date: Mon, 10 Jun 2024 02:03:04 +0500 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B0=D1=89=D0=B8=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 24 +---- src/presenter/trip-events-presenter.js | 136 ++++++++++++------------- src/presenter/trip-point-presenter.js | 46 ++++----- src/render.js | 19 ---- src/util.js | 36 ++----- src/view/editable-point-view.js | 121 +++++++++++----------- src/view/filter-view.js | 4 +- src/view/list-empty-view.js | 4 +- src/view/sort-view.js | 4 +- src/view/trip-info-view.js | 5 +- 10 files changed, 174 insertions(+), 225 deletions(-) delete mode 100644 src/render.js diff --git a/src/const.js b/src/const.js index 017ec37..0f9ec2b 100644 --- a/src/const.js +++ b/src/const.js @@ -1,13 +1,4 @@ -const POINT_TYPE = ['taxi', 'bus', 'train', 'ship', 'drive', 'flight', 'check-in', 'sightseeing', 'restaurant']; -const CITIES = ['Amsterdam', 'Geneva', 'Chamonix', 'Moscow', 'Paris']; -const DESCRIPTIONS = [ - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'Cras aliquet varius magna, non porta ligula feugiat eget.', - 'Fusce tristique felis at fermentum pharetra.', - 'Aliquam id orci ut lectus varius viverra.', - 'Nullam nunc ex, convallis sed finibus eget, sollicitudin eget ante.', - 'Phasellus eros mauris, condimentum sed nibh vitae, sodales efficitur ipsum.' -]; +const POINT_TYPES = ['taxi', 'bus', 'train', 'ship', 'drive', 'flight', 'check-in', 'sightseeing', 'restaurant']; const FilterType = { EVERYTHING: 'everything', @@ -16,7 +7,7 @@ const FilterType = { FUTUTRE: 'future' }; -const LIST_EMPTY_TEXT = { +const ListEmptyText = { [FilterType.EVERYTHING] : 'Click New Event to create your first point', [FilterType.PAST] : 'There are no past events now', [FilterType.PRESENT] : 'There are no present events now', @@ -44,16 +35,9 @@ const SortType = { OFFERS: 'offers' }; -const MIN_PRICE = 100; -const MAX_PRICE = 5000; - export { - POINT_TYPE, - CITIES, - DESCRIPTIONS, - MAX_PRICE, - MIN_PRICE, - LIST_EMPTY_TEXT, + POINT_TYPES, + ListEmptyText, UserAction, UpdateType, FilterType, diff --git a/src/presenter/trip-events-presenter.js b/src/presenter/trip-events-presenter.js index 6053389..773f247 100644 --- a/src/presenter/trip-events-presenter.js +++ b/src/presenter/trip-events-presenter.js @@ -83,90 +83,32 @@ export default class TripEventsPresenter { this.#newPointPresenter.init(); } - #handleViewAction = async (actionType, updateType, update) => { - switch (actionType) { - case UserAction.UPDATE_POINT: - this.#pointPresenters.get(update.id).setSaving(); - try { - await this.#pointsModel.updatePoint(updateType, update); - } catch(err) { - this.#pointPresenters.get(update.id).setAborting(); - } - break; - - case UserAction.ADD_POINT: - this.#newPointPresenter.setSaving(); - try { - await this.#pointsModel.addPoint(updateType, update); - } catch(err) { - this.#pointPresenters.get(update.id).setAborting(); - } - break; - - case UserAction.DELETE_POINT: - this.#pointPresenters.get(update.id).setDeleting(); - try { - await this.#pointsModel.deletePoint(updateType, update); - } catch(err) { - this.#pointPresenters.get(update.id).setAborting(); - } - break; - } - }; - - #handleModelEvent = (updateType, data) => { - switch (updateType) { - case UpdateType.PATCH: - this.#pointPresenters.get(data.id).init(data); - break; - case UpdateType.MINOR: - this.#clearBoard(); - this.#renderBoard(); - break; - case UpdateType.MAJOR: - this.#clearBoard(true); - this.#renderBoard(); - break; - case UpdateType.INIT: - this.#isLoading = false; - remove(this.#loadingComponent); - this.#clearBoard(true); - this.#renderBoard(); - break; - } - }; - #changeSortType = (type) => { this.#currentSortType = type; this.#clearBoard(); this.#renderBoard(); }; - #changeViewHandler = () => { - this.#newPointPresenter.destroy(); - this.#pointPresenters.forEach((presenter) => presenter.resetView()); - }; - - #renderSort = () => { + #renderSort() { this.#sortComponent = new SortView(this.#changeSortType, this.#currentSortType); render(this.#sortComponent, this.#tpipEventsContainer); - }; + } - #renderList = () => { + #renderList() { render(this.#listComponent, this.#tpipEventsContainer); - }; + } #renderLoading() { render(this.#loadingComponent, this.#tpipEventsContainer); } - #renderListEmpty = () => { + #renderListEmpty() { this.#listEmptyComponent = new ListEmptyView(this.#filterType); render(this.#listEmptyComponent, this.#tpipEventsContainer); remove(this.#loadingComponent); - }; + } - #renderPoints = (points) => { + #renderPoints(points) { this.#clearListEmptyText(); if (points.length === 0) { @@ -186,12 +128,12 @@ export default class TripEventsPresenter { pointPresenter.init(point); this.#pointPresenters.set(point.id, pointPresenter); } - }; + } - #renderTripInfo = () => { + #renderTripInfo() { this.#tripInfoComponent = new TripInfoView(this.#pointsModel, this.#destinationsModel, this.#offersModel); render(this.#tripInfoComponent, this.#mainContainer, RenderPosition.AFTERBEGIN); - }; + } #renderBoard() { if (this.#isLoading) { @@ -224,4 +166,62 @@ export default class TripEventsPresenter { remove(this.#listEmptyComponent); } } + + #changeViewHandler = () => { + this.#newPointPresenter.destroy(); + this.#pointPresenters.forEach((presenter) => presenter.resetView()); + }; + + #handleViewAction = async (actionType, updateType, update) => { + switch (actionType) { + case UserAction.UPDATE_POINT: + this.#pointPresenters.get(update.id).setSaving(); + try { + await this.#pointsModel.updatePoint(updateType, update); + } catch(err) { + this.#pointPresenters.get(update.id).setAborting(); + } + break; + + case UserAction.ADD_POINT: + this.#newPointPresenter.setSaving(); + try { + await this.#pointsModel.addPoint(updateType, update); + } catch(err) { + this.#pointPresenters.get(update.id).setAborting(); + } + break; + + case UserAction.DELETE_POINT: + this.#pointPresenters.get(update.id).setDeleting(); + try { + await this.#pointsModel.deletePoint(updateType, update); + } catch(err) { + this.#pointPresenters.get(update.id).setAborting(); + } + break; + } + }; + + #handleModelEvent = (updateType, data) => { + switch (updateType) { + case UpdateType.PATCH: + this.#pointPresenters.get(data.id).init(data); + break; + case UpdateType.MINOR: + this.#clearBoard(); + this.#renderBoard(); + break; + case UpdateType.MAJOR: + this.#clearBoard(true); + this.#renderBoard(); + break; + case UpdateType.INIT: + this.#isLoading = false; + remove(this.#loadingComponent); + this.#clearBoard(true); + this.#renderBoard(); + break; + } + }; } diff --git a/src/presenter/trip-point-presenter.js b/src/presenter/trip-point-presenter.js index 208c55e..9d4cd4f 100644 --- a/src/presenter/trip-point-presenter.js +++ b/src/presenter/trip-point-presenter.js @@ -70,36 +70,17 @@ export default class TripPointPresenter { } } - #favoriteButtonClickHandler = () => { - this.#onDataChange( - UserAction.UPDATE_POINT, - UpdateType.MINOR, - {...this.#point, isFavorite: !this.#point.isFavorite} - ); - }; - - #replacePointToForm() { - this.#onViewChange(); - replace(this.#editPointComponent, this.#pointComponent); - this.#view = VIEW.EDIT; - } - - #replaceFormToPoint() { - replace(this.#pointComponent, this.#editPointComponent); - this.#view = VIEW.DEFAULT; - } - - resetView = () => { + resetView() { if (this.#view === VIEW.EDIT){ this.#editPointComponent.reset(this.#point, this.#destination, this.#offer); this.#replaceFormToPoint(); } - }; + } - remove = () => { + remove() { remove(this.#pointComponent); remove(this.#editPointComponent); - }; + } setSaving() { if (this.#view === VIEW.EDIT) { @@ -136,6 +117,17 @@ export default class TripPointPresenter { this.#editPointComponent.shake(resetFormState); } + #replacePointToForm() { + this.#onViewChange(); + replace(this.#editPointComponent, this.#pointComponent); + this.#view = VIEW.EDIT; + } + + #replaceFormToPoint() { + replace(this.#pointComponent, this.#editPointComponent); + this.#view = VIEW.DEFAULT; + } + #pointRollupButtonClikHandler = () => { this.#replacePointToForm(); document.addEventListener('keydown', this.#onFormKeydown); @@ -173,4 +165,12 @@ export default class TripPointPresenter { this.#replaceFormToPoint(); } }; + + #favoriteButtonClickHandler = () => { + this.#onDataChange( + UserAction.UPDATE_POINT, + UpdateType.MINOR, + {...this.#point, isFavorite: !this.#point.isFavorite} + ); + }; } diff --git a/src/render.js b/src/render.js deleted file mode 100644 index 8c22c92..0000000 --- a/src/render.js +++ /dev/null @@ -1,19 +0,0 @@ -const RenderPosition = { - BEFOREBEGIN: 'beforebegin', - AFTERBEGIN: 'afterbegin', - BEFOREEND: 'beforeend', - AFTEREND: 'afterend', -}; - -function createElement(template) { - const newElement = document.createElement('div'); - newElement.innerHTML = template; - - return newElement.firstElementChild; -} - -function render(component, container, place = RenderPosition.BEFOREEND) { - container.insertAdjacentElement(place, component.getElement()); -} - -export {RenderPosition, createElement, render}; diff --git a/src/util.js b/src/util.js index 25d1c34..111d55d 100644 --- a/src/util.js +++ b/src/util.js @@ -6,29 +6,17 @@ function formatEventDate(dueDate, dateFormat) { } function formatEventDuration(diff) { - const hours = Math.floor(diff / 60); + const days = Math.floor(diff / 1440); + const hours = Math.floor((diff % 1440) / 60); const minutes = diff % 60; - return hours === 0 ? `${minutes}M` : `${hours}H ${minutes}M`; -} - -function createId() { - let lastGeneratedId = 0; - return function () { - lastGeneratedId += 1; - return lastGeneratedId; - }; -} - -function updateItem(items, update) { - return items.map((item) => item.id === update.id ? update : item); -} - -function getRandomInteger(a, b) { - const lower = Math.ceil(Math.min(a, b)); - const upper = Math.floor(Math.max(a, b)); - const result = Math.random() * (upper - lower + 1) + lower; - return Math.floor(result); + if (days > 0) { + return `${days}D ${hours}H ${minutes}M`; + } else if (hours > 0) { + return `${hours}H ${minutes}M`; + } else { + return `${minutes}M`; + } } function calculateDateDifference(start, end) { @@ -40,8 +28,6 @@ function calculateDateDifference(start, end) { const isElementHas = (element) => element !== null && element !== undefined && element.length > 0; -const getRandomArrayElement = (arr) => arr[getRandomInteger(0, arr.length - 1)]; - const isEscapeKey = (evt) => evt.key === 'Escape'; const filter = { @@ -52,14 +38,10 @@ const filter = { }; export { - createId, - getRandomInteger, - getRandomArrayElement, formatEventDate, isElementHas, isEscapeKey, calculateDateDifference, formatEventDuration, - updateItem, filter }; diff --git a/src/view/editable-point-view.js b/src/view/editable-point-view.js index f3f0a09..ae8fe16 100644 --- a/src/view/editable-point-view.js +++ b/src/view/editable-point-view.js @@ -1,4 +1,4 @@ -import { POINT_TYPE } from '../const.js'; +import { POINT_TYPES } from '../const.js'; import { formatEventDate, isElementHas } from '../util.js'; import AbstractStatefulView from '../framework/view/abstract-stateful-view.js'; import flatpickr from 'flatpickr'; @@ -107,7 +107,7 @@ function createDestinationPhotosList(pictures) { } function createEventTypeList(type, isDisabled) { - const eventTypeList = POINT_TYPE.map((pointType) => `
+ const eventTypeList = POINT_TYPES.map((pointType) => `
`); @@ -212,48 +212,25 @@ export default class EditablePointView extends AbstractStatefulView { this.#setDatepicker(); } - static parsePointToState(point, destination, offer) { - return{ - point, - offer, - destination, - type: point.type, - basePrice: point.basePrice, - name: destination?.name, - dateFrom: point.dateFrom, - dateTo: point.dateTo, - checkedOffers: point.offers, - isOffers: isElementHas(offer?.offers), - isDestination: isElementHas(destination?.description), - isPictures: isElementHas(destination?.pictures), - isDisabled: false, - isSaving: false, - isDeleting: false, - }; - } - - static parseStateToPoint(state) { - const point = state.point; - point.destination = state.destination.id; - point.type = state.type; - point.offers = state.checkedOffers; - point.dateFrom = state.dateFrom; - point.dateTo = state.dateTo; - point.basePrice = Number(state.basePrice); - - return point; - } - - static parseStateToOffer(state) { - const offer = state.offer; - - return offer; - } - - static parseStateToDestination(state) { - const destination = state.destination; + #setDatepicker() { + this.#fromDatepicker = flatpickr( + this.element.querySelector('#event-start-time-1'), + { + dateFormat: 'j F, H:i', + defaultDate: new Date(this._state.dateFrom), + onChange: this.#dateFromChangeHandler + }, + ); - return destination; + this.#toDatepicker = flatpickr( + this.element.querySelector('#event-end-time-1'), + { + dateFormat: 'j F, H:i', + defaultDate: new Date(this._state.dateTo), + minDate: this.#fromDatepicker.selectedDates[0], + onChange: this.#dateToChangeHandler + }, + ); } #deleteButtonClickHandler = (evt) => { @@ -334,24 +311,48 @@ export default class EditablePointView extends AbstractStatefulView { }); }; - #setDatepicker() { - this.#fromDatepicker = flatpickr( - this.element.querySelector('#event-start-time-1'), - { - dateFormat: 'j F', - defaultDate: new Date(this._state.dateFrom), - onChange: this.#dateFromChangeHandler - }, - ); + static parsePointToState(point, destination, offer) { + return{ + point, + offer, + destination, + type: point.type, + basePrice: point.basePrice, + name: destination?.name, + dateFrom: point.dateFrom, + dateTo: point.dateTo, + checkedOffers: point.offers, + isOffers: isElementHas(offer?.offers), + isDestination: isElementHas(destination?.description), + isPictures: isElementHas(destination?.pictures), + isDisabled: false, + isSaving: false, + isDeleting: false, + }; + } - this.#toDatepicker = flatpickr( - this.element.querySelector('#event-end-time-1'), - { - dateFormat: 'j F', - defaultDate: new Date(this._state.dateTo), - onChange: this.#dateToChangeHandler - }, - ); + static parseStateToPoint(state) { + const point = state.point; + point.destination = state.destination.id; + point.type = state.type; + point.offers = state.checkedOffers; + point.dateFrom = state.dateFrom; + point.dateTo = state.dateTo; + point.basePrice = Number(state.basePrice); + + return point; + } + + static parseStateToOffer(state) { + const offer = state.offer; + + return offer; + } + + static parseStateToDestination(state) { + const destination = state.destination; + + return destination; } } diff --git a/src/view/filter-view.js b/src/view/filter-view.js index 7fafd22..60948ae 100644 --- a/src/view/filter-view.js +++ b/src/view/filter-view.js @@ -43,14 +43,14 @@ export default class FilterView extends AbstractView { this.#currentFilter = currentFilter; this.#onFilterClick = onFilterTypeChange; - this.element.addEventListener('change', this.#changeFilterType); + this.element.addEventListener('change', this.#changeFilterTypeHandler); } get template() { return createFilterTemplate(this.#filters, this.#currentFilter); } - #changeFilterType = (evt) => { + #changeFilterTypeHandler = (evt) => { evt.preventDefault(); this.#onFilterClick(evt.target.value); }; diff --git a/src/view/list-empty-view.js b/src/view/list-empty-view.js index 956dff0..8f1fb9c 100644 --- a/src/view/list-empty-view.js +++ b/src/view/list-empty-view.js @@ -1,8 +1,8 @@ import AbstractView from '../framework/view/abstract-view.js'; -import { LIST_EMPTY_TEXT } from '../const.js'; +import { ListEmptyText } from '../const.js'; function createListEmptyTemplate(filterType) { - const text = LIST_EMPTY_TEXT[filterType]; + const text = ListEmptyText[filterType]; return `

${text}

`; } diff --git a/src/view/sort-view.js b/src/view/sort-view.js index 2c8c279..c051c7c 100644 --- a/src/view/sort-view.js +++ b/src/view/sort-view.js @@ -40,14 +40,14 @@ export default class SortView extends AbstractView { this.#onSortClick = onSortClick; this.#currentSortType = currentSortType; - this.element.addEventListener('change', this.#changeSortType); + this.element.addEventListener('change', this.#changeSortTypeHandler); } get template() { return createSortTemplate(this.#currentSortType); } - #changeSortType = (evt) => { + #changeSortTypeHandler = (evt) => { evt.preventDefault(); this.#onSortClick(evt.target.dataset.name); }; diff --git a/src/view/trip-info-view.js b/src/view/trip-info-view.js index 854e521..40fe1b5 100644 --- a/src/view/trip-info-view.js +++ b/src/view/trip-info-view.js @@ -1,6 +1,8 @@ import AbstractView from '../framework/view/abstract-view.js'; import { formatEventDate } from '../util.js'; +const DATE_FORMAT = 'MMM D'; + function createTripInfoTemplate(pointsModel, destinationsModel, offersModel) { const points = pointsModel.points.sort((a, b) => new Date(a.dateFrom) - new Date(b.dateFrom)); @@ -47,8 +49,7 @@ function getDates(points) { const firstPoint = points[0]; const lastPoint = points[pointsCount - 1]; - const dateFormat = 'MMM D'; - return `${formatEventDate(firstPoint.dateFrom, dateFormat)} — ${formatEventDate(lastPoint.dateTo, dateFormat)}`; + return `${formatEventDate(firstPoint.dateFrom, DATE_FORMAT)} — ${formatEventDate(lastPoint.dateTo, DATE_FORMAT)}`; } function getCost(points, offersModel) {