Skip to content

Commit

Permalink
8.8. Дополнительная функциональность
Browse files Browse the repository at this point in the history
  • Loading branch information
TeaWithSalt committed May 27, 2024
1 parent fb74a83 commit c825529
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/const.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const API_SRC = 'https://23.objects.htmlacademy.pro/big-trip';
const AUTHORIZATION = 'Basic awdaf5g34123csdrh56w2r5';
const AUTHORIZATION = 'Basic awdaf5g34123csdrh56w2r51';

const ACTIONS = {
UPDATE_POINT: 'update',
Expand Down
6 changes: 2 additions & 4 deletions src/main.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {render, RenderPosition} from './framework/render.js';
import InfoView from './view/info-view.js';
import WaypointsListPresenter from './presenter/waypoints-list-presenter.js';
import WaypointsModel from './model/waypoint-model.js';
import {getMockFilters} from './mock/filter.js';
Expand All @@ -17,7 +16,6 @@ const eventContainer = document.querySelector('.trip-events');
const mockFilters = getMockFilters();
const mockSorts = getMockSorts();


const waypointsModel = new WaypointsModel({
waypointsService: new WaypointsService(API_SRC, AUTHORIZATION)
});
Expand All @@ -27,6 +25,7 @@ const filterModel = new FilterModel();
const filterPresenter = new FilterPresenter({
filterContainer,
filterModel,
waypointsModel,
filters: mockFilters
});

Expand All @@ -39,6 +38,7 @@ function handleNewPointFormClose() {
}

const eventPresenter = new WaypointsListPresenter({
mainContainer,
eventContainer,
waypointsModel,
filterModel,
Expand All @@ -53,8 +53,6 @@ function handleNewPointButtonClick() {
newPointButtonComponent.element.disabled = true;
}


render(new InfoView(), mainContainer, RenderPosition.AFTERBEGIN);
render(newPointButtonComponent, mainContainer, RenderPosition.BEFOREEND);

filterPresenter.init();
Expand Down
17 changes: 15 additions & 2 deletions src/presenter/filter-presenter.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import {remove, render, replace} from '../framework/render';
import FilterView from '../view/filter-view';
import {FILTER_TYPE} from '../const';

export default class FilterPresenter {
#filterContainer;
#filters;
#filterComponent = null;
#filterModel;
#waypointsModel;
#waypoints = null;

constructor({filterContainer, filterModel, filters}) {
constructor({filterContainer, filterModel, waypointsModel, filters}) {
this.#filterContainer = filterContainer;
this.#filters = filters;
this.#filterModel = filterModel;
this.#waypointsModel = waypointsModel;

this.#waypointsModel.addObserver(this.init.bind(this));
this.#filterModel.addObserver(this.init.bind(this));
}

get filters() {
return Object.values(FILTER_TYPE).map((name) => ({
name,
count: this.#filters.find((filter) => filter.name.toUpperCase() === name.toUpperCase()).getPoints(this.#waypoints).length,
}));
}

init() {
this.#waypoints = [...this.#waypointsModel.getWaypoints()];
const prevFilterComponent = this.#filterComponent;

this.#filterComponent = new FilterView({
filters: this.#filters,
filters: this.filters,
type: this.#filterModel.filter,
onChange: this.#handleTypeChange
});
Expand Down
34 changes: 27 additions & 7 deletions src/presenter/waypoints-list-presenter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ import {
import NewWaypointPresenter from './new-waypoint-presenter';
import LoadingView from '../view/loading-view';
import UiBlocker from '../framework/ui-blocker/ui-blocker';
import {getRoute, getTotalPrice} from '../utils';
import InfoView from '../view/info-view';

export default class WaypointsListPresenter {
#eventListContainer = new EventListView();
#waypointPresenters = [];
#eventContainer;
#mainContainer;
#infoComponent;
#sorts;
#filters;
#currentSortType;
Expand All @@ -36,7 +40,8 @@ export default class WaypointsListPresenter {
upperLimit: TIME_LIMITS.UPPER_LIMIT
});

constructor({eventContainer, waypointsModel, filterModel, sorts, filters, onNewPointDestroy}) {
constructor({mainContainer, eventContainer, waypointsModel, filterModel, sorts, filters, onNewPointDestroy}) {
this.#mainContainer = mainContainer;
this.#eventContainer = eventContainer;
this.#sorts = sorts;
this.#filters = filters;
Expand Down Expand Up @@ -94,13 +99,23 @@ export default class WaypointsListPresenter {
onChange: this.#handleSortTypeChange
});

render(
this.#sortsComponent,
this.#eventContainer,
RenderPosition.AFTERBEGIN
this.#renderInfo();
render(this.#sortsComponent, this.#eventContainer, RenderPosition.AFTERBEGIN);
filteredPoints.forEach((waypoint) => this.#renderWaypoint(waypoint));
}

#renderInfo() {
const route = getRoute(
this.#sortWaypoints(SORTING_TYPES.DAY, this.waypointsModel.getWaypoints()),
this.waypointsModel.destinations
);
this.#infoComponent = new InfoView({
route: route.route,
routeDates: route.routeDates,
totalPrice: getTotalPrice(this.waypointsModel.getWaypoints(), this.waypointsModel.offers),
});

filteredPoints.forEach((waypoint) => this.#renderWaypoint(waypoint));
render(this.#infoComponent, this.#mainContainer, RenderPosition.AFTERBEGIN);
}

reset() {
Expand All @@ -115,6 +130,10 @@ export default class WaypointsListPresenter {
remove(this.#sortsComponent);
}

if (this.#infoComponent) {
remove(this.#infoComponent);
}

if (this.#emptyComponent) {
remove(this.#emptyComponent);
}
Expand Down Expand Up @@ -192,8 +211,9 @@ export default class WaypointsListPresenter {
};

#sortWaypoints(sortType) {
this.#sorts.find((sort) => sort.name === sortType).getPoints(this.waypointsModel.getWaypoints());
const sortedWaypoints = this.#sorts.find((sort) => sort.name === sortType).getPoints(this.waypointsModel.getWaypoints());
this.#currentSortType = sortType;
return sortedWaypoints;
}

#getFilteredWaypoints(waypoints) {
Expand Down
72 changes: 45 additions & 27 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,36 +25,55 @@ function formatDuration(minutes) {
return result;
}

function stringToDate(str, format) {
const normalized = str.replace(/[^a-zA-Z0-9]/g, '-');
const normalizedFormat = format.toLowerCase().replace(/[^a-zA-Z0-9]/g, '-');
const formatItems = normalizedFormat.split('-');
const dateItems = normalized.split('-');

const monthIndex = formatItems.indexOf('mm');
const dayIndex = formatItems.indexOf('dd');
const yearIndex = formatItems.indexOf('yy');
const hourIndex = formatItems.indexOf('hh');
const minutesIndex = formatItems.indexOf('ii');
const secondsIndex = formatItems.indexOf('ss');

const today = new Date();

const year = yearIndex > -1 ? parseInt(`20${dateItems[yearIndex]}`, 10) : today.getFullYear();
const month = monthIndex > -1 ? dateItems[monthIndex] - 1 : today.getMonth() - 1;
const day = dayIndex > -1 ? dateItems[dayIndex] : today.getDate();

const hour = hourIndex > -1 ? dateItems[hourIndex] : today.getHours();
const minute = minutesIndex > -1 ? dateItems[minutesIndex] : today.getMinutes();
const second = secondsIndex > -1 ? dateItems[secondsIndex] : today.getSeconds();

return new Date(year, month, day, hour, minute, second);
}

function isEscape(key) {
return key === 'Escape' || key === 'Esc';
}

export const formatDate = (date, formatPattern) =>
date ? dayjs(date).format(formatPattern) : '';

export const getRoute = (events, destinations) => {
let route = '';
let routeDates = '';
const eventsLength = events.length;
const firstEvent = events[0];
const lastEvent = events[eventsLength - 1];

routeDates = `
${formatDate(firstEvent.dateFrom, 'DD MMM')}
 — 
${formatDate(lastEvent.dateTo, 'DD MMM')}
`;

if (eventsLength <= 3) {
route = events
.map((event) => destinations.find((destination) => destination.id === event.destination).name)
.join(' &mdash; ');

return { route, routeDates };
}

const firstRoutePoint = destinations.find((destination) => destination.id === firstEvent.destination);
const lastRoutePoint = destinations.find((destination) => destination.id === lastEvent.destination);
route = `${firstRoutePoint.name} &mdash; ... &mdash; ${lastRoutePoint.name}`;

return { route, routeDates };
};

export const getOfferById = (offers, type, id) =>
offers
.find((offer) => offer.type === type)
.offers.find((item) => item.id === id);

export const getTotalEventPrice = (event, offers) => event.basePrice +
event.offers.reduce(
(sum, offer) => sum + getOfferById(offers, event.type, offer).price,
0
);
export const getTotalPrice = (events, offers) =>
events.reduce((sum, event) => sum + getTotalEventPrice(event, offers), 0);


const filters = {
[FILTER_TYPE.EVERYTHING]: (points) => points.filter((point) => point),
[FILTER_TYPE.FUTURE]: (points) => points.filter((point) => new Date(point.dateFrom) > new Date()),
Expand All @@ -75,7 +94,6 @@ export {
humanizeWaypointDueDate,
countDuration,
formatDuration,
stringToDate,
isEscape,
filters,
sorts
Expand Down
4 changes: 2 additions & 2 deletions src/view/filter-view.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import AbstractView from '../framework/view/abstract-view.js';

function createFilterItemTemplate(filter, isChecked) {
const {name} = filter;
const {name, count} = filter;
return (`
<div class="trip-filters__filter">
<input id="filter-${name}" class="trip-filters__filter-input visually-hidden" type="radio" name="trip-filter" value="${name}" ${isChecked ? 'checked' : ''}>
<input id="filter-${name}" class="trip-filters__filter-input visually-hidden" type="radio" name="trip-filter" value="${name}" ${isChecked ? 'checked' : ''} ${!count ? 'disabled' : ''}>
<label class="trip-filters__filter-label" for="filter-${name}">${name}</label>
</div>
`);
Expand Down
20 changes: 13 additions & 7 deletions src/view/info-view.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,33 @@
import AbstractView from '../framework/view/abstract-view.js';

function createInfoTemplate() {
function createInfoTemplate(route, routeDates, totalPrice) {
return `
<section class="trip-main__trip-info trip-info">
<div class="trip-info__main">
<h1 class="trip-info__title">Amsterdam &mdash; Chamonix &mdash; Geneva</h1>
<p class="trip-info__dates">Mar 18&nbsp;&mdash;&nbsp;20</p>
<h1 class="trip-info__title">${route}</h1>
<p class="trip-info__dates">${routeDates}</p>
</div>
<p class="trip-info__cost">
Total: &euro;&nbsp;<span class="trip-info__cost-value">1230</span>
Total: &euro;&nbsp;<span class="trip-info__cost-value">${totalPrice}</span>
</p>
</section>
`;
}

export default class InfoView extends AbstractView {
constructor() {
#route = null;
#routeDates = null;
#totalPrice = null;

constructor({route, routeDates, totalPrice}) {
super();
this.#route = route;
this.#routeDates = routeDates;
this.#totalPrice = totalPrice;
}

get template() {
return createInfoTemplate();
return createInfoTemplate(this.#route, this.#routeDates, this.#totalPrice);
}
}

0 comments on commit c825529

Please sign in to comment.