Skip to content

Commit

Permalink
Merge pull request #8 from vvvyat/module5-task2
Browse files Browse the repository at this point in the history
  • Loading branch information
keksobot authored Jun 19, 2024
2 parents d6a235d + 1edf0f5 commit 33bbe3b
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 56 deletions.
29 changes: 19 additions & 10 deletions src/const.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,6 @@ const POINT_COUNT = 5;

const DESTINATIONS = ['Paris', 'London', 'New York', 'Shanghai', 'Moscow'];

const FILTERS = {
'Everything': POINT_COUNT,
'Future': POINT_COUNT,
'Present': POINT_COUNT,
'Past': POINT_COUNT
};

const DEFAULT_FILTER = 'Everything';

const DESCRIPTIONS = [
'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.',
Expand Down Expand Up @@ -40,5 +31,23 @@ const DEFAULT_POINT_DATA = {
type: 'Flight'
};

const FilterType = {
EVERYTHING: 'everything',
FUTURE: 'future',
PRESENT: 'present',
PAST: 'past',
};

const Mode = {
DEFAULT: 'DEFAULT',
EDITING: 'EDITING',
};

const SortType = {
DAY: 'day',
TIME: 'time',
PRICE: 'price',
};

export {POINT_COUNT, DESTINATIONS, DESCRIPTIONS, DATE_FORMAT, TIME_FORMAT, HOUR_IN_DAY, MINUTES_IN_HOUR,
TYPES, DEFAULT_POINT_DATA, FILTERS, DEFAULT_FILTER};
TYPES, DEFAULT_POINT_DATA, FilterType, Mode, SortType};
10 changes: 6 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import FilterView from './view/filter-view.js';
import ListPresenter from './presenter/presenter.js';
import Presenter from './presenter/presenter.js';
import PointsModel from './model/points-model.js';
import {render} from './framework/render.js';
import {generateFilter} from './mock/filter.js';

const filterContainer = document.querySelector('.trip-controls__filters');
const pointsListContainer = document.querySelector('.trip-events');

