Added mobile phone generator and made selecting generators bettter, probably... #8
@@ -1,7 +1,6 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { AppComponent } from './components/app/app.component';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
@@ -14,6 +13,7 @@ import { NipComponent } from './components/nip/nip.component';
|
||||
import { RegonComponent } from './components/regon/regon.component';
|
||||
import { IbanComponent } from './components/iban/iban.component';
|
||||
import { IdentityCardComponent } from './components/identitycard/identitycard.component';
|
||||
import { MobileComponent } from './components/mobile/mobile.component';
|
||||
import {NgOptimizedImage} from "@angular/common";
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
@@ -26,11 +26,11 @@ import { environment } from '../environments/environment';
|
||||
NipComponent,
|
||||
RegonComponent,
|
||||
IbanComponent,
|
||||
IdentityCardComponent
|
||||
IdentityCardComponent,
|
||||
MobileComponent
|
||||
],
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<div class="gradient"></div>
|
||||
<div class="hover-zone"></div>
|
||||
<button class="settings-button" [class.initial-visible]="isInitialVisible" [class.controls-open]="showControls" (click)="showControls = !showControls">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
@if (showControls) {
|
||||
<div class="controls" (mouseenter)="showControls = true">
|
||||
<mat-button-toggle-group multiple>
|
||||
<div class="controls">
|
||||
<mat-button-toggle-group vertical multiple>
|
||||
<mat-button-toggle [checked]="showRegon" (change)="showRegon = $event.source.checked">REGON</mat-button-toggle>
|
||||
<mat-button-toggle [checked]="showNip" (change)="showNip = $event.source.checked">NIP</mat-button-toggle>
|
||||
<mat-button-toggle [checked]="showPesel" (change)="showPesel = $event.source.checked">PESEL</mat-button-toggle>
|
||||
<mat-button-toggle [checked]="showIdentityCard" (change)="showIdentityCard = $event.source.checked">DOWÓD</mat-button-toggle>
|
||||
<mat-button-toggle [checked]="showMobile" (change)="showMobile = $event.source.checked">MOBILNY</mat-button-toggle>
|
||||
<mat-button-toggle [checked]="showIban" (change)="showIban = $event.source.checked">IBAN</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</div>
|
||||
@@ -24,6 +27,9 @@
|
||||
@if (showIdentityCard) {
|
||||
<app-identity-card></app-identity-card>
|
||||
}
|
||||
@if (showMobile) {
|
||||
<app-mobile></app-mobile>
|
||||
}
|
||||
@if (showIban) {
|
||||
<app-iban></app-iban>
|
||||
}
|
||||
|
||||
@@ -1,22 +1,55 @@
|
||||
.hover-zone {
|
||||
.settings-button {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 10px;
|
||||
z-index: 9;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
z-index: 11;
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 50%;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 16px 0 rgba(0, 38, 135, 0.2);
|
||||
transition: background-color 0.3s, transform 0.3s, opacity 0.5s ease-in-out;
|
||||
padding: 0;
|
||||
opacity: 0;
|
||||
|
||||
&.initial-visible, &:hover, &.controls-open {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.3);
|
||||
transform: rotate(30deg);
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
font-size: 24px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 1em;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 60px;
|
||||
right: 10px;
|
||||
z-index: 10;
|
||||
animation: slideIn 300ms ease-out forwards;
|
||||
pointer-events: none;
|
||||
|
||||
& > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
mat-button-toggle-group {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
@@ -25,16 +58,19 @@
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 16px 0 rgba(0, 38, 135, 0.2);
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
mat-button-toggle {
|
||||
color: white;
|
||||
font-family: 'Comfortaa', sans-serif;
|
||||
border-left: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
background-color: rgba(26, 35, 126, 0.4);
|
||||
|
||||
&:first-child {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2) !important;
|
||||
border-left: none !important;
|
||||
background-color: rgba(51, 98, 188, 0.4);
|
||||
width: 100%;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
&.mat-button-toggle-checked {
|
||||
@@ -49,7 +85,7 @@
|
||||
}
|
||||
|
||||
.generators {
|
||||
padding-top: 2em;
|
||||
padding-top: 10px;
|
||||
|
||||
& > * {
|
||||
display: block;
|
||||
@@ -59,7 +95,7 @@
|
||||
|
||||
@keyframes slideIn {
|
||||
from {
|
||||
transform: translateY(-100%);
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, HostListener } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, ElementRef, HostListener, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
@@ -13,23 +13,29 @@ export class AppComponent implements OnInit {
|
||||
showPesel = true;
|
||||
showIdentityCard = true;
|
||||
showIban = true;
|
||||
showMobile = true;
|
||||
|
||||
showControls = false;
|
||||
isInitialVisible = true;
|
||||
|
||||
constructor() {
|
||||
constructor(private cdr: ChangeDetectorRef, private eRef: ElementRef) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
setTimeout(() => {
|
||||
this.isInitialVisible = false;
|
||||
this.cdr.detectChanges();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
@HostListener('window:mousemove', ['$event'])
|
||||
onMouseMove(event: MouseEvent) {
|
||||
// Show if mouse is in the top 20px (hover zone)
|
||||
if (event.clientY < 20) {
|
||||
this.showControls = true;
|
||||
}
|
||||
// Hide if mouse moves below 120px
|
||||
else if (event.clientY > 120) {
|
||||
@HostListener('document:click', ['$event'])
|
||||
clickout(event: Event) {
|
||||
const settingsButton = this.eRef.nativeElement.querySelector('.settings-button');
|
||||
const controls = this.eRef.nativeElement.querySelector('.controls');
|
||||
|
||||
if (this.showControls &&
|
||||
settingsButton && !settingsButton.contains(event.target) &&
|
||||
controls && !controls.contains(event.target)) {
|
||||
this.showControls = false;
|
||||
}
|
||||
}
|
||||
|
||||
19
src/app/components/mobile/mobile.component.html
Normal file
19
src/app/components/mobile/mobile.component.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<div class="generator">
|
||||
<div class="title">
|
||||
<span>KOMÓRKA</span>
|
||||
<div class="titleButtons">
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<input type="text" [formControl]="valueField" />
|
||||
|
||||
<div class="buttons">
|
||||
<img id="mobileGenerateButton" ngSrc="assets/autorenew_black_24dp.svg" title="Generuj numer telefonu" alt="Generuj numer telefonu" style="margin-left: 1em;" (click)="generate()"
|
||||
height="24" width="24"/>
|
||||
<img id="mobileCopyButton" ngSrc="assets/content_copy_black_24dp.svg" title="Skopiuj numer telefonu do schowka" alt="Skopiuj numer telefonu do schowka" style="margin: auto 1em;" (click)="copyToClipboard()"
|
||||
height="24" width="24"/>
|
||||
<img id="mobileHelpButton" ngSrc="assets/info_black_24dp.svg" title="Szczegóły dotyczące numeracji w Polsce" alt="Definicja numerów w Polsce na Wikipedii" (click)="navigateToDocs()"
|
||||
height="24" width="24"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
0
src/app/components/mobile/mobile.component.scss
Normal file
0
src/app/components/mobile/mobile.component.scss
Normal file
35
src/app/components/mobile/mobile.component.ts
Normal file
35
src/app/components/mobile/mobile.component.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { AbstractControl, FormControl } from '@angular/forms';
|
||||
import { MobileService } from 'src/app/service/mobile.service';
|
||||
import { ClipboardService } from 'src/app/service/gui/clipboard.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-mobile',
|
||||
templateUrl: './mobile.component.html',
|
||||
styleUrls: ['./mobile.component.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class MobileComponent implements OnInit {
|
||||
public valueField: FormControl;
|
||||
|
||||
constructor(private mobileService: MobileService, private clipboardService: ClipboardService) {
|
||||
this.valueField = new FormControl('');
|
||||
this.valueField.setValidators([(control: AbstractControl) => this.mobileService.validateMobile(control.value)]);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.generate();
|
||||
}
|
||||
|
||||
generate(): void {
|
||||
this.valueField.setValue(this.mobileService.generateMobile());
|
||||
}
|
||||
|
||||
copyToClipboard(): void {
|
||||
this.clipboardService.copyToClipboard(this.valueField.value);
|
||||
}
|
||||
|
||||
navigateToDocs(): void {
|
||||
window.open('https://pl.wikipedia.org/wiki/Numery_telefonu_w_Polsce', "_blank");
|
||||
}
|
||||
}
|
||||
63
src/app/service/mobile.service.ts
Normal file
63
src/app/service/mobile.service.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CommonService } from './common.service';
|
||||
import { ValidationErrors } from '@angular/forms';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'any'
|
||||
})
|
||||
export class MobileService {
|
||||
|
||||
private static readonly mobilePrefixes: string[] = [
|
||||
'450', '451', '452', '453', '454', '455', '456', '457', '458', '459',
|
||||
'500', '501', '502', '503', '504', '505', '506', '507', '508', '509',
|
||||
'510', '511', '512', '513', '514', '515', '516', '517', '518', '519',
|
||||
'530', '531', '532', '533', '534', '535', '536', '537', '538', '539',
|
||||
'570', '571', '572', '573', '574', '575', '576', '577', '578', '579',
|
||||
'600', '601', '602', '603', '604', '605', '606', '607', '608', '609',
|
||||
'660', '661', '662', '663', '664', '665', '666', '667', '668', '669',
|
||||
'690', '691', '692', '693', '694', '695', '696', '697', '698', '699',
|
||||
'720', '721', '722', '723', '724', '725', '726', '727', '728', '729',
|
||||
'730', '731', '732', '733', '734', '735', '736', '737', '738', '739',
|
||||
'780', '781', '782', '783', '784', '785', '786', '787', '788', '789',
|
||||
'790', '791', '792', '793', '794', '795', '796', '797', '798', '799',
|
||||
'880', '881', '882', '883', '884', '885', '886', '887', '888', '889'
|
||||
];
|
||||
|
||||
constructor(private common: CommonService) { }
|
||||
|
||||
public generateMobile(): string {
|
||||
const prefixIndex = this.common.getRandomInt(0, MobileService.mobilePrefixes.length - 1);
|
||||
const prefix = MobileService.mobilePrefixes[prefixIndex];
|
||||
const rest = this.common.getRandomInt(0, 999999);
|
||||
return prefix + this.common.pad(rest, 6);
|
||||
}
|
||||
|
||||
public validateMobile(mobile: string): ValidationErrors | null {
|
||||
const errors: ValidationErrors = {};
|
||||
|
||||
if (!mobile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mobile.length < 9) {
|
||||
errors.tooShort = true;
|
||||
}
|
||||
|
||||
if (mobile.length > 9) {
|
||||
errors.tooLong = true;
|
||||
}
|
||||
|
||||
if (!CommonService.numericRegExp.test(mobile)) {
|
||||
errors.invalidPattern = true;
|
||||
}
|
||||
|
||||
if (mobile.length >= 3) {
|
||||
const prefix = mobile.substring(0, 3);
|
||||
if (!MobileService.mobilePrefixes.includes(prefix)) {
|
||||
errors.invalidPrefix = true;
|
||||
}
|
||||
}
|
||||
|
||||
return Object.keys(errors).length > 0 ? errors : null;
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -37,7 +36,7 @@ body {
|
||||
}
|
||||
|
||||
.generator {
|
||||
margin: 0 1em 2em 1em;
|
||||
margin: 1em;
|
||||
background: rgba( 255, 255, 255, 0.15 );
|
||||
box-shadow: 0 8px 32px 0 rgba( 0, 38, 135, 0.37 );
|
||||
border-radius: 3px;
|
||||
|
||||
Reference in New Issue
Block a user