diff --git a/public/index.html b/public/index.html index 44c26b4..d90e695 100644 --- a/public/index.html +++ b/public/index.html @@ -21,9 +21,6 @@

Filter events

- - -
diff --git a/src/const.js b/src/const.js index 32797ad..b886953 100644 --- a/src/const.js +++ b/src/const.js @@ -1,8 +1,11 @@ const DEFAULT_TYPE = 'taxi'; +const AUTHORIZATION = 'Basic mofy87osm1d'; +const END_POINT = 'https://21.objects.htmlacademy.pro/big-trip'; + //пустая точка const POINT_EMPTY = { - basePrice: 0, + basePrice: 1, dateFrom: null, dateTo: null, destination: null, @@ -23,37 +26,6 @@ const POINT_TYPE = [ 'Restaurant' ]; -const DESTINATION = [ - 'Ekaterinburg', - 'Moscow', - 'Tokyo', - 'Kawaguchiko', - 'Shibuya', - 'Harayuki', - 'Roppongi', - 'Kyoto', - 'Gose Palace', - 'Kinkaku-ji', - 'Hiroshima', - 'Miyajima Island', - 'Nikko Park' -]; - -const DESCRIPTION = [ - 'Nullam nunc ex, convallis sed finibus eget, sollicitudin eget ante.', - 'Phasellus eros mauris, condimentum sed nibh vitae, sodales efficitur ipsum.', - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.', - 'Aliquam erat volutpat.' -]; - -const OFFERS = [ - 'Add luggage', - 'Switch to comfort class', - 'Add meal', - 'Choose seats', - 'Travel by train', -]; - const FilterType = { EVERYTHING: 'everything', FUTURE: 'future', @@ -66,11 +38,11 @@ const Mode = { EDITING: 'EDITING', }; -const SortType = [{ +const SortType = { DAY: 'day', TIME: 'time', PRICE: 'price' -}]; +}; const UserAction = { UPDATE_POINT: 'UPDATE_POINT', @@ -105,11 +77,15 @@ const ButtonLabels = { SAVE_IN_PROGRESS: 'Saving...' }; +const TimeLimit = { + LOWER_LIMIT: 350, + UPPER_LIMIT: 1000, +}; + export {POINT_EMPTY, + AUTHORIZATION, + END_POINT, POINT_TYPE, - DESTINATION, - DESCRIPTION, - OFFERS, FilterType, Mode, SortType, @@ -117,4 +93,5 @@ export {POINT_EMPTY, EditingType, UpdateType, Method, - ButtonLabels}; + ButtonLabels, + TimeLimit}; diff --git a/src/main.js b/src/main.js index c6d8a99..4d53d0d 100644 --- a/src/main.js +++ b/src/main.js @@ -12,11 +12,8 @@ import FilterModel from './model/filter-model.js'; import PointsApiService from './api-service/points-api-service.js'; -const AUTHORIZATION = 'Basic mofy87osm1d'; -const END_POINT = 'https://21.objects.htmlacademy.pro/big-trip'; +import { AUTHORIZATION, END_POINT } from './const.js'; -//const filterHeaderElement = document.querySelector('.trip-controls'); -//const siteFilterElement = filterHeaderElement.querySelector('.trip-controls__filters'); const siteMainElement = document.querySelector('.page-main'); const tripInfoElement = document.querySelector('.trip-main'); diff --git a/src/presenter/trip-presenter.js b/src/presenter/trip-presenter.js index b2e4f3e..05290bf 100644 --- a/src/presenter/trip-presenter.js +++ b/src/presenter/trip-presenter.js @@ -3,6 +3,7 @@ import EventListEmptyView from '../view/event-list-empty-view.js'; import SortPointsView from '../view/sort-points-view.js'; import LoadingView from '../view/loading-view.js'; +import UiBlocker from '../framework/ui-blocker/ui-blocker.js'; import { remove, render, RenderPosition } from '../framework/render.js'; import PointPresenter from './point-presenter.js'; @@ -10,7 +11,7 @@ import NewPointPresenter from './new-point-presenter.js'; import { sortPointsByTime, sortPointsByPrice } from '../utils/points.js'; import { filter } from '../utils/filter.js'; -import { SortType, UserAction, UpdateType, FilterType } from '../const.js'; +import { SortType, UserAction, UpdateType, FilterType, TimeLimit } from '../const.js'; //import EditPointView from '../view/editing-form-view.js'; export default class TripPresenter { @@ -29,6 +30,11 @@ export default class TripPresenter { #filterType = FilterType.EVERYTHING; #isLoading = true; + #uiBlocker = new UiBlocker({ + lowerLimit: TimeLimit.LOWER_LIMIT, + upperLimit: TimeLimit.UPPER_LIMIT + }); + #pointPresenters = new Map(); #newPointPresenter = null; @@ -146,6 +152,8 @@ export default class TripPresenter { }; #handleViewAction = async (actionType, updateType, update) => { + this.#uiBlocker.block(); + switch(actionType) { case UserAction.UPDATE_POINT: this.#pointPresenters.get(update.id).setSaving(); @@ -172,6 +180,8 @@ export default class TripPresenter { } break; } + + this.#uiBlocker.unblock(); }; #clearBoard = ({resetSortType = false} = {}) => { diff --git a/src/template/additional-new-point-template.js b/src/template/additional-new-point-template.js deleted file mode 100644 index 33263c7..0000000 --- a/src/template/additional-new-point-template.js +++ /dev/null @@ -1,94 +0,0 @@ -import { POINT_TYPE, OFFERS } from '../const'; -import { formatFullDate } from '../utils/day'; -import { getRandomValue } from '../utils/common'; - -function createNewPointTemplate(point){ - return `
  • -
    -
    -
    - - - -
    -
    - Event type - - ${POINT_TYPE.map((type) => `
    - - -
    `).join('')} -
    -
    -
    - -
    - - - - - - - -
    - -
    - - - — - - -
    - -
    - - -
    - - - -
    -
    -
    -

    Offers

    - -
    - ${OFFERS.map((offer) => `
    - - -
    `).join('')} -
    -
    - -
    -

    Destination

    -

    Geneva is a city in Switzerland that lies at the southern tip of expansive Lac Léman (Lake Geneva). Surrounded by the Alps and Jura mountains, the city has views of dramatic Mont Blanc.

    - -
    -
    - Event photo - Event photo - Event photo - Event photo - Event photo -
    -
    -
    -
    -
    -
  • `; -} - -export {createNewPointTemplate}; diff --git a/src/template/editing-form-template.js b/src/template/editing-form-template.js index 9762045..ecdc4f5 100644 --- a/src/template/editing-form-template.js +++ b/src/template/editing-form-template.js @@ -1,29 +1,49 @@ -import { POINT_TYPE, OFFERS, ButtonLabels, EditingType } from '../const'; +import { POINT_TYPE, /* OFFERS, */ ButtonLabels, EditingType } from '../const'; import { formatFullDate } from '../utils/day'; -import { getRandomValue } from '../utils/common'; +//import { getRandomValue } from '../utils/common'; import he from 'he'; function createPointType(pointId, currentType, isDisabled) { - return POINT_TYPE.map((type) => `
    - - -
    `).join(''); + return POINT_TYPE.map((type) => + `
    + + +
    `).join(''); } -function createPointOffer() { - return OFFERS.map((offer) => `
    - - -
    `).join(''); +function createPointOffer(offers, point, isDisabled) { + return offers.map((offer) => ` +
    + + +
    `).join(''); } -function generateDestinations(destinations) { +function createPointPictures(destination) { + return ( + `
    +
    + ${destination.pictures.map((picture) => + `${picture.description}`).join('')} +
    +
    ` + ); +} + +function createDestination( destination ) { + return destination.descriptions.length && destination.pictures.length ? `
    +

    Destination

    + ${destination.description.length ? `

    ${destination.description}

    ` : ''} + ${destination.pictures.length ? createPointPictures(destination) : ''} +
    ` : ''; +} + +function createPointDestinations(destinations) { return ( `${destinations.map((destination) => ``).join('')} `); } @@ -62,77 +82,65 @@ function createControlsButtonsTemplate({ type, isSaving, isDeleting, isDisabled function createEditPointTemplate({state, pointDestinations, /* pointOffers */}) { const { point, isDisabled, isSaving, isDeleting } = state; - const { id, price, /* dateFrom, dateTo, offers, */ type } = point; - const currentDestination = pointDestinations.find((destination) => destination.id === point.destination); + const { id, price, dateFrom, dateTo, offers, type } = point; + const currentDestination = pointDestinations.find((destination) => destination.id === point.destinations); //const currentOffers = pointOffers.find((offer) => offer.type === type); const destinationName = (currentDestination) ? currentDestination.name : ''; - return `
  • -
    -
    -
    - - - -
    -
    - Event type - ${createPointType(id, type, isDisabled)} -
    -
    -
    - -
    - - - - ${generateDestinations(pointDestinations)} - -
    - -
    - - - — - - -
    - -
    - - -
    - - ${createControlsButtonsTemplate({ type, isSaving, isDeleting, isDisabled })} -
    -
    -
    -

    Offers

    - -
    - ${createPointOffer()} -
    -
    - -
    -

    Destination

    -

    Chamonix-Mont-Blanc (usually shortened to Chamonix) is a resort area near the junction of France, Switzerland and Italy. At the base of Mont Blanc, the highest summit in the Alps, it's renowned for its skiing.

    -
    -
    -
    -
  • `; + return (` +
  • +
    +
    +
    + + +
    +
    + Event type + ${createPointType(id, type, isDisabled)} +
    +
    +
    +
    + + + + ${createPointDestinations(pointDestinations)} + +
    +
    + + + — + + +
    +
    + + +
    + + ${createControlsButtonsTemplate({ type, isSaving, isDeleting, isDisabled })} +
    +
    +
    +

    Offers

    + ${createPointOffer(offers, point, isDisabled)} +
    + ${currentDestination ? `
    + ${createDestination(currentDestination)} +
    ` : ''} +
    +
    +
  • `); } export {createEditPointTemplate}; diff --git a/src/template/trip-info-template.js b/src/template/trip-info-template.js index 7f958ab..70fea33 100644 --- a/src/template/trip-info-template.js +++ b/src/template/trip-info-template.js @@ -1,13 +1,73 @@ -function createTripInfoTemplate() { +import { humanizePointDate } from '../utils/points'; +import { getStartPoint, getEndPoint } from '../utils/common'; + +function getTotalPrice(points, offers) { + if (points.length === 0) { + return ''; + } + let totalPrice = 0; + points.forEach((point) => { + + if (offers.length === 0) { + return 0; + } + + let pricePointOffers = 0; + const offersByType = offers.find((offer) => offer.type === point.type); + const pointOffers = point.offers; + + pointOffers.forEach((offer) => { + pricePointOffers += offersByType.offers.find((item) => item.id === offer).price; + }); + + totalPrice += point.basePrice; + totalPrice += pricePointOffers; + }); + + return `Total: € ${totalPrice}`; +} + +function getDates(points) { + if (points.length === 0) { + return ''; + } + + const startPoint = getStartPoint(points); + const endPoint = getEndPoint(points); + + return `

    ${humanizePointDate(startPoint.startDate, 'MMM D')} — ${humanizePointDate(endPoint.endDate, 'MMM D')}

    `; +} + +function getRouteTrip(points, destinations) { + if (points.length === 0) { + return ''; + } + const route = [points[0].destination]; + for (let i = 1; i < points.length; i++) { + if (points[i].destination !== points[i - 1].destination) { + route.push(points[i].destination); + } + } + + if (route.length > 3) { + const startPoint = destinations.find((item) => item.id === route[0]); + const endPoint = destinations.find((item) => item.id === route[route.length - 1]); + return `${startPoint.name} — ... — ${endPoint.name}`; + } + + return route.map((destination) => `${destinations.find((item) => item.id === destination).name}`).join(' — '); + +} + +function createTripInfoTemplate(points, destinations, offers) { return `
    -

    Amsterdam — Chamonix — Geneva

    - -

    Mar 18 — 20

    +

    ${getRouteTrip(points, destinations)}

    + ${getDates(points)}

    - Total: € 1230 + ${getTotalPrice(points, offers)}

    `; } diff --git a/src/utils/common.js b/src/utils/common.js index d0f578e..ac7d0a1 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -1,5 +1,39 @@ +import dayjs from 'dayjs'; + function getRandomValue(lower = 0, upper = 1000) { return Math.round((upper - lower) * Math.random() + lower); } -export { getRandomValue }; +const getStartPoint = (points) => { + let startPoint = points[0]; + for(let i = 1; i < points.length; i++) { + const currPointDate = points[i].startDate; + const currentPointDate = points[i].startDate; + const endPointDate = startPoint.startDate; + if(dayjs(currPointDate).diff(dayjs(endPointDate), 'M') < 0 + || dayjs(currPointDate).diff(dayjs(endPointDate), 'M') === 0 + && dayjs(currPointDate).diff(dayjs(endPointDate), 'D') < 0) { + if(dayjs(currentPointDate).diff(dayjs(endPointDate), 'M') < 0 + || dayjs(currentPointDate).diff(dayjs(endPointDate), 'M') === 0 + && dayjs(currentPointDate).diff(dayjs(endPointDate), 'D') < 0) { + startPoint = points[i]; + } + } + return startPoint; + } +}; + +const getEndPoint = (points) => { + const endPoint = points[0]; + for(let i = 1; i < points.length; i++) { + //const currentPointDate = points[i].endDate; + /* if(dayjs(currentPointDate).diff(dayjs(endPointDate), 'M') > 0 + || dayjs(currentPointDate).diff(dayjs(endPointDate), 'M') === 0 + && dayjs(currentPointDate).diff(dayjs(endPointDate), 'D') > 0) { + endPoint = points[i]; + } */ + } + return endPoint; +}; + +export { getRandomValue, getStartPoint, getEndPoint }; diff --git a/src/utils/points.js b/src/utils/points.js index 92f660d..525525e 100644 --- a/src/utils/points.js +++ b/src/utils/points.js @@ -23,6 +23,8 @@ function sortPointsByPrice(pointA, pointB){ } } +const humanizePointDate = (date, form) => dayjs(date).format(form); + function isDatesEqual(dateA, dateB) { return (dateA === null && dateB === null) || dayjs(dateA).isSame(dateB, 'D'); } @@ -31,4 +33,4 @@ function isPriceEqual(priceA, priceB) { return priceA === priceB; } -export {sortPointsByPrice, sortPointsByTime, sortPointsByDay, isDatesEqual, isPriceEqual}; +export {sortPointsByPrice, sortPointsByTime, sortPointsByDay, isDatesEqual, isPriceEqual, humanizePointDate}; diff --git a/src/view/additional-new-point-view.js b/src/view/additional-new-point-view.js deleted file mode 100644 index ed7515f..0000000 --- a/src/view/additional-new-point-view.js +++ /dev/null @@ -1,13 +0,0 @@ -import AbstractView from '../framework/view/abstract-view.js'; -import { createNewPointTemplate } from '../template/additional-new-point-template.js'; - -export default class NewPointView extends AbstractView { - constructor({point}) { - super(); - this.point = point; - } - - get template() { - return createNewPointTemplate(this.point); - } -} diff --git a/src/view/trip-info-view.js b/src/view/trip-info-view.js index 7b9a689..2eafded 100644 --- a/src/view/trip-info-view.js +++ b/src/view/trip-info-view.js @@ -2,7 +2,18 @@ import AbstractView from '../framework/view/abstract-view.js'; import { createTripInfoTemplate } from '../template/trip-info-template.js'; export default class TripInfoView extends AbstractView { + #destinations = null; + #offers = null; + #points = 0; + + constructor({destinations, offers, points}) { + super(); + this.#destinations = destinations; + this.#offers = offers; + this.#points = points; + } + get template() { - return createTripInfoTemplate(); + return createTripInfoTemplate(this.#points, this.#destinations, this.#offers); } }