const pointsModel = new PointsModel();
const listPresenter = new ListPresenter({
const presenter = new Presenter({
container: pointsListContainer,
pointsModel
});

render(new FilterView(), filterContainer);
listPresenter.init();
const filters = generateFilter(pointsModel.points);
render(new FilterView({filters}), filterContainer);
presenter.init();
12 changes: 12 additions & 0 deletions src/mock/filter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {filter} from '../utils/filters.js';

function generateFilter(points) {
return Object.entries(filter).map(
([filterType, filterPoints]) => ({
type: filterType,
count: filterPoints(points).length,
}),
);
}

export {generateFilter};
13 changes: 7 additions & 6 deletions src/mock/point.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const mockPoints = [
{
id: 3,
basePrice: 75,
dateFrom: '2019-07-15T7:55',
dateFrom: '2019-07-12T7:55',
dateTo: '2019-07-15T14:20',
destination: 2,
isFavorite: true,
Expand All @@ -35,8 +35,8 @@ const mockPoints = [
{
id: 4,
basePrice: 75,
dateFrom: '2019-07-15T7:55',
dateTo: '2019-07-15T14:20',
dateFrom: '2025-07-15T7:55',
dateTo: '2025-07-15T14:20',
destination: 2,
isFavorite: true,
offers: [0],
Expand All @@ -45,8 +45,8 @@ const mockPoints = [
{
id: 5,
basePrice: 5,
dateFrom: '2019-07-15T7:55',
dateTo: '2019-07-15T14:20',
dateFrom: '2019-07-14T7:55',
dateTo: '2025-07-15T14:20',
destination: 2,
isFavorite: true,
offers: [0],
Expand Down Expand Up @@ -149,7 +149,8 @@ function getOffersByType(type) {
return offers.find((offersByType) => offersByType.type === type).offers;
}

function getSelectedOffers(offerIds, offersByType) {
function getSelectedOffers(offerIds, type) {
const offersByType = getOffersByType(type);
const selectedOffers = [];
for (let i = 0; i < offerIds.length; i++ ) {
selectedOffers.push(offersByType.find((offer) => offer.id === offerIds[i]));
Expand Down
12 changes: 6 additions & 6 deletions src/presenter/point-presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@ import EditPointView from '../view/edit-point-view.js';
import PointView from '../view/point-view.js';
import {render, replace, remove} from '../framework/render.js';
import {getDestinationById, getOffersByType, getSelectedOffers} from '../mock/point.js';

const Mode = {
DEFAULT: 'DEFAULT',
EDITING: 'EDITING',
};
import {Mode} from '../const.js';

export default class PointPresenter {
#container;
Expand Down Expand Up @@ -36,7 +32,7 @@ export default class PointPresenter {
this.#pointComponent = new PointView({
point: this.#point,
destination,
selectedOffers: getSelectedOffers(this.#point.offers, offersByType),
selectedOffers: getSelectedOffers(this.#point.offers, this.#point.type),
handleOpenEditClick: this.#handleOpenEditClick,
handleFavoriteButtonClick: this.#handleFavoriteButtonClick
});
Expand Down Expand Up @@ -111,4 +107,8 @@ export default class PointPresenter {
}
}

destroy() {
remove(this.#pointComponent);
remove(this.#pointEditComponent);
}
}
47 changes: 44 additions & 3 deletions src/presenter/points-list-presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,25 @@ import NoPointsView from '../view/no-points-view.js';
import PointPresenter from './point-presenter.js';
import {render} from '../framework/render.js';
import {updateItem} from '../utils/common.js';
import {SortType} from '../const.js';
import {sortByDay, sortByPrice, sortByTime} from '../utils/point.js';

export default class PointsListPresenter {
#listComponent = new ListView();
#pointPresenters = new Map();
#currentSortType = SortType.DAY;
#sortComponent;
#container;
#points;
#pointPresenters = new Map();
#sourcedPoints;

constructor({container}) {
this.#container = container;
}

init(points) {
this.#points = points;
this.#points = [...points].sort(sortByDay);
this.#sourcedPoints = [...this.#points];
this.#renderPointsList();
}

Expand All @@ -32,12 +38,21 @@ export default class PointsListPresenter {
}
}

#clearPoints() {
this.#pointPresenters.forEach((presenter) => presenter.destroy());
this.#pointPresenters.clear();
}

#renderNoPoints() {
render(new NoPointsView(), this.#container);
}

#renderSort() {
render(new SortView(), this.#container);
this.#sortComponent = new SortView({
handleSortTypeChange: this.#handleSortTypeChange
});

render(this.#sortComponent, this.#container);
}

#renderPointsList() {
Expand All @@ -54,9 +69,35 @@ export default class PointsListPresenter {
#handlePointChange = (updatedPoint) => {
this.#points = updateItem(this.#points, updatedPoint);
this.#pointPresenters.get(updatedPoint.id).init(updatedPoint);
this.#sourcedPoints = updateItem(this.#sourcedPoints, updatedPoint);
};

#handleModeChange = () => {
this.#pointPresenters.forEach((presenter) => presenter.resetView());
};

#sortPoints(sortType) {
switch (sortType) {
case SortType.PRICE:
this.#points.sort(sortByPrice);
break;
case SortType.TIME:
this.#points.sort(sortByTime);
break;
default:
this.#points = [...this.#sourcedPoints];
}

this.#currentSortType = sortType;
}

#handleSortTypeChange = (sortType) => {
if (this.#currentSortType === sortType) {
return;
}

this.#sortPoints(sortType);
this.#clearPoints();
this.#renderPoints();
};
}
11 changes: 11 additions & 0 deletions src/utils/filters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {FilterType} from '../const.js';
import dayjs from 'dayjs';

const filter = {
[FilterType.EVERYTHING]: (points) => points,
[FilterType.FUTURE]: (points) => points.filter((point) => dayjs().isBefore(point.dateFrom)),
[FilterType.PRESENT]: (points) => points.filter((point) => (dayjs().isAfter(point.dateFrom)) && dayjs().isBefore(point.dateTo)),
[FilterType.PAST]: (points) => points.filter((point) => dayjs().isAfter(point.dateTo)),
};

export {filter};
66 changes: 64 additions & 2 deletions src/utils/point.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dayjs from 'dayjs';
import {DATE_FORMAT, TIME_FORMAT, HOUR_IN_DAY, MINUTES_IN_HOUR} from '../const';
import {getSelectedOffers} from '../mock/point';

function humanizeDueDate(dueDate) {
return dueDate ? dayjs(dueDate).format(DATE_FORMAT) : '';
Expand All @@ -9,8 +10,12 @@ function humanizeDueTime(dueDate) {
return dueDate ? dayjs(dueDate).format(TIME_FORMAT) : '';
}

function calculateDuration(start, end) {
return start && end ? dayjs(end).diff(start, 'minute') : '';
}

function humanizeDuration(start, end) {
const duration = start && end ? dayjs(end).diff(start, 'minute') : '';
const duration = calculateDuration(start, end);
if (duration === '') {
return '';
}
Expand All @@ -30,4 +35,61 @@ function humanizeDuration(start, end) {
}
}

export {humanizeDueDate, humanizeDueTime, humanizeDuration};
function calculateTotalPrice(point, selectedOffers) {
let totalPrice = point.basePrice;
for (const offer of selectedOffers) {
totalPrice += offer.price;
}
return totalPrice;
}

function sortByTime(pointA, pointB) {
const durationA = calculateDuration(pointA.dateFrom, pointA.dateTo);
const durationB = calculateDuration(pointB.dateFrom, pointB.dateTo);

if (durationA === durationB) {
return 0;
}

if (durationA > durationB) {
return 1;
}

if (durationB > durationA) {
return -1;
}
}

function sortByPrice(pointA, pointB) {
const priceA = calculateTotalPrice(pointA, getSelectedOffers(pointA.offers, pointA.type));
const priceB = calculateTotalPrice(pointB, getSelectedOffers(pointB.offers, pointB.type));
if (priceA === priceB) {
return 0;
}

if (priceA > priceB) {
return 1;
}

if (priceB > priceA) {
return -1;
}
}

function sortByDay(pointA, pointB) {
const startA = pointA.dateFrom;
const startB = pointB.dateFrom;
if (dayjs(startA).isSame(dayjs(startB))) {
return 0;
}

if (dayjs(startB).isBefore(dayjs(startA))) {
return 1;
}

if (dayjs(startA).isBefore(dayjs(startB))) {
return -1;
}
}

export {humanizeDueDate, humanizeDueTime, humanizeDuration, sortByDay, sortByTime, sortByPrice, calculateTotalPrice};
38 changes: 24 additions & 14 deletions src/view/filter-view.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,37 @@
import AbstractView from '../framework/view/abstract-view.js';
import {FILTERS, DEFAULT_FILTER} from '../const.js';

function createFilterTemplate(filterName, count) {
const filter = filterName.toLowerCase();
const isChecked = filterName === DEFAULT_FILTER ? 'checked' : '';
function createFilterItemTemplate(filter, isChecked) {
const {type, count} = filter;
const isDisabled = count === 0 ? 'disabled' : '';

return `
<div class="trip-filters__filter">
<input id="filter-${filter}" class="trip-filters__filter-input visually-hidden" type="radio" name="trip-filter" value="${filter}" ${isChecked} ${isDisabled}>
<label class="trip-filters__filter-label" for="filter-${filter}">${filterName}</label>
<input id="filter-${type}" class="trip-filters__filter-input visually-hidden" type="radio" name="trip-filter" value="${type}" ${isChecked} ${isDisabled}>
<label class="trip-filters__filter-label" for="filter-${type}">${type}</label>
</div>
`;
}

function createFilterTemplate(filters) {
const filtersTemplate = filters
.map((filter, index) => createFilterItemTemplate(filter, index === 0))
.join('');

return `
<form class="trip-filters" action="#" method="get">
${filtersTemplate}
<button class="visually-hidden" type="submit">Accept filter</button>
</form>`;
}
export default class FilterView extends AbstractView {
get template() {
const filtersTemplate = Object.entries(FILTERS).map(([filter, count]) => createFilterTemplate(filter, count)).join('');
#filters;

constructor({filters}) {
super();
this.#filters = filters;
}

return `
<form class="trip-filters" action="#" method="get">
${filtersTemplate}
<button class="visually-hidden" type="submit">Accept filter</button>
</form>
`;
get template() {
return createFilterTemplate(this.#filters);
}
}
Loading

0 comments on commit 33bbe3b

Please sign in to comment.