Если посмотреть на исходный проект, то можно увидеть, что нам необходимо создать одну главную страницу.
Результаты поиска авиабилетов, отелей и туров отличаются лишь формой. Поэтому нету смысла делать несколько реализаций.
Создадим библиотеку:
mkdir src/app/home
mkdir src/app/home/page
mkdir src/app/home/page/lib
echo >src/app/home/page/index.ts
Генерируем компонент:
yarn ng g c home-page
Так как блоки на главной могут меняться, вынесем их отдельно в home/ui
.
mkdir src/app/home/ui
mkdir src/app/home/ui/widgets
mkdir src/app/home/ui/widgets/lib
echo >src/app/home/ui/widgets/index.ts
Укажем алиасы:
"@baf/home/page": ["src/app/home/page/index.ts"],
"@baf/home/ui/widgets": ["src/app/home/ui/widgets/index.ts"],
Рассмотрим ConnectComponent
.
Запустим команду:
yarn ng g c connect
Разметка:
<h2 baf-headline i18n="Connect|Title">We are always in touch</h2>
<baf-card>
<div>
<h3 baf-title i18n="Connect|Question">Have a question - write</h3>
<p i18n="Connect|Desctiption">For example, if you need help choosing a ticket or paying</p>
<p>
<a baf-button bafMode="primary" bafSize="large" [routerLink]="paths.faq | path" i18n="Connect|Write">Write</a>
</p>
</div>
<img ngSrc="/images/home/connect.svg" width="160" height="160" alt="connect" />
</baf-card>
Немного стилей:
@use 'src/stylesheets/device' as device;
.baf-card {
display: flex;
flex-direction: column-reverse;
img {
max-width: 10rem;
aspect-ratio: 1;
}
@include device.media-tablet-up() {
flex-direction: row;
justify-content: space-between;
}
}
Логика:
import { NgOptimizedImage } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterLink } from '@angular/router';
import { PathPipe, PATHS } from '@baf/core';
import { AnchorComponent } from '@baf/ui/buttons';
import { CardComponent } from '@baf/ui/cards';
import { HeadlineComponent } from '@baf/ui/headline';
import { TitleComponent } from '@baf/ui/title';
@Component({
selector: 'baf-connect',
standalone: true,
imports: [NgOptimizedImage, TitleComponent, HeadlineComponent, CardComponent, AnchorComponent, RouterLink, PathPipe],
templateUrl: './connect.component.html',
styleUrl: './connect.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ConnectComponent {
readonly paths = PATHS;
}
SVG:
<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
<path
d="M118.9 388.7h328.6c14.3 0 25.9 11.6 25.9 25.9v208.7c0 14.3-11.6 25.9-25.9 25.9H275.6l-52.1 50.1-54.1-50.1h-50.5c-14.3 0-25.9-11.6-25.9-25.9V414.6c0-14.3 11.6-25.9 25.9-25.9z"
fill="#bdd0fb"
/>
<path
d="M223.5 699.2l-54.1-50.1h-50.5c-14.3 0-25.9-11.6-25.9-25.9V414.6c0-14.3 11.6-25.9 25.9-25.9h328.7c14.3 0 25.9 11.6 25.9 25.9v208.7c0 14.3-11.6 25.9-25.9 25.9H275.7l-52.2 50z m-91.7-88.9h52.8l38.4 35.5 37-35.5h174.6V427.5H131.8v182.8z"
fill="#333333"
/>
<path
d="M321.6 267.9h508.9c14.3 0 25.9 11.6 25.9 25.9v399c0 14.3-11.6 25.9-25.9 25.9h-177L584 785.5l-72.2-66.8H321.5c-14.3 0-25.9-11.6-25.9-25.9v-399c0.1-14.3 11.7-25.9 26-25.9z"
fill="#FFFFFF"
/>
<path
d="M584.4 821.1l-82.6-76.5H321.6c-28.5 0-51.8-23.2-51.8-51.8v-399c0-28.5 23.2-51.8 51.8-51.8h508.9c28.5 0 51.8 23.2 51.8 51.8v399c0 28.5-23.2 51.8-51.8 51.8H663.9l-79.5 76.5zM321.6 293.8v399H522l61.7 57.1 59.4-57.1h187.4v-399H321.6z"
fill="#333333"
/>
<path
d="M642.2 509.5H582l-0.2 10.9c-0.3 14.1-11.8 25.4-25.9 25.4h-0.1c-13.8 0-25-11.2-25-25v-0.5l0.7-37.1c0.3-13.8 11.3-24.9 24.9-25.4 0.8-0.1 1.6-0.1 2.4-0.1h57.3v-47.4H520c-14.3 0-25.9-11.6-25.9-25.9s11.6-25.9 25.9-25.9H642c14.3 0 25.9 11.6 25.9 25.9v99.2c0 14.2-11.5 25.7-25.7 25.9z m-112.3 96.1V603c0-14.3 11.6-25.9 25.9-25.9s25.9 11.6 25.9 25.9v2.6c0 14.3-11.6 25.9-25.9 25.9s-25.9-11.6-25.9-25.9z"
fill="#e1473d"
/>
</svg>
Аналогично для всех остальных виджетов.
Как видно из примера, используется локализация. Чтобы она заработала необходимо импортировать @angular/localize
.
yarn ng add @angular/localize
Либо все сделать руками.
В package.json
добавляем пакет - @angular/localize
.
Затем в файлы main.ts
и main.server.ts
указываем типизацию:
/// <reference types="@angular/localize" />
Расширяем полифилы:
{
"polyfills": ["zone.js", "@angular/localize/init"]
}
Немного меняем tsconfig.app.json и tsconfig.spec.json:
{
"types": ["node", "@angular/localize"]
}
Выводим виджеты на главной:
<baf-container>
<baf-promo />
<router-outlet name="form" />
</baf-container>
<baf-section>
<baf-container>
<baf-must-buy />
<baf-traveling />
<baf-convenient-with-us />
<baf-connect />
</baf-container>
</baf-section>
<baf-section bafColor="smoke">
<baf-container>
<baf-questions />
</baf-container>
</baf-section>
Подключим их:
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import {
ConnectComponent,
ConvenientWithUsComponent,
MustBuyComponent,
PromoComponent,
QuestionsComponent,
TravelingComponent,
} from '@baf/home/ui/widgets';
import { ContainerComponent } from '@baf/ui/container';
import { SectionComponent } from '@baf/ui/section';
@Component({
selector: 'baf-home-page',
standalone: true,
imports: [
RouterOutlet,
ContainerComponent,
SectionComponent,
PromoComponent,
MustBuyComponent,
TravelingComponent,
ConvenientWithUsComponent,
ConnectComponent,
QuestionsComponent,
],
templateUrl: './home-page.component.html',
styleUrl: './home-page.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class HomePageComponent {}
Теперь страницы:
mkdir src/app/routes
echo >src/app/routes/home.routes.ts
Создаем роуты:
import type { Routes } from '@angular/router';
import { PATHS } from '@baf/core';
export const homeRoutes: Routes = [
{
path: PATHS.homeAvia,
loadComponent: () => import('@baf/home/page').then((m) => m.HomePageComponent),
},
{
path: PATHS.homeHotels,
loadComponent: () => import('@baf/home/page').then((m) => m.HomePageComponent),
},
{
path: PATHS.homeTours,
loadComponent: () => import('@baf/home/page').then((m) => m.HomePageComponent),
},
{
path: PATHS.homeRailways,
loadComponent: () => import('@baf/home/page').then((m) => m.HomePageComponent),
},
];
В app.routes.ts
:
{
path: '',
loadChildren: () => import('./routes/home.routes').then((m) => m.homeRoutes),
}
Запустим наше приложение.
Errors
Если пользователь перейдет по ссылке, которой не существует, то в дефолте роутер выбросит исключение
Создадим библиотеку, где разместим базовые HTTP
ошибки: 403, 404 и 500.
mkdir src/app/errors
mkdir src/app/errors/not-found
mkdir src/app/errors/not-found/page
mkdir src/app/errors/not-found/page/lib
echo >src/app/errors/not-found/page/index.ts
mkdir src/app/errors/permission-denied
mkdir src/app/errors/permission-denied/page
mkdir src/app/errors/permission-denied/page/lib
echo >src/app/errors/permission-denied/page/index.ts
mkdir src/app/errors/server-error
mkdir src/app/errors/server-error/page
mkdir src/app/errors/server-error/page/lib
echo >src/app/errors/server-error/page/index.ts
Все страницы будут похожими.
Накидаем шаблон для not-found
:
<baf-container bafAlign="center">
<h1 baf-headline>404</h1>
<h3 baf-title i18n="Not Found|Title">Page not found</h3>
<baf-errors-links />
</baf-container>
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ErrorsLinkComponent } from '@baf/errors/ui/links';
import { ContainerComponent } from '@baf/ui/container';
import { HeadlineComponent } from '@baf/ui/headline';
import { TitleComponent } from '@baf/ui/title';
@Component({
selector: 'baf-not-found-page',
standalone: true,
imports: [ContainerComponent, HeadlineComponent, TitleComponent, ErrorsLinkComponent],
templateUrl: './not-found-page.component.html',
styleUrls: ['./not-found-page.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NotFoundPageComponent {}
Добавим общий компонент с ссылками:
mkdir src/app/errors/ui
mkdir src/app/errors/ui/lib
echo >src/app/errors/ui/index.ts
Запустим команду:
yarn ng g c errors-link
Перенесем errors-link
в src/app/errors/ui/lib
.
<p i18n="Not Found|Perhaps you were looking for pages">Perhaps you were looking for pages</p>
<baf-nav [links]="links"></baf-nav>
import { ChangeDetectionStrategy, Component } from '@angular/core';
import type { NavigationLink } from '@baf/core';
import { PATHS } from '@baf/core';
import { NavComponent } from '@baf/ui/nav';
@Component({
selector: 'baf-errors-links',
standalone: true,
imports: [NavComponent],
templateUrl: './errors-link.component.html',
styleUrls: ['./errors-link.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ErrorsLinkComponent {
readonly links: NavigationLink[] = [
{
route: PATHS.home,
label: 'home',
},
{
route: PATHS.documents,
label: 'Documents',
},
];
}
Определим пути до ошибок errors.routes.ts
:
import type { Routes } from '@angular/router';
import { PATHS } from '@baf/core';
export const errorsRoutes: Routes = [
{
path: PATHS.permissionDenied,
title: 'Permission Denied',
loadComponent: () => import('@baf/errors/permission-denied/page').then((m) => m.PermissionDeniedPageComponent),
},
{
path: PATHS.serverError,
title: 'Internal Server Error',
loadComponent: () => import('@baf/errors/server-error/page').then((m) => m.ServerErrorPageComponent),
},
{
path: '**',
title: 'Page not found',
loadComponent: () => import('@baf/errors/not-found/page').then((m) => m.NotFoundPageComponent),
},
];
Подключим в app.routes.ts
:
export const routes: Routes = [
{
path: '',
loadComponent: () => import('@baf/ui/layout').then((m) => m.LayoutComponent),
children: [
//…
{
path: '',
loadChildren: () => import('./routes/errors.routes').then((m) => m.errorsRoutes),
},
],
},
];
Раздел в разработке
Добавим техническую страницу, которая будет использоваться как заглушка.
mkdir src/app/development
mkdir src/app/development/page
mkdir src/app/development/page/lib
echo >src/app/development/page/index.ts
Накидаем компонент:
<baf-container>
<h1 baf-headline i18n="Development Page|Title">Page is under construction</h1>
<p i18n="Development Page|Description">
This section is currently under development and will be available soon. We are working diligently to bring you new and exciting content,
packed with features and improvements to enhance your experience. Please check back later for updates. We appreciate your patience and
look forward to unveiling this new section shortly. Thank you for your understanding and support!
</p>
<img ngSrc="/images/development.svg" width="379" height="379" sizes="(min-width: 0) 33vw" alt="" priority />
</baf-container>
:host {
position: relative;
display: block;
img {
height: auto;
}
}
import { NgOptimizedImage } from '@angular/common';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ContainerComponent } from '@baf/ui/container';
import { HeadlineComponent } from '@baf/ui/headline';
@Component({
selector: 'baf-development-page',
standalone: true,
imports: [NgOptimizedImage, ContainerComponent, HeadlineComponent],
templateUrl: './development-page.component.html',
styleUrl: './development-page.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DevelopmentPageComponent {}
Укажем роуты в documents.routes.ts
:
import type { Routes } from '@angular/router';
import { PATHS } from '@baf/core';
export const documentsRoutes: Routes = [
{
path: PATHS.rules,
title: $localize`:Documents Rules:Rules for using the site`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.terms,
title: $localize`:Documents Terms:Conditions for participation in the program`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.documents,
title: $localize`:Documents All:Documents`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.faq,
title: $localize`:Documents FAQ:FAQ`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.cards,
title: $localize`:Cards:Application`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.login,
title: $localize`:Login Title:Sign in`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
{
path: PATHS.registration,
title: $localize`:Registration Title:Sign up`,
loadComponent: () => import('@baf/development/page').then((m) => m.DevelopmentPageComponent),
},
];
Подключим все маршруты в app.routes.ts
.
Дальше займемся реализацией поиска.
Ссылки
Все исходники находятся на github, в репозитории - github.com/Fafnur/buy-and-fly
Демо можно посмотреть здесь - buy-and-fly.fafn.ru/
Top comments (0)