diff --git a/src/const.js b/src/const.js index 5e9794f..92a97f2 100644 --- a/src/const.js +++ b/src/const.js @@ -86,6 +86,13 @@ export const EnabledSortType = { [POINT_SORTS.OFFERS]: false }; +export const EmptyListMessage = { + [FILTER_TYPES.EVERYTHING]: 'Click New Event to create your first point', + [FILTER_TYPES.FUTURE]: 'There are no future events now', + [FILTER_TYPES.PRESENT]: 'There are no present events now', + [FILTER_TYPES.PAST]: 'There are no past events now' +}; + export const POINT_EMPTY = { basePrice: 0, dateFrom: null, diff --git a/src/main.js b/src/main.js index c7ba708..2f4750b 100644 --- a/src/main.js +++ b/src/main.js @@ -23,7 +23,7 @@ const pointsModel = new PointsModel({service : service, destinationsModel : dest const filterModel = new FilterModel(); const newPointButtonPresenter = new NewPointButtonPresenter({ - container: tripEventsContainer + container: siteMainContainer }); const tripInfoPresenter = new TripInfoPresenter({ @@ -48,12 +48,10 @@ const filterPresenter = new FilterPresenter({ filterModel, }); - -newPointButtonPresenter.init({ - onButtonClick:boardPresenter.handleNewPointClick -}); - pointsModel.init(); filterPresenter.init(); boardPresenter.init(); +newPointButtonPresenter.init({ + onButtonClick:boardPresenter.handleNewPointClick +}); tripInfoPresenter.init(); diff --git a/src/mock/const.js b/src/mock/const.js deleted file mode 100644 index d41d659..0000000 --- a/src/mock/const.js +++ /dev/null @@ -1,49 +0,0 @@ -export const CITIES = [ - 'Oslo', - 'Kopenhagen', - 'Den Haag', - 'Rotterdam', - 'Sochi', - 'Moscow', - 'London', - 'Amsterdam', - 'Chamonix', - 'Geneva', - 'Saint Petersburg', - 'Paris', - 'Ekaterinburg', -]; - -export const OFFERS = [ - 'Close But No Cigar', - 'On the Same Page', - 'Jaws of Death', - 'Every Cloud Has a Silver Lining', - 'Jig Is Up', - 'In a Pickle', - 'What Goes Up Must Come Down', - 'Break The Ice', - 'In the Red', -]; - -export 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.', - 'Sed blandit, eros vel aliquam faucibus, purus ex euismod diam, eu luctus nunc ante ut dui.', - 'Sed sed nisi sed augue convallis suscipit in sed felis. Aliquam erat volutpat. Nunc fermentum tortor ac porta dapibus. In rutrum ac purus sit amet tempus.' -]; - -export const Price = { - MIN: 1, - MAX: 1000 - -}; - -export const Duration = { - DAY: 5, - HOUR: 5, - MINUTE: 59, -}; - diff --git a/src/mock/destination.js b/src/mock/destination.js deleted file mode 100644 index 0849dde..0000000 --- a/src/mock/destination.js +++ /dev/null @@ -1,19 +0,0 @@ -import {getRandomArrayElement} from './util.js'; -import {CITIES, DESCRIPTIONS} from './const.js'; - -export const getRandomDestination = () => { - const city = getRandomArrayElement(CITIES); - const description = getRandomArrayElement(DESCRIPTIONS); - - return { - id: crypto.randomUUID(), - name: city, - description: description, - pictures: [ - { - 'src': `https://loremflickr.com/248/152?random=${crypto.randomUUID()}`, - 'description' : `${city} description` - } - ] - }; -}; diff --git a/src/mock/filter.js b/src/mock/filter.js deleted file mode 100644 index a7eda9d..0000000 --- a/src/mock/filter.js +++ /dev/null @@ -1,9 +0,0 @@ -import {filter} from '../utils'; - -export const generateFilter = (points) => - Object.entries(filter).map( - ([filterName, filterPoints]) => ({ - name: filterName, - count: filterPoints(points).length, - }), - ); diff --git a/src/mock/offer.js b/src/mock/offer.js deleted file mode 100644 index 6ff10be..0000000 --- a/src/mock/offer.js +++ /dev/null @@ -1,8 +0,0 @@ -import {getRandomInteger, getRandomArrayElement} from './util.js'; -import{Price, OFFERS} from './const.js'; - -export const getRandomOffer = () => ({ - id:crypto.randomUUID(), - title: getRandomArrayElement(OFFERS), - price: getRandomInteger(Price.MIN, (Price.MAX / 10)) -}); diff --git a/src/mock/point.js b/src/mock/point.js deleted file mode 100644 index 36d4528..0000000 --- a/src/mock/point.js +++ /dev/null @@ -1,15 +0,0 @@ -import {getRandomInteger, getRandomDate} from './util.js'; -import {Price} from './const.js'; - -export const getRandomPoint = (type, destinationId, offerIds) => ({ - id: crypto.randomUUID(), - basePrice: getRandomInteger(Price.MIN, Price.MAX), - dateFrom: getRandomDate(), - dateTo: getRandomDate({ next: true }), - destination: destinationId, - isFavorite: Boolean(getRandomInteger(0, 1)), - offers: offerIds, - type -}); - - diff --git a/src/mock/util.js b/src/mock/util.js deleted file mode 100644 index 892869c..0000000 --- a/src/mock/util.js +++ /dev/null @@ -1,32 +0,0 @@ -import dayjs from 'dayjs'; -import {Duration} from './const.js'; - -export const getRandomInteger = (a = 0, b = 1) => { - const lower = Math.ceil(Math.min(a, b)); - const upper = Math.floor(Math.max(a, b)); - - return Math.floor(lower + Math.random() * (upper - lower + 1)); -}; - -export const getRandomArrayElement = (items) => items[getRandomInteger(0, items.length - 1)]; - -let date = dayjs().subtract(getRandomInteger(0, Duration.DAY), 'day').toDate(); - -export const getRandomDate = (next) => { - const minsGap = getRandomInteger(0, Duration.MINUTE); - const hoursGap = getRandomInteger(1, Duration.HOUR); - const daysGap = getRandomInteger(0, Duration.DAY); - - if (next) { - date = dayjs(date) - .add(minsGap, 'minute') - .add(hoursGap, 'hour') - .add(daysGap, 'day') - .toDate(); - } - - return date; -}; - -export const updateItem = (items, update) => items.map((item) => item.id === update.id ? update : item); - diff --git a/src/model/point-model.js b/src/model/point-model.js index feb2873..9e76b95 100644 --- a/src/model/point-model.js +++ b/src/model/point-model.js @@ -1,5 +1,5 @@ import Observable from '../framework/observable'; -import { updateItem } from '../mock/util.js'; +import { updateItem } from '../utils/common.js'; import {UpdateType} from '../const.js'; import { adaptToClient, adaptToServer } from '../utils/adapter.js'; diff --git a/src/presenter/board-presenter.js b/src/presenter/board-presenter.js index 29661e3..835b011 100644 --- a/src/presenter/board-presenter.js +++ b/src/presenter/board-presenter.js @@ -5,7 +5,7 @@ import PointPresenter from './point-presenter'; import NewPointPresenter from './new-point-presenter'; import SortPresenter from './sort-presenter'; import {remove, render, RenderPosition} from '../framework/render'; -import { filter, sort } from '../utils/utils'; +import { filter, sort } from '../utils/common.js'; import LoadingView from '../view/load-view.js'; import UiBlocker from '../framework/ui-blocker/ui-blocker.js'; import {FILTER_TYPES, POINT_SORTS, UpdateType, UserAction} from '../const.js'; @@ -70,17 +70,15 @@ export default class BoardPresenter { } #renderBoard = () =>{ - - if (this.#isLoading) { - this.#renderLoader(); - return; - } - if (this.#isError) { this.#renderError(); this.#clearBoard({ resetSortType: true }); return; } + if (this.#isLoading) { + this.#renderLoader(); + return; + } if (!this.points.length && !this.#isCreating) { this.#renderEmptyList(); @@ -181,6 +179,7 @@ export default class BoardPresenter { #clearTaskList = () => { this.#pointPresenters.forEach((presenter) => presenter.destroy()); this.#pointPresenters.clear(); + this.#newPointPresenter.destroy(); }; #handleSortChange = (sortType) => { @@ -203,8 +202,10 @@ export default class BoardPresenter { break; case UpdateType.PATCH: this.#pointPresenters.get(data.id).init(data); + this.#pointPresenters.get(data.id).resetView(); break; case UpdateType.MINOR: + this.#clearBoard(); this.#renderBoard(); break; diff --git a/src/presenter/filter-presenter.js b/src/presenter/filter-presenter.js index aff0a1f..39c6585 100644 --- a/src/presenter/filter-presenter.js +++ b/src/presenter/filter-presenter.js @@ -1,6 +1,6 @@ import { UpdateType } from '../const'; import { render, replace, remove } from '../framework/render'; -import { filter } from '../utils/utils.js'; +import { filter } from '../utils/common.js'; import FilterView from '../view/filter-view'; export default class FilterPresenter { diff --git a/src/presenter/new-point-presenter.js b/src/presenter/new-point-presenter.js index 5b9eeb2..c62ae94 100644 --- a/src/presenter/new-point-presenter.js +++ b/src/presenter/new-point-presenter.js @@ -59,8 +59,6 @@ export default class NewPointPresenter { UpdateType.MINOR, point ); - - this.destroy({ isCanceled: false }); }; setSaving = () => { @@ -70,17 +68,17 @@ export default class NewPointPresenter { }); }; - setAborting = () => { - this.#newPointElement.shake(this.#resetFormState); - }; + setAborting() { + const resetFormState = () => { + this.#newPointElement.updateElement({ + isDisabled: false, + isSaving: false, + isDeleting: false, + }); + }; - #resetFormState = () => { - this.#newPointElement.updateElement({ - isDisabled: false, - isSaving: false, - isDeleting: false, - }); - }; + this.#newPointElement.shake(resetFormState); + } #onCloseForm = () => { this.destroy(); diff --git a/src/presenter/point-presenter.js b/src/presenter/point-presenter.js index c358844..a0783ff 100644 --- a/src/presenter/point-presenter.js +++ b/src/presenter/point-presenter.js @@ -2,7 +2,7 @@ import PointEditView from '../view/point-edit-view'; import PointView from '../view/point-view'; import {render,replace,remove } from '../framework/render'; import { Mode, EditType } from '../const'; -import { isBigDifference } from '../utils/utils.js'; +import { isMinorUpdate } from '../utils/common.js'; import {UpdateType, UserAction} from '../const.js'; @@ -78,7 +78,12 @@ export default class PointPresenter { this.#replaceToForm(); }; - #onCloseEditClick = () => this.#replaceToPoint(); + #onCloseEditClick = () => { + if (!this.#editPointElement.isDisabled) { + this.#editPointElement.reset(this.#point); + this.#replaceToPoint(); + } + }; #escKeydown = (evt) => { if (evt.keyCode === 27 || evt.key === 'Escape') { @@ -101,7 +106,7 @@ export default class PointPresenter { }; setSaving = () => { - if(this.#mode === Mode.DEFAULT){ + if(this.#mode === Mode.EDITING){ this.#editPointElement.updateElement({ isDisabled: true, isSaving: true, @@ -113,6 +118,9 @@ export default class PointPresenter { if(this.#mode === Mode.DEFAULT){ this.#editPointElement.shake(); } + else { + this.#editPointElement.shake(this.#resetFormState); + } }; resetView = () =>{ @@ -129,6 +137,14 @@ export default class PointPresenter { }); }; + #resetFormState = () => { + this.#editPointElement.updateElement({ + isDisabled: false, + isSaving: false, + isDeleting: false + }); + }; + destroy = () => { remove(this.#editPointElement); remove(this.#pointElement); @@ -145,14 +161,15 @@ export default class PointPresenter { }; #formSubmitHandler = (point) => { - const isMinor = isBigDifference(point, this.#point); + const isMinor = isMinorUpdate(point, this.#point); this.#onPointsChangeHandler( UserAction.UPDATE_POINT, isMinor ? UpdateType.MINOR : UpdateType.PATCH, point ); - - this.#replaceToPoint(); + if (!this.#editPointElement._state.isDisabled) { + this.#replaceToPoint(); + } }; #onEditPointDelete = (point) =>{ diff --git a/src/service/mock-service.js b/src/service/mock-service.js deleted file mode 100644 index 30a5508..0000000 --- a/src/service/mock-service.js +++ /dev/null @@ -1,71 +0,0 @@ -import {TYPES, POINT_COUNT, DESTINATION_COUNT, OFFER_COUNT} from '../const.js'; -import {getRandomArrayElement, getRandomInteger} from '../mock/util.js'; -import{getRandomDestination} from '../mock/destination.js'; -import{getRandomOffer} from '../mock/offer.js'; -import{getRandomPoint} from '../mock/point.js'; - - -export default class MockService { - - destinations = []; - offers = []; - points = []; - - constructor() { - this.destinations = this.generateDestinations(); - this.offers = this.generateOffers(); - this.points = this.generatePoints(); - } - - getDestinations() { - return this.destinations; - } - - getOffers(){ - return this.offers; - } - - getPoints(){ - return this.points; - } - - generateDestinations() { - return Array.from({ length: DESTINATION_COUNT }, getRandomDestination); - } - - generateOffers() { - return TYPES.map((type) => ({type, - offers: Array.from({ length: OFFER_COUNT }, getRandomOffer) - })); - } - - generatePoints() { - return Array.from({length: POINT_COUNT}, () =>{ - const type = getRandomArrayElement(TYPES); - const destination = getRandomArrayElement(this.destinations); - const hasOffers = getRandomInteger(0, 1); - - const offersByType = this.offers.find((offerByType) => offerByType.type === type); - const offerIds = (hasOffers) - ? offersByType.offers - .slice(0, getRandomInteger(0, 5)) - .map((offer) => offer.id) - : []; - - return getRandomPoint(type, destination.id, offerIds); - - }); - } - - updatePoint(updatedPoint){ - return updatedPoint; - } - - addPoint(data){ - return {...data, id: crypto.randomUUID()}; - } - - deletePoint(){ - // - } -} diff --git a/src/utils/utils.js b/src/utils/common.js similarity index 93% rename from src/utils/utils.js rename to src/utils/common.js index 50aa47f..ceb60cc 100644 --- a/src/utils/utils.js +++ b/src/utils/common.js @@ -1,9 +1,11 @@ import dayjs from 'dayjs'; import duration from 'dayjs/plugin/duration'; import relativeTime from 'dayjs/plugin/relativeTime'; -import {MSEC_IN_DAY, MSEC_IN_HOUR, FILTER_TYPES, POINT_SORTS} from '../const'; +import {MSEC_IN_DAY, MSEC_IN_HOUR, FILTER_TYPES, POINT_SORTS} from '../const.js'; +export const updateItem = (items, update) => items.map((item) => item.id === update.id ? update : item); + dayjs.extend(duration); dayjs.extend(relativeTime); @@ -39,7 +41,7 @@ export const getPointDuration = (point) => { }}; -export const isBigDifference = (pointA, pointB) => +export const isMinorUpdate = (pointA, pointB) => pointA.dateFrom !== pointB.dateFrom || pointA.basePrice !== pointB.basePrice || getPointDuration(pointA.dateFrom, pointA.dateTo) !== getPointDuration(pointB.dateFrom, pointB.dateTo); diff --git a/src/utils/trip-info-utils.js b/src/utils/trip-info-utils.js index 023354d..e8c75f6 100644 --- a/src/utils/trip-info-utils.js +++ b/src/utils/trip-info-utils.js @@ -1,5 +1,5 @@ import dayjs from 'dayjs'; -import { sort } from './utils.js'; +import { sort } from './common.js'; const getOffersCost = (currentOffers, offers) => { let totalCost = 0; diff --git a/src/view/empty-view.js b/src/view/empty-view.js index ec73d63..a6f8f67 100644 --- a/src/view/empty-view.js +++ b/src/view/empty-view.js @@ -1,8 +1,8 @@ import AbstractView from '../framework/view/abstract-view'; +import { EmptyListMessage } from '../const.js'; - -function createEmptyTemplate(){ - return '
Click New Event to create your first point
'; +function createEmptyTemplate({message}){ + return `${message}
`; } export default class EmptyView extends AbstractView{ @@ -15,6 +15,6 @@ export default class EmptyView extends AbstractView{ } get template(){ - return createEmptyTemplate(); + return createEmptyTemplate({message : EmptyListMessage[this.#filterType]}); } } diff --git a/src/view/point-edit-view.js b/src/view/point-edit-view.js index cf8ba7f..987089a 100644 --- a/src/view/point-edit-view.js +++ b/src/view/point-edit-view.js @@ -1,6 +1,6 @@ import { POINT_EMPTY, TYPES,EditType, ButtonLabel } from '../const.js'; import AbstractStatefulView from '../framework/view/abstract-stateful-view.js'; -import {formatToSlashDate} from '../utils/utils.js'; +import {formatToSlashDate} from '../utils/common.js'; import CalendarView from './calendar-view.js'; import he from 'he'; @@ -77,7 +77,7 @@ function createRollupButton(){ } function createPointControls({type, isDeleting, isSaving, isDisabled}){ - return `${createSaveButton(isSaving, isDisabled)} + return `${createSaveButton({isSaving, isDisabled})} ${createDeleteButton({type, isDeleting})} ${type === EditType.CREATING ? '' : createRollupButton()}`; } @@ -140,7 +140,7 @@ function createPointEditElement({state, destinations, offers, pointType}) {${pointType === EditType.CREATING ? '' : pointDestination.description}
+${pointDestination === undefined ? '' : pointDestination.description}