From 439b00e3eea223f4dfb1f6ff5f51cc589c8aef01 Mon Sep 17 00:00:00 2001 From: Vitaly Lipko Date: Wed, 18 Dec 2024 22:05:08 +0700 Subject: [PATCH] add mocks and remove static data --- package-lock.json | 8 +++ package.json | 5 +- src/main.js | 4 +- src/mock/event.js | 120 +++++++++++++++++++++++++++++++++++++ src/model/events-model.js | 15 +++++ src/presenter/presenter.js | 14 ++++- src/utils/utils.js | 56 +++++++++++++++++ src/view/edit-form.js | 117 ++++++++++++++++-------------------- src/view/event-item.js | 65 +++++++++++++++----- 9 files changed, 319 insertions(+), 85 deletions(-) create mode 100644 src/mock/event.js create mode 100644 src/model/events-model.js create mode 100644 src/utils/utils.js diff --git a/package-lock.json b/package-lock.json index 7a34538..162c06a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "big-trip", "version": "20.0.0", + "dependencies": { + "dayjs": "1.11.7" + }, "devDependencies": { "@babel/core": "7.21.4", "@babel/preset-env": "7.21.4", @@ -3195,6 +3198,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 5d843c1..b1354d1 100644 --- a/package.json +++ b/package.json @@ -29,5 +29,8 @@ "not ie <= 11", "not op_mini all", "not < 0.25%" - ] + ], + "dependencies": { + "dayjs": "1.11.7" + } } diff --git a/src/main.js b/src/main.js index a1c2b6b..49050e6 100644 --- a/src/main.js +++ b/src/main.js @@ -1,5 +1,7 @@ import Presenter from './presenter/presenter'; +import EventsModel from './model/events-model'; -const presenter = new Presenter(); +const eventsModel = new EventsModel(); +const presenter = new Presenter({eventsModel}); presenter.init(); diff --git a/src/mock/event.js b/src/mock/event.js new file mode 100644 index 0000000..2a27efb --- /dev/null +++ b/src/mock/event.js @@ -0,0 +1,120 @@ +const mockEvents = [ + { + 'id': '1', + 'base_price': 20, + 'date_from': new Date('December 20, 2024 03:24:00'), + 'date_to': new Date('December 20, 2024 03:54:00'), + 'destination': 'amst', + 'is_favorite': true, + 'offers': [ + 'uber' + ], + 'type': 'taxi' + }, + { + 'id': '2', + 'base_price': 1200, + 'date_from': new Date('December 20, 2024 10:24:00'), + 'date_to': new Date('December 21, 2024 06:24:00'), + 'destination': 'amst', + 'is_favorite': true, + 'offers': [ + 'luggage', + 'comfort' + ], + 'type': 'ship' + }, + { + 'id': '3', + 'base_price': 1200, + 'date_from': new Date('December 22, 2024 10:24:00'), + 'date_to': new Date('December 23, 2024 20:24:00'), + 'destination': 'gnv', + 'is_favorite': false, + 'offers': [ + 'rent' + ], + 'type': 'drive' + } +]; + +const mockDestinations = [ + { + 'id': 'chm', + 'description': 'Chamonix, is a beautiful city, a true asian pearl, with crowded streets.', + 'name': 'Chamonix', + 'pictures': [ + { + 'src': 'https://loremflickr.com/248/152?random=7', + 'description': 'Chamonix parliament building' + } + ] + }, + { + 'id': 'amst', + 'description': '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.', + 'name': 'Amsterdam', + 'pictures': [ + { + 'src': 'https://loremflickr.com/248/152?random=1', + 'description': '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.' + } + ] + }, + { + 'id': 'gnv', + 'description': 'Aliquam erat volutpat. Nunc fermentum tortor ac porta dapibus. In rutrum ac purus sit amet tempus.', + 'name': 'Geneva', + 'pictures': [ + { + 'src': 'https://loremflickr.com/248/152?random=8', + 'description': 'Aliquam erat volutpat. Nunc fermentum tortor ac porta dapibus. In rutrum ac purus sit amet tempus.' + } + ] + } +]; + +const mockOffers = [ + { + 'type': 'taxi', + 'offers': [ + { + 'id': 'uber', + 'title': 'Order Uber', + 'price': 20 + }, + { + 'id': 'childSeat', + 'title': 'Add child seat', + 'price': 5 + } + ] + }, + { + 'type': 'ship', + 'offers': [ + { + 'id': 'luggage', + 'title': 'Add luggage', + 'price': 50 + }, + { + 'id': 'comfort', + 'title': 'Switch to comfort', + 'price': 80 + } + ] + }, + { + 'type': 'drive', + 'offers': [ + { + 'id': 'rent', + 'title': 'Rent a car', + 'price': 200 + } + ] + }, +]; + +export {mockEvents, mockDestinations, mockOffers}; diff --git a/src/model/events-model.js b/src/model/events-model.js new file mode 100644 index 0000000..4c99018 --- /dev/null +++ b/src/model/events-model.js @@ -0,0 +1,15 @@ +import {mockDestinations, mockEvents, mockOffers} from '../mock/event'; + +export default class EventsModel { + getEvents() { + return [...mockEvents]; + } + + getDestinations() { + return [...mockDestinations]; + } + + getOffers() { + return [...mockOffers]; + } +} diff --git a/src/presenter/presenter.js b/src/presenter/presenter.js index 13ed6b7..148f792 100644 --- a/src/presenter/presenter.js +++ b/src/presenter/presenter.js @@ -10,14 +10,22 @@ export default class Presenter { eventsContainer = document.querySelector('.trip-events'); filterContainer = document.querySelector('.trip-controls__filters'); + constructor({eventsModel}) { + this.eventsModel = eventsModel; + } + init() { + this.events = this.eventsModel.getEvents(); + this.destinations = this.eventsModel.getDestinations(); + this.offers = this.eventsModel.getOffers(); + render(new Filters(), this.filterContainer); render(new Sorting(), this.eventsContainer); render(this.eventListComponent, this.eventsContainer); - render(new EditForm(), this.eventListComponent.getElement()); + render(new EditForm({event:this.events[0], destinations: this.destinations, offers: this.offers}), this.eventListComponent.getElement()); - for (let i = 0; i < 3; i++) { - render(new EventItem(), this.eventListComponent.getElement()); + for (let i = 1; i < this.events.length; i++) { + render(new EventItem({event:this.events[i], destinations: this.destinations, offers: this.offers}), this.eventListComponent.getElement()); } } } diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..901ba22 --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,56 @@ +import dayjs from 'dayjs'; + +function formatDate(date, format) { + return dayjs(date).format(format); +} + +function formatToDisplayString(value) { + return`${value}`.padStart(2, '0'); +} + +function getDuration(dateFrom, dateTo) { + const from = dayjs(dateFrom); + const to = dayjs(dateTo); + const minutes = to.diff(from, 'minute'); + const days = Math.floor(minutes / (24 * 60)); + const remainingMinutes = minutes % (24 * 60); + + const hours = Math.floor(remainingMinutes / 60); + const finalMinutes = remainingMinutes % 60; + + const result = []; + + if (days > 0) { + result.push(`${formatToDisplayString(days)}D`); + } + if (hours > 0) { + result.push(`${formatToDisplayString(hours)}H`); + } + if (finalMinutes > 0) { + result.push(`${formatToDisplayString(finalMinutes)}M`); + } + + return result.join(' '); +} + +function getEvent(type, destination) { + return `${type } ${ destination}`; +} + +function getDestination(id, destinations) { + return destinations.find((d) => d.id === id); +} + +function getEventIconUrl(type) { + return `img/icons/${type}.png`; +} + +function getTypeOffers(type, offers) { + return offers.find((d) => d.type === type)?.offers; +} + +function getOffer(id, offers) { + return offers?.find((d) => d.id === id); +} + +export {formatDate, getDuration, getEvent, getDestination, getEventIconUrl, getTypeOffers, getOffer}; diff --git a/src/view/edit-form.js b/src/view/edit-form.js index c5742da..8b7768f 100644 --- a/src/view/edit-form.js +++ b/src/view/edit-form.js @@ -1,6 +1,32 @@ import {createElement} from '../render'; +import {formatDate, getDestination, getEventIconUrl, getTypeOffers} from '../utils/utils'; + + +function getOfferTemplate(offer, eventOffers) { + const {title, price, id} = offer; + const isChecked = eventOffers.includes(id); + + return ` +
+ + +
+ `; +} + +function getEditFormTemplate(event, destinations, offers) { + const {date_from, date_to, type: eventType, destination: eventDestination, base_price, offers: eventOffers} = event; + const destination = getDestination(eventDestination, destinations); + const eventIconUrl = getEventIconUrl(eventType); + const startTime = formatDate(date_from, 'DD/MM/YY HH:MM'); + const endTime = formatDate(date_to, 'DD/MM/YY HH:MM'); + const typeOffers = getTypeOffers(eventType, offers) || []; + const isEventTypeChecked = (type) => type === eventType ? 'checked' : ''; -function getEditFormTemplate() { return `
  • @@ -8,7 +34,7 @@ function getEditFormTemplate() {
    @@ -17,47 +43,47 @@ function getEditFormTemplate() { Event type
    - +
    - +
    - +
    - +
    - +
    - +
    - +
    - +
    - +
    @@ -66,22 +92,20 @@ function getEditFormTemplate() {
    - + - - - + ${destinations.map((d) => ``).join('')}
    - + - +
    @@ -89,7 +113,7 @@ function getEditFormTemplate() { Price € - +
    @@ -103,56 +127,13 @@ function getEditFormTemplate() {

    Offers

    -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    - -
    - - -
    + ${typeOffers.map((offer) => getOfferTemplate(offer, eventOffers)).join('')}

    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.

    +

    ${destination.description}

    @@ -161,8 +142,14 @@ function getEditFormTemplate() { } export default class EditForm { + constructor({event, destinations, offers}) { + this.event = event; + this.destinations = destinations; + this.offers = offers; + } + getTemplate() { - return getEditFormTemplate(); + return getEditFormTemplate(this.event, this.destinations, this.offers); } getElement() { diff --git a/src/view/event-item.js b/src/view/event-item.js index 280b0c4..811cc7b 100644 --- a/src/view/event-item.js +++ b/src/view/event-item.js @@ -1,34 +1,63 @@ import {createElement} from '../render'; +import { + formatDate, + getDuration, + getDestination, + getEvent, + getEventIconUrl, + getOffer, + getTypeOffers +} from '../utils/utils'; + +function getOfferTemplate(id, type, offers){ + const typeOffers = getTypeOffers(type, offers) || []; + const {title, price} = getOffer(id, typeOffers) || {}; + + return ` +
  • + ${title} + +€  + ${price} +
  • + `; +} + +function getEventItemTemplate(event, destinations, offers) { + const {date_from, date_to, type, destination: eventDestionation, base_price, is_favorite, offers: eventOffers} = event; + const startDay = formatDate(date_from, 'MMM D'); + const startDayValue = formatDate(date_from, 'YYYY-MM-DD'); + const duration = getDuration(date_from, date_to); + const destination = getDestination(eventDestionation, destinations); + const eventTitle = getEvent(type, destination?.name); + const eventIconUrl = getEventIconUrl(type); + const startTime = formatDate(date_from, 'HH:MM'); + const endTime = formatDate(date_to, 'HH:MM'); + const favoriteClass = is_favorite ? 'event__favorite-btn--active' : ''; -function getEventItemTemplate() { return `
  • - +
    - Event type icon + Event type icon
    -

    Taxi Amsterdam

    +

    ${eventTitle}

    - + — - +

    -

    30M

    +

    ${duration}

    - € 20 + € ${base_price}

    Offers:

      -
    • - Order Uber - +€  - 20 -
    • + ${eventOffers.map((id) => getOfferTemplate(id, type, offers)).join('')}
    -