Тестовое задание на Angular. Создание страницы апартаментов.

Aleksandr Serenko
F.A.F.N.U.R
Published in
4 min readJul 5, 2021

В данной статье создадим страницу апартаментов, на которой выведем информацию об апартаментах, а также добавим форму бронирования.

В предыдущей статье была добавлена страница с выводом превью доступных вариантов, то теперь создадим страницу с полной информацией о выбранном варианте.

Создание RoomPage

Создадим компонент и модуль:

Информация о текущем бронировании берется из сервиса RoomManager, который получает сервисы по работе с отелями и собственниками и в результате выдает полную информацию об апартаментах (RoomExtended):

roomExtended$!: Observable<RoomExtended>;

constructor(private readonly activatedRoute: ActivatedRoute, private readonly roomManager: RoomManager) {}

ngOnInit(): void {
this.roomExtended$ = this.roomManager.roomExtended$(+this.activatedRoute.snapshot.params?.id);
}

Подробнее о RoomManager будет рассказано далее в статьях, но в данном случае приведем часть реализации сервиса, который по Room Id возвращает полную информацию об апартаментах:

roomExtended$ = (id: number): Observable<RoomExtended> =>
this.roomFacade.room$(id).pipe(
filter<any>(Boolean),
switchMap((room: Room) =>
this.buildingFacade.building$(room.building).pipe(
filter<any>(Boolean),
switchMap((building: Building) =>
this.personFacade.person$(building.person).pipe(
filter<any>(Boolean),
map((person: Person) => ({
...room,
buildingExtended: {
...building,
personExtended: person,
},
}))
)
)
)
)
);

constructor(
private readonly roomFacade: RoomFacade,
private readonly buildingFacade: BuildingFacade,
private readonly personFacade: PersonFacade
) {}

Также отметим, что ID доступного варианта берется из url с помощью ActivatedRoute:

+this.activatedRoute.snapshot.params?.id

Если в url будет невалидный id, то пользователь увидит страницу 404.

Если более детально посмотреть шаблон RoomPage, то можно увидеть, что вся информация выводится с помощью компонентов, а не просто в контексте данного шаблона.

В данном случае, это сделано специально и вот почему.

Чем больше становится компонент, тем больше логики он начинает содержать. Есть одно хорошее правило для разработки — не больше 100 строчек кода на компонент, не будь то класс, шаблон или стили.

В данном случае, RoomPage были выделены и вынесены в модули:

  • RoomPropsModule — модуль с выводом краткой информации,
  • RoomPhotoModule — модуль, который выводит фотографии,
  • RoomHeaderModule — модуль выводящий шапку,
  • RoomDetailsModule — модуль выводящий дополнительную информацию об апартаментах и собственнике,
  • RoomPersonModule — модуль выводящий информацию о собственнике,
  • RoomFeaturesModule — модуль выводящий особенности апартаментов,
  • RoomDescriptionModule — модуль выводящий описание апартаментов от собственника,
  • RoomBookingCardModule — модуль бронирования.

Данное разбиение позволило вынести всю логику работы с компонентом сделав его “легким”, в котором осталось только загрузка информации об апартаментах.

Рассмотрим более детально каждый модуль.

Создание RoomHeader

Создадим модуль и компонент:

Как видно из шаблона, компонент выводит заголовок варианта для бронирования, а также кнопку “close”, которая возвращает пользователя к главной странице.

Для перехода на главную используется NavigationService:

onBack(): void {
void this.navigationService.navigate(NavigationPath.Home);
}

NavigationService — это небольшая обертка над стандартным Router’ом, в котором есть набор алиасов, которые позволяют перемещаться по приложению по заранее определенным путям.

Формально строчка выше аналогична:

void this.router.navigate(['/']);

Подробнее о концепте NavigationService будет рассказано в следующих статьях.

Создание RoomDetails

Создадим модуль и компонент:

В данном компоненте выводим информацию о рейтинге варианта, а также информацию о собственнике.

Создание RoomPhoto

Создадим модуль и компонент:

Аналогично с BookingPage в данном компоненте имеем два шаблона, один для мобильной версии, другой для десктопной.

В десктопной версии, реализована похожая схема с ресурсом Airbnb по отображению фотографий:

<ng-template #desktopTpl>
<div automation-id="room-photos" class="room-photos" *ngIf="photos?.length">
<div class="room-photos-group">
<img automation-id="room-photo-source" class="room-photo-source" [src]="photos[0]" alt="" />
</div>
<div class="room-photos-group">
<div class="room-photos-group">
<div automation-id="room-photo-box" class="room-photo" *ngFor="let photo of photos | roomPreviewImages; let last = last">
<ng-container *ngTemplateOutlet="photoTpl; context: { photo: photo, last: last }"></ng-container>
</div>
</div>
</div>
</div>
</ng-template>

То есть сначала выводим одну большую фотографию, потом еще 4, остальные открываются в popup’е, если кликнуть по кнопке “Показать все”.

<ng-template #photoTpl let-photo="photo" let-last="last">
<div automation-id="room-photo-preview" class="room-photo-preview" [ngStyle]="photo | backgroundImage"></div>
<div class="room-photo-action" *ngIf="last">
<button automation-id="room-photo-show" class="room-photo-all" mat-raised-button (click)="onShowAll()">
<mat-icon>apps</mat-icon>
Показать все
</button>
</div>
</ng-template>

При клике вызывается событие показа диалога:

onShowAll(): void {
this.matDialog.open(RoomPhotosDialogComponent);
}

Реализация диалога:

В мобильной версии выводим только карусель:

<ng-template #mobileTpl>
<app-carousel automation-id="room-photos-carousel" class="room-photos-carousel" [images]="photos"></app-carousel>
</ng-template>

Создание RoomPerson

Создадим модуль и компонент:

Компонент выводит информацию о доступности апартаментов, а также показывает аватар собственника.

Создание RoomProps

Создадим модуль и компонент:

Данный компонент выводит детальную информацию об апартаментах, в частности о количестве комнат, ванных комнат, количестве гостей и спальных мест.

Создание RoomFeatures

Создадим модуль и компонент:

Компонент выводит информацию об апартаментах и нужен только для дизайна.

Создание RoomDescription

Создадим модуль и компонент:

Компонент выводит описание апартаментов, которое указал собственник.

И последний компонент, для бронирования апартаментов, будет рассмотрен в следующей статье.

Ссылки

Вернуться к оглавлению — Введение.

Следующая статья — Работа с формами.

Предыдущая статья — Создание страницы бронирования.

Все исходники на github/fafnur/barinb.

Группа в Medium: https://medium.com/fafnur
Группа в Vkontakte: https://vk.com/fafnur
Группа в Facebook: https://www.facebook.com/groups/fafnur/
Telegram канал: https://t.me/f_a_f_n_u_r
Twitter: https://twitter.com/Fafnur1
LinkedIn: https://www.linkedin.com/in/fafnur

--

--

Aleksandr Serenko
F.A.F.N.U.R

Senior Front-end Developer, Angular evangelist, Nx apologist, NodeJS warlock