From a94918353f395a4feb8546f2cc45b5e7d2e5e4af Mon Sep 17 00:00:00 2001 From: PavelUd Date: Mon, 27 May 2024 20:41:24 +0500 Subject: [PATCH] =?UTF-8?q?=D0=B1=D1=8B=D1=81=D1=82=D1=80=D0=BE=20=D0=B8?= =?UTF-8?q?=20=D1=87=D0=B8=D1=81=D1=82=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/const.js | 8 +++++ src/model/point-model.js | 28 ++++++++++++----- src/presenter/board-presenter.js | 14 +++++++-- src/presenter/new-point-presenter.js | 19 ++++++++++++ src/presenter/point-presenter.js | 7 +++++ src/service/points-api-service.js | 21 +++++++++++-- src/view/point-edit-view.js | 45 +++++++++++++++------------- 7 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/const.js b/src/const.js index 25480c0..33eeb84 100644 --- a/src/const.js +++ b/src/const.js @@ -28,6 +28,14 @@ export const Method = { DELETE: 'DELETE', }; +export const ButtonLabel = { + CANCEL: 'Cancel', + DELETE: 'Delete', + SAVE: 'Save', + DELETE_IN_PROGRESS: 'Deleting...', + SAVE_IN_PROGRESS: 'Saving...' +}; + export const UpdateType = { INIT: 'INIT', PATCH: 'PATCH', diff --git a/src/model/point-model.js b/src/model/point-model.js index 9516d2d..feb2873 100644 --- a/src/model/point-model.js +++ b/src/model/point-model.js @@ -41,10 +41,17 @@ export default class PointsModel extends Observable { return this.#points.find((point) => point.id === id); } - add(type, point) { - const newPoint = this.#service.addPoint(point); - this.#points.push(newPoint); - this._notify(type, newPoint); + async add(type, point) { + try { + const adaptedToServerPoint = adaptToServer(point); + const newPoint = await this.#service.addPoint(adaptedToServerPoint); + const adaptedToClientPoint = adaptToClient(newPoint); + + this.#points.push(adaptedToClientPoint); + this._notify(type, adaptedToClientPoint); + } catch { + throw new Error('Can\'t add point'); + } } async update(type, point) { @@ -59,9 +66,14 @@ export default class PointsModel extends Observable { } } - delete(type, deletedPoint) { - this.#service.deletePoint(deletedPoint); - this.#points = this.#points.filter((point) => point.id !== deletedPoint.id); - this._notify(type); + async delete(type, deletedPoint) { + try { + const adaptedToServerPoint = adaptToServer(deletedPoint); + await this.#service.deletePoint(adaptedToServerPoint); + this.#points = this.#points.filter((point) => point.id !== deletedPoint.id); + this._notify(type); + } catch { + throw new Error('Can\'t delete point'); + } } } diff --git a/src/presenter/board-presenter.js b/src/presenter/board-presenter.js index 3f5f416..e0977ea 100644 --- a/src/presenter/board-presenter.js +++ b/src/presenter/board-presenter.js @@ -142,7 +142,12 @@ export default class BoardPresenter { this.#uiBlocker.block(); switch (action) { case UserAction.ADD_POINT: - this.#pointsModel.add(updateType, point); + this.#newPointPresenter.setSaving(); + try { + await this.#pointsModel.add(updateType, point); + } catch { + this.#newPointPresenter.setAborting(); + } break; case UserAction.UPDATE_POINT: this.#pointPresenters.get(point.id).setSaving(); @@ -154,7 +159,12 @@ export default class BoardPresenter { } break; case UserAction.DELETE_POINT: - this.#pointsModel.delete(updateType, point); + this.#pointPresenters.get(point.id).setDeleting(); + try { + await this.#pointsModel.delete(updateType, point); + } catch { + this.#pointPresenters.get(point.id).setAborting(); + } break; } diff --git a/src/presenter/new-point-presenter.js b/src/presenter/new-point-presenter.js index 889a32c..5b9eeb2 100644 --- a/src/presenter/new-point-presenter.js +++ b/src/presenter/new-point-presenter.js @@ -63,6 +63,25 @@ export default class NewPointPresenter { this.destroy({ isCanceled: false }); }; + setSaving = () => { + this.#newPointElement.updateElement({ + isDisabled: true, + isSaving: true, + }); + }; + + setAborting = () => { + this.#newPointElement.shake(this.#resetFormState); + }; + + #resetFormState = () => { + this.#newPointElement.updateElement({ + isDisabled: false, + isSaving: false, + isDeleting: false, + }); + }; + #onCloseForm = () => { this.destroy(); }; diff --git a/src/presenter/point-presenter.js b/src/presenter/point-presenter.js index 309d771..10bca7b 100644 --- a/src/presenter/point-presenter.js +++ b/src/presenter/point-presenter.js @@ -122,6 +122,13 @@ export default class PointPresenter { } }; + setDeleting = () => { + this.#editPointElement.updateElement({ + isDisabled: true, + isDeleting: true + }); + }; + destroy = () => { remove(this.#editPointElement); remove(this.#pointElement); diff --git a/src/service/points-api-service.js b/src/service/points-api-service.js index c9a5579..f88a9ec 100644 --- a/src/service/points-api-service.js +++ b/src/service/points-api-service.js @@ -28,6 +28,23 @@ export default class PointsApiService extends ApiService return ApiService.parseResponse(response); } - addPoint = (point) => ({...point, id: crypto.randomUUID()}); - deletePoint = () => {}; + async addPoint(point) { + const response = await this._load({ + url: 'points', + method: Method.POST, + body: JSON.stringify(point), + headers: new Headers({ + 'Content-Type': 'application/json', + }), + }); + + return ApiService.parseResponse(response); + } + + async deletePoint(point) { + await this._load({ + url: `points/${point.id}`, + method: Method.DELETE, + }); + } } diff --git a/src/view/point-edit-view.js b/src/view/point-edit-view.js index a5436a9..e5c80cf 100644 --- a/src/view/point-edit-view.js +++ b/src/view/point-edit-view.js @@ -1,8 +1,7 @@ -import { POINT_EMPTY, TYPES,EditType } from '../const.js'; +import { POINT_EMPTY, TYPES,EditType, ButtonLabel } from '../const.js'; import AbstractStatefulView from '../framework/view/abstract-stateful-view.js'; import {formatToSlashDate} from '../utils/utils.js'; import CalendarView from './calendar-view.js'; -import he from 'he'; const DEFAULT_TYPE = 'flight'; @@ -58,13 +57,18 @@ function createOfferSelector(pointOffers, offersArray){ return offersElements; } -function createSaveButton() { - return ''; +function createSaveButton({isDisabled, isSaving}) { + const saveLabel = isSaving ? ButtonLabel.SAVE_IN_PROGRESS : ButtonLabel.SAVE; + return ``; } -function createDeleteButton({type}){ - const label = type === EditType.CREATING ? 'Cancel' : 'Delete'; - return ``; +function createDeleteButton({isDisabled, type, isDeleting}){ + + let label = type === EditType.CREATING ? ButtonLabel.CANCEL : ButtonLabel.DELETE; + if(label === ButtonLabel.DELETE && isDeleting){ + label = ButtonLabel.DELETE_IN_PROGRESS; + } + return ``; } function createRollupButton(){ @@ -73,21 +77,22 @@ function createRollupButton(){ `; } -function createPointControls({type}){ - return `${createSaveButton()} - ${createDeleteButton({type})} +function createPointControls({type, isDeleting, isSaving, isDisabled}){ + return `${createSaveButton(isSaving, isDisabled)} + ${createDeleteButton({type, isDeleting})} ${type === EditType.CREATING ? '' : createRollupButton()}`; } function createPointEditElement({state, destinations, offers, pointType}) { - const { point } = state; + const { point, isDeleting, isDisabled, isSaving } = state; const pointDestination = destinations.find((destination) => destination.id === point.destination); const pointOffers = offers.find((subOffers) => subOffers.type === point.type)?.offers; - const name = pointType === EditType.CREATING ? '' : he.encode(pointDestination.name); + const name = pointDestination === undefined ? '' : pointDestination.name; + const {basePrice} = point; - const type = pointType === EditType.CREATING ? DEFAULT_TYPE : point.type; - const dateFrom = pointType === EditType.CREATING ? '' : formatToSlashDate(point.dateFrom); - const dateTo = pointType === EditType.CREATING ? '' : formatToSlashDate(point.dateTo); + const type = point.type === null ? DEFAULT_TYPE : point.type; + const dateFrom = point.dateFrom === null ? '' : formatToSlashDate(point.dateFrom); + const dateTo = point.dateTo === null ? '' : formatToSlashDate(point.dateTo); return `
  • @@ -112,24 +117,24 @@ function createPointEditElement({state, destinations, offers, pointType}) { ${type} - + ${createDestinationList(destinations)}
    - + - +
    - +
    - ${createPointControls({type : pointType})} + ${createPointControls({type : pointType, isDeleting: isDeleting, isDisabled: isDisabled, isSaving: isSaving})}
    ${createOfferSelector(point?.offers, pointOffers)}