Compare commits

14 Commits

Author SHA1 Message Date
5e11c83213 Add Chart.js 2021-02-02 11:56:14 +01:00
Felix
2aae141844 + Added Dashboard Navbar
+ Added Transitions
+ Added Shadows
+ Added LogIn Page
2021-02-02 10:59:22 +01:00
967ab2498d Merge branch 'dashboard' of https://nicolasklier.de:3000/LibrePay/Frontend into dashboard 2021-02-01 13:19:33 +01:00
Felix
a3e3eb983b add SVG Images to HeaderBar 2021-02-01 13:17:05 +01:00
Felix
8cc0d96abf add component "dashboard" 2021-02-01 13:17:03 +01:00
Felix
02f1727358 add login with dummy Data
add login page
add subcomponents
2021-02-01 13:15:43 +01:00
Felix
695dbf9d34 add login subcomponent 2021-02-01 13:14:48 +01:00
Felix
b409c3c670 merge master 2021-02-01 13:14:47 +01:00
Felix
c2ef9fe16d add SVG Images to HeaderBar 2021-01-06 19:12:19 +01:00
Felix
95b9a388c1 Merge branch 'dashboard' of https://nicolasklier.de:3000/LibrePay/Frontend into dashboard 2021-01-03 18:57:43 +01:00
Felix
976e3aa797 add login with dummy Data
add login page
add subcomponents
2021-01-03 18:55:26 +01:00
Felix
41d5f95810 add login subcomponent 2021-01-03 12:57:43 +01:00
Felix
c6e798716f merge master 2021-01-03 12:54:22 +01:00
Felix
fe2cc875f0 add component "dashboard" 2021-01-03 12:42:34 +01:00
33 changed files with 624 additions and 7 deletions

54
package-lock.json generated
View File

@@ -1552,6 +1552,14 @@
"semver-intersect": "1.4.0"
}
},
"@types/chart.js": {
"version": "2.9.30",
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.30.tgz",
"integrity": "sha512-EgjxUUZFvf6ls3kW2CwyrnSJhgyKxgwrlp/W5G9wqyPEO9iFatO63zAA7L24YqgMxiDjQ+tG7ODU+2yWH91lPg==",
"requires": {
"moment": "^2.10.2"
}
},
"@types/glob": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz",
@@ -2817,6 +2825,32 @@
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
"chart.js": {
"version": "2.9.4",
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-2.9.4.tgz",
"integrity": "sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==",
"requires": {
"chartjs-color": "^2.1.0",
"moment": "^2.10.2"
}
},
"chartjs-color": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/chartjs-color/-/chartjs-color-2.4.1.tgz",
"integrity": "sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==",
"requires": {
"chartjs-color-string": "^0.6.0",
"color-convert": "^1.9.3"
}
},
"chartjs-color-string": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz",
"integrity": "sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==",
"requires": {
"color-name": "^1.0.0"
}
},
"chokidar": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
@@ -6913,6 +6947,11 @@
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true
},
"lodash-es": {
"version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.20.tgz",
"integrity": "sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA=="
},
"lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@@ -7432,6 +7471,11 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -7535,6 +7579,16 @@
"tslib": "^2.0.0"
}
},
"ng2-charts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/ng2-charts/-/ng2-charts-2.4.2.tgz",
"integrity": "sha512-mY3C2uKCaApHCQizS2YxEOqQ7sSZZLxdV6N1uM9u/VvUgVtYvlPtdcXbKpN52ak93ZE22I73DiLWVDnDNG4/AQ==",
"requires": {
"@types/chart.js": "^2.9.24",
"lodash-es": "^4.17.15",
"tslib": "^2.0.0"
}
},
"ngx-clipboard": {
"version": "14.0.1",
"resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-14.0.1.tgz",

View File

@@ -20,7 +20,9 @@
"@angular/platform-browser-dynamic": "~11.0.5",
"@angular/router": "~11.0.5",
"angularx-qrcode": "^10.0.11",
"chart.js": "^2.9.4",
"ng-push-ivy": "^1.0.7",
"ng2-charts": "^2.4.2",
"ngx-clipboard": "^14.0.1",
"ngx-socket-io": "^3.2.0",
"rxjs": "~6.6.0",

View File

@@ -6,7 +6,6 @@ import { HeaderComponent } from './header/header.component';
import { PaymentComponent } from './payment/payment.component';
import { QRCodeModule } from 'angularx-qrcode';
import { PayComponent } from './pay/pay.component';
import { RouterModule } from '@angular/router';
import { HelloComponent } from './hello/hello.component';
import { SocketIoConfig, SocketIoModule } from 'ngx-socket-io';
import { HttpClientModule } from '@angular/common/http';
@@ -15,6 +14,13 @@ import { NotFoundComponent } from './not-found/not-found.component';
import { CartComponent } from './cart/cart.component';
import { PushNotificationsModule } from 'ng-push-ivy';
import { ClipboardModule } from 'ngx-clipboard';
import { DashboardComponent } from './dashboard/dashboard.component';
import { LoginComponent } from './dashboard/login/login.component';
import { FormsModule } from '@angular/forms';
import { OverviewComponent } from './dashboard/overview/overview.component';
import { DashboardHeaderComponent } from './dashboard/header/header.component';
import { ChartComponent } from './dashboard/chart/chart.component';
import { ChartsModule } from 'ng2-charts';
const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} };
@@ -26,7 +32,12 @@ const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} };
PayComponent,
HelloComponent,
NotFoundComponent,
CartComponent
CartComponent,
DashboardComponent,
LoginComponent,
OverviewComponent,
DashboardHeaderComponent,
ChartComponent
],
imports: [
BrowserModule,
@@ -35,7 +46,10 @@ const config: SocketIoConfig = { url: 'http://localhost:2009', options: {} };
AppRoutingModule,
SocketIoModule.forRoot(config),
PushNotificationsModule,
ClipboardModule
ClipboardModule,
FormsModule,
SocketIoModule.forRoot(config),
ChartsModule
],
providers: [],
bootstrap: [AppComponent]

