Initial commit

parents
Pipeline #1833 failed with stages
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}
FROM node:22 as builder
WORKDIR /app
COPY . .
RUN npm install npm install --legacy-peer-deps
RUN npm run build || true
FROM nginx:alpine
COPY --from=builder /app/dist/login-page/browser /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
COPY mime.types /etc/nginx/mime.types
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
---
**Automatização do Aceite Técnico de Navios**
Uma aplicação Front-End desenvolvida com o framework **Angular (JavaScript)** para **facilitar** e **otimizar** o processo de aceite técnico de embarcações.
---
**COMANDOS DOCKER**
1. docker build -t login-page .
2. docker run -d -p 4200:80 --name login-container login-page
### 🎯 **Descrição**
Este projeto é uma **aplicação web** que permite aos usuários gerenciar completamente o processo de aceite técnico de navios. Com ele, você pode **criar**, **visualizar**, **editar** e **deletar** tarefas relacionadas ao processo de aceitação, proporcionando um **fluxo de trabalho eficiente** e um acompanhamento detalhado das atividades necessárias para a aprovação técnica das embarcações.
---
### 🚀 **Instalação**
1. **Clone o repositório**:
```bash
git clone https://github.com/Reirenan/Projeto_Angular_App.git
```
2. **Navegue até o diretório do projeto**:
```bash
cd Projeto_Angular_App
```
3. **Instale as dependências necessárias**:
```bash
npm install --legacy-peer-deps
```
4. **Inicie o servidor de desenvolvimento**:
```bash
ng serve
```
5. **Acesse a aplicação** no seu navegador:
🌐 [http://localhost:4200](http://localhost:4200)
---
### 🌱 **Passos para Criar uma Nova Branch no Git**
1. **Atualize o repositório local** (opcional, mas recomendado):
Antes de criar uma nova branch, é uma boa prática garantir que o repositório local esteja atualizado
com as mudanças mais recentes da branch principal (geralmente `main` ou `master`).
```bash
git checkout main
git pull origin main
```
2. **Crie uma nova branch**:
Escolha um nome para a nova branch e crie-a:
```bash
git checkout -b MinhaNovaBranch
```
3. **Verifique se está na nova branch**:
Após criar a branch, verifique se você está nela.
```bash
git branch
```
Isso deve mostrar um asterisco (`*`) ao lado da branch atual.
4. **Faça suas alterações**:
Realize as alterações necessárias nos arquivos do projeto.
5. **Adicione os arquivos modificados para o commit**:
Depois de fazer as alterações, adicione os arquivos que deseja incluir no commit:
```bash
git add .
```
Ou adicione arquivos específicos:
```bash
git add nome_do_arquivo
```
6. **Faça o commit das suas alterações**:
Agora, faça o commit das suas alterações com uma mensagem descritiva:
```bash
git commit -m 'Comentário do commit da minha nova branch'
```
7. **Envie a branch para o repositório remoto**:
Envie a nova branch para o repositório remoto, criando um link entre sua branch local e a remota:
```bash
git push --set-upstream origin MinhaNovaBranch
```
8. **Crie um Pull Request** (opcional, dependendo do fluxo de trabalho):
Se o repositório usa Pull Requests (PRs) para revisar e integrar o código, você pode criar um PR na interface do GitHub ou outro serviço de hospedagem de repositórios.
- No GitHub, vá até o repositório, e você verá a opção de criar um PR a partir da nova branch.
---
Esses passos cobrem desde a criação da branch até o envio para o repositório remoto. Dependendo do fluxo de trabalho do projeto, a criação de um Pull Request pode ser necessária para a revisão de código antes de realizar o merge com a branch principal.
Agora, a aplicação deve estar rodando localmente. Se precisar de mais informações ou orientações, estou à disposição! 😉
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"login-page": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/login-page",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "login-page:build:production"
},
"development": {
"buildTarget": "login-page:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "login-page:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": []
}
}
}
}
},
"cli": {
"analytics": false
}
}
version: '3'
services:
hurr-ui:
build: .
ports:
- "4200:4200"
volumes:
- .:/usr/src/app
- /usr/src/app/node_modules
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'dist/hurr-ui')));
app.get('/*', function (req, res) {
res.sendFile(path.join(__dirname, 'dist/hurr-ui', 'index.html'));
});
app.listen(8080, () => {
console.log('Servidor Angular rodando na porta 8080');
});
types {
text/html html htm shtml;
text/css css;
application/javascript js;
application/json json;
image/gif gif;
image/jpeg jpeg jpg;
application/xml xml;
text/xml xml;
image/png png;
}
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "login-page",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.2.0",
"@angular/cdk": "^17.3.8",
"@angular/common": "^17.2.0",
"@angular/compiler": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/forms": "^17.2.0",
"@angular/material": "^17.3.8",
"@angular/platform-browser": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@angular/router": "^17.2.0",
"chart.js": "^4.4.3",
"install": "^0.13.0",
"jwt-decode": "^4.0.0",
"ngx-currency": "^18.0.0",
"ngx-toastr": "^18.0.0",
"npm": "^11.2.0",
"primeng": "^17.17.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.2.3",
"@angular/cli": "^17.2.3",
"@angular/compiler-cli": "^17.2.0",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.3.2"
}
}
<ng-container *ngIf="token_valido">
<mat-toolbar class="mat-elevation-z3" style="background-color: #4169E1;">
<button mat-icon-button (click)="toggleCollapsed()">
<mat-icon>menu</mat-icon>
</button>
<h1>PORTO DO ITAQUÍ</h1>
<button mat-icon-button [matMenuTriggerFor]="menu" aria-label="Example icon-button with a menu" class="user-info">
<mat-icon>person</mat-icon>
</button>
<mat-menu #menu="matMenu">
<button mat-menu-item (click)="logout()">
<mat-icon>exit_to_app</mat-icon>
<span>Sair</span>
</button>
</mat-menu>
</mat-toolbar>
<mat-sidenav-container>
<mat-sidenav opened mode="side" [style.width]="sidenavWidth">
<app-custom-sidenav [collapsed]="collapsed"></app-custom-sidenav>
</mat-sidenav>
<mat-sidenav-content class="content" [style.margin-left]="sidenavWidth">
<router-outlet></router-outlet>
</mat-sidenav-content>
</mat-sidenav-container>
</ng-container>
<ng-container *ngIf="!token_valido">
<router-outlet></router-outlet>
</ng-container>
mat-toolbar {
position: relative;
z-index: 5;
color: #fff;
}
.content {
padding: 24px;
}
mat-sidenav-container {
height: calc(100vh - 60px);
}
h1 {
color: #fff;
margin: 0;
}
.user-info {
margin-left: auto;
display: flex;
align-items: center;
}
.example-spacer {
flex: 1 1 auto;
}
.user-info button {
margin-left: 10px;
}
.header-text h2 {
margin: 0;
font-size: 1rem;
line-height: 1.5rem;
}
.header-text p {
margin: 0;
font-size: 0.8rem;
}
.hide-header-text {
opacity: 0;
height: 0px;
}
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have the 'login-page' title`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, login-page');
});
});
import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { AuthService } from './auth.service';
import { JwtDecoderService } from './jwt-decoder.service';
import { Router, RouterLink, RouterOutlet } from '@angular/router';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSidenavModule } from '@angular/material/sidenav';
import { CustomSidenavComponent } from './components/custom-sidenav/custom-sidenav.component';
import { CommonModule } from '@angular/common';
import { jwtDecode } from 'jwt-decode';
import {MatMenuModule} from '@angular/material/menu';
@Component({
selector: 'app-root',
standalone: true,
imports: [
RouterLink, RouterOutlet, CommonModule,
MatToolbarModule, MatButtonModule, MatIconModule,
MatSidenavModule, CustomSidenavComponent,MatIconModule,MatMenuModule
],
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
decodedToken: any;
collapsed = false;
sidenavWidth = '250px';
authTokenPresent = false;
token_valido = false;
constructor(
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private cdr: ChangeDetectorRef,
private router:Router
) {}
ngOnInit() {
this.authService.authToken$.subscribe(isLoggedIn => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
if (token) {
this.decodedToken = jwtDecode(token);
const isExpired = this.isTokenExpired(this.decodedToken);
if (isExpired) {
sessionStorage.removeItem('accessToken');
} else {
this.decodedToken = this.jwtDecoderService.decodeToken(token);
if (this.decodedToken.role != null) {
this.token_valido = true;
}
}
}
}
this.cdr.detectChanges();
});
}
logout() {
// Remove o token do armazenamento da sessão
sessionStorage.removeItem('accessToken');
// Atualiza o estado de autenticação para falso
this.authTokenPresent = false;
this.token_valido = false;
// Redireciona para a página de login ou outra rota
this.router.navigate(['/']);
// Detecta mudanças para atualizar o componente
this.cdr.detectChanges();
}
isTokenExpired(token: any): boolean {
if (!token || !token.exp) {
return true;
}
return token.exp < Date.now() / 1000;
}
toggleCollapsed() {
this.collapsed = !this.collapsed;
this.sidenavWidth = this.collapsed ? '65px' : '250px';
this.cdr.detectChanges();
}
}
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient, withFetch, withInterceptors } from '@angular/common/http';
import { provideAnimations } from '@angular/platform-browser/animations'
import { provideToastr } from 'ngx-toastr';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { provideClientHydration } from '@angular/platform-browser';
import { customInterceptor } from './custom.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes), provideHttpClient(withInterceptors([customInterceptor])),
provideAnimations(),
provideToastr(),
provideHttpClient(withFetch()), provideAnimationsAsync(),provideClientHydration(), provideAnimationsAsync(), provideHttpClient(withFetch())
]
};
import { Routes } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { SignUpComponent } from './pages/signup/signup.component';
import { UserComponent } from './pages/user/user.component';
import { AuthGuardService } from './services/auth-guard.service';
import { NaviosComponent } from './pages/crud-navios/navios/navios.component';
import { IsAdminService } from './services/is-admin.service';
import { DashboardComponent } from './pages/dashboard/dashboard.component';
import { AceitesComponent } from './pages/crud-aceites/aceites/aceites.component';
import { LoginSignupService } from './login-signup.service';
import { BercosComponent } from './pages/crud-bercos/bercos/bercos.component';
import { BlackListComponent } from './pages/crud-blackList/black-list/black-list.component';
export const routes: Routes = [
{
path: "",
component: LoginComponent,
canActivate: [LoginSignupService]
},
{
path: "signup",
component: SignUpComponent,
canActivate: [LoginSignupService]
},
{
path:'navio',
component: NaviosComponent,
canActivate: [AuthGuardService]
},
{
path:'dashboard',
component: DashboardComponent,
canActivate: [AuthGuardService,IsAdminService]
},
{
path:'aceite',
component: AceitesComponent,
canActivate: [AuthGuardService]
},
{
path:'berco',
component: BercosComponent,
canActivate: [AuthGuardService]
},
{
path:'black-list',
component: BlackListComponent,
canActivate:[AuthGuardService,IsAdminService]
},
{
path:'users',
component: UserComponent,
canActivate:[AuthGuardService,IsAdminService]
}
];
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private authTokenSubject = new BehaviorSubject<boolean>(this.checkAuthToken());
authToken$ = this.authTokenSubject.asObservable();
constructor() {}
private checkAuthToken(): boolean {
const authToken = sessionStorage.getItem('accessToken');
return !!authToken;
}
updateAuthTokenStatus(isLoggedIn: boolean) {
this.authTokenSubject.next(isLoggedIn);
}
}
<mat-nav-list>
@for (item of menuItems(); track item) {
@if(item.role === user.role) {
<a mat-list-item
[routerLink]="item.route"
routerLinkActive
#rla="routerLinkActive"
[activated]="rla.isActive"
>
<mat-icon matListItemIcon>{{item.icon}}</mat-icon>
<span matListItemTitle *ngIf="!sideNavCollapsed()">{{item.label}}</span>
</a>
} @else if(user.role === item.role || user.role === "COMPANY"){
<a mat-list-item
[routerLink]="item.route"
routerLinkActive
#rla="routerLinkActive"
[activated]="rla.isActive"
>
<mat-icon matListItemIcon>{{item.icon}}</mat-icon>
<span matListItemTitle *ngIf="!sideNavCollapsed()">{{item.label}}</span>
</a>
}
}
</mat-nav-list>
.header-text {
> h2 {
margin: 0;
font-size: 1rem;
line-height: 1.5rem;
}
> p {
margin: 0;
font-size: 0.8rem;
}
}
.hide-header-text {
opacity: 0;
height: 0px;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CustomSidenavComponent } from './custom-sidenav.component';
describe('CustomSidenavComponent', () => {
let component: CustomSidenavComponent;
let fixture: ComponentFixture<CustomSidenavComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CustomSidenavComponent]
})
.compileComponents();
fixture = TestBed.createComponent(CustomSidenavComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, Input, OnInit, computed, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatListModule } from '@angular/material/list';
import { MatIconModule } from '@angular/material/icon';
import { RouterModule } from '@angular/router';
import { JwtDecoderService } from '../../jwt-decoder.service';
import { AuthService } from '../../auth.service';
import { jwtDecode } from 'jwt-decode';
export type MenuItem = {
icon: string;
label: string;
route?: string;
role?:string;
}
@Component({
selector: 'app-custom-sidenav',
standalone: true,
imports: [CommonModule, MatListModule, MatIconModule, RouterModule],
templateUrl: './custom-sidenav.component.html',
styleUrls: ['./custom-sidenav.component.scss']
})
export class CustomSidenavComponent implements OnInit{
user: any;
sidenavWidth = '250px';
authTokenPresent = false;
constructor(
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private cdr: ChangeDetectorRef
) {}
ngOnInit() {
this.authService.authToken$.subscribe(isLoggedIn => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp? this.user.exp < Date.now()/1000:false
if(isExpired){
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
sideNavCollapsed = signal(false);
@Input() set collapsed(val: boolean) {
this.sideNavCollapsed.set(val);
}
menuItems = signal<MenuItem[]>([
{
icon: 'dashboard',
label: 'Dashboard',
route: 'dashboard',
role: 'COMPANY',
},
{
icon: 'directions_boat',
label: 'Navios',
route: 'navio',
role: 'CANDIDATE',
},
{
icon: 'calendar_today',
label: 'Aceites',
route: 'aceite',
role: 'CANDIDATE'
},
{
icon: 'dock',
label: 'Berços',
route: 'berco',
role: 'CANDIDATE'
},
{
icon:'block',
label:'Black List',
route:'black-list',
role:'COMPANY'
},
{
icon: 'groups',
label: 'Usuários',
route: 'users',
role: 'COMPANY'
}
]);
profilePicSize = computed(() => (this.sideNavCollapsed() ? '32' : '100'));
}
<main>
<section class="form-section">
<h2>{{ title }}</h2>
<ng-content></ng-content>
<div class="btn-wrapper">
<button
class="btn-primary"
(click)="submit()"
[disabled]="disablePrimaryBtn"
>
{{ primaryBtnText }}
</button>
<div class="divider">
<div></div>
<span>or</span>
<div></div>
</div>
<button class="btn-secondary" (click)="navigate()">{{ secondaryBtnText }}</button>
</div>
</section>
</main>
@import "../../../styles/variables.scss";
main {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
height: 100%;
section {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.main-section {
gap: 8px;
flex-grow: 1;
background-color: #4169E1;
}
.form-section {
flex-grow: 0.2; /* Reduzir o crescimento flexível para tornar a seção menor */
padding: 0 20px; /* Reduzir o padding */
img {
margin-bottom: 20px; /* Reduzir a margem inferior da imagem */
width: 100%;
max-width: 250px; /* Tornar a imagem responsiva */
height: auto;
}
h2 {
font-size: 18px; /* Reduzir o tamanho da fonte */
font-weight: bold;
margin-bottom: 30px; /* Reduzir a margem inferior */
}
.btn-wrapper {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 77%;
gap: 20px; /* Reduzir o espaçamento entre os botões */
.divider {
display: flex;
align-items: center;
justify-content: center;
gap: 10px; /* Reduzir o espaçamento entre os elementos do divisor */
width: 100%;
font-size: 12px; /* Reduzir o tamanho da fonte */
color: #4169E1;
font-weight: 400;
text-transform: uppercase;
div {
flex-grow: 1;
height: 1px; /* Reduzir a altura da linha */
background-color: #4169E1;
}
}
button {
width: 100%;
border-radius: 8px;
font-size: 14px; /* Reduzir o tamanho da fonte */
font-weight: 500;
border: none;
background: transparent;
padding: 10px 20px; /* Reduzir o padding */
cursor: pointer;
&:disabled {
opacity: 0.8;
}
&.btn-primary {
background-color: #4169E1;
color: white;
box-shadow: 0px 8px 12px rgba(148, 64, 255, 0.2);
}
&.btn-secondary {
border: 1px solid #4169E1;
color: #4169E1;
}
}
}
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DefaultLoginLayoutComponent } from './default-login-layout.component';
describe('DefaultLoginLayoutComponent', () => {
let component: DefaultLoginLayoutComponent;
let fixture: ComponentFixture<DefaultLoginLayoutComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DefaultLoginLayoutComponent]
})
.compileComponents();
fixture = TestBed.createComponent(DefaultLoginLayoutComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-default-login-layout',
standalone: true,
imports: [],
templateUrl: './default-login-layout.component.html',
styleUrl: './default-login-layout.component.scss'
})
export class DefaultLoginLayoutComponent {
@Input() title: string = "";
@Input() primaryBtnText: string = "";
@Input() secondaryBtnText: string = "";
@Input() disablePrimaryBtn: boolean = true;
@Output("submit") onSubmit = new EventEmitter();
@Output("navigate") onNavigate = new EventEmitter();
submit(){
this.onSubmit.emit();
}
navigate(){
this.onNavigate.emit();
}
}
<div class="input-wrapper">
<label [for]="inputName">{{ label }}</label>
<div class="input-content">
<input
[type]="type"
[placeholder]="placeholder"
[value]="value"
(input)="onInput($event)"
/>
</div>
</div>
@import "../../../styles/variables.scss";
.input-wrapper {
color: $text-color;
font-size: 16px;
text-align: start;
label {
margin-bottom: 10px;
}
.input-content {
width: 100%;
border-radius: 8px;
display: flex;
.icon {
padding: 12px;
background-color: #4169E1;
border-radius: 0 8px 8px 0;
img {
height: 20px;
}
}
input {
border: none;
border-radius: 8px 8px 8px 8px;
background-color: #dcdcdc; // Nova cor aqui
padding: 12px 0 12px 20px;
width: 100%;
}
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { PrimaryInputComponent } from './primary-input.component';
describe('PrimaryInputComponent', () => {
let component: PrimaryInputComponent;
let fixture: ComponentFixture<PrimaryInputComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PrimaryInputComponent]
})
.compileComponents();
fixture = TestBed.createComponent(PrimaryInputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Input, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormGroup, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
type InputTypes = "text" | "email" | "password"
@Component({
selector: 'app-primary-input',
standalone: true,
imports: [
ReactiveFormsModule
],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => PrimaryInputComponent),
multi: true
}
],
templateUrl: './primary-input.component.html',
styleUrl: './primary-input.component.scss'
})
export class PrimaryInputComponent implements ControlValueAccessor {
@Input() type: InputTypes = "text";
@Input() placeholder: string = "";
@Input() label: string = "";
@Input() inputName: string = "";
value: string = ''
onChange: any = () => {}
onTouched: any = () => {}
onInput(event: Event){
const value = (event.target as HTMLInputElement).value
this.onChange(value)
}
writeValue(value: any): void {
this.value = value
}
registerOnChange(fn: any): void {
this.onChange = fn
}
registerOnTouched(fn: any): void {
this.onTouched = fn
}
setDisabledState(isDisabled: boolean): void {}
}
import { TestBed } from '@angular/core/testing';
import { CoreService } from './core.service';
describe('CoreService', () => {
let service: CoreService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CoreService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
@Injectable({
providedIn: 'root',
})
export class CoreService {
constructor(private _snackBar: MatSnackBar) {}
openSnackBar(message: string, action: string = 'ok') {
this._snackBar.open(message, action, {
duration: 10000,
verticalPosition: 'top',
});
}
openSnackBar1(message: string, action: string = 'ok') {
this._snackBar.open(message, action, {
duration: 10000,
verticalPosition: 'top',
});
}
}
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { HttpInterceptorFn } from '@angular/common/http';
import { customInterceptor } from './custom.interceptor';
describe('customInterceptor', () => {
const interceptor: HttpInterceptorFn = (req, next) =>
TestBed.runInInjectionContext(() => customInterceptor(req, next));
beforeEach(() => {
TestBed.configureTestingModule({});
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
});
import { HttpInterceptorFn } from '@angular/common/http';
import { jwtDecode } from 'jwt-decode';
export const customInterceptor: HttpInterceptorFn = (req, next) => {
const myToken = sessionStorage.getItem('accessToken');
if (myToken){
const decodedToken = jwtDecode(myToken);
const isExpired =
decodedToken && decodedToken.exp? decodedToken.exp < Date.now()/1000:false
if(isExpired){
sessionStorage.removeItem('accessToken');
}
const clonedRequest = req.clone({
setHeaders: {
Authorization: `Bearer ${myToken}`
}
});
return next(clonedRequest);
}
return next(req);
};
import { TestBed } from '@angular/core/testing';
import { JwtDecoderService } from './jwt-decoder.service';
describe('JwtDecoderService', () => {
let service: JwtDecoderService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(JwtDecoderService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class JwtDecoderService {
constructor() { }
public decodeToken(token: string) {
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64)
.split('')
.map((c) => {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
})
.join('')
);
return JSON.parse(jsonPayload);
}
}
import { TestBed } from '@angular/core/testing';
import { LoginSignupService } from './login-signup.service';
describe('LoginSignupService', () => {
let service: LoginSignupService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LoginSignupService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { JwtDecoderService } from './jwt-decoder.service';
import { ChangeDetectorRef } from '@angular/core';
import { Location } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class LoginSignupService {
private decodedToken: any;
constructor(
private jwtDecoderService: JwtDecoderService,
private location: Location
) {}
canActivate(
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const authTokenPresent = sessionStorage.getItem('accessToken');
return authTokenPresent ? this.validToken(authTokenPresent) : true;
}
validToken(authTokenPresent:string){
this.decodedToken = this.jwtDecoderService.decodeToken(authTokenPresent);
return this.decodedToken ? false : true ;
}
}
<div mat-dialog-title>
<h1>{{'Solicitar Aceite' }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="imo">
<mat-error>
<ng-container *ngIf="empForm.get('imo')?.invalid">
<ng-container *ngIf="getErrorMessage('imo') === 'Esse imo não existe'">
{{ getErrorMessage('imo') }}, se desejar soliciatar a criação de um novo navio,
<a (click)="exibirFormNavio()" style="text-decoration: underline">clique aqui!</a>
</ng-container>
<ng-container *ngIf="getErrorMessage('imo') !== 'Esse imo não existe'">
{{ getErrorMessage('imo') }}
</ng-container>
</ng-container>
</mat-error>
</mat-form-field>
<mat-form-field class="field full-width" appearance="outline">
<mat-label>MMSI</mat-label>
<input matInput type="text" formControlName="mmsi" (keydown)="preventNegative($event)">
<mat-error *ngIf="empForm.get('mmsi')?.invalid">{{ getErrorMessage('mmsi') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome">
<mat-error *ngIf="empForm.get('nome')?.invalid">{{ getErrorMessage('nome') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>LOA (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="loa">
<mat-error *ngIf="empForm.get('loa')?.invalid">{{ getErrorMessage('loa') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Boca (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="boca">
<mat-error *ngIf="empForm.get('boca')?.invalid">{{ getErrorMessage('boca') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Calado de Entrada</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="calado_entrada">
<mat-error *ngIf="empForm.get('calado_entrada')?.invalid">{{ getErrorMessage('calado_entrada') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Calado de Saída</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="calado_saida">
<mat-error *ngIf="empForm.get('calado_saida')?.invalid">{{ getErrorMessage('calado_saida') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>DWT (Atual)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }"
formControlName="dwt">
<mat-error *ngIf="empForm.get('dwt')?.invalid">{{ getErrorMessage('dwt') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Pontal (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="pontal">
<mat-error *ngIf="empForm.get('pontal')?.invalid">{{ getErrorMessage('pontal') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Ponte Mfold (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="ponte_mfold">
<mat-error *ngIf="empForm.get('ponte_mfold')?.invalid">{{ getErrorMessage('ponte_mfold') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Mfold Quilha (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '',thousands: '.', decimal: ',' }" formControlName="mfold_quilha">
<mat-error *ngIf="empForm.get('mfold_quilha')?.invalid">{{ getErrorMessage('mfold_quilha') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat.id">
{{ cat.nome }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{ getErrorMessage('categoria') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Observação</mat-label>
<input matInput type="text" formControlName="obs">
<mat-error *ngIf="empForm.get('obs')?.invalid">{{ getErrorMessage('obs') }}</mat-error>
</mat-form-field>
</div>
<div class="row file-upload-container">
<mat-label style="color:cadetblue">Adicione o documente Q88 da embarcação</mat-label>
<input
type="file"
class="file-input"
(change)="onFileSelected($event)"
#fileUpload
style="display: none"
/>
<div class="file-upload-content">
<div class="file-info">
<span>{{ fileName || "No file uploaded yet." }}</span>
</div>
<div class="upload-button-wrapper">
<button
mat-mini-fab
color="primary"
class="upload-btn"
(click)="fileUpload.click()"
>
<mat-icon>attach_file</mat-icon>
</button>
</div>
</div>
<div class="uploaded-image-container" *ngIf="imageUrl">
<img [src]="imageUrl" alt="Uploaded Image" class="uploaded-image" />
<button
mat-mini-fab
color="warn"
class="remove-image-btn"
(click)="removeImage()"
>
<mat-icon>close</mat-icon>
</button>
</div>
</div>
</div>
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">Cancelar</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 5px;
}
.file-upload {
display: flex;
align-items: center;
}
.upload-btn {
margin-left: 10px; /* Ajuste conforme necessário */
}
.uploaded-image {
margin-left: 10px; /* Ajuste conforme necessário */
max-height: 100px; /* Ajuste conforme necessário */
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AceiteAddComponent } from './aceite-add.component';
describe('AceiteAddComponent', () => {
let component: AceiteAddComponent;
let fixture: ComponentFixture<AceiteAddComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AceiteAddComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AceiteAddComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { AbstractControl, AsyncValidatorFn, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { AceiteService } from '../../../services/aceites/aceite.service';
import { NavioAddComponent } from '../../crud-navios/navio-add/navio-add.component';
import { MatDialog } from '@angular/material/dialog';
import { Observable, catchError, distinctUntilChanged, map, of, switchMap, tap } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
@Component({
selector: 'app-aceite-add',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,NgxCurrencyDirective
],
templateUrl: './aceite-add.component.html',
styleUrls: ['./aceite-add.component.scss']
})
export class AceiteAddComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria = [
{ id: '1', nome: 'Granel Sólido' },
{ id: '2', nome: 'Granel Líquido' },
{ id: '3', nome: 'Carga Geral' }
];
constructor(
private _fb: FormBuilder,
private _empService: AceiteService,
private _dialogRef: MatDialogRef<AceiteAddComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private _coreService: CoreService,
private _dialog: MatDialog,
private http: HttpClient,
private toastService: ToastrService,
) {
this.empForm = this._fb.group({
imo: [data ? data.imo : '', Validators.required, this.ImoValidator()],
mmsi: [data ? data.mmsi : '', ],
nome: [data ? data.nome : '', Validators.required],
loa: [data ? data.loa : '', Validators.required],
boca: [data ? data.boca : '', Validators.required],
dwt: [data ? data.dwt : '', Validators.required],
pontal: [data ? data.pontal : '', Validators.required],
ponte_mfold: [data ? data.ponte_mfold : '',],
mfold_quilha: [data ? data.mfold_quilha : '',],
categoria: [data ? data.categoria : '', Validators.required],
flag: [data ? data.flag : '', Validators.required],
obs: [data ? data.obs : ''],
calado_entrada:[ '', Validators.required],
calado_saida:['', Validators.required],
});
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data);
}
this.empForm.get('imo')?.valueChanges
.pipe(
distinctUntilChanged(),
switchMap(imo => {
if (imo) {
return this._empService.getEmployeebyIMO(imo).pipe(
tap(res => {
this.empForm.patchValue(res);
}),
catchError(() => {
return of(null);
})
);
} else {
return of(null);
}
})
)
.subscribe();
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
ImoValidator(): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => {
const imoValue = control.value;
if (!imoValue) {
return of(null);
}
return this._empService.getEmployeebyIMO(imoValue).pipe(
map(res => {
return null;
}),
catchError(() => {
return of({ imoExists: true });
})
);
};
}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('imoExists')) {
return 'Esse imo não existe';
}
return '';
}
exibirFormNavio() {
this._dialog.open(NavioAddComponent, {
data: {
empForm: this.empForm.value
}
});
}
onFormSubmit() {
console.log(JSON.stringify(this.empForm.value));
if (this.empForm.valid) {
if (this.selectedFile) {
this._empService.addAceite(this.empForm.value,this.selectedFile).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Aceite cadastrado com sucesso!');
},
error: (err: any) => {
console.error(err);
},
});
} else {
this._empService.addAceite(this.empForm.value,null).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Aceite cadastrado com sucesso!');
},
error: (err: any) => {
console.error(err);
},
}); }
}
}
}
<div mat-dialog-title>
<h1>Editar Aceite</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="imo">
<mat-error>
<ng-container *ngIf="empForm.get('imo')?.invalid">
<ng-container *ngIf="getErrorMessage('imo') === 'Esse imo não existe'">
{{ getErrorMessage('imo') }}, se desejar soliciatar a criação de um novo navio,
<a (click)="exibirFormNavio()" style="text-decoration: underline">clique aqui!</a>
</ng-container>
<ng-container *ngIf="getErrorMessage('imo') !== 'Esse imo não existe'">
{{ getErrorMessage('imo') }}
</ng-container>
</ng-container>
</mat-error>
</mat-form-field>
<mat-form-field class="field full-width" appearance="outline">
<mat-label>MMSI</mat-label>
<input matInput type="text" formControlName="mmsi" (keydown)="preventNegative($event)">
<mat-error *ngIf="empForm.get('mmsi')?.invalid">{{ getErrorMessage('mmsi') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome">
<mat-error *ngIf="empForm.get('nome')?.invalid">{{ getErrorMessage('nome') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>LOA (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="loa">
<mat-error *ngIf="empForm.get('loa')?.invalid">{{ getErrorMessage('loa') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Boca (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="boca">
<mat-error *ngIf="empForm.get('boca')?.invalid">{{ getErrorMessage('boca') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Calado de Entrada</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="calado_entrada">
<mat-error *ngIf="empForm.get('calado_entrada')?.invalid">{{ getErrorMessage('calado_entrada') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Calado de Saída</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="calado_saida">
<mat-error *ngIf="empForm.get('calado_saida')?.invalid">{{ getErrorMessage('calado_saida') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>DWT (Atual)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="dwt">
<mat-error *ngIf="empForm.get('dwt')?.invalid">{{ getErrorMessage('dwt') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Pontal (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="pontal">
<mat-error *ngIf="empForm.get('pontal')?.invalid">{{ getErrorMessage('pontal') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Ponte Mfold (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="ponte_mfold">
<mat-error *ngIf="empForm.get('ponte_mfold')?.invalid">{{ getErrorMessage('ponte_mfold') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Mfold Quilha (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }" formControlName="mfold_quilha">
<mat-error *ngIf="empForm.get('mfold_quilha')?.invalid">{{ getErrorMessage('mfold_quilha') }}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat.id">
{{ cat.nome }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{ getErrorMessage('categoria') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Observação</mat-label>
<input matInput type="text" formControlName="obs">
<mat-error *ngIf="empForm.get('obs')?.invalid">{{ getErrorMessage('obs') }}</mat-error>
</mat-form-field>
</div>
<!-- Sexta Linha: Status -->
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Status</mat-label>
<mat-select formControlName="status" (selectionChange)="onStatusChange($event.value)">
<mat-option value="Y">Aceito</mat-option>
<mat-option value="NE">Negado</mat-option>
<mat-option value="N">Em Processamento</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('status')?.invalid">{{ getErrorMessage('status') }}</mat-error>
</mat-form-field>
</div>
<div *ngIf="empForm.get('status')?.value === 'Y' || empForm.get('status')?.value === 'NE'" class="field large">
<mat-form-field class="field large" appearance="outline">
<mat-label>Comentários sobre o aceite:</mat-label>
<input matInput type="text" formControlName="restricoes">
<mat-error *ngIf="empForm.get('restricoes')?.invalid">
{{ getErrorMessage('restricoes') }}
</mat-error>
</mat-form-field>
<div class="row file-upload-container">
<mat-label style="color:cadetblue">Adicione o documente Q88 da embarcação</mat-label>
<input
type="file"
class="file-input"
(change)="onFileSelected($event)"
#fileUpload
style="display: none"
/>
<div class="file-upload-content">
<div class="file-info">
<span>{{ fileName || "No file uploaded yet." }}</span>
</div>
<div class="upload-button-wrapper">
<button
mat-mini-fab
color="primary"
class="upload-btn"
(click)="fileUpload.click()"
type="button"
>
<mat-icon>attach_file</mat-icon>
</button>
</div>
</div>
<div class="uploaded-image-container" *ngIf="imageUrl">
<img [src]="imageUrl" alt="Uploaded Image" class="uploaded-image" />
<button
mat-mini-fab
color="warn"
class="remove-image-btn"
(click)="removeImage()"
type="button"
>
<mat-icon>close</mat-icon>
</button>
</div>
</div>
</div>
</div>
<!-- Ações do Diálogo -->
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">Cancelar</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AceiteEditComponent } from './aceite-edit.component';
describe('AceiteEditComponent', () => {
let component: AceiteEditComponent;
let fixture: ComponentFixture<AceiteEditComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AceiteEditComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AceiteEditComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { AbstractControl, AsyncValidator, AsyncValidatorFn, FormBuilder, FormGroup, ValidationErrors, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { AceiteService } from '../../../services/aceites/aceite.service';
import { NavioAddComponent } from '../../crud-navios/navio-add/navio-add.component';
import { MatDialog } from '@angular/material/dialog';
import { Observable, catchError, distinctUntilChanged, map, of, switchMap, tap } from 'rxjs';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
import { BercosService } from '../../../services/bercos/bercos.service';
import { PageEvent } from '@angular/material/paginator';
import { throwError } from 'rxjs';
@Component({
selector: 'app-aceite-edit',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule, // Corrigido
MatSnackBarModule, NgxCurrencyDirective
],
templateUrl: './aceite-edit.component.html',
styleUrl: './aceite-edit.component.scss'
})
export class AceiteEditComponent implements OnInit {
empForm: FormGroup;
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
selectedFile: File | null = null;
categoria = [
{ id: 1, nome: 'Granel Sólido' },
{ id: 2, nome: 'Granel Líquido' },
{ id: 3, nome: 'Carga Geral' }
]; bercos: any[] = [];
constructor(
private _fb: FormBuilder,
private _empService: AceiteService,
private _dialogRef: MatDialogRef<AceiteEditComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private _coreService: CoreService,
private _dialog: MatDialog,
private toastService: ToastrService,
private _bercoService: BercosService,
private cdr: ChangeDetectorRef,
) {
this.empForm = this._fb.group({
status: ['', Validators.required], // Inicialize o status como string vazia ou um valor padrão
imo: ['', Validators.required, this.ImoValidator()],
mmsi: ['',],
nome: ['', Validators.required],
loa: ['', Validators.required],
boca: ['', Validators.required],
dwt: ['', Validators.required],
pontal: ['', Validators.required],
ponte_mfold: ['',],
mfold_quilha: ['',],
categoria: [Number(this.data?.categoria) || '', Validators.required],
flag: ['', Validators.required],
obs: ['', Validators.required],
calado_entrada: ['', Validators.required],
calado_saida: ['', Validators.required],
restricoes: ['']
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
ngOnInit(): void {
this.getBercosList()
console.log(this.data)
if (this.data) {
this.empForm.patchValue({
...this.data,
categoria: Number(this.data.categoria),
flag: Number(this.data.flag),
}); }
this.empForm.get('imo')?.valueChanges
.pipe(
distinctUntilChanged(), // Verifica se o valor mudou realmente
switchMap(imo => {
if (imo) {
return this._empService.getEmployeebyIMO(imo).pipe(
tap(res => {
this.empForm.patchValue(res); // Atualiza o formulário com os dados recebidos
}),
catchError(() => {
return of(null); // Trata o erro aqui ou retorna null, dependendo do seu caso
})
);
} else {
return of(null); // Retorna um observable vazio se não houver imo
}
})
)
.subscribe();
}
ImoValidator(): AsyncValidatorFn {
return (control: AbstractControl): Observable<ValidationErrors | null> => {
const imoValue = control.value;
if (!imoValue) {
return of(null);
}
return this._empService.getEmployeebyIMO(imoValue).pipe(
map(() => {
return null;
}),
catchError(() => {
return of({ imoExists: true });
})
);
};
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.setAsyncValidators) {
return 'Esse imo não existe';
}
return '';
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
exibirFormNavio() {
const dialogRef = this._dialog.open(NavioAddComponent, {
data: {
empForm: this.empForm.value
}
});
}
onStatusChange(value: any): void {
// Atualiza o valor do campo status no formulário
this.empForm.get('status')?.setValue(value);
// Lógica adicional (opcional)
if (value === 'aceito') {
this.empForm.get('motivoNegacao')?.reset(); // Limpa o campo de motivo
} else if (value === 'negado') {
this.empForm.get('bercos')?.reset(); // Limpa o campo de berços
}
}
private getBercosList() {
this._bercoService.getBercosListSemPaginacao().subscribe({
next: (res: any) => {
// Acesse o array de bercoResponseList dentro de _embedded
this.bercos = res._embedded.bercoResponseList;
console.log(this.bercos); // Agora deve exibir corretamente a lista de berços
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
onFormSubmit() {
console.log(JSON.stringify(this.empForm.value));
if (this.empForm.valid) {
if (this.selectedFile) {
this._empService.updateAceite(this.data.id, this.empForm.value, this.selectedFile).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Aceite editado com sucesso');
},
error: (err: any) => {
console.error(err);
},
});
} else {
this._empService.updateAceite(this.data.id, this.empForm.value, null).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Aceite editado com sucesso');
},
error: (err: any) => {
console.error(err);
},
});
}
}
}
}
<div mat-dialog-title>
<h1>{{ "Buscar Aceite" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<!-- IMO -->
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input
matInput
type="number"
(keydown)="preventNegative($event)"
min="0"
formControlName="imo"
/>
<mat-error *ngIf="empForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
</div>
<!--
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat">
{{ cat === 1 ? "Granel Sólido" : cat === 2 ? "Granel Líquido" : "Carga Geral" }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{
getErrorMessage("categoria")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
-->
</div>
<div mat-dialog-actions class="action">
<button
mat-raised-button
type="button"
color="warn"
[mat-dialog-close]="false"
>
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Buscar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AceiteSearchComponent } from './aceite-search.component';
describe('AceiteSearchComponent', () => {
let component: AceiteSearchComponent;
let fixture: ComponentFixture<AceiteSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AceiteSearchComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AceiteSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
import { AceitesComponent } from '../aceites/aceites.component';
import { AceiteService } from '../../../services/aceites/aceite.service';
@Component({
selector: 'app-aceite-search',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
AceitesComponent,
NgxCurrencyDirective,
],
templateUrl: './aceite-search.component.html',
styleUrl: './aceite-search.component.scss',
})
export class AceiteSearchComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria: number[] = [1, 2,3];
constructor(
private _fb: FormBuilder,
private _empService: AceiteService,
private _dialogRef: MatDialogRef<AceiteSearchComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService,
private cdr: ChangeDetectorRef,
) {
this.empForm = this._fb.group({
imo: [''],
categoria: [''],
flag: [''],
});
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data.empForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
onFormSubmit() {
if (this.empForm.valid) {
const searchCriteria = {
imo: this.empForm.value.imo,
categoria: this.empForm.value.categoria,
flag: this.empForm.value.flag,
};
this._empService.searchAceite(searchCriteria).subscribe({
next: (val: any) => {
this.toastService.success('Busca realizada com sucesso');
this._dialogRef.close(true);
this.cdr.detectChanges();
},
error: (err: any) => {
console.error(err);
}
});
}
}
}
<app-add-search [title]="'Aceites'" [primaryButtonText]="'Solicitar Aceite'" [primaryButtonColor]="'primary'"
[primaryButtonAction]="openAddBercoForm.bind(this)" [secondaryButtonText]="'Buscar Aceite'"
[secondaryButtonColor]="'accent'" [secondaryButtonAction]="openSearchBercoForm.bind(this)">
</app-add-search>
<div class="main-body">
<div class="table-container" style="overflow-x: auto">
<table mat-table [dataSource]="dataSource" matSort>
<!-- ID Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Código</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<!-- IMO Column -->
<ng-container matColumnDef="imo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>IMO</th>
<td mat-cell *matCellDef="let row">{{ row.imo || "Null" }}</td>
</ng-container>
<!-- MMSI Column -->
<ng-container matColumnDef="user">
<th mat-header-cell *matHeaderCellDef>Usuário Responsável</th>
<td mat-cell *matCellDef="let row">
{{ parseUserString(row.user)?.email || "Sem email" }}
</td>
</ng-container>
<!-- MMSI Column -->
<ng-container matColumnDef="nome">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
<td mat-cell *matCellDef="let row">{{ row.nome ?? 'Null' }}
</td>
</ng-container>
<ng-container matColumnDef="data_create">
<th mat-header-cell *matHeaderCellDef>Data de Criação</th>
<td mat-cell *matCellDef="let row">{{ row.data_create || "Null" }}</td>
</ng-container>
<ng-container matColumnDef="data_update">
<th mat-header-cell *matHeaderCellDef>Data de Edição</th>
<td mat-cell *matCellDef="let row">{{ row.data_update || "Null" }}</td>
</ng-container>
<ng-container matColumnDef="dataAccept">
<th mat-header-cell *matHeaderCellDef>Data de Edição</th>
<td mat-cell *matCellDef="let row">{{ row.dataAccept || "Null" }}</td>
</ng-container>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef>Status</th>
<td mat-cell *matCellDef="let row">
{{ row.status == "Y" ? "Verificado" : "Não verificado" }}
</td>
</ng-container>
<!-- Vessel Column -->
<ng-container matColumnDef="vessel">
<th mat-header-cell *matHeaderCellDef>Vessel</th>
<td mat-cell *matCellDef="let row">{{ row.vessel || "Null" }}</td>
</ng-container>
<!-- Action Column -->
<!-- Action Column -->
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>Action</th>
<td mat-cell *matCellDef="let row" style="white-space: nowrap">
<button mat-icon-button (click)="openEditForm(row)" *ngIf="user.role === 'COMPANY'">
<mat-icon style="color: coral">edit</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="getBercoById(row)">
<mat-icon>visibility</mat-icon>
</button>
<button mat-icon-button color="warn" (click)="deleteBerco(row.id)" *ngIf="user.role === 'COMPANY'">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<!-- Add paginator reference #paginator="matPaginator" -->
<mat-paginator #paginator [length]="totalItems" [pageSize]="pageSize" (page)="loadData($event)">
</mat-paginator>
<button mat-button (click)="paginator.firstPage()" [disabled]="paginator.pageIndex === 0">
Primeira Página
</button>
<button mat-button (click)="paginator.lastPage()"
[disabled]="paginator.pageIndex === paginator.getNumberOfPages() - 1">
Última Página
</button>
</div>
\ No newline at end of file
.example-spacer {
flex: 1 1 auto;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 600px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AceitesComponent } from './aceites.component';
describe('AceitesComponent', () => {
let component: AceitesComponent;
let fixture: ComponentFixture<AceitesComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AceitesComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AceitesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { AceiteService } from '../../../services/aceites/aceite.service';
import { CoreService } from '../../../core/core.service';
import { VisualizacaoAceiteComponent } from '../visualizacao-aceite/visualizacao-aceite.component';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTableModule } from '@angular/material/table';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatPaginatorModule } from '@angular/material/paginator';
import { AceiteEditComponent } from '../aceite-edit/aceite-edit.component';
import { AceiteAddComponent } from '../aceite-add/aceite-add.component';
import { AddSearchComponent } from '../../../shared/addAndSearch/add-search/add-search.component';
import { AceiteSearchComponent } from '../aceite-search/aceite-search.component';
import { JwtDecoderService } from '../../../jwt-decoder.service';
import { AuthService } from '../../../auth.service';
import { jwtDecode } from 'jwt-decode';
interface AceiteData {
id: number;
imo: number;
codigo: string;
obs: string;
status: string;
bercos: any;
}
@Component({
selector: 'app-aceites',
standalone: true,
imports: [
MatPaginatorModule,
MatToolbarModule,
MatTableModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
MatSortModule,
AddSearchComponent,
],
templateUrl: './aceites.component.html',
styleUrls: ['./aceites.component.scss'],
})
export class AceitesComponent implements OnInit {
displayedColumns = [
'id',
'nome',
'user',
'imo',
'data_create',
'data_update',
'dataAccept',
'status',
'action',
];
dataSource = new MatTableDataSource<AceiteData>();
totalItems = 100;
pageSize = 10;
currentPage = 1;
user: any;
authTokenPresent = false;
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
constructor(
private _dialog: MatDialog,
private _aceiteService: AceiteService,
private _coreService: CoreService,
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void { this.validationToken();
}
ngAfterViewInit(): void {
this.loadData();
}
parseUserString(userString: string) {
const userRegex = /User\(id=(\d+), email=([^)]+)\)/;
const match = userRegex.exec(userString);
if (match) {
return {
id: parseInt(match[1], 10),
email: match[2],
};
}
return null;
}
loadData(event?: PageEvent): void {
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('aceitesSearch');
if (storedData) {
const aceites = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', aceites);
// Atualiza os dados na tabela
this.dataSource.data = aceites;
// Configurações do paginator e sort
if (this.paginator && this.sort) {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
// Atualiza a visualização
this.cdr.detectChanges();
// Remove dados do sessionStorage após o uso
sessionStorage.removeItem('aceitesSearch');
console.log('aceitesSearch removido do sessionStorage.');
return; // Retorna para evitar chamada à API
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
}
// Caso os dados não estejam no sessionStorage, chama a API
const pageIndex = event ? event.pageIndex + 1 : this.currentPage - 1;
this._aceiteService.getAceiteList(pageIndex, this.pageSize).subscribe({
next: (res: any) => {
const aceites = res._embedded.acceptResponseList;
console.log(aceites);
this.dataSource.data = aceites;
this.totalItems = res.page.totalElements;
console.log(res.page.totalElements);
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
deleteBerco(id: number) {
this._aceiteService.deleteEmployee(id).subscribe({
next: () => {
this._coreService.openSnackBar('Aceite deleted!', 'done');
this.loadData();
},
error: (err: any) => {
this._coreService.openSnackBar(err.error.title);
},
});
this.cdr.detectChanges();
}
openEditForm(data: any) {
this._dialog.open(AceiteEditComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
openSearchBercoForm() {
this._dialog.open(AceiteSearchComponent, {
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px' // Define a largura do diálogo
});
// Verifica se o sessionStorage está disponível
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('aceitesSearch');
if (storedData) {
const dataSource = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', dataSource);
this.dataSource.data = dataSource;
this.cdr.detectChanges();
// Atualiza a tabela com os dados
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
} else {
console.error('sessionStorage não está disponível.');
}
}
//
openAddBercoForm() {
this._dialog.open(AceiteAddComponent,{autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo});
});}
getBercoById(data: any) {
this._dialog.open(VisualizacaoAceiteComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
width: '600px', // Define a largura do diálogo
});
}
validationToken() {
this.authService.authToken$.subscribe((isLoggedIn) => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp
? this.user.exp < Date.now() / 1000
: false;
if (isExpired) {
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
}
<h1 mat-dialog-title class="mat-dialog-title">Aceite</h1>
<mat-dialog-content>
<mat-tab-group class="mat-tab-group">
<mat-tab label="Informações">
<mat-card>
<mat-card-header>
<mat-card-title class="mat-card-title">Aceite</mat-card-title>
<mat-card-subtitle class="mat-card-subtitle">
Nome do Navio: {{ data.nome }}
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="row">
<p class="field full-width" appearance="outline">ID: {{ data.id }}</p>
<p class="field full-width" appearance="outline">
USUÁRIO: {{ parseUserString(data.user)?.email || "Sem email" }}
</p>
<p class="field full-width" appearance="outline">
IMO: {{ data.imo || "Sem informação" }}
</p>
<p class="field full-width" appearance="outline">
STATUS:
<ng-container [ngSwitch]="data.status">
<span *ngSwitchCase="'Y'" [ngStyle]="{ color: 'green' }">Navio Aceito</span>
<span *ngSwitchCase="'NE'" [ngStyle]="{ color: 'red' }">Aceite Negado</span>
<span *ngSwitchCase="'N'" [ngStyle]="{ color: 'orange' }">Em processamento</span>
</ng-container>
</p>
</div>
</mat-card-content>
</mat-card>
<ng-container *ngIf="data.path">
<mat-card-actions>
<button (click)="downloadNavioFunction()">Download Documento Q88</button>
</mat-card-actions>
</ng-container>
</mat-tab>
<mat-tab label="Status do Aceite">
<mat-card>
<mat-card-header>
<mat-card-title class="mat-card-title">Aceite</mat-card-title>
<mat-card-subtitle class="mat-card-subtitle">
Nome do Navio: {{ data.nome }}
</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="row">
<ng-container [ngSwitch]="data.status">
<div *ngSwitchCase="'N'">
<p class="field full-width" appearance="outline">
Status: <span [ngStyle]="{ color: 'orange' }">Em processamento</span>
</p>
<p class="field full-width" appearance="outline">
O gerente está analisando a solicitação para verificar as especificações.
</p>
</div>
<div *ngSwitchCase="'Y'">
<p class="field full-width" appearance="outline">
Status: <span [ngStyle]="{ color: 'green' }">Navio Aceito</span>
</p>
@if(data.restricoes){
<p class="field full-width" appearance="outline">
{{data.restricoes}}
</p>
}@else{
<p class="field full-width" appearance="outline">
O navio é compatível com os seguintes berços:
</p>
<div *ngIf="data?.bercos?.length > 0">
<div *ngFor="let berco of data.bercos">
{{ berco.nome }}
</div>
</div>
}
</div>
<div *ngSwitchCase="'NE'">
<p class="field full-width" appearance="outline">
Status: <span [ngStyle]="{ color: 'red' }">Aceite Negado</span>
</p>
<p class="field full-width" appearance="outline">
{{data.restricoes}}
</p>
</div>
</ng-container>
</div>
</mat-card-content>
</mat-card>
</mat-tab>
</mat-tab-group>
</mat-dialog-content>
<mat-dialog-actions>
<!-- Botões de ação, se necessário -->
</mat-dialog-actions>
.card {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.field.row-gap {
display: grid;
row-gap: 50px;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VisualizacaoAceiteComponent } from './visualizacao-aceite.component';
describe('VisualizacaoAceiteComponent', () => {
let component: VisualizacaoAceiteComponent;
let fixture: ComponentFixture<VisualizacaoAceiteComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [VisualizacaoAceiteComponent]
})
.compileComponents();
fixture = TestBed.createComponent(VisualizacaoAceiteComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatTabsModule } from '@angular/material/tabs';
import { MatDialogModule } from '@angular/material/dialog';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-visualizacao-aceite',
standalone: true,
imports: [
CommonModule,
MatButtonModule,
MatCardModule,
MatTabsModule,
MatDialogModule,
],
templateUrl: './visualizacao-aceite.component.html',
styleUrls: ['./visualizacao-aceite.component.scss'],
})
export class VisualizacaoAceiteComponent implements OnInit {
constructor(@Inject(MAT_DIALOG_DATA) public data: any,
private httpClient: HttpClient ,// Adicione isto
) {}
ngOnInit(): void {
console.log(this.data);
}
parseUserString(userString: string) {
const userRegex = /User\(id=(\d+), email=([^)]+)\)/;
const match = userRegex.exec(userString);
if (match) {
return {
id: parseInt(match[1], 10),
email: match[2],
};
}
return null;
}
downloadNavioFunction() {
this.httpClient.get('http://localhost:8080/api/download-file', {
params: { filename: this.data.path },
responseType: 'blob' // Adiciona 'blob' para lidar com arquivos binários
}).subscribe({
next: (response) => {
// Criação de um URL temporário para o arquivo
const blob = new Blob([response]);
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = this.data.path || 'download'; // Define o nome do arquivo
link.click();
// Libera o objeto URL após o download
window.URL.revokeObjectURL(link.href);
console.log('Download iniciado:', this.data.path);
},
error: (error) => {
console.error('Erro ao baixar o arquivo:', error);
}
});
}}
<div mat-dialog-title>
<h1>{{ 'Adicionar Berço' }}</h1>
</div>
<form [formGroup]="bercoForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome">
<mat-error *ngIf="bercoForm.get('nome')?.invalid">{{ getErrorMessage('nome') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>Comprimento Estrutural</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="compri_estrutural">
<mat-error *ngIf="bercoForm.get('compri_estrutural')?.invalid">{{ getErrorMessage('compri_estrutural') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Comprimento Útil</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="compri_util">
<mat-error *ngIf="bercoForm.get('compri_util')?.invalid">{{ getErrorMessage('compri_util') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>DWT</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="dwt">
<mat-error *ngIf="bercoForm.get('dwt')?.invalid">{{ getErrorMessage('dwt') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Largura</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="largura">
<mat-error *ngIf="bercoForm.get('largura')?.invalid">{{ getErrorMessage('largura') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>Profundidade</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="profundidade">
<mat-error *ngIf="bercoForm.get('profundidade')?.invalid">{{ getErrorMessage('profundidade') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Calado Máximo</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="calado_max">
<mat-error *ngIf="bercoForm.get('calado_max')?.invalid">{{ getErrorMessage('calado_max') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Boca Máxima</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="boca_max">
<mat-error *ngIf="bercoForm.get('boca_max')?.invalid">{{ getErrorMessage('boca_max') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>LOA Máxima</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="loa_max">
<mat-error *ngIf="bercoForm.get('loa_max')?.invalid">{{ getErrorMessage('loa_max') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat.id">
{{ cat.nome }}
</mat-option>
</mat-select>
<mat-error *ngIf="bercoForm.get('categoria')?.invalid">{{ getErrorMessage('categoria') }}</mat-error>
</mat-form-field>
</div>
</div>
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">Cancelar</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-bottom: 5px;
}
.file-upload {
display: flex;
align-items: center;
}
.upload-btn {
margin-left: 10px; /* Ajuste conforme necessário */
}
.uploaded-image {
margin-left: 10px; /* Ajuste conforme necessário */
max-height: 100px; /* Ajuste conforme necessário */
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BercoAddComponent } from './berco-add.component';
describe('BercoAddComponent', () => {
let component: BercoAddComponent;
let fixture: ComponentFixture<BercoAddComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BercoAddComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BercoAddComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { BercosComponent } from '../bercos/bercos.component';
import { BercosService } from '../../../services/bercos/bercos.service';
@Component({
selector: 'app-berco-add',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
BercosComponent,
], templateUrl: './berco-add.component.html',
styleUrl: './berco-add.component.scss'
})
export class BercoAddComponent implements OnInit {
bercoForm: FormGroup;
categoria = [
{ id: 1, nome: 'Granel Sólido' },
{ id: 2, nome: 'Granel Líquido' },
{ id: 3, nome: 'Carga Geral' }
];
constructor(
private _fb: FormBuilder,
private _bercoService: BercosService,
private _dialogRef: MatDialogRef<BercoAddComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService,
) {
this.bercoForm = this._fb.group({
nome: ['', Validators.required],
compri_estrutural: ['', Validators.required],
compri_util: ['', Validators.required],
dwt: ['', Validators.required],
largura: ['', Validators.required],
profundidade: ['', Validators.required],
calado_max: ['', Validators.required],
boca_max: ['', Validators.required],
loa_max: ['', Validators.required],
categoria:['', Validators.required]
});
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.bercoForm.patchValue(this.data.bercoForm);
}
}
getErrorMessage(formControlName: string): string {
if (this.bercoForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
return '';
}
onFormSubmit() {
if (this.bercoForm.valid) {
console.log(this.bercoForm.value)
this._bercoService.addEmployee(this.bercoForm.value).subscribe({
next: (val: any) => {
this.toastService.success('Berço adicionado com sucesso');
this._dialogRef.close(true);
},
error: (err: any) => {
console.error(err);
}
});
}
}
}
\ No newline at end of file
<div mat-dialog-title>
<h1>{{ 'Editar Berço' }}</h1>
</div>
<form [formGroup]="bercoForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome">
<mat-error *ngIf="bercoForm.get('nome')?.invalid">{{ getErrorMessage('nome') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>Comprimento Estrutural</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="compri_estrutural">
<mat-error *ngIf="bercoForm.get('compri_estrutural')?.invalid">{{ getErrorMessage('compri_estrutural') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Comprimento Útil</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="compri_util">
<mat-error *ngIf="bercoForm.get('compri_util')?.invalid">{{ getErrorMessage('compri_util') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>DWT</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="dwt">
<mat-error *ngIf="bercoForm.get('dwt')?.invalid">{{ getErrorMessage('dwt') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Largura</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="largura">
<mat-error *ngIf="bercoForm.get('largura')?.invalid">{{ getErrorMessage('largura') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-medium" appearance="outline">
<mat-label>Profundidade</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="profundidade">
<mat-error *ngIf="bercoForm.get('profundidade')?.invalid">{{ getErrorMessage('profundidade') }}</mat-error>
</mat-form-field>
<mat-form-field class="field full-small" appearance="outline">
<mat-label>Calado Máximo</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="calado_max">
<mat-error *ngIf="bercoForm.get('calado_max')?.invalid">{{ getErrorMessage('calado_max') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Boca Máxima</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="boca_max">
<mat-error *ngIf="bercoForm.get('boca_max')?.invalid">{{ getErrorMessage('boca_max') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>LOA Máxima</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="loa_max">
<mat-error *ngIf="bercoForm.get('loa_max')?.invalid">{{ getErrorMessage('loa_max') }}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat.id">
{{ cat.nome }}
</mat-option>
</mat-select>
<mat-error *ngIf="bercoForm.get('categoria')?.invalid">{{ getErrorMessage('categoria') }}</mat-error>
</mat-form-field>
</div>
</div>
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">Cancelar</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BercoEditComponent } from './berco-edit.component';
describe('BercoEditComponent', () => {
let component: BercoEditComponent;
let fixture: ComponentFixture<BercoEditComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BercoEditComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BercoEditComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { BercosComponent } from '../bercos/bercos.component';
import { BercosService } from '../../../services/bercos/bercos.service';
@Component({
selector: 'app-berco-edit',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
BercosComponent,
],
templateUrl: './berco-edit.component.html',
styleUrl: './berco-edit.component.scss'
})
export class BercoEditComponent implements OnInit {
bercoForm: FormGroup;
constructor(
private _fb: FormBuilder,
private _bercoService: BercosService,
private _dialogRef: MatDialogRef<BercoEditComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService,
) {
this.bercoForm = this._fb.group({
nome: ['', Validators.required],
compri_estrutural: ['', Validators.required],
compri_util: ['', Validators.required],
dwt: ['', Validators.required],
largura: ['', Validators.required],
profundidade: ['', Validators.required],
calado_max: ['', Validators.required],
boca_max: ['', Validators.required],
loa_max: ['', Validators.required],
categoria:['', Validators.required]
});
}
categoria = [
{ id: 1, nome: 'Granel Sólido' },
{ id: 2, nome: 'Granel Líquido' },
{ id: 3, nome: 'Carga Geral' }
];
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
console.log(this.data)
this.bercoForm.patchValue(this.data);
}
}
getErrorMessage(formControlName: string): string {
if (this.bercoForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
return '';
}
onFormSubmit() {
if (this.bercoForm.valid) {
if (this.data) {
this._bercoService.updateEmployee(this.data.id, this.bercoForm.value).subscribe({
next: (val: any) => {
this.toastService.success('Detalhes do berço atualizados!');
this._dialogRef.close(true);
},
error: (err: any) => {
console.error(err);
},
});
}
}
}
}
\ No newline at end of file
<div mat-dialog-title>
<h1>{{ "Buscar Berço" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<!-- Nome -->
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome" />
<mat-error *ngIf="empForm.get('nome')?.invalid">{{
getErrorMessage("nome")
}}</mat-error>
</mat-form-field>
<!-- Categoria -->
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat">
{{ cat === 1 ? "Granel Sólido" : "Granel Líquido" }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{
getErrorMessage("categoria")
}}</mat-error>
</mat-form-field>
</div>
</div>
<div mat-dialog-actions class="action">
<button
mat-raised-button
type="button"
color="warn"
[mat-dialog-close]="false"
>
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Buscar</button>
</div>
</form>
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BercoSearchComponent } from './berco-search.component';
describe('BercoSearchComponent', () => {
let component: BercoSearchComponent;
let fixture: ComponentFixture<BercoSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BercoSearchComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BercoSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
import { BercosService } from '../../../services/bercos/bercos.service';
@Component({
selector: 'app-berco-search',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
BercoSearchComponent,
NgxCurrencyDirective,
],
templateUrl: './berco-search.component.html',
styleUrl: './berco-search.component.scss',
})
export class BercoSearchComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria: number[] = [1, 2];
constructor(
private _fb: FormBuilder,
private _bercoService: BercosService,
private _dialogRef: MatDialogRef<BercoSearchComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService
) {
this.empForm = this._fb.group({
nome: [''],
categoria: [''],
});
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data.empForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
onFormSubmit() {
if (this.empForm.valid) {
const searchCriteria = {
nome: this.empForm.value.nome,
categoria: this.empForm.value.categoria,
};
this._bercoService.searchBerco(searchCriteria).subscribe({
next: (val: any) => {
this.toastService.success('Busca realizada com sucesso');
this._dialogRef.close(true);
},
error: (err: any) => {
console.error(err);
}
});
}
}
}
<app-add-search
[title]="'Berços'"
[primaryButtonText]="'Adicionar Berço'"
[primaryButtonColor]="'primary'"
[primaryButtonAction]="openAddBercoForm.bind(this)"
[secondaryButtonText]="'Buscar Berço'"
[secondaryButtonColor]="'accent'"
[secondaryButtonAction]="openSearchBercoForm.bind(this)"
>
</app-add-search>
<div class="main-body">
<div class="table-container">
<table mat-table [dataSource]="dataSource" matSort>
<!-- ID Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<!-- Nome Column -->
<ng-container matColumnDef="nome">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
<td mat-cell *matCellDef="let row">{{ row.nome || "Null" }}</td>
</ng-container>
<!-- Compri_estrutural Column -->
<ng-container matColumnDef="compri_estrutural">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
Comprimento Estrutural
</th>
<td mat-cell *matCellDef="let row">
{{ row.compri_estrutural || "Null" }}
</td>
</ng-container>
<!-- Compri_util Column -->
<ng-container matColumnDef="compri_util">
<th mat-header-cell *matHeaderCellDef mat-sort-header>
Comprimento Útil
</th>
<td mat-cell *matCellDef="let row">{{ row.compri_util || "Null" }}</td>
</ng-container>
<!-- DWT Column -->
<ng-container matColumnDef="dwt">
<th mat-header-cell *matHeaderCellDef mat-sort-header>DWT</th>
<td mat-cell *matCellDef="let row">{{ row.dwt || "Null" }}</td>
</ng-container>
<!-- Largura Column -->
<ng-container matColumnDef="largura">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Largura</th>
<td mat-cell *matCellDef="let row">{{ row.largura || "Null" }}</td>
</ng-container>
<!-- Profundidade Column -->
<ng-container matColumnDef="profundidade">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Profundidade</th>
<td mat-cell *matCellDef="let row">{{ row.profundidade || "Null" }}</td>
</ng-container>
<!-- Calado_max Column -->
<!-- Action Column -->
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>Action</th>
<td mat-cell *matCellDef="let row" style="white-space: nowrap">
<button mat-icon-button (click)="openEditForm(row)" *ngIf="user.role === 'COMPANY'">
<mat-icon style="color: coral">edit</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="getBercoById(row)">
<mat-icon>visibility</mat-icon>
</button>
<button mat-icon-button color="warn" (click)="deleteBerco(row.id)" *ngIf="user.role === 'COMPANY'">
<mat-icon>delete</mat-icon>
</button>
<!-- Use *ngIf instead of @if -->
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<!-- Add paginator reference #paginator="matPaginator" -->
<mat-paginator
#paginator
[length]="totalItems"
[pageSize]="pageSize"
(page)="loadData($event)"
>
</mat-paginator>
<!-- Buttons for navigating to the first and last page -->
<button
mat-button
(click)="paginator.firstPage()"
[disabled]="paginator.pageIndex === 0"
>
Primeira Página
</button>
<button
mat-button
(click)="paginator.lastPage()"
[disabled]="paginator.pageIndex === paginator.getNumberOfPages() - 1"
>
Última Página
</button>
</div>
.example-spacer {
flex: 1 1 auto;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 1000px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BercosComponent } from './bercos.component';
describe('BercosComponent', () => {
let component: BercosComponent;
let fixture: ComponentFixture<BercosComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BercosComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BercosComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator, PageEvent } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { BercosService } from '../../../services/bercos/bercos.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTableModule } from '@angular/material/table';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { BercoAddComponent } from '../berco-add/berco-add.component';
import { BercoEditComponent } from '../berco-edit/berco-edit.component';
import { VisualizacaoBercosComponent } from '../visualizacao-bercos/visualizacao-bercos.component';
import { AddSearchComponent } from '../../../shared/addAndSearch/add-search/add-search.component';
import { BercoSearchComponent } from '../berco-search/berco-search.component';
import { JwtDecoderService } from '../../../jwt-decoder.service';
import { AuthService } from '../../../auth.service';
import { jwtDecode } from 'jwt-decode';
interface BercoData {
id: number;
nome: string;
compri_estrutural: number;
compri_util: number;
dwt: number;
largura: number;
profundidade: number;
calado_max: number;
boca_max: number;
loa_max: number;
action: number;
}
@Component({
selector: 'app-bercos',
standalone: true,
imports: [
MatPaginatorModule,
MatToolbarModule,
MatTableModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
MatSortModule,
AddSearchComponent,
],
templateUrl: './bercos.component.html',
styleUrls: ['./bercos.component.scss'],
})
export class BercosComponent implements OnInit {
totalItems = 100;
pageSize = 10;
currentPage = 1;
displayedColumns: string[] = [
'id',
'nome',
'compri_estrutural',
'compri_util',
'dwt',
'largura',
'profundidade',
'action',
];
dataSource = new MatTableDataSource<BercoData>();
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
user: any;
authTokenPresent = false;
constructor(
private _dialog: MatDialog,
private _bercoService: BercosService,
private _coreService: CoreService,
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void { this.validationToken();
}
ngAfterViewInit(): void {
this.loadData();
}
validationToken() {
this.authService.authToken$.subscribe((isLoggedIn) => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp
? this.user.exp < Date.now() / 1000
: false;
if (isExpired) {
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
loadData(event?: PageEvent): void {
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('bercosSearch');
if (storedData) {
const bercos = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', bercos);
// Atualiza os dados no MatTableDataSource
this.dataSource.data = bercos;
// Reassocia paginator e sort
if (this.paginator && this.sort) {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
// Atualiza a visualização
this.cdr.detectChanges();
// Remove dados do sessionStorage após o uso
sessionStorage.removeItem('bercosSearch');
console.log('bercosSearch removido do sessionStorage.');
return; // Retorna aqui, pois já usamos os dados do sessionStorage
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
}
// Caso os dados não estejam no sessionStorage, chama a API
const pageIndex = event ? event.pageIndex + 1 : this.currentPage - 1;
this._bercoService.getEmployeeList(pageIndex, this.pageSize).subscribe({
next: (res: any) => {
const bercos = res._embedded.bercoResponseList;
console.log(bercos);
this.dataSource.data = bercos;
this.totalItems = res.page.totalElements;
console.log(res.page.totalElements);
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
deleteBerco(id: number) {
this._bercoService.deleteEmployee(id).subscribe({
next: () => {
this._coreService.openSnackBar('Berço deleted!', 'done');
this.loadData();
},
error: (err: any) => {
this._coreService.openSnackBar(err.error.title);
},
});
this.cdr.detectChanges();
}
openEditForm(data: any) {
this._dialog.open(BercoEditComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
openAddBercoForm() {
this._dialog.open(BercoAddComponent,{autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '500px', // Define a largura do diálogo});
});
this.cdr.detectChanges();
}
openSearchBercoForm() {
this._dialog.open(BercoSearchComponent);
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('bercosSearch');
if (storedData) {
const dataSource = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', dataSource);
this.dataSource= dataSource;
this.cdr.detectChanges();
// Atualiza a tabela com os dados
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
} else {
console.error('sessionStorage não está disponível.');
}
}
getBercoById(data: any) {
this._dialog.open(VisualizacaoBercosComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
width: '800px', // Define a largura do diálogo
});
}
}
<mat-card>
<mat-card-header>
<mat-card-title>Berços</mat-card-title>
<mat-card-subtitle>Nome do Berço: {{ data.nome }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div
class="row"
style="display: flex; flex-wrap: wrap; justify-content: space-between"
>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>ID:</strong> {{ data.id }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Nome:</strong> {{ data.nome }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p>
<strong>Comprimento Estrutural:</strong> {{ data.compri_estrutural }}
</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Comprimento Útil:</strong> {{ data.compri_util }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>DWT:</strong> {{ data.dwt }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Largura:</strong> {{ data.largura }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Profundidade:</strong> {{ data.profundidade }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Calado Máximo:</strong> {{ data.calado_max }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>Boca Máxima:</strong> {{ data.boca_max }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px">
<p><strong>LOA Máxima:</strong> {{ data.loa_max }}</p>
</div>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Categoria:</strong> @if(data.categoria==1){Granel Sólido}@else if(data.categoria==2){Granel Líquido}@else if(data.categoria==3){Carga Geral}@else{Não informado}</p>
</div>
</mat-card-content>
</mat-card>
.card {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large,
.field.medium,
.field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VisualizacaoBercosComponent } from './visualizacao-bercos.component';
describe('VisualizacaoBercosComponent', () => {
let component: VisualizacaoBercosComponent;
let fixture: ComponentFixture<VisualizacaoBercosComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [VisualizacaoBercosComponent],
}).compileComponents();
fixture = TestBed.createComponent(VisualizacaoBercosComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import {
FormBuilder,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatTableDataSource } from '@angular/material/table';
import { MatTabsModule } from '@angular/material/tabs';
import { MatDialogModule } from '@angular/material/dialog';
@Component({
selector: 'app-visualizacao-bercos',
standalone: true,
imports: [
CommonModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule,
MatInputModule,
ReactiveFormsModule,
MatTabsModule,
MatDialogModule,
],
templateUrl: './visualizacao-bercos.component.html',
styleUrl: './visualizacao-bercos.component.scss',
})
export class VisualizacaoBercosComponent implements OnInit {
constructor(@Inject(MAT_DIALOG_DATA) public data: any) {}
ngOnInit(): void {
this.printa();
}
printa() {
console.log(this.data);
}
}
<div mat-dialog-title>
<h1>{{ "Adicionar Navio na Black-List" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input [value]="empForm.get('imo')?.invalid"
matInput
type="number"
(keydown)="preventNegative($event)"
min="0"
formControlName="imo"
/>
<mat-error *ngIf="empForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Motivo</mat-label>
<input matInput type="text" formControlName="reason" />
<mat-error *ngIf="empForm.get('reason')?.invalid">{{
getErrorMessage("reason")
}}</mat-error>
</mat-form-field>
</div>
<div class="row file-upload-container">
<input
type="file"
class="file-input"
(change)="onFileSelected($event)"
#fileUpload
style="display: none"
/>
</div>
</div>
<div mat-dialog-actions class="action">
<button
mat-raised-button
type="button"
color="warn"
[mat-dialog-close]="false"
>
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BlackListAddComponent } from './black-list-add.component';
describe('BlackListAddComponent', () => {
let component: BlackListAddComponent;
let fixture: ComponentFixture<BlackListAddComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BlackListAddComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BlackListAddComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
import { BlackListService } from '../../../services/Blacklists/black-list.service';
@Component({
selector: 'app-black-list-add',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
NgxCurrencyDirective,
],
templateUrl: './black-list-add.component.html',
styleUrl: './black-list-add.component.scss'
})
export class BlackListAddComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria: number[] = [1, 2];
constructor(
private _fb: FormBuilder,
private _empService: BlackListService,
@Inject(MAT_DIALOG_DATA) public data: any,
private _dialogRef: MatDialogRef<BlackListAddComponent>,
private toastService: ToastrService
) {
this.empForm = this._fb.group({
imo: [this.data?.imo || '', Validators.required],
reason: ['', Validators.required],
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data.empForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
onFormSubmit() {
console.log(JSON.stringify(this.empForm.value));
if (this.empForm.valid) {
this._empService.addEmployee(this.empForm.value).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Navio cadastrado na Black-List com sucesso!');
},
error: (err: any) => {
console.error(err);
},
});
}
}
}
<div mat-dialog-title>
<h1>{{ "Editar Navio" }}</h1>
</div>
<form [formGroup]="blackListForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input
matInput
type="number"
(keydown)="preventNegative($event)"
min="0"
formControlName="imo"
/>
<mat-error *ngIf="blackListForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Motivo</mat-label>
<input matInput type="text" formControlName="reason" value="{{blackListForm.get('reason')}}"/>
<mat-error *ngIf="blackListForm.get('reason')?.invalid">{{
getErrorMessage("reason")
}}</mat-error>
</mat-form-field>
</div>
<div class="row file-upload-container">
<input
type="file"
class="file-input"
(change)="onFileSelected($event)"
#fileUpload
style="display: none"
/>
</div>
</div>
<div mat-dialog-actions class="action">
<button
mat-raised-button
type="button"
color="warn"
[mat-dialog-close]="false"
>
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 50px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
.file-upload-container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20px;
}
.file-upload-content {
display: flex;
align-items: start;
justify-content: space-between;
width: 100%;
max-width: 400px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 8px;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
}
.file-info {
flex-grow: 1;
padding-right: 10px;
font-size: 14px;
color: #666;
}
@media (max-width: 600px) {
.field.large,
.field.medium,
.field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BlackListEditComponent } from './black-list-edit.component';
describe('BlackListEditComponent', () => {
let component: BlackListEditComponent;
let fixture: ComponentFixture<BlackListEditComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BlackListEditComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BlackListEditComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
import { BlackListService } from '../../../services/Blacklists/black-list.service';
@Component({
selector: 'app-black-list-edit',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
NgxCurrencyDirective,
],
templateUrl: './black-list-edit.component.html',
styleUrl: './black-list-edit.component.scss'
})
export class BlackListEdit implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
blackListForm: FormGroup;
selectedFile: File | null = null;
categoria: number[] = [1, 2];
constructor(
private _fb: FormBuilder,
private _empService: BlackListService,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService,
private _dialogRef: MatDialogRef<BlackListEdit>,
) {
this.blackListForm = this._fb.group({
imo: [this.data?.imo || '', Validators.required],
reason: [this.data?.reason || '', Validators.required],
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.blackListForm.patchValue(this.data.blackListForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.blackListForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.blackListForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
onFormSubmit() {
if (this.blackListForm.valid) {
if (this.data) {
this._empService.updateEmployee(this.data.id, this.blackListForm.value).subscribe({
next: (val: any) => {
this.toastService.success('Detalhes da Black-List atualizados!');
this._dialogRef.close(true);
},
error: (err: any) => {
console.error(err);
},
});
}
}
}
}
\ No newline at end of file
<app-add-search
[title]="'Black List'"
[primaryButtonText]="'Adicionar Navio'"
[primaryButtonColor]="'primary'"
[primaryButtonAction]="openAddEmpForm.bind(this)"
>
</app-add-search>
<div class="main-body">
<div class="table-container" style="overflow-x: auto">
<table mat-table [dataSource]="dataSource" matSort>
<!-- ID Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<!-- IMO Column -->
<ng-container matColumnDef="imo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>IMO</th>
<td mat-cell *matCellDef="let row">{{ row.imo || "Null" }}</td>
</ng-container>
<!-- MMSI Column -->
<ng-container matColumnDef="mmsi">
<th mat-header-cell *matHeaderCellDef mat-sort-header>MMSI</th>
<td mat-cell *matCellDef="let row">{{ row.mmsi || "Null" }}</td>
</ng-container>
<!-- Nome Column -->
<ng-container matColumnDef="nome">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
<td mat-cell *matCellDef="let row">{{ row.nome || "Null" }}</td>
</ng-container>
<!-- Categoria Column -->
<ng-container matColumnDef="categoria">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Categoria</th>
<td mat-cell *matCellDef="let row">
{{ row.categoria == 1 ? "Granel Sólido" : "Granel Líquido" }}
</td>
</ng-container>
<!-- Flag Column -->
<ng-container matColumnDef="flag">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Flag</th>
<td mat-cell *matCellDef="let row">{{ row.flag || "Null" }}</td>
</ng-container>
<!-- Action Column -->
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>Action</th>
<td mat-cell *matCellDef="let row" style="white-space: nowrap">
<button mat-icon-button (click)="openEditForm(row)" *ngIf="user.role === 'COMPANY'"
mat-icon-button
color="accent"
>
<mat-icon style="color: coral">edit</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="getAceiteById(row)">
<mat-icon>visibility</mat-icon>
</button>
<button mat-icon-button color="warn" (click)="deleteEmployee(row.id)" *ngIf="user.role === 'COMPANY'"
mat-icon-button
color="accent">
<mat-icon>delete</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<!-- Add paginator reference #paginator="matPaginator" -->
<mat-paginator
#paginator
[length]="totalItems"
[pageSize]="pageSize"
(page)="loadData($event)"
>
</mat-paginator>
<!-- Buttons for navigating to the first and last page -->
<button
mat-button
(click)="paginator.firstPage()"
[disabled]="paginator.pageIndex === 0"
>
Primeira Página
</button>
<button
mat-button
(click)="paginator.lastPage()"
[disabled]="paginator.pageIndex === paginator.getNumberOfPages() - 1"
>
Última Página
</button>
</div>
.example-spacer {
flex: 1 1 auto;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 600px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { BlackListComponent } from './black-list.component';
describe('BlackListComponent', () => {
let component: BlackListComponent;
let fixture: ComponentFixture<BlackListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [BlackListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(BlackListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTableModule } from '@angular/material/table';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { PageEvent } from '@angular/material/paginator';
import { AddSearchComponent } from '../../../shared/addAndSearch/add-search/add-search.component';
import { JwtDecoderService } from '../../../jwt-decoder.service';
import { AuthService } from '../../../auth.service';
import { jwtDecode } from 'jwt-decode';
import { BlackListAddComponent } from '../../crud-blackList/black-list-add/black-list-add.component';
import { BlackListEdit } from '../black-list-edit/black-list-edit.component';
import { BlackListService } from '../../../services/Blacklists/black-list.service';
import { VisualizacaoBlackListComponent } from '../visualizacao-black-list/visualizacao-black-list.component';
interface NavioData {
id: number;
imo: number;
mmsi: number;
nome: string;
loa: number;
boca: number;
dwt: number;
pontal: number;
ponte_mfold: number;
mfold_quilha: number;
categoria: number;
flag: string;
obs: string;
action: number;
}
@Component({
selector: 'app-black-list',
standalone: true,
imports: [
MatPaginatorModule,
MatToolbarModule,
MatTableModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
MatSortModule,
AddSearchComponent,
],
templateUrl: './black-list.component.html',
styleUrl: './black-list.component.scss',
})
export class BlackListComponent {
user: any;
authTokenPresent = false;
totalItems = 100;
pageSize = 10;
currentPage = 1;
displayedColumns: string[] = [
'id',
'imo',
'mmsi',
'nome',
'categoria',
'flag',
'action',
];
dataSource = new MatTableDataSource<NavioData>();
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
constructor(
private _dialog: MatDialog,
private _navioService: BlackListService,
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private _coreService: CoreService,
private cdr: ChangeDetectorRef,
) {}
ngOnInit(): void {
this.validationToken();
}
ngAfterViewInit(): void {
this.loadData();
}
validationToken() {
this.authService.authToken$.subscribe((isLoggedIn) => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp
? this.user.exp < Date.now() / 1000
: false;
if (isExpired) {
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
loadData(event?: PageEvent) {
const pageIndex = event ? event.pageIndex + 1 : this.currentPage - 1;
this._navioService.getEmployeeList(pageIndex, this.pageSize).subscribe({
next: (res: any) => {
const navios = res._embedded.blackListResponseList;
console.log(navios);
this.dataSource.data = navios;
this.totalItems = res.page.totalElements;
console.log(res.page.totalElements);
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
deleteEmployee(id: number) {
this._navioService.deleteEmployee(id).subscribe({
next: () => {
this._coreService.openSnackBar('Navio deleted!', 'done');
this.loadData();
},
error: (err: any) => {
this._coreService.openSnackBar(err.error.title);
},
});
}
openEditForm(data: any) {
this._dialog.open(BlackListEdit, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
addBlackList(data:any){
this._dialog.open(BlackListAddComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
openAddEmpForm() {
this._dialog.open(BlackListAddComponent,{autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo}));
})
this.cdr.detectChanges();
}
getAceiteById(data: any) {
this._dialog.open(VisualizacaoBlackListComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
width: '800px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
}
<mat-card>
<mat-card-header>
<mat-card-title>BlackList</mat-card-title>
<mat-card-subtitle>Nome do Navio: {{ data.nome || 'Não informado' }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="row" style="display: flex; flex-wrap: wrap; justify-content: space-between;">
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>ID:</strong> {{ navioInfo.id || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>IMO:</strong> {{ data.imo || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>MMSI:</strong> {{ navioInfo.mmsi || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Nome:</strong> {{ navioInfo.nome || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>LOA:</strong> {{ navioInfo.loa || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Boca:</strong> {{ navioInfo.boca || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>DWT:</strong> {{ navioInfo.dwt || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Pontal:</strong> {{ navioInfo.pontal || 'Não informado' }}</p>
</div>
<!--
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Ponte Mfold:</strong> {{ navioInfo.ponte_mfold || 'Não informado' }}</p>
</div>
-->
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Mfold Quilha:</strong> {{ navioInfo.mfold_quilha || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Categoria:</strong>
{{ navioInfo.categoria === 1 ? 'Granel Sólido' : (navioInfo.categoria === 2 ? 'Granel Líquido' : (navioInfo.categoria === 3 ? 'Carga Geral' : 'Não informado')) }}
</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Flag:</strong>
<ng-container *ngIf="navioInfo.flag; else flagNotAvailable">
<img [src]="countries[navioInfo.flag].flagUrl" width="20" height="15" alt="{{ countries[navioInfo.flag].name }} flag" style="margin-right: 8px" />
<p>{{ countries[navioInfo.flag]?.name }}</p>
</ng-container>
<ng-template #flagNotAvailable>Não informado</ng-template>
</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Observações:</strong> {{ data.reason || 'Não informado' }}</p>
</div>
</div>
</mat-card-content>
</mat-card>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VisualizacaoBlackListComponent } from './visualizacao-black-list.component';
describe('VisualizacaoBlackListComponent', () => {
let component: VisualizacaoBlackListComponent;
let fixture: ComponentFixture<VisualizacaoBlackListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [VisualizacaoBlackListComponent]
})
.compileComponents();
fixture = TestBed.createComponent(VisualizacaoBlackListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatGridTile } from '@angular/material/grid-list';
import { MatGridList } from '@angular/material/grid-list';
import { HttpClient } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
import { NavioService } from '../../../services/navio.service';
import { BlackListService } from '../../../services/Blacklists/black-list.service';
@Component({
selector: 'app-visualizacao-black-list',
standalone: true,
imports: [CommonModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule,
MatInputModule,MatGridTile,MatGridList,HttpClientModule],
templateUrl: './visualizacao-black-list.component.html',
styleUrl: './visualizacao-black-list.component.scss'
})
export class VisualizacaoBlackListComponent implements OnInit {
navioInfo: any = {}; // Informações do navio
entradaInfo: { imo: string; descricao: string } = { imo: '', descricao: '' }; // Informações de entrada
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
private _navioService: BlackListService
) {}
ngOnInit(): void {
this.carregarNavio();
}
carregarNavio() {
this._navioService.getEmployeebyIMO(this.data.imo).subscribe((res) => {
this.navioInfo = res; // Armazena as informações do navio
});
}
salvar() {
console.log('Informações de Entrada:', this.entradaInfo);
// Adicione a lógica para salvar as informações de entrada
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
}
<div mat-dialog-title>
<h1>{{ "Adicionar Navio" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input
matInput
type="number"
(keydown)="preventNegative($event)"
min="0"
formControlName="imo"
/>
<mat-error *ngIf="empForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field full-width" appearance="outline">
<mat-label>MMSI</mat-label>
<input
matInput
type="number"
formControlName="mmsi"
(keydown)="preventNegative($event)"
/>
<mat-error *ngIf="empForm.get('mmsi')?.invalid">{{
getErrorMessage("mmsi")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome" />
<mat-error *ngIf="empForm.get('nome')?.invalid">{{
getErrorMessage("nome")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>LOA</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="loa"
[currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('loa')?.invalid">{{
getErrorMessage("loa")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Boca</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="boca"
[currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('boca')?.invalid">{{
getErrorMessage("boca")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>DWT</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="dwt"
[currencyMask]="{ prefix: 'Tons ', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('dwt')?.invalid">{{
getErrorMessage("dwt")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Pontal</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="pontal"
[currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('pontal')?.invalid">{{
getErrorMessage("pontal")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Ponte Mfold</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="ponte_mfold"
[currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('ponte_mfold')?.invalid">{{
getErrorMessage("ponte_mfold")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Mfold Quilha</mat-label>
<input
matInput
type="text"
(keydown)="preventNegative($event)"
min="0"
formControlName="mfold_quilha"
[currencyMask]="{ prefix: '', thousands: '.', decimal: ',' }"
/>
<mat-error *ngIf="empForm.get('mfold_quilha')?.invalid">{{
getErrorMessage("mfold_quilha")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat.id">
{{ cat.nome }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{ getErrorMessage('categoria') }}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Observação</mat-label>
<input matInput type="text" formControlName="obs" />
<mat-error *ngIf="empForm.get('obs')?.invalid">{{
getErrorMessage("obs")
}}</mat-error>
</mat-form-field>
</div>
<div class="row file-upload-container">
<mat-label style="color:cadetblue">Adicione o documente Q88 da embarcação</mat-label>
<input
type="file"
class="file-input"
(change)="onFileSelected($event)"
#fileUpload
style="display: none"
/>
<div class="file-upload-content">
<div class="file-info">
<span>{{ fileName || "No file uploaded yet." }}</span>
</div>
<div class="upload-button-wrapper">
<button
mat-mini-fab
color="primary"
class="upload-btn"
(click)="fileUpload.click()"
>
<mat-icon>attach_file</mat-icon>
</button>
</div>
</div>
<div class="uploaded-image-container" *ngIf="imageUrl">
<img [src]="imageUrl" alt="Uploaded Image" class="uploaded-image" />
<button
mat-mini-fab
color="warn"
class="remove-image-btn"
(click)="removeImage()"
>
<mat-icon>close</mat-icon>
</button>
</div>
</div>
</div>
<div mat-dialog-actions class="action">
<button
mat-raised-button
type="button"
color="warn"
[mat-dialog-close]="false"
>
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
.file-upload-container {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 20px;
}
.file-upload-content {
display: flex;
align-items: start;
justify-content: space-between;
width: 100%;
max-width: 400px;
padding: 10px;
background-color: #f5f5f5;
border-radius: 8px;
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.1);
}
.file-info {
flex-grow: 1;
padding-right: 10px;
font-size: 14px;
color: #666;
}
.upload-button-wrapper {
display: flex;
align-items: start;
}
.upload-btn {
cursor: pointer;
}
.uploaded-image-container {
margin-top: 20px;
text-align: center;
}
.uploaded-image {
max-width: 100%;
height: auto;
border-radius: 8px;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.2);
}
@media (max-width: 600px) {
.field.large,
.field.medium,
.field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NavioAddComponent } from './navio-add.component';
describe('NavioAddComponent', () => {
let component: NavioAddComponent;
let fixture: ComponentFixture<NavioAddComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NavioAddComponent],
}).compileComponents();
fixture = TestBed.createComponent(NavioAddComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { NaviosComponent } from '../navios/navios.component';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
@Component({
selector: 'app-navio-add',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
NaviosComponent,
NgxCurrencyDirective,
],
templateUrl: './navio-add.component.html',
styleUrl: './navio-add.component.scss',
})
export class NavioAddComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria = [
{ id: 1, nome: 'Granel Sólido' },
{ id: 2, nome: 'Granel Líquido' },
{ id: 3, nome: 'Carga Geral' }
];
constructor(
private _fb: FormBuilder,
private _empService: NavioService,
private _dialogRef: MatDialogRef<NavioAddComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService
) {
this.empForm = this._fb.group({
imo: ['', Validators.required],
mmsi: ['', Validators.required],
nome: ['', Validators.required],
loa: ['', Validators.required],
boca: ['', Validators.required],
dwt: ['', Validators.required],
pontal: ['', Validators.required],
ponte_mfold: ['', Validators.required],
mfold_quilha: ['', Validators.required],
categoria: ['', Validators.required],
flag: ['', Validators.required],
obs: [''],
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data.empForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
onFormSubmit() {
console.log(JSON.stringify(this.empForm.value));
if (this.empForm.valid) {
if (this.selectedFile) {
this._empService.addEmployee1(this.empForm.value, this.selectedFile).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Navio cadastrado com sucesso!');
},
error: (err: any) => {
console.error(err);
},
});
} else {
console.error('Nenhum arquivo selecionado');
}
}
}
}
\ No newline at end of file
<div mat-dialog-title>
<h1>{{ data ? "Editar Navio" : "Adicionar Navio" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content" tabindex="0">
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input matInput type="number" (keydown)="preventNegative($event)" min="0" formControlName="imo" />
<mat-error *ngIf="empForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field full-width" appearance="outline">
<mat-label>MMSI</mat-label>
<input matInput type="text" formControlName="mmsi" (keydown)="preventNegative($event)" />
<mat-error *ngIf="empForm.get('mmsi')?.invalid">{{
getErrorMessage("mmsi")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Nome</mat-label>
<input matInput type="text" formControlName="nome" />
<mat-error *ngIf="empForm.get('nome')?.invalid">{{
getErrorMessage("nome")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>LOA (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
formControlName="loa" />
<mat-error *ngIf="empForm.get('loa')?.invalid">{{
getErrorMessage("loa")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Boca (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
formControlName="boca" />
<mat-error *ngIf="empForm.get('boca')?.invalid">{{
getErrorMessage("boca")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>DWT</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: 'tons ', thousands: '.', decimal: ',' }"
formControlName="dwt" />
<mat-error *ngIf="empForm.get('dwt')?.invalid">{{
getErrorMessage("dwt")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Pontal (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
formControlName="pontal" />
<mat-error *ngIf="empForm.get('pontal')?.invalid">{{
getErrorMessage("pontal")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Ponte Mfold (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
formControlName="ponte_mfold" />
<mat-error *ngIf="empForm.get('ponte_mfold')?.invalid">{{
getErrorMessage("ponte_mfold")
}}</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field large" appearance="outline">
<mat-label>Mfold Quilha (m)</mat-label>
<input matInput type="text" [currencyMask]="{ prefix: ' ', thousands: '.', decimal: ',' }"
formControlName="mfold_quilha" />
<mat-error *ngIf="empForm.get('mfold_quilha')?.invalid">{{
getErrorMessage("mfold_quilha")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option [value]="1">Granel Sólido</mat-option>
<mat-option [value]="2">Granel Líquido</mat-option>
<mat-option [value]="3">Carga Geral</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">
{{ getErrorMessage("categoria") }}
</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
<div class="row">
<mat-form-field class="field full-width" appearance="outline">
<mat-label>Observação</mat-label>
<input matInput type="text" formControlName="obs" />
<mat-error *ngIf="empForm.get('obs')?.invalid">{{
getErrorMessage("obs")
}}</mat-error>
</mat-form-field>
</div>
<div class="row file-upload-container">
<mat-label style="color:cadetblue">Adicione o documente Q88 da embarcação</mat-label>
<input type="file" class="file-input" (change)="onFileSelected($event)" #fileUpload style="display: none" />
<div class="file-upload-content">
<div class="file-info">
<span>{{ fileName || "No file uploaded yet." }}</span>
</div>
<div class="upload-button-wrapper">
<button mat-mini-fab color="primary" class="upload-btn" (click)="fileUpload.click()" type="button">
<mat-icon>attach_file</mat-icon>
</button>
</div>
</div>
<div class="uploaded-image-container" *ngIf="imageUrl">
<img [src]="imageUrl" alt="Uploaded Image" class="uploaded-image" />
<button mat-mini-fab color="warn" class="remove-image-btn" (click)="removeImage()">
<mat-icon>close</mat-icon>
</button>
</div>
</div>
</div>
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Salvar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large,
.field.medium,
.field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NavioEditComponent } from './navio-edit.component';
describe('NavioEditComponent', () => {
let component: NavioEditComponent;
let fixture: ComponentFixture<NavioEditComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NavioEditComponent],
}).compileComponents();
fixture = TestBed.createComponent(NavioEditComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { NaviosComponent } from '../navios/navios.component';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
@Component({
selector: 'app-navio-edit',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
NaviosComponent,
NgxCurrencyDirective,
],
templateUrl: './navio-edit.component.html',
styleUrl: './navio-edit.component.scss',
})
export class NavioEditComponent implements OnInit {
empForm: FormGroup;
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
selectedFile: File | null = null;
categoria: number[] = [1, 2];
constructor(
private _fb: FormBuilder,
private _empService: NavioService,
private _dialogRef: MatDialogRef<NavioService>,
@Inject(MAT_DIALOG_DATA) public data: any,
private _coreService: CoreService,
private toastService: ToastrService
) {
this.empForm = this._fb.group({
imo: [this.data?.imo || '', Validators.required],
mmsi: [this.data?.mmsi || ''],
nome: [this.data?.nome || '', Validators.required],
loa: [this.data?.loa || '', Validators.required],
boca: [this.data?.boca || '', Validators.required],
dwt: [this.data?.dwt || '', Validators.required],
pontal: [this.data?.pontal || '', Validators.required],
ponte_mfold: [this.data?.ponte_mfold || '',],
mfold_quilha: [this.data?.mfold_quilha || '',],
categoria: [Number(this.data?.categoria) || '', Validators.required],
flag: [Number(this.data?.flag) || '', Validators.required],
obs: [this.data?.obs || ''],
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { name: string; flagUrl: string } | null = null;
onCountrySelected(country: { name: string; flagUrl: string }) {
this.selectedCountry = country;
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
console.log(this.data)
}
removeImage() {
this.imageUrl = null;
this.fileName = '';
}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
return '';
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}
}
onFormSubmit() {
console.log(JSON.stringify(this.empForm.value));
if (this.empForm.valid) {
if (this.selectedFile) {
this._empService.editEmployeeWithUpload(this.data.id, this.empForm.value, this.selectedFile).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Navio cadastrado com sucesso!');
},
error: (err: any) => {
console.error(err);
},
});
} else {
this._empService.editEmployeeWithUpload(this.data.id, this.empForm.value, null).subscribe({
next: () => {
this._dialogRef.close(true);
this.toastService.success('Navio editado com sucesso!');
},
error: (err: any) => {
console.error(err);
},
});
}
}
}
}
<div mat-dialog-title>
<h1>{{ "Buscar Navio" }}</h1>
</div>
<form [formGroup]="empForm" (ngSubmit)="onFormSubmit()">
<div mat-dialog-content class="content">
<div class="row">
<!-- IMO -->
<mat-form-field class="field full-width" appearance="outline">
<mat-label>IMO</mat-label>
<input
matInput
type="number"
(keydown)="preventNegative($event)"
min="0"
formControlName="imo"
/>
<mat-error *ngIf="empForm.get('imo')?.invalid">{{
getErrorMessage("imo")
}}</mat-error>
</mat-form-field>
</div>
<!--
<mat-form-field class="field medium" appearance="outline">
<mat-label>Categoria</mat-label>
<mat-select formControlName="categoria">
<mat-option *ngFor="let cat of categoria" [value]="cat">
{{ cat === 1 ? "Granel Sólido" : cat === 2 ? "Granel Líquido" : "Carga Geral" }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('categoria')?.invalid">{{
getErrorMessage("categoria")
}}</mat-error>
</mat-form-field>
<mat-form-field class="field small" appearance="outline">
<mat-label>Flag</mat-label>
<mat-select formControlName="flag">
<mat-select-trigger>
<img
*ngIf="selectedCountry"
[src]="selectedCountry.flagUrl"
width="20"
height="15"
alt="{{ selectedCountry.name }} flag"
style="margin-right: 8px"
/>
{{ selectedCountry?.name }}
</mat-select-trigger>
<mat-option
*ngFor="let country of countries"
[value]="country.id"
(onSelectionChange)="onCountrySelected(country)"
>
<img
[src]="country.flagUrl"
width="20"
height="15"
alt="{{ country.name }} flag"
style="margin-right: 8px"
/>
{{ country.name }}
</mat-option>
</mat-select>
<mat-error *ngIf="empForm.get('flag')?.invalid">
{{ getErrorMessage("flag") }}
</mat-error>
</mat-form-field>
</div>
-->
</div>
<div mat-dialog-actions class="action">
<button mat-raised-button type="button" color="warn" [mat-dialog-close]="false">
Cancelar
</button>
<button mat-raised-button color="primary" type="submit">Buscar</button>
</div>
</form>
\ No newline at end of file
.content {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NavioSearchComponent } from './navio-search.component';
describe('NavioSearchComponent', () => {
let component: NavioSearchComponent;
let fixture: ComponentFixture<NavioSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NavioSearchComponent]
})
.compileComponents();
fixture = TestBed.createComponent(NavioSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon'; // Corrigido
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { NaviosComponent } from '../navios/navios.component';
import { ToastrService } from 'ngx-toastr';
import { NgxCurrencyDirective } from 'ngx-currency';
@Component({
selector: 'app-navio-search',
standalone: true,
imports: [
MatDialogModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
NaviosComponent,
NgxCurrencyDirective,
],
templateUrl: './navio-search.component.html',
styleUrl: './navio-search.component.scss',
})
export class NavioSearchComponent implements OnInit {
fileName = '';
imageUrl: string | ArrayBuffer | null = '';
empForm: FormGroup;
selectedFile: File | null = null;
categoria: number[] = [1, 2, 3];
constructor(
private _fb: FormBuilder,
private _empService: NavioService,
private _dialogRef: MatDialogRef<NavioSearchComponent>,
@Inject(MAT_DIALOG_DATA) public data: any,
private toastService: ToastrService,
private cdr: ChangeDetectorRef,
) {
this.empForm = this._fb.group({
imo: [''],
categoria: [''],
flag: [''],
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
preventNegative(event: KeyboardEvent): void {
if (event.key === '-' || event.key === '+' || event.key === 'e') {
event.preventDefault();
}
}
ngOnInit(): void {
if (this.data) {
this.empForm.patchValue(this.data.empForm);
}
}
onFileSelected(event: Event): void {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const file = input.files[0];
const allowedTypes = ['application/pdf', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'];
if (!allowedTypes.includes(file.type)) {
this.toastService.error('Apenas arquivos PDF ou Word são permitidos.');
return;
}
this.selectedFile = file;
this.fileName = file.name;
const reader = new FileReader();
reader.onload = (e) => {
this.imageUrl = (e.target?.result as string) || '';
};
reader.readAsDataURL(file);
}}
getErrorMessage(formControlName: string): string {
if (this.empForm.get(formControlName)?.hasError('required')) {
return 'Campo obrigatório';
}
if (this.empForm.get(formControlName)?.hasError('email')) {
return 'E-mail inválido';
}
return '';
}
onFormSubmit() {
if (this.empForm.valid) {
const searchCriteria = {
imo: this.empForm.value.imo,
categoria: this.empForm.value.categoria,
flag: this.empForm.value.flag,
};
this._empService.searchNavios(searchCriteria).subscribe({
next: (val: any) => {
this.toastService.success('Busca realizada com sucesso');
this._dialogRef.close(true);
},
error: (err: any) => {
console.error(err);
}
});
}
}
}
<app-add-search
[title]="'Navios'"
[primaryButtonText]="'Adicionar Navio'"
[primaryButtonColor]="'primary'"
[primaryButtonAction]="openAddEmpForm.bind(this)"
[secondaryButtonText]="'Buscar Navio'"
[secondaryButtonColor]="'accent'"
[secondaryButtonAction]="openAddEmpFormSearch.bind(this)"
>
</app-add-search>
<div class="main-body">
<div class="table-container" style="overflow-x: auto">
<table mat-table [dataSource]="dataSource" matSort>
<!-- ID Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID</th>
<td mat-cell *matCellDef="let row">{{ row.id }}</td>
</ng-container>
<!-- IMO Column -->
<ng-container matColumnDef="imo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>IMO</th>
<td mat-cell *matCellDef="let row">{{ row.imo || "Null" }}</td>
</ng-container>
<!-- MMSI Column -->
<ng-container matColumnDef="mmsi">
<th mat-header-cell *matHeaderCellDef mat-sort-header>MMSI</th>
<td mat-cell *matCellDef="let row">{{ row.mmsi || "Null" }}</td>
</ng-container>
<!-- Nome Column -->
<ng-container matColumnDef="nome">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Nome</th>
<td mat-cell *matCellDef="let row">{{ row.nome || "Null" }}</td>
</ng-container>
<!-- Categoria Column -->
<ng-container matColumnDef="categoria">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Categoria</th>
<td mat-cell *matCellDef="let row">
{{ row.categoria == 1 ? "Granel Sólido" : "Granel Líquido" }}
</td>
</ng-container>
<!-- Flag Column -->
<ng-container matColumnDef="flag">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Flag</th>
<td mat-cell *matCellDef="let row">
<ng-container *ngIf="row.flag; else noFlag">
<div style="display: inline-flex; align-items: center;">
<img
[src]="countries[row.flag]?.flagUrl"
width="20"
height="15"
alt="{{ countries[row.flag]?.name }} flag"
style="margin-right: 8px"
/>
<span>{{ countries[row.flag]?.name }}</span>
</div>
</ng-container>
<ng-template #noFlag>Não Informado</ng-template>
</td>
</ng-container>
<!-- Action Column -->
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef>Action</th>
<td mat-cell *matCellDef="let row" style="white-space: nowrap">
<button mat-icon-button (click)="openEditForm(row)">
<mat-icon style="color: coral">edit</mat-icon>
</button>
<button mat-icon-button color="primary" (click)="getAceiteById(row)">
<mat-icon>visibility</mat-icon>
</button>
<button mat-icon-button color="warn" (click)="deleteEmployee(row.id)" *ngIf="user.role === 'COMPANY'">
<mat-icon>delete</mat-icon>
</button>
<button
*ngIf="user.role === 'COMPANY'"
mat-icon-button
color="accent"
(click)="addBlackList(row)"
>
<mat-icon>block</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<!-- Add paginator reference #paginator="matPaginator" -->
<mat-paginator
#paginator
[length]="totalItems"
[pageSize]="pageSize"
(page)="loadData($event)"
>
</mat-paginator>
<!-- Buttons for navigating to the first and last page -->
<button
mat-button
(click)="paginator.firstPage()"
[disabled]="paginator.pageIndex === 0"
>
Primeira Página
</button>
<button
mat-button
(click)="paginator.lastPage()"
[disabled]="paginator.pageIndex === paginator.getNumberOfPages() - 1"
>
Última Página
</button>
</div>
\ No newline at end of file
.example-spacer {
flex: 1 1 auto;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 600px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {NaviosComponent } from './navios.component';
describe('NaviosComponent', () => {
let component: NaviosComponent;
let fixture: ComponentFixture<NaviosComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NaviosComponent]
})
.compileComponents();
fixture = TestBed.createComponent(NaviosComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatPaginator } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { NavioService } from '../../../services/navio.service';
import { CoreService } from '../../../core/core.service';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatTableModule } from '@angular/material/table';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatPaginatorModule } from '@angular/material/paginator';
import { MatSortModule } from '@angular/material/sort';
import { NavioEditComponent } from '../navio-edit/navio-edit.component';
import { NavioAddComponent } from '../navio-add/navio-add.component';
import { VisualizacaoNavioComponent } from '../visualizacao-navio/visualizacao-navio.component';
import { PageEvent } from '@angular/material/paginator';
import { AddSearchComponent } from '../../../shared/addAndSearch/add-search/add-search.component';
import { NavioSearchComponent } from '../navio-search/navio-search.component';
import { JwtDecoderService } from '../../../jwt-decoder.service';
import { AuthService } from '../../../auth.service';
import { jwtDecode } from 'jwt-decode';
import { BlackListAddComponent } from '../../crud-blackList/black-list-add/black-list-add.component';
import { ToastrService } from 'ngx-toastr';
interface NavioData {
id: number;
imo: number;
mmsi: number;
nome: string;
loa: number;
boca: number;
dwt: number;
pontal: number;
ponte_mfold: number;
mfold_quilha: number;
categoria: number;
flag: string;
obs: string;
action: number;
}
@Component({
selector: 'app-navios',
standalone: true,
imports: [
MatPaginatorModule,
MatToolbarModule,
MatTableModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
MatSortModule,
AddSearchComponent,
],
templateUrl: './navios.component.html',
styleUrls: ['./navios.component.scss'],
})
export class NaviosComponent implements OnInit {
user: any;
authTokenPresent = false;
totalItems = 100;
pageSize = 10;
currentPage = 1;
displayedColumns: string[] = [
'id',
'imo',
'mmsi',
'nome',
'categoria',
'flag',
'action',
];
dataSource = new MatTableDataSource<NavioData>();
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
constructor(
private _dialog: MatDialog,
private _navioService: NavioService,
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private _coreService: CoreService,
private cdr: ChangeDetectorRef,
private toastService: ToastrService,
) {}
ngOnInit(): void {
this.validationToken();
}
ngAfterViewInit(): void {
this.loadData();
}
validationToken() {
this.authService.authToken$.subscribe((isLoggedIn) => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp
? this.user.exp < Date.now() / 1000
: false;
if (isExpired) {
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
loadData(event?: PageEvent): void {
const pageIndex = event ? event.pageIndex + 1 : this.currentPage - 1;
// Verifica se há dados no sessionStorage
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('naviosSearch');
if (storedData) {
const navios = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', navios);
// Atualiza os dados na tabela
this.dataSource.data = navios;
// Atualiza o total de itens para paginação (opcional)
this.totalItems = navios.length;
// Configurações do paginator e sort
if (this.paginator && this.sort) {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
// Remove dados do sessionStorage após o uso
sessionStorage.removeItem('naviosSearch');
console.log('naviosSearch removido do sessionStorage.');
return; // Retorna para evitar chamada à API
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
}
// Caso os dados não estejam no sessionStorage, chama a API
this._navioService.getEmployeeList(pageIndex, this.pageSize).subscribe({
next: (res: any) => {
const navios = res._embedded.vesselResponseList;
console.log(navios);
this.dataSource.data = navios;
this.totalItems = res.page.totalElements;
console.log(res.page.totalElements);
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
deleteEmployee(id: number) {
this._navioService.deleteEmployee(id).subscribe({
next: () => {
this.toastService.success('Navio deleted!');
//this._coreService.openSnackBar('Navio deleted!', 'done');
this.loadData();
},
error: (err: any) => {
this._coreService.openSnackBar(err.error.title);
},
});
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
selectedCountry: { id: number; name: string; flagUrl: string } | null = null;
onCountrySelected(country: { id: number; name: string; flagUrl: string }) {
this.selectedCountry = country;
}
openEditForm(data: any) {
this._dialog.open(NavioEditComponent, {
data, // Passa os dados para o componente de edição
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
addBlackList(data:any){
this._dialog.open(BlackListAddComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
openAddEmpForm() {
this._dialog.open(NavioAddComponent,{
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
openAddEmpFormSearch() {
this._dialog.open(NavioSearchComponent, {
width: '600px', // Ajuste o tamanho conforme necessário
panelClass: 'custom-dialog-container'
}); if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('naviosSearch');
if (storedData) {
const dataSource = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', dataSource);
this.dataSource.data = dataSource;
this.cdr.detectChanges();
// Atualiza a tabela com os dados
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
} else {
console.error('sessionStorage não está disponível.');
}
}
getAceiteById(data: any) {
this._dialog.open(VisualizacaoNavioComponent, {
data,
autoFocus: true, // Foca no primeiro campo interativo do formulário
width: '600px', // Define a largura do diálogo
});
}
}
<mat-card>
<mat-card-header>
<mat-card-title>Navio</mat-card-title>
<mat-card-subtitle>Nome do Navio: {{ data.nome || 'Não informado' }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<div class="row" style="display: flex; flex-wrap: wrap; justify-content: space-between;">
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>ID:</strong> {{ data.id || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>IMO:</strong> {{ data.imo || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>MMSI:</strong> {{ data.mmsi || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Nome:</strong> {{ data.nome || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>LOA:</strong> {{ data.loa || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Boca:</strong> {{ data.boca || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>DWT:</strong> {{ data.dwt || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Pontal:</strong> {{ data.pontal || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Ponte Mfold:</strong> {{ data.ponte_mfold || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Mfold Quilha:</strong> {{ data.mfold_quilha || 'Não informado' }}</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Categoria:</strong>
{{ data.categoria === 1 ? 'Granel Sólido' : (data.categoria === 2 ? 'Granel Líquido' : (data.categoria === 3 ? 'Carga Geral' : 'Não informado')) }}
</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Flag:</strong>
<ng-container *ngIf="data.flag; else flagNotAvailable">
<img [src]="countries[data.flag].flagUrl" width="20" height="15" alt="{{ countries[data.flag].name }} flag" style="margin-right: 8px" />
<p>{{ countries[data.flag]?.name }}</p>
</ng-container>
<ng-template #flagNotAvailable>Não informado</ng-template>
</p>
</div>
<div class="column" style="flex: 1 1 30%; margin-bottom: 10px;">
<p><strong>Observações:</strong> {{ data.obs || 'Não informado' }}</p>
</div>
</div>
</mat-card-content>
<ng-container *ngIf="data.path">
<mat-card-actions>
<button (click)="downloadNavioFunction()">Download Documento Q88</button>
</mat-card-actions>
</ng-container>
</mat-card>
.card {
padding-top: 10px;
}
.row {
display: flex;
flex-wrap: wrap;
gap: 5px;
margin-bottom: 20px;
}
.field {
margin-bottom: 5px;
}
.field.full-width {
flex: 1 1 100%;
}
.field.large {
flex: 1 1 60%;
}
.field.medium {
flex: 1 1 40%;
}
.field.small {
flex: 1 1 20%;
}
.action {
display: flex;
justify-content: flex-end;
padding: 5px 0;
gap: 10px;
margin: 10px; /* Adiciona margem ao redor do container do botão */
}
@media (max-width: 600px) {
.field.large, .field.medium, .field.small {
flex: 1 1 100%;
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { VisualizacaoNavioComponent } from './visualizacao-navio.component';
describe('VisualizacaoNavioComponent', () => {
let component: VisualizacaoNavioComponent;
let fixture: ComponentFixture<VisualizacaoNavioComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [VisualizacaoNavioComponent]
})
.compileComponents();
fixture = TestBed.createComponent(VisualizacaoNavioComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatGridTile } from '@angular/material/grid-list';
import { MatGridList } from '@angular/material/grid-list';
import { HttpClient } from '@angular/common/http';
import { HttpClientModule } from '@angular/common/http';
import { NavioService } from '../../../services/navio.service';
@Component({
selector: 'app-visualizacao-navio',
standalone: true,
imports: [
CommonModule,
MatButtonModule,
MatCardModule,
MatFormFieldModule,
MatInputModule,MatGridTile,MatGridList,HttpClientModule
],
templateUrl: './visualizacao-navio.component.html',
styleUrls: ['./visualizacao-navio.component.scss']
})
export class VisualizacaoNavioComponent implements OnInit {
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
private httpClient: HttpClient ,// Adicione isto
private httpView: NavioService
// Adicione isto
) {}
ngOnInit(): void {
this.printa();
}
printa() {
console.log(this.data);
}
countries = [
{ id: 1, name: 'Afeganistão', flagUrl: 'https://flagcdn.com/w20/af.png' },
{ id: 2, name: 'África do Sul', flagUrl: 'https://flagcdn.com/w20/za.png' },
{ id: 3, name: 'Albânia', flagUrl: 'https://flagcdn.com/w20/al.png' },
{ id: 4, name: 'Alemanha', flagUrl: 'https://flagcdn.com/w20/de.png' },
{ id: 5, name: 'Andorra', flagUrl: 'https://flagcdn.com/w20/ad.png' },
{ id: 6, name: 'Angola', flagUrl: 'https://flagcdn.com/w20/ao.png' },
{
id: 7,
name: 'Antígua e Barbuda',
flagUrl: 'https://flagcdn.com/w20/ag.png',
},
{
id: 8,
name: 'Arábia Saudita',
flagUrl: 'https://flagcdn.com/w20/sa.png',
},
{ id: 9, name: 'Argélia', flagUrl: 'https://flagcdn.com/w20/dz.png' },
{ id: 10, name: 'Argentina', flagUrl: 'https://flagcdn.com/w20/ar.png' },
{ id: 11, name: 'Armênia', flagUrl: 'https://flagcdn.com/w20/am.png' },
{ id: 12, name: 'Austrália', flagUrl: 'https://flagcdn.com/w20/au.png' },
{ id: 13, name: 'Áustria', flagUrl: 'https://flagcdn.com/w20/at.png' },
{ id: 14, name: 'Azerbaijão', flagUrl: 'https://flagcdn.com/w20/az.png' },
{ id: 15, name: 'Bahamas', flagUrl: 'https://flagcdn.com/w20/bs.png' },
{ id: 16, name: 'Bahrein', flagUrl: 'https://flagcdn.com/w20/bh.png' },
{ id: 17, name: 'Bangladesh', flagUrl: 'https://flagcdn.com/w20/bd.png' },
{ id: 18, name: 'Barbados', flagUrl: 'https://flagcdn.com/w20/bb.png' },
{ id: 19, name: 'Bélgica', flagUrl: 'https://flagcdn.com/w20/be.png' },
{ id: 20, name: 'Belize', flagUrl: 'https://flagcdn.com/w20/bz.png' },
{ id: 21, name: 'Benin', flagUrl: 'https://flagcdn.com/w20/bj.png' },
{ id: 22, name: 'Bielorrússia', flagUrl: 'https://flagcdn.com/w20/by.png' },
{ id: 23, name: 'Bolívia', flagUrl: 'https://flagcdn.com/w20/bo.png' },
{
id: 24,
name: 'Bósnia e Herzegovina',
flagUrl: 'https://flagcdn.com/w20/ba.png',
},
{ id: 25, name: 'Botswana', flagUrl: 'https://flagcdn.com/w20/bw.png' },
{ id: 26, name: 'Brasil', flagUrl: 'https://flagcdn.com/w20/br.png' },
{ id: 27, name: 'Brunei', flagUrl: 'https://flagcdn.com/w20/bn.png' },
{ id: 28, name: 'Bulgária', flagUrl: 'https://flagcdn.com/w20/bg.png' },
{ id: 29, name: 'Burkina Faso', flagUrl: 'https://flagcdn.com/w20/bf.png' },
{ id: 30, name: 'Burundi', flagUrl: 'https://flagcdn.com/w20/bi.png' },
{ id: 31, name: 'Butão', flagUrl: 'https://flagcdn.com/w20/bt.png' },
{ id: 32, name: 'Cabo Verde', flagUrl: 'https://flagcdn.com/w20/cv.png' },
{ id: 33, name: 'Camboja', flagUrl: 'https://flagcdn.com/w20/kh.png' },
{ id: 34, name: 'Camarões', flagUrl: 'https://flagcdn.com/w20/cm.png' },
{ id: 35, name: 'Canadá', flagUrl: 'https://flagcdn.com/w20/ca.png' },
{ id: 36, name: 'Catar', flagUrl: 'https://flagcdn.com/w20/qa.png' },
{ id: 37, name: 'Cazaquistão', flagUrl: 'https://flagcdn.com/w20/kz.png' },
{ id: 38, name: 'Chade', flagUrl: 'https://flagcdn.com/w20/td.png' },
{ id: 39, name: 'Chile', flagUrl: 'https://flagcdn.com/w20/cl.png' },
{ id: 40, name: 'China', flagUrl: 'https://flagcdn.com/w20/cn.png' },
{ id: 41, name: 'Chipre', flagUrl: 'https://flagcdn.com/w20/cy.png' },
{ id: 42, name: 'Colômbia', flagUrl: 'https://flagcdn.com/w20/co.png' },
{ id: 43, name: 'Comores', flagUrl: 'https://flagcdn.com/w20/km.png' },
{ id: 44, name: 'Congo', flagUrl: 'https://flagcdn.com/w20/cg.png' },
{
id: 45,
name: 'Costa do Marfim',
flagUrl: 'https://flagcdn.com/w20/ci.png',
},
{ id: 46, name: 'Costa Rica', flagUrl: 'https://flagcdn.com/w20/cr.png' },
{ id: 47, name: 'Croácia', flagUrl: 'https://flagcdn.com/w20/hr.png' },
{ id: 48, name: 'Cuba', flagUrl: 'https://flagcdn.com/w20/cu.png' },
{ id: 49, name: 'Dinamarca', flagUrl: 'https://flagcdn.com/w20/dk.png' },
{ id: 50, name: 'Dominica', flagUrl: 'https://flagcdn.com/w20/dm.png' },
{ id: 51, name: 'Egito', flagUrl: 'https://flagcdn.com/w20/eg.png' },
{ id: 52, name: 'El Salvador', flagUrl: 'https://flagcdn.com/w20/sv.png' },
{
id: 53,
name: 'Emirados Árabes Unidos',
flagUrl: 'https://flagcdn.com/w20/ae.png',
},
{ id: 54, name: 'Equador', flagUrl: 'https://flagcdn.com/w20/ec.png' },
{ id: 55, name: 'Eritreia', flagUrl: 'https://flagcdn.com/w20/er.png' },
{ id: 56, name: 'Eslováquia', flagUrl: 'https://flagcdn.com/w20/sk.png' },
{ id: 57, name: 'Eslovênia', flagUrl: 'https://flagcdn.com/w20/si.png' },
{ id: 58, name: 'Espanha', flagUrl: 'https://flagcdn.com/w20/es.png' },
{
id: 59,
name: 'Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{ id: 60, name: 'Estônia', flagUrl: 'https://flagcdn.com/w20/ee.png' },
{ id: 61, name: 'Eswatini', flagUrl: 'https://flagcdn.com/w20/sz.png' },
{ id: 62, name: 'Etiópia', flagUrl: 'https://flagcdn.com/w20/et.png' },
{ id: 63, name: 'Fiji', flagUrl: 'https://flagcdn.com/w20/fj.png' },
{ id: 64, name: 'Filipinas', flagUrl: 'https://flagcdn.com/w20/ph.png' },
{ id: 65, name: 'Finlândia', flagUrl: 'https://flagcdn.com/w20/fi.png' },
{ id: 66, name: 'França', flagUrl: 'https://flagcdn.com/w20/fr.png' },
{ id: 67, name: 'Guatemala', flagUrl: 'https://flagcdn.com/w20/gt.png' },
{ id: 68, name: 'Guiana', flagUrl: 'https://flagcdn.com/w20/gf.png' },
{ id: 69, name: 'Guiné', flagUrl: 'https://flagcdn.com/w20/gn.png' },
{ id: 70, name: 'Guiné-Bissau', flagUrl: 'https://flagcdn.com/w20/gw.png' },
{ id: 71, name: 'Haiti', flagUrl: 'https://flagcdn.com/w20/ht.png' },
{ id: 72, name: 'Honduras', flagUrl: 'https://flagcdn.com/w20/hn.png' },
{ id: 73, name: 'Hungria', flagUrl: 'https://flagcdn.com/w20/hu.png' },
{ id: 74, name: 'Iêmen', flagUrl: 'https://flagcdn.com/w20/ye.png' },
{
id: 75,
name: 'Ilhas Marshall',
flagUrl: 'https://flagcdn.com/w20/mh.png',
},
{
id: 76,
name: 'Ilhas Salomão',
flagUrl: 'https://flagcdn.com/w20/sb.png',
},
{ id: 77, name: 'Índia', flagUrl: 'https://flagcdn.com/w20/in.png' },
{ id: 78, name: 'Indonésia', flagUrl: 'https://flagcdn.com/w20/id.png' },
{ id: 79, name: 'Irã', flagUrl: 'https://flagcdn.com/w20/ir.png' },
{ id: 80, name: 'Iraque', flagUrl: 'https://flagcdn.com/w20/iq.png' },
{ id: 81, name: 'Irlanda', flagUrl: 'https://flagcdn.com/w20/ie.png' },
{ id: 82, name: 'Islândia', flagUrl: 'https://flagcdn.com/w20/is.png' },
{ id: 83, name: 'Israel', flagUrl: 'https://flagcdn.com/w20/il.png' },
{ id: 84, name: 'Itália', flagUrl: 'https://flagcdn.com/w20/it.png' },
{ id: 85, name: 'Jamaica', flagUrl: 'https://flagcdn.com/w20/jm.png' },
{ id: 86, name: 'Japão', flagUrl: 'https://flagcdn.com/w20/jp.png' },
{ id: 87, name: 'Jordânia', flagUrl: 'https://flagcdn.com/w20/jo.png' },
{ id: 88, name: 'Kosovo', flagUrl: 'https://flagcdn.com/w20/xk.png' },
{ id: 89, name: 'Kuwait', flagUrl: 'https://flagcdn.com/w20/kw.png' },
{ id: 90, name: 'Quirguistão', flagUrl: 'https://flagcdn.com/w20/kg.png' },
{ id: 91, name: 'Laos', flagUrl: 'https://flagcdn.com/w20/la.png' },
{ id: 92, name: 'Letônia', flagUrl: 'https://flagcdn.com/w20/lv.png' },
{ id: 93, name: 'Líbano', flagUrl: 'https://flagcdn.com/w20/lb.png' },
{ id: 94, name: 'Lesoto', flagUrl: 'https://flagcdn.com/w20/ls.png' },
{ id: 95, name: 'Libéria', flagUrl: 'https://flagcdn.com/w20/lr.png' },
{ id: 96, name: 'Líbia', flagUrl: 'https://flagcdn.com/w20/ly.png' },
{
id: 97,
name: 'Liechtenstein',
flagUrl: 'https://flagcdn.com/w20/li.png',
},
{ id: 98, name: 'Lituânia', flagUrl: 'https://flagcdn.com/w20/lt.png' },
{ id: 99, name: 'Luxemburgo', flagUrl: 'https://flagcdn.com/w20/lu.png' },
{
id: 100,
name: 'Macedônia do Norte',
flagUrl: 'https://flagcdn.com/w20/mk.png',
},
{ id: 101, name: 'Madagascar', flagUrl: 'https://flagcdn.com/w20/mg.png' },
{ id: 102, name: 'Malawi', flagUrl: 'https://flagcdn.com/w20/mw.png' },
{ id: 103, name: 'Malásia', flagUrl: 'https://flagcdn.com/w20/my.png' },
{ id: 104, name: 'Maldivas', flagUrl: 'https://flagcdn.com/w20/mv.png' },
{ id: 105, name: 'Mali', flagUrl: 'https://flagcdn.com/w20/ml.png' },
{ id: 106, name: 'Malta', flagUrl: 'https://flagcdn.com/w20/mt.png' },
{ id: 107, name: 'Mauritânia', flagUrl: 'https://flagcdn.com/w20/mr.png' },
{ id: 108, name: 'Maurício', flagUrl: 'https://flagcdn.com/w20/mu.png' },
{ id: 109, name: 'México', flagUrl: 'https://flagcdn.com/w20/mx.png' },
{ id: 110, name: 'Micronésia', flagUrl: 'https://flagcdn.com/w20/fm.png' },
{ id: 111, name: 'Moldávia', flagUrl: 'https://flagcdn.com/w20/md.png' },
{ id: 112, name: 'Mônaco', flagUrl: 'https://flagcdn.com/w20/mc.png' },
{ id: 113, name: 'Mongólia', flagUrl: 'https://flagcdn.com/w20/mn.png' },
{ id: 114, name: 'Montenegro', flagUrl: 'https://flagcdn.com/w20/me.png' },
{ id: 115, name: 'Marrocos', flagUrl: 'https://flagcdn.com/w20/ma.png' },
{ id: 116, name: 'Moçambique', flagUrl: 'https://flagcdn.com/w20/mz.png' },
{ id: 117, name: 'Myanmar', flagUrl: 'https://flagcdn.com/w20/mm.png' },
{ id: 118, name: 'Namíbia', flagUrl: 'https://flagcdn.com/w20/na.png' },
{ id: 119, name: 'Nauru', flagUrl: 'https://flagcdn.com/w20/nr.png' },
{ id: 120, name: 'Nepal', flagUrl: 'https://flagcdn.com/w20/np.png' },
{
id: 121,
name: 'Países Baixos',
flagUrl: 'https://flagcdn.com/w20/nl.png',
},
{
id: 122,
name: 'Nova Zelândia',
flagUrl: 'https://flagcdn.com/w20/nz.png',
},
{ id: 123, name: 'Nicarágua', flagUrl: 'https://flagcdn.com/w20/ni.png' },
{ id: 124, name: 'Níger', flagUrl: 'https://flagcdn.com/w20/ne.png' },
{ id: 125, name: 'Nigéria', flagUrl: 'https://flagcdn.com/w20/ng.png' },
{ id: 126, name: 'Noruega', flagUrl: 'https://flagcdn.com/w20/no.png' },
{ id: 127, name: 'Omã', flagUrl: 'https://flagcdn.com/w20/om.png' },
{ id: 128, name: 'Paquistão', flagUrl: 'https://flagcdn.com/w20/pk.png' },
{ id: 129, name: 'Palau', flagUrl: 'https://flagcdn.com/w20/pw.png' },
{ id: 130, name: 'Palestina', flagUrl: 'https://flagcdn.com/w20/ps.png' },
{ id: 131, name: 'Panamá', flagUrl: 'https://flagcdn.com/w20/pa.png' },
{
id: 132,
name: 'Papua Nova Guiné',
flagUrl: 'https://flagcdn.com/w20/pg.png',
},
{ id: 133, name: 'Paraguai', flagUrl: 'https://flagcdn.com/w20/py.png' },
{ id: 134, name: 'Peru', flagUrl: 'https://flagcdn.com/w20/pe.png' },
{ id: 135, name: 'Polônia', flagUrl: 'https://flagcdn.com/w20/pl.png' },
{ id: 136, name: 'Portugal', flagUrl: 'https://flagcdn.com/w20/pt.png' },
{ id: 137, name: 'Reino Unido', flagUrl: 'https://flagcdn.com/w20/gb.png' },
{
id: 138,
name: 'República Centro-Africana',
flagUrl: 'https://flagcdn.com/w20/cf.png',
},
{
id: 139,
name: 'República Dominicana',
flagUrl: 'https://flagcdn.com/w20/do.png',
},
{ id: 140, name: 'Romênia', flagUrl: 'https://flagcdn.com/w20/ro.png' },
{ id: 141, name: 'Ruanda', flagUrl: 'https://flagcdn.com/w20/rw.png' },
{ id: 142, name: 'Rússia', flagUrl: 'https://flagcdn.com/w20/ru.png' },
{
id: 143,
name: 'São Cristóvão e Nevis',
flagUrl: 'https://flagcdn.com/w20/kn.png',
},
{ id: 144, name: 'São Marino', flagUrl: 'https://flagcdn.com/w20/sm.png' },
{
id: 145,
name: 'São Tomé e Príncipe',
flagUrl: 'https://flagcdn.com/w20/st.png',
},
{
id: 146,
name: 'São Vicente e Granadinas',
flagUrl: 'https://flagcdn.com/w20/vc.png',
},
{ id: 147, name: 'Santa Lúcia', flagUrl: 'https://flagcdn.com/w20/lc.png' },
{ id: 148, name: 'Senegal', flagUrl: 'https://flagcdn.com/w20/sn.png' },
{ id: 149, name: 'Sérvia', flagUrl: 'https://flagcdn.com/w20/rs.png' },
{ id: 150, name: 'Seychelles', flagUrl: 'https://flagcdn.com/w20/sc.png' },
{ id: 151, name: 'Singapura', flagUrl: 'https://flagcdn.com/w20/sg.png' },
{ id: 152, name: 'Síria', flagUrl: 'https://flagcdn.com/w20/sy.png' },
{ id: 153, name: 'Somália', flagUrl: 'https://flagcdn.com/w20/so.png' },
{ id: 154, name: 'Sri Lanka', flagUrl: 'https://flagcdn.com/w20/lk.png' },
{ id: 155, name: 'Sudão', flagUrl: 'https://flagcdn.com/w20/sd.png' },
{
id: 156,
name: 'Sudão do Sul',
flagUrl: 'https://flagcdn.com/w20/ss.png',
},
{ id: 157, name: 'Suriname', flagUrl: 'https://flagcdn.com/w20/sr.png' },
{ id: 158, name: 'Suécia', flagUrl: 'https://flagcdn.com/w20/se.png' },
{ id: 159, name: 'Suíça', flagUrl: 'https://flagcdn.com/w20/ch.png' },
{ id: 160, name: 'Tajiquistão', flagUrl: 'https://flagcdn.com/w20/tj.png' },
{ id: 161, name: 'Tailândia', flagUrl: 'https://flagcdn.com/w20/th.png' },
{ id: 162, name: 'Timor-Leste', flagUrl: 'https://flagcdn.com/w20/tl.png' },
{ id: 163, name: 'Togo', flagUrl: 'https://flagcdn.com/w20/tg.png' },
{ id: 164, name: 'Tonga', flagUrl: 'https://flagcdn.com/w20/to.png' },
{
id: 165,
name: 'Trinidad e Tobago',
flagUrl: 'https://flagcdn.com/w20/tt.png',
},
{ id: 166, name: 'Tunísia', flagUrl: 'https://flagcdn.com/w20/tn.png' },
{ id: 167, name: 'Turquia', flagUrl: 'https://flagcdn.com/w20/tr.png' },
{
id: 168,
name: 'Turcomenistão',
flagUrl: 'https://flagcdn.com/w20/tm.png',
},
{ id: 169, name: 'Tuvalu', flagUrl: 'https://flagcdn.com/w20/tv.png' },
{ id: 170, name: 'Ucrânia', flagUrl: 'https://flagcdn.com/w20/ua.png' },
{ id: 171, name: 'Uganda', flagUrl: 'https://flagcdn.com/w20/ug.png' },
{ id: 172, name: 'Uruguai', flagUrl: 'https://flagcdn.com/w20/uy.png' },
{ id: 173, name: 'Uzbequistão', flagUrl: 'https://flagcdn.com/w20/uz.png' },
{ id: 174, name: 'Vanuatu', flagUrl: 'https://flagcdn.com/w20/vu.png' },
{ id: 175, name: 'Vaticano', flagUrl: 'https://flagcdn.com/w20/va.png' },
{ id: 176, name: 'Venezuela', flagUrl: 'https://flagcdn.com/w20/ve.png' },
{ id: 177, name: 'Vietnã', flagUrl: 'https://flagcdn.com/w20/vn.png' },
{ id: 178, name: 'Zâmbia', flagUrl: 'https://flagcdn.com/w20/zm.png' },
{ id: 179, name: 'Zimbábue', flagUrl: 'https://flagcdn.com/w20/zw.png' },
{
id: 180,
name: 'São Bartolomeu',
flagUrl: 'https://flagcdn.com/w20/bl.png',
},
{
id: 181,
name: 'Santa Helena, Ascensão e Tristão da Cunha',
flagUrl: 'https://flagcdn.com/w20/sh.png',
},
{
id: 182,
name: 'Território Britânico do Oceano Índico',
flagUrl: 'https://flagcdn.com/w20/io.png',
},
{
id: 183,
name: 'Ilhas Cayman',
flagUrl: 'https://flagcdn.com/w20/ky.png',
},
{
id: 184,
name: 'Ilhas Cocos (Keeling)',
flagUrl: 'https://flagcdn.com/w20/cc.png',
},
{ id: 185, name: 'Ilhas Cook', flagUrl: 'https://flagcdn.com/w20/ck.png' },
{ id: 186, name: 'Ilhas Feroé', flagUrl: 'https://flagcdn.com/w20/fo.png' },
{
id: 187,
name: 'Ilhas Georgianas do Sul e Sandwich do Sul',
flagUrl: 'https://flagcdn.com/w20/gs.png',
},
{
id: 188,
name: 'Ilhas Heard e Ilhas McDonald',
flagUrl: 'https://flagcdn.com/w20/hm.png',
},
{
id: 189,
name: 'Ilhas Malvinas',
flagUrl: 'https://flagcdn.com/w20/fk.png',
},
{
id: 190,
name: 'Ilhas Marianas do Norte',
flagUrl: 'https://flagcdn.com/w20/mp.png',
},
{
id: 191,
name: 'Ilhas Menores dos Estados Unidos',
flagUrl: 'https://flagcdn.com/w20/us.png',
},
{
id: 192,
name: 'Ilhas Pitcairn',
flagUrl: 'https://flagcdn.com/w20/pn.png',
},
{
id: 193,
name: 'Ilhas Virgens Americanas',
flagUrl: 'https://flagcdn.com/w20/vi.png',
},
{
id: 194,
name: 'Ilhas Virgens Britânicas',
flagUrl: 'https://flagcdn.com/w20/vg.png',
},
{
id: 195,
name: 'Samoa Americana',
flagUrl: 'https://flagcdn.com/w20/as.png',
},
];
downloadNavioFunction() {
this.httpClient.get('http://localhost:8080/api/download-file', {
params: { filename: this.data.path },
responseType: 'blob' // Adiciona 'blob' para lidar com arquivos binários
}).subscribe({
next: (response) => {
// Criação de um URL temporário para o arquivo
const blob = new Blob([response]);
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = this.data.path || 'download'; // Define o nome do arquivo
link.click();
// Libera o objeto URL após o download
window.URL.revokeObjectURL(link.href);
console.log('Download iniciado:', this.data.path);
},
error: (error) => {
console.error('Erro ao baixar o arquivo:', error);
}
});
}
}
<div class="grid-container">
<h1 class="mat-h1">Dashboard</h1>
<!-- Grid para os Gráficos -->
<mat-grid-list [cols]="isSmallScreen ? 1 : 3" gutterSize="16px">
<mat-grid-tile>
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>NAVIOS ACEITOS</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<p-chart type="pie" [data]="data" [options]="options"></p-chart>
</mat-card-content>
</mat-card>
</mat-grid-tile>
<mat-grid-tile>
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>PROCESSOS CONCLUÍDOS</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<p-chart type="bar" [data]="dataBar" [options]="options"></p-chart>
</mat-card-content>
</mat-card>
</mat-grid-tile>
<mat-grid-tile>
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>STATUS DE OPERAÇÃO</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<p-chart type="doughnut" [data]="dataDoughnut" [options]="options"></p-chart>
</mat-card-content>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
<!-- Grid para as Caixas de Informações -->
<mat-grid-list [cols]="isSmallScreen ? 2 : 4" gutterSize="16px">
<mat-grid-tile>
<mat-card class="info-card">
<mat-card-header>
<mat-card-title>NAVIOS</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="info-value">{{ totalNavios }}</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
<mat-grid-tile>
<mat-card class="info-card">
<mat-card-header>
<mat-card-title>USUÁRIOS</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="info-value">{{ totalUsuarios }}</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
<mat-grid-tile>
<mat-card class="info-card">
<mat-card-header>
<mat-card-title>BERÇOS</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="info-value">{{ totalBercos }}</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
<mat-grid-tile>
<mat-card class="info-card">
<mat-card-header>
<mat-card-title>ACEITES</mat-card-title>
</mat-card-header>
<mat-card-content>
<div class="info-value">{{ totalAceites }}</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
</mat-grid-list>
</div>
.grid-container {
margin: 10px; /* Reduzi a margem para 10px */
}
.dashboard-card {
display: flex;
flex-direction: column;
height: 100%; /* Garante que o cartão ocupe toda a altura do tile */
width: calc(100% - 20px); /* Ajusta a largura do cartão para compensar a margem do contêiner */
overflow: visible; /* Adiciona overflow: visible para garantir que o conteúdo completo seja visível */
}
.dashboard-card-content {
flex: 1; /* Faz com que o conteúdo do cartão ocupe o espaço disponível */
text-align: center;
}
.info-card {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%; /* Ocupará 100% da largura do grid-tile */
height: 120px; /* Altura maior para formar um retângulo */
background-color: #f5f5f5; /* Cor de fundo para melhor visualização */
}
.info-value {
font-size: 2em;
font-weight: bold;
color: #007bff;
text-align: center;
}
.mat-grid-list {
justify-content: start;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DashboardComponent } from './dashboard.component';
describe('DashboardComponent', () => {
let component: DashboardComponent;
let fixture: ComponentFixture<DashboardComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DashboardComponent]
})
.compileComponents();
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, HostListener, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { ChartModule } from 'primeng/chart';
import { HttpClientModule } from '@angular/common/http'; // Import necessário para requisições HTTP
import { NavioSearchComponent } from '../crud-navios/navio-search/navio-search.component';
import { NavioService } from '../../services/navio.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.scss'],
standalone: true,
imports: [
CommonModule,
MatGridListModule,
MatCardModule,
MatButtonModule,
MatIconModule,
MatMenuModule,
ChartModule,
HttpClientModule, // Adicionado para suporte HTTP
NavioSearchComponent // Incluído se for usado no template
],
providers: [NavioService] // Providenciado o serviço
})
export class DashboardComponent implements OnInit {
data: any;
dataBar: any;
dataDoughnut: any;
options: any;
totalNavios: number = 0;
totalUsuarios: number = 0;
totalBercos: number = 0;
totalAceites: number = 0;
isSmallScreen = false;
@HostListener('window:resize', ['$event'])
onResize() {
this.isSmallScreen = window.innerWidth < 768;
}
constructor(private navioService: NavioService) {}
ngOnInit(): void {
// Consumindo o serviço para obter os dados do dashboard
this.navioService.getDadosDah().subscribe(response => {
// Populando os cards com os valores do JSON
this.totalNavios = response.totalVessels;
this.totalUsuarios = response.totalUsers;
this.totalBercos = response.totalBercos;
this.totalAceites = response.totalAccepts;
// Configuração dos gráficos
this.data = {
labels: ['Não Aceitos', 'Aceitos'],
datasets: [
{
data: [response.statusCounts.NE, response.statusCounts.Y],
backgroundColor: ['#FF6384', '#36A2EB']
}
]
};
this.dataBar = {
labels: ['Aceitos', 'Não Aceitos', 'Não Especificados'],
datasets: [
{
label: 'Processos',
data: [response.statusCounts.Y, response.statusCounts.NE, response.statusCounts.N],
backgroundColor: ['#4BC0C0', '#FF6384', '#FFCE56']
}
]
};
this.dataDoughnut = {
labels: ['Aceitos', 'Não Aceitos', 'Blacklist'],
datasets: [
{
data: [response.statusCounts.Y, response.statusCounts.NE, response.totalBlackLists],
backgroundColor: ['#36A2EB', '#FF6384', '#FFCE56']
}
]
};
// Configuração padrão para os gráficos
this.options = {
responsive: true,
maintainAspectRatio: false
};
});
}
}
<app-default-login-layout
title="Login into your account"
primaryBtnText="Login Now"
secondaryBtnText="Signup Now"
(submit)="submit()"
(navigate)="navigate()"
[disablePrimaryBtn]="!loginForm.valid"
>
<form [formGroup]="loginForm">
<app-primary-input
formControlName="email"
inputName="email"
type="email"
label="Email"
placeholder="johndoe@gmail.com"
>
</app-primary-input>
<app-primary-input
formControlName="password"
inputName="password"
type="password"
label="Your Password"
placeholder="Senha"
>
</app-primary-input>
<span>Forgot password?</span>
</form>
</app-default-login-layout>
@import "../../../styles/variables.scss";
form {
width: 80%; // Reduzir a largura do formulário para 80%
max-width: 400px; // Definir uma largura máxima
display: flex;
flex-direction: column;
gap: 16px; // Diminuir o espaçamento entre os elementos
margin-bottom: 20px; // Ajustar a margem inferior
span {
font-size: 14px;
text-decoration: underline;
color: #4169E1;
text-align: end;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LoginComponent]
})
.compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component } from '@angular/core';
import { DefaultLoginLayoutComponent } from '../../components/default-login-layout/default-login-layout.component';
import {
FormControl,
FormGroup,
FormRecord,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { PrimaryInputComponent } from '../../components/primary-input/primary-input.component';
import { Router } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { ToastrService } from 'ngx-toastr';
import { AuthService } from '../../auth.service';
interface LoginForm {
email: FormControl;
password: FormControl;
}
@Component({
selector: 'app-login',
standalone: true,
imports: [
DefaultLoginLayoutComponent,
ReactiveFormsModule,
PrimaryInputComponent,
],
providers: [LoginService],
templateUrl: './login.component.html',
styleUrl: './login.component.scss',
})
export class LoginComponent {
loginForm!: FormGroup<LoginForm>;
constructor(
private router: Router,
private authService: AuthService,
private loginService: LoginService,
private toastService: ToastrService
) {
this.loginForm = new FormGroup({
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [
Validators.required,
Validators.minLength(6),
]),
});
}
submit() {
this.loginService
.login(this.loginForm.value.email, this.loginForm.value.password)
.subscribe({
next: () => {
this.authService.updateAuthTokenStatus(true);
this.router.navigate(['/dashboard']);
this.toastService.success('Login feito com sucesso!');
},
error: () =>
this.toastService.error(
'Erro inesperado! Tente novamente mais tarde'
),
});
}
navigate() {
this.router.navigate(['/signup']);
}
}
<app-default-login-layout
title="Sign in and start today!t"
primaryBtnText="Signup Now"
secondaryBtnText="Login Now"
(submit)="submit()"
(navigate)="navigate()"
[disablePrimaryBtn]="!signupForm.valid"
>
<form [formGroup]="signupForm">
<app-primary-input
formControlName="name"
inputName="name"
type="text"
label="Your name"
placeholder="John Doe"
>
<img src="/assets/svg/email-icon.svg"/>
</app-primary-input>
<app-primary-input
formControlName="email"
inputName="email"
type="email"
label="Email"
placeholder="johndoe@gmail.com"
>
<img src="/assets/svg/email-icon.svg"/>
</app-primary-input>
<app-primary-input
formControlName="password"
inputName="password"
type="password"
label="Your Password"
>
<img src="/assets/svg/password-icon.svg"/>
</app-primary-input>
<app-primary-input
formControlName="passwordConfirm"
inputName="passwordConfirm"
type="password"
label="Confirm your Password"
>
<img src="/assets/svg/password-icon.svg"/>
</app-primary-input>
<app-primary-input
formControlName="role"
inputName="role"
type="text"
label="Your role"
>
<img src="/assets/svg/password-icon.svg"/>
</app-primary-input>
</form>
</app-default-login-layout>
\ No newline at end of file
@import "../../../styles/variables.scss";
form {
width: 80%; // Reduzir a largura do formulário para 80%
max-width: 400px; // Definir uma largura máxima
display: flex;
flex-direction: column;
gap: 16px; // Diminuir o espaçamento entre os elementos
margin-bottom: 20px; // Ajustar a margem inferior
span {
font-size: 14px;
text-decoration: underline;
color: #4169E1;
text-align: end;
}
}
import { Component } from '@angular/core';
import { DefaultLoginLayoutComponent } from '../../components/default-login-layout/default-login-layout.component';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { PrimaryInputComponent } from '../../components/primary-input/primary-input.component';
import { Router } from '@angular/router';
import { LoginService } from '../../services/login.service';
import { ToastrService } from 'ngx-toastr';
interface SignupForm {
name: FormControl,
email: FormControl,
password: FormControl,
passwordConfirm: FormControl,
role: FormControl
}
@Component({
selector: 'app-signup',
standalone: true,
imports: [
DefaultLoginLayoutComponent,
ReactiveFormsModule,
PrimaryInputComponent
],
templateUrl: './signup.component.html',
styleUrl: './signup.component.scss'
})
export class SignUpComponent {
signupForm!: FormGroup<SignupForm>;
constructor(
private router: Router,
private loginService: LoginService,
private toastService: ToastrService
){
this.signupForm = new FormGroup({
name: new FormControl('', [Validators.required, Validators.minLength(3)]),
email: new FormControl('', [Validators.required, Validators.email]),
password: new FormControl('', [Validators.required, Validators.minLength(6)]),
passwordConfirm: new FormControl('', [Validators.required, Validators.minLength(6)]),
role: new FormControl('', [Validators.required]),
})
}
submit(){
this.loginService.signup(this.signupForm.value.name, this.signupForm.value.email, this.signupForm.value.password, this.signupForm.value.role).subscribe({
next: () => {this.router.navigate([""]);
this.toastService.success("cadastro feito com sucesso!")
},
error: () => this.toastService.error("Erro inesperado! Tente novamente mais tarde")
})
}
navigate(){
this.router.navigate(["login"])
}
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SignUpComponent } from './signup.component';
describe('LoginComponent', () => {
let component: SignUpComponent;
let fixture: ComponentFixture<SignUpComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SignUpComponent]
})
.compileComponents();
fixture = TestBed.createComponent(SignUpComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
<app-add-search [title]="'Usuários'"></app-add-search>
<div class="main-body">
<div class="table-container" style="overflow-x: auto">
<table mat-table [dataSource]="dataSource" matSort>
<!-- ID do Usuário -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ID Usuário</th>
<td mat-cell *matCellDef="let row">
{{ row.id || 'N/A' }}
</td>
</ng-container>
<!-- Email -->
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Email</th>
<td mat-cell *matCellDef="let row">
{{ row.email || "Sem email" }}
</td>
</ng-container>
<!-- Papel -->
<ng-container matColumnDef="role">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Papel</th>
<td mat-cell *matCellDef="let row">
{{
row.role === 'COMPANY'
? 'ADMIN'
: row.role === 'CANDIDATE'
? 'USUÁRIO'
: 'Desconhecido'
}}
</td>
</ng-container>
<!-- Enviar Email -->
<ng-container matColumnDef="sendEmail">
<th mat-header-cell *matHeaderCellDef mat-sort-header>Enviar Email?</th>
<td mat-cell *matCellDef="let row">
<button
mat-icon-button
(click)="toggleEmail(row)"
[ngClass]="{ 'email-enabled': row.sendEmail, 'email-disabled': !row.sendEmail }"
aria-label="Enviar Email"
>
<mat-icon>
{{ row.sendEmail ? 'toggle_on' : 'toggle_off' }}
</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</div>
<!-- Add paginator reference #paginator="matPaginator" -->
<mat-paginator
#paginator
[length]="totalItems"
[pageSize]="pageSize"
(page)="loadData($event)"
>
</mat-paginator>
<!-- Buttons for navigating to the first and last page -->
<button
mat-button
(click)="paginator.firstPage()"
[disabled]="paginator.pageIndex === 0"
>
Primeira Página
</button>
<button
mat-button
(click)="paginator.lastPage()"
[disabled]="paginator.pageIndex === paginator.getNumberOfPages() - 1"
>
Última Página
</button>
</div>
\ No newline at end of file
.example-spacer {
flex: 1 1 auto;
}
.email-enabled {
color: green;
}
.email-disabled {
color: red;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 600px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserComponent } from './user.component';
describe('UserComponent', () => {
let component: UserComponent;
let fixture: ComponentFixture<UserComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [UserComponent]
})
.compileComponents();
fixture = TestBed.createComponent(UserComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { ChangeDetectorRef, Component, ViewChild } from '@angular/core';
import { NavioEditComponent } from '../crud-navios/navio-edit/navio-edit.component';
import { MatPaginator, MatPaginatorModule, PageEvent } from '@angular/material/paginator';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatDialog } from '@angular/material/dialog';
import { NavioService } from '../../services/navio.service';
import { JwtDecoderService } from '../../jwt-decoder.service';
import { AuthService } from '../../auth.service';
import { CoreService } from '../../core/core.service';
import { ToastrService } from 'ngx-toastr';
import { jwtDecode } from 'jwt-decode';
import { MatIcon, MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { CommonModule, NumberFormatStyle } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { AddSearchComponent } from '../../shared/addAndSearch/add-search/add-search.component';
import { DIR_DOCUMENT } from '@angular/cdk/bidi';
import { UserService } from '../../services/users/user.service';
interface UsuarioData {
id: number;
imo: number;
mmsi: number;
nome: string;
loa: number;
boca: number;
dwt: number;
pontal: number;
ponte_mfold: number;
mfold_quilha: number;
categoria: number;
flag: string;
obs: string;
action: number;
}
@Component({
selector: 'app-user',
standalone: true,
imports: [
MatPaginatorModule,
MatToolbarModule,
MatTableModule,
CommonModule,
FormsModule,
ReactiveFormsModule,
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatDatepickerModule,
MatSelectModule,
MatRadioModule,
MatIconModule,
MatSnackBarModule,
MatSortModule,
AddSearchComponent,
],
templateUrl: './user.component.html',
styleUrl: './user.component.scss'
})
export class UserComponent {
user: any;
authTokenPresent = false;
totalItems = 100;
pageSize = 10;
currentPage = 1;
displayedColumns: string[] = ['id', 'email', 'role', 'sendEmail'];
dataSource = new MatTableDataSource<UsuarioData>();
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatSort) sort!: MatSort;
constructor(
private _dialog: MatDialog,
private _userService: UserService,
private jwtDecoderService: JwtDecoderService,
private authService: AuthService,
private _coreService: CoreService,
private cdr: ChangeDetectorRef,
private toastService: ToastrService,
) { }
ngOnInit(): void {
this.validationToken();
}
parseUserString(userString: string) {
const userRegex = /User\(id=(\d+), email=([^)]+)\)/;
const match = userRegex.exec(userString);
if (match) {
return {
id: parseInt(match[1], 10),
email: match[2],
};
}
return null;
}
ngAfterViewInit(): void {
this.loadData();
}
validationToken() {
this.authService.authToken$.subscribe((isLoggedIn) => {
this.authTokenPresent = isLoggedIn;
if (this.authTokenPresent) {
const token = sessionStorage.getItem('accessToken')!;
this.user = jwtDecode(token);
const isExpired =
this.user && this.user.exp
? this.user.exp < Date.now() / 1000
: false;
if (isExpired) {
sessionStorage.removeItem('accessToken');
}
this.user = this.jwtDecoderService.decodeToken(token);
console.log(this.user);
}
this.cdr.detectChanges();
});
}
loadData(event?: PageEvent): void {
const pageIndex = event ? event.pageIndex + 1 : this.currentPage - 1;
// Verifica se há dados no sessionStorage
if (typeof sessionStorage !== 'undefined') {
const storedData = sessionStorage.getItem('naviosSearch');
if (storedData) {
const navios = JSON.parse(storedData); // Converte o JSON em um objeto
console.log('Dados recuperados do sessionStorage:', navios);
// Atualiza os dados na tabela
this.dataSource.data = navios;
// Atualiza o total de itens para paginação (opcional)
this.totalItems = navios.length;
// Configurações do paginator e sort
if (this.paginator && this.sort) {
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
// Remove dados do sessionStorage após o uso
sessionStorage.removeItem('naviosSearch');
console.log('naviosSearch removido do sessionStorage.');
return; // Retorna para evitar chamada à API
} else {
console.warn('Nenhum dado encontrado no sessionStorage.');
}
}
// Caso os dados não estejam no sessionStorage, chama a API
this._userService.getUserList(pageIndex, this.pageSize).subscribe({
next: (res: any) => {
const navios = res._embedded.userResponseList;
console.log(navios);
console.log(navios)
this.dataSource.data = navios.filter((navio: any) => navio.role === 'COMPANY');
console.log(this.dataSource.data)
this.totalItems = res.page.totalElements;
console.log(res.page.totalElements);
},
error: (err: any) => {
console.error(err);
if (err.error.title) {
this._coreService.openSnackBar(err.error.title);
} else {
this._coreService.openSnackBar(err.error.message);
}
},
});
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
if (this.dataSource.paginator) {
this.dataSource.paginator.firstPage();
}
}
openEditForm(data: any) {
this._dialog.open(NavioEditComponent, {
data, // Passa os dados para o componente de edição
autoFocus: true, // Foca no primeiro campo interativo do formulário
disableClose: true, // Impede que o diálogo feche ao clicar fora
width: '600px', // Define a largura do diálogo
});
this.cdr.detectChanges();
}
toggleEmail(row: any): void {
const newSendEmailStatus = !row.sendEmail; // Define o novo estado que será enviado para a API
this._userService.sendEmail(row.id, newSendEmailStatus).subscribe({
next: () => {
row.sendEmail = newSendEmailStatus; // Atualiza o estado localmente apenas após o sucesso da requisição
this.toastService.success('Status de envio de email atualizado com sucesso!');
},
error: () => {
this.toastService.error('Erro ao atualizar status de envio de email.');
}
});
}
}
import { TestBed } from '@angular/core/testing';
import { BlackListService } from './black-list.service';
describe('BlackListService', () => {
let service: BlackListService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BlackListService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { AsyncValidatorFn, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class BlackListService {
users:any[]=[];
private apiUrl = 'http://localhost:8080/api/black-list';
private apiUrl_verifica_imo = 'http://localhost:8080/api/vdatas';
constructor(private _http: HttpClient) {}
addEmployee(data: any): Observable<any> {
return this._http.post(this.apiUrl, data).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
updateEmployee(id: number, data: any): Observable<any> {
return this._http.put(`${this.apiUrl}/${id}`, data).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
getEmployeeList(pageIndex: number, pageSize: number): Observable<any> {
let params = new HttpParams()
.set('page', pageIndex.toString())
.set('size', pageSize.toString());
return this._http.get<any>(this.apiUrl, { params }).pipe(
tap((res: any) => {
this.users = res;
console.log(this.users)
}),
catchError(error => {
return throwError(error);
})
);
}
getEmployeeListbyId(id: number): Observable<any> {
return this._http.get(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
})
);
}
getEmployeebyIMO(imo: number): Observable<any> {
return this._http.get(`${this.apiUrl_verifica_imo}/${imo}`).pipe(
tap((res: any) => {
console.log(res)
this.users = res;
}),
catchError(error => {
console.log(error)
return throwError(error);
})
);
}
deleteEmployee(id: number): Observable<any> {
return this._http.delete(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
}
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { AceiteService } from './aceite.service';
describe('AceiteService', () => {
let service: AceiteService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AceiteService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { AsyncValidatorFn, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
import { map } from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AceiteService {
users: any[] = [];
private apiUrl = 'http://localhost:8080/api/accepts';
private apiUrl_verifica_imo = 'http://localhost:8080/api/vdatas';
constructor(private _http: HttpClient) { }
addAceite(data: any, foto: File | null): Observable<any> {
console.log(JSON.stringify(JSON.stringify(data)));
console.log(foto);
// Cria uma instância de FormData
const formData: FormData = new FormData();
// Adiciona os dados JSON como uma string
formData.append('acceptRequestForm', JSON.stringify(data));
// Adiciona o arquivo PDF
if (foto) {
formData.append('foto', foto, foto.name);
}
return this._http.post(this.apiUrl, formData).pipe(
tap((res: any) => {
console.log('Resposta da API:', res);
}),
catchError(error => {
console.error('Erro ao enviar dados:', error);
return throwError(error);
})
);
}
editAceite(id: number, data: any, foto: File): Observable<any> {
console.log('Dados para edição:', JSON.stringify(data));
console.log('Arquivo enviado:', foto);
// Cria uma instância de FormData
const formData: FormData = new FormData();
// Adiciona os dados JSON como uma string
formData.append('acceptRequestForm', JSON.stringify(data));
// Adiciona o arquivo, se disponível
if (foto) {
formData.append('foto', foto, foto.name);
}
// Faz a requisição POST ou PUT dependendo do backend
return this._http.post(`${this.apiUrl}/upload/${id}`, formData).pipe(
tap((res: any) => {
console.log('Resposta da API (edição com upload):', res);
}),
catchError(error => {
console.error('Erro no upload/edição:', error);
return throwError(error);
})
);
}
searchAceite(data: any): Observable<any> {
let params = new HttpParams();
// Adiciona os parâmetros de forma condicional (apenas se existirem)
if (data.id) {
params = params.set('id', data.id);
}
if (data.imo) {
params = params.set('imo', data.imo);
}
if (data.status) {
params = params.set('status', data.status);
}
if (data.nome) {
params = params.set('nome', data.nome);
}
// Faz a requisição GET com os parâmetros
return this._http.get<any>(`${this.apiUrl}/custom`, { params }).pipe(
tap((res: any) => {
console.log('Resultado recebido:', res);
sessionStorage.setItem("aceitesSearch", JSON.stringify(res));
}),
catchError(error => {
console.error('Erro ao buscar dados:', error);
return throwError(error);
})
);
}
updateAceite(id: number, data: any, foto: File | null): Observable<any> {
console.log('Dados para atualização:', JSON.stringify(data));
console.log('Arquivo enviado:', foto);
// Cria uma instância de FormData
const formData: FormData = new FormData();
// Adiciona os dados JSON como uma string
formData.append('acceptRequestForm', JSON.stringify(data));
// Adiciona o arquivo, se disponível
if (foto) {
formData.append('foto', foto, foto.name);
}
// Faz a requisição PUT para atualizar os dados
return this._http.put(`${this.apiUrl}/${id}`, formData).pipe(
tap((res: any) => {
console.log('Resposta da API (update):', res);
}),
catchError(error => {
console.error('Erro ao atualizar dados:', error);
return throwError(error);
})
);
}
getAceiteList(pageIndex: number, pageSize: number): Observable<any> {
let params = new HttpParams()
.set('page', pageIndex.toString())
.set('size', pageSize.toString());
return this._http.get<any>(this.apiUrl, { params }).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
})
);
}
getAceiteListbyId(id: number): Observable<any> {
return this._http.get(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
})
);
}
getEmployeebyIMO(imo: number): Observable<any> {
return this._http.get(`${this.apiUrl_verifica_imo}/${imo}`).pipe(
tap((res: any) => {
console.log(res)
this.users = res;
}),
catchError(error => {
console.log(error)
return throwError(error);
})
);
}
deleteEmployee(id: number): Observable<any> {
return this._http.delete(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
}
import { TestBed } from '@angular/core/testing';
import { AuthGuardService } from './auth-guard.service';
describe('AuthGuardService', () => {
let service: AuthGuardService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthGuardService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
\ No newline at end of file
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { JwtDecoderService } from '../jwt-decoder.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
private decodedToken: any;
constructor(
private jwtDecoderService: JwtDecoderService,
private router: Router
) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const authTokenPresent = sessionStorage.getItem('accessToken');
if (authTokenPresent) {
this.decodedToken = this.jwtDecoderService.decodeToken(authTokenPresent);
if (this.decodedToken.role) {
return true;
} else {
return this.router.parseUrl('/notPermission');
}
} else {
return this.router.parseUrl('/');
}
}
}
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { BercosService } from './bercos.service';
describe('BercosService', () => {
let service: BercosService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BercosService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { AsyncValidatorFn, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
import { map} from 'rxjs/operators';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class BercosService {
users:any[]=[];
private apiUrl = 'http://localhost:8080/api/bercos';
constructor(private _http: HttpClient) {}
addEmployee(data: any): Observable<any> {
return this._http.post(this.apiUrl, data).pipe(
tap((res: any) => {
console.log(res);
}),
catchError(error => {
return throwError(error);
})
);
}
updateEmployee(id: number, data: any): Observable<any> {
return this._http.put(`${this.apiUrl}/${id}`, data).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
getEmployeeList(pageIndex: number, pageSize: number): Observable<any> {
let params = new HttpParams()
.set('page', pageIndex.toString())
.set('size', pageSize.toString());
return this._http.get<any>(this.apiUrl, { params }).pipe(
tap((res: any) => {
console.log(res);
}),
catchError(error => {
return throwError(error);
})
);
}
getEmployeeListbyId(id: number): Observable<any> {
return this._http.get(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
})
);
}
deleteEmployee(id: number): Observable<any> {
return this._http.delete(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError(error => {
return throwError(error);
}));
}
getBercosListSemPaginacao(): Observable<any> {
return this._http.get<any>(this.apiUrl).pipe(
tap((res: any) => {
console.log('Lista completa de berços:', res);
}),
catchError(error => {
return throwError(error);
})
);
}
searchBerco(data: any): Observable<any> {
let params = new HttpParams();
// Adiciona os parâmetros de forma condicional (apenas se existirem)
if (data.categoria) {
params = params.set('categoria', data.categoria);
}
if (data.nome) {
params = params.set('nome', data.nome);
}
// Faz a requisição GET com os parâmetros
return this._http.get<any>(`${this.apiUrl}/custom`, { params }).pipe(
tap((res: any) => {
console.log('Resultado recebido:', res);
sessionStorage.setItem("bercosSearch", JSON.stringify(res));
}),
catchError(error => {
console.error('Erro ao buscar dados:', error);
return throwError(error);
})
);
}
}
import { TestBed } from '@angular/core/testing';
import { IsAdminService } from './is-admin.service';
describe('IsAdminService', () => {
let service: IsAdminService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(IsAdminService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router, UrlTree } from '@angular/router';
import { Observable } from 'rxjs';
import { JwtDecoderService } from '../jwt-decoder.service';
@Injectable({
providedIn: 'root'
})
export class IsAdminService implements CanActivate {
private decodedToken: any;
constructor(
private jwtDecoderService: JwtDecoderService,
private router: Router
) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const authTokenPresent = sessionStorage.getItem('accessToken');
if (authTokenPresent) {
this.decodedToken = this.jwtDecoderService.decodeToken(authTokenPresent);
if (this.decodedToken.role === "COMPANY") {
return true;
} else {
return this.router.parseUrl('/notPermission');
}
} else {
return this.router.parseUrl('/');
}
}
}
import { TestBed } from '@angular/core/testing';
import { LoginService } from './login.service';
describe('LoginService', () => {
let service: LoginService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LoginService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { LoginResponse } from '../types/login-response.type';
import { tap } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class LoginService {
apiUrl: string = "http://localhost:8080/api/auth"
constructor(private httpClient: HttpClient) { }
login(email: string, password: string){
return this.httpClient.post<LoginResponse>(this.apiUrl + "/login", { email, password }).pipe(
tap((value) => {
if (value) {
sessionStorage.setItem("accessToken", value.accessToken);
}
})
);
}
signup(name: string, email: string, password: string, role: string){
return this.httpClient.post<LoginResponse>(this.apiUrl + "/register", { name, email, password, role }).pipe(
tap((value) => {
if (value) {
sessionStorage.setItem("username", value.name);
}
})
);
}
}
\ No newline at end of file
import { TestBed } from '@angular/core/testing';
import { NavioService } from './navio.service';
describe('NavioService', () => {
let service: NavioService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(NavioService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import {
HttpClient,
HttpErrorResponse,
HttpParams,
} from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root',
})
export class NavioService {
users: any[] = [];
private apiUrl = 'http://localhost:8080/api/vessels';
private apiUrlDash = 'http://localhost:8080/statistics/all';
constructor(private _http: HttpClient) {}
addEmployee1(data: any, foto: File): Observable<any> {
console.log(JSON.stringify(JSON.stringify(data)));
console.log(foto);
// Cria uma instância de FormData
const formData: FormData = new FormData();
// Adiciona os dados JSON como uma string
formData.append('vesselRequestForm', JSON.stringify(data));
// Adiciona o arquivo PDF
if (foto) {
formData.append('foto', foto, foto.name);
}
return this._http.post(this.apiUrl, formData).pipe(
tap((res: any) => {
console.log('Resposta da API:', res);
}),
catchError(error => {
console.error('Erro ao enviar dados:', error);
return throwError(error);
})
);
}
dowloadNavio(data: any): Observable<any> {
let params = new HttpParams();
if (data.path) {
params = params.set('fileName', data.path);
}
return this._http.get<any>(`${this.apiUrl}`, { params }).pipe(
tap((res: any) => {
console.log('Resultado recebido:', res);
}),
catchError((error) => {
console.error('Erro ao buscar dados:', error);
return throwError(error);
})
);
}
searchNavios(data: any): Observable<any> {
let params = new HttpParams();
// Adiciona os parâmetros de forma condicional (apenas se existirem)
if (data.id) {
params = params.set('id', data.id);
}
if (data.imo) {
params = params.set('imo', data.imo);
}
if (data.status) {
params = params.set('status', data.status);
}
if (data.nome) {
params = params.set('nome', data.nome);
}
// Faz a requisição GET com os parâmetros
return this._http.get<any>(`${this.apiUrl}/custom`, { params }).pipe(
tap((res: any) => {
console.log('Resultado recebido:', res);
sessionStorage.setItem('naviosSearch', JSON.stringify(res));
}),
catchError((error) => {
console.error('Erro ao buscar dados:', error);
return throwError(error);
})
);
}
editEmployeeWithUpload(
id: number,
vesselRequest: any,
foto: File | null
): Observable<any> {
console.log('Dados para edição:', JSON.stringify(vesselRequest));
console.log('Arquivo enviado:', foto);
// Cria uma instância de FormData
const formData: FormData = new FormData();
// Adiciona os dados JSON como uma string
formData.append('vesselRequestForm', JSON.stringify(vesselRequest));
// Adiciona o arquivo, se disponível
if (foto) {
formData.append('foto', foto, foto.name);
}
// Faz a requisição POST ou PUT dependendo da API
return this._http.put(`${this.apiUrl}/${id}`, formData).pipe(
tap((res: any) => {
console.log('Resposta da API (upload/edit):', res);
}),
catchError((error) => {
console.error('Erro no upload/edição:', error);
return throwError(error);
})
);
}
getEmployeeList(pageIndex: number, pageSize: number): Observable<any> {
let params = new HttpParams()
.set('page', pageIndex.toString())
.set('size', pageSize.toString());
return this._http.get<any>(this.apiUrl, { params }).pipe(
tap((res: any) => {
this.users = res;
}),
catchError((error) => {
return throwError(error);
})
);
}
deleteEmployee(id: number): Observable<any> {
return this._http.delete(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
this.users = res;
}),
catchError((error) => {
return throwError(error);
})
);
}
// Novo método para obter um empregado por ID
getEmployeeById(id: number): Observable<any> {
return this._http.get<any>(`${this.apiUrl}/${id}`).pipe(
tap((res: any) => {
console.log('Navio obtido:', res);
}),
catchError((error) => {
console.error('Erro ao buscar empregado por ID:', error);
return throwError(error);
})
);
}
getDadosDah(): Observable<any> {
return this._http.get<any>(`${this.apiUrlDash}`).pipe(
tap((res: any) => {
console.log('dados Dash:', res);
}),
catchError((error) => {
console.error('Erro ao buscar empregado por ID:', error);
return throwError(error);
})
);
}
}
import { TestBed } from '@angular/core/testing';
import { UserService } from './user.service';
describe('UserService', () => {
let service: UserService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(UserService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { catchError, Observable, tap, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
private apiUrl = 'http://localhost:8080/api/users'; // Certifique-se de que a URL está correta
private users: any; // Adicione a propriedade users
constructor(private _http: HttpClient) {}
getUserList(pageIndex: number, pageSize: number): Observable<any> {
let params = new HttpParams()
.set('page', pageIndex.toString())
.set('size', pageSize.toString());
return this._http.get<any>(`${this.apiUrl}`, { params }).pipe(
tap((res: any) => {
this.users = res; // Armazena os dados retornados
}),
catchError((error) => {
console.error('Erro ao buscar lista de usuários:', error);
return throwError(error); // Propaga o erro para ser tratado no componente
})
);
}
sendEmail(userId: number, sendEmail: boolean): Observable<any> {
const url = `${this.apiUrl}/${userId}`; // Monta a URL para o usuário específico
const body = { sendEmail: sendEmail ? 1 : 0 }; // Envia 1 para true e 0 para false
return this._http.put<any>(url, body).pipe(
tap(() => {
console.log(`Email status atualizado para o usuário com ID: ${userId}`);
}),
catchError((error) => {
console.error('Erro ao atualizar o status de envio de email:', error);
return throwError(error); // Propaga o erro para ser tratado no componente
})
);
}
}
<div class="main-body" style="display: flex; justify-content: space-between; align-items: center;">
<h1>{{ title }}</h1>
<div style="display: flex; align-items: center;">
@if(primaryButtonText != 'Primary Action'){
<button mat-raised-button [color]="primaryButtonColor" (click)="primaryButtonAction()" style="margin-right: 10px;">
{{ primaryButtonText }}
</button>
}
@if(secondaryButtonText != 'Secondary Action'){
<button mat-raised-button [color]="secondaryButtonColor" (click)="secondaryButtonAction()">
{{ secondaryButtonText }}
</button>
}
</div>
</div>
\ No newline at end of file
.example-spacer {
flex: 1 1 auto;
}
.mat-toolbar {
padding-top: 5px;
margin: 0 auto;
max-width: 1348px;
background-color: #4169E1;
color: #fff;
}
.main-body {
padding-top: 20px;
margin: 0 auto;
max-width: 1348px;
mat-form-field {
width: 100%;
}
}
.mat-toolbar {
padding-top: 5px;
background-color: #4169E1;
color: #fff;
}
.action {
display: flex;
align-items: center;
}
@media screen and (max-width: 600px) {
.action button {
margin-right: 5px;
}
.table-container {
overflow-x: auto;
}
}
td.mat-cell {
white-space: nowrap;
}
td.mat-cell.action-buttons {
display: flex;
justify-content: flex-end;
align-items: center;
}
\ No newline at end of file
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AddSearchComponent } from './add-search.component';
describe('AddSearchComponent', () => {
let component: AddSearchComponent;
let fixture: ComponentFixture<AddSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AddSearchComponent]
})
.compileComponents();
fixture = TestBed.createComponent(AddSearchComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Input } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
@Component({
selector: 'app-add-search',
standalone: true,
imports: [MatButtonModule],
templateUrl: './add-search.component.html',
styleUrl: './add-search.component.scss'
})
export class AddSearchComponent {
@Input() title: string = 'Default Title';
@Input() primaryButtonText: string = 'Primary Action';
@Input() primaryButtonColor: string = 'primary';
@Input() primaryButtonAction: () => void = () => {};
@Input() secondaryButtonText: string = 'Secondary Action';
@Input() secondaryButtonColor: string = 'accent';
@Input() secondaryButtonAction: () => void = () => {};
onPrimaryButtonClick() {
if (this.primaryButtonAction) {
this.primaryButtonAction();
}
}
onSecondaryButtonClick() {
if (this.secondaryButtonAction) {
this.secondaryButtonAction();
}
}
}
<div id="container">
<div id="header">Please confirm!</div>
<div id="content">{{ data.message }}</div>
<div id="actions">
<button mat-raised-button class="cancel" [mat-dialog-close]="false">Cancel</button>
<button mat-raised-button (click)="action()" [mat-dialog-close]="false">Yes</button>
</div>
</div>
:host {
display: flex;
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
align-items: center;
justify-content: center;
font-family: Arial, Helvetica, sans-serif;
}
#container {
width: 40%;
box-shadow: 5px 5px 4px rgba(19, 19, 19, 0.5);
border-radius: 5px;
background-color: #fff;
display: flex;
flex-direction: column;
}
#header {
margin-top: 30px;
border-bottom: 1px solid #ccc;
height: 70px;
padding: 0 30px;
font-size: 30px;
font-weight: bold;
color: #333;
}
#content {
flex-grow: 1;
padding: 30px;
font-size: 18px;
}
#actions {
display: flex;
justify-content: flex-end;
height: 50px;
gap: 20px;
padding: 20px;
}
#actions button {
padding: 5px 30px; /* Ajuste o padding conforme necessário */
background-color: cornflowerblue;
border: 0;
color: #fff;
font-size: 18px;
cursor: pointer;
}
#actions button.cancel {
background-color: #cf3d3d;
border: 1px solid #fff;
color: #fff;
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DialogComponent } from './dialog.component';
describe('DialogComponent', () => {
let component: DialogComponent;
let fixture: ComponentFixture<DialogComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DialogComponent]
})
.compileComponents();
fixture = TestBed.createComponent(DialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, Inject, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import { Router } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatSelectModule } from '@angular/material/select';
import { MatRadioModule } from '@angular/material/radio';
import { MatIconModule } from '@angular/material/icon';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatDialogModule } from '@angular/material/dialog';
import { MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-dialog',
standalone: true,
imports: [
MatDialogModule,
MatSnackBarModule,
MatIconModule,
MatRadioModule,
MatSelectModule,
MatDatepickerModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule
],
templateUrl: './dialog.component.html',
styleUrls: ['./dialog.component.scss']
})
export class DialogComponent implements OnInit {
private baseRota = "/"; // Corrigido para uma rota relativa
private tipoAcao = [
"redirect",
"delete" // Corrigido para "delete"
];
constructor(
@Inject(MAT_DIALOG_DATA) public data: any,
private router: Router,
private dialogRef: MatDialogRef<DialogComponent>, // Adicionado para fechar o diálogo
) {}
ngOnInit(): void {
console.log(this.data.message);
}
action() {
if (this.data.action === this.tipoAcao[0]) {
this.dialogRef.close(true);
this.router.navigate([this.baseRota + this.data.rota]);
}
}
}
export type LoginResponse = {
accessToken: string;
refreshToken: string;
name: string
}
\ No newline at end of file
import { AsyncValidator, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { map, catchError } from 'rxjs/operators';
import { AceiteService } from '../services/aceites/aceite.service';
import { Injectable } from '@angular/core';
@Injectable({ providedIn: 'root' })
export class Validator implements AsyncValidator {
constructor(private companyService: AceiteService) { }
validate(
val: AbstractControl
): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
return this.companyService.getAceiteListbyId(val.value).pipe(
map(isTaken => (isTaken ? { uniqueCompanyName: true } : null)),
catchError(() => of(null))
);
}
}
\ No newline at end of file
<svg preserveAspectRatio="none" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2204_33)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M0.25 8C0.25 3.72134 3.72009 0.25 8 0.25C12.2799 0.25 15.75 3.72134 15.75 8C15.75 12.2812 12.2799 15.75 8 15.75C3.72009 15.75 0.25 12.2812 0.25 8ZM7.25 11H6.875C6.66791 11 6.5 11.1679 6.5 11.375V11.625C6.5 11.8321 6.66791 12 6.875 12H9.125C9.33209 12 9.5 11.8321 9.5 11.625V11.375C9.5 11.1679 9.33209 11 9.125 11H8.75V6.625C8.75 6.41791 8.58209 6.25 8.375 6.25H6.875C6.66791 6.25 6.5 6.41791 6.5 6.625V6.875C6.5 7.08209 6.66791 7.25 6.875 7.25H7.25V11ZM7 4.5C7 3.94772 7.44772 3.5 8 3.5C8.55228 3.5 9 3.94772 9 4.5C9 5.05228 8.55228 5.5 8 5.5C7.44772 5.5 7 5.05228 7 4.5Z" fill="#7262E6"/>
</g>
<defs>
<clipPath id="clip0_2204_33">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6_1284)">
<path d="M3 3H21C21.2652 3 21.5196 3.10536 21.7071 3.29289C21.8946 3.48043 22 3.73478 22 4V20C22 20.2652 21.8946 20.5196 21.7071 20.7071C21.5196 20.8946 21.2652 21 21 21H3C2.73478 21 2.48043 20.8946 2.29289 20.7071C2.10536 20.5196 2 20.2652 2 20V4C2 3.73478 2.10536 3.48043 2.29289 3.29289C2.48043 3.10536 2.73478 3 3 3ZM20 7.238L12.072 14.338L4 7.216V19H20V7.238ZM4.511 5L12.061 11.662L19.502 5H4.511Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_6_1284">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
<svg width="182" height="60" viewBox="0 0 182 60" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="4.15417" width="5.53886" height="55.3886" rx="2.76943" fill="#9440FF"/>
<rect x="22.1554" y="4.15417" width="5.53886" height="55.3886" rx="2.76943" fill="#9440FF"/>
<rect x="44.3109" y="4.15417" width="5.53886" height="55.3886" rx="2.76943" fill="#9440FF"/>
<rect x="11.0778" width="5.53886" height="55.3886" rx="2.76943" fill="#1E2772"/>
<rect x="33.2332" width="5.53886" height="55.3886" rx="2.76943" fill="#1E2772"/>
<path d="M87.088 21.856V44H84.176V27.488L76.816 44H74.768L67.376 27.456V44H64.464V21.856H67.6L75.792 40.16L83.984 21.856H87.088ZM99.6745 44.288C98.0318 44.288 96.5385 43.9147 95.1945 43.168C93.8718 42.4213 92.8265 41.3653 92.0585 40C91.3118 38.6133 90.9385 37.0133 90.9385 35.2C90.9385 33.408 91.3225 31.8293 92.0905 30.464C92.8798 29.0773 93.9465 28.0213 95.2905 27.296C96.6345 26.5493 98.1385 26.176 99.8025 26.176C101.467 26.176 102.971 26.5493 104.315 27.296C105.659 28.0213 106.715 29.0667 107.483 30.432C108.272 31.7973 108.667 33.3867 108.667 35.2C108.667 37.0133 108.261 38.6133 107.451 40C106.661 41.3653 105.584 42.4213 104.219 43.168C102.853 43.9147 101.339 44.288 99.6745 44.288ZM99.6745 41.728C100.72 41.728 101.701 41.4827 102.619 40.992C103.536 40.5013 104.272 39.7653 104.827 38.784C105.403 37.8027 105.691 36.608 105.691 35.2C105.691 33.792 105.413 32.5973 104.859 31.616C104.304 30.6347 103.579 29.9093 102.683 29.44C101.787 28.9493 100.816 28.704 99.7705 28.704C98.7038 28.704 97.7225 28.9493 96.8265 29.44C95.9518 29.9093 95.2478 30.6347 94.7145 31.616C94.1812 32.5973 93.9145 33.792 93.9145 35.2C93.9145 36.6293 94.1705 37.8347 94.6825 38.816C95.2158 39.7973 95.9198 40.5333 96.7945 41.024C97.6692 41.4933 98.6292 41.728 99.6745 41.728ZM119.023 41.312L124.463 26.464H127.567L120.687 44H117.295L110.415 26.464H113.551L119.023 41.312ZM146.433 34.56C146.433 35.1147 146.401 35.7013 146.337 36.32H132.321C132.427 38.048 133.014 39.4027 134.081 40.384C135.169 41.344 136.481 41.824 138.017 41.824C139.275 41.824 140.321 41.536 141.153 40.96C142.006 40.3627 142.603 39.5733 142.945 38.592H146.081C145.611 40.2773 144.673 41.6533 143.265 42.72C141.857 43.7653 140.107 44.288 138.017 44.288C136.353 44.288 134.859 43.9147 133.537 43.168C132.235 42.4213 131.211 41.3653 130.465 40C129.718 38.6133 129.345 37.0133 129.345 35.2C129.345 33.3867 129.707 31.7973 130.433 30.432C131.158 29.0667 132.171 28.0213 133.473 27.296C134.795 26.5493 136.31 26.176 138.017 26.176C139.681 26.176 141.153 26.5387 142.433 27.264C143.713 27.9893 144.694 28.992 145.377 30.272C146.081 31.5307 146.433 32.96 146.433 34.56ZM143.425 33.952C143.425 32.8427 143.179 31.8933 142.689 31.104C142.198 30.2933 141.526 29.6853 140.673 29.28C139.841 28.8533 138.913 28.64 137.889 28.64C136.417 28.64 135.158 29.1093 134.113 30.048C133.089 30.9867 132.502 32.288 132.353 33.952H143.425ZM153.189 21.696V44H150.277V21.696H153.189ZM161.704 28.864V39.2C161.704 40.0533 161.885 40.6613 162.248 41.024C162.61 41.3653 163.24 41.536 164.135 41.536H166.28V44H163.656C162.034 44 160.818 43.6267 160.008 42.88C159.197 42.1333 158.792 40.9067 158.792 39.2V28.864H156.52V26.464H158.792V22.048H161.704V26.464H166.28V28.864H161.704ZM173.584 21.696L173.232 37.696H170.8L170.448 21.696H173.584ZM172.144 44.192C171.589 44.192 171.12 44 170.736 43.616C170.352 43.232 170.16 42.7627 170.16 42.208C170.16 41.6533 170.352 41.184 170.736 40.8C171.12 40.416 171.589 40.224 172.144 40.224C172.677 40.224 173.125 40.416 173.488 40.8C173.872 41.184 174.064 41.6533 174.064 42.208C174.064 42.7627 173.872 43.232 173.488 43.616C173.125 44 172.677 44.192 172.144 44.192Z" fill="black"/>
</svg>
<svg width="597" height="534" viewBox="0 0 597 534" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M298.713 100.132C439.276 121.253 537.3 193.015 537.3 307.592C537.3 444.924 415.523 302.232 331.553 382.301C247.583 462.37 68.6832 464.64 60.1255 307.592C52.1144 160.574 158.149 79.0112 298.713 100.132Z" fill="#7001FD" fill-opacity="0.8"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M226.861 322.147L264.044 279.125L264.898 279.729C270.389 283.591 274.744 286.136 277.962 287.364L278.915 287.725C294.374 293.542 305.004 295.518 303.296 296.884L301.181 298.584C287.517 309.617 268.808 325.661 245.055 346.716C241.802 349.851 237.419 351.863 232.683 352.4L227.785 352.923C179.704 358.014 148.857 358.453 137.553 356.214C135.192 355.747 127.926 356.968 122.44 361.897C114.211 369.29 102.444 387.1 100.467 387.1C97.5943 387.1 100.302 375.304 108.589 351.711L109.465 348.97C113.326 336.996 116.103 329.917 117.797 327.732C119.617 325.384 125.764 329.528 136.237 340.163L135.953 341.546C137.312 340.135 138.924 338.635 140.787 337.044L145.736 336.514C163.218 334.616 176.506 332.88 185.601 331.306L186.558 331.138C196.412 329.391 209.846 326.394 226.861 322.147Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M458.408 277.576L472.233 286.895C474.886 288.68 476.831 291.184 477.78 294.032L480.399 301.878C481.631 304.252 480.553 307.071 477.955 308.272L473.072 311.512C469.932 312.962 466.104 311.392 465.279 308.316L462.531 299.572C462.531 299.572 450.88 296.406 449.33 284.003L458.408 277.576" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M391.771 124.524C401.218 124.867 405.965 136.447 409.054 142.171C410.106 144.121 402.707 201.751 400.288 216.498C395.983 242.76 382.97 251.087 374.8 252.875C374.8 252.875 375.29 282.733 371.869 290.165C364.292 306.62 268.387 295.575 259.014 268.073C252.607 249.271 276.418 247.08 285.355 235.744C301.733 214.969 302.583 195.634 320.226 181.802C326.912 175.248 334.675 168.67 341.37 160.759L344.094 157.553C361.123 137.597 374.091 124.357 390.884 124.504L391.771 124.524Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M344.404 174.477C342.839 175.152 340.55 175.361 339.735 173.99C337.173 169.686 329.335 169.094 326.004 172.953C329.201 171.97 332.926 171.032 335.785 172.647C336.581 173.096 337.268 173.726 337.948 174.349C339.081 175.388 340.194 176.408 341.754 176.544C342.914 176.646 344.018 176.209 345.117 175.775C346.297 175.308 347.47 174.844 348.7 175.051C350.065 175.281 351.022 176.252 351.979 177.223C352.933 178.192 353.888 179.161 355.247 179.396C356.36 179.588 357.478 179.231 358.586 178.877C359.824 178.481 361.05 178.09 362.242 178.474C363.664 178.933 364.314 180.244 364.965 181.556C365.612 182.862 366.26 184.169 367.669 184.639C368.504 184.917 369.406 184.816 370.296 184.661L371.179 184.5C373.26 184.129 375.507 184.096 377.411 184.934C379.047 185.654 380.336 187.144 380.441 188.735C380.483 188.392 380.521 188.049 380.554 187.707L380.884 185.771C378.996 183.789 376.03 182.668 373.125 182.84C372.627 182.87 372.129 182.935 371.632 183C370.675 183.125 369.72 183.25 368.77 183.121C367.327 182.924 365.861 181.826 366.104 180.539L366.126 180.4C366.391 178.246 363.162 177.01 360.681 177.191C360.154 177.23 359.614 177.292 359.071 177.355C357.002 177.596 354.886 177.842 353.261 176.778C352.634 176.367 352.149 175.791 351.668 175.222C350.996 174.424 350.333 173.638 349.301 173.327C348.161 172.985 347.002 173.344 345.878 173.821L345.504 173.984L344.404 174.477ZM326.409 189.463C327.486 190.755 329.703 190.031 331.414 189.472L331.503 189.443C336.092 187.946 341.622 189.114 344.975 192.29C346.814 194.032 349.535 193.545 352.352 193.041C354.705 192.62 357.125 192.187 359.154 193.031C360.103 193.426 360.983 194.094 361.846 194.748C363.427 195.947 364.949 197.101 366.721 196.448C370.082 195.209 374.207 195.87 376.907 198.038L376.897 198.721L376.885 200.227C374.203 197.824 369.859 197.045 366.349 198.339C364.576 198.993 363.055 197.839 361.473 196.64C360.611 195.985 359.73 195.318 358.781 194.923C356.752 194.079 354.332 194.511 351.979 194.932C349.162 195.436 346.441 195.923 344.603 194.182C341.316 191.069 335.94 189.885 331.407 191.248L330.502 191.538C328.889 192.05 327.003 192.515 326.037 191.354C322.987 187.693 316.864 186.41 312.313 188.478L312.902 186.491L313.171 186.381C317.663 184.611 323.467 185.93 326.409 189.463ZM315.961 205.788C314.274 206.406 312.09 207.205 310.959 205.951C308.898 203.665 304.188 203.498 296.831 205.451C297.393 205.792 298.844 205.758 300.634 205.717C304.004 205.638 308.575 205.532 310.668 207.853C311.683 208.98 313.547 208.451 315.138 207.884L316.03 207.563C320.5 206.045 325.923 207.044 329.341 210.042C331.253 211.718 333.951 211.139 336.744 210.539C339.078 210.037 341.478 209.521 343.541 210.295C344.506 210.657 345.415 211.294 346.305 211.918C347.937 213.062 349.507 214.163 351.25 213.449L351.492 213.354C353.467 212.609 357.262 213.865 360.701 215.004C363.203 215.833 365.517 216.599 366.806 216.487C358.833 212.291 353.745 210.644 351.541 211.547L351.366 211.612C349.692 212.186 348.173 211.121 346.597 210.016C345.706 209.391 344.798 208.754 343.833 208.393C341.769 207.618 339.369 208.134 337.036 208.636C334.243 209.236 331.545 209.816 329.633 208.139C326.145 205.08 320.57 204.102 316.048 205.756L315.961 205.788ZM331.59 275.058C333.613 276.219 336.232 277.723 338.103 276.897C341.408 275.44 347.363 276.733 355.968 280.778L356.796 281.171C355.953 281.31 354.059 280.79 351.724 280.147L351.724 280.147C347.326 278.938 341.361 277.297 337.899 278.824C336.219 279.565 333.937 278.429 332.024 277.349L330.953 276.741C325.903 273.968 319.08 273.032 313.793 274.34C312.098 274.971 309.737 274.232 307.143 273.421C305.379 272.868 303.507 272.282 301.662 272.07C299.388 271.809 298.217 271.966 297.189 272.104C296.157 272.242 295.27 272.36 293.558 272.018C292.234 271.753 290.118 270.925 287.211 269.535C282.057 267.322 272.924 267.59 268.117 269.128L267.858 269.208C262.719 270.728 262.762 269.063 267.929 267.329L268.321 267.201L268.63 267.106C274.122 265.47 284.292 265.649 289.615 268.703L289.72 268.763C291.742 269.924 294.362 271.428 296.233 270.602L296.371 270.547C297.68 270.066 300.742 270.074 301.691 270.13L301.866 270.143C305.062 270.46 305.757 270.719 306.516 271.215L307.06 271.583L307.371 271.69C308.526 272.093 309.751 272.568 311.046 273.118C311.582 273.075 312.198 272.949 312.926 272.716L313.235 272.621C318.726 270.985 326.162 271.944 331.485 274.998L331.59 275.058ZM307.797 220.191C308.994 221.445 311.305 220.646 313.089 220.028L313.182 219.996C317.965 218.342 323.863 219.32 327.553 222.379C329.576 224.056 332.43 223.476 335.384 222.876C337.853 222.374 340.392 221.858 342.575 222.633C343.596 222.994 344.557 223.631 345.499 224.256C347.167 225.361 348.774 226.426 350.545 225.852L350.73 225.787C353.061 224.884 358.444 226.531 366.879 230.727C365.515 230.839 363.067 230.073 360.42 229.244C356.782 228.105 352.768 226.849 350.678 227.594L350.422 227.689C348.578 228.403 346.917 227.302 345.191 226.158C344.249 225.534 343.288 224.897 342.267 224.535C340.084 223.761 337.545 224.277 335.076 224.778C332.121 225.379 329.267 225.958 327.244 224.282C323.629 221.284 317.891 220.285 313.162 221.803L312.218 222.124C310.536 222.691 308.564 223.22 307.489 222.093C305.275 219.772 300.44 219.878 296.874 219.957H296.874H296.874C294.981 219.998 293.446 220.032 292.851 219.691C300.635 217.738 305.617 217.905 307.797 220.191ZM306.583 235.692C304.531 236.31 301.872 237.109 300.495 235.855C297.986 233.569 292.254 233.402 283.299 235.355C283.984 235.696 285.75 235.662 287.928 235.621C292.03 235.542 297.593 235.436 300.141 237.757C301.377 238.884 303.646 238.355 305.582 237.788L306.667 237.467C312.109 235.949 318.71 236.948 322.87 239.946C325.197 241.622 328.481 241.043 331.881 240.442H331.881C334.721 239.941 337.642 239.425 340.154 240.199C341.328 240.561 342.434 241.198 343.518 241.822C345.504 242.966 347.415 244.067 349.536 243.353L349.831 243.258C352.236 242.513 356.854 243.769 361.04 244.908L361.04 244.908C364.086 245.737 366.902 246.503 368.471 246.391C358.767 242.195 352.573 240.548 349.891 241.451L349.678 241.516C347.641 242.09 345.792 241.025 343.873 239.92L343.873 239.92C342.789 239.295 341.683 238.658 340.509 238.297C337.997 237.522 335.076 238.038 332.235 238.54C328.836 239.14 325.552 239.72 323.225 238.043C318.98 234.984 312.193 234.006 306.69 235.66L306.583 235.692ZM290.645 247.959C292.189 249.213 295.17 248.414 297.472 247.796L297.592 247.764C303.764 246.11 311.375 247.088 316.135 250.147C318.746 251.824 322.428 251.244 326.241 250.644C329.426 250.142 332.702 249.626 335.519 250.401C336.836 250.762 338.077 251.399 339.292 252.024L339.292 252.024C341.444 253.129 343.518 254.194 345.803 253.62L346.042 253.555C349.05 252.652 355.995 254.299 366.879 258.495C365.12 258.607 361.961 257.841 358.546 257.012L358.545 257.012L358.545 257.012L358.545 257.012C353.851 255.873 348.671 254.617 345.975 255.362L345.644 255.457C343.265 256.171 341.121 255.07 338.894 253.926L338.894 253.926C337.679 253.302 336.439 252.665 335.122 252.303C332.304 251.529 329.028 252.045 325.843 252.546H325.843C322.03 253.147 318.348 253.726 315.738 252.05C311.072 249.052 303.669 248.053 297.566 249.571L296.349 249.892C294.178 250.459 291.633 250.988 290.247 249.861C287.39 247.54 281.151 247.646 276.55 247.725C274.107 247.766 272.127 247.8 271.359 247.459C281.402 245.506 287.831 245.673 290.645 247.959ZM290.308 258.476C288.007 259.094 285.025 259.893 283.481 258.639C280.667 256.353 274.238 256.186 264.195 258.139C264.963 258.48 266.943 258.446 269.386 258.405C273.987 258.326 280.226 258.22 283.083 260.541C284.469 261.668 287.014 261.139 289.185 260.572L290.402 260.251C296.111 258.831 302.958 259.614 307.637 262.174C309.072 263.199 311.569 263.071 314.313 262.93C316.179 262.834 318.159 262.732 319.998 262.983C322.264 263.293 323.341 263.732 324.287 264.118C325.236 264.505 326.053 264.838 327.804 264.931C329.836 265.039 334.67 264.109 334.67 264.109C340.307 263.252 349.003 265.762 353.15 268.426L353.374 268.566C357.956 271.361 358.338 269.601 353.547 266.523L353.28 266.355C348.505 263.429 338.673 261.093 332.616 262.716L332.496 262.748C330.194 263.366 327.213 264.165 325.669 262.911C324.592 262.036 321.074 261.184 320.395 261.081C316.811 260.534 316.324 260.705 315.236 261.088C315.206 261.098 315.176 261.109 315.145 261.119C315.124 261.127 315.103 261.134 315.081 261.142C315.041 261.156 315.001 261.17 314.959 261.184L314.627 261.21C313.393 261.312 312.069 261.468 310.654 261.676C310.153 261.503 309.599 261.23 308.971 260.827L308.704 260.659C303.929 257.733 296.485 256.821 290.428 258.444L290.308 258.476Z" fill="#FFB61D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M388.723 133.193C402.153 133.234 412.752 143.425 411.846 155.422C411.846 155.422 396.186 216.362 404.123 238.022C407.194 246.402 451.529 272.478 449.655 275.157L443.399 288.565C441.176 291.739 373.128 251.023 373.128 251.023C366.599 246.388 365.385 154.224 365.385 154.224C365.257 142.617 375.758 133.152 388.723 133.193Z" fill="white"/>
<path d="M459.211 277.576L451.214 292.305L451.055 292.699C450.389 294.225 447.846 295.159 447.519 295.234L447.471 295.234L442.748 292.734C442.207 292.328 441.911 290.047 442.483 287.926L442.617 287.48C442.617 287.48 446.361 275.716 449.463 272.746C451.271 271.013 461.716 272.746 459.211 277.576Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M345.288 413.409H326.196C326.196 413.409 348.602 361.376 348.602 347.721C348.602 343.486 330.99 349.867 333.545 343.486C337.058 334.712 349.215 319.022 346.221 311.146C343.089 302.91 331.409 299.925 321.237 296.587C319.288 295.948 354.844 298.156 364.596 291.217C377.461 282.063 367.016 261.849 370.471 268.976C374.639 277.576 401.725 299.149 396.356 322.511C391.125 345.27 345.288 413.409 345.288 413.409Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M338.67 423.443L336.708 422.86C336.621 422.834 336.611 422.714 336.693 422.675L338.564 421.765V419.659C338.564 419.576 338.66 419.529 338.726 419.581L340.301 420.819L342.896 419.596C342.986 419.554 343.076 419.654 343.024 419.739L341.563 422.123L344.342 424.72C344.418 424.791 344.349 424.916 344.249 424.89L340.403 423.898L338.854 426.339C338.8 426.424 338.67 426.386 338.67 426.285V425.036V423.443Z" fill="#FFB61D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M287.8 310.937L287.8 310.937C286.248 312.412 284.697 313.886 283.079 315.301C280.053 317.948 276.996 320.581 273.784 323.043C269.8 326.098 265.716 329.059 261.541 331.901C256.815 335.117 251.976 338.203 247.116 341.254C246.858 341.416 246.6 341.58 246.343 341.743C243.864 343.316 241.386 344.888 238.201 345.373C237.292 345.512 236.441 345.92 235.584 346.331C234.903 346.658 234.218 346.986 233.497 347.182C228.529 348.529 223.535 349.812 218.51 350.976C215.425 351.69 212.275 352.2 209.133 352.69C207.177 352.995 195.974 354.587 188.522 355.555C181.069 356.522 156.421 356.522 150.267 356.407C146.814 356.343 143.362 356.236 139.91 356.118L139.732 356.112C139.029 356.09 138.282 356.066 137.67 355.818C134.281 354.444 131.658 355.941 129 357.457L128.809 357.566C125.319 359.554 123.183 362.545 121.073 365.609C119.952 367.237 118.764 368.828 117.576 370.418L117.576 370.419L117.575 370.419C116.297 372.131 115.019 373.843 113.824 375.6C112.242 377.927 110.831 380.349 109.421 382.769C109.168 383.204 108.915 383.639 108.66 384.073C106.797 387.255 104.002 389.106 99.9912 389.79C97.9979 390.131 96.2904 389.601 94.587 389.073L94.586 389.073C93.9551 388.877 93.3247 388.682 92.6805 388.531C91.4192 388.235 90.4024 385.187 90.8523 383.98C92.1646 380.461 93.4795 376.942 94.7945 373.424L94.7955 373.421L94.7964 373.418L94.7966 373.418C97.5463 366.06 100.296 358.702 103.022 351.337C104.925 346.194 106.783 341.038 108.642 335.882L108.643 335.879C109.168 334.423 109.692 332.967 110.218 331.512C110.468 330.819 110.706 330.122 110.944 329.425L110.944 329.424L110.944 329.424C111.339 328.268 111.733 327.113 112.184 325.975C112.332 325.602 112.944 325.143 113.36 325.128C116.367 325.02 119.254 325.679 121.997 326.686C127.182 328.589 131.173 331.8 134.102 336.074C134.879 337.207 136.234 337.615 137.944 337.345C138.769 337.214 139.601 337.116 140.433 337.018L140.434 337.018C141.705 336.868 142.974 336.718 144.215 336.454C146.975 335.868 149.768 335.849 152.561 335.829C154.359 335.816 156.157 335.803 157.945 335.639C159.171 335.527 160.403 335.463 161.635 335.399L161.637 335.399L161.638 335.398L161.64 335.398L161.641 335.398L161.643 335.398L161.644 335.398L161.645 335.398C163.295 335.312 164.943 335.226 166.575 335.026C169.542 334.661 172.494 334.201 175.446 333.74L175.447 333.74L175.449 333.74L175.45 333.74L175.451 333.74L175.452 333.74L175.454 333.739L175.455 333.739C176.856 333.521 178.256 333.303 179.658 333.095C180.791 332.926 181.927 332.767 183.062 332.608L183.063 332.608L183.063 332.608L183.064 332.608L183.065 332.608L183.066 332.608L183.067 332.608L183.068 332.608L183.072 332.607L183.074 332.607C185.264 332.3 187.453 331.994 189.629 331.62C192.415 331.142 195.179 330.559 197.942 329.975L198.443 329.87L198.939 329.765C201.859 329.15 204.775 328.516 207.69 327.881C208.915 327.614 210.14 327.348 211.365 327.083C211.557 327.041 211.748 326.996 211.94 326.952C211.92 326.942 211.899 326.933 211.879 326.923L211.833 326.902L211.74 326.858C211.595 326.792 211.451 326.725 211.312 326.649C210.888 326.414 210.451 326.193 210.014 325.972C209.017 325.466 208.019 324.961 207.169 324.302C205.26 322.82 205.913 320.359 208.34 319.703C210.19 319.203 212.096 318.702 214.006 318.587C216.58 318.432 218.924 317.668 221.271 316.903L221.271 316.902L221.272 316.902L221.272 316.902L221.272 316.902L221.272 316.902L221.273 316.902L221.273 316.902C222.215 316.595 223.158 316.287 224.116 316.019C226.379 315.386 227.736 314.195 228.872 312.373C229.419 311.496 230.221 310.751 231.026 310.003L231.026 310.003L231.026 310.003C231.593 309.477 232.161 308.949 232.644 308.372C235.146 305.381 237.578 302.341 239.947 299.265C240.45 298.611 240.854 297.896 241.258 297.181L241.258 297.181L241.258 297.181L241.258 297.181L241.258 297.181L241.259 297.181L241.259 297.18L241.259 297.18C241.568 296.633 241.877 296.086 242.232 295.565C243.063 294.343 243.908 293.106 244.935 292.018L245.07 291.875C247.424 289.378 249.785 286.873 252.346 284.551C253.742 283.285 255.282 282.147 256.823 281.009C257.551 280.471 258.28 279.934 258.993 279.382C259.352 279.104 259.698 278.803 260.001 278.475C260.52 277.913 260.734 277.445 259.95 276.78C259.746 276.607 259.541 276.435 259.336 276.262L259.335 276.262C257.288 274.54 255.222 272.803 254.104 270.421C253.986 270.172 253.868 269.922 253.75 269.672C252.852 267.776 251.945 265.862 251.434 263.877C250.747 261.204 251.024 258.484 251.914 255.791C253.161 252.023 255.77 249.168 259.304 247.118C261.484 245.854 263.778 244.748 266.073 243.642C267.773 242.823 269.474 242.003 271.129 241.118C272.409 240.435 273.503 239.439 274.571 238.469C274.673 238.376 274.775 238.283 274.877 238.191C279.684 233.841 283.034 228.577 286.371 223.332C286.726 222.774 287.08 222.217 287.436 221.662C290.662 216.627 293.557 211.417 296.442 206.214C297.273 204.716 297.985 203.165 298.698 201.614L298.698 201.614C299.327 200.243 299.957 198.872 300.669 197.536C301.232 196.481 301.925 195.482 302.62 194.483L302.62 194.483L302.62 194.483L302.62 194.482L302.62 194.482L302.621 194.482L302.621 194.481L302.621 194.481C303.131 193.748 303.641 193.014 304.099 192.256C304.592 191.443 305.041 190.607 305.49 189.772L305.49 189.772L305.491 189.771L305.491 189.771L305.491 189.77L305.492 189.77L305.492 189.77L305.492 189.769C306.174 188.502 306.854 187.237 307.683 186.052C308.274 185.206 309.133 184.509 309.99 183.812L309.99 183.812C310.349 183.52 310.707 183.229 311.046 182.926C311.468 182.55 311.898 182.18 312.328 181.81C312.776 181.424 313.224 181.038 313.664 180.645C314.439 179.951 315.204 179.248 315.947 178.527C317.375 177.141 318.811 175.76 320.247 174.38C323.788 170.976 327.328 167.573 330.752 164.077C334.763 159.981 338.579 155.725 342.327 151.432C343.817 149.725 345.161 147.915 346.504 146.106C347.102 145.3 347.7 144.494 348.312 143.697C348.319 143.687 348.326 143.677 348.333 143.668C348.34 143.657 348.347 143.647 348.353 143.636C348.362 143.622 348.371 143.608 348.379 143.594L348.403 143.553L348.403 143.553C348.443 143.483 348.484 143.413 348.541 143.356C349.511 142.401 350.47 141.437 351.43 140.472L351.432 140.47L351.432 140.47C353.687 138.203 355.942 135.937 358.328 133.787C361.868 130.597 365.923 127.952 370.324 125.749C370.996 125.413 371.643 125.032 372.289 124.651C373.308 124.051 374.324 123.452 375.428 123.034C375.689 122.936 375.952 122.835 376.216 122.733C378.326 121.922 380.538 121.072 382.716 121.032C387.312 120.948 392.089 120.995 395.947 123.9C396.678 124.451 396.873 124.321 396.942 123.585C397.007 122.882 397.141 122.157 397.274 121.433C397.585 119.746 397.896 118.057 397.354 116.628C397.027 115.765 396.912 114.894 396.799 114.03C396.67 113.053 396.543 112.085 396.111 111.15C394.664 108.023 393.372 104.837 392.082 101.653C391.887 101.174 391.693 100.694 391.498 100.215C391.094 99.2214 390.766 98.1775 390.616 97.1321C390.509 96.385 390.473 95.6296 390.437 94.8743C390.4 94.0989 390.363 93.3236 390.249 92.5574C389.844 89.8321 390.9 87.4375 391.96 85.0334L391.961 85.0318C392.155 84.5934 392.348 84.1547 392.533 83.7137C394.786 78.3345 399.008 74.2663 403.566 70.446C407.491 67.1568 413.992 66.1219 419.25 65.3108C421.192 65.0111 434.823 64.7246 442.022 64.5733C444.37 64.5239 446.034 64.4889 446.384 64.4726C447.803 64.4062 448.765 63.8154 449.727 63.1812C451.711 61.8721 452.221 59.8418 452.722 57.8439L452.723 57.8393C452.772 57.6439 452.821 57.4487 452.872 57.2546C452.882 57.2157 452.891 57.1776 452.901 57.1401L452.903 57.1313L452.906 57.1187L452.907 57.1152C453.036 56.5913 453.127 56.2241 454.008 56.2505C456.947 56.3388 458.459 58.0559 459.898 60.018C461.519 62.2274 462.832 64.5312 463.283 67.1647C463.832 70.3713 463.537 73.3499 460.988 75.9906C458.914 78.1383 456.501 79.7797 453.775 81.1571C453.413 81.34 453.184 82.3082 453.385 82.7218C455.439 86.9605 455.592 91.429 455.391 95.9152C455.342 97.004 455.145 98.0871 454.948 99.1705L454.948 99.1708C454.761 100.197 454.574 101.224 454.513 102.256C454.339 105.216 455.016 108.063 456.343 110.816C457.244 112.684 456.611 114.453 455.101 115.921C454.842 116.172 454.52 116.382 454.2 116.591C453.751 116.885 453.306 117.175 453.053 117.57C452.479 118.465 452.079 119.542 451.986 120.568C451.915 121.353 452.009 122.149 452.104 122.946C452.162 123.442 452.221 123.938 452.24 124.433C452.314 126.338 451.504 127.967 450.412 129.594C448.435 132.536 445.825 134.701 442.038 135.41C438.794 136.018 435.424 136.054 432.291 135.098C428.734 134.014 425.266 132.626 421.919 131.091C420.969 130.655 420.216 129.871 419.464 129.089C419.128 128.738 418.792 128.388 418.438 128.069C417.914 127.597 417.649 127.46 416.952 128.12C414.464 130.477 412.656 133.154 411.194 136.111C410.387 137.742 410.91 139.083 411.467 140.512L411.533 140.68C411.586 140.816 411.639 140.952 411.692 141.087C412.464 143.065 413.233 145.033 413.173 147.197C413.143 148.27 413.167 149.345 413.19 150.421V150.421C413.226 152.12 413.263 153.817 413.091 155.498C412.907 157.297 412.455 159.074 412.004 160.85C411.822 161.565 411.641 162.28 411.477 162.996C411.302 163.757 411.132 164.518 410.961 165.279C410.445 167.581 409.929 169.883 409.312 172.163C409.026 173.219 408.634 174.25 408.242 175.282L408.242 175.282L408.242 175.283L408.242 175.283L408.241 175.283L408.241 175.284L408.241 175.284L408.241 175.284L408.241 175.284L408.241 175.285C407.92 176.129 407.599 176.973 407.336 177.831C407.032 178.826 406.723 179.82 406.414 180.814C405.214 184.68 404.013 188.547 403.041 192.46C402.209 195.81 401.729 199.256 401.45 202.683C401.275 204.825 401.301 206.98 401.328 209.136C401.342 210.328 401.357 211.521 401.338 212.711C401.323 213.611 401.271 214.511 401.218 215.41C401.152 216.554 401.086 217.697 401.096 218.84C401.101 219.297 401.104 219.753 401.108 220.21V220.211V220.211V220.211V220.212V220.212V220.212V220.213C401.13 223.231 401.152 226.255 401.449 229.254C401.745 232.247 402.379 235.229 403.113 238.167C403.716 240.579 405.565 242.444 407.401 244.192C408.355 245.102 409.414 245.923 410.474 246.745L410.474 246.745L410.474 246.746L410.474 246.746L410.474 246.746L410.475 246.746L410.475 246.746L410.475 246.747C411.216 247.321 411.958 247.897 412.664 248.503C413.148 248.918 413.584 249.381 414.019 249.843C414.561 250.418 415.101 250.991 415.732 251.472C417.792 253.039 419.887 254.57 421.982 256.1L421.985 256.102L421.986 256.103L421.987 256.104L421.988 256.105L421.99 256.105L421.991 256.106L421.992 256.107L421.993 256.108C423.58 257.268 425.167 258.427 426.739 259.602C428.152 260.659 429.543 261.737 430.934 262.816C432.341 263.906 433.747 264.997 435.175 266.064C437.126 267.522 439.105 268.96 441.173 270.282C442.146 270.904 443.165 271.468 444.184 272.033L444.185 272.033L444.185 272.033L444.186 272.034L444.186 272.034L444.187 272.034L444.187 272.035L444.188 272.035C445.241 272.618 446.294 273.202 447.296 273.848C448.5 274.626 449.434 274.188 450.363 273.753C450.683 273.603 451.003 273.454 451.332 273.354C454.009 272.545 456.127 272.85 457.132 275.153C457.333 275.615 457.64 276.03 457.949 276.447C458.511 277.207 459.08 277.975 459.031 279.047C459.016 279.382 459.825 279.782 460.518 280.125C460.684 280.207 460.843 280.285 460.983 280.359C463.022 281.435 465.087 282.475 467.152 283.512C467.592 283.733 468.049 283.935 468.504 284.137C469.381 284.525 470.256 284.912 471.017 285.435C471.793 285.967 472.497 286.583 473.201 287.198C473.907 287.816 474.613 288.433 475.392 288.966C476.994 290.064 477.902 291.574 478.805 293.075C479.137 293.626 479.467 294.176 479.831 294.704C480.837 296.162 481.418 297.951 481.752 299.66C482.203 301.965 482.386 304.335 482.375 306.676C482.371 307.654 481.707 308.705 481.098 309.586C480.442 310.537 479.458 310.672 478.51 309.754C478.432 309.678 478.323 309.629 478.214 309.58C478.164 309.557 478.113 309.534 478.066 309.509C478.058 309.566 478.052 309.624 478.045 309.681L478.038 309.74C478.031 309.799 478.024 309.857 478.016 309.916C478.01 309.962 478.003 310.007 477.996 310.053C477.936 310.446 477.887 310.843 477.839 311.239C477.72 312.216 477.601 313.193 477.295 314.119C477.089 314.74 476.198 315.561 475.58 315.587C475.105 315.608 474.606 315.212 474.111 314.821C473.913 314.664 473.715 314.507 473.52 314.379C473.329 314.253 473.167 314.09 473.008 313.929L472.957 313.878C472.857 313.778 472.769 313.668 472.68 313.559L472.632 313.5L472.612 313.476C472.595 313.455 472.578 313.435 472.561 313.414C472.531 313.471 472.502 313.528 472.472 313.584C472.408 313.708 472.344 313.832 472.275 313.954C472.186 314.111 472.108 314.278 472.03 314.446C471.854 314.823 471.679 315.2 471.377 315.458C470.21 316.452 468.641 316.064 468.16 314.669C467.91 313.944 467.702 313.207 467.495 312.47L467.495 312.469L467.494 312.469L467.494 312.468L467.494 312.468L467.494 312.467L467.494 312.467C467.206 311.444 466.918 310.423 466.519 309.437C466.354 309.03 466.218 308.615 466.082 308.2C465.684 306.987 465.285 305.771 464.168 304.748C463.363 304.012 462.871 302.996 462.381 301.986C462.19 301.592 462 301.199 461.791 300.823C460.538 298.565 458.466 297.088 456.071 295.896C455.419 295.572 454.77 295.215 454.204 294.785C452.948 293.831 452.079 294.351 451.315 295.322C450.053 296.928 447.96 297.519 446.014 296.594C443.032 295.177 440.596 293.316 439.786 290.129C439.636 289.539 438.663 289.019 437.949 288.658C435.802 287.575 433.641 286.512 431.481 285.449C427.898 283.686 424.315 281.923 420.793 280.069C416.398 277.755 412.116 275.266 407.838 272.778C407.408 272.528 406.978 272.279 406.548 272.029C399.804 268.112 393.086 264.16 386.367 260.208L386.354 260.201C385.041 259.428 383.728 258.656 382.415 257.884C380.94 257.016 379.475 256.136 378.01 255.255L378.003 255.25C376.984 254.638 375.965 254.025 374.943 253.417C374.533 253.173 374.1 252.953 373.656 252.766C372.33 252.206 371.94 252.408 371.834 253.679C371.83 253.727 371.835 253.774 371.834 253.822C371.809 255.375 371.785 256.928 371.76 258.482L371.75 259.147C371.673 264.072 371.596 268.997 371.514 273.921C371.488 275.491 372.407 276.694 373.313 277.88L373.315 277.882C373.498 278.122 373.68 278.36 373.854 278.602C377.049 283.028 380.311 287.417 383.605 291.786C384.508 292.984 385.445 294.164 386.382 295.343L386.382 295.343L386.383 295.344L386.383 295.345L386.384 295.346L386.384 295.346L386.385 295.347L386.385 295.348C387.797 297.125 389.209 298.903 390.506 300.745C391.165 301.68 391.559 302.765 391.952 303.85C392.125 304.326 392.297 304.802 392.492 305.266C392.55 305.402 392.61 305.539 392.67 305.675C392.703 305.749 392.736 305.824 392.769 305.898C393.022 306.465 393.275 307.032 393.434 307.619C394.717 312.368 394.139 317.08 392.871 321.74C392.786 322.052 392.701 322.365 392.617 322.677L392.616 322.678C391.829 325.589 391.038 328.513 389.889 331.312C388.968 333.556 387.817 335.725 386.666 337.894C386.112 338.939 385.558 339.984 385.029 341.038C384.106 342.878 383.213 344.73 382.331 346.586C380.835 349.732 379.347 352.882 377.876 356.038C377.343 357.182 376.828 358.333 376.312 359.485L376.31 359.489C375.277 361.797 374.244 364.105 373.069 366.354C371.378 369.591 369.498 372.751 367.62 375.908L367.62 375.909L367.62 375.91L367.62 375.91L367.619 375.911L367.619 375.911L367.619 375.912L367.619 375.912C367.349 376.366 367.079 376.819 366.81 377.273C365.636 379.252 364.434 381.216 363.231 383.181C362.067 385.083 360.902 386.984 359.765 388.898C358.727 390.644 357.717 392.403 356.708 394.162C355.628 396.043 354.548 397.923 353.435 399.788C351.853 402.435 350.196 405.049 348.49 407.634C347.07 409.785 347.481 410.788 349.124 412.769C350.905 414.917 353.673 415.635 356.418 416.196C363.948 417.735 371.494 419.21 379.04 420.686L379.419 420.76C380.179 420.909 380.949 421.019 381.718 421.13C382.583 421.255 383.448 421.379 384.299 421.557C388.549 422.447 390.682 425.244 391.819 428.713C392.546 430.933 392.761 433.316 390.785 435.16C390.038 435.857 388.675 436.375 387.59 436.378C373.614 436.42 359.638 436.427 345.662 436.434C336.86 436.438 328.057 436.443 319.254 436.456C318.228 436.458 318.154 436.182 318.076 435.375C317.997 434.554 317.834 433.735 317.67 432.916C317.431 431.715 317.192 430.516 317.222 429.32C317.363 423.573 319.615 418.425 323.555 413.905C323.839 413.579 324.3 413.363 324.755 413.15C325.261 412.913 325.76 412.679 325.998 412.303C327.147 410.485 328.132 408.553 328.887 406.576C330.096 403.409 331.297 400.213 332.073 396.947C332.429 395.447 332.944 393.993 333.459 392.537C334.1 390.728 334.741 388.917 335.08 387.013C335.437 385.002 336.372 383.065 337.3 381.14C337.588 380.543 337.876 379.947 338.146 379.35C339.066 377.313 340.016 375.287 340.966 373.26L340.967 373.26L340.967 373.259L340.967 373.258L340.968 373.258L340.968 373.257L340.968 373.256L340.968 373.256C342.444 370.109 343.92 366.962 345.283 363.776C346.254 361.504 347.059 359.175 347.865 356.846C348.325 355.517 348.784 354.188 349.275 352.869C350.313 350.078 351.368 347.288 352.558 344.547C352.825 343.932 352.675 343.921 352.299 343.895C352.23 343.89 352.152 343.884 352.068 343.874C347.049 343.278 342.105 343.33 337.425 345.328C336.399 345.766 335.677 345.675 334.998 344.913C334.304 344.134 334.665 343.566 335.279 342.851C338.937 338.59 341.209 333.737 342.952 328.617C343.134 328.081 343.322 327.547 343.509 327.013L343.51 327.012L343.51 327.01C344.643 323.784 345.771 320.567 345.741 317.138C345.717 314.54 345.002 312.21 343.005 310.038C342.567 309.56 342.163 309.06 341.762 308.562C340.564 307.075 339.383 305.609 337.328 304.842C336.287 304.453 335.261 304.035 334.234 303.616L334.233 303.616L334.232 303.615C333.165 303.18 332.097 302.744 331.014 302.343C330.194 302.039 329.374 301.733 328.555 301.426L328.552 301.425L328.549 301.424L328.546 301.423L328.543 301.422L328.543 301.422C325.3 300.209 322.055 298.994 318.747 297.945C316.737 297.308 314.656 296.852 312.574 296.397L312.574 296.396C311.628 296.189 310.682 295.982 309.743 295.758C309.558 295.714 309.376 295.662 309.193 295.61C309.048 295.568 308.902 295.527 308.755 295.489C306.616 294.943 304.749 295.038 303.296 296.884C302.659 297.694 301.784 298.353 300.867 299.044C300.684 299.182 300.501 299.32 300.317 299.461C296.861 302.509 293.56 305.553 290.271 308.607C289.441 309.378 288.62 310.157 287.8 310.937ZM369.078 254.847L369.078 254.847L369.078 254.846C369.262 254.022 369.446 253.198 369.546 252.365L369.574 252.133C369.79 250.347 370.008 248.536 369.866 246.76C369.792 245.84 369.518 244.936 369.244 244.03C369.022 243.296 368.799 242.56 368.682 241.814C368.068 237.893 367.515 233.961 367.089 230.02C366.718 226.593 366.471 223.155 366.224 219.717L366.18 219.098L366.12 218.275C365.871 214.844 365.64 211.411 365.49 207.976C365.346 204.683 365.275 201.387 365.204 198.092V198.091L365.186 197.303L365.173 196.705C365.169 196.497 365.248 196.289 365.327 196.08L365.327 196.08C365.378 195.947 365.429 195.813 365.459 195.678C365.492 195.526 365.533 195.373 365.574 195.219C365.688 194.795 365.802 194.368 365.76 193.956C365.713 193.502 365.599 193.05 365.485 192.599C365.331 191.988 365.177 191.379 365.194 190.771C365.307 186.743 365.511 182.717 365.714 178.692L365.714 178.689C365.744 178.097 365.774 177.505 365.804 176.913C365.847 176.048 365.971 175.183 366.119 174.326C366.535 171.907 366.967 169.49 367.4 167.074L367.539 166.298L367.704 165.377C367.739 165.18 367.786 164.985 367.833 164.79C367.855 164.7 367.877 164.61 367.898 164.519C367.91 164.619 367.926 164.718 367.942 164.818L367.942 164.821C367.976 165.037 368.01 165.254 368.015 165.47C368.115 169.981 368.208 174.492 368.302 179.002L368.337 180.728C368.368 182.202 368.399 183.676 368.431 185.15L368.434 185.28C368.511 188.896 368.589 192.511 368.652 196.127C368.694 198.521 368.727 200.916 368.76 203.31C368.82 207.663 368.88 212.015 368.995 216.367C369.081 219.613 369.311 222.86 369.633 226.095C369.869 228.468 370.214 230.833 370.559 233.197L370.559 233.198L370.56 233.202L370.56 233.206L370.561 233.21C370.67 233.956 370.779 234.702 370.884 235.448C371.032 236.496 371.193 237.543 371.355 238.591C371.637 240.421 371.919 242.252 372.13 244.089C372.397 246.424 373.653 248.314 375.461 249.81C376.78 250.903 378.267 251.834 379.754 252.764L379.756 252.765L379.758 252.766L379.76 252.767L379.762 252.769L379.764 252.77L379.766 252.771L379.768 252.773C380.35 253.137 380.933 253.501 381.504 253.875C382.709 254.664 383.909 255.459 385.108 256.254L385.109 256.255C388.119 258.25 391.129 260.245 394.222 262.13C396.984 263.815 399.828 265.393 402.671 266.971L402.672 266.971L402.672 266.971L402.673 266.972L402.673 266.972L402.674 266.972L402.674 266.973L402.675 266.973L402.675 266.973L402.676 266.973L402.676 266.974L402.677 266.974L402.677 266.974L402.677 266.974L402.678 266.974C404.054 267.738 405.431 268.503 406.799 269.279C408.114 270.025 409.424 270.779 410.734 271.532C413.062 272.871 415.39 274.211 417.746 275.509L418.191 275.754C422.509 278.133 426.832 280.515 431.253 282.734C433.355 283.788 435.584 284.645 437.808 285.499L437.808 285.499C438.379 285.719 438.949 285.938 439.517 286.16C439.847 286.289 440.607 286.141 440.764 285.906C441.134 285.349 441.375 284.719 441.614 284.094L441.616 284.087L441.618 284.083C441.664 283.961 441.71 283.84 441.758 283.72C442.687 281.348 443.863 279.133 445.87 277.286C447.384 275.892 447.171 275.473 445.068 274.681C444.959 274.64 444.85 274.6 444.742 274.559L444.718 274.55L444.714 274.549C443.835 274.22 442.948 273.889 442.15 273.439C440.667 272.602 439.225 271.694 437.84 270.731C436.61 269.877 435.376 269.025 434.143 268.174L434.141 268.172L434.14 268.171L434.139 268.171L434.139 268.17L434.138 268.17L434.138 268.17L434.137 268.17C429.98 265.299 425.823 262.428 421.78 259.434C418.016 256.644 414.438 253.638 410.934 250.585C410.446 250.16 409.953 249.738 409.46 249.316L409.459 249.316C406.478 246.767 403.484 244.206 401.593 240.824C401.334 240.361 401.034 239.914 400.734 239.467C399.864 238.171 398.994 236.875 399.123 235.172C399.201 234.131 399.045 233.073 398.89 232.018L398.889 232.017L398.889 232.015L398.889 232.014L398.889 232.012C398.833 231.632 398.777 231.253 398.732 230.874C398.61 229.845 398.465 228.817 398.32 227.789L398.32 227.788C398.023 225.687 397.727 223.586 397.627 221.478C397.492 218.631 397.523 215.777 397.554 212.923V212.922C397.567 211.693 397.58 210.464 397.58 209.236C397.58 208.948 397.571 208.659 397.561 208.369C397.54 207.738 397.52 207.106 397.597 206.484C397.975 203.458 398.36 200.429 398.869 197.419C398.969 196.83 399.066 196.241 399.163 195.652C399.637 192.769 400.113 189.879 400.897 187.063C401.581 184.608 402.422 182.189 403.262 179.769L403.262 179.769L403.263 179.768L403.263 179.768L403.263 179.767L403.263 179.766L403.263 179.766L403.263 179.765L403.264 179.764C403.929 177.849 404.594 175.934 405.182 174.001C405.605 172.61 406.071 171.229 406.537 169.847C407.704 166.39 408.871 162.931 409.366 159.314C409.474 158.526 409.697 157.741 409.92 156.958C410.247 155.807 410.572 154.662 410.527 153.522C410.363 149.404 409.08 145.435 407.789 141.474C405.86 135.556 402.514 130.62 396.726 127.107C393.386 125.08 389.887 123.595 385.743 124.072C384.241 124.245 382.753 124.523 381.265 124.8L381.265 124.8L381.265 124.8L381.264 124.8L381.264 124.8L381.263 124.8L381.263 124.8L381.263 124.8L381.262 124.8C380.547 124.934 379.832 125.067 379.116 125.189C375.044 125.88 371.441 127.487 368.196 129.747C366.297 131.069 364.442 132.449 362.638 133.875C360.835 135.301 359.032 136.744 357.389 138.313C355.861 139.772 354.439 141.322 353.019 142.871L353.019 142.871L353.018 142.872L353.018 142.872L353.018 142.872L353.018 142.872L353.018 142.872L353.017 142.873L353.012 142.879L353.009 142.881C352.703 143.216 352.397 143.55 352.089 143.883C349.647 146.529 347.212 149.18 344.823 151.864C343.778 153.039 342.754 154.229 341.73 155.419L341.729 155.42L341.729 155.42L341.728 155.421L341.728 155.421L341.728 155.422L341.727 155.422L341.727 155.423C340.178 157.223 338.629 159.023 337.007 160.769C334.065 163.936 331.012 167.023 327.914 170.068C323.656 174.252 319.324 178.376 314.993 182.499C314.623 182.85 314.198 183.157 313.774 183.463C313.265 183.83 312.757 184.197 312.348 184.638C309.212 188.025 306.258 191.557 304.162 195.546C302.229 199.224 300.366 202.932 298.503 206.64C296.829 209.973 295.155 213.306 293.43 216.617C290.633 221.984 287.555 227.213 283.84 232.148L283.567 232.511C281.577 235.158 279.586 237.806 276.782 239.736C273.126 242.25 269.32 244.591 265.515 246.931L265.512 246.932L265.509 246.934L265.506 246.936L265.503 246.938C264.514 247.546 263.525 248.155 262.539 248.766C259.33 250.755 256.79 253.265 255.541 256.571C254.008 260.631 254.792 264.663 256.933 268.363C259.568 272.918 263.738 276.399 267.995 279.716C272.72 283.397 278.21 286.037 284.134 287.734C291.749 289.915 299.407 292.033 307.46 292.651C309.566 292.812 311.664 293.06 313.762 293.307L313.763 293.307C316.102 293.582 318.441 293.857 320.791 294.014C325.987 294.361 331.205 294.554 336.416 294.579C338.759 294.591 341.102 294.445 343.447 294.3C344.935 294.207 346.423 294.115 347.912 294.063C351.959 293.921 355.793 292.969 359.569 291.768C362.106 290.961 364.454 289.851 365.381 287.401C365.921 285.974 366.189 284.447 366.411 282.945L366.468 282.559C366.936 279.388 367.405 276.212 367.672 273.024C367.917 270.091 368.045 267.149 368.178 264.099L368.178 264.097L368.178 264.096L368.178 264.094L368.178 264.093L368.179 264.092L368.179 264.091L368.179 264.089L368.179 264.088L368.179 264.086L368.179 264.084C368.229 262.937 368.28 261.775 368.337 260.592C368.37 260.211 368.396 259.829 368.422 259.447C368.481 258.585 368.541 257.723 368.672 256.87C368.777 256.192 368.927 255.52 369.078 254.847ZM234.064 343.309C234.233 343.446 234.62 343.535 234.811 343.457C235.679 343.103 236.563 342.769 237.448 342.436C239.604 341.622 241.761 340.808 243.704 339.694C247.173 337.707 250.557 335.602 253.942 333.497C256.598 331.845 259.254 330.192 261.951 328.597C267.834 325.117 272.991 320.879 278.149 316.641C279.154 315.815 280.159 314.989 281.17 314.169C282.737 312.897 284.213 311.531 285.686 310.166L285.687 310.166L285.859 310.006L286.225 309.668L286.415 309.492L286.645 309.28C288.399 307.666 290.137 306.038 291.876 304.409C292.63 303.702 293.384 302.996 294.14 302.29C294.682 301.784 295.225 301.279 295.768 300.774C297.74 298.941 299.712 297.107 301.623 295.224C301.848 295.002 301.566 293.894 301.308 293.824C300.225 293.53 299.122 293.29 298.019 293.051L298.019 293.051L298.019 293.051L298.018 293.051C296.62 292.747 295.222 292.443 293.866 292.029L293.174 291.819C287.56 290.109 281.938 288.397 276.444 286.409C271.412 284.589 266.751 282.088 262.583 278.917C262.519 278.868 262.22 278.933 262.188 279.003C260.984 281.603 258.745 283.375 256.497 285.154L256.497 285.154L256.497 285.154L256.497 285.154L256.496 285.154L256.496 285.155L256.496 285.155L256.496 285.155C255.984 285.56 255.471 285.966 254.97 286.381C252.611 288.34 250.269 290.349 248.202 292.548C246.865 293.969 245.728 295.542 244.592 297.113C244.174 297.691 243.757 298.268 243.329 298.838C242.847 299.481 242.338 300.114 241.828 300.747L241.828 300.747L241.827 300.748L241.827 300.748L241.827 300.749L241.826 300.749L241.826 300.75L241.826 300.75C240.574 302.305 239.321 303.862 238.463 305.575C236.55 309.398 233.584 312.444 230.487 315.412C227.443 318.329 223.295 319.416 219.199 320.488L219.192 320.49L219.185 320.492C218.994 320.542 218.803 320.592 218.613 320.642C218.428 320.691 218.243 320.739 218.058 320.789C216.554 321.189 215.006 321.458 213.458 321.728L213.458 321.728L213.457 321.728L213.457 321.728L213.456 321.728L213.456 321.728L213.456 321.728L213.455 321.728L213.451 321.729C212.603 321.876 211.755 322.024 210.914 322.193C210.7 322.236 210.508 322.365 210.315 322.493C210.226 322.553 210.137 322.613 210.046 322.664C210.145 322.77 210.246 322.906 210.348 323.042C210.566 323.336 210.784 323.63 210.978 323.618C212.956 323.492 214.433 324.402 215.885 325.295C216.272 325.534 216.657 325.771 217.05 325.987C218.964 327.041 220.844 328.176 221.959 330.139C222.683 331.412 223.656 332.575 224.626 333.734L224.626 333.734C224.923 334.09 225.221 334.445 225.51 334.803C226.702 336.275 227.948 337.713 229.305 339.278L229.307 339.28L229.594 339.612C229.933 339.894 230.272 340.177 230.611 340.459L230.614 340.462C231.758 341.417 232.902 342.372 234.064 343.309ZM331.702 299.186C332.912 299.762 334.202 300.201 335.492 300.64C338.034 301.505 340.576 302.37 342.516 304.287C343.105 304.869 343.784 305.377 344.463 305.885C344.905 306.215 345.346 306.546 345.764 306.897C347.146 308.06 347.624 309.613 348.099 311.161C348.131 311.265 348.163 311.368 348.195 311.472C348.233 311.593 348.271 311.713 348.309 311.834C349.615 315.897 349.319 320.1 348.173 323.996C348.099 324.248 348.025 324.5 347.951 324.752C346.425 329.958 344.876 335.24 341.633 339.912C341.257 340.454 341.06 340.744 342.094 340.77C344.875 340.842 347.656 340.935 350.436 341.028C353.499 341.131 356.563 341.233 359.626 341.307C361.548 341.353 363.472 341.342 365.396 341.331C366.721 341.323 368.047 341.315 369.372 341.327C372.843 341.356 376.216 340.907 379.375 339.59C379.5 339.537 379.63 339.484 379.762 339.43C380.841 338.989 382.063 338.49 382.55 337.698C383.792 335.679 384.671 333.457 385.472 331.252C386.645 328.025 387.806 324.777 388.623 321.468C389.321 318.643 389.674 315.73 389.893 312.838C389.959 311.968 389.793 311.087 389.627 310.204C389.496 309.501 389.364 308.797 389.347 308.095C389.281 305.342 387.823 303.101 386.365 300.858L386.266 300.705L386.109 300.464C385.77 299.94 385.335 299.466 384.899 298.992L384.899 298.992L384.898 298.991C384.558 298.621 384.217 298.25 383.921 297.854C381.581 294.724 379.25 291.588 376.92 288.452L376.917 288.447C375.269 286.229 373.621 284.012 371.97 281.796C371.811 281.583 371.607 281.398 371.402 281.213C371.352 281.167 371.301 281.121 371.251 281.075C371.207 281.034 371.164 280.993 371.121 280.952C371.03 281.077 370.922 281.199 370.815 281.322C370.579 281.589 370.344 281.856 370.275 282.155C370.115 282.847 370.009 283.549 369.903 284.251L369.903 284.252L369.903 284.253C369.813 284.85 369.723 285.448 369.6 286.039C368.882 289.473 367.043 292.111 363.426 293.809C358.44 296.149 353.081 297.148 347.604 297.711C344.447 298.036 341.231 298.088 338.051 297.995C336.139 297.939 334.233 297.728 332.326 297.517C331.294 297.403 330.261 297.289 329.227 297.199C328.949 297.175 328.66 297.25 328.371 297.325C328.237 297.36 328.103 297.395 327.97 297.42C328.052 297.478 328.133 297.538 328.214 297.597L328.214 297.597L328.214 297.597L328.214 297.597L328.214 297.597L328.215 297.597L328.215 297.598L328.215 297.598C328.418 297.747 328.622 297.895 328.834 298.033C328.879 298.062 328.929 298.083 328.992 298.11C329.091 298.152 329.219 298.206 329.4 298.322C329.643 298.412 329.889 298.497 330.135 298.581L330.135 298.581L330.135 298.581L330.135 298.581L330.135 298.581L330.135 298.581L330.136 298.581L330.136 298.581C330.669 298.764 331.202 298.947 331.702 299.186ZM397.623 80.5767C395.608 83.2134 394.391 86.2202 393.777 89.381C393.153 92.5929 393.066 95.841 394.118 98.9761C394.74 100.827 395.443 102.657 396.146 104.486C396.96 106.603 397.773 108.72 398.46 110.87C398.884 112.198 399.845 112.819 400.905 113.153C405.912 114.731 411.351 112.813 414.46 108.695C415.303 107.578 414.817 107.119 413.959 106.338C412.798 105.28 411.782 104.055 410.918 102.785C409.628 100.889 410.174 98.9565 411.652 97.4255C413.131 95.8933 415.351 95.5528 417.417 96.1948C419.778 96.9282 421.477 98.5429 422.688 100.52C422.745 100.613 422.785 100.714 422.826 100.814C422.845 100.861 422.864 100.908 422.884 100.954C422.892 100.94 422.899 100.926 422.907 100.912L422.926 100.878L422.926 100.878C422.956 100.824 422.986 100.771 423.007 100.715C423.185 100.227 423.358 99.7359 423.53 99.2448L423.53 99.2441C424.435 96.666 425.342 94.0808 427.17 91.8812C428.595 90.1666 430.13 88.4567 431.94 87.0882C433.292 86.065 434.963 85.3531 436.602 84.6547C436.842 84.5525 437.081 84.4507 437.318 84.3482C437.877 84.1065 438.436 83.8598 438.995 83.6128C441.342 82.5762 443.698 81.5355 446.169 80.8429C446.585 80.7266 446.794 80.6692 446.891 80.6426L446.953 80.6258C446.962 80.6232 446.966 80.6221 446.965 80.6219C446.965 80.6216 446.96 80.6227 446.952 80.6243L446.952 80.6244C446.822 80.6503 445.985 80.8171 454.154 78.1818C465.56 74.5024 459.692 62.9116 456.315 60.3618C456.064 60.1719 455.664 59.968 455.394 60.0203C455.151 60.0672 454.842 60.4461 454.817 60.699C454.563 63.2328 450.412 67.1647 440.55 66.5542C433.801 66.1364 433.654 66.1605 433.331 66.2135C433.183 66.238 432.996 66.2686 432.108 66.265C429.982 66.2562 422.62 66.8694 421.132 67.2458C420.591 67.3825 419.884 67.5147 419.052 67.6702C415.087 68.4113 408.287 69.6824 403.142 74.5024C402.573 75.1218 401.987 75.7313 401.401 76.3408L401.401 76.3412C400.08 77.7154 398.76 79.0895 397.623 80.5767ZM424.594 105.734C424.594 107.016 424.307 108.276 424.02 109.537L424.02 109.538C423.882 110.144 423.744 110.749 423.638 111.357C423.621 111.454 423.565 111.544 423.509 111.635C423.492 111.662 423.475 111.69 423.459 111.718C423.451 111.732 423.443 111.747 423.435 111.761L423.422 111.714L423.412 111.682L423.399 111.638C423.372 111.551 423.346 111.463 423.327 111.375C423.197 110.754 423.075 110.131 422.953 109.509C422.678 108.1 422.403 106.692 422.027 105.306C421.576 103.644 421.074 101.95 420.241 100.425C419.278 98.6622 415.245 97.8304 413.26 98.7552C412.128 99.2825 411.585 100.546 412.319 101.465C413.014 102.333 413.865 103.221 414.878 103.738C416.542 104.587 417.083 106.003 417.218 107.391C417.472 110 414.411 113.669 411.436 114.329C408.732 114.929 405.976 115.346 403.222 115.763L403.222 115.763L403.218 115.764C402.569 115.862 401.92 115.96 401.272 116.061C401.205 116.071 401.139 116.081 401.073 116.091C400.206 116.219 399.516 116.321 399.791 117.457C400.536 120.54 400.78 123.647 400.155 126.783C400.117 126.974 400.504 127.273 400.751 127.461C401.066 127.702 401.397 127.929 401.728 128.156C402.337 128.573 402.945 128.989 403.448 129.491C404.275 130.315 405.046 131.185 405.817 132.054L405.818 132.055L405.819 132.055L405.819 132.056L405.819 132.056L405.819 132.056L405.82 132.057L405.82 132.057C406.349 132.653 406.878 133.25 407.425 133.832C407.568 133.984 408.143 134.048 408.281 133.93C408.984 133.329 409.668 132.711 410.353 132.094L410.354 132.092C411.155 131.369 411.956 130.646 412.786 129.951C414.794 128.27 416.851 126.635 418.934 125.028C419.203 124.82 419.575 124.718 419.947 124.616C420.118 124.569 420.29 124.522 420.451 124.465C420.385 124.601 420.32 124.739 420.255 124.877L420.251 124.884C420.071 125.266 419.891 125.648 419.677 126.015C419.64 126.08 419.533 126.105 419.42 126.133C419.323 126.156 419.222 126.18 419.158 126.231C419.123 126.258 419.089 126.284 419.055 126.31C418.654 126.616 418.359 126.841 419.25 127.221C420.192 127.622 421.065 128.154 421.937 128.686C422.302 128.909 422.667 129.131 423.037 129.344C428.732 132.623 434.869 134.162 441.661 133.166C445.503 132.602 448.14 130.774 449.312 127.392C450.433 124.152 449.967 123.21 446.506 121.908C446.389 121.863 446.271 121.819 446.152 121.776C444.327 121.097 442.514 120.422 442.036 118.421C441.836 117.585 443.061 116.98 443.815 117.395C443.874 117.428 443.913 117.463 443.922 117.497C444.291 119.006 445.571 119.528 446.921 120.071C449.405 121.071 449.708 120.931 449.708 118.651C449.708 115.666 449.708 115.666 452.635 114.736C454.331 114.197 454.604 113.671 453.833 112.197C452.67 109.972 451.91 107.706 452.232 105.19C452.629 102.09 452.96 98.9799 453.178 95.8661C453.318 93.8652 453.452 91.8177 453.132 89.8506C452.927 88.5911 452.424 87.3703 451.921 86.1498L451.921 86.1495L451.921 86.148C451.705 85.6234 451.489 85.0989 451.296 84.5714C450.844 83.3309 449.754 82.8325 448.332 83.2912C447.443 83.5778 446.548 83.8542 445.654 84.1306C443.163 84.9002 440.672 85.6702 438.297 86.6631C435.797 87.7082 433.266 89.0047 431.322 90.7129C429.576 92.2477 424.594 99.9792 424.594 105.734ZM222.449 346.676L222.455 346.675L222.465 346.673C224.756 346.219 227.047 345.766 229.333 345.294C229.662 345.226 229.97 345.074 230.277 344.922L230.279 344.921L230.28 344.92C230.323 344.899 230.367 344.877 230.41 344.856L230.451 344.836C230.468 344.828 230.484 344.82 230.501 344.812C230.569 344.78 230.638 344.748 230.707 344.719C230.585 344.655 230.461 344.593 230.338 344.531C230.051 344.387 229.764 344.243 229.501 344.07C229.211 343.88 228.964 343.63 228.723 343.386L228.723 343.386L228.71 343.372C228.024 342.677 227.329 341.989 226.633 341.301L226.631 341.3L226.631 341.299L226.631 341.299L226.631 341.299L226.63 341.298L226.63 341.298L226.63 341.298L226.629 341.298C224.934 339.621 223.238 337.944 221.69 336.165C220.158 334.404 218.94 332.409 217.738 330.44L217.709 330.391C217.117 329.421 216.444 329.011 215.306 329.367C210.464 330.879 205.452 331.705 200.439 332.53L200.437 332.531C197.823 332.961 195.209 333.392 192.619 333.92C188.373 334.786 167 338.074 165.139 338.193C164.233 338.251 163.327 338.333 162.422 338.416L162.42 338.416L162.419 338.416C160.658 338.576 158.897 338.736 157.138 338.718C152.643 338.673 148.236 339.107 143.833 339.871C142.446 340.112 141.04 340.264 139.634 340.417L139.633 340.417L139.632 340.417L139.632 340.417L139.631 340.417L139.63 340.417L139.63 340.417L139.629 340.417L139.628 340.417C138.021 340.592 136.414 340.766 134.838 341.071C129.763 342.055 128.063 345.93 129.37 349.717C129.621 350.444 130.518 351.265 131.323 351.52C134.995 352.681 138.838 352.983 142.722 353.01C144.722 353.024 146.722 353.107 148.721 353.19L148.724 353.19H148.724H148.725H148.725H148.725H148.726H148.726C149.489 353.222 150.251 353.254 151.014 353.282C153.887 353.386 156.76 353.493 159.633 353.6C161.864 353.684 164.094 353.767 166.325 353.849C166.483 353.854 166.642 353.852 166.801 353.85C166.96 353.848 167.119 353.846 167.278 353.852C168.062 353.881 168.847 353.928 169.632 353.976C171.35 354.081 173.068 354.186 174.772 354.091C177.445 353.944 180.109 353.661 182.773 353.378L182.78 353.378C184.015 353.247 185.249 353.116 186.485 352.998C187.244 352.926 188.005 352.867 188.766 352.808L188.767 352.808L188.767 352.808L188.768 352.808L188.768 352.808L188.769 352.808L188.769 352.808L188.77 352.807C190.149 352.701 191.528 352.594 192.893 352.409L193.581 352.315C197.073 351.841 200.572 351.367 204.018 350.686C206.693 350.158 209.35 349.555 212.064 348.938L212.066 348.937L212.07 348.936L212.076 348.935L212.077 348.935L212.079 348.934C214.062 348.483 216.076 348.026 218.151 347.585C218.195 347.574 218.239 347.563 218.283 347.552L218.387 347.525L218.512 347.492C218.771 347.424 219.03 347.356 219.293 347.303C220.345 347.093 221.397 346.885 222.449 346.676ZM340.411 413.147C342.056 411.034 343.612 408.863 345.121 406.67C346.492 404.676 347.775 402.632 349.056 400.59C350.203 398.762 351.394 396.956 352.585 395.15L352.585 395.149C355.349 390.958 358.112 386.766 360.331 382.294C361.609 379.718 363.089 377.223 364.569 374.728L364.57 374.726C365.275 373.537 365.981 372.348 366.664 371.15C366.986 370.585 367.315 370.023 367.643 369.461L367.644 369.46L367.644 369.459L367.644 369.459L367.644 369.459L367.644 369.458L367.645 369.458L367.645 369.458L367.645 369.457C368.545 367.916 369.445 366.375 370.218 364.785C370.802 363.583 371.313 362.35 371.825 361.118L371.825 361.117L371.825 361.116L371.826 361.116L371.826 361.115L371.827 361.114L371.827 361.113L371.827 361.112C372.614 359.216 373.401 357.321 374.446 355.547C376.126 352.696 377.239 349.684 378.354 346.67L378.354 346.67L378.355 346.669C378.716 345.691 379.078 344.713 379.459 343.74C379.518 343.589 379.556 343.432 379.594 343.274C379.612 343.201 379.629 343.127 379.649 343.054C379.559 343.07 379.468 343.084 379.377 343.098C379.179 343.128 378.981 343.158 378.79 343.209C378.407 343.31 378.026 343.435 377.646 343.558C376.856 343.816 376.067 344.073 375.26 344.129C372.244 344.342 369.21 344.433 366.183 344.432C364.312 344.432 362.441 344.366 360.57 344.3H360.569H360.569H360.568H360.567H360.567H360.566H360.566C359.358 344.257 358.151 344.214 356.943 344.189C356.719 344.185 356.368 344.436 356.277 344.641C356.167 344.891 356.056 345.14 355.946 345.39L355.945 345.391C355.189 347.097 354.433 348.804 353.772 350.54C352.127 354.865 350.53 359.206 348.954 363.551C346.952 369.068 344.488 374.392 341.773 379.675C339.256 384.573 337.38 389.788 336.189 395.156C335.632 397.662 334.809 400.123 333.987 402.58L333.987 402.582C333.789 403.174 333.591 403.766 333.397 404.358C332.787 406.217 332.115 408.059 331.442 409.901L331.441 409.903C331.344 410.169 331.247 410.436 331.15 410.702L330.991 411.139C330.899 411.392 330.807 411.646 330.716 411.899C330.166 413.426 330.649 414.851 331.991 415.036C333.486 415.243 335.03 415.168 336.711 415.073C338.238 414.883 339.549 414.256 340.411 413.147ZM120.7 360.669C122.359 358.228 124.069 356.019 127.442 355.359C128.694 355.114 128.763 354.53 127.933 353.593C127.751 353.387 127.559 353.182 127.366 352.976C126.672 352.237 125.966 351.483 125.666 350.627C125.343 349.701 125.406 348.655 125.468 347.627L125.468 347.627C125.484 347.362 125.5 347.099 125.509 346.839C125.619 343.734 126.599 341.084 130.037 339.575C131.057 339.127 131.669 338.453 130.646 337.133C128.341 334.158 125.285 332.052 121.917 330.228C120.596 329.513 119.38 329.938 118.855 331.187C118.627 331.729 118.396 332.271 118.166 332.813C117.436 334.526 116.706 336.239 116.059 337.977C115.349 339.884 114.673 341.803 113.997 343.721L113.997 343.722C113.284 345.746 112.57 347.771 111.816 349.784C111.193 351.446 110.645 353.127 110.097 354.808L110.097 354.809C109.106 357.847 108.115 360.887 106.682 363.821C103.382 370.576 100.715 377.562 99.4532 384.903C99.3865 385.291 99.4794 385.957 99.7361 386.074C100.127 386.251 100.793 386.186 101.221 386C101.933 385.689 102.68 385.299 103.179 384.767C104.744 383.096 106.199 381.342 107.697 379.336C108.93 377.572 110.167 375.81 111.404 374.048L111.405 374.048L111.405 374.048L111.405 374.047L111.407 374.045L111.41 374.04L111.415 374.034L111.427 374.016L111.428 374.016L111.428 374.015C114.543 369.58 117.658 365.145 120.7 360.669ZM353.37 418.011L353.365 418.01C350.602 417.408 347.856 416.811 346.255 414.256C345.5 413.051 344.839 413.142 344.076 414.466C343.415 415.614 342.597 416.622 341.292 417.22C340.597 417.539 339.862 417.796 339.125 418.029C335.466 419.189 331.906 419.336 328.698 416.991C327.134 415.847 326.625 415.952 325.404 417.375C323.43 419.677 322.419 422.361 321.412 425.033L321.326 425.262C320.241 428.14 320.83 428.741 324.25 428.741H385.587C385.615 428.741 385.642 428.742 385.669 428.743C385.701 428.744 385.733 428.745 385.766 428.747C385.838 428.751 385.911 428.756 385.984 428.762C386.291 428.785 386.598 428.809 386.842 428.708C387.157 428.579 387.577 427.964 387.524 427.912C387.299 427.692 387.079 427.458 386.858 427.224C386.183 426.507 385.499 425.781 384.632 425.387C382.901 424.601 380.961 424.136 379.062 423.706C372.055 422.119 365.027 420.603 357.689 419.06C357.332 418.97 356.976 418.879 356.619 418.788C355.838 418.588 355.056 418.388 354.269 418.209C354.103 418.172 353.937 418.135 353.77 418.098C353.642 418.07 353.514 418.042 353.386 418.014L353.375 418.012L353.37 418.011ZM474.224 312.786C474.297 313.026 474.618 313.206 474.939 313.386C475.088 313.47 475.236 313.553 475.36 313.642C475.44 313.54 475.541 313.438 475.641 313.337C475.86 313.117 476.079 312.898 476.091 312.669C476.108 312.364 476.131 312.056 476.154 311.748L476.154 311.747C476.243 310.548 476.333 309.335 476.068 308.195C475.551 305.965 474.736 303.772 473.811 301.646C473.58 301.115 473.856 300.862 474.115 300.624C474.303 300.452 474.482 300.287 474.453 300.031C474.619 300.126 474.797 300.214 474.975 300.301C475.381 300.5 475.787 300.7 476.054 300.998C476.29 301.262 476.398 301.612 476.508 301.966C476.573 302.177 476.639 302.389 476.732 302.584C476.862 302.859 476.992 303.134 477.122 303.409L477.122 303.409L477.123 303.41L477.123 303.41L477.123 303.411L477.123 303.411L477.124 303.412L477.124 303.412C477.756 304.751 478.388 306.09 479.119 307.384C479.249 307.614 479.64 307.726 480.03 307.838C480.21 307.889 480.39 307.941 480.545 308.004C480.611 307.873 480.695 307.742 480.778 307.611C480.962 307.325 481.145 307.039 481.142 306.755C481.128 305.465 481.014 304.172 480.843 302.891C480.816 302.689 480.792 302.485 480.768 302.28C480.66 301.356 480.549 300.414 480.151 299.596C478.937 297.104 477.649 294.62 476.102 292.287C475.123 290.811 473.791 289.429 472.313 288.335C471.001 287.364 469.49 286.602 467.985 285.844C467.582 285.641 467.18 285.438 466.783 285.232C464.355 283.972 461.893 282.763 459.426 281.566C459.401 281.554 459.375 281.54 459.348 281.527L459.346 281.525C459.057 281.378 458.716 281.205 458.413 281.797C457.842 282.913 457.236 284.016 456.631 285.118C455.685 286.838 454.74 288.558 453.929 290.327L453.901 290.388L453.874 290.446C453.556 291.122 452.994 292.315 454.715 292.975C456.562 293.683 458.378 294.701 459.835 295.935C464.121 299.568 466.055 304.422 467.975 309.243L468.125 309.621C468.495 310.548 468.759 311.51 469.024 312.471L469.025 312.472L469.025 312.473L469.025 312.474C469.151 312.93 469.276 313.386 469.413 313.838C469.463 314.003 469.521 314.165 469.58 314.328L469.581 314.33C469.608 314.404 469.635 314.479 469.661 314.553C469.751 314.495 469.856 314.441 469.96 314.388C470.186 314.272 470.412 314.157 470.491 313.987C471.301 312.248 471.544 310.5 470.941 308.609C470.462 307.107 470.289 305.517 470.118 303.952L470.103 303.809C470.082 303.618 470.38 303.399 470.678 303.179C470.816 303.078 470.953 302.977 471.06 302.878C471.131 302.963 471.214 303.044 471.297 303.126L471.298 303.126L471.298 303.126L471.298 303.126C471.479 303.304 471.66 303.482 471.724 303.689C471.86 304.128 471.987 304.569 472.116 305.018L472.116 305.019C472.35 305.836 472.592 306.678 472.911 307.577C473.022 308.031 473.129 308.486 473.237 308.941C473.54 310.229 473.844 311.517 474.224 312.786ZM454.676 283.74C454.905 283.247 455.177 282.776 455.45 282.304C456.111 281.16 456.772 280.016 456.809 278.574C456.842 277.255 456.575 276.548 455.385 275.899C454.125 275.211 452.691 274.796 451.57 275.587C449.023 277.384 446.672 279.471 445.31 282.144C444.452 283.827 443.833 285.61 443.216 287.391C443.004 288.002 442.792 288.613 442.571 289.219C442.445 289.564 442.505 289.994 442.587 290.365C443.08 292.589 444.934 293.688 446.998 294.62C448.088 295.112 448.893 294.868 449.382 293.905C449.716 293.248 450.045 292.59 450.378 291.926L450.379 291.923L450.381 291.919C451.075 290.531 451.781 289.118 452.569 287.644C452.692 287.418 452.817 287.194 452.943 286.97C453.04 286.797 453.138 286.623 453.236 286.45C453.742 285.556 454.248 284.662 454.676 283.74ZM95.9605 384.124C97.0976 381.701 98.1775 379.247 99.0885 376.75C99.6976 375.08 100.235 373.389 100.772 371.698L100.772 371.697C101.258 370.166 101.745 368.635 102.285 367.119C103.132 364.739 104.021 362.371 104.91 360.004C105.741 357.791 106.572 355.578 107.369 353.356C108.861 349.195 110.316 345.023 111.771 340.851L111.772 340.851C112.425 338.976 113.079 337.102 113.737 335.228C113.91 334.735 114.085 334.243 114.261 333.75L114.261 333.749L114.262 333.748C114.728 332.439 115.195 331.13 115.613 329.81C115.675 329.613 115.549 329.369 115.423 329.125C115.364 329.012 115.306 328.9 115.266 328.791C115.137 328.868 114.987 328.936 114.838 329.004C114.515 329.151 114.191 329.298 114.073 329.529C112.954 331.72 111.86 333.926 110.895 336.174C110.006 338.243 109.212 340.346 108.419 342.448L108.412 342.467L108.41 342.471L108.409 342.475C108.279 342.818 108.15 343.16 108.02 343.503C107.874 343.889 107.727 344.276 107.58 344.662L107.58 344.663L107.58 344.663L107.576 344.671C106.744 346.861 105.911 349.051 105.169 351.265C104.402 353.557 103.675 355.86 102.948 358.162L102.947 358.164L102.947 358.165C102.415 359.851 101.882 361.537 101.334 363.219C101.133 363.837 100.933 364.455 100.734 365.073C99.8955 367.671 99.0568 370.271 98.0802 372.827C97.472 374.419 96.8291 376 96.1837 377.587L96.1835 377.587L96.1831 377.588C95.2817 379.805 94.3754 382.033 93.5526 384.319C94.7458 385.728 95.2022 385.741 95.9605 384.124ZM365.477 434.009C366.199 433.965 366.922 433.917 367.645 433.869C369.237 433.764 370.83 433.659 372.425 433.589C374.527 433.498 376.631 433.415 378.734 433.333H378.735H378.736H378.736H378.737H378.738H378.739H378.74L378.751 433.333C381.529 433.224 384.307 433.116 387.084 432.985C387.304 432.975 387.512 432.779 387.721 432.584C387.818 432.493 387.915 432.402 388.013 432.329C387.929 432.284 387.846 432.234 387.764 432.184C387.572 432.068 387.381 431.953 387.17 431.888C387.006 431.838 386.818 431.851 386.63 431.863C386.546 431.868 386.463 431.874 386.381 431.874H323.189C323.141 431.874 323.09 431.871 323.038 431.867L323.002 431.864L322.973 431.862L322.956 431.86L322.912 431.855L322.871 431.851C322.63 431.826 322.389 431.801 322.257 431.897C321.803 432.224 321.396 432.642 321.121 433.096C321.064 433.192 321.612 433.768 321.953 433.835C322.892 434.022 323.868 434.138 324.83 434.14C338.326 434.158 351.822 434.152 365.477 434.009ZM456.551 438.4L456.538 438.404C451.703 440.105 446.895 441.796 442.152 443.621C438.912 444.867 435.666 445.059 432.292 444.969C432.005 444.962 431.72 444.904 431.435 444.846C431.128 444.784 430.822 444.723 430.516 444.723C430.268 444.723 430.021 444.845 429.774 444.967C429.663 445.022 429.552 445.077 429.441 445.121C429.499 445.202 429.552 445.288 429.605 445.375C429.722 445.566 429.839 445.757 430.01 445.894C430.497 446.285 431.006 446.685 431.58 446.954C435.953 449.002 438.481 454.595 436.935 458.791C436.177 460.851 435.259 463.039 433.722 464.643C432.473 465.947 430.294 466.807 428.35 467.259C425.28 467.972 422.076 467.994 418.981 466.99C416.275 466.112 414.332 464.487 412.899 462.292C409.418 456.957 410.848 452.329 414.55 448.022C415.036 447.456 415.82 447.1 416.61 446.741C417.051 446.54 417.495 446.339 417.89 446.099C418.17 445.929 418.387 445.677 418.604 445.425C418.703 445.31 418.802 445.194 418.907 445.087C418.733 445.049 418.559 445.003 418.385 444.957C417.986 444.852 417.588 444.747 417.185 444.732C416.907 444.721 416.628 444.785 416.347 444.849L416.347 444.849C416.086 444.909 415.825 444.969 415.564 444.969L405.723 444.975H405.677C383.38 444.987 361.083 444.999 338.787 444.968C333.399 444.96 328.011 444.888 322.623 444.816C319.453 444.774 316.283 444.732 313.112 444.702C310.77 444.681 308.426 444.686 306.083 444.692C305.017 444.695 303.951 444.697 302.885 444.697C302.655 444.697 302.425 444.696 302.196 444.695C301.559 444.691 300.923 444.688 300.287 444.71C300.155 444.715 300.025 444.795 299.896 444.876C299.836 444.914 299.777 444.951 299.717 444.981C299.774 445.017 299.831 445.054 299.888 445.091C300.01 445.17 300.132 445.25 300.26 445.322C300.795 445.619 301.356 445.893 301.916 446.167C303.121 446.756 304.325 447.344 305.271 448.169C311.738 453.814 309.652 464.973 299.976 467.209C292.147 469.018 285.229 466.689 282.906 458.373C281.473 453.247 285.304 447.134 291.097 445.533C291.348 445.463 291.564 445.295 291.781 445.126C291.881 445.047 291.982 444.968 292.086 444.9C292.024 444.87 291.962 444.835 291.9 444.798L291.879 444.786L291.847 444.767C291.82 444.75 291.793 444.734 291.767 444.717C291.538 444.576 291.309 444.435 291.08 444.434C283.443 444.407 276.285 442.42 269.265 440.045C259.835 436.855 250.667 433.134 242.178 428.224L242.016 428.13C240.448 427.225 238.83 426.291 238.276 424.396C237.239 420.851 239.244 418.117 242.944 417.218C246.885 416.261 250.664 417.268 254.385 418.336C260.849 420.19 267.307 422.058 273.766 423.926C277.351 424.962 280.935 425.999 284.521 427.033L284.991 427.169C286.938 427.731 288.885 428.293 290.849 428.805C291.569 428.993 292.345 429.089 293.097 429.091C296.337 429.102 299.577 429.103 302.817 429.105C306.041 429.106 309.265 429.107 312.49 429.118C312.968 429.12 313.789 429.239 313.859 429.455C314.009 429.922 314.008 430.428 314.006 430.934L314.006 431.034C314.006 431.088 314.006 431.142 314.006 431.196C314.006 431.262 314.007 431.328 314.009 431.393C314.01 431.437 314.011 431.48 314.013 431.524C313.966 431.509 313.918 431.49 313.87 431.47C313.766 431.428 313.663 431.386 313.564 431.394C313.199 431.424 312.834 431.464 312.469 431.504C311.927 431.563 311.384 431.623 310.84 431.648C308.951 431.736 307.062 431.814 305.172 431.893C302.645 431.998 300.118 432.103 297.593 432.229C293.125 432.453 288.911 431.327 284.735 430.211L284.697 430.201C281.456 429.334 278.256 428.347 275.055 427.359C273.247 426.801 271.438 426.243 269.622 425.707C267.349 425.036 265.069 424.381 262.79 423.726C260.161 422.97 257.533 422.215 254.914 421.435C254.253 421.238 253.609 420.975 252.966 420.713L252.966 420.713L252.965 420.713L252.965 420.713L252.965 420.713L252.965 420.712L252.964 420.712L252.964 420.712C251.939 420.294 250.918 419.878 249.846 419.735C247.875 419.474 245.765 419.615 243.8 419.962C243.032 420.098 242.172 421.191 241.93 421.987C241.607 423.05 241.826 424.097 243.217 424.888C249.672 428.559 256.476 431.602 263.463 434.363C269.811 436.872 276.364 438.827 283.059 440.422C284.132 440.677 285.294 440.698 286.418 440.717C288.983 440.76 291.548 440.789 294.113 440.817C298.446 440.865 302.779 440.914 307.109 441.032C311.904 441.162 316.696 441.37 321.488 441.579C323.717 441.675 325.945 441.772 328.174 441.861C330.149 441.94 332.125 442.016 334.101 442.093L334.136 442.094H334.136H334.137H334.138H334.138C336.99 442.204 339.842 442.315 342.693 442.433C343.31 442.458 343.927 442.504 344.543 442.55L344.545 442.55L344.546 442.55L344.547 442.55L344.548 442.55C345.636 442.632 346.723 442.712 347.807 442.682C348.756 442.654 349.703 442.537 350.649 442.419L350.65 442.419L350.651 442.419C351.469 442.317 352.288 442.216 353.11 442.172C353.665 442.143 354.226 442.216 354.788 442.29L354.788 442.29C355.244 442.35 355.7 442.411 356.155 442.416L356.388 442.419C356.608 442.421 356.827 442.424 357.047 442.427L357.452 442.433L357.802 442.438C360.327 442.475 362.855 442.511 365.374 442.404C367.547 442.311 369.718 442.157 371.889 442.004H371.889H371.889H371.89H371.89H371.891H371.891H371.892C373.985 441.856 376.079 441.709 378.176 441.615C378.798 441.587 379.427 441.726 380.058 441.865C380.613 441.987 381.17 442.109 381.726 442.119C385.539 442.189 389.356 442.182 393.17 442.135C396.889 442.089 400.609 442.001 404.323 441.843C405.06 441.811 405.8 441.697 406.538 441.583L406.539 441.583L406.539 441.583C407.631 441.414 408.718 441.246 409.777 441.349C414.027 441.761 418.291 441.866 422.55 441.97C425.476 442.042 428.399 442.114 431.315 442.285C436.58 442.595 441.243 441.47 445.86 439.782C452.11 437.497 458.309 435.077 464.391 432.459C468.193 430.822 471.822 428.85 475.436 426.885L475.436 426.885L476.098 426.525C478.402 425.274 480.161 423.508 480.884 421.081C481.248 419.857 480.486 418.921 479.114 418.894C474.86 418.81 470.975 420.131 467.112 421.462C461.494 423.395 455.9 425.385 450.325 427.413C448.074 428.232 445.84 429.09 443.606 429.947L443.605 429.947L443.603 429.948L443.601 429.949L443.599 429.949L443.598 429.95L443.596 429.951L443.594 429.951C441.919 430.594 440.245 431.236 438.562 431.863C437.975 432.082 437.299 432.205 436.663 432.207C431.342 432.226 426.022 432.225 420.701 432.223C419.239 432.223 417.778 432.222 416.316 432.222C414.85 432.222 413.384 432.223 411.918 432.223C407.961 432.224 404.004 432.225 400.048 432.219C398.693 432.216 397.338 432.176 395.983 432.131C395.897 432.128 395.757 431.935 395.748 431.823C395.736 431.667 395.742 431.508 395.749 431.35C395.758 431.127 395.768 430.906 395.724 430.692C395.54 429.784 395.975 429.644 396.912 429.649C403.588 429.689 410.265 429.707 416.941 429.66C417.605 429.655 418.27 429.651 418.935 429.646H418.936C424.587 429.609 430.241 429.572 435.88 429.315C437.669 429.233 439.471 428.537 441.183 427.876L441.183 427.876C441.33 427.819 441.476 427.763 441.621 427.707C451.393 423.957 461.265 420.439 471.438 417.647C473.28 417.141 475.242 416.951 477.186 416.762H477.186L477.537 416.728L477.807 416.702C477.966 416.686 478.125 416.67 478.285 416.653C479.61 416.517 481.014 416.43 482.299 416.674C484.34 417.062 485.186 418.813 484.563 420.644C483.429 423.97 481.162 426.502 477.864 428.298C475.536 429.567 473.201 430.824 470.853 432.088L470.853 432.088L470.852 432.089L470.819 432.106L470.809 432.112L470.78 432.127L470.774 432.131L470.774 432.131C468.587 433.308 466.388 434.492 464.175 435.695C461.64 436.609 459.108 437.5 456.584 438.388L456.551 438.4ZM431.665 451.076C427.949 447.458 423.656 446.793 418.537 449.439C415.578 450.968 414.28 454.565 414.529 456.843C414.796 459.297 416.168 461.332 418.263 462.925C420.775 464.836 423.713 464.84 426.739 464.258C433.46 462.966 435.477 455.158 431.665 451.076ZM286.678 455.43C286.676 455.561 286.673 455.691 286.671 455.821C286.66 456.382 286.648 456.942 286.69 457.499C287.03 462.094 292.992 465.663 298.25 464.311C301.992 463.349 304.15 461.35 304.915 457.84C306.087 452.455 302.349 448.576 297.185 447.908C292.084 447.247 287.887 449.766 286.681 455.046C286.681 455.174 286.68 455.302 286.678 455.43ZM327.429 471.342L339.366 471.342H398.032C400.785 471.342 403.538 471.343 406.291 471.343C419.394 471.345 432.496 471.347 445.599 471.306C446.454 471.303 447.396 470.863 448.1 470.43C448.289 470.314 447.887 469.39 447.496 468.994C447.232 468.725 446.513 468.628 445.998 468.628C404.064 468.617 362.131 468.614 320.198 468.612C303.835 468.611 287.473 468.61 271.11 468.609C270.503 468.608 269.895 468.572 269.287 468.535H269.287H269.286H269.285H269.285H269.284C269.067 468.522 268.851 468.509 268.634 468.498C267.628 468.445 266.324 469.644 266.739 470.331C267.336 471.319 268.56 471.344 269.76 471.344C288.934 471.342 308.108 471.342 327.372 471.342H327.383H327.395H327.406H327.418H327.429ZM222.681 472.046L214.73 472.046H214.717H214.703H214.69H214.677H214.663C203.007 472.046 191.435 472.047 179.864 472.042C179.742 472.042 179.619 472.045 179.495 472.049C178.714 472.072 177.934 472.095 177.622 471.185C177.261 470.13 177.756 469.364 179.071 469.227C179.321 469.201 179.576 469.207 179.83 469.214C179.947 469.218 180.064 469.221 180.181 469.221L192.239 469.221H192.675C213.143 469.221 233.611 469.221 254.079 469.217L254.188 469.217L254.281 469.216C255.347 469.211 256.356 469.206 256.31 470.494C256.273 471.56 255.566 472.046 253.921 472.046C246.057 472.046 238.193 472.046 230.26 472.046H230.237H230.214H230.19H222.681ZM499.232 472.05L507.586 472.05C509.366 472.05 511.14 472.051 512.908 472.051C519.696 472.052 526.404 472.053 533.112 472.039C533.808 472.038 534.515 471.913 535.193 471.772C535.381 471.733 535.568 471.44 535.613 471.243C535.956 469.723 535.404 469.226 533.413 469.226C508.785 469.226 484.157 469.226 459.529 469.226C459.413 469.226 459.296 469.222 459.178 469.217C458.922 469.207 458.666 469.197 458.421 469.234C457.065 469.44 456.58 470.281 457.12 471.301C457.533 472.082 458.298 472.067 459.068 472.052C459.112 472.051 459.157 472.05 459.201 472.049C459.263 472.048 459.325 472.048 459.387 472.048C472.498 472.051 485.608 472.05 498.806 472.05H498.816H498.826H498.837H499.232ZM441.78 94.8796C442.057 94.8543 443.356 95.0352 444.958 95.2582C447.149 95.5632 449.905 95.9469 451.383 95.9895C452.864 96.032 451.459 97.4504 451.214 97.4597C447.947 97.5839 440.866 95.6542 441.78 94.8796ZM446.551 106.068C445.168 105.6 445.829 101.808 447.201 101.808C448.556 101.808 447.902 106.526 446.551 106.068ZM426.618 453.71C427.815 456.138 427.733 457.131 426.309 458.451C425.336 459.353 423.573 459.506 422.468 458.785C421.288 458.015 420.741 456.194 421.31 454.931C422.311 452.71 424.512 452.167 426.618 453.71ZM298.49 453.897C296.631 452.358 294.78 452.444 292.506 454.437C291.678 456.152 292.084 457.969 295.154 458.453C296.807 458.714 297.786 458.277 298.7 457.392C299.65 456.471 299.378 454.633 298.49 453.897Z" fill="#00160A"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M406.338 144.723C403.574 143.997 402.918 140.248 400.13 139.6C397.372 138.96 394.722 141.881 391.972 141.214C390.101 140.76 389.228 138.913 388.193 137.449C387.186 136.024 385.063 134.738 383.548 135.657L383.423 135.739C381.322 137.222 378.169 136.285 376.052 134.819C373.935 133.353 372.14 131.377 369.598 130.623C370.932 129.445 373.244 130.3 374.536 131.515C375.829 132.731 376.88 134.332 378.675 134.818C381.425 135.563 384.523 133.279 387.119 134.381C388.733 135.066 389.389 136.76 390.356 138.104C391.322 139.448 393.425 140.574 394.797 139.551C398.128 137.067 404.079 138.642 405.362 142.346C405.734 143.42 407.379 144.996 406.338 144.723Z" fill="#E7EAEE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M241.47 426.236C249.149 430.282 273.203 442.202 290.836 442.597L436.683 443.008C436.683 443.008 513.372 418.884 457.302 427.986C454.129 428.501 445.04 433.363 430.427 434.423C403.714 436.36 290.836 435.122 290.836 435.122C290.836 435.122 239.45 425.171 241.47 426.236Z" fill="#E7EAEE"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M116.216 345.977C116.395 345.798 116.613 345.671 116.749 345.721C118.284 346.29 119.17 345.796 119.637 344.439C119.714 344.214 120.109 344.075 120.357 343.896C120.585 344.168 121.005 344.44 121.006 344.712C121.009 345.617 121.448 346.042 122.409 346.311C122.819 346.426 123.061 347.013 123.38 347.385C123.059 347.451 122.575 347.427 122.452 347.603C122.201 347.96 122.069 348.419 122.031 348.847C121.999 349.21 122.203 349.585 122.238 349.959C122.285 350.451 122.197 350.811 121.549 350.316C120.256 349.327 119.134 349.698 118.03 350.63C117.762 350.857 117.291 350.893 116.913 351.016C116.982 350.709 117.003 350.385 117.129 350.097C117.787 348.588 117.332 347.292 116.216 345.977Z" fill="#FFB61D"/>
<ellipse cx="433.024" cy="115.344" rx="5.57201" ry="4.984" fill="#FFB61D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M353.298 159.707L353.939 160.591L354.151 160.877C355.494 162.639 357.534 164.371 359.802 163.857C365.84 162.491 372.709 164.876 376.133 169.528C377.825 171.828 381.585 171.377 384.658 170.787L385.063 170.708C388.146 170.097 392.408 170.385 393.187 173.056L393.227 173.21C393.587 174.748 395.752 175.216 397.534 175.176L398.086 175.158C402.567 175.158 403.153 177.362 403.154 177.135C403.154 177.135 393.303 176.467 391.23 173.479L391.103 173.288C389.783 171.22 386.448 171.556 383.84 172.26L383.122 172.46L382.762 172.554C380.216 173.192 377.125 173.423 375.847 171.458C372.915 166.948 366.805 164.268 361.021 164.954C359.532 165.131 357.989 165.505 356.563 165.083C353.153 164.073 352.707 159.363 349.352 158.215C345.119 156.766 341.019 162.27 336.638 161.231C339.303 159.413 342.257 157.934 345.385 156.854C346.433 156.491 347.545 156.169 348.66 156.29C350.726 156.514 352.113 158.102 353.298 159.707ZM407.09 165.141C406.667 166.305 406.356 167.339 406.149 168.216C405.72 165.688 402.91 163.35 400.262 164.168L400.109 164.219C398.428 164.818 396.648 163.575 395.561 162.281L395.3 161.966L394.908 161.485C394.03 160.411 393.084 159.352 391.677 159.047C389.104 158.488 386.834 160.778 384.204 161.052C378.119 161.685 375.077 151.94 369.102 153.149C367.795 153.413 366.665 154.214 365.338 154.376C361.674 154.824 359.709 150.657 356.621 148.837C354.297 147.468 351.018 147.551 348.785 149.035C348.898 146.656 352.516 145.607 354.986 146.502C357.456 147.398 359.151 149.41 361.202 150.932C363.202 152.415 366.169 153.434 368.346 152.227L368.512 152.13C371.131 150.508 374.635 152.565 376.681 154.75L377.424 155.545C379.291 157.533 381.425 159.599 384.224 159.408C386.795 159.233 388.983 157.091 391.533 157.433C395.248 157.933 396.766 163.288 400.501 162.926C402.902 162.693 405.399 163.414 407.194 164.858L407.09 165.141ZM409.019 153.935C408.419 154.687 407.818 155.29 407.215 155.746L407.014 155.893L406.512 155.571C404.069 154.019 401.401 152.509 398.431 152.571C397.346 152.594 396.235 152.828 395.194 152.555C392.43 151.829 391.774 148.08 388.986 147.432C386.228 146.792 383.578 149.713 380.828 149.046C378.957 148.592 378.084 146.745 377.049 145.281C376.042 143.856 373.919 142.57 372.404 143.489L372.279 143.571C370.178 145.054 367.025 144.117 364.908 142.651C362.791 141.185 360.996 139.209 358.454 138.455C359.788 137.277 362.1 138.132 363.392 139.347C364.685 140.563 365.736 142.164 367.531 142.65C370.281 143.395 373.379 141.111 375.975 142.213C377.589 142.898 378.245 144.592 379.212 145.936C380.178 147.28 382.281 148.406 383.654 147.383C386.984 144.899 392.935 146.474 394.218 150.178C394.59 151.252 396.19 151.502 397.425 151.286C398.66 151.07 399.929 150.589 401.129 150.927C402.655 151.357 403.437 152.944 404.907 153.509C406.437 154.096 408.266 153.349 409.289 152.168L409.392 152.044C410.215 151.012 409.83 152.92 409.019 153.935Z" fill="#FFB61D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M376.971 182.183L377.431 182.304C378.049 182.472 378.513 182.721 379.055 183.131L379.323 183.342L379.663 183.619C379.828 183.753 379.957 183.854 380.088 183.95C380.991 184.612 382.013 185.022 383.718 185.264C384.861 185.427 385.667 185.264 387.057 184.685L387.558 184.471C389.804 183.501 391.11 183.231 393.216 183.664C395.015 184.034 395.841 184.657 396.513 185.829L396.683 186.14C397.004 186.74 398.042 187.295 398.86 187.733C399.474 188.061 399.965 188.324 399.94 188.491C399.881 188.88 396.083 188.25 395.328 186.902L395.164 186.6C394.673 185.694 394.225 185.333 392.859 185.052C391.258 184.723 390.287 184.895 388.499 185.647L387.998 185.862C386.184 186.642 385.073 186.899 383.468 186.671C381.484 186.389 380.2 185.873 379.079 185.051C379.001 184.994 378.926 184.937 378.846 184.875L378.18 184.338C377.713 183.966 377.395 183.783 376.966 183.666L376.703 183.595C375.592 183.303 373.049 184.059 371.195 184.609C370.033 184.955 369.142 185.219 369.045 185.095C368.836 184.826 374.757 181.651 376.971 182.183ZM376.699 193.005L377.126 193.111C377.699 193.259 378.13 193.478 378.632 193.838L378.88 194.023L379.196 194.267C379.349 194.384 379.468 194.473 379.59 194.558C380.427 195.139 381.375 195.5 382.956 195.713C384.016 195.855 384.763 195.712 386.053 195.204L386.517 195.015C388.6 194.163 389.811 193.926 391.764 194.307C393.432 194.632 394.199 195.179 394.822 196.209L394.979 196.482C395.277 197.01 396.239 197.497 396.998 197.882L396.998 197.882L396.998 197.882L396.998 197.882C397.567 198.171 398.023 198.401 397.999 198.548C397.945 198.89 394.423 198.337 393.722 197.152L393.57 196.886C393.115 196.09 392.699 195.773 391.433 195.526C389.948 195.237 389.048 195.388 387.39 196.049L386.925 196.238C385.243 196.923 384.213 197.149 382.724 196.949C380.884 196.701 379.694 196.248 378.654 195.526C378.582 195.475 378.512 195.425 378.438 195.371L377.821 194.898C377.387 194.571 377.092 194.411 376.695 194.308L376.45 194.245C375.42 193.989 373.062 194.653 371.343 195.137C370.265 195.44 369.439 195.673 369.349 195.564C369.156 195.328 374.646 192.537 376.699 193.005ZM377.49 204.503L377.086 204.397C375.148 203.929 369.962 206.72 370.145 206.956C370.229 207.065 371.01 206.832 372.028 206.529C373.651 206.045 375.879 205.381 376.852 205.637L377.082 205.7C377.458 205.803 377.736 205.963 378.146 206.29L378.729 206.763C378.799 206.817 378.865 206.867 378.933 206.918C379.915 207.64 381.039 208.093 382.777 208.341C384.183 208.541 385.156 208.315 386.745 207.63L387.183 207.441C388.749 206.78 389.6 206.629 391.002 206.918C392.198 207.165 392.591 207.482 393.02 208.278L393.164 208.544C393.825 209.729 397.152 210.282 397.203 209.94C397.225 209.793 396.795 209.563 396.258 209.274L396.258 209.274C395.541 208.889 394.632 208.402 394.351 207.874L394.202 207.601C393.614 206.571 392.89 206.024 391.314 205.699C389.47 205.318 388.326 205.555 386.359 206.408L385.921 206.596C384.703 207.104 383.997 207.247 382.996 207.105C381.502 206.892 380.607 206.531 379.817 205.95C379.702 205.865 379.589 205.776 379.444 205.659L379.146 205.415L378.912 205.23C378.437 204.87 378.03 204.651 377.49 204.503ZM377.086 217.925L377.49 218.031C378.03 218.179 378.437 218.398 378.912 218.758L379.146 218.943L379.444 219.187C379.589 219.304 379.702 219.393 379.817 219.478C380.607 220.059 381.502 220.42 382.996 220.633C383.997 220.775 384.703 220.632 385.921 220.124L386.359 219.936C388.326 219.083 389.47 218.846 391.314 219.227C392.89 219.552 393.614 220.099 394.202 221.129L394.351 221.402C394.632 221.93 395.541 222.417 396.258 222.802C396.795 223.091 397.225 223.321 397.203 223.468C397.152 223.81 393.825 223.257 393.164 222.072L393.02 221.806C392.591 221.01 392.198 220.693 391.002 220.446C389.6 220.157 388.749 220.308 387.183 220.969L386.745 221.158C385.156 221.843 384.183 222.069 382.777 221.869C381.039 221.621 379.915 221.168 378.933 220.446C378.865 220.395 378.799 220.345 378.729 220.291L378.146 219.818C377.736 219.491 377.458 219.331 377.082 219.228L376.852 219.165C375.879 218.909 373.652 219.573 372.028 220.057L372.028 220.057L372.028 220.057C371.01 220.36 370.229 220.593 370.145 220.484C369.962 220.248 375.148 217.457 377.086 217.925ZM378.718 231.559L378.291 231.453C376.238 230.985 370.748 233.776 370.941 234.012C371.031 234.121 371.857 233.888 372.935 233.585L372.935 233.585L372.935 233.585L372.935 233.585C374.654 233.101 377.012 232.437 378.042 232.693L378.287 232.756C378.684 232.859 378.979 233.019 379.413 233.346L380.03 233.819C380.104 233.873 380.174 233.923 380.246 233.974C381.286 234.696 382.476 235.149 384.316 235.397C385.805 235.597 386.835 235.371 388.517 234.686L388.982 234.497C390.64 233.836 391.54 233.685 393.025 233.974C394.291 234.221 394.707 234.538 395.162 235.334L395.314 235.6C396.015 236.785 399.537 237.338 399.591 236.996C399.615 236.849 399.159 236.619 398.59 236.33C397.831 235.945 396.869 235.458 396.571 234.93L396.414 234.657C395.791 233.627 395.024 233.08 393.356 232.755C391.403 232.374 390.192 232.611 388.109 233.464L387.645 233.652C386.355 234.16 385.608 234.303 384.548 234.161C382.967 233.948 382.019 233.587 381.182 233.006C381.06 232.921 380.941 232.832 380.788 232.715L380.472 232.471L380.224 232.286C379.722 231.926 379.291 231.707 378.718 231.559ZM382.63 243.97L383.071 244.009C383.664 244.066 384.131 244.214 384.696 244.491L384.976 244.635L385.334 244.825C385.508 244.917 385.642 244.986 385.779 245.051C386.716 245.493 387.719 245.701 389.318 245.665C390.39 245.641 391.098 245.384 392.269 244.683L392.69 244.426C394.576 243.263 395.722 242.841 397.719 242.912C399.425 242.973 400.286 243.393 401.1 244.311L401.308 244.556C401.704 245.029 402.746 245.36 403.568 245.621C404.185 245.816 404.678 245.973 404.683 246.121C404.696 246.467 401.12 246.468 400.2 245.41L399.999 245.172C399.396 244.459 398.925 244.211 397.63 244.165C396.112 244.111 395.254 244.399 393.75 245.308L393.329 245.566C391.805 246.502 390.834 246.885 389.33 246.918C387.47 246.96 386.209 246.699 385.045 246.149L384.803 246.03L384.103 245.661C383.612 245.406 383.291 245.294 382.879 245.254L382.626 245.231C381.562 245.139 379.369 246.159 377.77 246.902C376.767 247.368 375.998 247.726 375.889 247.632C375.652 247.429 380.518 243.829 382.63 243.97ZM392.672 253.19L392.318 253.22C390.63 253.397 387.274 256.716 387.488 256.835C387.587 256.89 388.146 256.523 388.875 256.043C390.038 255.279 391.632 254.23 392.486 254.156L392.688 254.14C393.019 254.114 393.288 254.155 393.71 254.279L394.313 254.459L394.521 254.515C395.515 254.768 396.546 254.794 398.01 254.515C399.194 254.289 399.909 253.876 400.986 252.979L401.284 252.731C402.349 251.857 402.987 251.528 404.194 251.366C405.224 251.228 405.63 251.349 406.202 251.798L406.394 251.948C407.264 252.61 410.088 252.133 410.031 251.878C410.007 251.769 409.596 251.718 409.083 251.655C408.398 251.571 407.53 251.465 407.153 251.166L406.955 251.013C406.188 250.44 405.451 250.243 404.095 250.425C402.508 250.638 401.659 251.104 400.327 252.218L400.029 252.465C399.199 253.141 398.674 253.426 397.831 253.587C396.573 253.827 395.752 253.806 394.952 253.602C394.835 253.573 394.719 253.54 394.57 253.495L394.261 253.401L394.02 253.331C393.537 253.201 393.148 253.153 392.672 253.19ZM401.074 259.628L401.428 259.598C401.904 259.561 402.293 259.609 402.776 259.739L403.017 259.809L403.326 259.903C403.475 259.948 403.591 259.981 403.708 260.01C404.508 260.214 405.329 260.235 406.587 259.995C407.43 259.834 407.955 259.549 408.785 258.873L409.083 258.626C410.415 257.512 411.264 257.046 412.851 256.833C414.207 256.651 414.944 256.848 415.711 257.421L415.909 257.574C416.286 257.873 417.154 257.979 417.839 258.063C418.352 258.126 418.763 258.177 418.787 258.286C418.844 258.541 416.02 259.018 415.15 258.356L414.958 258.206C414.386 257.757 413.98 257.636 412.95 257.774C411.743 257.936 411.105 258.265 410.04 259.139L409.742 259.387C408.665 260.284 407.95 260.697 406.766 260.923C405.302 261.202 404.271 261.176 403.277 260.923L403.069 260.867L402.466 260.687C402.044 260.563 401.775 260.522 401.444 260.548L401.242 260.564C400.388 260.638 398.794 261.687 397.631 262.451C396.902 262.931 396.343 263.298 396.244 263.243C396.03 263.124 399.386 259.805 401.074 259.628ZM412.634 266.526L412.356 266.594C411.035 266.948 408.875 270.025 409.065 270.093C409.153 270.125 409.541 269.76 410.049 269.285L410.049 269.285C410.857 268.527 411.967 267.488 412.637 267.321L412.797 267.283C413.057 267.221 413.279 267.219 413.636 267.265L414.146 267.333L414.321 267.352C415.156 267.429 415.984 267.319 417.11 266.912C418.021 266.582 418.528 266.162 419.248 265.308L419.446 265.073C420.16 264.24 420.619 263.897 421.558 263.615C422.359 263.375 422.703 263.42 423.231 263.707L423.408 263.803C424.208 264.222 426.39 263.484 426.305 263.288C426.268 263.204 425.932 263.215 425.511 263.23C424.951 263.249 424.24 263.273 423.892 263.082L423.709 262.984C423.006 262.623 422.386 262.559 421.33 262.875C420.095 263.246 419.49 263.725 418.6 264.783L418.401 265.018C417.844 265.664 417.47 265.958 416.821 266.192C415.853 266.543 415.194 266.63 414.522 266.568C414.424 266.559 414.326 266.547 414.199 266.53L413.938 266.494L413.734 266.469C413.327 266.425 413.009 266.436 412.634 266.526ZM421.203 272.347L421.481 272.278C421.856 272.189 422.174 272.178 422.581 272.221L422.785 272.246L423.047 272.282C423.173 272.3 423.271 272.311 423.369 272.32C424.041 272.382 424.7 272.295 425.668 271.945C426.317 271.71 426.692 271.416 427.249 270.771L427.447 270.536C428.337 269.478 428.942 268.998 430.178 268.628C431.233 268.311 431.853 268.376 432.557 268.737L432.739 268.834C433.087 269.026 433.798 269.001 434.359 268.982C434.779 268.968 435.115 268.956 435.152 269.04C435.238 269.237 433.055 269.975 432.255 269.555L432.078 269.46C431.55 269.173 431.206 269.127 430.405 269.368C429.466 269.649 429.007 269.992 428.293 270.826L428.095 271.061C427.375 271.914 426.869 272.335 425.957 272.664C424.831 273.072 424.003 273.181 423.168 273.104L422.994 273.086L422.483 273.018C422.126 272.972 421.904 272.973 421.644 273.035L421.485 273.074C420.814 273.24 419.705 274.28 418.896 275.038L418.896 275.038C418.389 275.513 418 275.877 417.912 275.846C417.722 275.778 419.882 272.701 421.203 272.347ZM431.829 277.974L431.551 278.043C430.23 278.397 428.07 281.474 428.26 281.542C428.348 281.573 428.737 281.209 429.244 280.734C430.053 279.976 431.162 278.936 431.833 278.77L431.992 278.731C432.252 278.669 432.474 278.668 432.831 278.714L433.341 278.782L433.516 278.8C434.351 278.877 435.179 278.768 436.305 278.36C437.216 278.031 437.723 277.61 438.443 276.757L438.641 276.522C439.355 275.688 439.814 275.345 440.753 275.063C441.554 274.823 441.898 274.869 442.426 275.156L442.603 275.251C443.403 275.671 445.586 274.933 445.5 274.736C445.463 274.652 445.127 274.664 444.707 274.678C444.146 274.697 443.435 274.722 443.087 274.53L442.905 274.433C442.201 274.072 441.581 274.007 440.525 274.324C439.29 274.694 438.685 275.174 437.795 276.232L437.597 276.467C437.04 277.112 436.665 277.406 436.016 277.641C435.048 277.991 434.389 278.078 433.717 278.016C433.619 278.007 433.521 277.996 433.395 277.978L433.133 277.942L432.929 277.917C432.522 277.874 432.204 277.885 431.829 277.974Z" fill="#FFB61D"/>
</svg>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6_1293)">
<path d="M19 10H20C20.2652 10 20.5196 10.1054 20.7071 10.2929C20.8946 10.4804 21 10.7348 21 11V21C21 21.2652 20.8946 21.5196 20.7071 21.7071C20.5196 21.8946 20.2652 22 20 22H4C3.73478 22 3.48043 21.8946 3.29289 21.7071C3.10536 21.5196 3 21.2652 3 21V11C3 10.7348 3.10536 10.4804 3.29289 10.2929C3.48043 10.1054 3.73478 10 4 10H5V9C5 8.08075 5.18106 7.1705 5.53284 6.32122C5.88463 5.47194 6.40024 4.70026 7.05025 4.05025C7.70026 3.40024 8.47194 2.88463 9.32122 2.53284C10.1705 2.18106 11.0807 2 12 2C12.9193 2 13.8295 2.18106 14.6788 2.53284C15.5281 2.88463 16.2997 3.40024 16.9497 4.05025C17.5998 4.70026 18.1154 5.47194 18.4672 6.32122C18.8189 7.1705 19 8.08075 19 9V10ZM5 12V20H19V12H5ZM11 14H13V18H11V14ZM17 10V9C17 7.67392 16.4732 6.40215 15.5355 5.46447C14.5979 4.52678 13.3261 4 12 4C10.6739 4 9.40215 4.52678 8.46447 5.46447C7.52678 6.40215 7 7.67392 7 9V10H17Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_6_1293">
<rect width="24" height="24" fill="white"/>
</clipPath>
</defs>
</svg>
<svg preserveAspectRatio="none" width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.06063 5L9.26562 1.795L9.92656 1.13406C10.0241 1.03656 10.0241 0.878125 9.92656 0.780625L9.21937 0.0734376C9.12187 -0.0240624 8.96344 -0.0240624 8.86594 0.0734376L5 3.93937L1.13406 0.073125C1.03656 -0.024375 0.878125 -0.024375 0.780625 0.073125L0.073125 0.780313C-0.024375 0.877813 -0.024375 1.03625 0.073125 1.13375L3.93937 5L0.073125 8.86594C-0.024375 8.96344 -0.024375 9.12187 0.073125 9.21937L0.780312 9.92656C0.877812 10.0241 1.03625 10.0241 1.13375 9.92656L5 6.06063L8.205 9.26562L8.86594 9.92656C8.96344 10.0241 9.12187 10.0241 9.21937 9.92656L9.92656 9.21937C10.0241 9.12187 10.0241 8.96344 9.92656 8.86594L6.06063 5Z" fill="black" stroke="black" stroke-width="0.03125"/>
</svg>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>LoginPage</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body class="mat-typography">
<app-root></app-root>
</body>
</html>
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
@import 'ngx-toastr/toastr';
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
html, body {
height: 100%;
}
html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
$primary-color: #7001fd;
$text-color: #555555;
$secondary-color: #1e2772;
$gray-bg: #eeeeee;
$gray-secondary-bg: #f1f3f6;
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts"
],
"include": [
"src/**/*.d.ts"
]
}
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"esModuleInterop": true,
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment