diff --git a/src/constants.js b/src/constants.js index dbad70e..4014520 100644 --- a/src/constants.js +++ b/src/constants.js @@ -36,24 +36,12 @@ export const EVENT_TYPES = [ export const DEFAULT_EVENT_TYPE = 'train'; -export const FILTER_TYPES = [ - { - type: 'everything', - checked: true, - }, - { - type: 'future', - checked: false, - }, - { - type: 'present', - checked: false, - }, - { - type: 'past', - checked: false, - }, -]; +export const FilterType = { + EVERYTHING: 'everything', + PAST: 'past', + PRESENT: 'present', + FUTURE: 'future' +}; export const TRIP_SORT_ITEMS = [ { @@ -91,3 +79,15 @@ export const DATE_TIME_FORMAT = { H_M_DURATION: 'HH[H] mm[M]', M_DURATION: 'mm[M]' }; + +export const EVENTS_MESSAGE = { + EMPTY: 'Click New Event to create your first point', + LOADING: 'Loading...' +}; + +export const FilterMessage = { + [FilterType.EVERYTHING]: 'Click New Event to create your first point', + [FilterType.FUTURE]: 'There are no future events now', + [FilterType.PRESENT]: 'There are no present events now', + [FilterType.PAST]: 'There are no past events now' +}; diff --git a/src/main.js b/src/main.js index a4d0f32..3483094 100644 --- a/src/main.js +++ b/src/main.js @@ -4,7 +4,9 @@ import PointModel from './model/point-model.js'; const tripMainElement = document.querySelector('.trip-main'); const tripEventsElement = document.querySelector('.trip-events'); const filtersElement = document.querySelector('.trip-controls__filters'); + const pointModel = new PointModel(); +pointModel.init(); const presenter = new Presenter({ infoContainer: tripMainElement, @@ -13,5 +15,4 @@ const presenter = new Presenter({ pointModel: pointModel }); -pointModel.init(); presenter.init(); diff --git a/src/mocks/destinations.js b/src/mocks/destinations.js index 2134d91..312edde 100644 --- a/src/mocks/destinations.js +++ b/src/mocks/destinations.js @@ -1,4 +1,4 @@ -import { getRandomInteger, getRandomArrayElement } from '../utils.js'; +import { getRandomInteger, getRandomArrayElement } from '../util/utils.js'; import { CITIES, CITY_DESCRIPTIONS } from '../constants.js'; export const destinations = [ diff --git a/src/mocks/filters.js b/src/mocks/filters.js new file mode 100644 index 0000000..078de5d --- /dev/null +++ b/src/mocks/filters.js @@ -0,0 +1,16 @@ +import { FilterType } from '../constants.js'; +import { isDatePast, isDatePresent, isDateFuture } from '../util/utils.js'; + +const filter = { + [FilterType.EVERYTHING]: (points) => points, + [FilterType.FUTURE]: (points) => points.filter((point) => isDateFuture(point.dateFrom)), + [FilterType.PRESENT]: (points) => points.filter((point) => isDatePresent(point.dateFrom, point.dateTo)), + [FilterType.PAST]: (points) => points.filter((point) => isDatePast(point.dateTo)) +}; + +export function generateFilter(points) { + return Object.entries(filter).map(([filterType, filterPoints]) => ({ + type: filterType, + count: filterPoints(points).length, + })); +} diff --git a/src/mocks/offers.js b/src/mocks/offers.js index 6fb0e62..0f0ca53 100644 --- a/src/mocks/offers.js +++ b/src/mocks/offers.js @@ -1,4 +1,4 @@ -import { getRandomInteger } from '../utils.js'; +import { getRandomInteger } from '../util/utils.js'; export const offers = [ { diff --git a/src/mocks/points.js b/src/mocks/points.js index 5122e04..495c023 100644 --- a/src/mocks/points.js +++ b/src/mocks/points.js @@ -1,12 +1,12 @@ -import { getRandomInteger } from '../utils.js'; +import { getRandomInteger } from '../util/utils.js'; import { PRICE } from '../constants'; export const points = [ { id: 1, basePrice: `${getRandomInteger(PRICE.MIN, PRICE.MAX)}`, - dateFrom: '2023-05-09T22:55:56.845Z', - dateTo: '2023-05-15T11:22:13.375Z', + dateFrom: '2024-09-09T22:55:56.845Z', + dateTo: '2024-09-29T11:22:13.375Z', destination: 'cfe416cq-10xa-ye10-8077-2fs9a01e73ab', isFavorite: false, offers: [ @@ -30,8 +30,8 @@ export const points = [ { id: 3, basePrice: `${getRandomInteger(PRICE.MIN, PRICE.MAX)}`, - dateFrom: '2023-08-22T04:10:01.845Z', - dateTo: '2023-08-22T07:22:13.845Z', + dateFrom: '2025-08-22T04:10:01.845Z', + dateTo: '2025-08-22T07:22:13.845Z', destination: 'f4b62099-29rf-4cud-ate2-u457c4a2998r', isFavorite: true, offers: [], diff --git a/src/presenter/presenter.js b/src/presenter/presenter.js index 23f35d2..c1e0ca2 100644 --- a/src/presenter/presenter.js +++ b/src/presenter/presenter.js @@ -6,10 +6,12 @@ import EventEditorView from '../view/event-editor-view.js'; import FiltersView from '../view/filters-view.js'; import SortView from '../view/sort-view.js'; import EventAddButtonView from '../view/event-add-button-view.js'; +import { EVENTS_MESSAGE } from '../constants'; +import EventsMessageView from '../view/events-message-view.js'; +import {generateFilter} from '../mocks/filters'; export default class Presenter { #tripInfoComponent = new TripInfoView(); - #filtersComponent = new FiltersView(); #addButtonComponent = new EventAddButtonView(); #sortComponent = new SortView(); #listComponent = new EventsListView(); @@ -26,13 +28,18 @@ export default class Presenter { const points = this.#pointModel.points; const destinations = this.#pointModel.destinations; const offers = this.#pointModel.offers; + const filters = generateFilter(points); render(this.#tripInfoComponent, this.infoContainer, RenderPosition.AFTERBEGIN); - render(this.#filtersComponent, this.filtersContainer); + render(new FiltersView({filters}), this.filtersContainer); render(this.#addButtonComponent, this.infoContainer); render(this.#sortComponent, this.contentContainer); render(this.#listComponent, this.contentContainer); + if (points.length === 0) { + render(new EventsMessageView(EVENTS_MESSAGE.EMPTY), this.infoContainer); + } + points.forEach((point) => this.#renderPoint(point, destinations, offers)); } diff --git a/src/utils.js b/src/util/utils.js similarity index 75% rename from src/utils.js rename to src/util/utils.js index 38f5d33..8096611 100644 --- a/src/utils.js +++ b/src/util/utils.js @@ -1,6 +1,6 @@ import dayjs from 'dayjs'; import duration from 'dayjs/plugin/duration'; -import { DATE_TIME_FORMAT, DEFAULT_EVENT_TYPE } from './constants.js'; +import { DATE_TIME_FORMAT } from '../constants.js'; export const getRandomInteger = (min = 1, max = 100) => Math.round(Math.random() * Math.abs(max - min)) + min; @@ -24,14 +24,12 @@ export const convertDuration = (value) => { return value.format(DATE_TIME_FORMAT.M_DURATION); }; +export const isDateFuture = (start) => dayjs().isBefore(start); + +export const isDatePresent = (start, end) => dayjs().isAfter(start) && dayjs().isBefore(end); + +export const isDatePast = (end) => dayjs().isAfter(end); + export const getCapitalized = (word) => `${word[0].toUpperCase()}${word.slice(1)}`; -export const getDefaultPoint = () => ({ - basePrice: 0, - dateFrom: new Date().toISOString(), - dateTo: new Date().toISOString(), - destination: 0, - isFavorite: false, - offers: [], - type: DEFAULT_EVENT_TYPE -}); + diff --git a/src/view/event-editor-view.js b/src/view/event-editor-view.js index a137af9..50aa3a8 100644 --- a/src/view/event-editor-view.js +++ b/src/view/event-editor-view.js @@ -1,5 +1,5 @@ import AbstractView from '../framework/view/abstract-view.js'; -import { convertDate, getCapitalized } from '../utils.js'; +import { convertDate, getCapitalized } from '../util/utils.js'; import { DATE_TIME_FORMAT, EVENT_TYPES } from '../constants.js'; const createEventTypeItemTemplate = (type) => ` diff --git a/src/view/events-item-view.js b/src/view/events-item-view.js index 1a72bae..37db681 100644 --- a/src/view/events-item-view.js +++ b/src/view/events-item-view.js @@ -1,5 +1,5 @@ import AbstractView from '../framework/view/abstract-view.js'; -import { calculateDuration, convertDate, convertDuration, getCapitalized } from '../utils.js'; +import { calculateDuration, convertDate, convertDuration, getCapitalized } from '../util/utils.js'; import { DATE_TIME_FORMAT } from '../constants.js'; const createEventSelectedOffersTemplate = (selectedOffers) => { diff --git a/src/view/events-message-view.js b/src/view/events-message-view.js index 65a77a4..a902b42 100644 --- a/src/view/events-message-view.js +++ b/src/view/events-message-view.js @@ -1,10 +1,17 @@ import AbstractView from '../framework/view/abstract-view.js'; -const createEventsMessageTemplate = () => ` -

`; +const createEventsMessageTemplate = (message) => ` +

${message}

`; export default class EventsMessageView extends AbstractView { + #message = null; + + constructor({message}) { + super(); + this.#message = message; + } + get template() { - return createEventsMessageTemplate(); + return createEventsMessageTemplate(this.#message); } } diff --git a/src/view/filters-view.js b/src/view/filters-view.js index 67c749d..fb8e3e2 100644 --- a/src/view/filters-view.js +++ b/src/view/filters-view.js @@ -1,19 +1,18 @@ import AbstractView from '../framework/view/abstract-view.js'; -import { getCapitalized } from '../utils.js'; -import { FILTER_TYPES } from '../constants.js'; +import { getCapitalized } from '../util/utils.js'; -const createTripFilterTypeTemplate = (filter) => ` +const createTripFilterTypeTemplate = (filter, isChecked) => `
- +
`; -const createFiltersTemplate = () => ` +const createFiltersTemplate = (filters) => `

Filter events

- ${FILTER_TYPES.map((filter) => createTripFilterTypeTemplate(filter)).join('')} + ${filters.map((filter, index) => createTripFilterTypeTemplate(filter, index === 0)).join('')}
@@ -21,7 +20,14 @@ const createFiltersTemplate = () => `
`; export default class FiltersView extends AbstractView { + #filters = []; + + constructor({filters}) { + super(); + this.#filters = filters; + } + get template() { - return createFiltersTemplate(); + return createFiltersTemplate(this.#filters); } }