View File

@@ -65,7 +65,7 @@ export interface IInvoice {
})
export class BackendService {
SERVER_URL = 'http://192.168.178.26:2009';
SERVER_URL = 'http://localhost:2009';
// Fill with empty data
invoice: IInvoice = {
@@ -107,7 +107,7 @@ export class BackendService {
/**
* Subscribe to the real-time status of the selected invoice.
*/
subscribeTo(selector: string): void {
subscribeTo(): void {
this.socket.on('subscribe', (status: boolean) => {
if (status) {
this.updateInvoice();
@@ -120,7 +120,7 @@ export class BackendService {
this.confirmations = update.count;
});
this.socket.emit('subscribe', { selector });
this.socket.emit('subscribe', { selector: this.invoice.selector });
}
/**
@@ -137,6 +137,8 @@ export class BackendService {
*/
setInvoice(selector: string): Promise<IInvoice> {
return new Promise(async (resolve, reject) => {
console.log('Sel.:', selector);
if (selector === undefined || selector === 'undefined' || selector === '') {
reject('There is no selector. Please set one before calling setInvoice(...)');
return;

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { DashboardService } from './dashboard.service';
describe('DashboardService', () => {
let service: DashboardService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DashboardService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,28 @@
import { Injectable } from '@angular/core';
export interface IUser {
username: string;
token: string;
}
@Injectable({
providedIn: 'root'
})
export class DashboardService {
user: IUser | undefined;
constructor() { }
login(username: string, password: string): boolean {
if (username === 'admin' && password === 'password') {
this.user = {
username: 'admin',
token: 'abc'
}
return true;
} else {
return false;
}
}
}

View File

@@ -0,0 +1,2 @@
<script src="node_modules/chart.js/src/chart.js"></script>
<h1>Test</h1>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ChartComponent } from './chart.component';
describe('ChartComponent', () => {
let component: ChartComponent;
let fixture: ComponentFixture<ChartComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ChartComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ChartComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-chart',
templateUrl: './chart.component.html',
styleUrls: ['./chart.component.css']
})
export class ChartComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@@ -0,0 +1,8 @@
.bg {
position: fixed;
background-color: #1D1D28;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
}

View File

@@ -0,0 +1,4 @@
<dashboard-header></dashboard-header>
<dashboard-chart></dashboard-chart>
<div class="bg"></div>
<router-outlet></router-outlet>

View File

@@ -0,0 +1,25 @@
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({
declarations: [ DashboardComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,16 @@
import { Component, OnInit } from '@angular/core';
import { DashboardService } from '../dashboard.service';
@Component({
selector: 'app-dashboard',
templateUrl: './dashboard.component.html',
styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
constructor(public dashboard: DashboardService) { }
ngOnInit(): void {
}
}

View File

@@ -0,0 +1,66 @@
.header {
position: fixed;
top: 1rem;
left: 5vw;
width: 90vw;
height: 100%;
max-height: 35px;
padding: 15px;
margin: 0 auto;
background-color: #27293D;
z-index: 999;
border-radius: 8px;
transition: .2s ease;
box-shadow: 0 1.1px 12.5px -23px rgba(0, 0, 0, 0.014), 0 2.4px 23.6px -23px rgba(0, 0, 0, 0.027), 0 4.1px 33.4px -23px rgba(0, 0, 0, 0.038), 0 6.2px 42.1px -23px rgba(0, 0, 0, 0.045), 0 8.9px 49.9px -23px rgba(0, 0, 0, 0.05), 0 12.6px 57.5px -23px rgba(0, 0, 0, 0.054), 0 17.8px 65.8px -23px rgba(0, 0, 0, 0.058), 0 25.9px 76.9px -23px rgba(0, 0, 0, 0.062), 0 39.9px 96.3px -23px rgba(0, 0, 0, 0.066), 0 71px 148px -23px rgba(0, 0, 0, 0.07);
}
.header:hover {
max-height: 55px;
transition: .2s ease;
}
.icon::after {
content: ' ';
opacity: 0;
}
.header:hover .icon::after {
content: "Test";
color: white;
opacity: 1;
transition: .2s ease;
transition: .5s opacity ease;
}
.icon:hover {
transform: translateY(-5px);
}
.grid-container {
display: grid;
grid-template-columns: 32px 32px 1fr 32px 32px;
grid-template-rows: 1fr;
gap: 20px 30px;
grid-template-areas: "dashboard history . settings admin";
}
.dashboard {
grid-area: dashboard;
}
.history {
grid-area: history;
}
.settings {
grid-area: settings;
}
.admin {
grid-area: admin;
}
.icon {
grid-row: 1;
transition: .2s ease;
}

View File

@@ -0,0 +1,18 @@
<div class="header" *ngIf="this.dashboard.user != undefined">
<div class="grid-container">
<div class="dashboard icon">
<img src="assets/dashboard.svg" class="dash-svg">
</div>
<div class="history icon">
<img src="assets/history.svg" class="history-svg">
</div>
<div class="settings icon">
<img src="assets/settings.svg" class="settings-svg">
</div>
<div class="admin icon">
<img src="assets/admin.svg" class="admin-svg">
</div>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
let component: HeaderComponent;
let fixture: ComponentFixture<HeaderComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ HeaderComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,20 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { DashboardService } from 'src/app/dashboard.service';
@Component({
selector: 'dashboard-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.css']
})
export class DashboardHeaderComponent implements OnInit {
constructor(
public dashboard: DashboardService,
public router: Router
) { }
ngOnInit(): void {
}
}

View File

@@ -0,0 +1,133 @@
.frame {
background-color: #1D1D28;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
font-family: 'Inter', sans-serif;
}
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400&display=swap');
.btn {
display: inline-block;
*display: inline;
*zoom: 1;
padding: 4px 10px 4px;
margin-bottom: 0;
font-size: 13px;
line-height: 18px;
color: #333333;
text-align: center;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
vertical-align: middle;
background-color: #f5f5f5;
background-repeat: repeat-x;
border-color: #e6e6e6 #e6e6e6 #e6e6e6;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border: 1px solid #e6e6e6;
border-radius: 4px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
cursor: pointer;
*margin-left: .3em;
}
.btn:hover,
.btn:active,
.btn.active,
.btn.disabled,
.btn[disabled] {
background-color: #e6e6e6;
}
.btn-large {
padding: 9px 14px;
font-size: 15px;
line-height: normal;
border-radius: 5px;
}
.btn:hover {
color: #333333;
text-decoration: none;
background-color: #e6e6e6;
background-position: 0 -15px;
transition: background-position 0.1s linear;
transition: ease 0.5;
}
.btn-primary,
.btn-primary:hover {
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
color: #ffffff;
}
.btn-primary.active {
color: rgba(255, 255, 255, 0.75);
}
.btn-primary {
background-color: #1D1D28;
background-image: linear-gradient(top, #6eb6de, #4a77d4);
background-repeat: repeat-x;
border: 1px solid #3762bc;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.4);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5);
transition: ease;
}
.btn-primary:hover,
.btn-primary:active,
.btn-primary.active,
.btn-primary.disabled,
.btn-primary[disabled] {
filter: none;
background-color: #4a77d4;
}
.btn-block {
width: 100%;
display: block;
}
* {
box-sizing: border-box;
}
.login {
position: absolute;
top: 50%;
left: 50%;
margin: -150px 0 0 -150px;
width: 300px;
height: 300px;
}
.login h1 {
color: #fff;
text-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
letter-spacing: 1px;
text-align: center;
font-weight: 200;
}
input {
width: 100%;
margin-bottom: 10px;
background: #1D1D28;
border: none;
outline: none;
padding: 10px;
font-size: 13px;
color: #fff;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
border: 1px solid rgb(138, 138, 138);
border-radius: 4px;
box-shadow: inset 0 -5px 45px rgba(100, 100, 100, 0), 0 1px 1px rgba(255, 255, 255, 0.2);
transition: box-shadow .5s ease;
}
input:focus {
box-shadow: inset 0 -5px 45px rgba(100, 100, 100, 0.4), 0 1px 1px rgba(255, 255, 255, 0.2);
}

View File

@@ -0,0 +1,10 @@
<div class="frame">
<div class="login">
<h1>Login</h1>
<form (submit)="login()">
<input type="text" placeholder="Username" required="required" [(ngModel)]="username" [ngModelOptions]="{standalone: true}" />
<input type="password" placeholder="Password" required="required" [(ngModel)]="password" [ngModelOptions]="{standalone: true}" />
<button type="submit" value="login" id="login-form-submit" onclick="return check(this.form)" class="btn btn-primary btn-block btn-large">Login</button>
</form>
</div>
</div>

View File

@@ -0,0 +1,25 @@
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({
declarations: [ LoginComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,41 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { DashboardService } from 'src/app/dashboard.service';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
username = '';
password = '';
constructor(
public dashboard: DashboardService,
private router: Router
) { }
ngOnInit(): void {
const loginStatus = this.dashboard.login("admin", "password");
if (loginStatus) {
this.router.navigate(['dashboard', 'overview']);
} else {
// TODO: Meldung anzeigen
}
}
login() {
const loginStatus = this.dashboard.login(this.username, this.password);
if (loginStatus) {
this.router.navigate(['dashboard', 'overview']);
} else {
// TODO: Meldung anzeigen
}
}
}

View File

@@ -0,0 +1 @@
<p>overview works!</p>

View File

@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { OverviewComponent } from './overview.component';
describe('OverviewComponent', () => {
let component: OverviewComponent;
let fixture: ComponentFixture<OverviewComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ OverviewComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(OverviewComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,19 @@
import { Component, OnInit } from '@angular/core';
import { DashboardService } from 'src/app/dashboard.service';
@Component({
selector: 'app-overview',
templateUrl: './overview.component.html',
styleUrls: ['./overview.component.css']
})
export class OverviewComponent implements OnInit {
constructor(private dashboard: DashboardService) { }
ngOnInit(): void {
if (this.dashboard.user === undefined) {
this.dashboard.login('admin', 'password');
}
}
}

View File

@@ -39,7 +39,6 @@ export class PaymentComponent implements OnInit {
ngOnInit(): void {
this.route.params.subscribe(params => {
this.paymentSelector = params.id;
this.backend.subscribeTo(this.paymentSelector);
this.get();
});
@@ -126,7 +125,10 @@ export class PaymentComponent implements OnInit {
}
async get(): Promise<void> {
console.log('Selector:', this.paymentSelector);
const res = await this.backend.setInvoice(this.paymentSelector);
this.backend.subscribeTo();
this.status = this.backend.getStatus();
this.backend.getConfirmation().catch();
this.ready = true;

1
src/assets/admin.svg Normal file
View File

@@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="32" height="32" viewBox="0 0 24 24"><path d="M12,19.2C9.5,19.2 7.29,17.92 6,16C6.03,14 10,12.9 12,12.9C14,12.9 17.97,14 18,16C16.71,17.92 14.5,19.2 12,19.2M12,5A3,3 0 0,1 15,8A3,3 0 0,1 12,11A3,3 0 0,1 9,8A3,3 0 0,1 12,5M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z" fill="#fff" fill-rule="evenodd" /></svg>

After

Width:  |  Height:  |  Size: 581 B

1
src/assets/dash.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);"><path d="M21 16V4H3v12h18m0-14a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-7v2h2v2H8v-2h2v-2H3a2 2 0 0 1-2-2V4c0-1.11.89-2 2-2h18M5 6h9v5H5V6m10 0h4v2h-4V6m4 3v5h-4V9h4M5 12h4v2H5v-2m5 0h4v2h-4v-2z" fill="white"/><rect x="0" y="0" width="24" height="24" fill="rgba(0, 0, 0, 0)" /></svg>

After

Width:  |  Height:  |  Size: 537 B

3
src/assets/dashboard.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 16 16">
<path fill="#fff" fill-rule="evenodd" d="M13.5,2.13413878 C13.9783,2.41028878 14.1422,3.02187878 13.866,3.50016878 L12.6872,5.54193878 C12.6693,5.57941878 12.6488,5.61619878 12.6258,5.65205878 L12.6093,5.67680878 L9.62879,10.8392688 C9.8625,11.1665688 10,11.5673688 10,12.0001688 C10,13.1047688 9.10457,14.0001688 8,14.0001688 C6.89543,14.0001688 6,13.1047688 6,12.0001688 C6,10.9637688 6.78831,10.1114688 7.79803,10.0102688 L10.4011,5.50156878 C9.71258,5.20089878 8.97101,5.03106878 8.21451,5.00400878 C7.13787,4.96548878 6.07072,5.21756878 5.12511,5.73376878 C4.1795,6.24996878 3.39032,7.01124878 2.84044,7.93766878 C2.29055,8.86409878 2.00024,9.92148878 2,10.9987688 C1.99988,11.5510688 1.55206,11.9986688 0.999774,11.9985688 C0.44749,11.9984688 0,11.5506688 0,10.9983688 C0.000324182,9.56192878 0.387399,8.15206878 1.12058,6.91683878 C1.85376,5.68160878 2.906,4.66656878 4.16681,3.97829878 C5.42763,3.29002878 6.85049,2.95392878 8.28601,3.00528878 C9.36996,3.04405878 10.4309,3.30266878 11.4058,3.76135878 L12.134,2.50016878 C12.4101,2.02187878 13.0217,1.85799878 13.5,2.13413878 Z M13.4873,6.54043878 C13.9608,6.25621878 14.5751,6.40969878 14.8593,6.88323878 C15.6057,8.12678878 16,9.54983878 16,11.0001688 C16,11.5524688 15.5523,12.0001688 15,12.0001688 C14.4477,12.0001688 14,11.5524688 14,11.0001688 C14,9.91241878 13.7043,8.84512878 13.1445,7.91246878 C12.8603,7.43892878 13.0138,6.82464878 13.4873,6.54043878 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

1
src/assets/history.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24" style="-ms-transform: rotate(360deg); -webkit-transform: rotate(360deg); transform: rotate(360deg);"><path d="M13.5 8H12v5l4.28 2.54l.72-1.21l-3.5-2.08V8M13 3a9 9 0 0 0-9 9H1l3.96 4.03L9 12H6a7 7 0 0 1 7-7a7 7 0 0 1 7 7a7 7 0 0 1-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42A8.896 8.896 0 0 0 13 21a9 9 0 0 0 9-9a9 9 0 0 0-9-9" fill="#fff" fill-rule="evenodd"/><rect x="0" y="0" width="32" height="32" fill="rgba(0, 0, 0, 0)" /></svg>

After

Width:  |  Height:  |  Size: 593 B

4
src/assets/settings.svg Normal file
View File

@@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="M7.99994 6C6.89537 6 5.99994 6.89543 5.99994 8C5.99994 9.10457 6.89537 10 7.99994 10C9.10451 10 9.99994 9.10457 9.99994 8C9.99994 6.89543 9.10451 6 7.99994 6ZM6.99994 8C6.99994 7.44772 7.44765 7 7.99994 7C8.55222 7 8.99994 7.44772 8.99994 8C8.99994 8.55228 8.55222 9 7.99994 9C7.44765 9 6.99994 8.55228 6.99994 8Z" fill="#fff"/>
<path d="M10.618 4.39833C10.233 4.46825 9.86392 4.21413 9.7937 3.83074L9.53397 2.41496C9.50816 2.27427 9.39961 2.16301 9.25912 2.13325C8.84818 2.04621 8.42685 2.00195 8 2.00195C7.57289 2.00195 7.1513 2.04627 6.74013 2.13341C6.5996 2.1632 6.49104 2.27452 6.46529 2.41527L6.20629 3.8308C6.1994 3.86844 6.18942 3.90551 6.17647 3.9416C6.04476 4.30859 5.6392 4.49978 5.27062 4.36863L3.91115 3.88463C3.77603 3.83652 3.62511 3.87431 3.52891 3.98033C2.96005 4.60729 2.52892 5.34708 2.2672 6.15302C2.22305 6.28899 2.26562 6.43805 2.37502 6.53053L3.47694 7.46206C3.50626 7.48685 3.53352 7.51399 3.55843 7.5432C3.81177 7.84027 3.77528 8.28558 3.47693 8.53783L2.37502 9.46935C2.26562 9.56183 2.22305 9.71089 2.2672 9.84685C2.52892 10.6528 2.96005 11.3926 3.52891 12.0196C3.62511 12.1256 3.77603 12.1634 3.91115 12.1153L5.27068 11.6312C5.30687 11.6184 5.3441 11.6084 5.38196 11.6015C5.76701 11.5316 6.13608 11.7857 6.2063 12.1691L6.46529 13.5846C6.49104 13.7254 6.5996 13.8367 6.74013 13.8665C7.1513 13.9536 7.57289 13.9979 8 13.9979C8.42685 13.9979 8.84818 13.9537 9.25912 13.8666C9.39961 13.8369 9.50816 13.7256 9.53397 13.5849L9.79368 12.1692C9.8006 12.1314 9.81058 12.0944 9.82353 12.0583C9.95524 11.6913 10.3608 11.5001 10.7294 11.6312L12.0888 12.1153C12.224 12.1634 12.3749 12.1256 12.4711 12.0196C13.04 11.3926 13.4711 10.6528 13.7328 9.84685C13.777 9.71089 13.7344 9.56183 13.625 9.46935L12.5231 8.53782C12.4937 8.51303 12.4665 8.48589 12.4416 8.45667C12.1882 8.1596 12.2247 7.71429 12.5231 7.46205L13.625 6.53053C13.7344 6.43805 13.777 6.28899 13.7328 6.15302C13.4711 5.34708 13.04 4.60729 12.4711 3.98033C12.3749 3.87431 12.224 3.83652 12.0888 3.88463L10.7293 4.36865C10.6931 4.38152 10.6559 4.39146 10.618 4.39833ZM3.99863 4.97726L4.93522 5.3107C5.82017 5.62559 6.79872 5.16815 7.11769 4.2794C7.14903 4.19207 7.17324 4.1021 7.18996 4.01078L7.36738 3.04113C7.5757 3.01512 7.78684 3.00195 8 3.00195C8.213 3.00195 8.42397 3.0151 8.63214 3.04107L8.81011 4.01117C8.98053 4.9408 9.87266 5.55003 10.7967 5.38225C10.8877 5.36572 10.9775 5.34176 11.0647 5.31073L12.0014 4.97726C12.2564 5.31084 12.4684 5.67476 12.6319 6.06064L11.8774 6.6984C11.1566 7.30787 11.0675 8.38649 11.6807 9.10555C11.7408 9.17609 11.8067 9.24166 11.8775 9.3015L12.6319 9.93924C12.4684 10.3251 12.2564 10.689 12.0014 11.0226L11.0646 10.6891C10.1797 10.3742 9.20128 10.8317 8.88231 11.7205C8.85096 11.8078 8.82677 11.8978 8.81004 11.9891L8.63214 12.9588C8.42397 12.9848 8.213 12.9979 8 12.9979C7.78684 12.9979 7.5757 12.9848 7.36738 12.9587L7.18994 11.989C7.01965 11.0592 6.12743 10.4498 5.2033 10.6176C5.11227 10.6342 5.0225 10.6581 4.93528 10.6892L3.99863 11.0226C3.74357 10.689 3.53161 10.3251 3.36814 9.93924L4.12257 9.30148C4.84343 8.69201 4.93254 7.61339 4.31933 6.89433C4.25917 6.82378 4.19332 6.75822 4.12254 6.69838L3.36814 6.06064C3.53161 5.67476 3.74357 5.31084 3.99863 4.97726Z" fill="#fff"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,11 +1,22 @@
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { DashboardComponent } from "./app/dashboard/dashboard.component";
import { LoginComponent } from "./app/dashboard/login/login.component";
import { OverviewComponent } from "./app/dashboard/overview/overview.component";
import { HelloComponent } from "./app/hello/hello.component";
import { NotFoundComponent } from "./app/not-found/not-found.component";
import { PayComponent } from "./app/pay/pay.component";
const routes: Routes = [
{ path: 'pay/:id', component: PayComponent, data: { title: 'Payment' } },
{ path: 'dashboard', component: DashboardComponent, children: [
{
path: 'login', component: LoginComponent
},
{
path: 'overview', component: OverviewComponent
}
]},
{ path: '', component: HelloComponent },
{ path: '**', component: NotFoundComponent }
]