first commit
50
src/app/app-routing.module.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { BrowserModule } from "@angular/platform-browser";
|
||||
import { Routes, RouterModule } from "@angular/router";
|
||||
|
||||
import { AdminLayoutComponent } from "./layouts/admin-layout/admin-layout.component";
|
||||
import { AuthLayoutComponent } from './layouts/auth-layout/auth-layout.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: "",
|
||||
redirectTo: "company-information",
|
||||
pathMatch: "full"
|
||||
},
|
||||
{
|
||||
path: "",
|
||||
component: AdminLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
loadChildren: () => import ("./layouts/admin-layout/admin-layout.module").then(m => m.AdminLayoutModule)
|
||||
}
|
||||
]
|
||||
}, {
|
||||
path: "",
|
||||
component: AuthLayoutComponent,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
loadChildren: () => import ("./layouts/auth-layout/auth-layout.module").then(m => m.AuthLayoutModule)
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: "**",
|
||||
redirectTo: "company-information"
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
BrowserModule,
|
||||
RouterModule.forRoot(routes, {
|
||||
useHash: true
|
||||
})
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
3
src/app/app.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<!--The content below is only a placeholder and can be replaced.-->
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
0
src/app/app.component.scss
Normal file
33
src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { TestBed, async } from "@angular/core/testing";
|
||||
import { RouterTestingModule } from "@angular/router/testing";
|
||||
import { AppComponent } from "./app.component";
|
||||
|
||||
describe("AppComponent", () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [RouterTestingModule],
|
||||
declarations: [AppComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it("should create the app", () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'black-dashboard-angular'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app.title).toEqual("black-dashboard-angular");
|
||||
});
|
||||
|
||||
it("should render title in a h1 tag", () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector("h1").textContent).toContain(
|
||||
"Welcome to black-dashboard-angular!"
|
||||
);
|
||||
});
|
||||
});
|
||||
10
src/app/app.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-root",
|
||||
templateUrl: "./app.component.html",
|
||||
styleUrls: ["./app.component.scss"]
|
||||
})
|
||||
export class AppComponent {
|
||||
title = "black-dashboard-angular";
|
||||
}
|
||||
34
src/app/app.module.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { ToastrModule } from "ngx-toastr";
|
||||
|
||||
import { AppComponent } from "./app.component";
|
||||
import { AdminLayoutComponent } from "./layouts/admin-layout/admin-layout.component";
|
||||
import { AuthLayoutComponent } from "./layouts/auth-layout/auth-layout.component";
|
||||
|
||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
|
||||
import { AppRoutingModule } from "./app-routing.module";
|
||||
import { ComponentsModule } from "./components/components.module";
|
||||
import { LoginComponent } from './pages/login/login.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserAnimationsModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
ComponentsModule,
|
||||
NgbModule,
|
||||
RouterModule,
|
||||
AppRoutingModule,
|
||||
ToastrModule.forRoot(),
|
||||
],
|
||||
declarations: [AppComponent, AdminLayoutComponent, AuthLayoutComponent, LoginComponent],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
15
src/app/components/components.module.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
|
||||
import { FooterComponent } from "./footer/footer.component";
|
||||
import { NavbarComponent } from "./navbar/navbar.component";
|
||||
import { SidebarComponent } from "./sidebar/sidebar.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, RouterModule, NgbModule],
|
||||
declarations: [FooterComponent, NavbarComponent, SidebarComponent],
|
||||
exports: [FooterComponent, NavbarComponent, SidebarComponent]
|
||||
})
|
||||
export class ComponentsModule {}
|
||||
0
src/app/components/footer/footer.component.css
Normal file
28
src/app/components/footer/footer.component.html
Normal file
@@ -0,0 +1,28 @@
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
<ul class="nav">
|
||||
<!-- <li class="nav-item">
|
||||
<a class="nav-link" href="https://www.creative-tim.com?ref=bda-footer">
|
||||
Creative Tim
|
||||
</a>
|
||||
</li> -->
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link"
|
||||
href="https://talenttic.com"
|
||||
>
|
||||
About Us
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://blog.talenttic.com">
|
||||
Blog
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="copyright">
|
||||
© {{ test | date : "yyyy" }} Powered by
|
||||
<a href="https://talenttic.com" target="_blank"> Talenttic Tech Hub</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
24
src/app/components/footer/footer.component.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { FooterComponent } from "./footer.component";
|
||||
|
||||
describe("FooterComponent", () => {
|
||||
let component: FooterComponent;
|
||||
let fixture: ComponentFixture<FooterComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [FooterComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(FooterComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
14
src/app/components/footer/footer.component.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-footer",
|
||||
templateUrl: "./footer.component.html",
|
||||
styleUrls: ["./footer.component.css"]
|
||||
})
|
||||
export class FooterComponent implements OnInit {
|
||||
test: Date = new Date();
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
||||
0
src/app/components/navbar/navbar.component.css
Normal file
137
src/app/components/navbar/navbar.component.html
Normal file
@@ -0,0 +1,137 @@
|
||||
<nav class=" navbar navbar-expand-lg navbar-absolute navbar-transparent">
|
||||
<div class=" container-fluid">
|
||||
<div class=" navbar-wrapper">
|
||||
<div class=" navbar-toggle d-inline">
|
||||
<button class=" navbar-toggler" type="button" (click)="sidebarToggle()">
|
||||
<span class=" navbar-toggler-bar bar1"> </span>
|
||||
<span class=" navbar-toggler-bar bar2"> </span>
|
||||
<span class=" navbar-toggler-bar bar3"> </span>
|
||||
</button>
|
||||
</div>
|
||||
<a class=" navbar-brand" href="javascript:void(0)"> {{ getTitle() }} </a>
|
||||
</div>
|
||||
<button
|
||||
aria-label="Toggle navigation"
|
||||
class=" navbar-toggler"
|
||||
(click)="collapse()"
|
||||
[attr.aria-expanded]="!isCollapsed"
|
||||
aria-controls="collapseExample"
|
||||
id="navigation"
|
||||
type="button"
|
||||
>
|
||||
<span class=" navbar-toggler-bar navbar-kebab"> </span>
|
||||
<span class=" navbar-toggler-bar navbar-kebab"> </span>
|
||||
<span class=" navbar-toggler-bar navbar-kebab"> </span>
|
||||
</button>
|
||||
<div class=" navbar-collapse" [ngbCollapse]="isCollapsed" id="navigation">
|
||||
<ul class=" navbar-nav ml-auto">
|
||||
<li class=" search-bar input-group">
|
||||
<button
|
||||
class=" btn btn-link"
|
||||
data-target="#searchModal"
|
||||
data-toggle="modal"
|
||||
(click)="open(content)"
|
||||
id="search-button"
|
||||
>
|
||||
<i class=" tim-icons icon-zoom-split"> </i>
|
||||
<span class=" d-lg-none d-md-block"> Search </span>
|
||||
</button>
|
||||
</li>
|
||||
<li class=" nav-item" ngbDropdown>
|
||||
<a
|
||||
class=" nav-link"
|
||||
data-toggle="dropdown"
|
||||
href="javascript:void(0)"
|
||||
ngbDropdownToggle
|
||||
>
|
||||
<div class=" notification d-none d-lg-block d-xl-block"></div>
|
||||
<i class=" tim-icons icon-sound-wave"> </i>
|
||||
<p class=" d-lg-none">Notifications</p>
|
||||
</a>
|
||||
<ul class=" dropdown-menu-right dropdown-navbar" ngbDropdownMenu>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Mike John responded to your email
|
||||
</a>
|
||||
</li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
You have 5 more tasks
|
||||
</a>
|
||||
</li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Your friend Michael is in town
|
||||
</a>
|
||||
</li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Another notification
|
||||
</a>
|
||||
</li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Another one
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class=" nav-item" ngbDropdown>
|
||||
<a
|
||||
class=" nav-link"
|
||||
data-toggle="dropdown"
|
||||
href="javascript:void(0)"
|
||||
ngbDropdownToggle
|
||||
>
|
||||
<div class=" photo">
|
||||
<img alt="Profile Photo" src="assets/img/anime3.png" />
|
||||
</div>
|
||||
<b class=" caret d-none d-lg-block d-xl-block"> </b>
|
||||
<p class=" d-lg-none">Log out</p>
|
||||
</a>
|
||||
<ul class=" dropdown-navbar" ngbDropdownMenu>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Profile
|
||||
</a>
|
||||
</li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Settings
|
||||
</a>
|
||||
</li>
|
||||
<li class=" dropdown-divider"></li>
|
||||
<li class=" nav-link">
|
||||
<a class=" nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
Log out
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class=" separator d-lg-none"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<ng-template #content let-modal>
|
||||
<div class=" modal-header">
|
||||
<input
|
||||
class=" form-control"
|
||||
id="inlineFormInputGroup"
|
||||
placeholder="SEARCH"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<button
|
||||
aria-label="Close"
|
||||
class=" close"
|
||||
data-dismiss="modal"
|
||||
type="button"
|
||||
(click)="modal.dismiss('Cross click')"
|
||||
>
|
||||
<i class=" tim-icons icon-simple-remove"> </i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</ng-template>
|
||||
24
src/app/components/navbar/navbar.component.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { NavbarComponent } from "./navbar.component";
|
||||
|
||||
describe("NavbarComponent", () => {
|
||||
let component: NavbarComponent;
|
||||
let fixture: ComponentFixture<NavbarComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [NavbarComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(NavbarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
196
src/app/components/navbar/navbar.component.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { Component, OnInit, ElementRef, OnDestroy } from "@angular/core";
|
||||
import { ROUTES } from "../sidebar/sidebar.component";
|
||||
import { Location } from "@angular/common";
|
||||
import { Router } from "@angular/router";
|
||||
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Component({
|
||||
selector: "app-navbar",
|
||||
templateUrl: "./navbar.component.html",
|
||||
styleUrls: ["./navbar.component.css"]
|
||||
})
|
||||
export class NavbarComponent implements OnInit, OnDestroy {
|
||||
private listTitles: any[];
|
||||
location: Location;
|
||||
mobile_menu_visible: any = 0;
|
||||
private toggleButton: any;
|
||||
private sidebarVisible: boolean;
|
||||
|
||||
public isCollapsed = true;
|
||||
|
||||
closeResult: string;
|
||||
|
||||
constructor(
|
||||
location: Location,
|
||||
private element: ElementRef,
|
||||
private router: Router,
|
||||
private modalService: NgbModal
|
||||
) {
|
||||
this.location = location;
|
||||
this.sidebarVisible = false;
|
||||
}
|
||||
// function that adds color white/transparent to the navbar on resize (this is for the collapse)
|
||||
updateColor = () => {
|
||||
var navbar = document.getElementsByClassName('navbar')[0];
|
||||
if (window.innerWidth < 993 && !this.isCollapsed) {
|
||||
navbar.classList.add('bg-white');
|
||||
navbar.classList.remove('navbar-transparent');
|
||||
} else {
|
||||
navbar.classList.remove('bg-white');
|
||||
navbar.classList.add('navbar-transparent');
|
||||
}
|
||||
};
|
||||
ngOnInit() {
|
||||
window.addEventListener("resize", this.updateColor);
|
||||
this.listTitles = ROUTES.filter(listTitle => listTitle);
|
||||
const navbar: HTMLElement = this.element.nativeElement;
|
||||
this.toggleButton = navbar.getElementsByClassName("navbar-toggler")[0];
|
||||
this.router.events.subscribe(event => {
|
||||
this.sidebarClose();
|
||||
var $layer: any = document.getElementsByClassName("close-layer")[0];
|
||||
if ($layer) {
|
||||
$layer.remove();
|
||||
this.mobile_menu_visible = 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
collapse() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
const navbar = document.getElementsByTagName("nav")[0];
|
||||
if (!this.isCollapsed) {
|
||||
navbar.classList.remove("navbar-transparent");
|
||||
navbar.classList.add("bg-white");
|
||||
} else {
|
||||
navbar.classList.add("navbar-transparent");
|
||||
navbar.classList.remove("bg-white");
|
||||
}
|
||||
}
|
||||
|
||||
sidebarOpen() {
|
||||
const toggleButton = this.toggleButton;
|
||||
const mainPanel = <HTMLElement>(
|
||||
document.getElementsByClassName("main-panel")[0]
|
||||
);
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
if (window.innerWidth < 991) {
|
||||
mainPanel.style.position = "fixed";
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
toggleButton.classList.add("toggled");
|
||||
}, 500);
|
||||
|
||||
html.classList.add("nav-open");
|
||||
|
||||
this.sidebarVisible = true;
|
||||
}
|
||||
sidebarClose() {
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
this.toggleButton.classList.remove("toggled");
|
||||
const mainPanel = <HTMLElement>(
|
||||
document.getElementsByClassName("main-panel")[0]
|
||||
);
|
||||
|
||||
if (window.innerWidth < 991) {
|
||||
setTimeout(function() {
|
||||
mainPanel.style.position = "";
|
||||
}, 500);
|
||||
}
|
||||
this.sidebarVisible = false;
|
||||
html.classList.remove("nav-open");
|
||||
}
|
||||
sidebarToggle() {
|
||||
// const toggleButton = this.toggleButton;
|
||||
// const html = document.getElementsByTagName('html')[0];
|
||||
var $toggle = document.getElementsByClassName("navbar-toggler")[0];
|
||||
|
||||
if (this.sidebarVisible === false) {
|
||||
this.sidebarOpen();
|
||||
} else {
|
||||
this.sidebarClose();
|
||||
}
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
|
||||
if (this.mobile_menu_visible == 1) {
|
||||
// $('html').removeClass('nav-open');
|
||||
html.classList.remove("nav-open");
|
||||
if ($layer) {
|
||||
$layer.remove();
|
||||
}
|
||||
setTimeout(function() {
|
||||
$toggle.classList.remove("toggled");
|
||||
}, 400);
|
||||
|
||||
this.mobile_menu_visible = 0;
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
$toggle.classList.add("toggled");
|
||||
}, 430);
|
||||
|
||||
var $layer = document.createElement("div");
|
||||
$layer.setAttribute("class", "close-layer");
|
||||
|
||||
if (html.querySelectorAll(".main-panel")) {
|
||||
document.getElementsByClassName("main-panel")[0].appendChild($layer);
|
||||
} else if (html.classList.contains("off-canvas-sidebar")) {
|
||||
document
|
||||
.getElementsByClassName("wrapper-full-page")[0]
|
||||
.appendChild($layer);
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
$layer.classList.add("visible");
|
||||
}, 100);
|
||||
|
||||
$layer.onclick = function() {
|
||||
//asign a function
|
||||
html.classList.remove("nav-open");
|
||||
this.mobile_menu_visible = 0;
|
||||
$layer.classList.remove("visible");
|
||||
setTimeout(function() {
|
||||
$layer.remove();
|
||||
$toggle.classList.remove("toggled");
|
||||
}, 400);
|
||||
}.bind(this);
|
||||
|
||||
html.classList.add("nav-open");
|
||||
this.mobile_menu_visible = 1;
|
||||
}
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
var title = this.location.prepareExternalUrl(this.location.path());
|
||||
if (title.charAt(0) === "#") {
|
||||
title = title.slice(1);
|
||||
}
|
||||
|
||||
for (var item = 0; item < this.listTitles.length; item++) {
|
||||
if (this.listTitles[item].path === title) {
|
||||
return this.listTitles[item].title;
|
||||
}
|
||||
}
|
||||
return "Dashboard";
|
||||
}
|
||||
|
||||
open(content) {
|
||||
this.modalService.open(content, {windowClass: 'modal-search'}).result.then((result) => {
|
||||
this.closeResult = `Closed with: ${result}`;
|
||||
}, (reason) => {
|
||||
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
|
||||
});
|
||||
}
|
||||
|
||||
private getDismissReason(reason: any): string {
|
||||
if (reason === ModalDismissReasons.ESC) {
|
||||
return 'by pressing ESC';
|
||||
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
|
||||
return 'by clicking on a backdrop';
|
||||
} else {
|
||||
return `with: ${reason}`;
|
||||
}
|
||||
}
|
||||
ngOnDestroy(){
|
||||
window.removeEventListener("resize", this.updateColor);
|
||||
}
|
||||
}
|
||||
0
src/app/components/sidebar/sidebar.component.css
Normal file
25
src/app/components/sidebar/sidebar.component.html
Normal file
@@ -0,0 +1,25 @@
|
||||
<div class="logo">
|
||||
<a routerLink="dashboard" class="simple-text logo-mini">
|
||||
<div class="logo-img">
|
||||
<img src="../../../assets/img/logo.png" />
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a routerLink="company-information" class="simple-text logo-normal">
|
||||
Talenttic Tech Hub CRM
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-wrapper">
|
||||
<ul class="nav">
|
||||
<li
|
||||
routerLinkActive="active"
|
||||
*ngFor="let menuItem of menuItems"
|
||||
class="{{ menuItem.class }} nav-item"
|
||||
>
|
||||
<a [routerLink]="[menuItem.path]">
|
||||
<i class="bi {{ menuItem.icon }}"></i>
|
||||
<p>{{ menuItem.title }}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
24
src/app/components/sidebar/sidebar.component.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { SidebarComponent } from "./sidebar.component";
|
||||
|
||||
describe("SidebarComponent", () => {
|
||||
let component: SidebarComponent;
|
||||
let fixture: ComponentFixture<SidebarComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [SidebarComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SidebarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
68
src/app/components/sidebar/sidebar.component.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
declare interface RouteInfo {
|
||||
path: string;
|
||||
title: string;
|
||||
icon: string;
|
||||
class: string;
|
||||
}
|
||||
export const ROUTES: RouteInfo[] = [
|
||||
// {
|
||||
// path: "/dashboard",
|
||||
// title: "Dashboard",
|
||||
// icon: "bi-speedometer",
|
||||
// class: "",
|
||||
// },
|
||||
{
|
||||
path: "/company-information",
|
||||
title: "Company Information",
|
||||
icon: "bi-person-vcard",
|
||||
class: "",
|
||||
},
|
||||
{
|
||||
path: "/notifications",
|
||||
title: "Notifications",
|
||||
icon: "bi-bell",
|
||||
class: "",
|
||||
},
|
||||
|
||||
{
|
||||
path: "/company-profile",
|
||||
title: "Company Profile",
|
||||
icon: "bi-person-lines-fill",
|
||||
class: "",
|
||||
},
|
||||
{
|
||||
path: "/invoices",
|
||||
title: "Invoices",
|
||||
icon: "bi-receipt-cutoff",
|
||||
class: "",
|
||||
},
|
||||
{
|
||||
path: "/payments",
|
||||
title: "Payments",
|
||||
icon: "bi-credit-card",
|
||||
class: "",
|
||||
},
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: "app-sidebar",
|
||||
templateUrl: "./sidebar.component.html",
|
||||
styleUrls: ["./sidebar.component.css"],
|
||||
})
|
||||
export class SidebarComponent implements OnInit {
|
||||
menuItems: any[];
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {
|
||||
this.menuItems = ROUTES.filter((menuItem) => menuItem);
|
||||
}
|
||||
isMobileMenu() {
|
||||
if (window.innerWidth > 991) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
154
src/app/data/company.ts
Normal file
@@ -0,0 +1,154 @@
|
||||
import { CompanyModel } from "../models/company";
|
||||
|
||||
export const company: CompanyModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Stark Industries",
|
||||
username: "starkindustries",
|
||||
email: "info@starkindustries.com",
|
||||
phone: "09055784625",
|
||||
image:
|
||||
"https://webtoolfeed.files.wordpress.com/2012/05/the-union-repoman.jpg",
|
||||
description:
|
||||
"A multinational technology company specializing in weapons manufacturing, led by Tony Stark.",
|
||||
address: "200 Park Ave, New York, NY 10166",
|
||||
city: "New York City, NY ",
|
||||
stagingUrl: "stage.starkindustries.com",
|
||||
productionUrl: "starkindustries.com",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Wayne Enterprises",
|
||||
username: "wayneenterprises",
|
||||
email: "info@wayneenterprises.com",
|
||||
phone: "0812012234",
|
||||
image:
|
||||
"https://www.thesun.co.uk/wp-content/uploads/2019/07/NINTCHDBPICT000491000000.jpg?strip=all&w=960",
|
||||
description:
|
||||
"A multinational conglomerate holding company headquartered in Gotham City, led by Bruce Wayne.",
|
||||
address: "10 Wayne Tower, Gotham City, NJ 07102",
|
||||
city: "Gotham City, NJ ",
|
||||
stagingUrl: "stage.wayneenterprises.com",
|
||||
productionUrl: "wayneenterprises.com",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "LexCorp",
|
||||
username: "lexcorp",
|
||||
email: "info@lexcorp.com",
|
||||
phone: "08174361092",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-woman-mia-avatar-600w-2127358541.jpg",
|
||||
description:
|
||||
"LexCorp is a multinational conglomerate that operates in various industries, including technology, finance, and media. Founded by billionaire businessman and philanthropist Lex Luthor.",
|
||||
address: "LexCorp Tower, Metropolis, NY 10001",
|
||||
city: "Metropolis, NY",
|
||||
stagingUrl: "stage.lexcorp.com",
|
||||
productionUrl: "lexcorp.com",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Sahara Security & Investigation Ltd.",
|
||||
username: "saharasecurity_ng",
|
||||
email: "info@saharasecurity.ng",
|
||||
phone: "08120122347",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-man-adam-avatar-600w-2107967969.jpg",
|
||||
description:
|
||||
"Sahara Security & Investigation is a leading provider of security and investigation services for businesses and individuals across Nigeria. With a team of highly trained professionals and state-of-the-art equipment, we are committed to protecting our clients' assets and interests.",
|
||||
address: "5, Bode Thomas Street, Surulere, Lagos State",
|
||||
city: "Lagos, Nigeria",
|
||||
stagingUrl: "stage.saharasecurity.com",
|
||||
productionUrl: "saharasecurity.ng",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Umbrella Corporation",
|
||||
username: "umbrellacorporation",
|
||||
email: "info@umbrellacorp.com",
|
||||
phone: "07073214806",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-man-adam-avatar-600w-2107967969.jpg",
|
||||
description:
|
||||
"Umbrella Corporation is a pharmaceutical company that specializes in bioweapons and bioengineering.",
|
||||
address: "Umbrella Corporation, Raccoon City, NY 10001",
|
||||
city: "Raccoon City, NY",
|
||||
stagingUrl: "stage.umbrellacorp.com",
|
||||
productionUrl: "umbrellacorp.com",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: "Aperture Science",
|
||||
username: "aperturescience",
|
||||
email: "aperturescience@info.com",
|
||||
phone: "08033567890",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-man-adam-avatar-600w-2107967969.jpg",
|
||||
description:
|
||||
"Aperture Science is a science and technology company that specializes in the development of advanced research facilities and the manufacturing of consumer products.",
|
||||
address: "Aperture Science, New York City, NY 10001",
|
||||
city: "New York City, NY",
|
||||
stagingUrl: "stage.aperturescience.com",
|
||||
productionUrl: "aperturescience.com",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: "Stellar Airways Nigeria Ltd.",
|
||||
username: "stellarairways_ng",
|
||||
email: "info@stellarairways.ng",
|
||||
phone: "07084849673",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-woman-mia-avatar-600w-2127358541.jpg",
|
||||
description:
|
||||
"Stellar Airways Nigeria is a premier airline that provides domestic and international travel services to individuals and businesses across Nigeria. With a focus on safety, comfort, and convenience, we are dedicated to providing exceptional travel experiences to our customers.",
|
||||
address: "Murtala Muhammed International Airport, Ikeja, Lagos State",
|
||||
city: "Lagos, Nigeria",
|
||||
stagingUrl: "stage.stellarairways.com",
|
||||
productionUrl: "stellarairways.ng",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: "Deltacore Technologies Ltd.",
|
||||
username: "deltacore_ng",
|
||||
email: "info@deltacore.ng",
|
||||
phone: "09022345109",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-woman-mia-avatar-600w-2127358541.jpg",
|
||||
description:
|
||||
"Deltacore Technologies is a leading provider of software and hardware solutions for businesses and individuals across Nigeria. With a focus on innovation and quality, we provide cutting-edge technology products and services to help our clients stay ahead of the competition.",
|
||||
address: "23, Adeyemo Alakija Street, Victoria Island, Lagos State",
|
||||
city: "Lagos, Nigeria",
|
||||
stagingUrl: "stage.deltacore.com",
|
||||
productionUrl: "deltacore.ng",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
name: "Goldmine Oil & Gas Ltd.",
|
||||
username: "goldmineoilgas_ng",
|
||||
email: "info@goldmineoilgas.ng",
|
||||
phone: "0911250021",
|
||||
image:
|
||||
"https://www.shutterstock.com/image-vector/young-smiling-man-adam-avatar-600w-2107967969.jpg",
|
||||
description:
|
||||
"Goldmine Oil & Gas is a leading exploration and production company that operates in the Nigerian oil and gas industry. With a focus on sustainability and innovation, we are committed to maximizing the potential of Nigeria's natural resources while minimizing our environmental impact.",
|
||||
address: "14, Marina Road, Warri South, Delta State",
|
||||
city: "Warri, Nigeria",
|
||||
stagingUrl: "stage.goldmineoilgas.com",
|
||||
productionUrl: "goldmineoilgas.ng",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
name: "Cedarwood Construction & Engineering Ltd.",
|
||||
username: "cedarwoodconstruction_ng",
|
||||
email: "info@cedarwoodconstruction.ng",
|
||||
phone: "0911250021",
|
||||
image:
|
||||
"https://thumbs.dreamstime.com/b/male-avatar-icon-flat-style-male-user-icon-cartoon-man-avatar-hipster-vector-stock-91462914.jpg",
|
||||
description:
|
||||
"Cedarwood Construction & Engineering is a leading construction company that provides innovative solutions for residential, commercial, and industrial projects across Nigeria. With a team of skilled professionals and state-of-the-art equipment, we are committed to delivering high-quality projects on time and within budget.",
|
||||
address: "9, Adeniyi Jones Avenue, Ikeja, Lagos State",
|
||||
city: "Lagos, Nigeria",
|
||||
stagingUrl: "stage.cedarwoodconstruction.com",
|
||||
productionUrl: "cedarwoodconstruction.ng",
|
||||
},
|
||||
];
|
||||
124
src/app/data/database-info.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import { DatabaseInfoModel } from "../models/database-info";
|
||||
|
||||
export const databaseInfo: DatabaseInfoModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
serverId: 1,
|
||||
companyId: 1,
|
||||
databaseName: "database1",
|
||||
databaseType: "MySQL",
|
||||
bandwidthGB: 1,
|
||||
username: "user123",
|
||||
password: "password123",
|
||||
host: "localhost",
|
||||
port: 3306,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
serverId: 2,
|
||||
companyId: 2,
|
||||
databaseName: "database2",
|
||||
databaseType: "PostgreSQL",
|
||||
bandwidthGB: 10,
|
||||
username: "dbuser2",
|
||||
password: "dbpassword2",
|
||||
host: "db-host-1a3c.example.com",
|
||||
port: 5432,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
serverId: 3,
|
||||
companyId: 3,
|
||||
databaseName: "database3",
|
||||
databaseType: "MongoDB",
|
||||
bandwidthGB: 100,
|
||||
username: "dbuser3",
|
||||
password: "dbpassword3",
|
||||
host: "db2-4f8d.example.org",
|
||||
port: 27017,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
serverId: 4,
|
||||
companyId: 4,
|
||||
databaseName: "database4",
|
||||
databaseType: "SQLite",
|
||||
bandwidthGB: 1000,
|
||||
username: "dbuser4",
|
||||
password: "dbpassword4",
|
||||
host: "random-db-12a5.example.net",
|
||||
port: 3306,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
serverId: 5,
|
||||
companyId: 5,
|
||||
databaseName: "database5",
|
||||
databaseType: "MySQL",
|
||||
bandwidthGB: 2000,
|
||||
username: "dbuser5",
|
||||
password: "dbpassword5",
|
||||
host: "host-9c5b.example.net",
|
||||
port: 5432,
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
serverId: 6,
|
||||
companyId: 6,
|
||||
databaseName: "database6",
|
||||
databaseType: "PostgreSQL",
|
||||
bandwidthGB: 3000,
|
||||
username: "dbuser6",
|
||||
password: "dbpassword6",
|
||||
host: "db-server-7e2f.example.com",
|
||||
port: 27017,
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
serverId: 8,
|
||||
companyId: 8,
|
||||
databaseName: "database7",
|
||||
databaseType: "MongoDB",
|
||||
bandwidthGB: 4000,
|
||||
username: "dbuser7",
|
||||
password: "dbpassword7",
|
||||
host: "mydb-1f4a.example.net",
|
||||
port: 3306,
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
serverId: 7,
|
||||
companyId: 7,
|
||||
databaseName: "database8",
|
||||
databaseType: "SQLite",
|
||||
bandwidthGB: 5000,
|
||||
username: "dbuser8",
|
||||
password: "dbpassword8",
|
||||
host: "db-1f4a.example.net",
|
||||
port: 5432,
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
serverId: 9,
|
||||
companyId: 9,
|
||||
databaseName: "database9",
|
||||
databaseType: "MySQL",
|
||||
bandwidthGB: 400,
|
||||
username: "dbuser9",
|
||||
password: "dbpassword9",
|
||||
host: "dbhost-5b9c.example.org",
|
||||
port: 27017,
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
serverId: 10,
|
||||
companyId: 10,
|
||||
databaseName: "database10",
|
||||
databaseType: "PostgreSQL",
|
||||
bandwidthGB: 300,
|
||||
username: "dbuser10",
|
||||
password: "dbpassword10",
|
||||
host: "randomdb-3e8d.example.com",
|
||||
port: 3306,
|
||||
},
|
||||
];
|
||||
124
src/app/data/hosting-info.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
import { HostingInfoModel } from "../models/hosting-info";
|
||||
|
||||
export const hostingInfo: HostingInfoModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
companyId: 1,
|
||||
provider: "Digital Ocean",
|
||||
serverType: "VPS",
|
||||
diskSpaceGB: 100,
|
||||
bandwidthGB: 1000,
|
||||
username: "user123",
|
||||
password: "password123",
|
||||
serverLocation: "United States",
|
||||
expirationDate: new Date("2025-12-31"),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
companyId: 2,
|
||||
provider: "Bluehost",
|
||||
serverType: "shared",
|
||||
diskSpaceGB: 150,
|
||||
bandwidthGB: 500,
|
||||
username: "user456",
|
||||
password: "password456",
|
||||
serverLocation: "United States",
|
||||
expirationDate: new Date("2024-02-31"),
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
companyId: 3,
|
||||
provider: "SiteGround",
|
||||
serverType: "dedicated",
|
||||
diskSpaceGB: 500,
|
||||
bandwidthGB: 5000,
|
||||
username: "user789",
|
||||
password: "password789",
|
||||
serverLocation: "United Kingdom",
|
||||
expirationDate: new Date("2023-03-31"),
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
companyId: 4,
|
||||
provider: "HostGator",
|
||||
serverType: "shared",
|
||||
diskSpaceGB: 200,
|
||||
bandwidthGB: 1000,
|
||||
username: "user101",
|
||||
password: "password101",
|
||||
serverLocation: "Canada",
|
||||
expirationDate: new Date("2022-04-31"),
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
companyId: 5,
|
||||
provider: "DreamHost",
|
||||
serverType: "shared",
|
||||
diskSpaceGB: 50,
|
||||
bandwidthGB: 500,
|
||||
username: "user111",
|
||||
password: "password111",
|
||||
serverLocation: "United States",
|
||||
expirationDate: new Date("2023-05-11"),
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
companyId: 6,
|
||||
provider: "GoDaddy",
|
||||
serverType: "VPS",
|
||||
diskSpaceGB: 100,
|
||||
bandwidthGB: 1000,
|
||||
username: "user121",
|
||||
password: "password121",
|
||||
serverLocation: "United States",
|
||||
expirationDate: new Date("2022-06-21"),
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
companyId: 7,
|
||||
provider: "Hostinger",
|
||||
serverType: "shared",
|
||||
diskSpaceGB: 500,
|
||||
bandwidthGB: 5000,
|
||||
username: "user131",
|
||||
password: "password131",
|
||||
serverLocation: "Singapore",
|
||||
expirationDate: new Date("2025-04-08"),
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
companyId: 8,
|
||||
provider: "InMotion Hosting",
|
||||
serverType: "dedicated",
|
||||
diskSpaceGB: 2000,
|
||||
bandwidthGB: 20000,
|
||||
username: "user141",
|
||||
password: "password141",
|
||||
serverLocation: "United States",
|
||||
expirationDate: new Date("2024-07-21"),
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
companyId: 9,
|
||||
provider: "Namecheap",
|
||||
serverType: "shared",
|
||||
diskSpaceGB: 100,
|
||||
bandwidthGB: 1000,
|
||||
username: "user151",
|
||||
password: "password151",
|
||||
serverLocation: "Netherlands",
|
||||
expirationDate: new Date("2023-10-01"),
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
companyId: 10,
|
||||
provider: "A2 Hosting",
|
||||
serverType: "VPS",
|
||||
diskSpaceGB: 500,
|
||||
bandwidthGB: 5000,
|
||||
username: "user161",
|
||||
password: "password161",
|
||||
serverLocation: "United Kingdom",
|
||||
expirationDate: new Date("2022-11-11"),
|
||||
},
|
||||
];
|
||||
238
src/app/data/invoice.ts
Normal file
@@ -0,0 +1,238 @@
|
||||
import { InvoiceModel } from "../models/invoice";
|
||||
|
||||
export const invoice: InvoiceModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
invoiceNumber: "INV-0001",
|
||||
companyId: 2,
|
||||
dateIssued: new Date("2023-03-15"),
|
||||
dueDate: new Date("2023-03-30"),
|
||||
status: "paid",
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Custom Website Development",
|
||||
service: 1,
|
||||
unitPrice: 100000,
|
||||
total: 100000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
invoiceNumber: "INV-0002",
|
||||
companyId: 3,
|
||||
dateIssued: new Date("2023-03-20"),
|
||||
dueDate: new Date("2023-04-10"),
|
||||
status: "pending",
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Custom Mobile App Development",
|
||||
service: 1,
|
||||
unitPrice: 300000,
|
||||
total: 300000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
invoiceNumber: "INV-0003",
|
||||
companyId: 1,
|
||||
dateIssued: new Date("2023-03-25"),
|
||||
dueDate: new Date("2023-04-15"),
|
||||
status: "pending",
|
||||
amount: "200000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "E-commerce Website Development",
|
||||
service: 1,
|
||||
unitPrice: 200000,
|
||||
total: 200000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
invoiceNumber: "INV-0004",
|
||||
companyId: 5,
|
||||
dateIssued: new Date("2023-03-30"),
|
||||
dueDate: new Date("2023-04-20"),
|
||||
status: "paid",
|
||||
amount: "500000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Redesign",
|
||||
service: 1,
|
||||
unitPrice: 500000,
|
||||
total: 500000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
invoiceNumber: "INV-0005",
|
||||
companyId: 6,
|
||||
dateIssued: new Date("2023-04-05"),
|
||||
dueDate: new Date("2023-04-25"),
|
||||
status: "overdue",
|
||||
amount: "250000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Maintenance",
|
||||
service: 1,
|
||||
unitPrice: 250000,
|
||||
total: 250000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
invoiceNumber: "INV-0006",
|
||||
companyId: 7,
|
||||
dateIssued: new Date("2023-04-10"),
|
||||
dueDate: new Date("2023-04-30"),
|
||||
status: "paid",
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Hosting",
|
||||
service: 1,
|
||||
unitPrice: 100000,
|
||||
total: 100000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
invoiceNumber: "INV-0007",
|
||||
companyId: 4,
|
||||
dateIssued: new Date("2023-04-15"),
|
||||
dueDate: new Date("2023-05-05"),
|
||||
status: "paid",
|
||||
amount: "200000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Custom Software Development",
|
||||
service: 1,
|
||||
unitPrice: 200000,
|
||||
total: 200000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
invoiceNumber: "INV-0008",
|
||||
companyId: 8,
|
||||
dateIssued: new Date("2023-04-15"),
|
||||
dueDate: new Date("2023-05-05"),
|
||||
status: "paid",
|
||||
amount: "200000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Custom Software Development",
|
||||
service: 1,
|
||||
unitPrice: 200000,
|
||||
total: 200000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
invoiceNumber: "INV-0009",
|
||||
companyId: 9,
|
||||
dateIssued: new Date("2023-04-20"),
|
||||
dueDate: new Date("2023-05-10"),
|
||||
status: "paid",
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Security Audit",
|
||||
service: 1,
|
||||
unitPrice: 300000,
|
||||
total: 300000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
invoiceNumber: "INV-00010",
|
||||
companyId: 10,
|
||||
dateIssued: new Date("2023-04-20"),
|
||||
dueDate: new Date("2023-05-10"),
|
||||
status: "paid",
|
||||
amount: "150000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Optimization",
|
||||
service: 1,
|
||||
unitPrice: 150000,
|
||||
total: 150000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
invoiceNumber: "INV-00011",
|
||||
companyId: 1,
|
||||
dateIssued: new Date("2023-03-10"),
|
||||
dueDate: new Date("2023-06-15"),
|
||||
status: "paid",
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Hosting",
|
||||
service: 1,
|
||||
unitPrice: 100000,
|
||||
total: 100000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
invoiceNumber: "INV-00012",
|
||||
companyId: 1,
|
||||
dateIssued: new Date("2023-05-05"),
|
||||
dueDate: new Date("2024-07-15"),
|
||||
status: "overdue",
|
||||
amount: "250000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Maintenance",
|
||||
service: 1,
|
||||
unitPrice: 250000,
|
||||
total: 250000,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
invoiceNumber: "INV-00013",
|
||||
companyId: 1,
|
||||
dateIssued: new Date("2023-03-21"),
|
||||
dueDate: new Date("2023-05-15"),
|
||||
status: "pending",
|
||||
amount: "70000",
|
||||
currency: "₦",
|
||||
services: [
|
||||
{
|
||||
description: "Website Security Audit",
|
||||
service: 1,
|
||||
unitPrice: 70000,
|
||||
total: 70000,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
0
src/app/data/notification.ts
Normal file
172
src/app/data/payment.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
import { PaymentModel } from "../models/payment";
|
||||
|
||||
export const payment: PaymentModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
invoiceId: 1,
|
||||
companyId: 1,
|
||||
invoiceNumber: "INV-001",
|
||||
paymentNumber: "PAY-001",
|
||||
paymentDate: new Date("2023-03-10"),
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
method: "bank transfer",
|
||||
status: "pending",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
invoiceId: 2,
|
||||
companyId: 2,
|
||||
invoiceNumber: "INV-002",
|
||||
paymentNumber: "PAY-002",
|
||||
paymentDate: new Date("2023-03-15"),
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
method: "credit card",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
invoiceId: 3,
|
||||
companyId: 3,
|
||||
invoiceNumber: "INV-003",
|
||||
paymentNumber: "PAY-003",
|
||||
paymentDate: new Date("2023-03-20"),
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
method: "bank transfer",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
invoiceId: 4,
|
||||
companyId: 5,
|
||||
invoiceNumber: "INV-004",
|
||||
paymentNumber: "PAY-004",
|
||||
paymentDate: new Date("2023-04-10"),
|
||||
amount: "500000",
|
||||
currency: "₦",
|
||||
method: "cheque",
|
||||
status: "failed",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
invoiceId: 5,
|
||||
companyId: 6,
|
||||
invoiceNumber: "INV-005",
|
||||
paymentNumber: "PAY-005",
|
||||
paymentDate: new Date("2023-04-15"),
|
||||
amount: "250000",
|
||||
currency: "₦",
|
||||
method: "bank transfer",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
invoiceId: 6,
|
||||
companyId: 7,
|
||||
invoiceNumber: "INV-006",
|
||||
paymentNumber: "PAY-006",
|
||||
paymentDate: new Date("2023-04-17"),
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
method: "credit card",
|
||||
status: "pending",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
invoiceId: 7,
|
||||
companyId: 4,
|
||||
invoiceNumber: "INV-007",
|
||||
paymentNumber: "PAY-007",
|
||||
paymentDate: new Date("2023-04-22"),
|
||||
amount: "200000",
|
||||
currency: "₦",
|
||||
method: "cash",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
invoiceId: 8,
|
||||
companyId: 8,
|
||||
invoiceNumber: "INV-008",
|
||||
paymentNumber: "PAY-008",
|
||||
paymentDate: new Date("2023-04-25"),
|
||||
amount: "200000",
|
||||
currency: "₦",
|
||||
method: "cash",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
invoiceId: 9,
|
||||
companyId: 9,
|
||||
invoiceNumber: "INV-009",
|
||||
paymentNumber: "PAY-009",
|
||||
paymentDate: new Date("2023-04-30"),
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
method: "cheque",
|
||||
status: "failed",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
invoiceId: 10,
|
||||
companyId: 10,
|
||||
invoiceNumber: "INV-010",
|
||||
paymentNumber: "PAY-010",
|
||||
paymentDate: new Date("2023-05-05"),
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
method: "bank transfer",
|
||||
status: "pending",
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
invoiceId: 11,
|
||||
companyId: 1,
|
||||
invoiceNumber: "INV-011",
|
||||
paymentNumber: "PAY-011",
|
||||
paymentDate: new Date("2023-05-10"),
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
method: "credit card",
|
||||
status: "completed",
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
invoiceId: 12,
|
||||
companyId: 1,
|
||||
invoiceNumber: "INV-012",
|
||||
paymentNumber: "PAY-012",
|
||||
paymentDate: new Date("2023-05-15"),
|
||||
amount: "100000",
|
||||
currency: "₦",
|
||||
method: "bank transfer",
|
||||
status: "pending",
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
invoiceId: 13,
|
||||
companyId: 1,
|
||||
invoiceNumber: "INV-013",
|
||||
paymentNumber: "PAY-013",
|
||||
paymentDate: new Date("2023-05-20"),
|
||||
amount: "300000",
|
||||
currency: "₦",
|
||||
method: "cheque",
|
||||
status: "failed",
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
invoiceId: 14,
|
||||
companyId: 1,
|
||||
invoiceNumber: "INV-014",
|
||||
paymentNumber: "PAY-014",
|
||||
paymentDate: new Date("2023-05-25"),
|
||||
amount: "500000",
|
||||
currency: "₦",
|
||||
method: "cash",
|
||||
status: "completed",
|
||||
},
|
||||
];
|
||||
144
src/app/data/server-info.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { ServerInfoModel } from "../models/server-info";
|
||||
|
||||
export const serverInfo: ServerInfoModel[] = [
|
||||
{
|
||||
id: 1,
|
||||
companyId: 1,
|
||||
databaseId: 1,
|
||||
provider: "DigitalOcean",
|
||||
serverType: "shared",
|
||||
operatingSystem: "Ubuntu 20.04 LTS",
|
||||
cpu: "Intel Xeon 2.3 GHz",
|
||||
storageGB: 100,
|
||||
ramGB: 4,
|
||||
bandwidthGB: 4,
|
||||
monthlyCostUSD: 10,
|
||||
location: "New York, USA",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
companyId: 2,
|
||||
databaseId: 2,
|
||||
provider: "Amazon Web Services",
|
||||
serverType: "VPS",
|
||||
operatingSystem: "Amazon Linux 2",
|
||||
cpu: "Intel Xeon 2.5 GHz",
|
||||
storageGB: 500,
|
||||
ramGB: 16,
|
||||
bandwidthGB: 10,
|
||||
monthlyCostUSD: 80,
|
||||
location: "North Virginia, USA",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
companyId: 3,
|
||||
databaseId: 4,
|
||||
provider: "Google Cloud Platform",
|
||||
serverType: "dedicated",
|
||||
operatingSystem: "CentOS 7",
|
||||
cpu: "Intel Xeon 2.4 GHz",
|
||||
storageGB: 200,
|
||||
ramGB: 8,
|
||||
bandwidthGB: 5,
|
||||
monthlyCostUSD: 30,
|
||||
location: "Oregon, USA",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
companyId: 4,
|
||||
databaseId: 3,
|
||||
provider: "Vultr",
|
||||
serverType: "shared",
|
||||
operatingSystem: "Ubuntu 18.04 LTS",
|
||||
cpu: "AMD Ryzen 2.2 GHz",
|
||||
storageGB: 250,
|
||||
ramGB: 12,
|
||||
bandwidthGB: 8,
|
||||
monthlyCostUSD: 50,
|
||||
location: "Singapore",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
companyId: 5,
|
||||
databaseId: 8,
|
||||
provider: "Linode",
|
||||
serverType: "VPS",
|
||||
operatingSystem: "Debian 10",
|
||||
cpu: "AMD EPYC 2.4 GHz",
|
||||
storageGB: 300,
|
||||
ramGB: 16,
|
||||
bandwidthGB: 6,
|
||||
monthlyCostUSD: 40,
|
||||
location: "Dallas, USA",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
companyId: 6,
|
||||
databaseId: 6,
|
||||
provider: "Hostinger",
|
||||
serverType: "shared",
|
||||
operatingSystem: "CentOS 8",
|
||||
cpu: "Intel Xeon 2.0 GHz",
|
||||
storageGB: 150,
|
||||
ramGB: 6,
|
||||
bandwidthGB: 3,
|
||||
monthlyCostUSD: 15,
|
||||
location: "Lithuania",
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
companyId: 7,
|
||||
databaseId: 7,
|
||||
provider: "Hetzner",
|
||||
serverType: "dedicated",
|
||||
operatingSystem: "Ubuntu 16.04 LTS",
|
||||
cpu: "Intel Xeon 2.2 GHz",
|
||||
storageGB: 400,
|
||||
ramGB: 12,
|
||||
bandwidthGB: 10,
|
||||
monthlyCostUSD: 60,
|
||||
location: "Falkenstein, Germany",
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
companyId: 8,
|
||||
databaseId: 5,
|
||||
provider: "OVH",
|
||||
serverType: "shared",
|
||||
operatingSystem: "Ubuntu 20.04 LTS",
|
||||
cpu: "Intel Xeon 2.3 GHz",
|
||||
storageGB: 100,
|
||||
ramGB: 4,
|
||||
bandwidthGB: 4,
|
||||
monthlyCostUSD: 10,
|
||||
location: "France",
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
companyId: 9,
|
||||
databaseId: 9,
|
||||
provider: "AWS",
|
||||
serverType: "VPS",
|
||||
operatingSystem: "Amazon Linux 2",
|
||||
cpu: "2 vCPUs",
|
||||
storageGB: 40,
|
||||
ramGB: 4,
|
||||
bandwidthGB: 10,
|
||||
monthlyCostUSD: 50,
|
||||
location: "Sydney, Australia",
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
companyId: 10,
|
||||
databaseId: 10,
|
||||
provider: "AWS",
|
||||
serverType: "dedicated",
|
||||
operatingSystem: "Red Hat Enterprise Linux 8",
|
||||
cpu: "4 vCPUs",
|
||||
storageGB: 100,
|
||||
ramGB: 8,
|
||||
bandwidthGB: 20,
|
||||
monthlyCostUSD: 200,
|
||||
location: "Mumbai, India",
|
||||
},
|
||||
];
|
||||
44
src/app/layouts/admin-layout/admin-layout.component.html
Normal file
@@ -0,0 +1,44 @@
|
||||
<div class="wrapper">
|
||||
<div class="sidebar"><app-sidebar></app-sidebar></div>
|
||||
<div class="main-panel">
|
||||
<app-navbar></app-navbar>
|
||||
<router-outlet></router-outlet>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" fixed-plugin">
|
||||
<div class=" show-dropdown" ngbDropdown>
|
||||
<a data-toggle="dropdown" ngbDropdownToggle>
|
||||
<i class=" fa fa-cog fa-2x"> </i>
|
||||
</a>
|
||||
<ul ngbDropdownMenu>
|
||||
<li class=" header-title">Sidebar Background</li>
|
||||
<li class=" adjustments-line">
|
||||
<a class=" switch-trigger background-color" href="javascript:void(0)">
|
||||
<div class=" badge-colors text-center">
|
||||
<span
|
||||
class=" badge filter badge-danger"
|
||||
[ngClass]="{'active':sidebarColor==='red'}" (click)="changeSidebarColor('red')"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class=" badge filter badge-primary"
|
||||
[ngClass]="{'active':sidebarColor==='primary'}" (click)="changeSidebarColor('primary')"
|
||||
>
|
||||
</span>
|
||||
<span class=" badge filter badge-info" [ngClass]="{'active':sidebarColor==='blue'}" (click)="changeSidebarColor('blue')"> </span>
|
||||
<span class=" badge filter badge-success" [ngClass]="{'active':sidebarColor==='green'}" (click)="changeSidebarColor('green')">
|
||||
</span>
|
||||
</div>
|
||||
<div class=" clearfix"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class=" adjustments-line text-center color-change">
|
||||
<span class=" color-label"> LIGHT MODE </span>
|
||||
<span class=" badge light-badge mr-2" (click)="changeDashboardColor('white-content')"> </span>
|
||||
<span class=" badge dark-badge ml-2" (click)="changeDashboardColor('black-content')"> </span>
|
||||
<span class=" color-label"> DARK MODE </span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
24
src/app/layouts/admin-layout/admin-layout.component.spec.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { async, ComponentFixture, TestBed } from "@angular/core/testing";
|
||||
|
||||
import { AdminLayoutComponent } from "./admin-layout.component";
|
||||
|
||||
describe("AdminLayoutComponent", () => {
|
||||
let component: AdminLayoutComponent;
|
||||
let fixture: ComponentFixture<AdminLayoutComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AdminLayoutComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AdminLayoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it("should create", () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
35
src/app/layouts/admin-layout/admin-layout.component.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-admin-layout",
|
||||
templateUrl: "./admin-layout.component.html",
|
||||
styleUrls: ["./admin-layout.component.scss"]
|
||||
})
|
||||
export class AdminLayoutComponent implements OnInit {
|
||||
public sidebarColor: string = "red";
|
||||
|
||||
constructor() {}
|
||||
changeSidebarColor(color){
|
||||
var sidebar = document.getElementsByClassName('sidebar')[0];
|
||||
var mainPanel = document.getElementsByClassName('main-panel')[0];
|
||||
|
||||
this.sidebarColor = color;
|
||||
|
||||
if(sidebar != undefined){
|
||||
sidebar.setAttribute('data',color);
|
||||
}
|
||||
if(mainPanel != undefined){
|
||||
mainPanel.setAttribute('data',color);
|
||||
}
|
||||
}
|
||||
changeDashboardColor(color){
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
if (body && color === 'white-content') {
|
||||
body.classList.add(color);
|
||||
}
|
||||
else if(body.classList.contains('white-content')) {
|
||||
body.classList.remove('white-content');
|
||||
}
|
||||
}
|
||||
ngOnInit() {}
|
||||
}
|
||||
35
src/app/layouts/admin-layout/admin-layout.module.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import { AdminLayoutRoutes } from "./admin-layout.routing";
|
||||
// import { DashboardComponent } from "../../pages/dashboard/dashboard.component";
|
||||
import { CompanyInformationComponent } from "../../pages/company-information/company-information.component";
|
||||
import { CompanyProfileComponent } from "../../pages/company-profile/company-profile.component";
|
||||
import { InvoicesComponent } from "../../pages/invoices/invoices.component";
|
||||
import { PaymentsComponent } from "../../pages/payments/payments.component";
|
||||
import { NotificationsComponent } from "../../pages/notifications/notifications.component";
|
||||
|
||||
import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(AdminLayoutRoutes),
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
HttpClientModule,
|
||||
NgbModule,
|
||||
],
|
||||
declarations: [
|
||||
// DashboardComponent,
|
||||
CompanyInformationComponent,
|
||||
CompanyProfileComponent,
|
||||
InvoicesComponent,
|
||||
PaymentsComponent,
|
||||
NotificationsComponent,
|
||||
],
|
||||
})
|
||||
export class AdminLayoutModule {}
|
||||
20
src/app/layouts/admin-layout/admin-layout.routing.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Routes } from "@angular/router";
|
||||
|
||||
import { DashboardComponent } from "../../pages/dashboard/dashboard.component";
|
||||
import { CompanyInformationComponent } from "../../pages/company-information/company-information.component";
|
||||
import { CompanyProfileComponent } from "../../pages/company-profile/company-profile.component";
|
||||
import { InvoicesComponent } from "../../pages/invoices/invoices.component";
|
||||
import { PaymentsComponent } from "../../pages/payments/payments.component";
|
||||
import { LoginComponent } from "src/app/pages/login/login.component";
|
||||
|
||||
import { NotificationsComponent } from "../../pages/notifications/notifications.component";
|
||||
|
||||
export const AdminLayoutRoutes: Routes = [
|
||||
{ path: "dashboard", component: DashboardComponent },
|
||||
{ path: "company-information", component: CompanyInformationComponent },
|
||||
{ path: "company-profile", component: CompanyProfileComponent },
|
||||
{ path: "invoices", component: InvoicesComponent },
|
||||
{ path: "payments", component: PaymentsComponent },
|
||||
{ path: "notifications", component: NotificationsComponent },
|
||||
{ path: "login", component: LoginComponent}
|
||||
];
|
||||
307
src/app/layouts/auth-layout/auth-layout.component.html
Normal file
@@ -0,0 +1,307 @@
|
||||
<div class="wrapper">
|
||||
<div class="sidebar">
|
||||
<div class="logo">
|
||||
<a
|
||||
href="https://www.creative-tim.com?ref=bda-auth-layout-sidebar-logo"
|
||||
class="simple-text logo-mini"
|
||||
>
|
||||
<div class="logo-img">
|
||||
<img src="./assets/img/angular2-logo-white.png" />
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.creative-tim.com?ref=bda-auth-layout-sidebar-logo"
|
||||
class="simple-text logo-normal"
|
||||
>
|
||||
الإبداعية تيم
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-wrapper">
|
||||
<ul class="nav">
|
||||
<li
|
||||
routerLinkActive="active"
|
||||
*ngFor="let menuItem of menuItems"
|
||||
class="{{ menuItem.class }} nav-item"
|
||||
>
|
||||
<a [routerLink]="[menuItem.path]">
|
||||
<i class="tim-icons {{ menuItem.icon }}"></i>
|
||||
<p>{{ menuItem.rtlTitle }}</p>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main-panel">
|
||||
<nav class="navbar navbar-expand-lg navbar-absolute navbar-transparent">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-wrapper">
|
||||
<div class="navbar-toggle d-inline">
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
(click)="sidebarToggle()"
|
||||
>
|
||||
<span class="navbar-toggler-bar bar1"> </span>
|
||||
<span class="navbar-toggler-bar bar2"> </span>
|
||||
<span class="navbar-toggler-bar bar3"> </span>
|
||||
</button>
|
||||
</div>
|
||||
<a class="navbar-brand" href="javascript:void(0)"> ار تي ال </a>
|
||||
</div>
|
||||
<button
|
||||
aria-label="Toggle navigation"
|
||||
class="navbar-toggler"
|
||||
(click)="collapse()"
|
||||
[attr.aria-expanded]="!isCollapsed"
|
||||
aria-controls="collapseExample"
|
||||
id="navigation"
|
||||
type="button"
|
||||
>
|
||||
<span class="navbar-toggler-bar navbar-kebab"> </span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"> </span>
|
||||
<span class="navbar-toggler-bar navbar-kebab"> </span>
|
||||
</button>
|
||||
<div
|
||||
class="navbar-collapse"
|
||||
[ngbCollapse]="isCollapsed"
|
||||
id="navigation"
|
||||
>
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="search-bar input-group">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
data-target="#searchModal"
|
||||
data-toggle="modal"
|
||||
(click)="open(content)"
|
||||
id="search-button"
|
||||
>
|
||||
<i class="tim-icons icon-zoom-split"> </i>
|
||||
<span class="d-lg-none d-md-block"> بحث </span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" ngbDropdown>
|
||||
<a class="nav-link" data-toggle="dropdown" ngbDropdownToggle>
|
||||
<div class="notification d-none d-lg-block d-xl-block"></div>
|
||||
<i class="tim-icons icon-sound-wave"> </i>
|
||||
<p class="d-lg-none">إخطارات</p>
|
||||
</a>
|
||||
<ul class="dropdown-menu-right dropdown-navbar" ngbDropdownMenu>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
ورد مايك جون على بريدك الإلكتروني
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
لديك 5 مهام أخرى
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
صديقك مايكل في المدينة
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
إشعار آخر
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
واحدة أخرى
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item" ngbDropdown>
|
||||
<a class="nav-link" data-toggle="dropdown" ngbDropdownToggle>
|
||||
<div class="photo">
|
||||
<img alt="Profile Photo" src="assets/img/anime3.png" />
|
||||
</div>
|
||||
<b class="caret d-none d-lg-block d-xl-block"> </b>
|
||||
<p class="d-lg-none">الخروج</p>
|
||||
</a>
|
||||
<ul class="dropdown-navbar" ngbDropdownMenu>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
الملف الشخصي
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
الإعدادات
|
||||
</a>
|
||||
</li>
|
||||
<li class="dropdown-divider"></li>
|
||||
<li class="nav-link">
|
||||
<a class="nav-item" href="javascript:void(0)" ngbDropdownItem>
|
||||
الخروج
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="separator d-lg-none"></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<router-outlet></router-outlet>
|
||||
<footer class="footer">
|
||||
<div class="container-fluid">
|
||||
<ul class="nav">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link"
|
||||
href="https://www.creative-tim.com?ref=bda-auth-layout-footer"
|
||||
>
|
||||
تيم الإبداعية
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link"
|
||||
href="https://www.creative-tim.com/about-us?ref=bda-auth-layout-footer"
|
||||
>
|
||||
معلومات عنا
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link"
|
||||
href="http://blog.creative-tim.com?ref=bda-auth-layout-footer"
|
||||
>
|
||||
مدونة
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="copyright">
|
||||
© {{ test | date : "yyyy" }} مصنوع من
|
||||
<i class="tim-icons icon-heart-2"> </i> بواسطة
|
||||
<a
|
||||
href="https://www.creative-tim.com?ref=bda-auth-layout-footer"
|
||||
target="_blank"
|
||||
>
|
||||
تيم الإبداعية
|
||||
</a>
|
||||
من أجل شبكة أفضل.
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fixed-plugin">
|
||||
<div class="show-dropdown" ngbDropdown>
|
||||
<a data-toggle="dropdown" ngbDropdownToggle>
|
||||
<i class="fa fa-cog fa-2x"> </i>
|
||||
</a>
|
||||
<ul ngbDropdownMenu>
|
||||
<li class="header-title">خلفية الشريط الجانبي</li>
|
||||
<li class="adjustments-line">
|
||||
<a class="switch-trigger background-color" href="javascript:void(0)">
|
||||
<div class="badge-colors text-center">
|
||||
<span
|
||||
class="badge filter badge-danger"
|
||||
[ngClass]="{ active: sidebarColor === 'red' }"
|
||||
(click)="changeSidebarColor('red')"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="badge filter badge-primary"
|
||||
data-color="primary"
|
||||
[ngClass]="{ active: sidebarColor === 'primary' }"
|
||||
(click)="changeSidebarColor('primary')"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="badge filter badge-info"
|
||||
[ngClass]="{ active: sidebarColor === 'blue' }"
|
||||
(click)="changeSidebarColor('blue')"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="badge filter badge-success"
|
||||
[ngClass]="{ active: sidebarColor === 'green' }"
|
||||
(click)="changeSidebarColor('green')"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
</a>
|
||||
</li>
|
||||
<li class="adjustments-line text-center color-change">
|
||||
<span class="color-label"> وضع الضوء </span>
|
||||
<span
|
||||
class="badge light-badge mr-2"
|
||||
(click)="changeDashboardColor('white-content')"
|
||||
>
|
||||
</span>
|
||||
<span
|
||||
class="badge dark-badge ml-2"
|
||||
(click)="changeDashboardColor('black-content')"
|
||||
>
|
||||
</span>
|
||||
<span class="color-label"> وضع الظلام</span>
|
||||
</li>
|
||||
<li class="button-container">
|
||||
<a
|
||||
class="btn btn-primary btn-block btn-round"
|
||||
href="https://www.creative-tim.com/product/black-dashboard-angular?ref=bda-auth-layout-fixed-plugin"
|
||||
target="_blank"
|
||||
>
|
||||
التحميل الان
|
||||
</a>
|
||||
<a
|
||||
class="btn btn-default btn-block btn-round"
|
||||
href="https://demos.creative-tim.com/black-dashboard-angular/#/documentation/tutorial?ref=bda-auth-layout-fixed-plugin"
|
||||
target="_blank"
|
||||
>
|
||||
كابل بيانات
|
||||
</a>
|
||||
</li>
|
||||
<li class="header-title">شكرا لك على 95 سهم!</li>
|
||||
<li class="button-container text-center">
|
||||
<button class="btn btn-round btn-info" id="twitter">
|
||||
<i class="fab fa-twitter"> </i> · 45
|
||||
</button>
|
||||
<button class="btn btn-round btn-info" id="facebook">
|
||||
<i class="fab fa-facebook-f"> </i> · 50
|
||||
</button>
|
||||
<br />
|
||||
|
||||
<br />
|
||||
|
||||
<a
|
||||
aria-label="Star ntkme/github-buttons on GitHub"
|
||||
class="github-button"
|
||||
data-icon="octicon-star"
|
||||
data-show-count="true"
|
||||
data-size="large"
|
||||
href="https://github.com/creativetimofficial/black-dashboard-angular?ref=bda-auth-layout-fixed-plugin"
|
||||
>
|
||||
نجمة
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #content let-modal>
|
||||
<div class="modal-header">
|
||||
<input
|
||||
class="form-control"
|
||||
id="inlineFormInputGroup"
|
||||
placeholder="بحث"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="close"
|
||||
data-dismiss="modal"
|
||||
type="button"
|
||||
(click)="modal.dismiss('Cross click')"
|
||||
>
|
||||
<i class="tim-icons icon-simple-remove"> </i>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
25
src/app/layouts/auth-layout/auth-layout.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthLayoutComponent } from './auth-layout.component';
|
||||
|
||||
describe('AuthLayoutComponent', () => {
|
||||
let component: AuthLayoutComponent;
|
||||
let fixture: ComponentFixture<AuthLayoutComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AuthLayoutComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AuthLayoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
212
src/app/layouts/auth-layout/auth-layout.component.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { ROUTES } from '../../components/sidebar/sidebar.component';
|
||||
import { NgbModal, ModalDismissReasons } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
@Component({
|
||||
selector: 'app-auth-layout',
|
||||
templateUrl: './auth-layout.component.html',
|
||||
styleUrls: ['./auth-layout.component.scss']
|
||||
})
|
||||
export class AuthLayoutComponent implements OnInit, OnDestroy {
|
||||
public menuItems: any[];
|
||||
test: Date = new Date();
|
||||
closeResult: string;
|
||||
public sidebarColor: string = "red";
|
||||
public isCollapsed = true;
|
||||
mobile_menu_visible: any = 0;
|
||||
private toggleButton: any;
|
||||
private sidebarVisible: boolean;
|
||||
|
||||
constructor(private router: Router, private modalService: NgbModal) { }
|
||||
|
||||
changeSidebarColor(color){
|
||||
var sidebar = document.getElementsByClassName('sidebar')[0];
|
||||
var mainPanel = document.getElementsByClassName('main-panel')[0];
|
||||
|
||||
this.sidebarColor = color;
|
||||
|
||||
if(sidebar != undefined){
|
||||
sidebar.setAttribute('data',color);
|
||||
}
|
||||
if(mainPanel != undefined){
|
||||
mainPanel.setAttribute('data',color);
|
||||
}
|
||||
}
|
||||
changeDashboardColor(color){
|
||||
var body = document.getElementsByTagName('body')[0];
|
||||
if (body && color === 'white-content') {
|
||||
body.classList.add(color);
|
||||
}
|
||||
else if(body.classList.contains('white-content')) {
|
||||
body.classList.remove('white-content');
|
||||
}
|
||||
}
|
||||
// function that adds color white/transparent to the navbar on resize (this is for the collapse)
|
||||
updateColor = () => {
|
||||
var navbar = document.getElementsByClassName('navbar')[0];
|
||||
if (window.innerWidth < 993 && !this.isCollapsed) {
|
||||
navbar.classList.add('bg-white');
|
||||
navbar.classList.remove('navbar-transparent');
|
||||
} else {
|
||||
navbar.classList.remove('bg-white');
|
||||
navbar.classList.add('navbar-transparent');
|
||||
}
|
||||
};
|
||||
ngOnInit() {
|
||||
var navbar = document.getElementsByClassName('navbar')[0];
|
||||
|
||||
window.addEventListener("resize", this.updateColor);
|
||||
this.toggleButton = navbar.getElementsByClassName("navbar-toggler")[0];
|
||||
this.router.events.subscribe(event => {
|
||||
this.sidebarClose();
|
||||
var $layer: any = document.getElementsByClassName("close-layer")[0];
|
||||
if ($layer) {
|
||||
$layer.remove();
|
||||
this.mobile_menu_visible = 0;
|
||||
}
|
||||
});
|
||||
this.menuItems = ROUTES.filter(menuItem => menuItem);
|
||||
// on this page, we need on the body tag the classes .rtl and .menu-on-right
|
||||
document.body.classList.add("rtl", "menu-on-right");
|
||||
// we also need the rtl bootstrap
|
||||
// so we add it dynamically to the head
|
||||
let head = document.head;
|
||||
let link = document.createElement("link");
|
||||
link.type = "text/css";
|
||||
link.rel = "stylesheet";
|
||||
link.id = "rtl-id";
|
||||
link.href =
|
||||
"https://cdnjs.cloudflare.com/ajax/libs/bootstrap-rtl/3.4.0/css/bootstrap-rtl.css";
|
||||
head.appendChild(link);
|
||||
|
||||
}
|
||||
ngOnDestroy() {
|
||||
// when we exit this page, we need to delete the classes .rtl and .menu-on-right
|
||||
// from the body tag
|
||||
document.body.classList.remove("rtl", "menu-on-right");
|
||||
// we also need to delete the rtl bootstrap, so it does not break the other pages
|
||||
// that do not make use of rtl
|
||||
document.getElementById("rtl-id").remove();
|
||||
}
|
||||
collapse() {
|
||||
this.isCollapsed = !this.isCollapsed;
|
||||
const navbar = document.getElementsByTagName("nav")[0];
|
||||
if (!this.isCollapsed) {
|
||||
navbar.classList.remove("navbar-transparent");
|
||||
navbar.classList.add("bg-white");
|
||||
} else {
|
||||
navbar.classList.add("navbar-transparent");
|
||||
navbar.classList.remove("bg-white");
|
||||
}
|
||||
}
|
||||
|
||||
sidebarOpen() {
|
||||
const toggleButton = this.toggleButton;
|
||||
const mainPanel = <HTMLElement>(
|
||||
document.getElementsByClassName("main-panel")[0]
|
||||
);
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
if (window.innerWidth < 991) {
|
||||
mainPanel.style.position = "fixed";
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
toggleButton.classList.add("toggled");
|
||||
}, 500);
|
||||
|
||||
html.classList.add("nav-open");
|
||||
|
||||
this.sidebarVisible = true;
|
||||
}
|
||||
sidebarClose() {
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
this.toggleButton.classList.remove("toggled");
|
||||
const mainPanel = <HTMLElement>(
|
||||
document.getElementsByClassName("main-panel")[0]
|
||||
);
|
||||
|
||||
if (window.innerWidth < 991) {
|
||||
setTimeout(function() {
|
||||
mainPanel.style.position = "";
|
||||
}, 500);
|
||||
}
|
||||
this.sidebarVisible = false;
|
||||
html.classList.remove("nav-open");
|
||||
}
|
||||
sidebarToggle() {
|
||||
// const toggleButton = this.toggleButton;
|
||||
// const html = document.getElementsByTagName('html')[0];
|
||||
var $toggle = document.getElementsByClassName("navbar-toggler")[0];
|
||||
|
||||
if (this.sidebarVisible === false) {
|
||||
this.sidebarOpen();
|
||||
} else {
|
||||
this.sidebarClose();
|
||||
}
|
||||
const html = document.getElementsByTagName("html")[0];
|
||||
|
||||
if (this.mobile_menu_visible == 1) {
|
||||
// $('html').removeClass('nav-open');
|
||||
html.classList.remove("nav-open");
|
||||
if ($layer) {
|
||||
$layer.remove();
|
||||
}
|
||||
setTimeout(function() {
|
||||
$toggle.classList.remove("toggled");
|
||||
}, 400);
|
||||
|
||||
this.mobile_menu_visible = 0;
|
||||
} else {
|
||||
setTimeout(function() {
|
||||
$toggle.classList.add("toggled");
|
||||
}, 430);
|
||||
|
||||
var $layer = document.createElement("div");
|
||||
$layer.setAttribute("class", "close-layer");
|
||||
|
||||
if (html.querySelectorAll(".main-panel")) {
|
||||
document.getElementsByClassName("main-panel")[0].appendChild($layer);
|
||||
} else if (html.classList.contains("off-canvas-sidebar")) {
|
||||
document
|
||||
.getElementsByClassName("wrapper-full-page")[0]
|
||||
.appendChild($layer);
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
$layer.classList.add("visible");
|
||||
}, 100);
|
||||
|
||||
$layer.onclick = function() {
|
||||
//asign a function
|
||||
html.classList.remove("nav-open");
|
||||
this.mobile_menu_visible = 0;
|
||||
$layer.classList.remove("visible");
|
||||
setTimeout(function() {
|
||||
$layer.remove();
|
||||
$toggle.classList.remove("toggled");
|
||||
}, 400);
|
||||
}.bind(this);
|
||||
|
||||
html.classList.add("nav-open");
|
||||
this.mobile_menu_visible = 1;
|
||||
}
|
||||
}
|
||||
open(content) {
|
||||
this.modalService.open(content, {windowClass: 'modal-search'}).result.then((result) => {
|
||||
this.closeResult = `Closed with: ${result}`;
|
||||
}, (reason) => {
|
||||
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
|
||||
});
|
||||
}
|
||||
|
||||
private getDismissReason(reason: any): string {
|
||||
if (reason === ModalDismissReasons.ESC) {
|
||||
return 'by pressing ESC';
|
||||
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
|
||||
return 'by clicking on a backdrop';
|
||||
} else {
|
||||
return `with: ${reason}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/app/layouts/auth-layout/auth-layout.module.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { AuthLayoutRoutes } from './auth-layout.routing';
|
||||
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { HttpClientModule } from "@angular/common/http";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(AuthLayoutRoutes),
|
||||
FormsModule,
|
||||
HttpClientModule,
|
||||
NgbModule
|
||||
],
|
||||
declarations: [
|
||||
|
||||
]
|
||||
})
|
||||
export class AuthLayoutModule { }
|
||||
5
src/app/layouts/auth-layout/auth-layout.routing.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Routes } from "@angular/router";
|
||||
|
||||
export const AuthLayoutRoutes: Routes = [
|
||||
// { path: 'rtl', component: RtlComponent },
|
||||
];
|
||||
26
src/app/models/company.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
export interface CompanyModel {
|
||||
id: number;
|
||||
name: string;
|
||||
username: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
image: string;
|
||||
description: string;
|
||||
address: string;
|
||||
city: string;
|
||||
stagingUrl: string;
|
||||
productionUrl: string;
|
||||
}
|
||||
|
||||
// export interface CompanyProfileModel {
|
||||
// id: number;
|
||||
// username: string;
|
||||
// name: string;
|
||||
// email: string;
|
||||
// phone: string;
|
||||
// description: string;
|
||||
// address: string;
|
||||
// city: string;
|
||||
// stagingUrl: string;
|
||||
// productionUrl: string;
|
||||
// }
|
||||
12
src/app/models/database-info.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface DatabaseInfoModel {
|
||||
id: number;
|
||||
companyId: number;
|
||||
serverId: number;
|
||||
databaseName: string;
|
||||
databaseType: 'MySQL' | 'PostgreSQL' | 'MongoDB' | 'SQLite';
|
||||
bandwidthGB: number;
|
||||
username: string;
|
||||
password: string;
|
||||
host: string;
|
||||
port: number;
|
||||
}
|
||||
12
src/app/models/hosting-info.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface HostingInfoModel {
|
||||
id: number;
|
||||
companyId: number;
|
||||
provider: string;
|
||||
serverType: 'shared' | 'VPS' | 'dedicated';
|
||||
diskSpaceGB: number;
|
||||
bandwidthGB: number;
|
||||
username: string;
|
||||
password: string;
|
||||
serverLocation: string;
|
||||
expirationDate: Date;
|
||||
}
|
||||
18
src/app/models/invoice.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export interface InvoiceModel {
|
||||
id: number; // unique ID for the invoice
|
||||
invoiceNumber: string; // invoice number
|
||||
companyId: number; // ID of the company to which this invoice belongs
|
||||
dateIssued: Date; // date the invoice was issued
|
||||
dueDate: Date; // date the invoice is due
|
||||
amount: string; // total amount due
|
||||
currency: string; // currency in which the invoice is billed
|
||||
status: 'pending' | 'paid' | 'overdue'; // current status of the invoice
|
||||
services: InvoiceService[]; // an array of individual items on the invoice
|
||||
}
|
||||
|
||||
export interface InvoiceService {
|
||||
description: string; // description of the service
|
||||
service: number; // number of service rendered
|
||||
unitPrice: number; // price of each unit service
|
||||
total: number; // total cost of the services
|
||||
}
|
||||
9
src/app/models/notification.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export interface NotificationModel {
|
||||
header: string;
|
||||
source: string;
|
||||
time: string;
|
||||
message: string;
|
||||
user_id?: number;
|
||||
date: Date;
|
||||
timestamp: string;
|
||||
}
|
||||
12
src/app/models/payment.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
export interface PaymentModel {
|
||||
id: number; // unique ID for the payment
|
||||
invoiceId: number; // ID of the invoice to which this payment applies
|
||||
companyId: number; // ID of the company to which this payment belongs
|
||||
invoiceNumber: string; // invoice number
|
||||
paymentNumber: string; // unique payment number
|
||||
paymentDate: Date; // date the payment was made
|
||||
amount: string; // amount of the payment
|
||||
currency: string; // currency in which the payment was made
|
||||
method: "credit card" | "bank transfer" | "cash" | "cheque"; // payment method used
|
||||
status: "completed" | "pending" | "failed"; // status of the payment
|
||||
}
|
||||
14
src/app/models/server-info.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
export interface ServerInfoModel {
|
||||
id: number;
|
||||
companyId: number;
|
||||
databaseId: number;
|
||||
provider: string;
|
||||
serverType: 'shared' | 'VPS' | 'dedicated';
|
||||
operatingSystem: string;
|
||||
cpu: string;
|
||||
storageGB: number;
|
||||
ramGB: number;
|
||||
bandwidthGB: number;
|
||||
monthlyCostUSD: number;
|
||||
location: string;
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
<div class="content ml-2">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card" style="padding: 20px">
|
||||
<div class="card-header">
|
||||
<h5 class="title">Company Information</h5>
|
||||
</div>
|
||||
<div class="card-body all-icons">
|
||||
<div class="card-child-content">
|
||||
<div class="font-icon-list box mr-3">
|
||||
<div class="font-icon-detail px-3">
|
||||
<i class="bi bi-person-vcard-fill"></i>
|
||||
<h2 class="fw-bolder">Company Information</h2>
|
||||
</div>
|
||||
<div class="card-child-contentOne">
|
||||
<div>
|
||||
<p><strong>Name:</strong> {{ company.name }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Email:</strong> {{ company.email }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Company Phone:</strong> {{ company.phone }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Address:</strong> {{ company.phone }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Staging URL:</strong>
|
||||
<a> {{ company.stagingUrl }}</a>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Production URL:</strong>
|
||||
<a> {{ company.productionUrl }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-icon-list box">
|
||||
<div class="font-icon-detail px-3">
|
||||
<i class="bi bi-pc-display"></i>
|
||||
<h2 class="fw-bolder">Hosting Information</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-child-contentTwo">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Hosting Provider:</strong>
|
||||
{{ hostingInfo.provider }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Server Type:</strong>
|
||||
<span class="text-capitalize">{{
|
||||
hostingInfo.serverType
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong> Disk Space (GB) :</strong>
|
||||
{{ hostingInfo.diskSpaceGB }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong> Bandwidth (GB) :</strong>
|
||||
{{ hostingInfo.bandwidthGB }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Username:</strong> {{ hostingInfo.username }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p><strong>Password:</strong> {{ hostingInfo.password }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Server Location: </strong>
|
||||
{{ hostingInfo.serverLocation }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Expiration Date: </strong>
|
||||
{{ timeDiff }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-icon-list box">
|
||||
<div class="font-icon-detail px-3">
|
||||
<i class="bi bi-hdd-rack"></i>
|
||||
<h2 class="fw-bolder">Server Information</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-child-contentThree">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Server Type:</strong>
|
||||
<span class="text-capitalize">{{
|
||||
serverInfo.serverType
|
||||
}}</span>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Operating System:</strong>
|
||||
{{ serverInfo.operatingSystem }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>CPU:</strong> PROCESSOR</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Storage (GB):</strong> {{ serverInfo.storageGB }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>RAM (GB): </strong> {{ serverInfo.ramGB }}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<strong>Bandwidth (GB): </strong>
|
||||
{{ serverInfo.bandwidthGB }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<strong>Monthly Cost (USD): </strong>
|
||||
{{ serverInfo.monthlyCostUSD }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Location: </strong> {{ serverInfo.location }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-icon-list box">
|
||||
<div class="font-icon-detail px-3">
|
||||
<i class="bi bi-database"></i>
|
||||
<h2 class="fw-bolder">Database Information</h2>
|
||||
</div>
|
||||
|
||||
<div class="card-child-contentFour">
|
||||
<div>
|
||||
<p>
|
||||
<strong>Database Name:</strong>
|
||||
{{ databaseInfo.databaseName }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Database Type:</strong>
|
||||
{{ databaseInfo.databaseType }}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<strong>Bandwidth: </strong>
|
||||
{{ databaseInfo.bandwidthGB }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p><strong>Username:</strong> {{ databaseInfo.username }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p><strong>Password: </strong> {{ databaseInfo.password }}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<strong>Database Host: </strong> {{ databaseInfo.host }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
<strong>Database Port Number: </strong>
|
||||
{{ databaseInfo.port }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-telephone"></i>
|
||||
<p><strong>Phone:</strong> PHONE</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-journal-richtext"></i>
|
||||
<p><strong>Description:</strong> About Company</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-pin-map"></i>
|
||||
<p><strong>Address:</strong> ADDRESS</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-buildings"></i>
|
||||
<p><strong>City:</strong> CITY</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-link-45deg"></i>
|
||||
<p>
|
||||
<strong>Staging URL:</strong>
|
||||
<a href="#" target="_blank"> COMPANY URL </a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="font-icon-list col-md-4 col-sm-6 col-xs-12">
|
||||
<div class="font-icon-detail">
|
||||
<i class="bi bi-link-45deg"></i>
|
||||
<p>
|
||||
<strong>Production URL:</strong>
|
||||
<a href="#" target="_blank"> COMPANY URL </a>
|
||||
</p>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
.card-child-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-gap: 1rem;
|
||||
padding: 1rem;
|
||||
.box {
|
||||
border-radius: 10px !important;
|
||||
box-shadow: inset 5px 5px 5px rgba(0, 0, 0, 0.05),
|
||||
inset -5px -5px 5px rgba(255, 255, 255, 0.05),
|
||||
5px 5px 5px rgba(0, 0, 0, 0.05), -5px -5px 5px rgba(255, 255, 255, 0.05) !important;
|
||||
}
|
||||
|
||||
.card-child-contentOne,
|
||||
.card-child-contentTwo,
|
||||
.card-child-contentThree,
|
||||
.card-child-contentFour {
|
||||
padding: 15px;
|
||||
|
||||
strong {
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CompanyInformationComponent } from './company-information.component';
|
||||
|
||||
describe('CompanyInformationComponent', () => {
|
||||
let component: CompanyInformationComponent;
|
||||
let fixture: ComponentFixture<CompanyInformationComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CompanyInformationComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CompanyInformationComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { CompanyModel } from "../../models/company";
|
||||
import { HostingInfoModel } from "../../models/hosting-info";
|
||||
import { DatabaseInfoModel } from "../../models/database-info";
|
||||
import { ServerInfoModel } from "../../models/server-info";
|
||||
import { CompanyService } from "../../services/company.service";
|
||||
import { HostingInfoService } from "../../services/hosting-info.service";
|
||||
import { DatabaseInfoService } from "../../services/database-info.service";
|
||||
import { ServerInfoService } from "../../services/server-info.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-company-information",
|
||||
templateUrl: "./company-information.component.html",
|
||||
styleUrls: ["./company-information.component.scss"],
|
||||
})
|
||||
export class CompanyInformationComponent implements OnInit {
|
||||
company: CompanyModel;
|
||||
hostingInfo: HostingInfoModel;
|
||||
databaseInfo: DatabaseInfoModel;
|
||||
serverInfo: ServerInfoModel;
|
||||
companyLocalStorage: any;
|
||||
timeDiff: any;
|
||||
|
||||
constructor(
|
||||
private companyService: CompanyService,
|
||||
private hostingInfoService: HostingInfoService,
|
||||
private databaseInfoService: DatabaseInfoService,
|
||||
private serverInfoService: ServerInfoService
|
||||
) {
|
||||
this.companyService.getCompanyById(1).subscribe((company) => {
|
||||
this.company = company;
|
||||
console.log("Company: ", this.company);
|
||||
});
|
||||
|
||||
this.hostingInfoService.getHostingInfoById(2).subscribe((hostingInfo) => {
|
||||
this.hostingInfo = hostingInfo;
|
||||
console.log("Hosting Info: ", this.hostingInfo);
|
||||
|
||||
this.timeDiff = this.calculateTimeDiff(this.hostingInfo.expirationDate);
|
||||
console.log("Time Diff: ", this.timeDiff);
|
||||
});
|
||||
|
||||
this.databaseInfoService
|
||||
.getDatabaseInfoById(1)
|
||||
.subscribe((databaseInfo) => {
|
||||
this.databaseInfo = databaseInfo;
|
||||
console.log("Database Info: ", this.databaseInfo);
|
||||
});
|
||||
|
||||
this.serverInfoService.getServerInfoById(1).subscribe((serverInfo) => {
|
||||
this.serverInfo = serverInfo;
|
||||
console.log("Server Info: ", this.serverInfo);
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
// Calculate time difference between current time and expiration time
|
||||
calculateTimeDiff(date: any) {
|
||||
const currentDate = new Date();
|
||||
const hostingInfoDate = new Date(date);
|
||||
const diff = hostingInfoDate.getTime() - currentDate.getTime();
|
||||
const resultInMinutes = Math.round(diff / 60000);
|
||||
const resultInHours = Math.round(diff / 3600000);
|
||||
const resultInDays = Math.round(diff / 86400000);
|
||||
const resultInWeeks = Math.round(diff / 604800000);
|
||||
const resultInMonths = Math.round(diff / 2628000000);
|
||||
const resultInYears = Math.round(diff / 31536000000);
|
||||
|
||||
if (resultInMinutes < 60) {
|
||||
return resultInMinutes + " minutes left";
|
||||
} else if (resultInHours < 24) {
|
||||
return resultInHours + " hours left";
|
||||
} else if (resultInDays < 7) {
|
||||
return resultInDays + " days left";
|
||||
} else if (resultInWeeks < 4) {
|
||||
return resultInWeeks + " weeks left";
|
||||
} else if (resultInMonths < 12) {
|
||||
return resultInMonths + " months left";
|
||||
} else {
|
||||
return resultInYears + " years left";
|
||||
}
|
||||
}
|
||||
}
|
||||
443
src/app/pages/company-profile/company-profile.component.html
Normal file
@@ -0,0 +1,443 @@
|
||||
<div class="companyProfile content">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header"><h5 class="title">Edit Profile</h5></div>
|
||||
<div class="card-body companyProfileBody">
|
||||
<form
|
||||
(ngSubmit)="updateInfo()"
|
||||
[formGroup]="updateInfoForm"
|
||||
novalidate
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group mb-5">
|
||||
<div
|
||||
class="institutionDashboard__editInfoFormGroup input-group inputField__uploadFile"
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
name="companyLogo"
|
||||
|
||||
style="display: none"
|
||||
id="avatar-image"
|
||||
accept="image/*"
|
||||
(change)="onFileChange($event)"
|
||||
/>
|
||||
<label
|
||||
for="avatar-image"
|
||||
style="
|
||||
background: linear-gradient(
|
||||
rgb(72, 0, 72, 0.8),
|
||||
rgb(192, 72, 72, 0.8)
|
||||
); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
|
||||
background-size: cover;
|
||||
border-radius: 50%;
|
||||
padding: 2px;
|
||||
width: 90px;
|
||||
height: 90px;
|
||||
filter: drop-shadow(2px 4px 6px black);
|
||||
"
|
||||
>
|
||||
<!-- <img
|
||||
class="image-avatar"
|
||||
style="
|
||||
height: 85px;
|
||||
width: 85px;
|
||||
border-radius: 50%;
|
||||
"
|
||||
[src]="imgSrc ? imgSrc : institutionData.image"
|
||||
alt="avatar"
|
||||
/> -->
|
||||
|
||||
<img
|
||||
class="image-avatar"
|
||||
style="height: 85px; width: 85px; border-radius: 50%"
|
||||
[src]="imgSrc"
|
||||
alt="avatar"
|
||||
/>
|
||||
<div
|
||||
class="upload__icon"
|
||||
style="
|
||||
position: absolute;
|
||||
left: 32%;
|
||||
bottom: 24%;
|
||||
color: white;
|
||||
filter: opacity(0.85);
|
||||
"
|
||||
>
|
||||
<i
|
||||
class="bi bi-upload fw-bolder"
|
||||
style="font-size: 2.2rem"
|
||||
></i>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyLogo.touched &&
|
||||
formControls.companyLogo.invalid
|
||||
"
|
||||
class="alert alert-danger"
|
||||
>
|
||||
<div *ngIf="formControls.companyLogo.errors?.required">
|
||||
Image file is required
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="imgFormatError"
|
||||
class="alert alert-danger"
|
||||
>
|
||||
<div
|
||||
id="imageError"
|
||||
aria-live="assertive"
|
||||
style="color: crimson; font-weight: 700"
|
||||
>
|
||||
File type not supported.
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="fileSizeError">
|
||||
<div
|
||||
id="imageError"
|
||||
style="color: crimson; font-weight: 700"
|
||||
>
|
||||
File size must be less than 2 MB.
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 pr-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyName"> Company (disabled) </label>
|
||||
<input
|
||||
class="form-control"
|
||||
disabled=""
|
||||
id="companyName"
|
||||
type="text"
|
||||
formControlName="companyName"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 px-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyUsername"> Username </label>
|
||||
<input
|
||||
class="form-control"
|
||||
disabled=""
|
||||
type="text"
|
||||
id="companyUsername"
|
||||
formControlName="companyUsername"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 pr-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyName"> Company Name </label>
|
||||
<input
|
||||
id="companyName"
|
||||
class="form-control"
|
||||
placeholder="Company"
|
||||
type="text"
|
||||
formControlName="companyName"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyName.touched &&
|
||||
formControls.companyName.errors?.minlength
|
||||
"
|
||||
>
|
||||
<div id="instituionNameError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Company Name must be at least 6 characters</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyName.errors?.required &&
|
||||
formControls.companyName?.touched
|
||||
"
|
||||
>
|
||||
<div id="institutionNameError" aria-live="assertive">
|
||||
<i class="bi bi-x"></i>
|
||||
<span>Company Name Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 pl-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyEmail"> Email Address </label>
|
||||
<input
|
||||
id="companyEmail"
|
||||
class="form-control"
|
||||
placeholder="Company Email"
|
||||
type="email"
|
||||
formControlName="companyEmail"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error mt-1">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyEmail.invalid &&
|
||||
(formControls.companyEmail.dirty ||
|
||||
formControls.companyEmail.touched)
|
||||
"
|
||||
>
|
||||
<div id="emailError" aria-live="assertive">
|
||||
<i class="bi bi-x"> </i>
|
||||
<span>Email Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="formControls.companyEmail.errors?.pattern"
|
||||
>
|
||||
<div id="emailError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Please enter a valid email</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="companyAddress"> Enter Address </label>
|
||||
<input
|
||||
class="form-control"
|
||||
placeholder="Company Address"
|
||||
type="text"
|
||||
id="companyAddress"
|
||||
formControlName="companyAddress"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyAddress.touched &&
|
||||
formControls.companyAddress.errors?.minlength
|
||||
"
|
||||
>
|
||||
<div id="addressError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Company Address must be at least 6 characters</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyAddress.invalid &&
|
||||
(formControls.companyAddress.dirty ||
|
||||
formControls.companyAddress.touched)
|
||||
"
|
||||
>
|
||||
<div id="addressError" aria-live="assertive">
|
||||
<i class="bi bi-x"></i>
|
||||
<span>Company Address Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 pr-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyPhone">Phone </label>
|
||||
<input
|
||||
class="form-control"
|
||||
placeholder="Company Phone Number"
|
||||
type="text"
|
||||
id="companyPhone"
|
||||
formControlName="companyPhone"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error mt-1">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyPhone.errors?.required &&
|
||||
formControls.companyPhone?.touched
|
||||
"
|
||||
class="alert alert-danger"
|
||||
>
|
||||
<div id="phoneNumberError" aria-live="assertive">
|
||||
<i class="bi bi-x"> </i>
|
||||
<span>Phone Number Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="formControls.companyPhone.errors?.minlength"
|
||||
>
|
||||
<div id="phoneNumberError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Phone number must be at least 11 characters</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="formControls.companyPhone.errors?.pattern"
|
||||
>
|
||||
<div id="phoneNumberError" aria-live="assertive">
|
||||
<i class="bi bi-x"> </i>
|
||||
<span
|
||||
>Please enter a valid phone number (e.g.
|
||||
090321...)</span
|
||||
>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 pl-md-1">
|
||||
<div class="form-group">
|
||||
<label for="companyCity"> City </label>
|
||||
<input
|
||||
class="form-control"
|
||||
placeholder="City"
|
||||
type="text"
|
||||
id="companyCity"
|
||||
formControlName="companyCity"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyCity.touched &&
|
||||
formControls.companyCity.errors?.minlength
|
||||
"
|
||||
>
|
||||
<div id="addressError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Company City must be at least 6 characters</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyCity.invalid &&
|
||||
(formControls.companyCity.dirty ||
|
||||
formControls.companyCity.touched)
|
||||
"
|
||||
>
|
||||
<div id="addressError" aria-live="assertive">
|
||||
<i class="bi bi-x"></i>
|
||||
<span>Company City Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="form-group">
|
||||
<label for="companyDescription"> About Company </label>
|
||||
<textarea
|
||||
class="form-control"
|
||||
placeholder="Company description"
|
||||
id="companyDescription"
|
||||
rows="4"
|
||||
formControlName="companyDescription"
|
||||
>
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="companyEditForm--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyDescription.touched &&
|
||||
formControls.companyDescription.errors?.minlength
|
||||
"
|
||||
>
|
||||
<div id="descError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>
|
||||
Institution Description must be at least 10 characters
|
||||
</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyDescription.errors?.required &&
|
||||
formControls.companyDescription?.touched
|
||||
"
|
||||
>
|
||||
<div id="descError" aria-live="assertive">
|
||||
<i class="bi bi-x"></i>
|
||||
<span>Company Description Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="updateSaveBtn">
|
||||
<button class="btn btn-fill btn-save" type="submit">
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card card-user">
|
||||
<div class="card-body">
|
||||
<p class="card-text"></p>
|
||||
<div class="author">
|
||||
<div class="block block-one"></div>
|
||||
<div class="block block-two"></div>
|
||||
<div class="block block-three"></div>
|
||||
<div class="block block-four"></div>
|
||||
<a href="javascript:void(0)">
|
||||
<img alt="..." class="avatar" src="assets/img/emilyz.jpg" />
|
||||
|
||||
<h5 class="title">Mike Andrew</h5>
|
||||
</a>
|
||||
<p class="description">Ceo/Co-Founder</p>
|
||||
</div>
|
||||
<div class="card-description">
|
||||
Do not be scared of the truth because we need to restart the human
|
||||
foundation in truth And I love you like Kanye loves Kanye I love
|
||||
Rick Owens’ bed design but the back is...
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="button-container">
|
||||
<button class="btn btn-icon btn-round btn-facebook" href="#">
|
||||
<i class="bi bi-facebook"> </i>
|
||||
</button>
|
||||
<button class="btn btn-icon btn-round btn-twitter" href="#">
|
||||
<i class="bi bi-twitter"> </i>
|
||||
</button>
|
||||
<button class="btn btn-icon btn-round btn-linkedin" href="#">
|
||||
<i class="bi bi-linkedin"> </i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
169
src/app/pages/company-profile/company-profile.component.scss
Normal file
@@ -0,0 +1,169 @@
|
||||
.companyProfile {
|
||||
.title {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.companyProfileBody {
|
||||
form {
|
||||
|
||||
|
||||
.inputField__uploadFile {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
i {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.institutionDashboard__editInfoFormGroup {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
// Input
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
border: 2px solid #cccccc;
|
||||
border-radius: 10px !important;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: -webkit-fill-available;
|
||||
outline: none;
|
||||
resize: none;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
border: 2px solid #cccccc;
|
||||
border-radius: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.institutionsDashboard__editInfo__button {
|
||||
button {
|
||||
border: 1px solid #564794;
|
||||
background-color: white;
|
||||
|
||||
&:focus,
|
||||
&:hover {
|
||||
background-color: #564794;
|
||||
color: white;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background-color: #cccccc !important;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error message
|
||||
.companyEditForm--error {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
width: -webkit-fill-available;
|
||||
margin-top: -15px;
|
||||
font-weight: 600;
|
||||
row-gap: 3px;
|
||||
|
||||
.bi {
|
||||
font-size: 1.018rem;
|
||||
padding: 0 !important;
|
||||
|
||||
&::before {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
}
|
||||
|
||||
#imageError {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#institutionEditError,
|
||||
#emailError,
|
||||
#phoneNumberError,
|
||||
#addressError,
|
||||
#descError,
|
||||
#institutionNameError,
|
||||
#imageError {
|
||||
color: crimson;
|
||||
width: -webkit-fill-available;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 0;
|
||||
margin-bottom: 10px;
|
||||
line-height: 1.1;
|
||||
|
||||
.bi-x {
|
||||
&::before {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.bi-exclamation-octagon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
color: crimson;
|
||||
|
||||
.bi-check {
|
||||
color: #564794 !important;
|
||||
}
|
||||
|
||||
.bi {
|
||||
font-size: 1.018rem;
|
||||
|
||||
&::before {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.updateSaveBtn {
|
||||
.btn-save {
|
||||
background: #211069;
|
||||
background-image: -webkit-linear-gradient(
|
||||
to bottom left,
|
||||
#211069,
|
||||
#564794,
|
||||
#211069
|
||||
);
|
||||
background-image: -o-linear-gradient(
|
||||
to bottom left,
|
||||
#211069,
|
||||
#564794,
|
||||
#211069
|
||||
);
|
||||
background-image: -moz-linear-gradient(
|
||||
to bottom left,
|
||||
#211069,
|
||||
#564794,
|
||||
#211069
|
||||
);
|
||||
background-image: linear-gradient(
|
||||
to bottom left,
|
||||
#211069,
|
||||
#564794,
|
||||
#211069
|
||||
);
|
||||
background-size: 210% 210%;
|
||||
background-position: top right;
|
||||
background-color: #211069;
|
||||
transition: all 0.15s ease;
|
||||
box-shadow: none;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CompanyProfileComponent } from './company-profile.component';
|
||||
|
||||
describe('CompanyProfileComponent', () => {
|
||||
let component: CompanyProfileComponent;
|
||||
let fixture: ComponentFixture<CompanyProfileComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ CompanyProfileComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CompanyProfileComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
119
src/app/pages/company-profile/company-profile.component.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormGroup, Validators } from "@angular/forms";
|
||||
import { ToastrService } from "ngx-toastr";
|
||||
import { CompanyService } from "src/app/services/company.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-company-profile",
|
||||
templateUrl: "./company-profile.component.html",
|
||||
styleUrls: ["./company-profile.component.scss"],
|
||||
})
|
||||
export class CompanyProfileComponent implements OnInit {
|
||||
updateInfoForm: FormGroup;
|
||||
imgFile: any;
|
||||
fileName: any;
|
||||
imgSrc: any;
|
||||
institutionId!: number;
|
||||
imgFormatError: boolean = false;
|
||||
fileSizeError: boolean = false;
|
||||
company: any;
|
||||
|
||||
private emailPattern =
|
||||
"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])";
|
||||
|
||||
constructor(
|
||||
private fb: FormBuilder,
|
||||
private toastr: ToastrService,
|
||||
private companyService: CompanyService
|
||||
) {
|
||||
this.updateInfoForm = this.fb.group({
|
||||
companyName: ["", [Validators.required, Validators.minLength(6)]],
|
||||
companyUsername: ["", [Validators.required]],
|
||||
companyAddress: ["", [Validators.required, Validators.minLength(6)]],
|
||||
companyCity: ["", [Validators.required, Validators.minLength(3)]],
|
||||
companyPhone: [
|
||||
"",
|
||||
[
|
||||
Validators.required,
|
||||
Validators.minLength(11),
|
||||
Validators.pattern("^[0-9]*$"),
|
||||
],
|
||||
],
|
||||
companyEmail: [
|
||||
"",
|
||||
[Validators.required, Validators.pattern(this.emailPattern)],
|
||||
],
|
||||
companyDescription: ["", [Validators.required, Validators.minLength(10)]],
|
||||
companyLogo: ["", Validators.required],
|
||||
});
|
||||
|
||||
this.companyService.getCompanyById(1).subscribe((company) => {
|
||||
this.company = company;
|
||||
console.log(this.company);
|
||||
});
|
||||
}
|
||||
|
||||
get formControls() {
|
||||
return this.updateInfoForm.controls;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.updateInfoForm.patchValue({
|
||||
companyName: this.company.name,
|
||||
companyUsername: this.company.username,
|
||||
companyEmail: this.company.email,
|
||||
companyPhone: this.company.phone,
|
||||
companyAddress: this.company.address,
|
||||
companyCity: this.company.city,
|
||||
companyDescription: this.company.description,
|
||||
companyLogo: this.company.image,
|
||||
});
|
||||
}
|
||||
|
||||
// Check file type
|
||||
checkFileType(file: File): boolean {
|
||||
const imageTypes = ["image/jpeg", "image/png", "image/gif", "image/jpg"]; // Add more types if needed
|
||||
return imageTypes.includes(file.type);
|
||||
}
|
||||
|
||||
onFileChange(event: any) {
|
||||
this.imgFile = <File>event.target.files[0];
|
||||
this.fileName = this.imgFile.name;
|
||||
|
||||
console.log(this.imgFile);
|
||||
|
||||
if (this.checkFileType(this.imgFile)) {
|
||||
let reader = new FileReader();
|
||||
reader.readAsDataURL(event.target.files[0]);
|
||||
reader.onload = (event: any) => {
|
||||
this.imgSrc = event.target.result;
|
||||
this.updateInfoForm.patchValue({
|
||||
image: this.imgSrc,
|
||||
});
|
||||
};
|
||||
} else {
|
||||
// Use toastr service to show error message
|
||||
this.toastr.error("Please select correct image format", "Error", {
|
||||
timeOut: 3000,
|
||||
progressBar: true,
|
||||
progressAnimation: "increasing",
|
||||
closeButton: true,
|
||||
positionClass: "toast-top-center",
|
||||
});
|
||||
this.imgFormatError = true;
|
||||
}
|
||||
|
||||
/* checking file size here is greater than 2MB */
|
||||
if (this.imgFile.size > 2000000) {
|
||||
this.fileSizeError = true;
|
||||
} else {
|
||||
this.fileSizeError = false;
|
||||
}
|
||||
}
|
||||
|
||||
updateInfo() {
|
||||
if (this.updateInfoForm.invalid) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
441
src/app/pages/dashboard/dashboard.component.html
Normal file
@@ -0,0 +1,441 @@
|
||||
<!-- <div class="content">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card card-chart">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col-sm-6 text-left">
|
||||
<h5 class="card-category">Total Shipments</h5>
|
||||
<h2 class="card-title">Performance</h2>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div
|
||||
class="btn-group btn-group-toggle float-right"
|
||||
data-toggle="buttons"
|
||||
>
|
||||
<label
|
||||
class="btn btn-sm btn-danger btn-simple"
|
||||
(click)="
|
||||
data = datasets[0];
|
||||
updateOptions();
|
||||
clicked = true;
|
||||
clicked1 = false;
|
||||
clicked2 = false
|
||||
"
|
||||
[ngClass]="{ active: clicked === true }"
|
||||
>
|
||||
<input checked="checked" name="options" type="radio" />
|
||||
|
||||
<span
|
||||
class="d-none d-sm-block d-md-block d-lg-block d-xl-block"
|
||||
>
|
||||
Accounts
|
||||
</span>
|
||||
<span class="d-block d-sm-none">
|
||||
<i class="tim-icons icon-single-02"> </i>
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="btn btn-sm btn-danger btn-simple"
|
||||
(click)="
|
||||
data = datasets[1];
|
||||
updateOptions();
|
||||
clicked = false;
|
||||
clicked1 = true;
|
||||
clicked2 = false
|
||||
"
|
||||
[ngClass]="{ active: clicked1 === true }"
|
||||
>
|
||||
<input class="d-none d-sm-none" name="options" type="radio" />
|
||||
|
||||
<span
|
||||
class="d-none d-sm-block d-md-block d-lg-block d-xl-block"
|
||||
>
|
||||
Purchases
|
||||
</span>
|
||||
<span class="d-block d-sm-none">
|
||||
<i class="tim-icons icon-gift-2"> </i>
|
||||
</span>
|
||||
</label>
|
||||
<label
|
||||
class="btn btn-sm btn-danger btn-simple"
|
||||
(click)="
|
||||
data = datasets[2];
|
||||
updateOptions();
|
||||
clicked = false;
|
||||
clicked1 = false;
|
||||
clicked2 = true
|
||||
"
|
||||
[ngClass]="{ active: clicked2 === true }"
|
||||
>
|
||||
<input class="d-none" name="options" type="radio" />
|
||||
|
||||
<span
|
||||
class="d-none d-sm-block d-md-block d-lg-block d-xl-block"
|
||||
>
|
||||
Sessions
|
||||
</span>
|
||||
<span class="d-block d-sm-none">
|
||||
<i class="tim-icons icon-tap-02"> </i>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-area"><canvas id="chartBig1"> </canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<div class="card card-chart">
|
||||
<div class="card-header">
|
||||
<h5 class="card-category">Total Shipments</h5>
|
||||
<h3 class="card-title">
|
||||
<i class="tim-icons icon-bell-55 text-danger-states"> </i> 763,215
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-area"><canvas id="chartLineRed"> </canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card card-chart">
|
||||
<div class="card-header">
|
||||
<h5 class="card-category">Daily Sales</h5>
|
||||
<h3 class="card-title">
|
||||
<i class="tim-icons icon-delivery-fast text-info"> </i> 3,500€
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-area"><canvas id="CountryChart"> </canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="card card-chart">
|
||||
<div class="card-header">
|
||||
<h5 class="card-category">Completed Tasks</h5>
|
||||
<h3 class="card-title">
|
||||
<i class="tim-icons icon-send text-success"> </i> 12,100K
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="chart-area"><canvas id="chartLineGreen"> </canvas></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12">
|
||||
<div class="card card-tasks">
|
||||
<div class="card-header">
|
||||
<h6 class="title d-inline">Tasks(5)</h6>
|
||||
<p class="card-category d-inline">today</p>
|
||||
<div ngbDropdown>
|
||||
<button
|
||||
class="btn btn-link btn-icon"
|
||||
data-toggle="dropdown"
|
||||
ngbDropdownToggle
|
||||
type="button"
|
||||
>
|
||||
<i class="tim-icons icon-settings-gear-63"> </i>
|
||||
</button>
|
||||
<div
|
||||
aria-labelledby="dropdownMenuLink"
|
||||
class="dropdown-menu-right"
|
||||
ngbDropdownMenu
|
||||
>
|
||||
<a href="javascript:void(0)" ngbDropdownItem> Action </a>
|
||||
<a href="javascript:void(0)" ngbDropdownItem> Another action </a>
|
||||
<a href="javascript:void(0)" ngbDropdownItem> Something else </a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-full-width table-responsive">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">Update the Documentation</p>
|
||||
<p class="text-muted">Dwuamish Head, Seattle, WA 8:47 AM</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
checked=""
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">GDPR Compliance</p>
|
||||
<p class="text-muted">
|
||||
The GDPR is a regulation that requires businesses to
|
||||
protect the personal data and privacy of Europe citizens
|
||||
for transactions that occur within EU member states.
|
||||
</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">Solve the issues</p>
|
||||
<p class="text-muted">
|
||||
Fifty percent of all respondents said they would be more
|
||||
likely to shop at a company
|
||||
</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">Release v2.0.0</p>
|
||||
<p class="text-muted">
|
||||
Ra Ave SW, Seattle, WA 98116, SUA 11:19 AM
|
||||
</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">Export the processed files</p>
|
||||
<p class="text-muted">
|
||||
The report also shows that consumers will not easily
|
||||
forgive a company once a breach exposing their personal
|
||||
data occurs.
|
||||
</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label">
|
||||
<input
|
||||
class="form-check-input"
|
||||
type="checkbox"
|
||||
value=""
|
||||
/>
|
||||
|
||||
<span class="form-check-sign">
|
||||
<span class="check"> </span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class="title">Arival at export process</p>
|
||||
<p class="text-muted">Capitol Hill, Seattle, WA 12:34 AM</p>
|
||||
</td>
|
||||
<td class="td-actions text-right">
|
||||
<button
|
||||
class="btn btn-link"
|
||||
type="button"
|
||||
placement="left"
|
||||
ngbTooltip="Edit Task"
|
||||
container="body"
|
||||
>
|
||||
<i class="tim-icons icon-pencil"> </i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Simple Table</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table tablesorter" id="">
|
||||
<thead class="text-primary">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Country</th>
|
||||
<th>City</th>
|
||||
<th class="text-center">Salary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Dakota Rice</td>
|
||||
<td>Niger</td>
|
||||
<td>Oud-Turnhout</td>
|
||||
<td class="text-center">$36,738</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minerva Hooper</td>
|
||||
<td>Curaçao</td>
|
||||
<td>Sinaai-Waas</td>
|
||||
<td class="text-center">$23,789</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sage Rodriguez</td>
|
||||
<td>Netherlands</td>
|
||||
<td>Baileux</td>
|
||||
<td class="text-center">$56,142</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Philip Chaney</td>
|
||||
<td>Korea, South</td>
|
||||
<td>Overland Park</td>
|
||||
<td class="text-center">$38,735</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Doris Greene</td>
|
||||
<td>Malawi</td>
|
||||
<td>Feldkirchen in Kärnten</td>
|
||||
<td class="text-center">$63,542</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mason Porter</td>
|
||||
<td>Chile</td>
|
||||
<td>Gloucester</td>
|
||||
<td class="text-center">$78,615</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jon Porter</td>
|
||||
<td>Portugal</td>
|
||||
<td>Gloucester</td>
|
||||
<td class="text-center">$98,615</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
470
src/app/pages/dashboard/dashboard.component.ts
Normal file
@@ -0,0 +1,470 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import Chart from 'chart.js';
|
||||
|
||||
@Component({
|
||||
selector: "app-dashboard",
|
||||
templateUrl: "dashboard.component.html"
|
||||
})
|
||||
export class DashboardComponent implements OnInit {
|
||||
public canvas : any;
|
||||
public ctx;
|
||||
public datasets: any;
|
||||
public data: any;
|
||||
public myChartData;
|
||||
public clicked: boolean = true;
|
||||
public clicked1: boolean = false;
|
||||
public clicked2: boolean = false;
|
||||
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {
|
||||
var gradientChartOptionsConfigurationWithTooltipBlue: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.0)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#2380f7"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#2380f7"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var gradientChartOptionsConfigurationWithTooltipPurple: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.0)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(225,78,202,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var gradientChartOptionsConfigurationWithTooltipRed: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.0)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(233,32,16,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9a9a9a"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var gradientChartOptionsConfigurationWithTooltipOrange: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.0)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 50,
|
||||
suggestedMax: 110,
|
||||
padding: 20,
|
||||
fontColor: "#ff8a76"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(220,53,69,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#ff8a76"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
var gradientChartOptionsConfigurationWithTooltipGreen: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.0)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 50,
|
||||
suggestedMax: 125,
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
barPercentage: 1.6,
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(0,242,195,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var gradientBarChartConfiguration: any = {
|
||||
maintainAspectRatio: false,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
|
||||
tooltips: {
|
||||
backgroundColor: '#f5f5f5',
|
||||
titleFontColor: '#333',
|
||||
bodyFontColor: '#666',
|
||||
bodySpacing: 4,
|
||||
xPadding: 12,
|
||||
mode: "nearest",
|
||||
intersect: 0,
|
||||
position: "nearest"
|
||||
},
|
||||
responsive: true,
|
||||
scales: {
|
||||
yAxes: [{
|
||||
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
suggestedMin: 60,
|
||||
suggestedMax: 120,
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}],
|
||||
|
||||
xAxes: [{
|
||||
|
||||
gridLines: {
|
||||
drawBorder: false,
|
||||
color: 'rgba(29,140,248,0.1)',
|
||||
zeroLineColor: "transparent",
|
||||
},
|
||||
ticks: {
|
||||
padding: 20,
|
||||
fontColor: "#9e9e9e"
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
this.canvas = document.getElementById("chartLineRed");
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
|
||||
var gradientStroke = this.ctx.createLinearGradient(0, 230, 0, 50);
|
||||
|
||||
gradientStroke.addColorStop(1, 'rgba(233,32,16,0.2)');
|
||||
gradientStroke.addColorStop(0.4, 'rgba(233,32,16,0.0)');
|
||||
gradientStroke.addColorStop(0, 'rgba(233,32,16,0)'); //red colors
|
||||
|
||||
var data = {
|
||||
labels: ['JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'],
|
||||
datasets: [{
|
||||
label: "Data",
|
||||
fill: true,
|
||||
backgroundColor: gradientStroke,
|
||||
borderColor: '#ec250d',
|
||||
borderWidth: 2,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
pointBackgroundColor: '#ec250d',
|
||||
pointBorderColor: 'rgba(255,255,255,0)',
|
||||
pointHoverBackgroundColor: '#ec250d',
|
||||
pointBorderWidth: 20,
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [80, 100, 70, 80, 120, 80],
|
||||
}]
|
||||
};
|
||||
|
||||
var myChart = new Chart(this.ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: gradientChartOptionsConfigurationWithTooltipRed
|
||||
});
|
||||
|
||||
|
||||
this.canvas = document.getElementById("chartLineGreen");
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
|
||||
|
||||
var gradientStroke = this.ctx.createLinearGradient(0, 230, 0, 50);
|
||||
|
||||
gradientStroke.addColorStop(1, 'rgba(66,134,121,0.15)');
|
||||
gradientStroke.addColorStop(0.4, 'rgba(66,134,121,0.0)'); //green colors
|
||||
gradientStroke.addColorStop(0, 'rgba(66,134,121,0)'); //green colors
|
||||
|
||||
var data = {
|
||||
labels: ['JUL', 'AUG', 'SEP', 'OCT', 'NOV'],
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
fill: true,
|
||||
backgroundColor: gradientStroke,
|
||||
borderColor: '#00d6b4',
|
||||
borderWidth: 2,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
pointBackgroundColor: '#00d6b4',
|
||||
pointBorderColor: 'rgba(255,255,255,0)',
|
||||
pointHoverBackgroundColor: '#00d6b4',
|
||||
pointBorderWidth: 20,
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: [90, 27, 60, 12, 80],
|
||||
}]
|
||||
};
|
||||
|
||||
var myChart = new Chart(this.ctx, {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: gradientChartOptionsConfigurationWithTooltipGreen
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
var chart_labels = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
|
||||
this.datasets = [
|
||||
[100, 70, 90, 70, 85, 60, 75, 60, 90, 80, 110, 100],
|
||||
[80, 120, 105, 110, 95, 105, 90, 100, 80, 95, 70, 120],
|
||||
[60, 80, 65, 130, 80, 105, 90, 130, 70, 115, 60, 130]
|
||||
];
|
||||
this.data = this.datasets[0];
|
||||
|
||||
|
||||
|
||||
this.canvas = document.getElementById("chartBig1");
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
|
||||
var gradientStroke = this.ctx.createLinearGradient(0, 230, 0, 50);
|
||||
|
||||
gradientStroke.addColorStop(1, 'rgba(233,32,16,0.2)');
|
||||
gradientStroke.addColorStop(0.4, 'rgba(233,32,16,0.0)');
|
||||
gradientStroke.addColorStop(0, 'rgba(233,32,16,0)'); //red colors
|
||||
|
||||
var config = {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: chart_labels,
|
||||
datasets: [{
|
||||
label: "My First dataset",
|
||||
fill: true,
|
||||
backgroundColor: gradientStroke,
|
||||
borderColor: '#ec250d',
|
||||
borderWidth: 2,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
pointBackgroundColor: '#ec250d',
|
||||
pointBorderColor: 'rgba(255,255,255,0)',
|
||||
pointHoverBackgroundColor: '#ec250d',
|
||||
pointBorderWidth: 20,
|
||||
pointHoverRadius: 4,
|
||||
pointHoverBorderWidth: 15,
|
||||
pointRadius: 4,
|
||||
data: this.data,
|
||||
}]
|
||||
},
|
||||
options: gradientChartOptionsConfigurationWithTooltipRed
|
||||
};
|
||||
this.myChartData = new Chart(this.ctx, config);
|
||||
|
||||
|
||||
this.canvas = document.getElementById("CountryChart");
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
var gradientStroke = this.ctx.createLinearGradient(0, 230, 0, 50);
|
||||
|
||||
gradientStroke.addColorStop(1, 'rgba(29,140,248,0.2)');
|
||||
gradientStroke.addColorStop(0.4, 'rgba(29,140,248,0.0)');
|
||||
gradientStroke.addColorStop(0, 'rgba(29,140,248,0)'); //blue colors
|
||||
|
||||
|
||||
var myChart = new Chart(this.ctx, {
|
||||
type: 'bar',
|
||||
responsive: true,
|
||||
legend: {
|
||||
display: false
|
||||
},
|
||||
data: {
|
||||
labels: ['USA', 'GER', 'AUS', 'UK', 'RO', 'BR'],
|
||||
datasets: [{
|
||||
label: "Countries",
|
||||
fill: true,
|
||||
backgroundColor: gradientStroke,
|
||||
hoverBackgroundColor: gradientStroke,
|
||||
borderColor: '#1f8ef1',
|
||||
borderWidth: 2,
|
||||
borderDash: [],
|
||||
borderDashOffset: 0.0,
|
||||
data: [53, 20, 10, 80, 100, 45],
|
||||
}]
|
||||
},
|
||||
options: gradientBarChartConfiguration
|
||||
});
|
||||
|
||||
}
|
||||
public updateOptions() {
|
||||
this.myChartData.data.datasets[0].data = this.data;
|
||||
this.myChartData.update();
|
||||
}
|
||||
}
|
||||
52
src/app/pages/invoices/invoices.component.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title font-weight-bolder">Invoices Details</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table tablesorter" id="">
|
||||
<thead class="text-primary">
|
||||
<tr>
|
||||
<th>S/N</th>
|
||||
<th>Invoice Number</th>
|
||||
<th>Date Issued</th>
|
||||
<th>Due Date</th>
|
||||
<th>Status</th>
|
||||
<th class="text-center">Amount</th>
|
||||
<th>Services Rendered</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let invoice of invoices; let i = index">
|
||||
<td>{{ i + 1 }}</td>
|
||||
<td>{{ invoice.invoiceNumber }}</td>
|
||||
|
||||
<td>
|
||||
{{
|
||||
invoice.dateIssued.toLocaleDateString("en-US", options)
|
||||
}}
|
||||
</td>
|
||||
<td>
|
||||
{{ invoice.dueDate.toLocaleDateString("en-US", options) }}
|
||||
</td>
|
||||
<td
|
||||
class="text-capitalize"
|
||||
style="font-weight: 600"
|
||||
[ngStyle]="{ 'color': getStatusColor(invoice.status) }"
|
||||
>
|
||||
{{ invoice.status }}
|
||||
</td>
|
||||
<td class="text-center">₦{{ invoice.amount }}</td>
|
||||
<td>{{ invoice.services[0].description }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
0
src/app/pages/invoices/invoices.component.scss
Normal file
25
src/app/pages/invoices/invoices.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { InvoicesComponent } from './invoices.component';
|
||||
|
||||
describe('InvoicesComponent', () => {
|
||||
let component: InvoicesComponent;
|
||||
let fixture: ComponentFixture<InvoicesComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ InvoicesComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(InvoicesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
52
src/app/pages/invoices/invoices.component.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { InvoiceModel } from "../../models/invoice";
|
||||
import { InvoiceService } from "../../services/invoice.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-invoices",
|
||||
templateUrl: "./invoices.component.html",
|
||||
styleUrls: ["./invoices.component.scss"],
|
||||
})
|
||||
export class InvoicesComponent implements OnInit {
|
||||
invoices: InvoiceModel[];
|
||||
options: any;
|
||||
|
||||
constructor(private invoiceService: InvoiceService) {
|
||||
this.invoiceService
|
||||
.getInvoiceById(1)
|
||||
.subscribe((invoice: InvoiceModel[]) => {
|
||||
this.invoices = invoice;
|
||||
|
||||
for (let i = 0; i < invoice.length; i++) {
|
||||
let amountWithCommas = invoice[i].amount.replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
","
|
||||
);
|
||||
invoice[i].amount = amountWithCommas;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.options = {
|
||||
weekday: "short",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
};
|
||||
}
|
||||
|
||||
// Get color status
|
||||
getStatusColor(status: string): string {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "#FFC107";
|
||||
case "paid":
|
||||
return "#4CAF50";
|
||||
case "overdue":
|
||||
return "#DC143C";
|
||||
default:
|
||||
return "inherit";
|
||||
}
|
||||
}
|
||||
}
|
||||
96
src/app/pages/login/login.component.html
Normal file
@@ -0,0 +1,96 @@
|
||||
<div class="content ml-2 signinContainer overflow-hidden">
|
||||
<div class="logo">
|
||||
<img
|
||||
src="../../../assets/img/logo.png"
|
||||
class="img-fluid"
|
||||
height="150"
|
||||
width="150"
|
||||
alt="logo"
|
||||
style="width: 200px; height: 200px"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section class="forms">
|
||||
<form (ngSubmit)="signin()" [formGroup]="loginForm" novalidate>
|
||||
<div class="forms__inputBox">
|
||||
<input
|
||||
type="email"
|
||||
formControlName="companyEmail"
|
||||
id="companyEmail"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
<label for="companyEmail">Email</label>
|
||||
|
||||
<div class="signinForms--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.companyEmail.errors?.required &&
|
||||
formControls.companyEmail?.touched
|
||||
"
|
||||
>
|
||||
<div id="emailError" aria-live="assertive">
|
||||
<i class="bi bi-x"> </i>
|
||||
<span>Email Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="formControls.companyEmail.errors?.pattern">
|
||||
<div id="emailError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Please enter a valid email</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="forms__inputBox">
|
||||
<input
|
||||
type="password"
|
||||
[type]="hide ? 'password' : 'text'"
|
||||
formControlName="password"
|
||||
id="password"
|
||||
data-cy="signin-password"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
<i
|
||||
[class]="hide ? 'bi bi-eye-slash' : 'bi bi-eye'"
|
||||
(click)="hide = !hide"
|
||||
></i>
|
||||
<label for="password">Password</label>
|
||||
|
||||
<div class="signinForms--error">
|
||||
<ng-container
|
||||
*ngIf="
|
||||
formControls.password.errors?.required &&
|
||||
formControls.password?.touched
|
||||
"
|
||||
>
|
||||
<div id="passwordError" aria-live="assertive">
|
||||
<i class="bi bi-x"></i>
|
||||
<span>Password Required</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="formControls.password.errors?.minlength">
|
||||
<div id="passwordError" aria-live="assertive">
|
||||
<i class="bi bi-exclamation-octagon"></i>
|
||||
<span>Password must be at least 6 characters</span>
|
||||
</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="forgotPassw">
|
||||
<p>
|
||||
Forgot Password?
|
||||
<a routerLink="/request-reset-password">Reset password </a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="signinBtn">
|
||||
<button (click)="signin()" data-cy="signin-button">Sign In</button>
|
||||
</div>
|
||||
</div>
|
||||
134
src/app/pages/login/login.component.scss
Normal file
@@ -0,0 +1,134 @@
|
||||
.signinContainer {
|
||||
.forms {
|
||||
// Sign in form
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
|
||||
.forms__inputBox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
// Input
|
||||
input {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
border: 2px solid #cccccc;
|
||||
border-radius: 10px;
|
||||
outline: none;
|
||||
|
||||
&:focus ~ label,
|
||||
&:valid ~ label {
|
||||
color: #564794;
|
||||
transform: translateX(10px) translateY(-7px);
|
||||
font-size: 0.65rem;
|
||||
padding: 0 10px;
|
||||
font-weight: 600;
|
||||
background-color: white;
|
||||
letter-spacing: 0.1px;
|
||||
}
|
||||
|
||||
&:focus,
|
||||
&:valid {
|
||||
color: black;
|
||||
border: 2px solid #564794;
|
||||
}
|
||||
}
|
||||
|
||||
i.bi-eye,
|
||||
i.bi-eye-slash {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
padding: 10px;
|
||||
padding-top: 5px;
|
||||
font-size: 1.5rem;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// Label
|
||||
label {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
padding: 10px;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
color: #7f7e7f;
|
||||
text-transform: uppercase;
|
||||
pointer-events: none;
|
||||
transition: 0.6s;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forgot password
|
||||
.forgotPassw {
|
||||
margin-top: 0.6rem;
|
||||
p {
|
||||
margin-top: 5px !important;
|
||||
margin-bottom: 0 !important;
|
||||
|
||||
a {
|
||||
color: #564794;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Signin Error message
|
||||
.signinForms--error {
|
||||
width: -webkit-fill-available;
|
||||
font-weight: 600;
|
||||
|
||||
.bi {
|
||||
font-size: 1.018rem;
|
||||
padding: 0 !important;
|
||||
|
||||
&::before {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 900 !important;
|
||||
}
|
||||
}
|
||||
|
||||
#emailError,
|
||||
#passwordError {
|
||||
color: crimson;
|
||||
width: -webkit-fill-available;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 6px;
|
||||
line-height: 1.1;
|
||||
|
||||
.bi-x {
|
||||
&::before {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.bi-exclamation-octagon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sign in button
|
||||
.signinBtn {
|
||||
button {
|
||||
border: none;
|
||||
background-color: #211069;
|
||||
width: -webkit-fill-available;
|
||||
padding: 1rem 0;
|
||||
border-radius: 25px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
font-size: 1.07rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
25
src/app/pages/login/login.component.spec.ts
Normal 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();
|
||||
});
|
||||
});
|
||||
49
src/app/pages/login/login.component.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormGroup, FormBuilder, Validators } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: "app-login",
|
||||
templateUrl: "./login.component.html",
|
||||
styleUrls: ["./login.component.scss"],
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
private emailPattern =
|
||||
"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\\])";
|
||||
loginForm: FormGroup;
|
||||
hide: boolean = true;
|
||||
|
||||
constructor(private fb: FormBuilder) {
|
||||
this.loginForm = this.fb.group({
|
||||
companyEmail: ["", [Validators.required, Validators.pattern(this.emailPattern)]],
|
||||
password: ["", [Validators.required, Validators.minLength(6)]],
|
||||
})
|
||||
}
|
||||
|
||||
get formControls() {
|
||||
return this.loginForm.controls;
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
signin() {
|
||||
const email = this.loginForm.get('email')?.value;
|
||||
const password = this.loginForm.get('password')?.value;
|
||||
|
||||
if (this.loginForm.invalid) {
|
||||
console.log('Form error');
|
||||
return;
|
||||
}
|
||||
|
||||
this.loginForm.reset();
|
||||
// this.userService.signinUser(email, password);
|
||||
|
||||
// this.userService.signinMessage$.subscribe((msg) => {
|
||||
// console.log('message', msg);
|
||||
// this.signinMessage = msg;
|
||||
// setTimeout(() => {
|
||||
// this.signinMessage = msg;
|
||||
// }, 1000);
|
||||
// });
|
||||
}
|
||||
}
|
||||
182
src/app/pages/notifications/notifications.component.html
Normal file
@@ -0,0 +1,182 @@
|
||||
<div class=" content">
|
||||
<div class=" row">
|
||||
<div class=" col-md-6">
|
||||
<div class=" card">
|
||||
<div class=" card-header">
|
||||
<h4 class=" card-title">Notifications Style</h4>
|
||||
</div>
|
||||
<div class=" card-body">
|
||||
<ngb-alert [type]="'info'" [dismissible]="false">
|
||||
<span> This is a plain notification </span>
|
||||
</ngb-alert>
|
||||
<ngb-alert [type]="'info'" *ngIf="!staticAlertClosed" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span> This is a notification with close button. </span>
|
||||
</ngb-alert>
|
||||
<ngb-alert
|
||||
class=" alert-with-icon"
|
||||
data-notify="container"
|
||||
[type]="'info'"*ngIf="!staticAlertClosed1" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed1 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span class=" tim-icons icon-bell-55" data-notify="icon">
|
||||
</span>
|
||||
<span data-notify="message">
|
||||
This is a notification with close button and icon.
|
||||
</span>
|
||||
</ngb-alert>
|
||||
<ngb-alert
|
||||
class=" alert-with-icon"
|
||||
data-notify="container"
|
||||
[type]="'info'"
|
||||
*ngIf="!staticAlertClosed2" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed2 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span class=" tim-icons icon-bell-55" data-notify="icon">
|
||||
</span>
|
||||
<span data-notify="message">
|
||||
This is a notification with close button and icon and have
|
||||
many lines. You can see that the icon and the close button
|
||||
are always vertically aligned. This is a beautiful
|
||||
notification. So you don't have to worry about the style.
|
||||
</span>
|
||||
</ngb-alert>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" col-md-6">
|
||||
<div class=" card">
|
||||
<div class=" card-header">
|
||||
<h4 class=" card-title">Notification states</h4>
|
||||
</div>
|
||||
<div class=" card-body">
|
||||
<ngb-alert [type]="'primary'" *ngIf="!staticAlertClosed3" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed3 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span>
|
||||
<b> Primary - </b> This is a regular notification made
|
||||
with ".alert-primary"
|
||||
</span>
|
||||
</ngb-alert>
|
||||
<ngb-alert [type]="'info'" *ngIf="!staticAlertClosed4" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed4 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span>
|
||||
<b> Info - </b> This is a regular notification made with
|
||||
".alert-info"
|
||||
</span>
|
||||
</ngb-alert>
|
||||
<ngb-alert [type]="'success'" *ngIf="!staticAlertClosed5" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed5 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span>
|
||||
<b> Success - </b> This is a regular notification made
|
||||
with ".alert-success"
|
||||
</span>
|
||||
</ngb-alert>
|
||||
<ngb-alert [type]="'warning'" *ngIf="!staticAlertClosed6" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed6 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span>
|
||||
<b> Warning - </b> This is a regular notification made
|
||||
with ".alert-warning"
|
||||
</span>
|
||||
</ngb-alert>
|
||||
<ngb-alert [type]="'danger'" *ngIf="!staticAlertClosed7" [dismissible]="false">
|
||||
<button type="button" aria-hidden="true" class="close" data-dismiss="alert" aria-label="Close" (click)="staticAlertClosed7 = true">
|
||||
<i class="tim-icons icon-simple-remove"></i>
|
||||
</button>
|
||||
<span>
|
||||
<b> Danger - </b> This is a regular notification made with
|
||||
".alert-danger"
|
||||
</span>
|
||||
</ngb-alert>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" col-md-12">
|
||||
<div class=" card">
|
||||
<div class=" card-body">
|
||||
<div class=" places-buttons">
|
||||
<div class=" row">
|
||||
<div class=" col-md-6 ml-auto mr-auto text-center">
|
||||
<h4 class=" card-title">Notifications Places</h4>
|
||||
<p class=" category">Click to view notifications</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" row">
|
||||
<div class=" col-lg-8 ml-auto mr-auto">
|
||||
<div class=" row">
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="showNotification('top', 'left')"
|
||||
>
|
||||
Top Left
|
||||
</button>
|
||||
</div>
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="showNotification('top', 'center')"
|
||||
>
|
||||
Top Center
|
||||
</button>
|
||||
</div>
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="showNotification('top', 'right')"
|
||||
>
|
||||
Top Right
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" row">
|
||||
<div class=" col-lg-8 ml-auto mr-auto">
|
||||
<div class=" row">
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="showNotification('bottom', 'left')"
|
||||
>
|
||||
Bottom Left
|
||||
</button>
|
||||
</div>
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="
|
||||
showNotification('bottom', 'center')
|
||||
"
|
||||
>
|
||||
Bottom Center
|
||||
</button>
|
||||
</div>
|
||||
<div class=" col-md-4">
|
||||
<button
|
||||
class=" btn btn-danger btn-block"
|
||||
(click)="showNotification('bottom', 'right')"
|
||||
>
|
||||
Bottom Right
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
76
src/app/pages/notifications/notifications.component.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ToastrService } from 'ngx-toastr';
|
||||
|
||||
@Component({
|
||||
selector: "app-notifications",
|
||||
templateUrl: "notifications.component.html"
|
||||
})
|
||||
export class NotificationsComponent implements OnInit {
|
||||
staticAlertClosed = false;
|
||||
staticAlertClosed1 = false;
|
||||
staticAlertClosed2 = false;
|
||||
staticAlertClosed3 = false;
|
||||
staticAlertClosed4 = false;
|
||||
staticAlertClosed5 = false;
|
||||
staticAlertClosed6 = false;
|
||||
staticAlertClosed7 = false;
|
||||
|
||||
constructor(private toastr: ToastrService) {}
|
||||
|
||||
showNotification(from, align){
|
||||
|
||||
const color = Math.floor((Math.random() * 5) + 1);
|
||||
|
||||
switch(color){
|
||||
case 1:
|
||||
this.toastr.info('<span class="tim-icons icon-bell-55" [data-notify]="icon"></span> Welcome to <b>Black Dashboard Angular</b> - a beautiful freebie for every web developer.', '', {
|
||||
disableTimeOut: true,
|
||||
closeButton: true,
|
||||
enableHtml: true,
|
||||
toastClass: "alert alert-info alert-with-icon",
|
||||
positionClass: 'toast-' + from + '-' + align
|
||||
});
|
||||
break;
|
||||
case 2:
|
||||
this.toastr.success('<span class="tim-icons icon-bell-55" [data-notify]="icon"></span> Welcome to <b>Black Dashboard Angular</b> - a beautiful freebie for every web developer.', '', {
|
||||
disableTimeOut: true,
|
||||
closeButton: true,
|
||||
enableHtml: true,
|
||||
toastClass: "alert alert-success alert-with-icon",
|
||||
positionClass: 'toast-' + from + '-' + align
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
this.toastr.warning('<span class="tim-icons icon-bell-55" [data-notify]="icon"></span> Welcome to <b>Black Dashboard Angular</b> - a beautiful freebie for every web developer.', '', {
|
||||
disableTimeOut: true,
|
||||
closeButton: true,
|
||||
enableHtml: true,
|
||||
toastClass: "alert alert-warning alert-with-icon",
|
||||
positionClass: 'toast-' + from + '-' + align
|
||||
});
|
||||
break;
|
||||
case 4:
|
||||
this.toastr.error('<span class="tim-icons icon-bell-55" [data-notify]="icon"></span> Welcome to <b>Black Dashboard Angular</b> - a beautiful freebie for every web developer.', '', {
|
||||
disableTimeOut: true,
|
||||
enableHtml: true,
|
||||
closeButton: true,
|
||||
toastClass: "alert alert-danger alert-with-icon",
|
||||
positionClass: 'toast-' + from + '-' + align
|
||||
});
|
||||
break;
|
||||
case 5:
|
||||
this.toastr.show('<span class="tim-icons icon-bell-55" [data-notify]="icon"></span> Welcome to <b>Black Dashboard Angular</b> - a beautiful freebie for every web developer.', '', {
|
||||
disableTimeOut: true,
|
||||
closeButton: true,
|
||||
enableHtml: true,
|
||||
toastClass: "alert alert-primary alert-with-icon",
|
||||
positionClass: 'toast-' + from + '-' + align
|
||||
});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
||||
122
src/app/pages/payments/payments.component.html
Normal file
@@ -0,0 +1,122 @@
|
||||
<div class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Payment Details</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table tablesorter">
|
||||
<thead class="text-primary">
|
||||
<tr>
|
||||
<th>S/N</th>
|
||||
<th>Payment Number</th>
|
||||
<th>Invoice Number</th>
|
||||
<th class="text-center">Payment Date</th>
|
||||
<th class="text-center">Amount</th>
|
||||
<th>Method</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let payment of payments; let i = index">
|
||||
<td>{{ i + 1 }}</td>
|
||||
<td>{{ payment.paymentNumber }}</td>
|
||||
<td>{{ payment.invoiceNumber }}</td>
|
||||
<td>
|
||||
{{
|
||||
payment.paymentDate.toLocaleDateString("en-US", options)
|
||||
}}
|
||||
</td>
|
||||
<td class="text-center">₦{{ payment.amount }}</td>
|
||||
<td
|
||||
class="text-capitalize"
|
||||
[ngStyle]="{ 'color': getMethodColor(payment.method) }"
|
||||
style="font-weight: 600;"
|
||||
>
|
||||
{{ payment.method }}
|
||||
</td>
|
||||
<td
|
||||
class="text-capitalize"
|
||||
style="font-weight: 600"
|
||||
[ngStyle]="{ 'color': getStatusColor(payment.status) }"
|
||||
>
|
||||
{{ payment.status }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class=" col-md-12">
|
||||
<div class=" card card-plain">
|
||||
<div class=" card-header">
|
||||
<h4 class=" card-title">Table on Plain Background</h4>
|
||||
<p class=" category">Here is a subtitle for this table</p>
|
||||
</div>
|
||||
<div class=" card-body">
|
||||
<div class=" table-responsive">
|
||||
<table class=" table tablesorter" id="">
|
||||
<thead class=" text-primary">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Country</th>
|
||||
<th>City</th>
|
||||
<th class=" text-center">Salary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Dakota Rice</td>
|
||||
<td>Niger</td>
|
||||
<td>Oud-Turnhout</td>
|
||||
<td class=" text-center">$36,738</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minerva Hooper</td>
|
||||
<td>Curaçao</td>
|
||||
<td>Sinaai-Waas</td>
|
||||
<td class=" text-center">$23,789</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sage Rodriguez</td>
|
||||
<td>Netherlands</td>
|
||||
<td>Baileux</td>
|
||||
<td class=" text-center">$56,142</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Philip Chaney</td>
|
||||
<td>Korea, South</td>
|
||||
<td>Overland Park</td>
|
||||
<td class=" text-center">$38,735</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Doris Greene</td>
|
||||
<td>Malawi</td>
|
||||
<td>Feldkirchen in Kärnten</td>
|
||||
<td class=" text-center">$63,542</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mason Porter</td>
|
||||
<td>Chile</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$78,615</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jon Porter</td>
|
||||
<td>Portugal</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$98,615</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
0
src/app/pages/payments/payments.component.scss
Normal file
25
src/app/pages/payments/payments.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PaymentsComponent } from './payments.component';
|
||||
|
||||
describe('PaymentsComponent', () => {
|
||||
let component: PaymentsComponent;
|
||||
let fixture: ComponentFixture<PaymentsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ PaymentsComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(PaymentsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
68
src/app/pages/payments/payments.component.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { PaymentModel } from "../../models/payment";
|
||||
import { PaymentService } from "../../services/payment.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-payments",
|
||||
templateUrl: "./payments.component.html",
|
||||
styleUrls: ["./payments.component.scss"],
|
||||
})
|
||||
export class PaymentsComponent implements OnInit {
|
||||
payments: PaymentModel[];
|
||||
options: any;
|
||||
|
||||
constructor(private paymentService: PaymentService) {
|
||||
this.paymentService
|
||||
.getPaymentById(1)
|
||||
.subscribe((payment: PaymentModel[]) => {
|
||||
this.payments = payment;
|
||||
|
||||
for (let i = 0; i < payment.length; i++) {
|
||||
let amountWithCommas = payment[i].amount.replace(
|
||||
/\B(?=(\d{3})+(?!\d))/g,
|
||||
","
|
||||
);
|
||||
payment[i].amount = amountWithCommas;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.options = {
|
||||
weekday: "short",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
};
|
||||
}
|
||||
|
||||
// Get color status
|
||||
getStatusColor(status: string): string {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "#FFC107";
|
||||
case "completed":
|
||||
return "#4CAF50";
|
||||
case "failed":
|
||||
return "#DC143C";
|
||||
default:
|
||||
return "inherit";
|
||||
}
|
||||
}
|
||||
|
||||
// Get color for methods
|
||||
getMethodColor(method: string): string {
|
||||
switch (method) {
|
||||
case "bank transfer":
|
||||
return "#0072c6";
|
||||
case "credit card":
|
||||
return "#ff6f00";
|
||||
case "cheque":
|
||||
return "#8bc34a";
|
||||
case "cash":
|
||||
return "#795548";
|
||||
default:
|
||||
return "inherit";
|
||||
}
|
||||
}
|
||||
}
|
||||
136
src/app/pages/tables/tables.component.html
Normal file
@@ -0,0 +1,136 @@
|
||||
|
||||
<div class=" content">
|
||||
<div class=" row">
|
||||
<div class=" col-md-12">
|
||||
<div class=" card">
|
||||
<div class=" card-header">
|
||||
<h4 class=" card-title">Simple Table</h4>
|
||||
</div>
|
||||
<div class=" card-body">
|
||||
<div class=" table-responsive">
|
||||
<table class=" table tablesorter" id="">
|
||||
<thead class=" text-primary">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Country</th>
|
||||
<th>City</th>
|
||||
<th class=" text-center">Salary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Dakota Rice</td>
|
||||
<td>Niger</td>
|
||||
<td>Oud-Turnhout</td>
|
||||
<td class=" text-center">$36,738</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minerva Hooper</td>
|
||||
<td>Curaçao</td>
|
||||
<td>Sinaai-Waas</td>
|
||||
<td class=" text-center">$23,789</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sage Rodriguez</td>
|
||||
<td>Netherlands</td>
|
||||
<td>Baileux</td>
|
||||
<td class=" text-center">$56,142</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Philip Chaney</td>
|
||||
<td>Korea, South</td>
|
||||
<td>Overland Park</td>
|
||||
<td class=" text-center">$38,735</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Doris Greene</td>
|
||||
<td>Malawi</td>
|
||||
<td>Feldkirchen in Kärnten</td>
|
||||
<td class=" text-center">$63,542</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mason Porter</td>
|
||||
<td>Chile</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$78,615</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jon Porter</td>
|
||||
<td>Portugal</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$98,615</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class=" col-md-12">
|
||||
<div class=" card card-plain">
|
||||
<div class=" card-header">
|
||||
<h4 class=" card-title">Table on Plain Background</h4>
|
||||
<p class=" category">Here is a subtitle for this table</p>
|
||||
</div>
|
||||
<div class=" card-body">
|
||||
<div class=" table-responsive">
|
||||
<table class=" table tablesorter" id="">
|
||||
<thead class=" text-primary">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Country</th>
|
||||
<th>City</th>
|
||||
<th class=" text-center">Salary</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Dakota Rice</td>
|
||||
<td>Niger</td>
|
||||
<td>Oud-Turnhout</td>
|
||||
<td class=" text-center">$36,738</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minerva Hooper</td>
|
||||
<td>Curaçao</td>
|
||||
<td>Sinaai-Waas</td>
|
||||
<td class=" text-center">$23,789</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sage Rodriguez</td>
|
||||
<td>Netherlands</td>
|
||||
<td>Baileux</td>
|
||||
<td class=" text-center">$56,142</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Philip Chaney</td>
|
||||
<td>Korea, South</td>
|
||||
<td>Overland Park</td>
|
||||
<td class=" text-center">$38,735</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Doris Greene</td>
|
||||
<td>Malawi</td>
|
||||
<td>Feldkirchen in Kärnten</td>
|
||||
<td class=" text-center">$63,542</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mason Porter</td>
|
||||
<td>Chile</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$78,615</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Jon Porter</td>
|
||||
<td>Portugal</td>
|
||||
<td>Gloucester</td>
|
||||
<td class=" text-center">$98,615</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
11
src/app/pages/tables/tables.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-tables",
|
||||
templateUrl: "tables.component.html"
|
||||
})
|
||||
export class TablesComponent implements OnInit {
|
||||
constructor() {}
|
||||
|
||||
ngOnInit() {}
|
||||
}
|
||||
27
src/app/services/company.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { CompanyModel } from "../models/company";
|
||||
import { company } from "../data/company";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class CompanyService {
|
||||
constructor() {}
|
||||
|
||||
companyData = new Observable<CompanyModel[]>((subscriber) => {
|
||||
subscriber.next(company);
|
||||
});
|
||||
|
||||
// Get all companies
|
||||
getAllCompanies(): Observable<CompanyModel[]> {
|
||||
return this.companyData;
|
||||
}
|
||||
|
||||
// Get a company based on id
|
||||
getCompanyById(id: number): Observable<CompanyModel> {
|
||||
return this.companyData.pipe(
|
||||
map((companies) => companies.find((company) => company.id === id))
|
||||
);
|
||||
}
|
||||
}
|
||||
29
src/app/services/database-info.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { DatabaseInfoModel } from "../models/database-info";
|
||||
import { databaseInfo } from "../data/database-info";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class DatabaseInfoService {
|
||||
constructor() {}
|
||||
|
||||
databaseInfoData = new Observable<DatabaseInfoModel[]>((subscriber) => {
|
||||
subscriber.next(databaseInfo);
|
||||
});
|
||||
|
||||
// Get all database info
|
||||
getAllDatabaseInfo(): Observable<DatabaseInfoModel[]> {
|
||||
return this.databaseInfoData;
|
||||
}
|
||||
|
||||
// Get a database info based on id
|
||||
getDatabaseInfoById(id: number): Observable<DatabaseInfoModel> {
|
||||
return this.databaseInfoData.pipe(
|
||||
map((databaseInfo) =>
|
||||
databaseInfo.find((databaseInfo) => databaseInfo.id === id)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
29
src/app/services/hosting-info.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { HostingInfoModel } from "../models/hosting-info";
|
||||
import { hostingInfo } from "../data/hosting-info";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class HostingInfoService {
|
||||
constructor() {}
|
||||
|
||||
hostingInfoData = new Observable<HostingInfoModel[]>((subscriber) => {
|
||||
subscriber.next(hostingInfo);
|
||||
});
|
||||
|
||||
// Get all hosting info
|
||||
getAllHostingInfo(): Observable<HostingInfoModel[]> {
|
||||
return this.hostingInfoData;
|
||||
}
|
||||
|
||||
// Get a hosting info based on id
|
||||
getHostingInfoById(id: number): Observable<HostingInfoModel> {
|
||||
return this.hostingInfoData.pipe(
|
||||
map((hostingInfo) =>
|
||||
hostingInfo.find((hostingInfo) => hostingInfo.id === id)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
27
src/app/services/invoice.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { InvoiceModel } from "../models/invoice";
|
||||
import { invoice } from "../data/invoice";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class InvoiceService {
|
||||
invoiceData = new Observable<InvoiceModel[]>((subscriber) => {
|
||||
subscriber.next(invoice);
|
||||
});
|
||||
|
||||
// Get all invoices
|
||||
getAllInvoices(): Observable<InvoiceModel[]> {
|
||||
return this.invoiceData;
|
||||
}
|
||||
|
||||
// Get an invoice based on id
|
||||
getInvoiceById(companyId: number): Observable<InvoiceModel[]> {
|
||||
return this.invoiceData.pipe(
|
||||
map((invoice) =>
|
||||
invoice.filter((invoice) => invoice.companyId === companyId)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
27
src/app/services/payment.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { PaymentModel } from "../models/payment";
|
||||
import { payment } from "../data/payment";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class PaymentService {
|
||||
constructor() {}
|
||||
|
||||
paymentData = new Observable<PaymentModel[]>((subscriber) => {
|
||||
subscriber.next(payment);
|
||||
});
|
||||
|
||||
// Get all payments
|
||||
getAllPayments(): Observable<PaymentModel[]> {
|
||||
return this.paymentData;
|
||||
}
|
||||
|
||||
// Get a payment based on id
|
||||
getPaymentById(companyId: number): Observable<PaymentModel[]> {
|
||||
return this.paymentData.pipe(
|
||||
map((payment) => payment.filter((payment) => payment.companyId === companyId))
|
||||
);
|
||||
}
|
||||
}
|
||||
29
src/app/services/server-info.service.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable, map } from "rxjs";
|
||||
import { ServerInfoModel } from "../models/server-info";
|
||||
import { serverInfo } from "../data/server-info";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class ServerInfoService {
|
||||
constructor() {}
|
||||
|
||||
serverInfoData = new Observable<ServerInfoModel[]>((subscriber) => {
|
||||
subscriber.next(serverInfo);
|
||||
});
|
||||
|
||||
// Get all server info
|
||||
getAllServerInfo(): Observable<ServerInfoModel[]> {
|
||||
return this.serverInfoData;
|
||||
}
|
||||
|
||||
// Get a server info based on id
|
||||
getServerInfoById(id: number): Observable<ServerInfoModel> {
|
||||
return this.serverInfoData.pipe(
|
||||
map((serverInfo) =>
|
||||
serverInfo.find((serverInfo) => serverInfo.id === id)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
548
src/assets/css/nucleo-icons.css
Normal file
@@ -0,0 +1,548 @@
|
||||
/* --------------------------------
|
||||
|
||||
Nucleo Outline Web Font - nucleoapp.com/
|
||||
License - nucleoapp.com/license/
|
||||
Created using IcoMoon - icomoon.io
|
||||
|
||||
-------------------------------- */
|
||||
|
||||
@font-face {
|
||||
font-family: "Nucleo";
|
||||
src: url("../fonts/nucleo.eot");
|
||||
src: url("../fonts/nucleo.eot") format("embedded-opentype"),
|
||||
url("../fonts/nucleo.woff2") format("woff2"),
|
||||
url("../fonts/nucleo.woff") format("woff"),
|
||||
url("../fonts/nucleo.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
base class definition
|
||||
-------------------------*/
|
||||
|
||||
.tim-icons {
|
||||
display: inline-block;
|
||||
font: normal normal normal 1em/1 "Nucleo";
|
||||
vertical-align: middle;
|
||||
speak: none;
|
||||
text-transform: none;
|
||||
/* Better Font Rendering */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.font-icon-detail {
|
||||
text-align: center;
|
||||
padding: 45px 0 30px;
|
||||
/* border: 1px solid #e44cc4; */
|
||||
border-radius: 0.1875rem;
|
||||
margin: 15px 0;
|
||||
min-height: 168px;
|
||||
box-shadow: rgba(0, 0, 0, 0.05) 0px 6px 24px 0px,
|
||||
rgba(0, 0, 0, 0.08) 0px 0px 0px 1px;
|
||||
}
|
||||
|
||||
.font-icon-detail i {
|
||||
color: #ffffff;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.font-icon-detail p {
|
||||
color: #e44cc4 !important;
|
||||
padding: 0 10px;
|
||||
font-size: 0.9rem;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
change icon size
|
||||
-------------------------*/
|
||||
|
||||
.tim-icons-sm {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.tim-icons-lg {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
/* absolute units */
|
||||
|
||||
.tim-icons-16 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.tim-icons-32 {
|
||||
font-size: 32px;
|
||||
}
|
||||
|
||||
/*----------------------------------
|
||||
add a square/circle background
|
||||
-----------------------------------*/
|
||||
|
||||
.tim-icons-bg-square,
|
||||
.tim-icons-bg-circle {
|
||||
padding: 0.35em;
|
||||
}
|
||||
|
||||
.tim-icons-bg-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
list icons
|
||||
-------------------------*/
|
||||
|
||||
/*------------------------
|
||||
spinning icons
|
||||
-------------------------*/
|
||||
|
||||
.tim-icons-is-spinning {
|
||||
-webkit-animation: tim-icons-spin 2s infinite linear;
|
||||
-moz-animation: tim-icons-spin 2s infinite linear;
|
||||
animation: tim-icons-spin 2s infinite linear;
|
||||
}
|
||||
|
||||
@-webkit-keyframes tim-icons-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@-moz-keyframes tim-icons-spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-moz-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes tim-icons-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
-moz-transform: rotate(0deg);
|
||||
-ms-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
-moz-transform: rotate(360deg);
|
||||
-ms-transform: rotate(360deg);
|
||||
-o-transform: rotate(360deg);
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------
|
||||
rotated/flipped icons
|
||||
-------------------------*/
|
||||
|
||||
/*------------------------
|
||||
icons
|
||||
-------------------------*/
|
||||
|
||||
.icon-alert-circle-exc::before {
|
||||
content: "\ea02";
|
||||
}
|
||||
|
||||
.icon-align-center::before {
|
||||
content: "\ea03";
|
||||
}
|
||||
|
||||
.icon-align-left-2::before {
|
||||
content: "\ea04";
|
||||
}
|
||||
|
||||
.icon-app::before {
|
||||
content: "\ea05";
|
||||
}
|
||||
|
||||
.icon-atom::before {
|
||||
content: "\ea06";
|
||||
}
|
||||
|
||||
.icon-attach-87::before {
|
||||
content: "\ea07";
|
||||
}
|
||||
|
||||
.icon-badge::before {
|
||||
content: "\ea08";
|
||||
}
|
||||
|
||||
.icon-bag-16::before {
|
||||
content: "\ea09";
|
||||
}
|
||||
|
||||
.icon-bank::before {
|
||||
content: "\ea0a";
|
||||
}
|
||||
|
||||
.icon-basket-simple::before {
|
||||
content: "\ea0b";
|
||||
}
|
||||
|
||||
.icon-bell-55::before {
|
||||
content: "\ea0c";
|
||||
}
|
||||
|
||||
.icon-bold::before {
|
||||
content: "\ea0d";
|
||||
}
|
||||
|
||||
.icon-book-bookmark::before {
|
||||
content: "\ea0e";
|
||||
}
|
||||
|
||||
.icon-bulb-63::before {
|
||||
content: "\ea0f";
|
||||
}
|
||||
|
||||
.icon-bullet-list-67::before {
|
||||
content: "\ea10";
|
||||
}
|
||||
|
||||
.icon-bus-front-12::before {
|
||||
content: "\ea11";
|
||||
}
|
||||
|
||||
.icon-button-pause::before {
|
||||
content: "\ea12";
|
||||
}
|
||||
|
||||
.icon-button-power::before {
|
||||
content: "\ea13";
|
||||
}
|
||||
|
||||
.icon-calendar-60::before {
|
||||
content: "\ea14";
|
||||
}
|
||||
|
||||
.icon-camera-18::before {
|
||||
content: "\ea15";
|
||||
}
|
||||
|
||||
.icon-caps-small::before {
|
||||
content: "\ea16";
|
||||
}
|
||||
|
||||
.icon-cart::before {
|
||||
content: "\ea17";
|
||||
}
|
||||
|
||||
.icon-chart-bar-32::before {
|
||||
content: "\ea18";
|
||||
}
|
||||
|
||||
.icon-chart-pie-36::before {
|
||||
content: "\ea19";
|
||||
}
|
||||
|
||||
.icon-chat-33::before {
|
||||
content: "\ea1a";
|
||||
}
|
||||
|
||||
.icon-check-2::before {
|
||||
content: "\ea1b";
|
||||
}
|
||||
|
||||
.icon-cloud-download-93::before {
|
||||
content: "\ea1c";
|
||||
}
|
||||
|
||||
.icon-cloud-upload-94::before {
|
||||
content: "\ea1d";
|
||||
}
|
||||
|
||||
.icon-coins::before {
|
||||
content: "\ea1e";
|
||||
}
|
||||
|
||||
.icon-compass-05::before {
|
||||
content: "\ea1f";
|
||||
}
|
||||
|
||||
.icon-controller::before {
|
||||
content: "\ea20";
|
||||
}
|
||||
|
||||
.icon-credit-card::before {
|
||||
content: "\ea21";
|
||||
}
|
||||
|
||||
.icon-delivery-fast::before {
|
||||
content: "\ea22";
|
||||
}
|
||||
|
||||
.icon-double-left::before {
|
||||
content: "\ea23";
|
||||
}
|
||||
|
||||
.icon-double-right::before {
|
||||
content: "\ea24";
|
||||
}
|
||||
|
||||
.icon-email-85::before {
|
||||
content: "\ea25";
|
||||
}
|
||||
|
||||
.icon-gift-2::before {
|
||||
content: "\ea26";
|
||||
}
|
||||
|
||||
.icon-globe-2::before {
|
||||
content: "\ea27";
|
||||
}
|
||||
|
||||
.icon-headphones::before {
|
||||
content: "\ea28";
|
||||
}
|
||||
|
||||
.icon-heart-2::before {
|
||||
content: "\ea29";
|
||||
}
|
||||
|
||||
.icon-html5::before {
|
||||
content: "\ea2a";
|
||||
}
|
||||
|
||||
.icon-image-02::before {
|
||||
content: "\ea2b";
|
||||
}
|
||||
|
||||
.icon-istanbul::before {
|
||||
content: "\ea2c";
|
||||
}
|
||||
|
||||
.icon-key-25::before {
|
||||
content: "\ea2d";
|
||||
}
|
||||
|
||||
.icon-laptop::before {
|
||||
content: "\ea2e";
|
||||
}
|
||||
|
||||
.icon-light-3::before {
|
||||
content: "\ea2f";
|
||||
}
|
||||
|
||||
.icon-link-72::before {
|
||||
content: "\ea30";
|
||||
}
|
||||
|
||||
.icon-lock-circle::before {
|
||||
content: "\ea31";
|
||||
}
|
||||
|
||||
.icon-map-big::before {
|
||||
content: "\ea32";
|
||||
}
|
||||
|
||||
.icon-minimal-down::before {
|
||||
content: "\ea33";
|
||||
}
|
||||
|
||||
.icon-minimal-left::before {
|
||||
content: "\ea34";
|
||||
}
|
||||
|
||||
.icon-minimal-right::before {
|
||||
content: "\ea35";
|
||||
}
|
||||
|
||||
.icon-minimal-up::before {
|
||||
content: "\ea36";
|
||||
}
|
||||
|
||||
.icon-mobile::before {
|
||||
content: "\ea37";
|
||||
}
|
||||
|
||||
.icon-molecule-40::before {
|
||||
content: "\ea38";
|
||||
}
|
||||
|
||||
.icon-money-coins::before {
|
||||
content: "\ea39";
|
||||
}
|
||||
|
||||
.icon-notes::before {
|
||||
content: "\ea3a";
|
||||
}
|
||||
|
||||
.icon-palette::before {
|
||||
content: "\ea3b";
|
||||
}
|
||||
|
||||
.icon-paper::before {
|
||||
content: "\ea3c";
|
||||
}
|
||||
|
||||
.icon-pencil::before {
|
||||
content: "\ea3d";
|
||||
}
|
||||
|
||||
.icon-pin::before {
|
||||
content: "\ea3e";
|
||||
}
|
||||
|
||||
.icon-planet::before {
|
||||
content: "\ea3f";
|
||||
}
|
||||
|
||||
.icon-puzzle-10::before {
|
||||
content: "\ea40";
|
||||
}
|
||||
|
||||
.icon-satisfied::before {
|
||||
content: "\ea41";
|
||||
}
|
||||
|
||||
.icon-scissors::before {
|
||||
content: "\ea42";
|
||||
}
|
||||
|
||||
.icon-send::before {
|
||||
content: "\ea43";
|
||||
}
|
||||
|
||||
.icon-settings-gear-63::before {
|
||||
content: "\ea44";
|
||||
}
|
||||
|
||||
.icon-settings::before {
|
||||
content: "\ea45";
|
||||
}
|
||||
|
||||
.icon-simple-add::before {
|
||||
content: "\ea46";
|
||||
}
|
||||
|
||||
.icon-simple-delete::before {
|
||||
content: "\ea47";
|
||||
}
|
||||
|
||||
.icon-simple-remove::before {
|
||||
content: "\ea48";
|
||||
}
|
||||
|
||||
.icon-single-02::before {
|
||||
content: "\ea49";
|
||||
}
|
||||
|
||||
.icon-single-copy-04::before {
|
||||
content: "\ea4a";
|
||||
}
|
||||
|
||||
.icon-sound-wave::before {
|
||||
content: "\ea4b";
|
||||
}
|
||||
|
||||
.icon-spaceship::before {
|
||||
content: "\ea4c";
|
||||
}
|
||||
|
||||
.icon-square-pin::before {
|
||||
content: "\ea4d";
|
||||
}
|
||||
|
||||
.icon-support-17::before {
|
||||
content: "\ea4e";
|
||||
}
|
||||
|
||||
.icon-tablet-2::before {
|
||||
content: "\ea4f";
|
||||
}
|
||||
|
||||
.icon-tag::before {
|
||||
content: "\ea50";
|
||||
}
|
||||
|
||||
.icon-tap-02::before {
|
||||
content: "\ea51";
|
||||
}
|
||||
|
||||
.icon-tie-bow::before {
|
||||
content: "\ea52";
|
||||
}
|
||||
|
||||
.icon-time-alarm::before {
|
||||
content: "\ea53";
|
||||
}
|
||||
|
||||
.icon-trash-simple::before {
|
||||
content: "\ea54";
|
||||
}
|
||||
|
||||
.icon-triangle-right-17::before {
|
||||
content: "\ea55";
|
||||
}
|
||||
|
||||
.icon-trophy::before {
|
||||
content: "\ea56";
|
||||
}
|
||||
|
||||
.icon-tv-2::before {
|
||||
content: "\ea57";
|
||||
}
|
||||
|
||||
.icon-upload::before {
|
||||
content: "\ea58";
|
||||
}
|
||||
|
||||
.icon-user-run::before {
|
||||
content: "\ea59";
|
||||
}
|
||||
|
||||
.icon-vector::before {
|
||||
content: "\ea5a";
|
||||
}
|
||||
|
||||
.icon-video-66::before {
|
||||
content: "\ea5b";
|
||||
}
|
||||
|
||||
.icon-volume-98::before {
|
||||
content: "\ea5c";
|
||||
}
|
||||
|
||||
.icon-wallet-43::before {
|
||||
content: "\ea5d";
|
||||
}
|
||||
|
||||
.icon-watch-time::before {
|
||||
content: "\ea5e";
|
||||
}
|
||||
|
||||
.icon-wifi::before {
|
||||
content: "\ea5f";
|
||||
}
|
||||
|
||||
.icon-world::before {
|
||||
content: "\ea60";
|
||||
}
|
||||
|
||||
.icon-zoom-split::before {
|
||||
content: "\ea61";
|
||||
}
|
||||
|
||||
.icon-refresh-01::before {
|
||||
content: "\ea62";
|
||||
}
|
||||
|
||||
.icon-refresh-02::before {
|
||||
content: "\ea63";
|
||||
}
|
||||
|
||||
.icon-shape-star::before {
|
||||
content: "\ea64";
|
||||
}
|
||||
|
||||
.icon-components::before {
|
||||
content: "\ea65";
|
||||
}
|
||||
77
src/assets/demo/demo.css
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
=========================================================
|
||||
* Black Dashboard Angular - v1.2.0
|
||||
=========================================================
|
||||
|
||||
* Product Page: https://www.creative-tim.com/product/black-dashboard-angular
|
||||
* Copyright 2020 Creative Tim (https://www.creative-tim.com)
|
||||
* Licensed under MIT (https://github.com/creativetimofficial/argon-dashboard/blob/master/LICENSE.md)
|
||||
|
||||
=========================================================
|
||||
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
*/
|
||||
.tim-row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tim-white-buttons {
|
||||
background-color: #777777;
|
||||
}
|
||||
|
||||
.typography-line {
|
||||
padding-left: 25%;
|
||||
margin-bottom: 35px;
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.typography-line span {
|
||||
bottom: 10px;
|
||||
color: #c0c1c2;
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 260px;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.tim-row {
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.tim-row h3 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.offline-doc .page-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.offline-doc .footer {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
bottom: 0;
|
||||
color: #fff;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@media all and (min-width: 992px) {
|
||||
.sidebar .nav>li.active-pro {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.card.card-upgrade .card-category {
|
||||
max-width: 530px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
BIN
src/assets/fonts/nucleo.eot
Normal file
BIN
src/assets/fonts/nucleo.ttf
Normal file
BIN
src/assets/fonts/nucleo.woff
Normal file
BIN
src/assets/fonts/nucleo.woff2
Normal file
BIN
src/assets/img/angular.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
src/assets/img/angular2-logo-red.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/assets/img/angular2-logo-white.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
src/assets/img/anime3.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src/assets/img/anime6.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
src/assets/img/apple-icon.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
src/assets/img/argon-white.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/img/bg5.jpg
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
src/assets/img/default-avatar.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
src/assets/img/emilyz.jpg
Normal file
|
After Width: | Height: | Size: 84 KiB |
BIN
src/assets/img/favicon_io/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
src/assets/img/favicon_io/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 85 KiB |
BIN
src/assets/img/favicon_io/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
src/assets/img/favicon_io/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 579 B |
BIN
src/assets/img/favicon_io/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/img/favicon_io/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
1
src/assets/img/favicon_io/site.webmanifest
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
||||