Home  >  Article  >  Web Front-end  >  Development of application pages

Development of application pages

DDD
DDDOriginal
2024-09-13 22:15:02624browse

Разработка страниц приложения

If you look at the original project, you can see that we need to create one main page.

Search results for flights, hotels and tours differ only in form. Therefore, there is no point in making multiple implementations.

Let's create a library:

mkdir src/app/home
mkdir src/app/home/page
mkdir src/app/home/page/lib
echo >src/app/home/page/index.ts

Generate the component:

yarn ng g c home-page

Since the blocks on the main page can change, we will move them separately to 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

Specify aliases:

"@baf/home/page": ["src/app/home/page/index.ts"], 
"@baf/home/ui/widgets": ["src/app/home/ui/widgets/index.ts"],

Consider ConnectComponent.
Let's run the command:

yarn ng g c Development of application pages

Marking:

<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" path i18n="Connect|Write">Write</a>
    </p>
  </div>
  <img ngsrc="/images/home/Development of application pages.svg"    style="max-width:90%"  style="max-width:90%" alt="Development of application pages">
</baf-card>

A few styles:

@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;
  }
}

Logic:

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-Development of application pages',
  standalone: true,
  imports: [NgOptimizedImage, TitleComponent, HeadlineComponent, CardComponent, AnchorComponent, RouterLink, PathPipe],
  templateUrl: './Development of application pages.component.html',
  styleUrl: './Development of application pages.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>
  <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>
  <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>
  <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>
  <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"></path>
</svg>

Similarly for all other widgets.

As can be seen from the example, localization is used. For it to work you need to import @angular/localize.

yarn ng add @angular/localize

Or do everything by hand.

Add the package to package.json - @angular/localize.

Then we specify the typing in the main.ts and main.server.ts files:

/// <reference types="@angular/localize"></reference>

Expanding polyfills:

{
  "polyfills": ["zone.js", "@angular/localize/init"]
}

Change tsconfig.app.json and tsconfig.spec.json a little:

{
  "types": ["node", "@angular/localize"]
}

Display widgets on the main page:

<baf-container>
  <baf-promo></baf-promo>
  <router-outlet name="form"></router-outlet>
</baf-container>
<baf-section>
  <baf-container>
    <baf-must-buy></baf-must-buy>
    <baf-traveling></baf-traveling>
    <baf-convenient-with-us></baf-convenient-with-us>
    <baf-development of application pages></baf-development>
  </baf-container>
</baf-section>
<baf-section bafcolor="smoke">
  <baf-container>
    <baf-questions></baf-questions>
  </baf-container>
</baf-section>

Let's Development of application pages them:

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 {}

Now pages:

mkdir src/app/routes
echo >src/app/routes/home.routes.ts

Creating routes:

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),
  },
];

In app.routes.ts:

{
  path: '',
  loadChildren: () => import('./routes/home.routes').then((m) => m.homeRoutes),
}

Let's launch our application.

Errors

If the user follows a link that does not exist, then in default the router will throw an exception

Let's create a library where we will place basic HTTP errors: 403, 404 and 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

All pages will be similar.

Create a template for 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-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 {}

Add a common component with links:

mkdir src/app/errors/ui
mkdir src/app/errors/ui/lib
echo >src/app/errors/ui/index.ts

Run the command:

yarn ng g c errors-link

Move errors-link to src/app/errors/ui/lib.

<p i18n="Not Found|Perhaps you were looking for pages">Perhaps you were looking for pages</p>
<baf-nav></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',
    },
  ];
}

Let's define the paths to errors 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),
  },
];

Connect in 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),
      },
    ],
  },
];

Section under development

Let's add a technical page that will be used as a placeholder.

mkdir src/app/development
mkdir src/app/development/page
mkdir src/app/development/page/lib
echo >src/app/development/page/index.ts

Add the component:

<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"    style="max-width:90%"  style="max-width:90%" 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 {}

Specify the routes in 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),
  },
];

Connect all routes in app.routes.ts.

Next, let's implement the search.

Links

All sources are on github, in the repository - github.com/Fafnur/buy-and-fly

You can watch the demo here - buy-and-fly.fafn.ru/

My groups: telegram, medium, vk, x.com, linkedin, site

The above is the detailed content of Development of application pages. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn