Тестовое задание на Angular. Создание страницы апартаментов.
В данной статье создадим страницу апартаментов, на которой выведем информацию об апартаментах, а также добавим форму бронирования.
В предыдущей статье была добавлена страница с выводом превью доступных вариантов, то теперь создадим страницу с полной информацией о выбранном варианте.
Создание 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