diff --git a/src/const.js b/src/const.js index cc4c19a..414d7d5 100644 --- a/src/const.js +++ b/src/const.js @@ -59,6 +59,13 @@ const POINT_EMPTY = { type: DEFAULT_TYPE }; +const FilterType = { + EVERYTHING: 'everything', + FUTURE: 'future', + PRESENT: 'present', + PAST: 'past' +}; + export { OFFER_COUNT, DESTINATION_COUNT, @@ -69,5 +76,6 @@ export { Price, TYPES, DEFAULT_TYPE, - POINT_EMPTY -} + POINT_EMPTY, + FilterType +}; diff --git a/src/main.js b/src/main.js index 22f2c77..04d7fa9 100644 --- a/src/main.js +++ b/src/main.js @@ -1,6 +1,6 @@ import TripInfoView from './view/trip-info-view.js'; -import FilterView from './view/filter-view.js'; import TripPresenter from './presenter/trip-presenter.js'; +import FilterPresenter from './presenter/filter-presenter.js'; import MockService from './service/mock-service.js'; import DestinationsModel from './model/destinations-model.js'; import OffersModel from './model/offers-model.js'; @@ -10,6 +10,7 @@ import { render, RenderPosition } from './framework/render.js'; const tripInfoElement = document.querySelector('.trip-main'); const siteMainElement = document.querySelector('.page-main'); const eventListElement = siteMainElement.querySelector('.trip-events'); +const filterElement = tripInfoElement.querySelector('.trip-controls__filters'); const mockService = new MockService(); const destinationsModel = new DestinationsModel(mockService); @@ -17,8 +18,9 @@ const offersModel = new OffersModel(mockService); const pointsModel = new PointsModel(mockService); const tripPresenter = new TripPresenter({ tripContainer: eventListElement, destinationsModel, offersModel, pointsModel }); +const filterPresenter = new FilterPresenter({ container: filterElement, pointsModel }); render(new TripInfoView(), tripInfoElement, RenderPosition.AFTERBEGIN); -render(new FilterView(), tripInfoElement.querySelector('.trip-controls__filters')); tripPresenter.init(); +filterPresenter.init(); diff --git a/src/mock/filter.js b/src/mock/filter.js new file mode 100644 index 0000000..d1dc4a8 --- /dev/null +++ b/src/mock/filter.js @@ -0,0 +1,11 @@ +import { filter } from '../utils/filter.js'; + +const generateFilters = (points) => { + return Object.entries(filter) + .map(([filterType, filterPoints]) => ({ + type: filterType, + hasPoints: filterPoints(points).length > 0 + })); +}; + +export { generateFilters }; diff --git a/src/presenter/filter-presenter.js b/src/presenter/filter-presenter.js new file mode 100644 index 0000000..9c17249 --- /dev/null +++ b/src/presenter/filter-presenter.js @@ -0,0 +1,19 @@ +import FilterView from '../view/filter-view.js'; +import { render } from '../framework/render.js'; +import { generateFilters } from '../mock/filter.js'; + +export default class FilterPresenter { + #container = null; + #pointsModel = null; + #filters = []; + + constructor({ container, pointsModel }) { + this.#container = container; + this.#pointsModel = pointsModel; + this.#filters = generateFilters(this.#pointsModel.get()); + } + + init() { + render(new FilterView(this.#filters), this.#container); + } +} diff --git a/src/presenter/trip-presenter.js b/src/presenter/trip-presenter.js index d4c628a..9dcecbe 100644 --- a/src/presenter/trip-presenter.js +++ b/src/presenter/trip-presenter.js @@ -2,6 +2,7 @@ import SortView from '../view/sort-view.js'; import EditPointView from '../view/edit-point-view.js'; import PointView from '../view/point-view.js'; import TripView from '../view/point-list-view.js'; +import EmptyListView from '../view/empty-list-view.js'; import { render, replace } from '../framework/render.js'; export default class TripPresenter { @@ -23,6 +24,11 @@ export default class TripPresenter { } init() { + if (this.#points.length === 0) { + render(new EmptyListView(), this.#tripContainer); + return; + } + render(this.#sortComponent, this.#tripContainer); render(this.#pointListComponent, this.#tripContainer); diff --git a/src/utils.js b/src/utils.js index 9a0deaf..54db7ef 100644 --- a/src/utils.js +++ b/src/utils.js @@ -10,7 +10,7 @@ const TimePeriods = { SEC_IN_MIN: 60, MIN_IN_HOUR: 60, HOUR_IN_DAY: 24 -} +}; const MSEC_IN_HOUR = TimePeriods.MIN_IN_HOUR * TimePeriods.SEC_IN_MIN * TimePeriods.MSEC_IN_SEC; const MSEC_IN_DAY = TimePeriods.HOUR_IN_DAY * MSEC_IN_HOUR; @@ -62,6 +62,10 @@ function formatStringToTime(date) { return dayjs(date).format('HH:mm'); } +function capitalize(string) { + return `${string[0].toUpperCase()}${string.slice(1)}`; +} + function getPointDuration(dateFrom, dateTo) { const timeDiff = dayjs(dateTo).diff(dayjs(dateFrom)); @@ -82,6 +86,18 @@ function getPointDuration(dateFrom, dateTo) { return pointDuration; } +function isPointFuture(point) { + return dayjs().isBefore(point.dateFrom); +} + +function isPointPresent(point) { + return (dayjs().isAfter(point.dateFrom) && dayjs().isBefore(point.dateTo)); +} + +function isPointPast(point) { + return dayjs().isAfter(point.dateTo); +} + export { getDate, getRandomInteger, @@ -89,5 +105,9 @@ export { formatStringToDateTime, formatStringToShortDate, formatStringToTime, - getPointDuration -} + capitalize, + getPointDuration, + isPointFuture, + isPointPast, + isPointPresent +}; diff --git a/src/utils/filter.js b/src/utils/filter.js new file mode 100644 index 0000000..1db606a --- /dev/null +++ b/src/utils/filter.js @@ -0,0 +1,11 @@ +import { FilterType } from '../const.js'; +import { isPointFuture, isPointPresent, isPointPast } from '../utils.js'; + +const filter = { + [FilterType.EVERYTHING]: (points) => [...points], + [FilterType.FUTURE]: (points) => points.filter((point) => isPointFuture(point)), + [FilterType.PRESENT]: (points) => points.filter((point) => isPointPresent(point)), + [FilterType.PAST]: (points) => points.filter((point) => isPointPast(point)) +}; + +export { filter }; diff --git a/src/view/empty-list-view.js b/src/view/empty-list-view.js new file mode 100644 index 0000000..14ee290 --- /dev/null +++ b/src/view/empty-list-view.js @@ -0,0 +1,16 @@ +import AbstractView from '../framework/view/abstract-view.js'; + +const createEmptyListViewTemplate = () => { + return ( + `
+

Trip events

+

Click New Event to create your first point

+
` + ); +}; + +export default class EmptyListView extends AbstractView { + get template() { + return createEmptyListViewTemplate(); + } +} diff --git a/src/view/filter-view.js b/src/view/filter-view.js index dcc3181..a969897 100644 --- a/src/view/filter-view.js +++ b/src/view/filter-view.js @@ -1,32 +1,41 @@ import AbstractView from '../framework/view/abstract-view.js'; +import { capitalize } from '../utils.js'; -const createFilterTemplate = () => { +const createFilterItemsTemplate = ({ filters }) => { + const filterItems = filters.map(filter => { + return ( + `
+ + +
` + ); + }).join(''); + + return filterItems; +}; + +const createFilterTemplate = ({ filters }) => { return ( `
-
- - -
-
- - -
-
- - -
-
- - -
- + ${createFilterItemsTemplate({ filters })} +
` ); -} +}; export default class FilterView extends AbstractView { + #filters = []; + + constructor(filters) { + super(); + this.#filters = filters; + } + get template() { - return createFilterTemplate(); + return createFilterTemplate({ + filters: this.#filters + }); } } diff --git a/src/view/point-list-view.js b/src/view/point-list-view.js index 0efcfa4..ff0f932 100644 --- a/src/view/point-list-view.js +++ b/src/view/point-list-view.js @@ -4,7 +4,7 @@ const createPointListTemplate = () => { return ( `