From 7cace1cbeec531c88e1130b38f173f78731855aa Mon Sep 17 00:00:00 2001 From: InsomniaRolodex Date: Tue, 13 Aug 2024 18:23:07 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D0=9E=D0=B1=D1=8A=D0=B5=D0=B4=D0=B8=D0=BD?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B0=D0=B2=D0=B0?= =?UTF-8?q?=D0=B5=D0=BC=D1=8B=D0=B5=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D1=87=D0=B8=D0=BA=D0=B8=20=D0=B2=20=D0=BE=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=20=D0=BE=D0=B1=D1=8A=D0=B5=D0=BA=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/presenter/point-presenter.js | 9 +++------ src/view/edit-form-view.js | 2 +- src/view/trip-point-view.js | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/presenter/point-presenter.js b/src/presenter/point-presenter.js index a54cc16..90b9a2a 100644 --- a/src/presenter/point-presenter.js +++ b/src/presenter/point-presenter.js @@ -30,18 +30,15 @@ export default class PointPresenter { onEditClick: () => { this.#replacePointToForm(); document.addEventListener('keydown', this.#escKeyDownHanlder); - } - }, - { onFavoriteClick: this.#handleFavoriteClick } + }, + onFavoriteClick: this.#handleFavoriteClick } ); this.#editTripForm = new EditFormView(point, destination, offer, { onEditClick: () => { this.#replaceFormToPoint(); - } - }, - { + }, onFormSubmit: () => { this.#replaceFormToPoint(); } diff --git a/src/view/edit-form-view.js b/src/view/edit-form-view.js index 687fa36..3ebafc9 100644 --- a/src/view/edit-form-view.js +++ b/src/view/edit-form-view.js @@ -135,7 +135,7 @@ export default class EditFormView extends AbstractView { #handleFormSubmit; #handleClick; - constructor(points, destionations, offers, { onEditClick }, { onFormSubmit }) { + constructor(points, destionations, offers, { onEditClick, onFormSubmit }) { super(); this.points = points; this.destionations = destionations; diff --git a/src/view/trip-point-view.js b/src/view/trip-point-view.js index 7d84007..c7bde7a 100644 --- a/src/view/trip-point-view.js +++ b/src/view/trip-point-view.js @@ -82,7 +82,7 @@ export default class TripPointView extends AbstractView { #onEditClick; #handleFavoriteClick; - constructor(points, destinations, offers, {onEditClick}, {onFavoriteClick}) { + constructor(points, destinations, offers, {onEditClick, onFavoriteClick}) { super(); this.points = points; this.destinations = destinations; From 16304dad450b14003c621a5cbfc291597551aca4 Mon Sep 17 00:00:00 2001 From: InsomniaRolodex Date: Mon, 19 Aug 2024 18:14:55 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A1=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 8 +++++ src/presenter/trip-presenter.js | 53 +++++++++++++++++++++++++++++++-- src/util.js | 33 +++++++++++++++++++- src/view/sorting-view.js | 32 ++++++++++++++++---- 4 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 src/const.js diff --git a/src/const.js b/src/const.js new file mode 100644 index 0000000..d872d98 --- /dev/null +++ b/src/const.js @@ -0,0 +1,8 @@ +const SortingTypes = { + DAY: 'day', + EVENT: 'event', + TIME: 'time', + PRICE: 'price', + OFFERS: 'offers'}; + +export {SortingTypes}; diff --git a/src/presenter/trip-presenter.js b/src/presenter/trip-presenter.js index c9fafe0..64b283f 100644 --- a/src/presenter/trip-presenter.js +++ b/src/presenter/trip-presenter.js @@ -5,7 +5,9 @@ import TripListView from '../view/trip-list-view.js'; import ListEmptyView from '../view/list-empty-view.js'; import PointModel from '../model/point-model.js'; import PointPresenter from './point-presenter.js'; -import { updateItem } from '../util.js'; +import { updateItem, sortPointsByDay, sortPointsByPrice, sortPointsByTime } from '../util.js'; +import { SortingTypes } from '../const.js'; + export default class TripPresenter { #tripList = new TripListView(); @@ -15,6 +17,9 @@ export default class TripPresenter { #points; #destinations; #offers; + #sortingComponent; + #currentSortingType = SortingTypes.PRICE; + #sourcedPointsOrder = []; constructor ({ container, pointModel = new PointModel }) { this.#container = container; @@ -26,9 +31,11 @@ export default class TripPresenter { this.#points = this.#pointModel.points; this.#destinations = this.#pointModel.destinations; this.#offers = this.#pointModel.offers; + this.#sourcedPointsOrder = this.#pointModel.points; // const defaultPoint = this.#pointModel.defaultPoint; - render(new SortingView, this.#container); + this.#renderSorting(); + render(this.#tripList, this.#container); if (this.#points.length === 0) { render(new ListEmptyView, this.#container); @@ -46,10 +53,47 @@ export default class TripPresenter { #handleFavStatusChange = (updatedPoint, destination = this.#destinations, offer = this.#offers) => { this.#points = updateItem(this.#points, updatedPoint.points); + this.#sourcedPointsOrder = updateItem(this.#sourcedPointsOrder, updatedPoint.points); this.#pointPresenters.get(updatedPoint.points.id).init(updatedPoint.points, destination, offer); }; + #sortPoints(sortingType) { + switch (sortingType) { + case SortingTypes.DAY: + this.#points.sort(sortPointsByDay); + break; + case SortingTypes.PRICE: + this.#points.sort(sortPointsByPrice); + break; + case SortingTypes.TIME: + this.#points.sort(sortPointsByTime); + break; + default: + this.#points = [...this.#sourcedPointsOrder]; + } + this.#currentSortingType = sortingType; + } + + #handleSortingTypeChange(sortingType) { + + if (this.#currentSortingType === sortingType) { + return; + } + this.#sortPoints(sortingType); + this.#clearPointList(); + this.#points.forEach((point) => this.#renderPoint(point, this.#destinations, this.#offers)); + + } + + #renderSorting() { + this.#sortingComponent = new SortingView({ + onSortTypeChange: this.#handleSortingTypeChange + }); + + render(this.#sortingComponent, this.#container); + } + #renderPoint(point, destination, offer) { const pointPresenter = new PointPresenter({ tripList: this.#tripList, @@ -59,4 +103,9 @@ export default class TripPresenter { pointPresenter.init(point, destination, offer); this.#pointPresenters.set(point.id, pointPresenter); } + + #clearPointList() { + this.#pointPresenters.forEach((presenter) => presenter.destroy()); + this.#pointPresenters.clear(); + } } diff --git a/src/util.js b/src/util.js index 4d838f5..ee33132 100644 --- a/src/util.js +++ b/src/util.js @@ -40,5 +40,36 @@ const toCamelCase = (str) => lodash.camelCase(str); const updateItem = (items, update) => items.map((item) => item.id === update.id ? update : item); +const getWeightForDate = (dateA, dateB) => { + if (dateA === null && dateB === 0) { + return 0; + } + + if (dateA === null) { + return 1; + } + + if (dateB === null) { + return -1; + } + + return null; +}; + +const sortPointsByDay = (pointA, pointB) => { + const weight = getWeightForDate(pointA.dateFrom, pointB.dateFrom); + + return weight ?? dayjs(pointA.dateFrom).diff(dayjs(pointB.dateFrom)); +}; + +const sortPointsByPrice = (pointA, pointB) => getWeightForDate(pointA.basPrice, pointB.basPrice); + +const sortPointsByTime = (pointA, pointB) => { + pointA = findDuration(pointA.dateFrom, pointA.dateTo); + pointB = findDuration(pointB.dateFrom, pointB.dateTo); + + return getWeightForDate(pointA, pointB); +}; + -export { humanizeDueDate, capitalize, findDuration, toCamelCase, checkPastPoints, checkPresentPoints, updateItem }; +export { humanizeDueDate, capitalize, findDuration, toCamelCase, checkPastPoints, checkPresentPoints, updateItem, sortPointsByDay, sortPointsByPrice, sortPointsByTime }; diff --git a/src/view/sorting-view.js b/src/view/sorting-view.js index 036fc70..7ea3a02 100644 --- a/src/view/sorting-view.js +++ b/src/view/sorting-view.js @@ -1,22 +1,42 @@ +import { SortingTypes } from '../const.js'; import AbstractView from '../framework/view/abstract-view.js'; +import { capitalize } from '../util.js'; -const sortingTypes = ['Day', 'Event', 'Time', 'Price', 'Offers']; - -const findCheckedElement = (element) => element === 'Price' ? 'checked' : ''; +const findCheckedElement = (element) => element === 'price' ? 'checked' : ''; const createSortingElement = (sortingType) => `
- - + +
`; const createSortingTemplate = () => `
- ${sortingTypes.map((sortingType) => createSortingElement(sortingType)).join('')} + ${Object.values(SortingTypes).map((sortingType) => createSortingElement(sortingType)).join('')}
`; export default class SortingView extends AbstractView{ + #handleSortTypeChange; + + constructor ({onSortTypeChange}) { + super(); + this.#handleSortTypeChange = onSortTypeChange; + this.element.addEventListener('click', this.#sortTypeChangeHandler); + } + get template () { return createSortingTemplate(); } + + #sortTypeChangeHandler = (evt) => { + if (evt.target.tagName !== 'INPUT') { + return; + } + + evt.preventDefault(); + this.#handleSortTypeChange(evt.target.dataset.sortType); + }; } From af7c685c7059facce2d014c73a72a9bdffe5e7dd Mon Sep 17 00:00:00 2001 From: InsomniaRolodex Date: Tue, 20 Aug 2024 21:24:51 +0300 Subject: [PATCH 3/4] Sorting full --- src/mock/points.js | 24 ++++++++++++------------ src/presenter/trip-presenter.js | 13 +++++++------ src/util.js | 18 +++++------------- src/view/sorting-view.js | 4 ++-- src/view/trip-point-view.js | 2 +- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/mock/points.js b/src/mock/points.js index bfa16b6..cfedac2 100644 --- a/src/mock/points.js +++ b/src/mock/points.js @@ -1,18 +1,6 @@ import { toCamelCase } from '../util.js' export const points = [ - { - id: 'f4b62099-293f-4c3d-a702-94eec4a2808c', - basePrice: 11300, - dateFrom: '2025-07-10T00:55:56.845Z', - dateTo: '2025-07-11T11:01:13.375Z', - destination: 'bfa5cb75-a1fe-4b77-a83c-0e528e910e04', - isFavorite: false, - offers: [ - 'b4c3e4e6-9053-42ce-b747-e281314baa31' - ], - type: 'taxi' - }, { id: 'f4b62099-293f-4c3d-a702-94eec4a2808d', basePrice: 11200, @@ -37,6 +25,18 @@ export const points = [ offers: [], type: 'ship' }, + { + id: 'f4b62099-293f-4c3d-a702-94eec4a2808c', + basePrice: 11300, + dateFrom: '2025-07-10T00:55:56.845Z', + dateTo: '2025-07-11T11:01:13.375Z', + destination: 'bfa5cb75-a1fe-4b77-a83c-0e528e910e04', + isFavorite: false, + offers: [ + 'b4c3e4e6-9053-42ce-b747-e281314baa31' + ], + type: 'taxi' + }, { id: 'f4b62099-293f-4c3d-a702-94eec4a2808f', basePrice: 11100, diff --git a/src/presenter/trip-presenter.js b/src/presenter/trip-presenter.js index 64b283f..46ab5b1 100644 --- a/src/presenter/trip-presenter.js +++ b/src/presenter/trip-presenter.js @@ -5,7 +5,7 @@ import TripListView from '../view/trip-list-view.js'; import ListEmptyView from '../view/list-empty-view.js'; import PointModel from '../model/point-model.js'; import PointPresenter from './point-presenter.js'; -import { updateItem, sortPointsByDay, sortPointsByPrice, sortPointsByTime } from '../util.js'; +import { updateItem, sortPointsByDay, findSortingDuration } from '../util.js'; import { SortingTypes } from '../const.js'; @@ -64,10 +64,11 @@ export default class TripPresenter { this.#points.sort(sortPointsByDay); break; case SortingTypes.PRICE: - this.#points.sort(sortPointsByPrice); + this.#points.sort((pointA, pointB) => pointA.basePrice - pointB.basePrice); break; case SortingTypes.TIME: - this.#points.sort(sortPointsByTime); + + this.#points.sort((pointA, pointB) => findSortingDuration(pointA) - findSortingDuration(pointB)); break; default: this.#points = [...this.#sourcedPointsOrder]; @@ -76,19 +77,19 @@ export default class TripPresenter { } #handleSortingTypeChange(sortingType) { - if (this.#currentSortingType === sortingType) { return; } this.#sortPoints(sortingType); this.#clearPointList(); - this.#points.forEach((point) => this.#renderPoint(point, this.#destinations, this.#offers)); + this.#renderSorting(); + this.#points.forEach((point) => this.#renderPoint(point, this.#destinations, this.#offers)); } #renderSorting() { this.#sortingComponent = new SortingView({ - onSortTypeChange: this.#handleSortingTypeChange + onSortTypeChange: (sortingType) => this.#handleSortingTypeChange(sortingType), }); render(this.#sortingComponent, this.#container); diff --git a/src/util.js b/src/util.js index ee33132..efd21f0 100644 --- a/src/util.js +++ b/src/util.js @@ -5,8 +5,10 @@ const humanizeDueDate = (dueDate, dateFormat) => dueDate ? dayjs(dueDate).format const capitalize = (str) => str[0].toUpperCase() + str.slice(1); -const findDuration = (date1, date2) => { - let minutesDuration = dayjs(date1).diff(dayjs(date2), 'm'); +const findSortingDuration = (point) => dayjs(point.dateTo).diff(dayjs(point.dateFrom), 'm'); + +const findDuration = (point) => { + let minutesDuration = findSortingDuration(point); const minutesAfterHours = minutesDuration % 60; if (minutesDuration >= 60 && minutesAfterHours !== 0) { @@ -62,14 +64,4 @@ const sortPointsByDay = (pointA, pointB) => { return weight ?? dayjs(pointA.dateFrom).diff(dayjs(pointB.dateFrom)); }; -const sortPointsByPrice = (pointA, pointB) => getWeightForDate(pointA.basPrice, pointB.basPrice); - -const sortPointsByTime = (pointA, pointB) => { - pointA = findDuration(pointA.dateFrom, pointA.dateTo); - pointB = findDuration(pointB.dateFrom, pointB.dateTo); - - return getWeightForDate(pointA, pointB); -}; - - -export { humanizeDueDate, capitalize, findDuration, toCamelCase, checkPastPoints, checkPresentPoints, updateItem, sortPointsByDay, sortPointsByPrice, sortPointsByTime }; +export { humanizeDueDate, capitalize, findDuration, toCamelCase, checkPastPoints, checkPresentPoints, updateItem, sortPointsByDay, findSortingDuration }; diff --git a/src/view/sorting-view.js b/src/view/sorting-view.js index 7ea3a02..765b8a9 100644 --- a/src/view/sorting-view.js +++ b/src/view/sorting-view.js @@ -2,11 +2,11 @@ import { SortingTypes } from '../const.js'; import AbstractView from '../framework/view/abstract-view.js'; import { capitalize } from '../util.js'; -const findCheckedElement = (element) => element === 'price' ? 'checked' : ''; +// const findCheckedElement = (element) => element === 'day' ? 'checked' : ''; const createSortingElement = (sortingType) => `
- diff --git a/src/view/trip-point-view.js b/src/view/trip-point-view.js index c7bde7a..37b9373 100644 --- a/src/view/trip-point-view.js +++ b/src/view/trip-point-view.js @@ -34,7 +34,7 @@ const createScheduleTemplate = (point) => { —

-

${findDuration(dateTo, dateFrom)}

+

${findDuration(point)}

€ ${basePrice} From 74bc99d2bbd925d789c2fab07f188d6c217d6491 Mon Sep 17 00:00:00 2001 From: InsomniaRolodex Date: Wed, 21 Aug 2024 00:11:30 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=91=D0=BE=D0=BB=D1=8C=D1=88=D0=B8=D0=B5?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D1=8B=20(=D1=87?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D1=8C=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 4 ++-- src/presenter/trip-presenter.js | 11 +++++------ src/view/sorting-view.js | 13 +++---------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/src/const.js b/src/const.js index d872d98..bf115f8 100644 --- a/src/const.js +++ b/src/const.js @@ -1,8 +1,8 @@ -const SortingTypes = { +const SortingType = { DAY: 'day', EVENT: 'event', TIME: 'time', PRICE: 'price', OFFERS: 'offers'}; -export {SortingTypes}; +export {SortingType}; diff --git a/src/presenter/trip-presenter.js b/src/presenter/trip-presenter.js index 46ab5b1..97d0d9c 100644 --- a/src/presenter/trip-presenter.js +++ b/src/presenter/trip-presenter.js @@ -6,7 +6,7 @@ import ListEmptyView from '../view/list-empty-view.js'; import PointModel from '../model/point-model.js'; import PointPresenter from './point-presenter.js'; import { updateItem, sortPointsByDay, findSortingDuration } from '../util.js'; -import { SortingTypes } from '../const.js'; +import { SortingType } from '../const.js'; export default class TripPresenter { @@ -18,7 +18,7 @@ export default class TripPresenter { #destinations; #offers; #sortingComponent; - #currentSortingType = SortingTypes.PRICE; + #currentSortingType = SortingType.PRICE; #sourcedPointsOrder = []; constructor ({ container, pointModel = new PointModel }) { @@ -60,13 +60,13 @@ export default class TripPresenter { #sortPoints(sortingType) { switch (sortingType) { - case SortingTypes.DAY: + case SortingType.DAY: this.#points.sort(sortPointsByDay); break; - case SortingTypes.PRICE: + case SortingType.PRICE: this.#points.sort((pointA, pointB) => pointA.basePrice - pointB.basePrice); break; - case SortingTypes.TIME: + case SortingType.TIME: this.#points.sort((pointA, pointB) => findSortingDuration(pointA) - findSortingDuration(pointB)); break; @@ -82,7 +82,6 @@ export default class TripPresenter { } this.#sortPoints(sortingType); this.#clearPointList(); - this.#renderSorting(); this.#points.forEach((point) => this.#renderPoint(point, this.#destinations, this.#offers)); } diff --git a/src/view/sorting-view.js b/src/view/sorting-view.js index 765b8a9..a7d9c37 100644 --- a/src/view/sorting-view.js +++ b/src/view/sorting-view.js @@ -1,9 +1,7 @@ -import { SortingTypes } from '../const.js'; +import { SortingType } from '../const.js'; import AbstractView from '../framework/view/abstract-view.js'; import { capitalize } from '../util.js'; -// const findCheckedElement = (element) => element === 'day' ? 'checked' : ''; - const createSortingElement = (sortingType) => `

` const createSortingTemplate = () => `
- ${Object.values(SortingTypes).map((sortingType) => createSortingElement(sortingType)).join('')} + ${Object.values(SortingType).map((sortingType) => createSortingElement(sortingType)).join('')}
`; export default class SortingView extends AbstractView{ @@ -24,7 +22,7 @@ export default class SortingView extends AbstractView{ constructor ({onSortTypeChange}) { super(); this.#handleSortTypeChange = onSortTypeChange; - this.element.addEventListener('click', this.#sortTypeChangeHandler); + this.element.addEventListener('change', this.#sortTypeChangeHandler); } get template () { @@ -32,11 +30,6 @@ export default class SortingView extends AbstractView{ } #sortTypeChangeHandler = (evt) => { - if (evt.target.tagName !== 'INPUT') { - return; - } - - evt.preventDefault(); this.#handleSortTypeChange(evt.target.dataset.sortType); }; }