first commit

This commit is contained in:
Kola92
2023-04-25 09:17:32 +01:00
commit c36c04def5
274 changed files with 55044 additions and 0 deletions

View File

@@ -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>

View File

@@ -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;
}
}
}

View File

@@ -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();
});
});

View File

@@ -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";
}
}
}

View 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>

View 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;
}
}
}
}
}

View File

@@ -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();
});
});

View 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;
}
}
}

View 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> -->

View 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();
}
}

View 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>

View 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();
});
});

View 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";
}
}
}

View 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>

View 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;
}
}
}

View File

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

View File

@@ -0,0 +1,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);
// });
}
}

View 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>

View 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() {}
}

View 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>

View 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();
});
});

View 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";
}
}
}

View 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>

View 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() {}
}