diff --git a/package-lock.json b/package-lock.json index 442816d..c598e7a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "big-trip", "version": "22.0.0", + "dependencies": { + "dayjs": "1.11.7" + }, "devDependencies": { "@babel/core": "7.21.4", "@babel/preset-env": "7.21.4", @@ -3257,6 +3260,11 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/dayjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz", + "integrity": "sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", diff --git a/package.json b/package.json index 3e38fa0..3604b67 100644 --- a/package.json +++ b/package.json @@ -29,5 +29,8 @@ }, "engines": { "node": "20" + }, + "dependencies": { + "dayjs": "1.11.7" } } diff --git a/src/const.js b/src/const.js new file mode 100644 index 0000000..c008a71 --- /dev/null +++ b/src/const.js @@ -0,0 +1,11 @@ +export const EVENT_TYPES = ['taxi', 'bus', 'train', 'ship', 'drive', 'flight', 'check-in', 'sightseeing', 'restaurant']; + +export const getDefaultPoint = () => ({ + 'basePrice': 0, + 'dateFrom': new Date().toISOString(), + 'dateTo': new Date().toISOString(), + 'destination': '', + 'isFavorite': false, + 'offers': [], + 'type': EVENT_TYPES[0], +}); diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 0000000..f48a342 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,22 @@ +import dayjs from 'dayjs'; +import durationPlugin from 'dayjs/plugin/duration'; + +dayjs.extend(durationPlugin); + +/** Возвращает слово с заглавной буквы */ +export const capitalize = (word) => word[0].toUpperCase() + word.slice(1); + +/** Возвращает слечайный элемент массива */ +export const getRandomArrayElement = (items) => items[Math.floot(Math.randon() * items.length)]; + +export const getDate = (date) => dayjs(date).format('YYYY-MM-DD'); +export const getDateSeparatedBySlash = (date) => dayjs(date).format('YY/MM/DD'); +export const getTime = (date) => dayjs(date).format('HH:mm'); +export const getDateTime = (date) => dayjs(date).format('YYYY-MM-DDTHH:mm'); +export const getHumanDate = (date) => dayjs(date).format('MMM D'); +export const getDateDuration = (date1, date2) => { + const diff = dayjs(date2).diff(date1); + const diffDuration = dayjs.duration(diff); + return diffDuration.format('HH[H] mm[M]'); +}; + diff --git a/src/helpers/string.js b/src/helpers/string.js deleted file mode 100644 index fca6db3..0000000 --- a/src/helpers/string.js +++ /dev/null @@ -1,2 +0,0 @@ -/** Возвращает слово с заглавной буквы */ -export const capitalize = (word) => word[0].toUpperCase() + word.slice(1); diff --git a/src/main.js b/src/main.js index 98e2b87..92b7990 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,10 @@ +import PointModel from './model/point-model'; import TripPlanPresenter from './presenter/trip-plan-presenter'; -const tripPlanetPresenter = new TripPlanPresenter(); +const headerContainer = document.querySelector('.trip-controls__filters'); +const mainContainer = document.querySelector('.trip-events'); +const pointModel = new PointModel(); +pointModel.init(); -tripPlanetPresenter.init(); +const tripPlanPresenter = new TripPlanPresenter(headerContainer, mainContainer, pointModel); +tripPlanPresenter.init(); diff --git a/src/mock/destinations.js b/src/mock/destinations.js new file mode 100644 index 0000000..51e5b70 --- /dev/null +++ b/src/mock/destinations.js @@ -0,0 +1,59 @@ +export const destinations = [ + { + 'id': '1', + 'description': 'Chamonix, is a beautiful city, a true asian pearl, with crowded streets.', + 'name': 'Chamonix', + 'pictures': [ + { + 'src': 'https://loremflickr.com/248/152?random=3', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=2', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=1', + 'description': 'Chamonix parliament building' + } + ] + }, + { + 'id': '2', + 'description': 'London is the capital of Great Britain', + 'name': 'London', + 'pictures': [ + { + 'src': 'http://picsum.photos/300/200?r=0.0762563005163317', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=6', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=8', + 'description': 'Chamonix parliament building' + } + ] + }, + { + 'id': '3', + 'description': 'Saint-Petersburg is the most beautiful city in the world', + 'name': 'Saint-Petersburg', + 'pictures': [ + { + 'src': 'http://picsum.photos/300/200?r=0.0762563005163317', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=4', + 'description': 'Chamonix parliament building' + }, + { + 'src': 'https://loremflickr.com/248/152?random=9', + 'description': 'Chamonix parliament building' + } + ] + } +]; diff --git a/src/mock/offers.js b/src/mock/offers.js new file mode 100644 index 0000000..f74dfea --- /dev/null +++ b/src/mock/offers.js @@ -0,0 +1,66 @@ +export const offers = [ + { + 'type': 'taxi', + 'offers': [ + { + 'id': '1', + 'title': 'Upgrade to a business class', + 'price': 120 + }, + { + 'id': '2', + 'title': 'Add luggage', + 'price': 130 + }, + { + 'id': '3', + 'title': 'Add meal', + 'price': 170 + }, + ] + }, + { + 'type': 'bus', + 'offers': [ + { + 'id': '4', + 'title': 'Switch to comfort class', + 'price': 220 + }, + { + 'id': '5', + 'title': 'Add meal', + 'price': 420 + }, + { + 'id': '6', + 'title': 'Upgrade to a business class', + 'price': 820 + }, + ] + }, + { + 'type': 'flight', + 'offers': [ + { + 'id': '7', + 'title': 'Choose seats', + 'price': 4420 + }, + { + 'id': '8', + 'title': 'Upgrade to a business class', + 'price': 8620 + }, + { + 'id': '9', + 'title': 'Travel by train', + 'price': 20 + }, + ] + }, + { + 'type': 'train', + 'offers': [], + } +]; diff --git a/src/mock/points.js b/src/mock/points.js new file mode 100644 index 0000000..24dcfa0 --- /dev/null +++ b/src/mock/points.js @@ -0,0 +1,42 @@ +export const points = [ + { + 'id': '1', + 'basePrice': 1200, + 'dateFrom': '2019-07-10T18:15:56.845Z', + 'dateTo': '2019-07-10T18:35:56.845Z', + 'destination': '1', + 'isFavorite': true, + 'offers': [ '2' ], + 'type': 'taxi' + }, + { + 'id': '2', + 'basePrice': 1100, + 'dateFrom': '2019-06-10T21:55:56.845Z', + 'dateTo': '2019-07-11T12:22:13.375Z', + 'destination': '2', + 'isFavorite': false, + 'offers': [ '5', '6' ], + 'type': 'bus' + }, + { + 'id': '3', + 'basePrice': 1500, + 'dateFrom': '2019-07-10T07:55:56.845Z', + 'dateTo': '2019-08-11T11:19:13.375Z', + 'destination': '3', + 'isFavorite': true, + 'offers': [ '7' ], + 'type': 'flight' + }, + { + 'id': '4', + 'basePrice': 1900, + 'dateFrom': '2019-07-10T07:55:56.845Z', + 'dateTo': '2019-08-11T11:19:13.375Z', + 'destination': '2', + 'isFavorite': false, + 'offers': [], + 'type': 'train' + }, +]; diff --git a/src/model/point-model.js b/src/model/point-model.js new file mode 100644 index 0000000..8499b5b --- /dev/null +++ b/src/model/point-model.js @@ -0,0 +1,23 @@ +import { points } from '../mock/points'; +import { destinations } from '../mock/destinations'; +import { offers } from '../mock/offers'; + +export default class PointModel { + init() { + this.points = points; + this.destinations = destinations; + this.offers = offers; + } + + getPoints() { + return this.points; + } + + getDestinations() { + return this.destinations; + } + + getOffers() { + return this.offers; + } +} diff --git a/src/presenter/trip-plan-presenter.js b/src/presenter/trip-plan-presenter.js index 62bcb83..9036c14 100644 --- a/src/presenter/trip-plan-presenter.js +++ b/src/presenter/trip-plan-presenter.js @@ -1,26 +1,33 @@ -import FilterForm from '../view/filter-form'; -import SortForm from '../view/sort-form'; -import WaypointForm from '../view/waypoint-form'; -import Waypoint from '../view/waypoint'; +import FilterForm from '../view/filter'; +import SortForm from '../view/sort'; +import PointForm from '../view/point-form'; +import PointsList from '../view/points-list'; +import Point from '../view/point'; import { render } from '../render'; +import { getDefaultPoint } from '../const'; export default class TripPlanPresenter { - filterFormComponent = new FilterForm(); - sortFormComponent = new SortForm(); - waypointFormComponent = new WaypointForm(); + pointsListComponent = new PointsList(); - constructor() { - this.filterContainer = document.querySelector('.trip-controls__filters'); - this.eventsContainer = document.querySelector('.trip-events'); + constructor(headerContainer, mainContainer, pointModel) { + this.filterContainer = headerContainer; + this.eventsContainer = mainContainer; + this.pointModel = pointModel; } init() { - render(this.filterFormComponent, this.filterContainer); - render(this.sortFormComponent, this.eventsContainer); - render(this.waypointFormComponent, this.eventsContainer); + const points = this.pointModel.getPoints(); + const destinations = this.pointModel.getDestinations(); + const offers = this.pointModel.getOffers(); - for (let i = 0; i < 3; i++) { - render(new Waypoint(), this.eventsContainer); + render(new FilterForm(), this.filterContainer); + render(new SortForm(), this.eventsContainer); + render(this.pointsListComponent, this.eventsContainer); + render(new PointForm(getDefaultPoint(), destinations, offers), this.pointsListComponent.element); + render(new PointForm(points[1], destinations, offers), this.pointsListComponent.element); + + for (const point of points) { + render(new Point({ point, destinations, offers}), this.pointsListComponent.element); } } } diff --git a/src/view/filter-form.js b/src/view/filter.js similarity index 93% rename from src/view/filter-form.js rename to src/view/filter.js index 86bdf90..a501be1 100644 --- a/src/view/filter-form.js +++ b/src/view/filter.js @@ -30,7 +30,7 @@ const createFilterItemTemplate = ({label, id, initialValue}) => ` `; -const createFilterFormTemplate = () => ` +const createFilterTemplate = () => `
+`; +}; + +export default class PointForm { + constructor(point, destinations, offers) { + this.point = point; + this.destinations = destinations; + this.offers = offers; + } + + getTemplate() { + return createPointFormTemplate(this.point, this.destinations, this.offers); + } + + getElement() { + if (!this.element) { + this.element = createElement(this.getTemplate()); + } + + return this.element; + } + + removeElement() { + this.element = null; + } + +} diff --git a/src/view/point.js b/src/view/point.js new file mode 100644 index 0000000..22f5cab --- /dev/null +++ b/src/view/point.js @@ -0,0 +1,76 @@ +import { getDate, getDateTime, getHumanDate, getTime, getDateDuration } from '../helpers'; +import { capitalize } from '../helpers'; +import { createElement } from '../render'; + +const createPointTemplate = (point, destinations, offers) => { + const {basePrice, dateFrom, dateTo, isFavorite} = point; + const pointDestination = destinations.find((item) => item.id === point.destination).name; + const typeOffers = offers.find((item) => item.type === point.type).offers; + const pointOffers = typeOffers.filter((item) => point.offers.includes(item.id)); + + return `+ + — + +
+${getDateDuration(dateFrom, dateTo)}
++ € ${basePrice} +
+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.
- -- - — - -
-30M
-- € 20 -
-