7 changed files with 3687 additions and 20 deletions
@ -1,11 +1,321 @@ |
|||
<div class="flex flex-col flex-auto min-w-0"> |
|||
<div class="flex flex-col flex-auto w-full"> |
|||
|
|||
<!-- Main --> |
|||
<div class="flex-auto p-6 sm:p-10"> |
|||
<div class="flex flex-wrap w-full max-w-screen-xl mx-auto p-6 md:p-8"> |
|||
|
|||
<!-- CONTENT GOES HERE --> |
|||
<div class="h-400 min-h-400 max-h-400 border-2 border-dashed border-gray-300 rounded-2xl"></div> |
|||
<!-- Title and action buttons --> |
|||
<div class="flex items-center justify-between w-full"> |
|||
<div> |
|||
<div class="text-3xl font-semibold tracking-tight leading-8">Analytics dashboard</div> |
|||
<div class="font-medium tracking-tight text-secondary">Monitor metrics, check statistics and review performance on Teso</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 w-full mt-8"> |
|||
<!-- Visitors overview --> |
|||
<div class="sm:col-span-2 lg:col-span-3 light flex flex-col flex-auto bg-card shadow rounded-2xl overflow-hidden"> |
|||
<div class="flex items-center justify-between mt-10 ml-10 mr-6 sm:mr-10"> |
|||
<div class="flex flex-col"> |
|||
<div class="mr-4 text-2xl md:text-3xl font-semibold tracking-tight leading-7">Visitors Overview |
|||
</div> |
|||
<div class="font-medium text-secondary">Number of unique visitors</div> |
|||
</div> |
|||
<div class="ml-2"> |
|||
<mat-button-toggle-group class="hidden sm:inline-flex border-none space-x-1" value="this-year" #visitorsYearSelector="matButtonToggleGroup"> |
|||
<mat-button-toggle class="px-1.5 rounded-full overflow-hidden border-none font-medium" value="last-year">Last Year |
|||
</mat-button-toggle> |
|||
<mat-button-toggle class="px-1.5 rounded-full overflow-hidden border-none font-medium" value="this-year">This Year |
|||
</mat-button-toggle> |
|||
</mat-button-toggle-group> |
|||
<div class="sm:hidden"> |
|||
<button mat-icon-button [matMenuTriggerFor]="visitorsMenu"> |
|||
<mat-icon [svgIcon]="'heroicons_outline:dots-vertical'"></mat-icon> |
|||
</button> |
|||
<mat-menu #visitorsMenu="matMenu"> |
|||
<button mat-menu-item>This Year</button> |
|||
<button mat-menu-item>Last Year</button> |
|||
</mat-menu> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col flex-auto h-80"> |
|||
<apx-chart class="flex-auto w-full h-full" [chart]="chartVisitors.chart" [colors]="chartVisitors.colors" [dataLabels]="chartVisitors.dataLabels" [fill]="chartVisitors.fill" [grid]="chartVisitors.grid" [series]="chartVisitors.series[visitorsYearSelector.value]" |
|||
[stroke]="chartVisitors.stroke" [tooltip]="chartVisitors.tooltip" [xaxis]="chartVisitors.xaxis" [yaxis]="chartVisitors.yaxis"> |
|||
</apx-chart> |
|||
</div> |
|||
</div> |
|||
<!-- Conversions --> |
|||
<div class="sm:col-span-2 lg:col-span-1 flex flex-col flex-auto bg-card shadow rounded-2xl overflow-hidden"> |
|||
<div class="flex items-start justify-between m-6 mb-0"> |
|||
<div class="text-lg font-medium tracking-tight leading-6 truncate">Coupon Redemptions</div> |
|||
<div class="ml-2"> |
|||
<button class="h-6 min-h-6 px-2 rounded-full bg-hover" mat-button [matMenuTriggerFor]="conversionMenu"> |
|||
<span class="font-medium text-sm text-secondary">30 days</span> |
|||
</button> |
|||
<mat-menu #conversionMenu="matMenu"> |
|||
<button mat-menu-item>30 days</button> |
|||
<button mat-menu-item>3 months</button> |
|||
<button mat-menu-item>9 months</button> |
|||
</mat-menu> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col lg:flex-row lg:items-center mx-6 mt-3"> |
|||
<div class="text-7xl font-bold tracking-tighter leading-tight">{{data.conversions.amount | number:'1.0-0'}} |
|||
</div> |
|||
<div class="flex lg:flex-col lg:ml-3"> |
|||
<mat-icon class="icon-size-5 text-red-500" [svgIcon]="'heroicons_solid:trending-down'"> |
|||
</mat-icon> |
|||
<div class="flex items-center ml-1 lg:ml-0 lg:mt-0.5 text-md leading-none whitespace-nowrap text-secondary"> |
|||
<span class="font-medium text-red-500">2%</span> |
|||
<span class="ml-1">below target</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col flex-auto h-20"> |
|||
<apx-chart class="flex-auto w-full h-full" [chart]="chartConversions.chart" [colors]="chartConversions.colors" [series]="chartConversions.series" [stroke]="chartConversions.stroke" [tooltip]="chartConversions.tooltip" [xaxis]="chartConversions.xaxis" |
|||
[yaxis]="chartConversions.yaxis"></apx-chart> |
|||
</div> |
|||
</div> |
|||
<!-- Impressions --> |
|||
<div class="flex flex-col flex-auto bg-card shadow rounded-2xl overflow-hidden"> |
|||
<div class="flex items-start justify-between m-6 mb-0"> |
|||
<div class="text-lg font-medium tracking-tight leading-6 truncate">Total Sales</div> |
|||
<div class="ml-2"> |
|||
<button class="h-6 min-h-6 px-2 rounded-full bg-hover" mat-button [matMenuTriggerFor]="impressionsMenu"> |
|||
<span class="font-medium text-sm text-secondary">30 days</span> |
|||
</button> |
|||
<mat-menu #impressionsMenu="matMenu"> |
|||
<button mat-menu-item>30 days</button> |
|||
<button mat-menu-item>3 months</button> |
|||
<button mat-menu-item>9 months</button> |
|||
</mat-menu> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col lg:flex-row lg:items-center mx-6 mt-3"> |
|||
<div class="text-7xl font-bold tracking-tighter leading-tight">{{data.impressions.amount | number:'1.0-0'}} |
|||
</div> |
|||
<div class="flex lg:flex-col lg:ml-3"> |
|||
<mat-icon class="icon-size-5 text-red-500" [svgIcon]="'heroicons_solid:trending-down'"> |
|||
</mat-icon> |
|||
<div class="flex items-center ml-1 lg:ml-0 lg:mt-0.5 text-md leading-none whitespace-nowrap text-secondary"> |
|||
<span class="font-medium text-red-500">4%</span> |
|||
<span class="ml-1">below target</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col flex-auto h-20"> |
|||
<apx-chart class="flex-auto w-full h-full" [chart]="chartImpressions.chart" [colors]="chartImpressions.colors" [series]="chartImpressions.series" [stroke]="chartImpressions.stroke" [tooltip]="chartImpressions.tooltip" [xaxis]="chartImpressions.xaxis" |
|||
[yaxis]="chartImpressions.yaxis"></apx-chart> |
|||
</div> |
|||
</div> |
|||
<!-- Visits --> |
|||
<div class="flex flex-col flex-auto bg-card shadow rounded-2xl overflow-hidden"> |
|||
<div class="flex items-start justify-between m-6 mb-0"> |
|||
<div class="text-lg font-medium tracking-tight leading-6 truncate">Visits</div> |
|||
<div class="ml-2"> |
|||
<button class="h-6 min-h-6 px-2 rounded-full bg-hover" mat-button [matMenuTriggerFor]="impressionsMenu"> |
|||
<span class="font-medium text-sm text-secondary">30 days</span> |
|||
</button> |
|||
<mat-menu #impressionsMenu="matMenu"> |
|||
<button mat-menu-item>30 days</button> |
|||
<button mat-menu-item>3 months</button> |
|||
<button mat-menu-item>9 months</button> |
|||
</mat-menu> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col lg:flex-row lg:items-center mx-6 mt-3"> |
|||
<div class="text-7xl font-bold tracking-tighter leading-tight">{{data.visits.amount | number:'1.0-0'}} |
|||
</div> |
|||
<div class="flex lg:flex-col lg:ml-3"> |
|||
<mat-icon class="icon-size-5 text-red-500" [svgIcon]="'heroicons_solid:trending-down'"> |
|||
</mat-icon> |
|||
<div class="flex items-center ml-1 lg:ml-0 lg:mt-0.5 text-md leading-none whitespace-nowrap text-secondary"> |
|||
<span class="font-medium text-red-500">4%</span> |
|||
<span class="ml-1">below target</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col flex-auto h-20"> |
|||
<apx-chart class="flex-auto w-full h-full" [chart]="chartVisits.chart" [colors]="chartVisits.colors" [series]="chartVisits.series" [stroke]="chartVisits.stroke" [tooltip]="chartVisits.tooltip" [xaxis]="chartVisits.xaxis" [yaxis]="chartVisits.yaxis"></apx-chart> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="grid grid-cols-1 xl:grid-cols-3 gap-8 w-full mt-8"> |
|||
<!-- Recent transactions table --> |
|||
<div class="xl:col-span-2 flex flex-col flex-auto bg-card shadow rounded-2xl overflow-hidden"> |
|||
<div class="p-6"> |
|||
<div class="mr-4 text-lg font-medium tracking-tight leading-6 truncate">Recent transactions</div> |
|||
<!-- <div class="text-secondary font-medium">1 pending, 4 completed</div> --> |
|||
</div> |
|||
<div class="overflow-x-auto mx-6"> |
|||
<table class="w-full bg-transparent" mat-table matSort [dataSource]="recentTransactionsDataSource" [trackBy]="trackByFn" #recentTransactionsTable> |
|||
|
|||
<!-- Transaction ID --> |
|||
<ng-container matColumnDef="transactionId"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Transaction ID |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="pr-6 font-medium text-sm text-secondary whitespace-nowrap"> |
|||
{{transaction.transactionId}} |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<!-- Date --> |
|||
<ng-container matColumnDef="date"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Date |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="pr-6 whitespace-nowrap"> |
|||
{{transaction.date | date:'MMM dd, y'}} |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<!-- Name --> |
|||
<ng-container matColumnDef="name"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Name |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="pr-6 whitespace-nowrap"> |
|||
{{transaction.name}} |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<!-- Amount --> |
|||
<ng-container matColumnDef="discount"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Amount Discounted |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="pr-6 font-medium whitespace-nowrap"> |
|||
{{(transaction.amount - 900) | currency:'GH¢'}} |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<!-- Amount --> |
|||
<ng-container matColumnDef="amount"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Amount Paid |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="pr-6 font-medium whitespace-nowrap"> |
|||
{{transaction.amount | currency:'GH¢'}} |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
</div> |
|||
<!-- Status --> |
|||
<ng-container matColumnDef="status"> |
|||
<th mat-header-cell mat-sort-header *matHeaderCellDef> |
|||
Status |
|||
</th> |
|||
<td mat-cell *matCellDef="let transaction"> |
|||
<span class="inline-flex items-center font-bold text-xs px-2.5 py-0.5 rounded-full tracking-wide uppercase" [ngClass]="{'bg-red-200 text-red-800 dark:bg-red-600 dark:text-red-50': transaction.status === 'pending', |
|||
'bg-green-200 text-green-800 dark:bg-green-600 dark:text-green-50': transaction.status === 'completed'}"> |
|||
<span class="leading-relaxed whitespace-nowrap">{{transaction.status}}</span> |
|||
</span> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<!-- Footer --> |
|||
<ng-container matColumnDef="recentOrdersTableFooter"> |
|||
<td class="py-6 px-0 border-0" mat-footer-cell *matFooterCellDef colspan="6"> |
|||
<button mat-stroked-button>See all transactions</button> |
|||
</td> |
|||
</ng-container> |
|||
|
|||
<tr mat-header-row *matHeaderRowDef="recentTransactionsTableColumns"></tr> |
|||
<tr class="order-row h-16" mat-row *matRowDef="let row; columns: recentTransactionsTableColumns;"></tr> |
|||
<tr class="h-16 border-0" mat-footer-row *matFooterRowDef="['recentOrdersTableFooter']"></tr> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Views List --> |
|||
<div class="flex flex-col flex-auto p-6 bg-card rounded-2xl shadow"> |
|||
<div class="flex items-center"> |
|||
<div class="flex flex-col"> |
|||
<div class="mr-4 text-lg font-medium tracking-tight leading-6 truncate" *ngIf="couponStats"> |
|||
Coupon Statistics</div> |
|||
<div class="mr-4 text-lg font-medium tracking-tight leading-6 truncate" *ngIf="!couponStats"> |
|||
Coupon Views</div> |
|||
<!-- <div class="text-secondary font-medium">Monthly budget summary</div> --> |
|||
</div> |
|||
<div class="ml-auto -mt-2 -mr-2"> |
|||
<button mat-icon-button (click)="switchCouponStats()"> |
|||
<mat-icon>code</mat-icon> |
|||
</button> |
|||
|
|||
</div> |
|||
</div> |
|||
<div class="mt-6" *ngIf="!couponStats"> |
|||
The following Teso users have shown interest in some of your coupons. Click to further engage them by sending them personalized coupons |
|||
</div> |
|||
<div class="mt-6" *ngIf="couponStats"> |
|||
The chart below depicts your shops top performing types of coupons |
|||
</div> |
|||
<div class="my-8 space-y-8"> |
|||
<div class="flex flex-col"> |
|||
<div class="flex items-center"> |
|||
<div class="flex items-center justify-center w-14 h-14 rounded bg-red-100 text-red-800 dark:bg-red-600 dark:text-red-50"> |
|||
<mat-icon class="text-current" [svgIcon]="'heroicons_outline:credit-card'"></mat-icon> |
|||
</div> |
|||
<div class="flex-auto ml-4 leading-none"> |
|||
<div class="text-sm font-medium text-secondary">Freebies</div> |
|||
<div class="mt-2 font-medium text-2xl">{{dataE.budget.expenses | currency:'GH¢'}}</div> |
|||
<mat-progress-bar class="mt-3 rounded-full" [color]="'warn'" [mode]="'determinate'" [value]="(dataE.budget.expenses * 100) / dataE.budget.expensesLimit"> |
|||
</mat-progress-bar> |
|||
</div> |
|||
<div class="flex items-end justify-end min-w-18 mt-auto ml-6"> |
|||
<div class="text-lg leading-none">2.6%</div> |
|||
<mat-icon class="text-green-600 icon-size-4 ml-1" [svgIcon]="'heroicons_solid:arrow-narrow-down'"></mat-icon> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col"> |
|||
<div class="flex items-center"> |
|||
<div class="flex items-center justify-center w-14 h-14 rounded bg-indigo-100 text-indigo-800 dark:bg-indigo-600 dark:text-indigo-50"> |
|||
<mat-icon class="text-current" [svgIcon]="'heroicons_outline:cash'"></mat-icon> |
|||
</div> |
|||
<div class="flex-auto ml-4 leading-none"> |
|||
<div class="text-sm font-medium text-secondary">Discount</div> |
|||
<div class="mt-2 font-medium text-2xl">{{dataE.budget.savings | currency:'GH¢'}}</div> |
|||
<mat-progress-bar class="mt-3 rounded-full" [mode]="'determinate'" [value]="(dataE.budget.savings * 100) / dataE.budget.savingsGoal"> |
|||
</mat-progress-bar> |
|||
</div> |
|||
<div class="flex items-end justify-end min-w-18 mt-auto ml-6"> |
|||
<div class="text-lg leading-none">12.7%</div> |
|||
<mat-icon class="text-red-600 icon-size-4 ml-1" [svgIcon]="'heroicons_solid:arrow-narrow-up'"></mat-icon> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div class="flex flex-col"> |
|||
<div class="flex items-center"> |
|||
<div class="flex items-center justify-center w-14 h-14 rounded bg-teal-100 text-teal-800 dark:bg-teal-600 dark:text-teal-50"> |
|||
<mat-icon class="text-current" [svgIcon]="'heroicons_outline:light-bulb'"></mat-icon> |
|||
</div> |
|||
<div class="flex-auto ml-4 leading-none"> |
|||
<div class="text-sm font-medium text-secondary">Proximity Coupons</div> |
|||
<div class="mt-2 font-medium text-2xl">{{dataE.budget.bills | currency:'GH¢'}}</div> |
|||
<mat-progress-bar class="mt-3 rounded-full" [mode]="'determinate'" [value]="(dataE.budget.bills * 100) / dataE.budget.billsLimit"></mat-progress-bar> |
|||
</div> |
|||
<div class="flex items-end justify-end min-w-18 mt-auto ml-6"> |
|||
<div class="text-lg leading-none">105.7%</div> |
|||
<mat-icon class="text-red-600 icon-size-4 ml-1" [svgIcon]="'heroicons_solid:arrow-narrow-up'"></mat-icon> |
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
|
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
File diff suppressed because it is too large
@ -0,0 +1,9 @@ |
|||
import { Route } from '@angular/router'; |
|||
import { DashboardComponent } from './dashboard.component'; |
|||
|
|||
export const dashboardRoutes: Route[] = [ |
|||
{ |
|||
path : '', |
|||
component: DashboardComponent |
|||
} |
|||
]; |
@ -0,0 +1,50 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import { HttpClient } from '@angular/common/http'; |
|||
import { BehaviorSubject, Observable } from 'rxjs'; |
|||
import { tap } from 'rxjs/operators'; |
|||
import { analytics as analyticsData } from 'app/mock-api/dashboards/analytics/data'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root' |
|||
}) |
|||
export class DashboardService |
|||
{ |
|||
private _data: BehaviorSubject<any> = new BehaviorSubject(null); |
|||
|
|||
/** |
|||
* Constructor |
|||
*/ |
|||
constructor(private _httpClient: HttpClient) |
|||
{ |
|||
} |
|||
|
|||
// -----------------------------------------------------------------------------------------------------
|
|||
// @ Accessors
|
|||
// -----------------------------------------------------------------------------------------------------
|
|||
|
|||
/** |
|||
* Getter for data |
|||
*/ |
|||
get data$(): Observable<any> |
|||
{ |
|||
return this._data.asObservable(); |
|||
} |
|||
|
|||
// -----------------------------------------------------------------------------------------------------
|
|||
// @ Public methods
|
|||
// -----------------------------------------------------------------------------------------------------
|
|||
|
|||
/** |
|||
* Get data |
|||
*/ |
|||
getData(): Observable<any> |
|||
{ |
|||
console.log(analyticsData) |
|||
return this._httpClient.get('api/dashboards/analytics').pipe( |
|||
tap((response: any) => { |
|||
console.log(response) |
|||
this._data.next(analyticsData); |
|||
}) |
|||
); |
|||
} |
|||
} |
Loading…
Reference in new issue