Extract search bar into a standalone component and fix header design.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<div>
|
<div class="left">
|
||||||
<button type="button" (click)="sideMenu.open()">
|
<button type="button" (click)="sideMenu.open()" matTooltip="Click to show side menu">
|
||||||
<mat-icon>menu</mat-icon>
|
<mat-icon>menu</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
<a [routerLink]="['/home']">
|
<a [routerLink]="['/home']">
|
||||||
@@ -7,15 +7,12 @@
|
|||||||
<span class="title">Codiki</span>
|
<span class="title">Codiki</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div class="search-bar">
|
<div class="middle">
|
||||||
<input name="search-query" placeholder="Search something..." />
|
<app-publications-search-bar></app-publications-search-bar>
|
||||||
<button type="button">
|
|
||||||
<mat-icon>search</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
|
<div class="right">
|
||||||
<ng-container *ngIf="isAuthenticated; else anonymousRightMenu">
|
<ng-container *ngIf="isAuthenticated; else anonymousRightMenu">
|
||||||
<a [routerLink]="['/disconnect']" class="button" matRipple>Disconnect</a>
|
<a [routerLink]="['/disconnect']" class="button" matRipple>Disconnect</a>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|||||||
@@ -14,15 +14,17 @@ $headerHeight: 3.5em;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
height: $headerHeight;
|
height: $headerHeight;
|
||||||
|
|
||||||
&:nth-child(1) {
|
&.left {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background-color: #3f51b5;
|
background-color: #3f51b5;
|
||||||
@@ -70,15 +72,19 @@ $headerHeight: 3.5em;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(2) {
|
&.middle {
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.search-bar {
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
$borderRadiusValue: 10em;
|
$borderRadiusValue: 10em;
|
||||||
position: relative;
|
position: relative;
|
||||||
max-width: 12em;
|
|
||||||
transition: max-width .2s ease-in-out;
|
transition: max-width .2s ease-in-out;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
app-publications-search-bar {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 12em;
|
||||||
|
|
||||||
@media screen and (min-width: 435px) {
|
@media screen and (min-width: 435px) {
|
||||||
max-width: 16em;
|
max-width: 16em;
|
||||||
@@ -107,41 +113,14 @@ $headerHeight: 3.5em;
|
|||||||
@media screen and (min-width: 1100px) {
|
@media screen and (min-width: 1100px) {
|
||||||
max-width: 50em;
|
max-width: 50em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
|
||||||
flex: 1;
|
|
||||||
width: 60%;
|
|
||||||
max-width: 50em;
|
|
||||||
border-radius: $borderRadiusValue;
|
|
||||||
background-color: white;
|
|
||||||
border: solid 1px #ddd;
|
|
||||||
padding: .2em 2.7em .2em 1em;
|
|
||||||
height: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
position: absolute;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: $borderRadiusValue;
|
|
||||||
background-color: white;
|
|
||||||
border: none;
|
|
||||||
margin: .5em 0;
|
|
||||||
right: 1.1em;
|
|
||||||
color: #aaaaaa;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #eee;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(3) {
|
&.right {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -6,18 +6,36 @@ import { AuthenticationService } from '../../core/service/authentication.service
|
|||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { SideMenuComponent } from '../side-menu/side-menu.component';
|
import { SideMenuComponent } from '../side-menu/side-menu.component';
|
||||||
import { MatRippleModule } from '@angular/material/core';
|
import { MatRippleModule } from '@angular/material/core';
|
||||||
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { PublicationsSearchBarComponent } from '../publications-search-bar/publications-search-bar.component';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-header',
|
selector: 'app-header',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [CommonModule, MatButtonModule, MatIconModule, RouterModule, SideMenuComponent, MatRippleModule],
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatIconModule,
|
||||||
|
RouterModule,
|
||||||
|
SideMenuComponent,
|
||||||
|
MatRippleModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
PublicationsSearchBarComponent,
|
||||||
|
MatTooltipModule
|
||||||
|
],
|
||||||
templateUrl: './header.component.html',
|
templateUrl: './header.component.html',
|
||||||
styleUrl: './header.component.scss',
|
styleUrl: './header.component.scss',
|
||||||
})
|
})
|
||||||
export class HeaderComponent {
|
export class HeaderComponent {
|
||||||
private authenticationService = inject(AuthenticationService);
|
private authenticationService = inject(AuthenticationService);
|
||||||
|
searchControl = new FormControl('');
|
||||||
|
|
||||||
get isAuthenticated(): boolean {
|
get isAuthenticated(): boolean {
|
||||||
return this.authenticationService.isAuthenticated();
|
return this.authenticationService.isAuthenticated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
searchPublications(): void {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<form [formGroup]="formGroup">
|
||||||
|
<input name="search-query" placeholder="Search something..." formControlName="criteria"/>
|
||||||
|
<button type="submit" (click)="searchPublications()">
|
||||||
|
<mat-icon>search</mat-icon>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
:host {
|
||||||
|
$borderRadiusValue: 10em;
|
||||||
|
position: relative;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
input {
|
||||||
|
flex: 1;
|
||||||
|
border-radius: $borderRadiusValue;
|
||||||
|
background-color: white;
|
||||||
|
border: solid 1px #ddd;
|
||||||
|
padding: .2em 2.7em .2em 1em;
|
||||||
|
height: 2em;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: $borderRadiusValue;
|
||||||
|
background-color: white;
|
||||||
|
border: none;
|
||||||
|
top: .4em;
|
||||||
|
right: 0;
|
||||||
|
color: #aaaaaa;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #eee;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { HttpParams } from "@angular/common/http";
|
||||||
|
import { Component, inject } from "@angular/core";
|
||||||
|
import { FormBuilder, FormControl, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
import { MatIconModule } from "@angular/material/icon";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-publications-search-bar',
|
||||||
|
templateUrl: './publications-search-bar.component.html',
|
||||||
|
styleUrl: './publications-search-bar.component.scss',
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatIconModule
|
||||||
|
],
|
||||||
|
providers: []
|
||||||
|
})
|
||||||
|
export class PublicationsSearchBarComponent {
|
||||||
|
private formBuilder = inject(FormBuilder);
|
||||||
|
private router = inject(Router);
|
||||||
|
formGroup = this.formBuilder.group({
|
||||||
|
criteria: new FormControl<string | undefined>('', [Validators.required])
|
||||||
|
});
|
||||||
|
|
||||||
|
searchPublications(): void {
|
||||||
|
let queryParams = new HttpParams();
|
||||||
|
queryParams = queryParams.set('query', this.formGroup.controls.criteria.value ?? '');
|
||||||
|
this.router.navigate(['/publications'], {queryParams});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { HttpParams } from "@angular/common/http";
|
||||||
|
import { inject, Injectable } from "@angular/core";
|
||||||
|
import { Router } from "@angular/router";
|
||||||
|
import { BehaviorSubject } from "rxjs";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PublicationsSearchBarService {
|
||||||
|
private router = inject(Router);
|
||||||
|
private criteriaSubject = new BehaviorSubject<string>('');
|
||||||
|
|
||||||
|
private cri
|
||||||
|
|
||||||
|
searchPublications(): void {
|
||||||
|
let queryParams = new HttpParams();
|
||||||
|
queryParams = queryParams.set('query', this.criteriaSubject.value);
|
||||||
|
this.router.navigate(['/publications'], {queryParams});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user