ADDED Materialize theme
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"apiEndpoint": "https://localhost:5001"
|
||||
"apiEndpoint": "http://localhost:5000"
|
||||
}
|
||||
15
theme/docs/index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Modernize Angular Premium Template | Docs</title>
|
||||
<meta http-equiv="refresh"
|
||||
content="0; URL = 'https://adminmart.github.io/premium-documentation/angular/modernize/index.html'" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Modernize Angular Premium Template</h1>
|
||||
<a href="https://adminmart.github.io/premium-documentation/angular/modernize/index.html">https://adminmart.github.io/premium-documentation/angular/modernize/index.html</a>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
1
theme/figma-file/figma-file-to-download.txt
Normal file
@@ -0,0 +1 @@
|
||||
https://www.figma.com/file/vx7BDKIRGoSwxs5lItTMlD/Modernize
|
||||
14283
theme/packages/authguard/package-lock.json
generated
Normal file
46
theme/packages/authguard/package.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"name": "modernize",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^20.0.4",
|
||||
"@angular/cdk": "^20.0.3",
|
||||
"@angular/common": "^20.0.4",
|
||||
"@angular/compiler": "^20.0.4",
|
||||
"@angular/core": "^20.0.4",
|
||||
"@angular/forms": "^20.0.4",
|
||||
"@angular/material": "^20.0.3",
|
||||
"@angular/platform-browser": "^20.0.4",
|
||||
"@angular/platform-browser-dynamic": "^20.0.4",
|
||||
"@angular/router": "^20.0.4",
|
||||
"@ngx-translate/core": "^14.0.0",
|
||||
"@ngx-translate/http-loader": "^7.0.0",
|
||||
"angular-tabler-icons": "^3.26.0",
|
||||
"ngx-scrollbar": "^18.0.0",
|
||||
"rxjs": "~7.8.2",
|
||||
"sass": "^1.89.2",
|
||||
"tslib": "^2.8.1",
|
||||
"zone.js": "~0.15.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^20.0.3",
|
||||
"@angular/cli": "~20.0.3",
|
||||
"@angular/compiler-cli": "^20.0.4",
|
||||
"@types/date-fns": "^2.6.3",
|
||||
"@types/jasmine": "~5.1.8",
|
||||
"jasmine-core": "~5.8.0",
|
||||
"karma": "~6.4.4",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.1",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"typescript": "~5.8.3"
|
||||
}
|
||||
}
|
||||
35
theme/packages/authguard/src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'Angular20'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('Angular20');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement as HTMLElement;
|
||||
expect(compiled.querySelector('.content span')?.textContent).toContain('Angular20 app is running!');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,190 @@
|
||||
<mat-sidenav-container class="mainWrapper" autosize autoFocus [ngClass]="{
|
||||
'sidebarNav-mini': options.sidenavCollapsed && options.navPos !== 'top' && !resView,
|
||||
|
||||
'sidebarNav-horizontal': options.horizontal,
|
||||
cardBorder: options.cardBorder,
|
||||
|
||||
}" [dir]="options.dir!">
|
||||
<!-- ============================================================== -->
|
||||
<!-- Vertical Sidebar -->
|
||||
<!-- ============================================================== -->
|
||||
@if (!options.horizontal) {
|
||||
<mat-sidenav #leftsidenav [mode]="isOver ? 'over' : 'side'" [opened]="
|
||||
options.navPos === 'side' && options.sidenavOpened && !isOver && !resView
|
||||
" (openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||
<div class="flex-layout">
|
||||
<app-sidebar (toggleMobileNav)="sidenav.toggle()" [showToggle]="isOver"></app-sidebar>
|
||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||
<mat-nav-list class="sidebar-list">
|
||||
@for(item of navItems; track item) {
|
||||
<app-nav-item [item]="item" (notify)="sidenav.toggle()" class="top-parent">
|
||||
</app-nav-item>
|
||||
}
|
||||
</mat-nav-list>
|
||||
</ng-scrollbar>
|
||||
<div class="p-24 m-t-auto profile-bar">
|
||||
<div class="bg-light-secondary d-flex align-items-center rounded p-16">
|
||||
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle" width="40" />
|
||||
<div class="m-l-16">
|
||||
<h4 class="f-w-600">Mathew</h4>
|
||||
<span class="f-s-12">Designer</span>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<a mat-icon-button [routerLink]="['/authentication/login']" class="d-flex justify-content-center">
|
||||
<i-tabler name="power" class="text-primary icon-18 d-flex"></i-tabler>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
}
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- horizontal Sidebar -->
|
||||
<!-- ============================================================== -->
|
||||
@if (resView) {
|
||||
<mat-sidenav #leftsidenav [mode]="'over'" [opened]="options.sidenavOpened && !isTablet"
|
||||
(openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||
<app-sidebar> </app-sidebar>
|
||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||
<mat-nav-list class="sidebar-list">
|
||||
@for(item of navItems; track item) {
|
||||
<app-nav-item [item]="item" (notify)="sidenav.toggle()"> </app-nav-item>
|
||||
}
|
||||
</mat-nav-list>
|
||||
</ng-scrollbar>
|
||||
<div class="p-24 m-t-auto profile-bar">
|
||||
<div class="bg-light-secondary d-flex align-items-center rounded p-16">
|
||||
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle" width="40" />
|
||||
<div class="m-l-16">
|
||||
<h4 class="f-w-600">Mathew</h4>
|
||||
<span class="f-s-12">Designer</span>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<a mat-icon-button [routerLink]="['/authentication/login']" class="d-flex justify-content-center">
|
||||
<i-tabler name="power" class="text-primary icon-18 d-flex"></i-tabler>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
}
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main Content -->
|
||||
<!-- ============================================================== -->
|
||||
<mat-sidenav-content class="contentWrapper" #content>
|
||||
<!-- ============================================================== -->
|
||||
<!-- VerticalHeader -->
|
||||
<!-- ============================================================== -->
|
||||
@if (!options.horizontal) {
|
||||
<app-header [showToggle]="!isOver" (toggleCollapsed)="toggleCollapsed()" (toggleMobileNav)="sidenav.toggle()"
|
||||
(toggleMobileFilterNav)="toggleFilterNav()" (optionsChange)="receiveOptions($event)"></app-header>
|
||||
} @else {
|
||||
<!-- horizontal header -->
|
||||
<app-horizontal-header (toggleMobileNav)="sidenav.toggle()" (toggleMobileFilterNav)="toggleFilterNav()"
|
||||
(optionsChange)="receiveOptions($event)"></app-horizontal-header>
|
||||
} @if(options.horizontal) {
|
||||
<app-horizontal-sidebar></app-horizontal-sidebar>
|
||||
}
|
||||
|
||||
<main class="pageWrapper" [ngClass]="{
|
||||
maxWidth: options.boxed
|
||||
}">
|
||||
<app-breadcrumb></app-breadcrumb>
|
||||
<!-- ============================================================== -->
|
||||
<!-- Outlet -->
|
||||
<!-- ============================================================== -->
|
||||
<router-outlet></router-outlet>
|
||||
<div class="customizerBtn">
|
||||
<button mat-fab class="bg-primary text-white" (click)="customizerRight.toggle()">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- ------------------------------------------------------------------
|
||||
Mobile Apps Sidebar
|
||||
------------------------------------------------------------------ -->
|
||||
<div [class.open]="isFilterNavOpen" class="filter-sidebar">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="branding">
|
||||
@if(options.theme === 'light') {
|
||||
<a href="/">
|
||||
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||
</a>
|
||||
} @else {
|
||||
<a href="/">
|
||||
<img src="./assets/images/logos/light-logo.svg" class="align-middle m-2" alt="logo" />
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<button mat-icon-button (click)="isFilterNavOpen = !isFilterNavOpen" class="d-flex justify-content-center">
|
||||
<i-tabler name="x" class="icon-18 d-flex"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel class="shadow-none">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="f-s-16 f-w-500"> Apps </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div>
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.img) {
|
||||
<div class="col-12 text-hover-primary">
|
||||
<a [routerLink]="[appdd.link]" class="d-flex align-items-center text-decoration-none m-b-24 gap-16">
|
||||
<button mat-mini-fab class="text-primary bg-light-primary shadow-none rounded">
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<h5 class="f-s-14 f-w-600 m-0 textprimary f-s-14 hover-text">
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class="f-s-14 f-s-12">{{ appdd.subtitle }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a [routerLink]="['quicklink.link']"
|
||||
class="hover-text text-decoration-none f-s-14 f-w-600 d-block p-y-8">{{ quicklink.title }}</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
||||
<div class="p-x-16">
|
||||
<a [routerLink]="['/']" class="d-flex align-items-center text-decoration-none f-s-14 p-y-16 gap-8">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Calendar</span>
|
||||
</a>
|
||||
<a [routerLink]="['/']" class="d-flex align-items-center text-decoration-none f-s-14 p-y-16">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Chat</span>
|
||||
</a>
|
||||
<a [routerLink]="['/']" class="d-flex align-items-center text-decoration-none f-s-14 p-y-16 gap-8">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Email</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
|
||||
<mat-sidenav #customizerRight mode="over" position="end" class="customizerNav">
|
||||
<div class="p-x-16 p-y-20 d-flex align-items-center justify-content-between b-b-1">
|
||||
<h3 class="f-s-21 f-w-600">Settings</h3>
|
||||
|
||||
<a mat-icon-button (click)="customizerRight.toggle()" class="d-flex justify-content-center">
|
||||
<mat-icon>close</mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<app-customizer (optionsChange)="receiveOptions($event)"></app-customizer>
|
||||
</mat-sidenav>
|
||||
</mat-sidenav-container>
|
||||
@@ -0,0 +1,296 @@
|
||||
<mat-toolbar class="topbar horizontal-topbar ">
|
||||
<div class="container">
|
||||
<div class="d-none d-sm-flex">
|
||||
<app-branding></app-branding>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileNav.emit()"
|
||||
class="d-flex align-items-center justify-content-center d-lg-none m-x-4"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Search -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button mat-icon-button (click)="openDialog()" class="d-flex align-items-center justify-content-center m-x-4">
|
||||
<i-tabler name="search" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<div class="d-none d-lg-flex">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Links -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-button
|
||||
[matMenuTriggerFor]="appsmenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
Apps <i-tabler name="chevron-down" class="icon-16 m-l-4"></i-tabler>
|
||||
</div>
|
||||
</button>
|
||||
<mat-menu #appsmenu="matMenu" class="apps-dd cardWithShadow">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 b-r-1 p-r-0">
|
||||
<div class="p-32 p-b-0">
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.title) {
|
||||
<div class="col-sm-6 text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[appdd.link]"
|
||||
class="d-flex align-items-center text-decoration-none m-b-24"
|
||||
>
|
||||
<span
|
||||
class="text-primary bg-light rounded icon-40 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</span>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class=" f-s-12">{{
|
||||
appdd.subtitle
|
||||
}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="b-t-1 p-24 d-none d-lg-flex align-items-center justify-content-between"
|
||||
>
|
||||
<span
|
||||
class="d-flex align-items-center f-s-16 f-w-500"
|
||||
>
|
||||
<i-tabler name="help" class="icon-20 m-r-8"></i-tabler
|
||||
>Frequently Asked Questions
|
||||
</span>
|
||||
<a
|
||||
[routerLink]="['/theme-pages/faq']"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
>Check</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="p-x-16 p-y-32">
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[quicklink.link]"
|
||||
class="hover-text text-decoration-none f-w-600 d-block p-y-8"
|
||||
>{{ quicklink.title }}</a
|
||||
>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-menu>
|
||||
<a mat-button [routerLink]="['/']">Chat</a>
|
||||
<a mat-button [routerLink]="['/']">Calendar</a>
|
||||
<a mat-button [routerLink]="['/']">Email</a>
|
||||
</div>
|
||||
|
||||
<span class="flex-1-auto"></span>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileFilterNav.emit()"
|
||||
class="d-flex d-lg-none justify-content-center m-x-4"
|
||||
>
|
||||
<i-tabler name="grid-dots" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- langugage Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button [matMenuTriggerFor]="flags" mat-icon-button class="m-x-4">
|
||||
<img
|
||||
[src]="selectedLanguage.icon"
|
||||
class="rounded-circle object-cover icon-20"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #flags="matMenu" class="cardWithShadow">
|
||||
@for(lang of languages; track lang.icon) {
|
||||
<button mat-menu-item (click)="changeLanguage(lang)">
|
||||
<div class="d-flex align-items-center">
|
||||
<img
|
||||
[src]="lang.icon"
|
||||
class="rounded-circle object-cover m-r-8 icon-20"
|
||||
/>
|
||||
<span class=" f-s-14">{{ lang.language }}</span>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</mat-menu>
|
||||
|
||||
@if(options.theme=='light'){
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('dark')" >
|
||||
<i-tabler class="d-flex icon-22" [name]="'moon'"></i-tabler>
|
||||
</button>
|
||||
}@else{
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('light')">
|
||||
<i-tabler class="d-flex icon-22" [name]="'sun'"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Notification Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button matBadge="5"
|
||||
[matMenuTriggerFor]="notificationmenu"
|
||||
aria-label="Notifications" class="m-x-4 notification-badge"
|
||||
>
|
||||
<i-tabler
|
||||
class="d-flex"
|
||||
name="bell"
|
||||
></i-tabler>
|
||||
</button>
|
||||
<mat-menu
|
||||
#notificationmenu="matMenu"
|
||||
xPosition="before"
|
||||
class="topbar-dd cardWithShadow"
|
||||
>
|
||||
<div class="d-flex align-items-center p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">Notifications</h6>
|
||||
<span class="m-l-auto">
|
||||
<span class="bg-primary text-white p-x-8 p-y-4 f-w-500 rounded f-s-12"
|
||||
>5 new</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
@for(notification of notifications; track notification.title) {
|
||||
<button mat-menu-item class="p-x-32 p-y-16">
|
||||
<div class="d-flex align-items-center">
|
||||
<img [src]="notification.img" class="rounded-circle" width="48" />
|
||||
<div class="m-l-16">
|
||||
<h5 class="f-s-14 f-w-600 m-0 ">
|
||||
{{ notification.title }}
|
||||
</h5>
|
||||
<span>{{ notification.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<button mat-stroked-button color="primary" class="w-100">
|
||||
See all notifications
|
||||
</button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- profile Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="profilemenu"
|
||||
aria-label="Notifications" class="m-l-4"
|
||||
>
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle object-cover icon-35 profile-dd"
|
||||
width="35"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu
|
||||
#profilemenu="matMenu"
|
||||
xPosition="before"
|
||||
class="topbar-dd cardWithShadow"
|
||||
>
|
||||
<div class="p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">User Profile</h6>
|
||||
|
||||
<div class="d-flex align-items-center p-b-24 b-b-1 m-t-16">
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle"
|
||||
width="95"
|
||||
/>
|
||||
<div class="m-l-16">
|
||||
<h6 class="f-s-14 f-w-600 m-0 ">Mathew Anderson</h6>
|
||||
<span class="f-s-14 d-block m-b-4">Designer</span>
|
||||
<span class="d-flex align-items-center">
|
||||
<i-tabler name="mail" class="icon-15 m-r-4"></i-tabler>
|
||||
info@modernize.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-x-32">
|
||||
@for(profile of profiledd; track profile.title) {
|
||||
<a
|
||||
class="p-y-16 text-decoration-none d-block text-hover-primary"
|
||||
[routerLink]="[profile.link]"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
class="text-primary bg-light shadow-none rounded"
|
||||
>
|
||||
<img [src]="profile.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ profile.title }}
|
||||
</h5>
|
||||
<span class="">{{ profile.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
<!-- upgrade -->
|
||||
<div
|
||||
class="p-24 overflow-hidden bg-light-primary rounded position-relative m-y-16"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<h5 class="f-s-18 m-0 f-w-600 m-b-12 ">
|
||||
Unlimited <br />
|
||||
Access
|
||||
</h5>
|
||||
<button mat-flat-button color="primary">Upgrade</button>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<img
|
||||
src="/assets/images/backgrounds/unlimited-bg.png"
|
||||
alt="upgrade-bg"
|
||||
class="upgrade-bg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<a
|
||||
[routerLink]="['/authentication/login']"
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="w-100"
|
||||
>Logout</a
|
||||
>
|
||||
</div>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { Router, NavigationEnd, ActivatedRoute, Data } from '@angular/router';
|
||||
import { filter, map, mergeMap } from 'rxjs/operators';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
|
||||
@Component({
|
||||
selector: 'app-breadcrumb',
|
||||
imports: [RouterModule, TablerIconsModule],
|
||||
templateUrl: './breadcrumb.component.html',
|
||||
styleUrls: [],
|
||||
})
|
||||
export class AppBreadcrumbComponent {
|
||||
// @Input() layout;
|
||||
pageInfo: Data | any = Object.create(null);
|
||||
myurl: any = this.router.url.slice(1).split('/');
|
||||
constructor(
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private titleService: Title
|
||||
) {
|
||||
this.router.events
|
||||
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||
.pipe(map(() => this.activatedRoute))
|
||||
.pipe(
|
||||
map((route) => {
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild;
|
||||
}
|
||||
return route;
|
||||
})
|
||||
)
|
||||
.pipe(filter((route) => route.outlet === 'primary'))
|
||||
.pipe(mergeMap((route) => route.data))
|
||||
// tslint:disable-next-line - Disables all
|
||||
.subscribe((event) => {
|
||||
// tslint:disable-next-line - Disables all
|
||||
this.titleService.setTitle(event['title'] + ' - Angular 20');
|
||||
this.pageInfo = event;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,300 @@
|
||||
<mat-toolbar class="topbar gap-10">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Desktop Menu -->
|
||||
@if(showToggle) {
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleCollapsed.emit()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
@if(!showToggle) {
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileNav.emit()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Search -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="openDialog()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="search" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<div class="d-none d-lg-flex">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Links -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-button
|
||||
[matMenuTriggerFor]="appsmenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
Apps <i-tabler name="chevron-down" class="icon-16 m-l-4"></i-tabler>
|
||||
</div>
|
||||
</button>
|
||||
<mat-menu #appsmenu="matMenu" class="apps-dd cardWithShadow">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 b-r-1 p-r-0">
|
||||
<div class="p-32 p-b-0">
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.title) {
|
||||
<div class="col-sm-6 text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[appdd.link]"
|
||||
class="d-flex align-items-center text-decoration-none m-b-24"
|
||||
>
|
||||
<span
|
||||
class="bg-light rounded icon-40 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</span>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 hover-text"
|
||||
>
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class=" f-s-12 text-body">{{ appdd.subtitle }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="b-t-1 p-24 d-none d-lg-flex align-items-center justify-content-between"
|
||||
>
|
||||
<span
|
||||
class="d-flex align-items-center f-s-16 f-w-500"
|
||||
>
|
||||
<i-tabler name="help" class="icon-20 m-r-8"></i-tabler>Frequently
|
||||
Asked Questions
|
||||
</span>
|
||||
<a
|
||||
[routerLink]="['/theme-pages/faq']"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
>Check</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="p-x-16 p-y-32">
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[quicklink.link]"
|
||||
class="hover-text text-decoration-none f-w-600 d-block p-y-8"
|
||||
>{{ quicklink.title }}</a
|
||||
>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-menu>
|
||||
<a mat-button [routerLink]="['/apps/chat']">Chat</a>
|
||||
<a mat-button [routerLink]="['/apps/calendar']">Calendar</a>
|
||||
<a mat-button [routerLink]="['/apps/email/inbox']">Email</a>
|
||||
</div>
|
||||
|
||||
<span class="flex-1-auto"></span>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileFilterNav.emit()"
|
||||
class="d-flex d-lg-none justify-content-center"
|
||||
>
|
||||
<i-tabler name="grid-dots" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- langugage Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button [matMenuTriggerFor]="flags" mat-icon-button class="m-r-5">
|
||||
<img
|
||||
[src]="selectedLanguage.icon"
|
||||
class="rounded-circle object-cover icon-20"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #flags="matMenu" class="cardWithShadow">
|
||||
@for(lang of languages; track lang.icon) {
|
||||
<button mat-menu-item (click)="changeLanguage(lang)">
|
||||
<div class="d-flex align-items-center">
|
||||
<img
|
||||
[src]="lang.icon"
|
||||
class="rounded-circle object-cover m-r-8 icon-20"
|
||||
/>
|
||||
<span class=" f-s-14">{{ lang.language }}</span>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</mat-menu>
|
||||
@if(options.theme=='light'){
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('dark')" >
|
||||
<i-tabler class="d-flex icon-22" [name]="'moon'"></i-tabler>
|
||||
</button>
|
||||
}@else{
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('light')">
|
||||
<i-tabler class="d-flex icon-22" [name]="'sun'"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Notification Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button matBadge="5"
|
||||
[matMenuTriggerFor]="notificationmenu"
|
||||
aria-label="Notifications" class="notification-badge"
|
||||
>
|
||||
<i-tabler
|
||||
class="d-flex"
|
||||
name="bell"
|
||||
></i-tabler>
|
||||
</button>
|
||||
<mat-menu #notificationmenu="matMenu" class="topbar-dd cardWithShadow">
|
||||
<div class="d-flex align-items-center p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">Notifications</h6>
|
||||
<span class="m-l-auto">
|
||||
<span class="bg-primary text-white p-x-8 p-y-4 f-w-500 rounded f-s-12"
|
||||
>5 new</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@for(notification of notifications; track notification.title) {
|
||||
<button mat-menu-item class="p-x-32 p-y-16">
|
||||
<div class="d-flex align-items-center">
|
||||
<img [src]="notification.img" class="rounded-circle" width="48" />
|
||||
<div class="m-l-16">
|
||||
<h5 class="f-s-14 f-w-600 m-0 ">
|
||||
{{ notification.title }}
|
||||
</h5>
|
||||
<span>{{ notification.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<button mat-stroked-button color="primary" class="w-100">
|
||||
See all notifications
|
||||
</button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- profile Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="profilemenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle object-cover icon-35 profile-dd"
|
||||
width="35"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #profilemenu="matMenu" class="topbar-dd cardWithShadow">
|
||||
<ng-scrollbar class="position-relative" style="height: 647px">
|
||||
<div class="p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">User Profile</h6>
|
||||
|
||||
<div class="d-flex align-items-center p-b-24 b-b-1 m-t-16">
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle"
|
||||
width="95"
|
||||
/>
|
||||
<div class="m-l-16">
|
||||
<h6 class="f-s-14 f-w-600 m-0 ">Mathew Anderson</h6>
|
||||
<span class="f-s-14 d-block m-b-4">Designer</span>
|
||||
<span class="d-flex align-items-center">
|
||||
<i-tabler name="mail" class="icon-15 m-r-4"></i-tabler>
|
||||
info@modernize.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-x-32">
|
||||
@for(profile of profiledd; track profile.title) {
|
||||
<a
|
||||
class="p-y-16 text-decoration-none d-block text-hover-primary"
|
||||
[routerLink]="[profile.link]"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
class="text-primary bg-light shadow-none rounded"
|
||||
>
|
||||
<img [src]="profile.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ profile.title }}
|
||||
</h5>
|
||||
<span class="text-body">{{ profile.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
<!-- upgrade -->
|
||||
<div
|
||||
class="p-24 overflow-hidden bg-light rounded position-relative m-y-16"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<h5 class="f-s-18 m-0 f-w-600 m-b-12 ">
|
||||
Unlimited <br />
|
||||
Access
|
||||
</h5>
|
||||
<button mat-flat-button color="primary">Upgrade</button>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<img
|
||||
src="/assets/images/backgrounds/unlimited-bg.png"
|
||||
alt="upgrade-bg"
|
||||
class="upgrade-bg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<a
|
||||
[routerLink]="['/authentication/login']"
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="w-100"
|
||||
>Logout</a
|
||||
>
|
||||
</div>
|
||||
</ng-scrollbar>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
153
theme/packages/authguard/src/assets/scss/_container.scss
Normal file
@@ -0,0 +1,153 @@
|
||||
@use "variables" as *;
|
||||
|
||||
*,
|
||||
:after,
|
||||
:before {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: $font-family;
|
||||
line-height: 1.334rem;
|
||||
overflow-x: hidden;
|
||||
color: var(--mat-sys-on-background);
|
||||
}
|
||||
|
||||
.mainWrapper {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
padding-left: 24px;
|
||||
padding-right: 24px;
|
||||
margin: 0 auto;
|
||||
|
||||
&.full-width {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.pageWrapper {
|
||||
padding: 24px;
|
||||
min-height: calc(100vh - 70px);
|
||||
|
||||
margin: 0 auto;
|
||||
|
||||
&.maxWidth {
|
||||
max-width: $boxedWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.w-100 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.h-100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.shadow-none {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: $border-radius !important;
|
||||
}
|
||||
|
||||
.rounded-circle {
|
||||
border-radius: 50% !important;
|
||||
}
|
||||
|
||||
.rounded-pill {
|
||||
border-radius: 25px !important;
|
||||
}
|
||||
|
||||
.overflow-hidden {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.text-decoration-none {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.position-relative {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.table-responsive {
|
||||
overflow-x: auto;
|
||||
|
||||
td,
|
||||
mat-cell {
|
||||
white-space: nowrap;
|
||||
padding: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.op-5 {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatar-group {
|
||||
img {
|
||||
border: 2px solid $white;
|
||||
margin-right: -5px;
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--mat-sys-on-background);
|
||||
|
||||
&:hover {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-sidebar {
|
||||
width: 290px;
|
||||
position: fixed;
|
||||
right: -290px;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
height: 100%;
|
||||
transition: all 0.3s ease-in-out;
|
||||
box-shadow: var(--mat-sys-level3);
|
||||
background-color: var(--mat-sys-background);
|
||||
&.open {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
td.hljs-ln-line.hljs-ln-numbers {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
html .flex-sm-row {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-drawer[style*="visibility: hidden"] {
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
@use "../variables" as *;
|
||||
|
||||
html .topbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 9;
|
||||
height: $header-height;
|
||||
|
||||
.notification-badge{
|
||||
.mat-badge-content{
|
||||
left: 80%;
|
||||
bottom: 85%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.topbar-dd {
|
||||
min-width: 360px !important;
|
||||
}
|
||||
|
||||
.apps-dd {
|
||||
min-width: 830px !important;
|
||||
overflow: unset !important;
|
||||
|
||||
.mat-mdc-menu-content {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.text-hover-primary:hover {
|
||||
.hover-text {
|
||||
color: $primary;
|
||||
}
|
||||
}
|
||||
|
||||
.upgrade-bg {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.object-cover {
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.profile-dd {
|
||||
margin-top: -5px;
|
||||
margin-left: -5px;
|
||||
}
|
||||
|
||||
.dark-theme {
|
||||
.topbar {
|
||||
.mat-mdc-icon-button {
|
||||
color: $dark-text-secondary !important;
|
||||
}
|
||||
|
||||
.mdc-button {
|
||||
--mdc-text-button-label-text-color: $dark-text-secondary !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
126
theme/packages/dark/angular.json
Normal file
@@ -0,0 +1,126 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"Modernize": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:application",
|
||||
"options": {
|
||||
"allowedCommonJsDependencies": ["apexcharts", "bezier-easing", "chance"],
|
||||
"outputPath": {
|
||||
"base": "dist/Modernize"
|
||||
},
|
||||
"index": "src/index.html",
|
||||
"polyfills": ["zone.js"],
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": [
|
||||
|
||||
"src/styles.scss",
|
||||
"src/assets/scss/style.scss",
|
||||
"node_modules/ngx-toastr/toastr.css",
|
||||
"node_modules/angular-calendar/css/angular-calendar.css",
|
||||
"node_modules/highlight.js/styles/atom-one-dark.min.css"
|
||||
],
|
||||
"scripts": [],
|
||||
"browser": "src/main.ts"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "12mb",
|
||||
"maximumError": "12mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "12mb",
|
||||
"maximumError": "12mb"
|
||||
}
|
||||
],
|
||||
"outputHashing": "all"
|
||||
},
|
||||
"development": {
|
||||
"optimization": false,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular/build:dev-server",
|
||||
"configurations": {
|
||||
"production": {
|
||||
"buildTarget": "Modernize:build:production"
|
||||
},
|
||||
"development": {
|
||||
"buildTarget": "Modernize:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular/build:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "Modernize:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular/build:karma",
|
||||
"options": {
|
||||
"polyfills": ["zone.js", "zone.js/testing"],
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": ["src/favicon.ico", "src/assets"],
|
||||
"styles": ["src/styles.scss"],
|
||||
"scripts": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"analytics": false
|
||||
},
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"type": "component"
|
||||
},
|
||||
"@schematics/angular:directive": {
|
||||
"type": "directive"
|
||||
},
|
||||
"@schematics/angular:service": {
|
||||
"type": "service"
|
||||
},
|
||||
"@schematics/angular:guard": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:interceptor": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:module": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:pipe": {
|
||||
"typeSeparator": "."
|
||||
},
|
||||
"@schematics/angular:resolver": {
|
||||
"typeSeparator": "."
|
||||
}
|
||||
}
|
||||
}
|
||||
62
theme/packages/dark/package.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "modernize",
|
||||
"version": "3.1.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"watch": "ng build --watch --configuration development",
|
||||
"test": "ng test"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@angular/animations": "^20.0.4",
|
||||
"@angular/cdk": "^20.0.3",
|
||||
"@angular/common": "^20.0.4",
|
||||
"@angular/compiler": "^20.0.4",
|
||||
"@angular/core": "^20.0.4",
|
||||
"@angular/forms": "^20.0.4",
|
||||
"@angular/material": "^20.0.3",
|
||||
"@angular/platform-browser": "^20.0.4",
|
||||
"@angular/platform-browser-dynamic": "^20.0.4",
|
||||
"@angular/router": "^20.0.4",
|
||||
"@ng-matero/extensions": "^20.1.0",
|
||||
"@ngx-translate/core": "^16.0.4",
|
||||
"@ngx-translate/http-loader": "^16.0.1",
|
||||
"angular-calendar": "^0.31.1",
|
||||
"angular-tabler-icons": "^3.26.0",
|
||||
"apexcharts": "^4.7.0",
|
||||
"chance": "^1.1.13",
|
||||
"date-fns": "^4.1.0",
|
||||
"highlight.js": "^11.11.1",
|
||||
"ng-apexcharts": "^1.16.0",
|
||||
"ng2-search-filter": "^0.5.1",
|
||||
"ngx-dropzone": "^3.1.0",
|
||||
"ngx-editor": "^19.0.0-beta.1",
|
||||
"ngx-highlightjs": "^14.0.1",
|
||||
"ngx-owl-carousel-o": "^20.0.0",
|
||||
"ngx-pagination": "^6.0.3",
|
||||
"ngx-permissions": "^19.0.0",
|
||||
"ngx-scrollbar": "^18.0.0",
|
||||
"ngx-toastr": "^19.0.0",
|
||||
"rxjs": "~7.8.2",
|
||||
"sass": "^1.89.2",
|
||||
"tslib": "^2.8.1",
|
||||
"zone.js": "~0.15.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/build": "^20.0.3",
|
||||
"@angular/cli": "~20.0.3",
|
||||
"@angular/compiler-cli": "^20.0.4",
|
||||
"@types/chance": "^1.1.6",
|
||||
"@types/date-fns": "^2.6.3",
|
||||
"@types/jasmine": "~5.1.8",
|
||||
"jasmine-core": "~5.8.0",
|
||||
"karma": "~6.4.4",
|
||||
"karma-chrome-launcher": "~3.2.0",
|
||||
"karma-coverage": "~2.2.1",
|
||||
"karma-jasmine": "~5.1.0",
|
||||
"karma-jasmine-html-reporter": "~2.1.0",
|
||||
"typescript": "~5.8.3"
|
||||
}
|
||||
}
|
||||
107
theme/packages/dark/src/app/app.routes.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { BlankComponent } from './layouts/blank/blank.component';
|
||||
import { FullComponent } from './layouts/full/full.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: FullComponent,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirectTo: '/dashboards/dashboard1',
|
||||
pathMatch: 'full',
|
||||
},
|
||||
{
|
||||
path: 'starter',
|
||||
loadChildren: () =>
|
||||
import('./pages/pages.routes').then((m) => m.PagesRoutes),
|
||||
},
|
||||
{
|
||||
path: 'dashboards',
|
||||
loadChildren: () =>
|
||||
import('./pages/dashboards/dashboards.routes').then(
|
||||
(m) => m.DashboardsRoutes
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
path: 'forms',
|
||||
loadChildren: () =>
|
||||
import('./pages/forms/forms.routes').then((m) => m.FormsRoutes),
|
||||
},
|
||||
{
|
||||
path: 'charts',
|
||||
loadChildren: () =>
|
||||
import('./pages/charts/charts.routes').then((m) => m.ChartsRoutes),
|
||||
},
|
||||
{
|
||||
path: 'apps',
|
||||
loadChildren: () =>
|
||||
import('./pages/apps/apps.routes').then((m) => m.AppsRoutes),
|
||||
},
|
||||
{
|
||||
path: 'widgets',
|
||||
loadChildren: () =>
|
||||
import('./pages/widgets/widgets.routes').then((m) => m.WidgetsRoutes),
|
||||
},
|
||||
{
|
||||
path: 'tables',
|
||||
loadChildren: () =>
|
||||
import('./pages/tables/tables.routes').then((m) => m.TablesRoutes),
|
||||
},
|
||||
{
|
||||
path: 'datatable',
|
||||
loadChildren: () =>
|
||||
import('./pages/datatable/datatable.routes').then(
|
||||
(m) => m.DatatablesRoutes
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'theme-pages',
|
||||
loadChildren: () =>
|
||||
import('./pages/theme-pages/theme-pages.routes').then(
|
||||
(m) => m.ThemePagesRoutes
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'ui-components',
|
||||
loadChildren: () =>
|
||||
import('./pages/ui-components/ui-components.routes').then(
|
||||
(m) => m.UiComponentsRoutes
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: BlankComponent,
|
||||
children: [
|
||||
{
|
||||
path: 'authentication',
|
||||
loadChildren: () =>
|
||||
import('./pages/authentication/authentication.routes').then(
|
||||
(m) => m.AuthenticationRoutes
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'landingpage',
|
||||
loadChildren: () =>
|
||||
import('./pages/theme-pages/landingpage/landingpage.routes').then(
|
||||
(m) => m.LandingPageRoutes
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'front-pages',
|
||||
loadChildren: () =>
|
||||
import('./pages/front-pages/front-pages.routes').then(
|
||||
(m) => m.FrontPagesRoutes
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'authentication/error',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,55 @@
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-header>
|
||||
<mat-card-title>Yearly Breakup</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="row">
|
||||
<div class="col-7">
|
||||
<h4 class="f-s-24">$36,358</h4>
|
||||
<div class="d-flex align-items-center m-t-16">
|
||||
<button
|
||||
mat-mini-fab
|
||||
class="bg-light-success text-success shadow-none icon-27 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<i-tabler name="arrow-up-right" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
<div class="f-s-14 f-w-600 m-l-12">+9%</div>
|
||||
<div class="f-s-14 f-w-400 m-l-4">last year</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center m-t-32">
|
||||
<div class="d-flex align-items-center">
|
||||
<i-tabler
|
||||
name="circle-filled"
|
||||
class="text-primary icon-12 d-flex"
|
||||
></i-tabler>
|
||||
<div class="f-s-14 f-w-400 m-l-12">2025</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center m-l-16">
|
||||
<i-tabler
|
||||
name="circle-filled"
|
||||
class="text-light-primary icon-12 d-flex"
|
||||
></i-tabler>
|
||||
<div class="f-s-14 f-w-400 m-l-12">2024</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-5">
|
||||
<!-- ---------------------------- -->
|
||||
<!-- charts here -->
|
||||
<!-- ---------------------------- -->
|
||||
<apx-chart
|
||||
[series]="yearlyChart.series"
|
||||
[dataLabels]="yearlyChart.dataLabels"
|
||||
[chart]="yearlyChart.chart"
|
||||
[legend]="yearlyChart.legend"
|
||||
[colors]="yearlyChart.colors"
|
||||
[stroke]="yearlyChart.stroke"
|
||||
[tooltip]="yearlyChart.tooltip"
|
||||
[plotOptions]="yearlyChart.plotOptions"
|
||||
[responsive]="yearlyChart.responsive"
|
||||
></apx-chart>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
25
theme/packages/dark/src/app/config.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export interface AppSettings {
|
||||
dir: 'ltr' | 'rtl';
|
||||
theme: string;
|
||||
sidenavOpened: boolean;
|
||||
sidenavCollapsed: boolean;
|
||||
boxed: boolean;
|
||||
horizontal: boolean;
|
||||
activeTheme: string;
|
||||
language: string;
|
||||
cardBorder: boolean;
|
||||
navPos: 'side' | 'top';
|
||||
}
|
||||
|
||||
export const defaults: AppSettings = {
|
||||
dir: 'ltr',
|
||||
theme: 'dark',
|
||||
sidenavOpened: false,
|
||||
sidenavCollapsed: false,
|
||||
boxed: true,
|
||||
horizontal: false,
|
||||
cardBorder: false,
|
||||
activeTheme: 'blue_theme',
|
||||
language: 'en-us',
|
||||
navPos: 'side',
|
||||
};
|
||||
197
theme/packages/dark/src/app/layouts/full/full.component.html
Normal file
@@ -0,0 +1,197 @@
|
||||
<span [dir]="options.dir!">
|
||||
<mat-sidenav-container class="mainWrapper" autosize autoFocus [ngClass]="{
|
||||
'sidebarNav-mini':
|
||||
options.sidenavCollapsed && options.navPos !== 'top' && !resView,
|
||||
'sidebarNav-horizontal': options.horizontal,
|
||||
cardBorder: options.cardBorder
|
||||
}">
|
||||
<!-- ============================================================== -->
|
||||
<!-- Vertical Sidebar -->
|
||||
<!-- ============================================================== -->
|
||||
@if (!options.horizontal) {
|
||||
<mat-sidenav #leftsidenav [mode]="isOver ? 'over' : 'side'" [opened]="
|
||||
options.navPos === 'side' &&
|
||||
options.sidenavOpened &&
|
||||
!isOver &&
|
||||
!resView
|
||||
" (openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||
<div class="flex-layout">
|
||||
<app-sidebar (toggleMobileNav)="sidenav.toggle()" [showToggle]="isOver"></app-sidebar>
|
||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||
<mat-nav-list class="sidebar-list">
|
||||
@for(item of navItems; track item) {
|
||||
<app-nav-item [item]="item" (notify)="sidenav.toggle()" class="top-parent">
|
||||
</app-nav-item>
|
||||
}
|
||||
</mat-nav-list>
|
||||
</ng-scrollbar>
|
||||
<div class="p-24 m-t-auto profile-bar">
|
||||
<div class="bg-light-secondary d-flex align-items-center rounded p-16">
|
||||
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle" width="40" />
|
||||
<div class="m-l-16">
|
||||
<h4 class="f-w-600">Mathew</h4>
|
||||
<span class="f-s-12">Designer</span>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<a mat-icon-button [routerLink]="['/authentication/login']" class="d-flex justify-content-center">
|
||||
<i-tabler name="power" class="text-primary icon-18 d-flex"></i-tabler>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
}
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- horizontal Sidebar -->
|
||||
<!-- ============================================================== -->
|
||||
@if (resView) {
|
||||
<mat-sidenav #leftsidenav [mode]="'over'" [opened]="options.sidenavOpened && !isTablet"
|
||||
(openedChange)="onSidenavOpenedChange($event)" (closedStart)="onSidenavClosedStart()" class="sidebarNav">
|
||||
<app-sidebar> </app-sidebar>
|
||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||
<mat-nav-list class="sidebar-list">
|
||||
@for(item of navItems; track item) {
|
||||
<app-nav-item [item]="item" (notify)="sidenav.toggle()">
|
||||
</app-nav-item>
|
||||
}
|
||||
</mat-nav-list>
|
||||
</ng-scrollbar>
|
||||
<div class="p-24 m-t-auto profile-bar">
|
||||
<div class="bg-light-secondary d-flex align-items-center rounded p-16">
|
||||
<img src="/assets/images/profile/user-1.jpg" class="rounded-circle" width="40" />
|
||||
<div class="m-l-16">
|
||||
<h4 class="f-w-600">Mathew</h4>
|
||||
<span class="f-s-12">Designer</span>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<a mat-icon-button [routerLink]="['/authentication/login']" class="d-flex justify-content-center">
|
||||
<i-tabler name="power" class="text-primary icon-18 d-flex"></i-tabler>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
}
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Main Content -->
|
||||
<!-- ============================================================== -->
|
||||
<mat-sidenav-content class="contentWrapper" #content>
|
||||
<!-- ============================================================== -->
|
||||
<!-- VerticalHeader -->
|
||||
<!-- ============================================================== -->
|
||||
@if (!options.horizontal) {
|
||||
<app-header [showToggle]="!isOver" (toggleCollapsed)="toggleCollapsed()" (toggleMobileNav)="sidenav.toggle()"
|
||||
(toggleMobileFilterNav)="toggleFilterNav()" (optionsChange)="receiveOptions($event)"></app-header>
|
||||
} @else {
|
||||
<!-- horizontal header -->
|
||||
<app-horizontal-header (toggleMobileNav)="sidenav.toggle()" (toggleMobileFilterNav)="toggleFilterNav()"
|
||||
(optionsChange)="receiveOptions($event)"></app-horizontal-header>
|
||||
} @if(options.horizontal) {
|
||||
<app-horizontal-sidebar></app-horizontal-sidebar>
|
||||
}
|
||||
|
||||
<main class="pageWrapper" [ngClass]="{
|
||||
maxWidth: options.boxed
|
||||
}">
|
||||
<app-breadcrumb></app-breadcrumb>
|
||||
<!-- ============================================================== -->
|
||||
<!-- Outlet -->
|
||||
<!-- ============================================================== -->
|
||||
<router-outlet></router-outlet>
|
||||
<div class="customizerBtn">
|
||||
<button mat-fab class="bg-primary text-white" (click)="customizerRight.toggle()">
|
||||
<mat-icon>settings</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- ------------------------------------------------------------------
|
||||
Mobile Apps Sidebar
|
||||
------------------------------------------------------------------ -->
|
||||
<div [class.open]="isFilterNavOpen" class="filter-sidebar">
|
||||
<div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="branding">
|
||||
@if(options.theme === 'light') {
|
||||
<a href="/">
|
||||
<img src="./assets/images/logos/dark-logo.svg" class="align-middle m-2" alt="logo" />
|
||||
</a>
|
||||
} @else {
|
||||
<a href="/">
|
||||
<img src="./assets/images/logos/light-logo.svg" class="align-middle m-2" alt="logo" />
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
<button mat-icon-button (click)="isFilterNavOpen = !isFilterNavOpen" class="d-flex justify-content-center">
|
||||
<i-tabler name="x" class="icon-18 d-flex"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel class="shadow-none">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="f-s-16 f-w-500"> Apps </mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
<div>
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.img) {
|
||||
<div class="col-12 text-hover-primary">
|
||||
<a [routerLink]="[appdd.link]" class="d-flex align-items-center text-decoration-none m-b-24 gap-16">
|
||||
<button mat-mini-fab class="text-primary bg-light-primary shadow-none rounded">
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<h5 class="f-s-14 f-w-600 m-0 textprimary f-s-14 hover-text">
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class="f-s-14 f-s-12">{{ appdd.subtitle }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a [routerLink]="['quicklink.link']"
|
||||
class="hover-text text-decoration-none f-s-14 f-w-600 d-block p-y-8">{{ quicklink.title }}</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
|
||||
<div class="p-x-16">
|
||||
<a [routerLink]="['/apps/calendar']"
|
||||
class="d-flex align-items-center text-decoration-none f-s-14 p-y-16 gap-8">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Calendar</span>
|
||||
</a>
|
||||
<a [routerLink]="['/apps/chat']" class="d-flex align-items-center text-decoration-none f-s-14 p-y-16">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Chat</span>
|
||||
</a>
|
||||
<a [routerLink]="['/apps/email/inbox']"
|
||||
class="d-flex align-items-center text-decoration-none f-s-14 p-y-16 gap-8">
|
||||
<span class="f-s-15 f-w-500 m-l-8">Email</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
|
||||
<mat-sidenav #customizerRight mode="over" position="end">
|
||||
<div class="p-x-16 p-y-20 d-flex align-items-center justify-content-between">
|
||||
<h3 class="f-s-21 f-w-600">Settings</h3>
|
||||
<button class="d-lg-none" mat-button (click)="customizerRight.toggle()">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<app-customizer (optionsChange)="receiveOptions($event)"></app-customizer>
|
||||
</mat-sidenav>
|
||||
</mat-sidenav-container>
|
||||
</span>
|
||||
284
theme/packages/dark/src/app/layouts/full/full.component.ts
Normal file
@@ -0,0 +1,284 @@
|
||||
import { BreakpointObserver, MediaMatcher } from '@angular/cdk/layout';
|
||||
import { ChangeDetectorRef, Component, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { MatSidenav, MatSidenavContent } from '@angular/material/sidenav';
|
||||
import { CoreService } from 'src/app/services/core.service';
|
||||
import { AppSettings } from 'src/app/config';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { NavigationEnd, Router } from '@angular/router';
|
||||
import { navItems } from './vertical/sidebar/sidebar-data';
|
||||
import { NavService } from '../../services/nav.service';
|
||||
import { AppNavItemComponent } from './vertical/sidebar/nav-item/nav-item.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SidebarComponent } from './vertical/sidebar/sidebar.component';
|
||||
import { NgScrollbarModule } from 'ngx-scrollbar';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
import { HeaderComponent } from './vertical/header/header.component';
|
||||
import { AppHorizontalHeaderComponent } from './horizontal/header/header.component';
|
||||
import { AppHorizontalSidebarComponent } from './horizontal/sidebar/sidebar.component';
|
||||
import { AppBreadcrumbComponent } from './shared/breadcrumb/breadcrumb.component';
|
||||
import { CustomizerComponent } from './shared/customizer/customizer.component';
|
||||
|
||||
const MOBILE_VIEW = 'screen and (max-width: 768px)';
|
||||
const TABLET_VIEW = 'screen and (min-width: 769px) and (max-width: 1024px)';
|
||||
const MONITOR_VIEW = 'screen and (min-width: 1024px)';
|
||||
const BELOWMONITOR = 'screen and (max-width: 1023px)';
|
||||
|
||||
// for mobile app sidebar
|
||||
interface apps {
|
||||
id: number;
|
||||
img: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
interface quicklinks {
|
||||
id: number;
|
||||
title: string;
|
||||
link: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-full',
|
||||
imports: [
|
||||
RouterModule,
|
||||
AppNavItemComponent,
|
||||
MaterialModule,
|
||||
CommonModule,
|
||||
SidebarComponent,
|
||||
NgScrollbarModule,
|
||||
TablerIconsModule,
|
||||
HeaderComponent,
|
||||
AppHorizontalHeaderComponent,
|
||||
AppHorizontalSidebarComponent,
|
||||
AppBreadcrumbComponent,
|
||||
CustomizerComponent,
|
||||
],
|
||||
templateUrl: './full.component.html',
|
||||
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class FullComponent implements OnInit {
|
||||
navItems = navItems;
|
||||
|
||||
|
||||
|
||||
@ViewChild('leftsidenav')
|
||||
public sidenav: MatSidenav;
|
||||
resView = false;
|
||||
@ViewChild('content', { static: true }) content!: MatSidenavContent;
|
||||
//get options from service
|
||||
options = this.settings.getOptions();
|
||||
private layoutChangesSubscription = Subscription.EMPTY;
|
||||
private isMobileScreen = false;
|
||||
private isContentWidthFixed = true;
|
||||
private isCollapsedWidthFixed = false;
|
||||
private htmlElement!: HTMLHtmlElement;
|
||||
|
||||
get isOver(): boolean {
|
||||
return this.isMobileScreen;
|
||||
}
|
||||
|
||||
get isTablet(): boolean {
|
||||
return this.resView;
|
||||
}
|
||||
|
||||
// for mobile app sidebar
|
||||
apps: apps[] = [
|
||||
{
|
||||
id: 1,
|
||||
img: '/assets/images/svgs/icon-dd-chat.svg',
|
||||
title: 'Chat Application',
|
||||
subtitle: 'Messages & Emails',
|
||||
link: '/apps/chat',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
img: '/assets/images/svgs/icon-dd-cart.svg',
|
||||
title: 'Todo App',
|
||||
subtitle: 'Completed task',
|
||||
link: '/apps/todo',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: '/assets/images/svgs/icon-dd-invoice.svg',
|
||||
title: 'Invoice App',
|
||||
subtitle: 'Get latest invoice',
|
||||
link: '/apps/invoice',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: '/assets/images/svgs/icon-dd-date.svg',
|
||||
title: 'Calendar App',
|
||||
subtitle: 'Get Dates',
|
||||
link: '/apps/calendar',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
img: '/assets/images/svgs/icon-dd-mobile.svg',
|
||||
title: 'Contact Application',
|
||||
subtitle: '2 Unsaved Contacts',
|
||||
link: '/apps/contacts',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
img: '/assets/images/svgs/icon-dd-lifebuoy.svg',
|
||||
title: 'Tickets App',
|
||||
subtitle: 'Create new ticket',
|
||||
link: '/apps/tickets',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
img: '/assets/images/svgs/icon-dd-message-box.svg',
|
||||
title: 'Email App',
|
||||
subtitle: 'Get new emails',
|
||||
link: '/apps/email/inbox',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
img: '/assets/images/svgs/icon-dd-application.svg',
|
||||
title: 'Courses',
|
||||
subtitle: 'Create new course',
|
||||
link: '/apps/courses',
|
||||
},
|
||||
];
|
||||
|
||||
quicklinks: quicklinks[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Pricing Page',
|
||||
link: '/theme-pages/pricing',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Authentication Design',
|
||||
link: '/authentication/login',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: 'Register Now',
|
||||
link: '/authentication/side-register',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '404 Error Page',
|
||||
link: '/authentication/error',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: 'Notes App',
|
||||
link: '/apps/notes',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: 'Employee App',
|
||||
link: '/apps/employee',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
title: 'Todo Application',
|
||||
link: '/apps/todo',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
title: 'Treeview',
|
||||
link: '/theme-pages/treeview',
|
||||
},
|
||||
];
|
||||
|
||||
constructor(
|
||||
private settings: CoreService,
|
||||
private mediaMatcher: MediaMatcher,
|
||||
private router: Router,
|
||||
private breakpointObserver: BreakpointObserver,
|
||||
private navService: NavService, private cdr: ChangeDetectorRef
|
||||
) {
|
||||
this.htmlElement = document.querySelector('html')!;
|
||||
this.layoutChangesSubscription = this.breakpointObserver
|
||||
.observe([MOBILE_VIEW, TABLET_VIEW, MONITOR_VIEW, BELOWMONITOR])
|
||||
.subscribe((state) => {
|
||||
// SidenavOpened must be reset true when layout changes
|
||||
this.options.sidenavOpened = true;
|
||||
this.isMobileScreen = state.breakpoints[BELOWMONITOR];
|
||||
if (this.options.sidenavCollapsed == false) {
|
||||
this.options.sidenavCollapsed = state.breakpoints[TABLET_VIEW];
|
||||
}
|
||||
this.isContentWidthFixed = state.breakpoints[MONITOR_VIEW];
|
||||
this.resView = state.breakpoints[BELOWMONITOR];
|
||||
});
|
||||
|
||||
// Initialize project theme with options
|
||||
this.receiveOptions(this.options);
|
||||
|
||||
// This is for scroll to top
|
||||
this.router.events
|
||||
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||
.subscribe((e) => {
|
||||
this.content.scrollTo({ top: 0 });
|
||||
});
|
||||
}
|
||||
|
||||
isFilterNavOpen = false;
|
||||
|
||||
toggleFilterNav() {
|
||||
this.isFilterNavOpen = !this.isFilterNavOpen;
|
||||
console.log('Sidebar open:', this.isFilterNavOpen);
|
||||
this.cdr.detectChanges(); // Ensures Angular updates the view
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.layoutChangesSubscription.unsubscribe();
|
||||
}
|
||||
|
||||
toggleCollapsed() {
|
||||
this.isContentWidthFixed = false;
|
||||
this.options.sidenavCollapsed = !this.options.sidenavCollapsed;
|
||||
this.resetCollapsedState();
|
||||
}
|
||||
|
||||
resetCollapsedState(timer = 400) {
|
||||
setTimeout(() => this.settings.setOptions(this.options), timer);
|
||||
}
|
||||
|
||||
onSidenavClosedStart() {
|
||||
this.isContentWidthFixed = false;
|
||||
}
|
||||
|
||||
onSidenavOpenedChange(isOpened: boolean) {
|
||||
this.isCollapsedWidthFixed = !this.isOver;
|
||||
this.options.sidenavOpened = isOpened;
|
||||
this.settings.setOptions(this.options);
|
||||
}
|
||||
|
||||
receiveOptions(options: AppSettings): void {
|
||||
this.toggleDarkTheme(options);
|
||||
this.toggleColorsTheme(options);
|
||||
}
|
||||
|
||||
toggleDarkTheme(options: AppSettings) {
|
||||
if (options.theme === 'dark') {
|
||||
this.htmlElement.classList.add('dark-theme');
|
||||
this.htmlElement.classList.remove('light-theme');
|
||||
} else {
|
||||
this.htmlElement.classList.remove('dark-theme');
|
||||
this.htmlElement.classList.add('light-theme');
|
||||
}
|
||||
}
|
||||
|
||||
toggleColorsTheme(options: AppSettings) {
|
||||
// Remove any existing theme class dynamically
|
||||
this.htmlElement.classList.forEach((className) => {
|
||||
if (className.endsWith('_theme')) {
|
||||
this.htmlElement.classList.remove(className);
|
||||
}
|
||||
});
|
||||
|
||||
// Add the selected theme class
|
||||
this.htmlElement.classList.add(options.activeTheme);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
<mat-toolbar class="topbar horizontal-topbar">
|
||||
<div class="container">
|
||||
<div class="d-none d-sm-flex branding">
|
||||
<app-branding></app-branding>
|
||||
</div>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileNav.emit()"
|
||||
class="d-block d-lg-none"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Search -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button mat-icon-button (click)="openDialog()" class="d-flex">
|
||||
<i-tabler name="search" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<div class="d-none d-lg-flex">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Links -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-button
|
||||
[matMenuTriggerFor]="appsmenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
Apps <i-tabler name="chevron-down" class="icon-16 m-l-4"></i-tabler>
|
||||
</div>
|
||||
</button>
|
||||
<mat-menu #appsmenu="matMenu" class="apps-dd cardWithShadow">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 b-r-1 p-r-0">
|
||||
<div class="p-32 p-b-0">
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.title) {
|
||||
<div class="col-sm-6 text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[appdd.link]"
|
||||
class="d-flex align-items-center text-decoration-none m-b-24"
|
||||
>
|
||||
<span
|
||||
class="text-primary bg-light rounded icon-40 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</span>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class="text-body f-s-12">{{
|
||||
appdd.subtitle
|
||||
}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="b-t-1 p-24 d-none d-lg-flex align-items-center justify-content-between"
|
||||
>
|
||||
<span
|
||||
class="d-flex align-items-center f-s-16 f-w-500"
|
||||
>
|
||||
<i-tabler name="help" class="icon-20 m-r-8"></i-tabler
|
||||
>Frequently Asked Questions
|
||||
</span>
|
||||
<a
|
||||
[routerLink]="['/theme-pages/faq']"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
>Check</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="p-x-16 p-y-32">
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[quicklink.link]"
|
||||
class="hover-text text-decoration-none f-s-14 f-w-600 d-block p-y-8"
|
||||
>{{ quicklink.title }}</a
|
||||
>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-menu>
|
||||
<a mat-button [routerLink]="['/apps/chat']">Chat</a>
|
||||
<a mat-button [routerLink]="['/apps/calendar']">Calendar</a>
|
||||
<a mat-button [routerLink]="['/apps/email/inbox']">Email</a>
|
||||
</div>
|
||||
|
||||
<span class="flex-1-auto"></span>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileFilterNav.emit()"
|
||||
class="d-flex d-lg-none justify-content-center"
|
||||
>
|
||||
<i-tabler name="grid-dots" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- langugage Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button [matMenuTriggerFor]="flags" mat-icon-button class="m-r-5">
|
||||
<img
|
||||
[src]="selectedLanguage.icon"
|
||||
class="rounded-circle object-cover icon-20"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #flags="matMenu" class="cardWithShadow">
|
||||
@for(lang of languages; track lang.icon) {
|
||||
<button mat-menu-item (click)="changeLanguage(lang)">
|
||||
<div class="d-flex align-items-center">
|
||||
<img
|
||||
[src]="lang.icon"
|
||||
class="rounded-circle object-cover m-r-8 icon-20"
|
||||
/>
|
||||
<span class=" f-s-14">{{ lang.language }}</span>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</mat-menu>
|
||||
|
||||
@if(options.theme=='light'){
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('dark')" >
|
||||
<i-tabler class="d-flex icon-22" [name]="'moon'"></i-tabler>
|
||||
</button>
|
||||
}@else{
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('light')">
|
||||
<i-tabler class="d-flex icon-22" [name]="'sun'"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Notification Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button matBadge="5"
|
||||
[matMenuTriggerFor]="notificationmenu"
|
||||
aria-label="Notifications" class="m-x-5 notification-badge"
|
||||
>
|
||||
<i-tabler
|
||||
class="d-flex"
|
||||
name="bell"
|
||||
></i-tabler>
|
||||
</button>
|
||||
<mat-menu
|
||||
#notificationmenu="matMenu"
|
||||
xPosition="before"
|
||||
class="topbar-dd cardWithShadow"
|
||||
>
|
||||
<div class="d-flex align-items-center p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">Notifications</h6>
|
||||
<span class="m-l-auto">
|
||||
<span class="bg-primary text-white p-x-8 p-y-4 f-w-500 rounded f-s-12"
|
||||
>5 new</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
@for(notification of notifications; track notification.title) {
|
||||
<button mat-menu-item class="p-x-32 p-y-16">
|
||||
<div class="d-flex align-items-center">
|
||||
<img [src]="notification.img" class="rounded-circle" width="48" />
|
||||
<div class="m-l-16">
|
||||
<h5 class="f-s-14 f-w-600 m-0 ">
|
||||
{{ notification.title }}
|
||||
</h5>
|
||||
<span>{{ notification.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<button mat-stroked-button color="primary" class="w-100">
|
||||
See all notifications
|
||||
</button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- profile Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="profilemenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle object-cover icon-35 profile-dd"
|
||||
width="35"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu
|
||||
#profilemenu="matMenu"
|
||||
xPosition="before"
|
||||
class="topbar-dd cardWithShadow"
|
||||
>
|
||||
<div class="p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">User Profile</h6>
|
||||
|
||||
<div class="d-flex align-items-center p-b-24 b-b-1 m-t-16">
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle"
|
||||
width="95"
|
||||
/>
|
||||
<div class="m-l-16">
|
||||
<h6 class="f-s-14 f-w-600 m-0 ">Mathew Anderson</h6>
|
||||
<span class="f-s-14 d-block m-b-4">Designer</span>
|
||||
<span class="d-flex align-items-center">
|
||||
<i-tabler name="mail" class="icon-15 m-r-4"></i-tabler>
|
||||
info@modernize.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-x-32">
|
||||
@for(profile of profiledd; track profile.title) {
|
||||
<a
|
||||
class="p-y-16 text-decoration-none d-block text-hover-primary"
|
||||
[routerLink]="[profile.link]"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
class="text-primary bg-light-primary shadow-none rounded"
|
||||
>
|
||||
<img [src]="profile.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ profile.title }}
|
||||
</h5>
|
||||
<span class="f-s-14 text-body">{{ profile.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
<!-- upgrade -->
|
||||
<div
|
||||
class="p-24 overflow-hidden bg-light-primary rounded position-relative m-y-16"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<h5 class="f-s-18 m-0 f-w-600 m-b-12 ">
|
||||
Unlimited <br />
|
||||
Access
|
||||
</h5>
|
||||
<button mat-flat-button color="primary">Upgrade</button>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<img
|
||||
src="/assets/images/backgrounds/unlimited-bg.png"
|
||||
alt="upgrade-bg"
|
||||
class="upgrade-bg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<a
|
||||
[routerLink]="['/authentication/login']"
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="w-100"
|
||||
>Logout</a
|
||||
>
|
||||
</div>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
@@ -0,0 +1,633 @@
|
||||
import { NavItem } from '../../vertical/sidebar/nav-item/nav-item';
|
||||
|
||||
export const navItems: NavItem[] = [
|
||||
{
|
||||
navCap: 'Home',
|
||||
},
|
||||
{
|
||||
displayName: 'Dashboards',
|
||||
iconName: 'home',
|
||||
route: 'dashboards',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Analytical',
|
||||
iconName: 'point',
|
||||
route: 'dashboards/dashboard1',
|
||||
},
|
||||
{
|
||||
displayName: 'eCommerce',
|
||||
iconName: 'point',
|
||||
route: 'dashboards/dashboard2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Frontend pages',
|
||||
iconName: 'app-window',
|
||||
route: 'front-pages',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Home Page',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/homepage',
|
||||
} ,
|
||||
{
|
||||
displayName: 'About Us',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/about',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Blog',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/blog',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Blog Details',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/blog-details',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Portfolio',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/portfolio',
|
||||
},
|
||||
{
|
||||
displayName: 'Pricing',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/pricing',
|
||||
},
|
||||
{
|
||||
displayName: 'Contact',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/contact',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
displayName: 'Apps',
|
||||
iconName: 'apps',
|
||||
route: 'apps',
|
||||
ddType: '',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Chat',
|
||||
iconName: 'point',
|
||||
route: 'apps/chat',
|
||||
},
|
||||
{
|
||||
displayName: 'Calendar',
|
||||
iconName: 'point',
|
||||
route: 'apps/calendar',
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
iconName: 'point',
|
||||
route: 'apps/email/inbox',
|
||||
},
|
||||
{
|
||||
displayName: 'Contacts',
|
||||
iconName: 'point',
|
||||
route: 'apps/contacts',
|
||||
},
|
||||
{
|
||||
displayName: 'Contact List',
|
||||
iconName: 'point',
|
||||
route: 'apps/contact-list',
|
||||
},
|
||||
{
|
||||
displayName: 'Courses',
|
||||
iconName: 'point',
|
||||
route: 'apps/courses',
|
||||
},
|
||||
{
|
||||
displayName: 'Employee',
|
||||
iconName: 'point',
|
||||
route: 'apps/employee',
|
||||
},
|
||||
{
|
||||
displayName: 'Notes',
|
||||
iconName: 'point',
|
||||
route: 'apps/notes',
|
||||
},
|
||||
{
|
||||
displayName: 'Tickets',
|
||||
iconName: 'point',
|
||||
route: 'apps/tickets',
|
||||
},
|
||||
{
|
||||
displayName: 'Invoice',
|
||||
iconName: 'point',
|
||||
route: 'apps/invoice',
|
||||
},
|
||||
{
|
||||
displayName: 'ToDo',
|
||||
iconName: 'point',
|
||||
route: 'apps/todo',
|
||||
},
|
||||
{
|
||||
displayName: 'Kanban',
|
||||
iconName: 'point',
|
||||
route: 'apps/kanban',
|
||||
},
|
||||
{
|
||||
displayName: 'Blog',
|
||||
iconName: 'point',
|
||||
route: 'apps/blog',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Post',
|
||||
iconName: 'point',
|
||||
route: 'apps/blog/post',
|
||||
},
|
||||
{
|
||||
displayName: 'Detail',
|
||||
iconName: 'point',
|
||||
route: 'apps/blog/detail/Early Black Friday Amazon deals: cheap TVs, headphones, laptops',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'User Profile',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Profile',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/profile',
|
||||
},
|
||||
{
|
||||
displayName: 'Followers',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/followers',
|
||||
},
|
||||
{
|
||||
displayName: 'Friends',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/friends',
|
||||
},
|
||||
{
|
||||
displayName: 'Gellary',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/gallery',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Ecommerce',
|
||||
iconName: 'point',
|
||||
route: 'apps/product',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Product List',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/product-list',
|
||||
},
|
||||
{
|
||||
displayName: 'Add Product',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/add-product',
|
||||
},
|
||||
{
|
||||
displayName: 'Edit Product',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/edit-product',
|
||||
},
|
||||
{
|
||||
displayName: 'Shop',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/shop',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Ui',
|
||||
iconName: 'components',
|
||||
route: 'ui-components',
|
||||
ddType: '',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Badge',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/badge',
|
||||
},
|
||||
{
|
||||
displayName: 'Expansion Panel',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/expansion',
|
||||
},
|
||||
{
|
||||
displayName: 'Chips',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/chips',
|
||||
},
|
||||
{
|
||||
displayName: 'Dialog',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/dialog',
|
||||
},
|
||||
{
|
||||
displayName: 'Lists',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/lists',
|
||||
},
|
||||
{
|
||||
displayName: 'Divider',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/divider',
|
||||
},
|
||||
{
|
||||
displayName: 'Menu',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/menu',
|
||||
},
|
||||
{
|
||||
displayName: 'Paginator',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/paginator',
|
||||
},
|
||||
{
|
||||
displayName: 'Progress Bar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/progress',
|
||||
},
|
||||
{
|
||||
displayName: 'Progress Spinner',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/progress-spinner',
|
||||
},
|
||||
{
|
||||
displayName: 'Ripples',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/ripples',
|
||||
},
|
||||
{
|
||||
displayName: 'Slide Toggle',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/slide-toggle',
|
||||
},
|
||||
{
|
||||
displayName: 'Slider',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/slider',
|
||||
},
|
||||
{
|
||||
displayName: 'Snackbar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/snackbar',
|
||||
},
|
||||
{
|
||||
displayName: 'Tabs',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/tabs',
|
||||
},
|
||||
{
|
||||
displayName: 'Toolbar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/toolbar',
|
||||
},
|
||||
{
|
||||
displayName: 'Tooltips',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/tooltips',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Pages',
|
||||
iconName: 'clipboard',
|
||||
route: 'theme-pages',
|
||||
ddType: '',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Treeview',
|
||||
iconName: 'point',
|
||||
route: 'theme-pages/treeview',
|
||||
},
|
||||
{
|
||||
displayName: 'Pricing',
|
||||
iconName: 'point',
|
||||
route: 'theme-pages/pricing',
|
||||
},
|
||||
{
|
||||
displayName: 'Account Setting',
|
||||
iconName: 'point',
|
||||
route: 'theme-pages/account-setting',
|
||||
},
|
||||
{
|
||||
displayName: 'FAQ',
|
||||
iconName: 'point',
|
||||
route: 'theme-pages/faq',
|
||||
},
|
||||
{
|
||||
displayName: 'Landingpage',
|
||||
iconName: 'point',
|
||||
route: 'landingpage',
|
||||
},
|
||||
{
|
||||
displayName: 'Widgets',
|
||||
iconName: 'point',
|
||||
route: 'widgets',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Cards',
|
||||
iconName: 'point',
|
||||
route: 'widgets/cards',
|
||||
},
|
||||
{
|
||||
displayName: 'Banners',
|
||||
iconName: 'point',
|
||||
route: 'widgets/banners',
|
||||
},
|
||||
{
|
||||
displayName: 'Charts',
|
||||
iconName: 'point',
|
||||
route: 'widgets/charts',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Charts',
|
||||
iconName: 'point',
|
||||
route: 'charts',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Line',
|
||||
iconName: 'point',
|
||||
route: '/charts/line',
|
||||
},
|
||||
{
|
||||
displayName: 'Gredient',
|
||||
iconName: 'point',
|
||||
route: '/charts/gredient',
|
||||
},
|
||||
{
|
||||
displayName: 'Area',
|
||||
iconName: 'point',
|
||||
route: '/charts/area',
|
||||
},
|
||||
{
|
||||
displayName: 'Candlestick',
|
||||
iconName: 'point',
|
||||
route: '/charts/candlestick',
|
||||
},
|
||||
{
|
||||
displayName: 'Column',
|
||||
iconName: 'point',
|
||||
route: '/charts/column',
|
||||
},
|
||||
{
|
||||
displayName: 'Doughnut & Pie',
|
||||
iconName: 'point',
|
||||
route: '/charts/doughnut-pie',
|
||||
},
|
||||
{
|
||||
displayName: 'Radialbar & Radar',
|
||||
iconName: 'point',
|
||||
route: '/charts/radial-radar',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Auth',
|
||||
iconName: 'point',
|
||||
route: '/',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Login',
|
||||
iconName: 'point',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Login 1',
|
||||
iconName: 'point',
|
||||
route: '/authentication/login',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Login',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-login',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Register',
|
||||
iconName: 'point',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Login 1',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-register',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Login',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-register',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Forgot Password',
|
||||
iconName: 'point',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Side Forgot Password',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-forgot-pwd',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Forgot Password',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-forgot-pwd',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Two Steps',
|
||||
iconName: 'point',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Side Two Steps',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-two-steps',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Two Steps',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-two-steps',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Error',
|
||||
iconName: 'point',
|
||||
route: '/authentication/error',
|
||||
},
|
||||
{
|
||||
displayName: 'Maintenance',
|
||||
iconName: 'point',
|
||||
route: '/authentication/maintenance',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Forms',
|
||||
iconName: 'file-description',
|
||||
route: 'forms',
|
||||
ddType: '',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Form elements',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Autocomplete',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/autocomplete',
|
||||
},
|
||||
{
|
||||
displayName: 'Button',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/button',
|
||||
},
|
||||
{
|
||||
displayName: 'Checkbox',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/checkbox',
|
||||
},
|
||||
{
|
||||
displayName: 'Radio',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/radio',
|
||||
},
|
||||
{
|
||||
displayName: 'Datepicker',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/datepicker',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Form Layouts',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-layouts',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Horizontal',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-horizontal',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Vertical',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-vertical',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Wizard',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-wizard',
|
||||
},
|
||||
{
|
||||
displayName: 'Toastr',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-toastr',
|
||||
},
|
||||
{
|
||||
displayName: 'Editor',
|
||||
iconName: 'point',
|
||||
route: '/forms/form-editor',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Tables',
|
||||
iconName: 'layout',
|
||||
route: 'tables',
|
||||
ddType: '',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Basic Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/basic-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Dynamic Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/dynamic-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Expand Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/expand-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Filterable Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/filterable-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Footer Row Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/footer-row-table',
|
||||
},
|
||||
{
|
||||
displayName: 'HTTP Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/http-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Mix Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/mix-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Multi Header Footer',
|
||||
iconName: 'point',
|
||||
route: 'tables/multi-header-footer-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Pagination Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/pagination-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Row Context Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/row-context-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Selection Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/selection-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sortable Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/sortable-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sticky Column',
|
||||
iconName: 'point',
|
||||
route: 'tables/sticky-column-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sticky Header Footer',
|
||||
iconName: 'point',
|
||||
route: 'tables/sticky-header-footer-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Data table',
|
||||
iconName: 'point',
|
||||
route: '/datatable/kichen-sink',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,48 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
Input,
|
||||
ChangeDetectorRef,
|
||||
OnChanges,
|
||||
} from '@angular/core';
|
||||
import { navItems } from './sidebar-data';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavService } from '../../../../services/nav.service';
|
||||
import { MediaMatcher } from '@angular/cdk/layout';
|
||||
import { AppHorizontalNavItemComponent } from './nav-item/nav-item.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-horizontal-sidebar',
|
||||
imports: [AppHorizontalNavItemComponent, CommonModule],
|
||||
templateUrl: './sidebar.component.html',
|
||||
})
|
||||
export class AppHorizontalSidebarComponent implements OnInit {
|
||||
navItems = navItems;
|
||||
parentActive = '';
|
||||
|
||||
mobileQuery: MediaQueryList;
|
||||
private _mobileQueryListener: () => void;
|
||||
|
||||
constructor(
|
||||
public navService: NavService,
|
||||
public router: Router,
|
||||
media: MediaMatcher,
|
||||
changeDetectorRef: ChangeDetectorRef
|
||||
) {
|
||||
this.mobileQuery = media.matchMedia('(min-width: 1100px)');
|
||||
this._mobileQueryListener = () => changeDetectorRef.detectChanges();
|
||||
this.mobileQuery.addListener(this._mobileQueryListener);
|
||||
this.router.events.subscribe(
|
||||
() => (this.parentActive = this.router.url.split('/')[1])
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.parentActive = this.router.url.split('/')[1];
|
||||
|
||||
this.router.events.subscribe(() => {
|
||||
this.parentActive = this.router.url.split('/')[1];
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { Router, NavigationEnd, ActivatedRoute, Data } from '@angular/router';
|
||||
import { filter, map, mergeMap } from 'rxjs/operators';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
|
||||
@Component({
|
||||
selector: 'app-breadcrumb',
|
||||
imports: [RouterModule, TablerIconsModule],
|
||||
templateUrl: './breadcrumb.component.html',
|
||||
styleUrls: []
|
||||
})
|
||||
export class AppBreadcrumbComponent {
|
||||
// @Input() layout;
|
||||
pageInfo: Data | any = Object.create(null);
|
||||
myurl: any = this.router.url.slice(1).split('/');
|
||||
constructor(
|
||||
private router: Router,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private titleService: Title
|
||||
) {
|
||||
this.router.events
|
||||
.pipe(filter((event) => event instanceof NavigationEnd))
|
||||
.pipe(map(() => this.activatedRoute))
|
||||
.pipe(
|
||||
map((route) => {
|
||||
while (route.firstChild) {
|
||||
route = route.firstChild;
|
||||
}
|
||||
return route;
|
||||
})
|
||||
)
|
||||
.pipe(filter((route) => route.outlet === 'primary'))
|
||||
.pipe(mergeMap((route) => route.data))
|
||||
// tslint:disable-next-line - Disables all
|
||||
.subscribe((event) => {
|
||||
// tslint:disable-next-line - Disables all
|
||||
this.titleService.setTitle(event['title'] + ' - Angular 20');
|
||||
this.pageInfo = event;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,301 @@
|
||||
<mat-toolbar class="topbar">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Desktop Menu -->
|
||||
@if(showToggle) {
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleCollapsed.emit()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
@if(!showToggle) {
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileNav.emit()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="menu-2" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Search -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="openDialog()"
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="search" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<div class="d-none d-lg-flex">
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Links -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-button
|
||||
[matMenuTriggerFor]="appsmenu"
|
||||
aria-label="Notifications"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
Apps <i-tabler name="chevron-down" class="icon-16 m-l-4"></i-tabler>
|
||||
</div>
|
||||
</button>
|
||||
<mat-menu #appsmenu="matMenu" class="apps-dd cardWithShadow">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 b-r-1 p-r-0">
|
||||
<div class="p-32 p-b-0">
|
||||
<div class="row">
|
||||
@for(appdd of apps; track appdd.title) {
|
||||
<div class="col-sm-6 text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[appdd.link]"
|
||||
class="d-flex align-items-center text-decoration-none m-b-24"
|
||||
>
|
||||
<span
|
||||
class="text-primary bg-light rounded icon-40 d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<img [src]="appdd.img" width="20" />
|
||||
</span>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ appdd.title }}
|
||||
</h5>
|
||||
<span class="f-s-12 text-body">{{ appdd.subtitle }}</span>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="b-t-1 p-24 d-none d-lg-flex align-items-center justify-content-between"
|
||||
>
|
||||
<span
|
||||
class="d-flex align-items-center f-s-16 f-w-500"
|
||||
>
|
||||
<i-tabler name="help" class="icon-20 m-r-8"></i-tabler>Frequently
|
||||
Asked Questions
|
||||
</span>
|
||||
<a
|
||||
[routerLink]="['/theme-pages/faq']"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
>Check</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-4">
|
||||
<div class="p-x-16 p-y-32">
|
||||
<h4 class="f-s-18 f-w-600 m-b-16">Quick Links</h4>
|
||||
@for(quicklink of quicklinks; track quicklink.title) {
|
||||
<div class="text-hover-primary">
|
||||
<a
|
||||
[routerLink]="[quicklink.link]"
|
||||
class="hover-text text-decoration-none f-s-14 f-w-600 d-block p-y-8"
|
||||
>{{ quicklink.title }}</a
|
||||
>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mat-menu>
|
||||
<a mat-button [routerLink]="['/apps/chat']">Chat</a>
|
||||
<a mat-button [routerLink]="['/apps/calendar']">Calendar</a>
|
||||
<a mat-button [routerLink]="['/apps/email/inbox']">Email</a>
|
||||
</div>
|
||||
|
||||
<span class="flex-1-auto"></span>
|
||||
|
||||
<!-- Mobile Menu -->
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="toggleMobileFilterNav.emit()"
|
||||
class="d-flex d-lg-none justify-content-center"
|
||||
>
|
||||
<i-tabler name="grid-dots" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- langugage Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button [matMenuTriggerFor]="flags" mat-icon-button class="m-r-5">
|
||||
<img
|
||||
[src]="selectedLanguage.icon"
|
||||
class="rounded-circle object-cover icon-20"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #flags="matMenu" class="cardWithShadow">
|
||||
@for(lang of languages; track lang.icon) {
|
||||
<button mat-menu-item (click)="changeLanguage(lang)">
|
||||
<div class="d-flex align-items-center">
|
||||
<img
|
||||
[src]="lang.icon"
|
||||
class="rounded-circle object-cover m-r-8 icon-20"
|
||||
/>
|
||||
<span class=" f-s-14">{{ lang.language }}</span>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
</mat-menu>
|
||||
|
||||
@if(options.theme=='light'){
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('dark')" >
|
||||
<i-tabler class="d-flex icon-22" [name]="'moon'"></i-tabler>
|
||||
</button>
|
||||
}@else{
|
||||
<button mat-icon-button aria-label="lightdark" class="d-flex justify-content-center" (click)="setlightDark('light')">
|
||||
<i-tabler class="d-flex icon-22" [name]="'sun'"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- Notification Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button matBadge="5"
|
||||
[matMenuTriggerFor]="notificationmenu"
|
||||
aria-label="Notifications" class="m-x-5 notification-badge"
|
||||
>
|
||||
<i-tabler
|
||||
class="d-flex"
|
||||
name="bell"
|
||||
></i-tabler>
|
||||
</button>
|
||||
<mat-menu #notificationmenu="matMenu" class="topbar-dd cardWithShadow">
|
||||
<div class="d-flex align-items-center p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">Notifications</h6>
|
||||
<span class="m-l-auto">
|
||||
<span class="bg-primary text-white p-x-8 p-y-4 f-w-500 rounded f-s-12"
|
||||
>5 new</span
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@for(notification of notifications; track notification.title) {
|
||||
<button mat-menu-item class="p-x-32 p-y-16">
|
||||
<div class="d-flex align-items-center">
|
||||
<img [src]="notification.img" class="rounded-circle" width="48" />
|
||||
<div class="m-l-16">
|
||||
<h5 class="f-s-14 f-w-600 m-0 ">
|
||||
{{ notification.title }}
|
||||
</h5>
|
||||
<span>{{ notification.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
}
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<button mat-stroked-button color="primary" class="w-100">
|
||||
See all notifications
|
||||
</button>
|
||||
</div>
|
||||
</mat-menu>
|
||||
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<!-- profile Dropdown -->
|
||||
<!-- --------------------------------------------------------------- -->
|
||||
<button
|
||||
mat-icon-button
|
||||
[matMenuTriggerFor]="profilemenu"
|
||||
aria-label="Notifications" class="m-l-8"
|
||||
>
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle object-cover icon-35 profile-dd"
|
||||
width="35"
|
||||
/>
|
||||
</button>
|
||||
<mat-menu #profilemenu="matMenu" class="topbar-dd cardWithShadow">
|
||||
<ng-scrollbar class="position-relative" style="height: 647px">
|
||||
<div class="p-x-32 p-y-16">
|
||||
<h6 class="f-s-16 f-w-600 m-0 ">User Profile</h6>
|
||||
|
||||
<div class="d-flex align-items-center p-b-24 b-b-1 m-t-16">
|
||||
<img
|
||||
src="/assets/images/profile/user-1.jpg"
|
||||
class="rounded-circle"
|
||||
width="95"
|
||||
/>
|
||||
<div class="m-l-16">
|
||||
<h6 class="f-s-14 f-w-600 m-0 ">Mathew Anderson</h6>
|
||||
<span class="f-s-14 d-block m-b-4">Designer</span>
|
||||
<span class="d-flex align-items-center">
|
||||
<i-tabler name="mail" class="icon-15 m-r-4"></i-tabler>
|
||||
info@modernize.com
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-x-32">
|
||||
@for(profile of profiledd; track profile.title) {
|
||||
<a
|
||||
class="p-y-16 text-decoration-none d-block text-hover-primary"
|
||||
[routerLink]="[profile.link]"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<button
|
||||
mat-mini-fab
|
||||
class="text-primary bg-light shadow-none rounded"
|
||||
>
|
||||
<img [src]="profile.img" width="20" />
|
||||
</button>
|
||||
|
||||
<div class="m-l-16">
|
||||
<h5
|
||||
class="f-s-14 f-w-600 m-0 textprimary hover-text"
|
||||
>
|
||||
{{ profile.title }}
|
||||
</h5>
|
||||
<span class="f-s-14 text-body">{{ profile.subtitle }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
}
|
||||
|
||||
<!-- upgrade -->
|
||||
<div
|
||||
class="p-24 overflow-hidden bg-light-primary rounded position-relative m-y-16"
|
||||
>
|
||||
<div class="d-flex align-items-center">
|
||||
<div>
|
||||
<h5 class="f-s-18 m-0 f-w-600 m-b-12 ">
|
||||
Unlimited <br />
|
||||
Access
|
||||
</h5>
|
||||
<button mat-flat-button color="primary">Upgrade</button>
|
||||
</div>
|
||||
<div class="m-l-auto">
|
||||
<img
|
||||
src="/assets/images/backgrounds/unlimited-bg.png"
|
||||
alt="upgrade-bg"
|
||||
class="upgrade-bg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-y-12 p-x-32">
|
||||
<a
|
||||
[routerLink]="['/authentication/login']"
|
||||
mat-stroked-button
|
||||
color="primary"
|
||||
class="w-100"
|
||||
>Logout</a
|
||||
>
|
||||
</div>
|
||||
</ng-scrollbar>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
@@ -0,0 +1,103 @@
|
||||
import {
|
||||
Component,
|
||||
HostBinding,
|
||||
Input,
|
||||
OnInit,
|
||||
OnChanges,
|
||||
Output,
|
||||
EventEmitter,
|
||||
} from '@angular/core';
|
||||
import { NavItem } from './nav-item';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavService } from '../../../../../services/nav.service';
|
||||
import {
|
||||
animate,
|
||||
state,
|
||||
style,
|
||||
transition,
|
||||
trigger,
|
||||
} from '@angular/animations';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-item',
|
||||
imports: [TranslateModule, TablerIconsModule, MaterialModule, CommonModule],
|
||||
templateUrl: './nav-item.component.html',
|
||||
styleUrls: [],
|
||||
animations: [
|
||||
trigger('indicatorRotate', [
|
||||
state('collapsed', style({ transform: 'rotate(0deg)' })),
|
||||
state('expanded', style({ transform: 'rotate(180deg)' })),
|
||||
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4,0.0,0.2,1)')),
|
||||
]),
|
||||
]
|
||||
})
|
||||
export class AppNavItemComponent implements OnChanges {
|
||||
@Output() toggleMobileLink: any = new EventEmitter<void>();
|
||||
@Output() notify: EventEmitter<boolean> = new EventEmitter<boolean>();
|
||||
|
||||
expanded: any = false;
|
||||
disabled: any = false;
|
||||
twoLines: any = false;
|
||||
@HostBinding('attr.aria-expanded') ariaExpanded = this.expanded;
|
||||
@Input() item: NavItem | any;
|
||||
@Input() depth: any;
|
||||
|
||||
constructor(public navService: NavService, public router: Router) {
|
||||
if (this.depth === undefined) {
|
||||
this.depth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
const url = this.navService.currentUrl();
|
||||
if (this.item.route && url) {
|
||||
this.expanded = url.indexOf(`/${this.item.route}`) === 0;
|
||||
this.ariaExpanded = this.expanded;
|
||||
}
|
||||
}
|
||||
|
||||
onItemSelected(item: NavItem) {
|
||||
if (!item.children || !item.children.length) {
|
||||
this.router.navigate([item.route]);
|
||||
|
||||
}
|
||||
if (item.children && item.children.length) {
|
||||
this.expanded = !this.expanded;
|
||||
}
|
||||
//scroll
|
||||
window.scroll({
|
||||
top: 0,
|
||||
left: 0,
|
||||
behavior: 'smooth',
|
||||
});
|
||||
if (!this.expanded) {
|
||||
if (window.innerWidth < 1024) {
|
||||
this.notify.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onSubItemSelected(item: NavItem) {
|
||||
if (!item.children || !item.children.length) {
|
||||
if (this.expanded && window.innerWidth < 1024) {
|
||||
this.notify.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDirectlyActive(item: NavItem): boolean {
|
||||
return !!item.route && this.router.isActive(item.route, true);
|
||||
}
|
||||
|
||||
isChildActive(item: NavItem): boolean {
|
||||
if (!item.children) return false;
|
||||
return item.children.some(
|
||||
(child) => this.isDirectlyActive(child) || this.isChildActive(child)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,705 @@
|
||||
import { NavItem } from './nav-item/nav-item';
|
||||
|
||||
export const navItems: NavItem[] = [
|
||||
{
|
||||
navCap: 'Home',
|
||||
},
|
||||
{
|
||||
displayName: 'Analytical',
|
||||
iconName: 'aperture',
|
||||
route: '/dashboards/dashboard1',
|
||||
},
|
||||
{
|
||||
displayName: 'eCommerce',
|
||||
iconName: 'shopping-cart',
|
||||
route: '/dashboards/dashboard2',
|
||||
},
|
||||
{
|
||||
displayName: 'Frontend pages',
|
||||
iconName: 'app-window',
|
||||
route: 'front-pages',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Home Page',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/homepage',
|
||||
} ,
|
||||
{
|
||||
displayName: 'About Us',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/about',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Blog',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/blog',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Blog Details',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/blog-details',
|
||||
} ,
|
||||
{
|
||||
displayName: 'Portfolio',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/portfolio',
|
||||
},
|
||||
{
|
||||
displayName: 'Pricing',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/pricing',
|
||||
},
|
||||
{
|
||||
displayName: 'Contact',
|
||||
iconName: 'point',
|
||||
route: 'front-pages/contact',
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
navCap: 'Apps',
|
||||
},
|
||||
{
|
||||
displayName: 'Chat',
|
||||
iconName: 'message-2',
|
||||
route: 'apps/chat',
|
||||
},
|
||||
{
|
||||
displayName: 'Calendar',
|
||||
iconName: 'calendar-event',
|
||||
route: 'apps/calendar',
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
iconName: 'mail',
|
||||
route: 'apps/email/inbox',
|
||||
},
|
||||
{
|
||||
displayName: 'Kanban',
|
||||
iconName: 'checklist',
|
||||
route: 'apps/kanban',
|
||||
},
|
||||
{
|
||||
displayName: 'User Profile',
|
||||
iconName: 'user-circle',
|
||||
route: 'apps/profile-details',
|
||||
chip: true,
|
||||
chipClass: 'bg-error text-white',
|
||||
chipContent: 'New',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Profile',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/profile',
|
||||
},
|
||||
{
|
||||
displayName: 'Followers',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/followers',
|
||||
},
|
||||
{
|
||||
displayName: 'Friends',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/friends',
|
||||
},
|
||||
{
|
||||
displayName: 'Gellary',
|
||||
iconName: 'point',
|
||||
route: 'apps/profile-details/gallery',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Ecommerce',
|
||||
iconName: 'basket',
|
||||
route: 'apps/product',
|
||||
chip: true,
|
||||
chipClass: 'border-error text-error',
|
||||
chipContent: 'New',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Product List',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/product-list',
|
||||
},
|
||||
{
|
||||
displayName: 'Add Product',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/add-product',
|
||||
},
|
||||
{
|
||||
displayName: 'Edit Product',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/edit-product',
|
||||
},
|
||||
{
|
||||
displayName: 'Shop',
|
||||
iconName: 'point',
|
||||
route: 'apps/product/shop',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Contacts',
|
||||
iconName: 'phone',
|
||||
route: 'apps/contacts',
|
||||
},
|
||||
{
|
||||
displayName: 'Courses',
|
||||
iconName: 'certificate',
|
||||
route: 'apps/courses',
|
||||
},
|
||||
{
|
||||
displayName: 'Employee',
|
||||
iconName: 'brand-ctemplar',
|
||||
route: 'apps/employee',
|
||||
},
|
||||
{
|
||||
displayName: 'Notes',
|
||||
iconName: 'note',
|
||||
route: 'apps/notes',
|
||||
},
|
||||
{
|
||||
displayName: 'Tickets',
|
||||
iconName: 'ticket',
|
||||
route: 'apps/tickets',
|
||||
},
|
||||
{
|
||||
displayName: 'Contact List',
|
||||
iconName: 'phone',
|
||||
route: 'apps/contact-list',
|
||||
},
|
||||
{
|
||||
displayName: 'Invoice',
|
||||
iconName: 'file-invoice',
|
||||
route: 'apps/invoice',
|
||||
children: [
|
||||
{
|
||||
displayName: 'List',
|
||||
iconName: 'point',
|
||||
route: 'apps/invoice/list',
|
||||
},
|
||||
{
|
||||
displayName: 'Detail',
|
||||
iconName: 'point',
|
||||
route: 'apps/invoice/viewInvoice/101',
|
||||
},
|
||||
{
|
||||
displayName: 'Create',
|
||||
iconName: 'point',
|
||||
route: 'apps/invoice/addInvoice',
|
||||
},
|
||||
{
|
||||
displayName: 'Edit',
|
||||
iconName: 'point',
|
||||
route: 'apps/invoice/editinvoice/101',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'ToDo',
|
||||
iconName: 'edit',
|
||||
route: 'apps/todo',
|
||||
},
|
||||
{
|
||||
displayName: 'Blog',
|
||||
iconName: 'chart-donut-3',
|
||||
route: 'apps/blog',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Post',
|
||||
iconName: 'point',
|
||||
route: 'apps/blog/post',
|
||||
},
|
||||
{
|
||||
displayName: 'Detail',
|
||||
iconName: 'point',
|
||||
route: 'apps/blog/detail/Early Black Friday Amazon deals: cheap TVs, headphones, laptops',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
navCap: 'Pages',
|
||||
},
|
||||
{
|
||||
displayName: 'Roll Base Access',
|
||||
iconName: 'lock-access',
|
||||
route: 'apps/permission',
|
||||
},
|
||||
{
|
||||
displayName: 'Treeview',
|
||||
iconName: 'git-merge',
|
||||
route: 'theme-pages/treeview',
|
||||
},
|
||||
{
|
||||
displayName: 'Pricing',
|
||||
iconName: 'currency-dollar',
|
||||
route: 'theme-pages/pricing',
|
||||
},
|
||||
{
|
||||
displayName: 'Account Setting',
|
||||
iconName: 'user-circle',
|
||||
route: 'theme-pages/account-setting',
|
||||
},
|
||||
{
|
||||
displayName: 'FAQ',
|
||||
iconName: 'help',
|
||||
route: 'theme-pages/faq',
|
||||
},
|
||||
{
|
||||
displayName: 'Landingpage',
|
||||
iconName: 'app-window',
|
||||
route: 'landingpage',
|
||||
},
|
||||
{
|
||||
displayName: 'Widgets',
|
||||
iconName: 'layout',
|
||||
route: 'widgets',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Cards',
|
||||
iconName: 'point',
|
||||
route: 'widgets/cards',
|
||||
},
|
||||
{
|
||||
displayName: 'Banners',
|
||||
iconName: 'point',
|
||||
route: 'widgets/banners',
|
||||
},
|
||||
{
|
||||
displayName: 'Charts',
|
||||
iconName: 'point',
|
||||
route: 'widgets/charts',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
navCap: 'Forms',
|
||||
},
|
||||
{
|
||||
displayName: 'Form elements',
|
||||
iconName: 'apps',
|
||||
route: 'forms/forms-elements',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Autocomplete',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/autocomplete',
|
||||
},
|
||||
{
|
||||
displayName: 'Button',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/button',
|
||||
},
|
||||
{
|
||||
displayName: 'Checkbox',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/checkbox',
|
||||
},
|
||||
{
|
||||
displayName: 'Radio',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/radio',
|
||||
},
|
||||
{
|
||||
displayName: 'Datepicker',
|
||||
iconName: 'point',
|
||||
route: 'forms/forms-elements/datepicker',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Form Layouts',
|
||||
iconName: 'file-description',
|
||||
route: '/forms/form-layouts',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Horizontal',
|
||||
iconName: 'box-align-bottom',
|
||||
route: '/forms/form-horizontal',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Vertical',
|
||||
iconName: 'box-align-left',
|
||||
route: '/forms/form-vertical',
|
||||
},
|
||||
{
|
||||
displayName: 'Form Wizard',
|
||||
iconName: 'files',
|
||||
route: '/forms/form-wizard',
|
||||
},
|
||||
{
|
||||
displayName: 'Toastr',
|
||||
iconName: 'notification',
|
||||
route: '/forms/form-toastr',
|
||||
},
|
||||
{
|
||||
displayName: 'Editor',
|
||||
iconName: 'edit',
|
||||
route: '/forms/form-editor',
|
||||
chip: true,
|
||||
chipClass: 'bg-error text-white',
|
||||
chipContent: 'New',
|
||||
},
|
||||
{
|
||||
navCap: 'Tables',
|
||||
},
|
||||
{
|
||||
displayName: 'Tables',
|
||||
iconName: 'layout',
|
||||
route: 'tables',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Basic Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/basic-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Dynamic Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/dynamic-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Expand Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/expand-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Filterable Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/filterable-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Footer Row Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/footer-row-table',
|
||||
},
|
||||
{
|
||||
displayName: 'HTTP Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/http-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Mix Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/mix-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Multi Header Footer',
|
||||
iconName: 'point',
|
||||
route: 'tables/multi-header-footer-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Pagination Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/pagination-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Row Context Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/row-context-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Selection Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/selection-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sortable Table',
|
||||
iconName: 'point',
|
||||
route: 'tables/sortable-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sticky Column',
|
||||
iconName: 'point',
|
||||
route: 'tables/sticky-column-table',
|
||||
},
|
||||
{
|
||||
displayName: 'Sticky Header Footer',
|
||||
iconName: 'point',
|
||||
route: 'tables/sticky-header-footer-table',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Data table',
|
||||
iconName: 'border-outer',
|
||||
route: '/datatable/kichen-sink',
|
||||
},
|
||||
{
|
||||
navCap: 'Chart',
|
||||
},
|
||||
{
|
||||
displayName: 'Line',
|
||||
iconName: 'chart-line',
|
||||
route: '/charts/line',
|
||||
},
|
||||
{
|
||||
displayName: 'Gredient',
|
||||
iconName: 'chart-arcs',
|
||||
route: '/charts/gredient',
|
||||
},
|
||||
{
|
||||
displayName: 'Area',
|
||||
iconName: 'chart-area',
|
||||
route: '/charts/area',
|
||||
},
|
||||
{
|
||||
displayName: 'Candlestick',
|
||||
iconName: 'chart-candle',
|
||||
route: '/charts/candlestick',
|
||||
},
|
||||
{
|
||||
displayName: 'Column',
|
||||
iconName: 'chart-dots',
|
||||
route: '/charts/column',
|
||||
},
|
||||
{
|
||||
displayName: 'Doughnut & Pie',
|
||||
iconName: 'chart-donut-3',
|
||||
route: '/charts/doughnut-pie',
|
||||
},
|
||||
{
|
||||
displayName: 'Radialbar & Radar',
|
||||
iconName: 'chart-radar',
|
||||
route: '/charts/radial-radar',
|
||||
},
|
||||
{
|
||||
navCap: 'UI',
|
||||
},
|
||||
{
|
||||
displayName: 'Ui Components',
|
||||
iconName: 'box',
|
||||
route: 'ui-components',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Badge',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/badge',
|
||||
},
|
||||
{
|
||||
displayName: 'Expansion Panel',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/expansion',
|
||||
},
|
||||
{
|
||||
displayName: 'Chips',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/chips',
|
||||
},
|
||||
{
|
||||
displayName: 'Dialog',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/dialog',
|
||||
},
|
||||
{
|
||||
displayName: 'Lists',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/lists',
|
||||
},
|
||||
{
|
||||
displayName: 'Divider',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/divider',
|
||||
},
|
||||
{
|
||||
displayName: 'Menu',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/menu',
|
||||
},
|
||||
{
|
||||
displayName: 'Paginator',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/paginator',
|
||||
},
|
||||
{
|
||||
displayName: 'Progress Bar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/progress',
|
||||
},
|
||||
{
|
||||
displayName: 'Progress Spinner',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/progress-spinner',
|
||||
},
|
||||
{
|
||||
displayName: 'Ripples',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/ripples',
|
||||
},
|
||||
{
|
||||
displayName: 'Slide Toggle',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/slide-toggle',
|
||||
},
|
||||
{
|
||||
displayName: 'Slider',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/slider',
|
||||
},
|
||||
{
|
||||
displayName: 'Snackbar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/snackbar',
|
||||
},
|
||||
{
|
||||
displayName: 'Tabs',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/tabs',
|
||||
},
|
||||
{
|
||||
displayName: 'Toolbar',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/toolbar',
|
||||
},
|
||||
{
|
||||
displayName: 'Tooltips',
|
||||
iconName: 'point',
|
||||
route: 'ui-components/tooltips',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
navCap: 'Auth',
|
||||
},
|
||||
{
|
||||
displayName: 'Login',
|
||||
iconName: 'login',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Login 1',
|
||||
iconName: 'point',
|
||||
route: '/authentication/login',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Login',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-login',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Register',
|
||||
iconName: 'user-plus',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Side Register',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-register',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Register',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-register',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Forgot Password',
|
||||
iconName: 'rotate',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Side Forgot Password',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-forgot-pwd',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Forgot Password',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-forgot-pwd',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Two Steps',
|
||||
iconName: 'zoom-code',
|
||||
route: '/authentication',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Side Two Steps',
|
||||
iconName: 'point',
|
||||
route: '/authentication/side-two-steps',
|
||||
},
|
||||
{
|
||||
displayName: 'Boxed Two Steps',
|
||||
iconName: 'point',
|
||||
route: '/authentication/boxed-two-steps',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Error',
|
||||
iconName: 'alert-circle',
|
||||
route: '/authentication/error',
|
||||
},
|
||||
{
|
||||
displayName: 'Maintenance',
|
||||
iconName: 'settings',
|
||||
route: '/authentication/maintenance',
|
||||
},
|
||||
{
|
||||
navCap: 'Other',
|
||||
},
|
||||
{
|
||||
displayName: 'Menu Level',
|
||||
iconName: 'box-multiple',
|
||||
route: '/menu-level',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Menu 1',
|
||||
iconName: 'point',
|
||||
route: '/menu-1',
|
||||
children: [
|
||||
{
|
||||
displayName: 'Menu 1',
|
||||
iconName: 'point',
|
||||
route: '/menu-1',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Menu 2',
|
||||
iconName: 'point',
|
||||
route: '/menu-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Menu 2',
|
||||
iconName: 'point',
|
||||
route: '/menu-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Disabled',
|
||||
iconName: 'ban',
|
||||
route: '/disabled',
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
displayName: 'Chip',
|
||||
iconName: 'mood-smile',
|
||||
route: '/',
|
||||
chip: true,
|
||||
chipClass: 'bg-primary text-white',
|
||||
chipContent: '9',
|
||||
},
|
||||
{
|
||||
displayName: 'Outlined',
|
||||
iconName: 'mood-smile',
|
||||
route: '/',
|
||||
chip: true,
|
||||
chipClass: 'bg-error text-white',
|
||||
chipContent: 'outlined',
|
||||
},
|
||||
{
|
||||
displayName: 'External Link',
|
||||
iconName: 'star',
|
||||
route: 'https://www.google.com/',
|
||||
external: true,
|
||||
},
|
||||
];
|
||||
89
theme/packages/dark/src/app/material.module.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
// Material Form Controls
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatSliderModule } from '@angular/material/slider';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
// Material Navigation
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||
// Material Layout
|
||||
import { MatCardModule } from '@angular/material/card';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatGridListModule } from '@angular/material/grid-list';
|
||||
import { MatListModule } from '@angular/material/list';
|
||||
import { MatStepperModule } from '@angular/material/stepper';
|
||||
import { MatTabsModule } from '@angular/material/tabs';
|
||||
import { MatTreeModule } from '@angular/material/tree';
|
||||
// Material Buttons & Indicators
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||
import { MatBadgeModule } from '@angular/material/badge';
|
||||
import { MatChipsModule } from '@angular/material/chips';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatRippleModule } from '@angular/material/core';
|
||||
// Material Popups & Modals
|
||||
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
// Material Data tables
|
||||
import { MatPaginatorModule } from '@angular/material/paginator';
|
||||
import { MatSortModule } from '@angular/material/sort';
|
||||
import { MatTableModule } from '@angular/material/table';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
|
||||
],
|
||||
exports: [
|
||||
MatAutocompleteModule,
|
||||
MatCheckboxModule,
|
||||
MatDatepickerModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatRadioModule,
|
||||
MatSelectModule,
|
||||
MatSliderModule,
|
||||
MatSlideToggleModule,
|
||||
MatMenuModule,
|
||||
MatSidenavModule,
|
||||
MatToolbarModule,
|
||||
MatCardModule,
|
||||
MatDividerModule,
|
||||
MatExpansionModule,
|
||||
MatGridListModule,
|
||||
MatListModule,
|
||||
MatStepperModule,
|
||||
MatTabsModule,
|
||||
MatTreeModule,
|
||||
MatButtonModule,
|
||||
MatButtonToggleModule,
|
||||
MatBadgeModule,
|
||||
MatChipsModule,
|
||||
MatIconModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatProgressBarModule,
|
||||
MatRippleModule,
|
||||
MatBottomSheetModule,
|
||||
MatDialogModule,
|
||||
MatSnackBarModule,
|
||||
MatTooltipModule,
|
||||
MatPaginatorModule,
|
||||
MatSortModule,
|
||||
MatTableModule,
|
||||
],
|
||||
|
||||
})
|
||||
export class MaterialModule {}
|
||||
123
theme/packages/dark/src/app/pages/apps/chat/chat.component.html
Normal file
@@ -0,0 +1,123 @@
|
||||
<mat-card class="chat-app cardWithShadow">
|
||||
<mat-sidenav-container [ngClass]="{
|
||||
'side-panel-opened': sidePanelOpened,
|
||||
'side-panel-closed': !sidePanelOpened
|
||||
}">
|
||||
<!-- ---------------------------------------------------- -->
|
||||
<!-- sidebar -->
|
||||
<!-- ---------------------------------------------------- -->
|
||||
<mat-sidenav [mode]="isOver() ? 'over' : 'side'" [opened]="sidePanelOpened" (open)="sidePanelOpened = true"
|
||||
(close)="sidePanelOpened = false">
|
||||
<ng-scrollbar class="position-relative" style="height: 100%">
|
||||
<div class="d-flex align-items-center p-24 gap-16">
|
||||
<img src="assets/images/profile/user-1.jpg" class="rounded-circle" width="54" />
|
||||
<div>
|
||||
<h4 class="f-s-16 f-w-600">Mathew Anderson</h4>
|
||||
<span class="f-s-12">info@modernize.com</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-x-24">
|
||||
<!-- search -->
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<input matInput placeholder="Search Contacts" [(ngModel)]="searchTerm" (input)="searchMessages()" />
|
||||
<mat-icon matSuffix>
|
||||
<i-tabler name="search" class="icon-20 d-flex align-items-end m-t-2"></i-tabler>
|
||||
</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
@if (filteredMessages() && filteredMessages().length > 0) {
|
||||
<div class="m-x-24">
|
||||
<mat-nav-list class="chat-listing">
|
||||
@for(message of filteredMessages(); track message.from) {
|
||||
<mat-list-item role="listitem" (click)="selectMessage(message)"
|
||||
[class.bg-light-primary]="message === selectedMessage()" class="m-b-2 gap-12">
|
||||
<span matListItemIcon>
|
||||
<img src="{{ message.photo }}" alt="" width="42" class="rounded-circle" />
|
||||
</span>
|
||||
<h3 class="f-w-600 f-s-16" matListItemTitle>
|
||||
{{ message.from }}
|
||||
</h3>
|
||||
<p class="f-s-14 m-t-4" matListItemLine>
|
||||
{{ message.subject }}
|
||||
</p>
|
||||
</mat-list-item>
|
||||
}
|
||||
</mat-nav-list>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="p-15 bg-light-primary text-primary rounded m-x-20 m-t-20 text-center">
|
||||
<span class="f-s-14">No messages found.</span>
|
||||
</div>
|
||||
}
|
||||
</ng-scrollbar>
|
||||
</mat-sidenav>
|
||||
<mat-sidenav-content>
|
||||
<!-- ------------------------------------------- -->
|
||||
<!-- chat details -->
|
||||
<!-- ------------------------------------------- -->
|
||||
<mat-toolbar class="chat-right-panel d-flex align-items-center b-b-1 gap-8">
|
||||
<button (click)="sidePanelOpened = !sidePanelOpened" mat-icon-button>
|
||||
<mat-icon>short_text</mat-icon>
|
||||
</button>
|
||||
<div class="d-flex align-items-center gap-16">
|
||||
<img src="{{ selectedMessage()?.photo }}" width="40" class="rounded-circle" />
|
||||
<div class="f-s-16 f-w-600">
|
||||
{{ selectedMessage()?.from }}
|
||||
</div>
|
||||
</div>
|
||||
<button [matMenuTriggerFor]="moredd" class="m-l-auto" mat-icon-button>
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
<mat-menu #moredd="matMenu" x-position="before">
|
||||
<button mat-menu-item>Contact info</button>
|
||||
<button mat-menu-item>Mute</button>
|
||||
<button mat-menu-item>Delete chat</button>
|
||||
</mat-menu>
|
||||
</mat-toolbar>
|
||||
|
||||
<!-- ------------------------------------------- -->
|
||||
<!-- chat content -->
|
||||
<!-- ------------------------------------------- -->
|
||||
<ng-scrollbar style="height: calc(100vh - 442px)" class="position-relative">
|
||||
<mat-card-content class="chat-middle-box p-24">
|
||||
@for(c of selectedMessage()?.chat; track c) { @if(c.type === 'odd') {
|
||||
<div class="chat-list odd">
|
||||
<div class="m-b-15">
|
||||
<div class="bg-light-primary p-10 rounded d-flex align-items-center gap-16">
|
||||
<img src="{{ selectedMessage()?.photo }}" class="rounded-circle" width="40" />
|
||||
<span class="f-s-14">{{ c.msg }}</span>
|
||||
</div>
|
||||
<span class="f-s-12">
|
||||
{{ c.date | date }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="chat-list even">
|
||||
<div class="m-b-15">
|
||||
<div class="bg-light-secondary p-10 rounded d-flex align-items-center f-s-14">
|
||||
{{ c.msg }}
|
||||
</div>
|
||||
<span class="f-s-12">
|
||||
{{ c.date | date }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
} }
|
||||
</mat-card-content>
|
||||
</ng-scrollbar>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="p-t-20 p-x-24">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<input matInput placeholder="Send message" [ngModel]="msg()" (ngModelChange)="msg.set($event)"
|
||||
(keydown.enter)="sendMessage()" />
|
||||
<button mat-icon-button matSuffix (click)="sendMessage()" [disabled]="!msg">
|
||||
<mat-icon>send</mat-icon>
|
||||
</button>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,286 @@
|
||||
import {
|
||||
Component,
|
||||
ChangeDetectionStrategy,
|
||||
Inject,
|
||||
signal,
|
||||
DOCUMENT
|
||||
} from '@angular/core';
|
||||
import { CommonModule, NgSwitch } from '@angular/common';
|
||||
import {
|
||||
MatDialog,
|
||||
MatDialogRef,
|
||||
MatDialogConfig,
|
||||
MAT_DIALOG_DATA,
|
||||
MatDialogModule,
|
||||
} from '@angular/material/dialog';
|
||||
import {
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
UntypedFormGroup,
|
||||
} from '@angular/forms';
|
||||
import { CalendarFormDialogComponent } from './calendar-form-dialog/calendar-form-dialog.component';
|
||||
import {
|
||||
startOfDay,
|
||||
subDays,
|
||||
addDays,
|
||||
endOfMonth,
|
||||
isSameDay,
|
||||
isSameMonth,
|
||||
addHours,
|
||||
subMonths,
|
||||
addMonths,
|
||||
} from 'date-fns';
|
||||
import { Subject } from 'rxjs';
|
||||
import {
|
||||
CalendarDateFormatter,
|
||||
CalendarEvent,
|
||||
CalendarEventAction,
|
||||
CalendarEventTimesChangedEvent,
|
||||
CalendarModule,
|
||||
CalendarView,
|
||||
} from 'angular-calendar';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import {
|
||||
MatNativeDateModule,
|
||||
provideNativeDateAdapter,
|
||||
} from '@angular/material/core';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
|
||||
const colors: any = {
|
||||
red: {
|
||||
primary: '#fa896b',
|
||||
secondary: '#fdede8',
|
||||
},
|
||||
blue: {
|
||||
primary: '#5d87ff',
|
||||
secondary: '#ecf2ff',
|
||||
},
|
||||
yellow: {
|
||||
primary: '#ffae1f',
|
||||
secondary: '#fef5e5',
|
||||
},
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-calendar-dialog',
|
||||
templateUrl: './dialog.component.html',
|
||||
imports: [
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
CommonModule,
|
||||
MatNativeDateModule,
|
||||
MatDialogModule,
|
||||
MatDatepickerModule, TablerIconsModule
|
||||
],
|
||||
providers: [provideNativeDateAdapter()],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class CalendarDialogComponent {
|
||||
options!: UntypedFormGroup;
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<CalendarDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any
|
||||
) {}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-fullcalendar',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: './fullcalendar.component.html',
|
||||
imports: [
|
||||
MaterialModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
NgSwitch,
|
||||
CalendarModule,
|
||||
CommonModule,
|
||||
MatDatepickerModule,
|
||||
MatDialogModule,
|
||||
MatFormFieldModule,
|
||||
],
|
||||
providers: [provideNativeDateAdapter(), CalendarDateFormatter]
|
||||
})
|
||||
export class AppFullcalendarComponent {
|
||||
dialogRef = signal<MatDialogRef<CalendarDialogComponent> | any>(null);
|
||||
dialogRef2 = signal<MatDialogRef<CalendarFormDialogComponent> | any>(null);
|
||||
lastCloseResult = signal<string>('');
|
||||
actionsAlignment = signal<string>('');
|
||||
view = signal<any>('month');
|
||||
viewDate = signal<Date>(new Date());
|
||||
activeDayIsOpen = signal<boolean>(true);
|
||||
|
||||
config: MatDialogConfig = {
|
||||
disableClose: false,
|
||||
width: '',
|
||||
height: '',
|
||||
position: {
|
||||
top: '',
|
||||
bottom: '',
|
||||
left: '',
|
||||
right: '',
|
||||
},
|
||||
data: {
|
||||
action: '',
|
||||
event: [],
|
||||
},
|
||||
};
|
||||
numTemplateOpens = 0;
|
||||
|
||||
actions: CalendarEventAction[] = [
|
||||
{
|
||||
label: '<span class="text-white link m-l-5">: Edit</span>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.handleEvent('Edit', event);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '<span class="text-danger m-l-5">Delete</span>',
|
||||
onClick: ({ event }: { event: CalendarEvent }): void => {
|
||||
this.events.set(
|
||||
this.events().filter((iEvent: CalendarEvent<any>) => iEvent !== event)
|
||||
);
|
||||
this.handleEvent('Deleted', event);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
refresh: Subject<any> = new Subject();
|
||||
|
||||
events = signal<CalendarEvent[] | any>([
|
||||
{
|
||||
start: subDays(startOfDay(new Date()), 1),
|
||||
end: addDays(new Date(), 1),
|
||||
title: 'A 3 day event',
|
||||
color: colors.red,
|
||||
actions: this.actions,
|
||||
},
|
||||
{
|
||||
start: startOfDay(new Date()),
|
||||
title: 'An event with no end date',
|
||||
color: colors.blue,
|
||||
actions: this.actions,
|
||||
},
|
||||
{
|
||||
start: subDays(endOfMonth(new Date()), 3),
|
||||
end: addDays(endOfMonth(new Date()), 3),
|
||||
title: 'A long event that spans 2 months',
|
||||
color: colors.blue,
|
||||
},
|
||||
{
|
||||
start: addHours(startOfDay(new Date()), 2),
|
||||
end: new Date(),
|
||||
title: 'A draggable and resizable event',
|
||||
color: colors.yellow,
|
||||
actions: this.actions,
|
||||
resizable: {
|
||||
beforeStart: true,
|
||||
afterEnd: true,
|
||||
},
|
||||
draggable: true,
|
||||
},
|
||||
]);
|
||||
|
||||
constructor(public dialog: MatDialog, @Inject(DOCUMENT) doc: any) {}
|
||||
|
||||
dayClicked({ date, events }: { date: Date; events: CalendarEvent[] }): void {
|
||||
if (isSameMonth(date, this.viewDate())) {
|
||||
if (
|
||||
(isSameDay(this.viewDate(), date) && this.activeDayIsOpen() === true) ||
|
||||
events.length === 0
|
||||
) {
|
||||
this.activeDayIsOpen.set(false);
|
||||
} else {
|
||||
this.activeDayIsOpen.set(true);
|
||||
this.viewDate.set(date);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventTimesChanged({
|
||||
event,
|
||||
newStart,
|
||||
newEnd,
|
||||
}: CalendarEventTimesChangedEvent): void {
|
||||
this.events.set(
|
||||
this.events().map((iEvent: CalendarEvent<any>) => {
|
||||
if (iEvent === event) {
|
||||
return {
|
||||
...event,
|
||||
start: newStart,
|
||||
end: newEnd,
|
||||
};
|
||||
}
|
||||
return iEvent;
|
||||
})
|
||||
);
|
||||
|
||||
this.handleEvent('Dropped or resized', event);
|
||||
}
|
||||
|
||||
handleEvent(action: string, event: CalendarEvent): void {
|
||||
this.config.data = { event, action };
|
||||
this.dialogRef.set(this.dialog.open(CalendarDialogComponent, this.config));
|
||||
|
||||
this.dialogRef()
|
||||
.afterClosed()
|
||||
.subscribe((result: string) => {
|
||||
this.lastCloseResult.set(result);
|
||||
this.dialogRef.set(null);
|
||||
this.refresh.next(result);
|
||||
});
|
||||
}
|
||||
|
||||
addEvent(): void {
|
||||
this.dialogRef2.set(
|
||||
this.dialog.open(CalendarFormDialogComponent, {
|
||||
panelClass: 'calendar-form-dialog',
|
||||
autoFocus: false,
|
||||
data: {
|
||||
action: 'add',
|
||||
date: new Date(),
|
||||
},
|
||||
})
|
||||
);
|
||||
this.dialogRef2()
|
||||
.afterClosed()
|
||||
.subscribe((res: { action: any; event: any }) => {
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
const dialogAction = res.action;
|
||||
const responseEvent = res.event;
|
||||
responseEvent.actions = this.actions;
|
||||
this.events.set([...this.events(), responseEvent]);
|
||||
this.dialogRef2.set(null);
|
||||
this.refresh.next(res);
|
||||
});
|
||||
}
|
||||
|
||||
deleteEvent(eventToDelete: CalendarEvent): void {
|
||||
this.events.set(
|
||||
this.events().filter(
|
||||
(event: CalendarEvent<any>) => event !== eventToDelete
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setView(view: CalendarView | any): void {
|
||||
this.view.set(view);
|
||||
}
|
||||
|
||||
goToPreviousMonth(): void {
|
||||
this.viewDate.set(subMonths(this.viewDate(), 1));
|
||||
}
|
||||
|
||||
goToNextMonth(): void {
|
||||
this.viewDate.set(addMonths(this.viewDate(), 1));
|
||||
}
|
||||
|
||||
goToToday() {
|
||||
this.viewDate.set(new Date());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
<form #invoiceForm="ngForm">
|
||||
<div class="row justify-content-between m-b-24">
|
||||
<div class="col-sm-4 d-flex align-items-center">
|
||||
<h4 class="f-s-18 f-w-600">
|
||||
#
|
||||
<span name="id" [(ngModel)]="invoice().id" ngDefaultControl>
|
||||
{{ invoice().id }}</span>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="col-sm-4 text-right">
|
||||
<a routerLink="/apps/invoice/list" mat-flat-button class="bg-error text-white m-r-10">
|
||||
Cancel
|
||||
</a>
|
||||
<button mat-flat-button color="primary" (click)="saveDetail($event)" [disabled]="addForm.invalid">
|
||||
Save Invoice
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="row p-y-24 justify-content-between">
|
||||
<div class="col-sm-4">
|
||||
<span class="f-w-600 f-s-15 d-block m-b-8">
|
||||
Order Status:
|
||||
</span>
|
||||
|
||||
<h6 name="date" class="m-t-5 m-b-0 f-w-500 f-s-14" ngDefaultControl>
|
||||
{{ invoice().status }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 d-flex align-items-center justify-content-end">
|
||||
<div class="text-right">
|
||||
<span class="f-w-600 f-s-15 d-block m-b-8">
|
||||
Order Date
|
||||
</span>
|
||||
<h6 name="date" class="m-t-5 m-b-0 f-w-500 f-s-14" [(ngModel)]="invoice().orderDate"
|
||||
ngDefaultControl>
|
||||
{{ invoice().orderDate | date : "dd-MM-yyyy" }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="row m-y-24 p-t-24">
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill From</mat-label>
|
||||
<input matInput placeholder="Bill From" name="from" [(ngModel)]="invoice().billFrom" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill To</mat-label>
|
||||
<input matInput placeholder="Bill To" name="to" [(ngModel)]="invoice().billTo" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Enter From Address</mat-label>
|
||||
<input matInput placeholder="Enter From Address" name="fromAddress"
|
||||
[(ngModel)]="invoice().billFromAddress" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill From</mat-label>
|
||||
<input matInput placeholder="Enter To Address" name="toAddress" [(ngModel)]="invoice().billToAddress" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div [formGroup]="addForm" class="add-invoice-list">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover b-1 no-wrap w-100 rounded text-left">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="p-16">#</th>
|
||||
<th class="p-16">Item Name</th>
|
||||
<th class="p-16">Unit Price</th>
|
||||
<th class="p-16">Units</th>
|
||||
<th class="p-16">Unit Total Price</th>
|
||||
<th class="p-16"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@for(row of addForm.get('rows')['controls']; track row; let index =
|
||||
$index) {
|
||||
<tr>
|
||||
<td class="p-16">
|
||||
{{ index + 1 }}
|
||||
</td>
|
||||
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input type="text" matInput class="form-control" [formControl]="row.get('itemName')"
|
||||
(input)="itemsChanged()" />
|
||||
</mat-form-field>
|
||||
</td>
|
||||
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input type="number" matInput class="form-control" min="1" [formControl]="row.get('unitPrice')"
|
||||
(input)="itemsChanged()" />
|
||||
</mat-form-field>
|
||||
</td>
|
||||
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input type="number" matInput class="form-control" min="1" [formControl]="row.get('units')"
|
||||
(input)="itemsChanged()" />
|
||||
</mat-form-field>
|
||||
</td>
|
||||
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input [disabled]="true" matInput matInput class="form-control" [formControl]="row.get('itemTotal')"
|
||||
[value]="
|
||||
row.get('unitPrice').value * row.get('units').value
|
||||
" />
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td>
|
||||
@if(addForm.get('rows')) {
|
||||
<button (click)="onAddRow()" [disabled]="addForm.invalid" class="d-flex justify-content-center icon-38 p-8" mat-icon-button>
|
||||
<i-tabler name="circle-plus" class="icon-18 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
@if(index > 0) {
|
||||
<button mat-icon-button (click)="onRemoveRow(index)" class="d-flex justify-content-center icon-38 p-8">
|
||||
<i-tabler name="trash" class="icon-18 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="text-right m-t-30">
|
||||
<h5 class="m-b-5 f-w-600 f-s-16">Sub total: {{ subTotal() }}</h5>
|
||||
<h5 class="f-w-600 f-s-16 m-b-24">Total Vat: {{ vat() }}%</h5>
|
||||
<mat-divider></mat-divider>
|
||||
<h3 class="m-b-0 p-t-20 f-s-18">Grand Total: {{ grandTotal() }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,239 @@
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
@if( invoice()) {
|
||||
<span>
|
||||
<form #invoiceForm="ngForm">
|
||||
<div class="row m-b-24">
|
||||
<div class="col-sm-4 d-flex align-items-center">
|
||||
<h4 class="f-s-14 f-s-18 f-w-600">
|
||||
#
|
||||
<span name="id" [(ngModel)]="invoice().id" ngDefaultControl>
|
||||
{{ invoice().id }}</span
|
||||
>
|
||||
</h4>
|
||||
</div>
|
||||
<div class="col-sm-8 text-right">
|
||||
<a
|
||||
routerLink="/apps/invoice/list"
|
||||
mat-flat-button
|
||||
class="bg-error text-white m-r-10"
|
||||
>
|
||||
Cancel
|
||||
</a>
|
||||
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
(click)="saveDetail($event)"
|
||||
>
|
||||
Save Invoice
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="row p-y-24 justify-content-between">
|
||||
<div class="col-sm-4">
|
||||
<span class="f-w-600 f-s-15 d-block m-b-8"> Order Status: </span>
|
||||
<mat-form-field appearance="outline" class="w-100 theme-select">
|
||||
<mat-select name="satus" [(ngModel)]="invoice().status">
|
||||
<mat-option value="Pending"> Pending </mat-option>
|
||||
<mat-option value="Shipped"> Shipped </mat-option>
|
||||
<mat-option value="Delivered"> Delivered </mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6 d-flex align-items-center justify-content-end">
|
||||
<div class="text-right">
|
||||
<span class="f-w-600 f-s-15 d-block m-b-8"> Order Date </span>
|
||||
<h6
|
||||
name="date"
|
||||
class="m-t-5 m-b-0 f-w-500 f-s-14 f-s-16"
|
||||
[(ngModel)]="invoice().orderDate"
|
||||
ngDefaultControl
|
||||
>
|
||||
{{ invoice().orderDate | date : "dd-MM-yyyy" }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="row m-y-24 p-t-24">
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill From</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="Bill From"
|
||||
name="from"
|
||||
[(ngModel)]="invoice().billFrom"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill To</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="Bill To"
|
||||
name="to"
|
||||
[(ngModel)]="invoice().billTo"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Enter From Address</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="Enter From Address"
|
||||
name="fromAddress"
|
||||
[(ngModel)]="invoice().billFromAddress"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-label>Bill From</mat-label>
|
||||
<input
|
||||
matInput
|
||||
placeholder="Enter To Address"
|
||||
name="toAddress"
|
||||
[(ngModel)]="invoice().billToAddress"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</span>
|
||||
}
|
||||
|
||||
<form [formGroup]="addForm" class="edit-invoice-list">
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
id="tblAdd"
|
||||
class="table table-hover b-1 no-wrap w-100 rounded text-left"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="p-16">#</th>
|
||||
<th class="p-16">Item Name</th>
|
||||
<th class="p-16">Unit Price</th>
|
||||
<th class="p-16">Units</th>
|
||||
<th class="p-16">Unit Total Price</th>
|
||||
<th class="p-16"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
@for(a of addForm.get('item')['controls']; track a; let i =$index) {
|
||||
<tbody formArrayName="item">
|
||||
<tr [formGroupName]="i">
|
||||
<td class="p-16">
|
||||
{{ i + 1 }}
|
||||
</td>
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input
|
||||
matInput
|
||||
type="text"
|
||||
[id]="'txtNameControl' + i"
|
||||
class="form-control"
|
||||
placeholder="Enter Item Name"
|
||||
formControlName="itemName"
|
||||
(input)="itemsChanged()"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
[id]="'txtCostControl' + i"
|
||||
class="form-control"
|
||||
placeholder="Enter Item Price"
|
||||
formControlName="itemCost"
|
||||
(input)="itemsChanged()"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
[id]="'txtTotalControl' + i"
|
||||
class="form-control"
|
||||
placeholder="Enter Item"
|
||||
formControlName="itemSold"
|
||||
(input)="itemsChanged()"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td class="p-16">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input
|
||||
matInput
|
||||
type="number"
|
||||
formControlName="itemTotal"
|
||||
[id]="'txtitemTotalControl' + i"
|
||||
[value]="
|
||||
(addForm.get('item')?.value[i]?.itemCost || 0) *
|
||||
(addForm.get('item')?.value[i]?.itemSold || 0)
|
||||
"
|
||||
class="form-control"
|
||||
[disabled]="true"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</td>
|
||||
<td>
|
||||
<button
|
||||
mat-icon-button
|
||||
color="primary"
|
||||
(click)="btnAddItemClick()"
|
||||
class="d-flex justify-content-center icon-38 p-8"
|
||||
[disabled]="addForm.get('item')?.invalid"
|
||||
>
|
||||
<i-tabler
|
||||
name="circle-plus"
|
||||
class="icon-18 d-flex"
|
||||
></i-tabler>
|
||||
</button>
|
||||
</td>
|
||||
<td>
|
||||
@if(addForm.get('item')?.length > 1) {
|
||||
<button
|
||||
mat-icon-button
|
||||
(click)="btnRemoveClick(i)"
|
||||
class="d-flex justify-content-center icon-38 p-8"
|
||||
>
|
||||
<i-tabler name="trash" class="icon-18 d-flex"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="text-right m-t-30">
|
||||
<div class="text-right m-t-30">
|
||||
@if(addForm.get('rows')) {
|
||||
<button color="accent" mat-flat-button [disabled]="addForm.invalid">
|
||||
Add row
|
||||
</button>
|
||||
}
|
||||
|
||||
<h5 class="m-b-5 f-w-600 f-s-16">Sub total: {{ subTotal() }}</h5>
|
||||
<h5 class="f-w-600 f-s-16 m-b-24">Total Vat: {{ vat() }}%</h5>
|
||||
<mat-divider></mat-divider>
|
||||
<h3 class="m-b-0 p-t-20 f-s-18">Grand Total: {{ grandTotal() }}</h3>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,164 @@
|
||||
import { Component, signal } from '@angular/core';
|
||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
|
||||
import { InvoiceService } from 'src/app/services/apps/invoice/invoice.service';
|
||||
import { InvoiceList, order } from '../invoice';
|
||||
import {
|
||||
UntypedFormGroup,
|
||||
UntypedFormArray,
|
||||
UntypedFormBuilder,
|
||||
Validators,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
} from '@angular/forms';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { OkDialogComponent } from './ok-dialog/ok-dialog.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
@Component({
|
||||
selector: 'app-edit-invoice',
|
||||
templateUrl: './edit-invoice.component.html',
|
||||
imports: [
|
||||
MaterialModule,
|
||||
CommonModule,
|
||||
RouterLink,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TablerIconsModule,
|
||||
],
|
||||
})
|
||||
export class AppEditInvoiceComponent {
|
||||
id = signal<any>(null);
|
||||
subTotal = signal<number>(0);
|
||||
vat = signal<number>(0);
|
||||
grandTotal = signal<number>(0);
|
||||
addForm: UntypedFormGroup | any;
|
||||
invoice = signal<InvoiceList | any>([]);
|
||||
constructor(
|
||||
activatedRouter: ActivatedRoute,
|
||||
private invoiceService: InvoiceService,
|
||||
private router: Router,
|
||||
private fb: UntypedFormBuilder,
|
||||
public dialog: MatDialog,
|
||||
private snackBar: MatSnackBar
|
||||
) {
|
||||
this.id.set(activatedRouter.snapshot.paramMap.get('id'));
|
||||
this.loadInvoice(); // Load invoice here
|
||||
this.subTotal.set(this.invoice()?.totalCost || 0);
|
||||
this.vat.set(this.invoice()?.vat || 0);
|
||||
this.grandTotal.set(this.invoice()?.grandTotal || 0);
|
||||
this.addForm = this.fb.group({
|
||||
item: this.fb.array([this.itemControl()]),
|
||||
});
|
||||
|
||||
this.fillAddControls();
|
||||
}
|
||||
|
||||
loadInvoice(): void {
|
||||
const invoiceData = this.invoiceService
|
||||
.getInvoiceList()
|
||||
.find((x) => x.id === +this.id());
|
||||
this.invoice.set(invoiceData); // Set the invoice signal
|
||||
}
|
||||
itemControl(): UntypedFormGroup {
|
||||
return this.fb.group({
|
||||
itemName: ['', Validators.required],
|
||||
itemCost: ['', Validators.required],
|
||||
itemSold: ['', Validators.required],
|
||||
itemTotal: [{ value: 0, disabled: true }],
|
||||
});
|
||||
}
|
||||
|
||||
fillAddControls(): void {
|
||||
this.addForm.setControl('item', this.setItem(this.invoice()?.orders));
|
||||
}
|
||||
|
||||
setItem(order: any): UntypedFormArray {
|
||||
const fa = new UntypedFormArray([]);
|
||||
order?.forEach((s: any) => {
|
||||
fa.push(
|
||||
this.fb.group({
|
||||
itemName: s.itemName,
|
||||
itemCost: s.unitPrice,
|
||||
itemSold: s.units,
|
||||
itemTotal: s.unitTotalPrice,
|
||||
})
|
||||
);
|
||||
});
|
||||
return fa;
|
||||
}
|
||||
|
||||
btnAddItemClick(): void {
|
||||
(<UntypedFormArray>this.addForm.get('item')).push(this.itemControl());
|
||||
}
|
||||
|
||||
btnRemoveClick(i: number): void {
|
||||
const totalCostOfItem =
|
||||
this.addForm.get('item')?.value[i].itemCost *
|
||||
this.addForm.get('item')?.value[i].itemSold;
|
||||
|
||||
this.subTotal.set(this.subTotal() - totalCostOfItem);
|
||||
this.vat.set(this.subTotal() / 10);
|
||||
this.grandTotal.set(this.subTotal() + this.vat());
|
||||
|
||||
(<UntypedFormArray>this.addForm.get('item')).removeAt(i);
|
||||
}
|
||||
|
||||
itemsChanged(): void {
|
||||
let total = 0;
|
||||
for (
|
||||
let t = 0;
|
||||
t < (<UntypedFormArray>this.addForm.get('item')).length;
|
||||
t++
|
||||
) {
|
||||
if (
|
||||
this.addForm.get('item')?.value[t].itemCost != '' &&
|
||||
this.addForm.get('item')?.value[t].itemSold
|
||||
) {
|
||||
total +=
|
||||
this.addForm.get('item')?.value[t].itemCost *
|
||||
this.addForm.get('item')?.value[t].itemSold;
|
||||
}
|
||||
}
|
||||
this.subTotal.set(total);
|
||||
this.vat.set(this.subTotal() / 10);
|
||||
this.grandTotal.set(this.subTotal() + this.vat());
|
||||
}
|
||||
|
||||
saveDetail(event: Event): void {
|
||||
event.preventDefault();
|
||||
const currentInvoice = this.invoice();
|
||||
if (currentInvoice) {
|
||||
currentInvoice.grandTotal = this.grandTotal();
|
||||
currentInvoice.totalCost = this.subTotal();
|
||||
currentInvoice.vat = this.vat();
|
||||
currentInvoice.orders = [];
|
||||
|
||||
for (
|
||||
let t = 0;
|
||||
t < (<UntypedFormArray>this.addForm.get('item')).length;
|
||||
t++
|
||||
) {
|
||||
const o: order = new order();
|
||||
o.itemName = this.addForm.get('item')?.value[t].itemName;
|
||||
o.unitPrice = this.addForm.get('item')?.value[t].itemCost;
|
||||
o.units = this.addForm.get('item')?.value[t].itemSold;
|
||||
o.unitTotalPrice = o.units * o.unitPrice;
|
||||
currentInvoice.orders.push(o);
|
||||
}
|
||||
this.dialog.open(OkDialogComponent);
|
||||
this.invoiceService.updateInvoice(currentInvoice.id, currentInvoice);
|
||||
this.router.navigate(['/apps/invoice/list']);
|
||||
this.showSnackbar('Invoice updated successfully!');
|
||||
}
|
||||
}
|
||||
|
||||
showSnackbar(message: string): void {
|
||||
this.snackBar.open(message, 'Close', {
|
||||
duration: 3000,
|
||||
horizontalPosition: 'center',
|
||||
verticalPosition: 'top',
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
<div class="row">
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card
|
||||
class="cardWithShadow cursor-pointer bg-light-primary shadow-none"
|
||||
[ngClass]="{ 'active-tab': activeTab() === 'All' }"
|
||||
(click)="handleTabClick('All')"
|
||||
>
|
||||
<mat-card-content class="d-flex align-items-center gap-16">
|
||||
<div
|
||||
class="icon icon-38 rounded d-flex align-items-center justify-content-center bg-primary text-white"
|
||||
>
|
||||
<i-tabler name="list-details" class="icon-24 d-flex"></i-tabler>
|
||||
</div>
|
||||
<div class="info">
|
||||
<h5 class="f-w-400 lh-sm f-s-14">Total</h5>
|
||||
<h5 class="f-w-500 lh-sm f-s-14">
|
||||
{{ allInvoices().length }} invoices
|
||||
</h5>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card
|
||||
class="cardWithShadow cursor-pointer bg-light-secondary shadow-none"
|
||||
[ngClass]="{ 'active-tab': activeTab() === 'Shipped' }"
|
||||
(click)="handleTabClick('Shipped')"
|
||||
>
|
||||
<mat-card-content class="d-flex align-items-center gap-16">
|
||||
<div
|
||||
class="icon icon-38 rounded d-flex align-items-center justify-content-center bg-secondary text-white"
|
||||
>
|
||||
<i-tabler name="shopping-bag" class="icon-24 d-flex"></i-tabler>
|
||||
</div>
|
||||
<div class="info">
|
||||
<h5 class="f-w-400 lh-sm f-s-14">Shipped</h5>
|
||||
<h5 class="f-w-500 lh-sm f-s-14">
|
||||
{{ countInvoicesByStatus("Shipped") }} invoices
|
||||
</h5>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card
|
||||
class="cardWithShadow cursor-pointer bg-light-success shadow-none"
|
||||
[ngClass]="{ 'active-tab': activeTab() === 'Delivered' }"
|
||||
(click)="handleTabClick('Delivered')"
|
||||
>
|
||||
<mat-card-content class="d-flex align-items-center gap-16">
|
||||
<div
|
||||
class="icon icon-38 rounded d-flex align-items-center justify-content-center bg-success text-white"
|
||||
>
|
||||
<i-tabler name="truck" class="icon-24 d-flex"></i-tabler>
|
||||
</div>
|
||||
<div class="info">
|
||||
<h5 class="f-w-400 lh-sm f-s-14">Delivered</h5>
|
||||
<h5 class="f-w-500 lh-sm f-s-14">
|
||||
{{ countInvoicesByStatus("Delivered") }} invoices
|
||||
</h5>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card
|
||||
class="cardWithShadow cursor-pointer bg-light-warning shadow-none"
|
||||
[ngClass]="{ 'active-tab': activeTab() === 'Pending' }"
|
||||
(click)="handleTabClick('Pending')"
|
||||
>
|
||||
<mat-card-content class="d-flex align-items-center gap-16">
|
||||
<div
|
||||
class="icon icon-38 rounded d-flex align-items-center justify-content-center bg-warning text-white"
|
||||
>
|
||||
<i-tabler name="sort-ascending" class="icon-24 d-flex"></i-tabler>
|
||||
</div>
|
||||
<div class="info">
|
||||
<h5 class="f-w-400 lh-sm f-s-14">Pending</h5>
|
||||
<h5 class="f-w-500 lh-sm f-s-14">
|
||||
{{ countInvoicesByStatus("Pending") }} invoices
|
||||
</h5>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
<div class="row justify-content-between align-items-center">
|
||||
<div class="col-sm-4">
|
||||
<mat-form-field appearance="outline" class="w-100 hide-hint">
|
||||
<input
|
||||
matInput
|
||||
placeholder="Search Invoice"
|
||||
(keyup)="filter($any($event.target).value)"
|
||||
/>
|
||||
<mat-icon matSuffix>
|
||||
<i-tabler name="search" class="icon-20 d-flex m-t-4"></i-tabler>
|
||||
</mat-icon>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-4 d-flex align-items-center justify-content-end">
|
||||
<a
|
||||
mat-button
|
||||
[routerLink]="['/apps/invoice/addInvoice']"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
>Add Invoice</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
<div class="table-responsive">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="invoiceList"
|
||||
matSort
|
||||
class="no-wrap m-t-0 v-middle w-100"
|
||||
>
|
||||
<ng-container matColumnDef="chk">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox
|
||||
[checked]="allComplete()"
|
||||
[indeterminate]="someComplete()"
|
||||
(change)="setAll($event.checked)"
|
||||
color="primary"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
<mat-checkbox
|
||||
[(ngModel)]="element.completed"
|
||||
(ngModelChange)="updateAllComplete()"
|
||||
color="primary"
|
||||
>
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="id">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
mat-sort-header
|
||||
class="f-w-600 f-s-15"
|
||||
>
|
||||
Id
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
{{ element.id }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="billFrom">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
mat-sort-header
|
||||
class="f-w-600 f-s-15"
|
||||
>
|
||||
Bill From
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
{{ element.billFrom }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="billTo">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
mat-sort-header
|
||||
class="f-w-600 f-s-15"
|
||||
>
|
||||
Bill To
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
{{ element.billTo }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="totalCost">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
mat-sort-header
|
||||
class="f-w-600 f-s-15"
|
||||
>
|
||||
Total Cost
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
{{ element.totalCost }}
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="status">
|
||||
<th
|
||||
mat-header-cell
|
||||
*matHeaderCellDef
|
||||
mat-sort-header
|
||||
class="f-w-600 f-s-15"
|
||||
>
|
||||
Status
|
||||
</th>
|
||||
|
||||
<td mat-cell *matCellDef="let element" class="f-s-14">
|
||||
<span
|
||||
class="p-x-8 p-y-4 f-w-500 rounded-pill f-s-12"
|
||||
[ngStyle]="{
|
||||
'background-color':
|
||||
element.status === 'Shipped'
|
||||
? 'rgb(93, 135, 255)'
|
||||
: element.status === 'Delivered'
|
||||
? 'rgb(19, 222, 185)'
|
||||
: element.status === 'Pending'
|
||||
? 'rgb(255, 174, 31)'
|
||||
: 'transparent',
|
||||
color: 'white'
|
||||
}"
|
||||
>
|
||||
{{ element.status }}
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="action">
|
||||
<th mat-header-cell *matHeaderCellDef class="f-w-600 f-s-15">
|
||||
Action
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let element" class="d-flex">
|
||||
<a
|
||||
mat-icon-button
|
||||
[routerLink]="['/apps/invoice/editinvoice', element.id]"
|
||||
class="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<i-tabler
|
||||
name="pencil"
|
||||
class="icon-18 d-flex align-items-center"
|
||||
></i-tabler>
|
||||
</a>
|
||||
<a
|
||||
mat-icon-button
|
||||
[routerLink]="['/apps/invoice/viewInvoice', element.id]"
|
||||
class="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<i-tabler
|
||||
name="eye"
|
||||
class="icon-18 d-flex align-items-center"
|
||||
></i-tabler>
|
||||
</a>
|
||||
|
||||
<a
|
||||
mat-icon-button
|
||||
(click)="deleteInvoice(element.id)"
|
||||
class="d-flex align-items-center justify-content-center"
|
||||
>
|
||||
<i-tabler
|
||||
name="trash"
|
||||
class="icon-18 d-flex align-items-center"
|
||||
></i-tabler>
|
||||
</a>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
<mat-paginator
|
||||
[pageSizeOptions]="[5, 8, 10]"
|
||||
showFirstLastButtons
|
||||
></mat-paginator>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,125 @@
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
@if(invoiceDetail()){
|
||||
<span>
|
||||
<div class="row m-b-24">
|
||||
<div class="col-sm-4 d-flex align-items-center">
|
||||
<h4 class="f-s-14 f-s-18 f-w-600">#{{ invoiceDetail()?.id }}</h4>
|
||||
</div>
|
||||
<div class="col-sm-8 text-right">
|
||||
<a routerLink="/apps/invoice/list" mat-stroked-button class="m-r-10"
|
||||
>Back to Invoice</a
|
||||
>
|
||||
|
||||
<a
|
||||
[routerLink]="['/apps/invoice/editinvoice/', invoiceDetail()?.id]"
|
||||
mat-flat-button
|
||||
>Edit Invoice</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="row p-y-24">
|
||||
<div class="col-sm-6">
|
||||
<span class="f-w-600 f-s-15"> Order Status: </span>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.status }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<span class="f-w-600 f-s-15"> Order Date: </span>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.orderDate | date : "fullDate" }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
<mat-divider></mat-divider>
|
||||
<div class="row p-y-24">
|
||||
<div class="col-sm-6">
|
||||
<span class="f-w-600 f-s-15"> Bill From: </span>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billFrom }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billFromEmail }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billFromAddress }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billFromPhone }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<span class="f-w-600 f-s-15"> Bill To: </span>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billTo }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billToEmail }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billToAddress }}
|
||||
</h6>
|
||||
<h6 class="m-t-5 m-b-0 f-w-500 f-s-14">
|
||||
{{ invoiceDetail()?.billToPhone }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="b-1 table-responsive">
|
||||
<table
|
||||
mat-table
|
||||
[dataSource]="invoiceDetail()?.orders || []"
|
||||
class="no-wrap v-middle"
|
||||
>
|
||||
<ng-container matColumnDef="itemName">
|
||||
<th mat-header-cell *matHeaderCellDef class="f-s-15 f-w-600">
|
||||
Item Name
|
||||
</th>
|
||||
<td class="font-normal" mat-cell *matCellDef="let element">
|
||||
{{ element.itemName }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="unitPrice">
|
||||
<th mat-header-cell *matHeaderCellDef class="f-s-15 f-w-600">
|
||||
Unit Price
|
||||
</th>
|
||||
<td class="font-normal" mat-cell *matCellDef="let element">
|
||||
{{ element.unitPrice }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="unit">
|
||||
<th mat-header-cell *matHeaderCellDef class="f-s-15 f-w-600">
|
||||
Unit
|
||||
</th>
|
||||
<td class="font-normal" mat-cell *matCellDef="let element">
|
||||
{{ element.units }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<ng-container matColumnDef="total">
|
||||
<th mat-header-cell *matHeaderCellDef class="f-s-15 f-w-600">
|
||||
Total Cost
|
||||
</th>
|
||||
<td class="font-normal" mat-cell *matCellDef="let element">
|
||||
{{ element.unitTotalPrice }}
|
||||
</td>
|
||||
</ng-container>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="text-right m-t-30">
|
||||
<h5 class="m-b-5 f-w-600 f-s-16">
|
||||
Sub total: {{ invoiceDetail()?.totalCost }}
|
||||
</h5>
|
||||
<span class="f-w-600 f-s-16">Vat: 10%</span>
|
||||
<h3 class="m-b-0 b-t-1 p-t-20 f-s-18 m-t-24">
|
||||
Grand Total: {{ invoiceDetail()?.grandTotal }}
|
||||
</h3>
|
||||
</div>
|
||||
</span>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
@@ -0,0 +1,132 @@
|
||||
@if(action !== 'Delete') {
|
||||
<mat-dialog-content class="mat-typography">
|
||||
<div class="d-flex align-items-center justify-content-between m-b-16">
|
||||
<h3>{{action}} Ticket</h3>
|
||||
<button
|
||||
mat-icon-button
|
||||
mat-dialog-close
|
||||
class="d-flex justify-content-center"
|
||||
>
|
||||
<i-tabler name="x" class="icon-20 d-flex"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
<form #userForm="ngForm">
|
||||
<div class="row">
|
||||
@if(action === 'Update') {
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Ticket Id</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
required
|
||||
id="id"
|
||||
name="id"
|
||||
[(ngModel)]="local_data.id"
|
||||
placeholder="id"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Ticket Title</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
required
|
||||
id="title"
|
||||
name="title"
|
||||
[(ngModel)]="local_data.title"
|
||||
placeholder="Ticker Title"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block"
|
||||
>Ticket Subtext</mat-label
|
||||
>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<input
|
||||
type="text"
|
||||
matInput
|
||||
required
|
||||
id="subtext"
|
||||
name="subtext"
|
||||
[(ngModel)]="local_data.subtext"
|
||||
placeholder="Ticket Subtext"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Assign User</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-select
|
||||
placeholder="Assign User"
|
||||
[(ngModel)]="local_data.assignee"
|
||||
name="assignee"
|
||||
required
|
||||
>
|
||||
@for(user of users; track trackByUser(user)) {
|
||||
<mat-option [value]="user.name">
|
||||
<div class="d-flex align-items-center gap-8">
|
||||
<img
|
||||
[src]="user.photo"
|
||||
alt="{{ user.name }}"
|
||||
style="width: 24px; height: 24px; border-radius: 50%"
|
||||
/>
|
||||
{{ user.name }}
|
||||
</div>
|
||||
</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@if(action === 'Update'){
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Status</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<select
|
||||
matNativeControl
|
||||
required
|
||||
name="status"
|
||||
[(ngModel)]="local_data.status"
|
||||
>
|
||||
<option value="inprogress">In Progress</option>
|
||||
<option value="open">Open</option>
|
||||
<option value="closed">Closed</option>
|
||||
</select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
} @if(action === 'Update') {
|
||||
<div class="col-sm-6 col-lg-12">
|
||||
<mat-form-field>
|
||||
<mat-label>Date</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[matDatepicker]="picker1"
|
||||
[formControl]="dateControl"
|
||||
/>
|
||||
<mat-datepicker-toggle
|
||||
matIconSuffix
|
||||
[for]="picker1"
|
||||
></mat-datepicker-toggle>
|
||||
<mat-datepicker #picker1></mat-datepicker>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
</mat-dialog-content>
|
||||
} @else {
|
||||
<div class="p-x-24 p-b-24">
|
||||
Sure to delete <span class="f-w-600">{{local_data.title}}</span>?
|
||||
</div>
|
||||
}
|
||||
<div mat-dialog-actions class="p-24 p-t-0">
|
||||
<button mat-flat-button (click)="doAction()">{{action}}</button>
|
||||
<button mat-flat-button class="bg-error text-white" (click)="closeDialog()">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,177 @@
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
ViewChild,
|
||||
AfterViewInit,
|
||||
Inject,
|
||||
} from '@angular/core';
|
||||
import { MatTableDataSource, MatTable } from '@angular/material/table';
|
||||
import {
|
||||
MatDialog,
|
||||
MatDialogRef,
|
||||
MAT_DIALOG_DATA,
|
||||
} from '@angular/material/dialog';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TablerIconsModule } from 'angular-tabler-icons';
|
||||
import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { TicketService } from 'src/app/services/apps/ticket/ticket.service';
|
||||
import { TicketElement } from 'src/app/pages/apps/tickets/ticket';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
|
||||
@Component({
|
||||
selector: 'app-ticket-list',
|
||||
templateUrl: './tickets.component.html',
|
||||
imports: [MaterialModule, CommonModule, TablerIconsModule],
|
||||
})
|
||||
export class AppTicketlistComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild(MatTable, { static: true }) table: MatTable<any>;
|
||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||
|
||||
searchText: string = '';
|
||||
totalCount = 0;
|
||||
Closed = 0;
|
||||
Inprogress = 0;
|
||||
Open = 0;
|
||||
|
||||
displayedColumns: string[] = [
|
||||
'id',
|
||||
'title',
|
||||
'assignee',
|
||||
'status',
|
||||
'date',
|
||||
'action',
|
||||
];
|
||||
|
||||
dataSource = new MatTableDataSource<TicketElement>([]);
|
||||
|
||||
constructor(private ticketService: TicketService, public dialog: MatDialog) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadTickets(); // Load the initial tickets
|
||||
}
|
||||
|
||||
private loadTickets(): void {
|
||||
const tickets = this.ticketService.tickets$; // Get tickets from the service
|
||||
this.dataSource.data = tickets; // Set the dataSource to the tickets
|
||||
|
||||
// Update counts based on the current tickets
|
||||
this.updateCounts();
|
||||
}
|
||||
|
||||
private updateCounts(): void {
|
||||
this.totalCount = this.dataSource.data.length;
|
||||
this.Open = this.countTicketsByStatus('open');
|
||||
this.Closed = this.countTicketsByStatus('closed');
|
||||
this.Inprogress = this.countTicketsByStatus('inprogress');
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.dataSource.paginator = this.paginator;
|
||||
}
|
||||
|
||||
onKeyup(event: KeyboardEvent): void {
|
||||
const input = event.target as HTMLInputElement;
|
||||
this.applyFilter(input.value);
|
||||
}
|
||||
applyFilter(filterValue: string): void {
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
|
||||
btnCategoryClick(val: string): number {
|
||||
this.dataSource.filter = val.trim().toLowerCase();
|
||||
return this.dataSource.filteredData.length;
|
||||
}
|
||||
|
||||
openDialog(action: string, ticket: TicketElement | any): void {
|
||||
const dialogRef = this.dialog.open(TicketDialogComponent, {
|
||||
data: { action, ticket },
|
||||
autoFocus: false,
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe(() => {
|
||||
this.loadTickets();
|
||||
});
|
||||
}
|
||||
|
||||
countTicketsByStatus(status: string): number {
|
||||
return this.dataSource.data.filter(
|
||||
(ticket) => ticket.status.toLowerCase() === status.toLowerCase()
|
||||
).length;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
// tslint:disable-next-line - Disables all
|
||||
selector: 'app-dialog-content',
|
||||
templateUrl: 'ticket-dialog-content.html',
|
||||
imports: [
|
||||
MaterialModule,
|
||||
CommonModule,
|
||||
TablerIconsModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TablerIconsModule,
|
||||
],
|
||||
})
|
||||
export class TicketDialogComponent {
|
||||
action: string;
|
||||
local_data: TicketElement;
|
||||
users: any[] = [];
|
||||
dateControl = new FormControl();
|
||||
|
||||
constructor(
|
||||
public dialogRef: MatDialogRef<TicketDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: any,
|
||||
private ticketService: TicketService,
|
||||
private snackBar: MatSnackBar
|
||||
) {
|
||||
this.action = data.action;
|
||||
this.local_data = { ...data.ticket };
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.users = this.ticketService.getUsers(); // Get users from the service
|
||||
|
||||
if (this.local_data.date) {
|
||||
this.dateControl.setValue(
|
||||
new Date(this.local_data.date).toISOString().split('T')[0]
|
||||
); // existing date
|
||||
} else {
|
||||
// Set to today's date if no existing date is available
|
||||
this.dateControl.setValue(new Date().toISOString().split('T')[0]);
|
||||
}
|
||||
}
|
||||
|
||||
doAction(): void {
|
||||
this.local_data.date = this.dateControl.value; // Update local_data with the new date
|
||||
|
||||
if (this.action === 'Update') {
|
||||
this.ticketService.updateTicket(this.local_data);
|
||||
this.openSnackBar('Ticket updated successfully!', 'Close');
|
||||
} else if (this.action === 'Add') {
|
||||
this.ticketService.addTicket(this.local_data);
|
||||
this.openSnackBar('Ticket added successfully!', 'Close');
|
||||
} else if (this.action === 'Delete') {
|
||||
this.ticketService.deleteTicket(this.local_data.id);
|
||||
this.openSnackBar('Ticket deleted successfully!', 'Close');
|
||||
}
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
openSnackBar(message: string, action: string): void {
|
||||
this.snackBar.open(message, action, {
|
||||
duration: 3000,
|
||||
horizontalPosition: 'center',
|
||||
verticalPosition: 'top',
|
||||
});
|
||||
}
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
|
||||
trackByUser(user: any): any {
|
||||
return user.id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<div class="contact-page">
|
||||
<div class="banner-section bg-light-primary contact-herder spacing-top-bottom">
|
||||
<div class="container p-y-20">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-6">
|
||||
<h1 class="m-b-24 f-s-48 lh-normal section-sub-title">
|
||||
Get to know Modernize Dashboard Template
|
||||
</h1>
|
||||
<div class="hstack">
|
||||
<a mat-flat-button color="primary">Create an account</a>
|
||||
<a mat-stroked-button color="primary" class="border-primary">View Open
|
||||
Positions</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<p class="lh-base m-t-32">
|
||||
Do you need a highly customizable and developer friendly premium
|
||||
Angular admin template packed with numerous features? Modernize
|
||||
Angular Admin Template has everything you need. This bootstrap based
|
||||
admin template is designed in accordance with industry standards and
|
||||
best practices to provide you.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spacing-top-bottom setup-process">
|
||||
<div class="container">
|
||||
<h2 class="text-center section-sub-title m-b-48 f-s-40 lh-normal">
|
||||
The hassle-free setup process
|
||||
</h2>
|
||||
<div class="row">
|
||||
@for(topcard of setupCards; track topcard.title) {
|
||||
<div class="col-lg-3 col-sm-6 d-flex align-items-stretch">
|
||||
<mat-card class="shadow-none text-center w-100 bg-light-{{
|
||||
topcard.color
|
||||
}} rounded-8 ">
|
||||
<mat-card-content>
|
||||
<div class="m-t-16">
|
||||
@if(topcard.id!==2){
|
||||
<img [src]="topcard.img" alt="users" width="40" class="rounded-circle" />
|
||||
}
|
||||
|
||||
<h6 class="f-s-16 m-t-16">
|
||||
{{ topcard.title }}
|
||||
</h6>
|
||||
<p class="f-s-14 m-t-16 m-b-0">
|
||||
{{ topcard.subtitle }}
|
||||
</p>
|
||||
@if(topcard.id===2){
|
||||
<img [src]="topcard.imgMain" alt="image" class="img-fluid w-100 m-t-10 m-b--32" />
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="spacing-top-bottom key-metric">
|
||||
<div class="container">
|
||||
<div class="row justify-content-between">
|
||||
<div class="col-md-5">
|
||||
<div class="m-b-32">
|
||||
<h2 class="f-s-40 m-b-16 section-sub-title f-s-40 lh-normal">Key metric at a glance</h2>
|
||||
<p class="f-s-14 m-0 lh-base">
|
||||
From the year we were founded to the impressive customer base
|
||||
we've built, and the growth percentages that reflect our
|
||||
continuous improvement, these numbers tell our story at a glance.
|
||||
Explore the data that drives our mission and underscores our
|
||||
commitment to excellence.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="row stat-section">
|
||||
@for (stat of stats; track stat) {
|
||||
<div class="col-6 m-b-32">
|
||||
<div class="stat-block">
|
||||
<p class="stat-label f-s-12 f-w-400 text-uppercase text-primary m-y-0">
|
||||
{{ stat.label }}
|
||||
</p>
|
||||
<h2 class="stat-value f-s-48 lh-normal section-sub-title">
|
||||
{{ stat.value }}
|
||||
</h2>
|
||||
<p class="f-s-14 m-y-0">{{ stat.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="our-leadership spacing-top p-b-48">
|
||||
<app-image-slider></app-image-slider>
|
||||
</div>
|
||||
|
||||
<div class="features spacing-bottom">
|
||||
<div class="container">
|
||||
<div class="row align-items-center justify-content-between">
|
||||
<!--row-->
|
||||
<div class="col-md-5 m-b-30">
|
||||
<div class="client-margin">
|
||||
<h2 class="lh-normal f-s-40 m-b-16 section-sub-title">
|
||||
What our clients <br> think <img src="assets/images/front-pages/logoIcon.svg" alt="logo" />
|
||||
about us?
|
||||
</h2>
|
||||
<p class="m-0">
|
||||
Our users' feedback is a testament to our commitment to quality
|
||||
and user satisfaction. Read what they have to say about their
|
||||
journey with us.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<mat-card class="cardWithShadow b-1 rounded-8 m-b-0 p-48">
|
||||
<mat-card-content>
|
||||
<mat-card-title class="f-s-24 f-w-600 m-b-24">Features availability</mat-card-title>
|
||||
|
||||
<div class="d-flex align-items-center gap-16 m-b-24">
|
||||
<div>
|
||||
<img [src]="currentUser().img" [alt]="currentUser().name" class="rounded-circle" width="40" />
|
||||
</div>
|
||||
<h6 class="f-s-14 f-w-600">{{ currentUser().name }}</h6>
|
||||
</div>
|
||||
|
||||
<p class="f-s-14 m-b-16 m-t-0">
|
||||
Our users' feedback is a testament to our commitment to quality
|
||||
and user satisfaction. Read what they have to say about their
|
||||
journey with us.
|
||||
</p>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="d-flex align-items-center gap-10 m-t-8">
|
||||
<button class="bg-light icon-32 d-flex align-items-center justify-content-center" mat-icon-button
|
||||
(click)="goPrev()">
|
||||
<i-tabler name="chevron-left"
|
||||
class="icon-18 d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
|
||||
<span class="f-s-14">{{ displayCount() }}</span>
|
||||
|
||||
<button class="bg-light icon-32 d-flex align-items-center justify-content-center" mat-icon-button
|
||||
(click)="goNext()">
|
||||
<i-tabler name="chevron-right"
|
||||
class="icon-18 d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
.contact-page {
|
||||
|
||||
.setup-process {
|
||||
|
||||
mat-card-content {
|
||||
padding: 0px !important;
|
||||
padding: 30px 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.key-metric {
|
||||
box-shadow: 0px 6px 12px rgba(127, 145, 156, 0.12);
|
||||
}
|
||||
|
||||
.features {
|
||||
|
||||
.cardWithShadow {
|
||||
mat-card-content {
|
||||
padding: 0px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AboutUsComponent } from './about-us.component';
|
||||
|
||||
describe('AboutUsComponent', () => {
|
||||
let component: AboutUsComponent;
|
||||
let fixture: ComponentFixture<AboutUsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [AboutUsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(AboutUsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { ImageSliderComponent } from '../image-slider/image-slider.component';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
//import { PagePricingComponent } from '../page-pricing/page-pricing.component';
|
||||
import {
|
||||
setupCards,
|
||||
stats,
|
||||
users,
|
||||
} from '../front-pagesData';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-about-us',
|
||||
imports: [IconModule,MaterialModule ,CommonModule,ImageSliderComponent,FooterComponent,
|
||||
//PagePricingComponent
|
||||
],
|
||||
templateUrl: './about-us.component.html',
|
||||
styleUrl: './about-us.component.scss'
|
||||
})
|
||||
export class AboutUsComponent {
|
||||
setupCards=setupCards;
|
||||
stats = stats;
|
||||
currentIndex = signal(0); // Starting from 0
|
||||
users = users;
|
||||
// Computed values to auto-update template
|
||||
currentUser = computed(() => this.users[this.currentIndex()]);
|
||||
displayCount = computed(
|
||||
() => `${this.currentIndex() + 1}/${this.users.length}`
|
||||
);
|
||||
goPrev() {
|
||||
if (this.currentIndex() > 0) {
|
||||
this.currentIndex.update((i) => i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
goNext() {
|
||||
if (this.currentIndex() < this.users.length - 1) {
|
||||
this.currentIndex.update((i) => i + 1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
<div class="banner-section bg-light-primary spacing-top-bottom">
|
||||
<div class="container">
|
||||
<p class="text-primary text-center text-uppercase f-s-14 m-t-0">
|
||||
Blog Page
|
||||
</p>
|
||||
<h1 class="text-center f-s-48 section-sub-title lh-normal">Latest blog & news</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="blog-details-content spacing-top-bottom">
|
||||
<div class="container">
|
||||
<!-- ----------------------------------------------------------------- -->
|
||||
<!-- If Blog is available -->
|
||||
<!-- ----------------------------------------------------------------- -->
|
||||
@if(blogDetail()) {
|
||||
<mat-card class="cardWithShadow">
|
||||
<img mat-card-image src="{{ blogDetail()?.imgSrc }}" alt="Photo of a Shiba Inu" height="440" />
|
||||
<div class="detail-card-overlay h-100 d-flex align-items-end justify-content-end">
|
||||
<span class="f-s-12 m-y-16 f-w-600 bg-white rounded-pill p-x-8 m-r-16">2 mins Read</span>
|
||||
</div>
|
||||
<mat-card-content class="p-24 b-b-1">
|
||||
<div class="user-category">
|
||||
<div>
|
||||
<img src="{{ blogDetail()?.user }}" class="rounded-circle" width="40" />
|
||||
</div>
|
||||
<span class="f-s-12 m-y-16 f-w-600 rounded-pill p-x-8 p-y-4 d-inline-block text-dark bg-light">{{
|
||||
blogDetail()?.category }}</span>
|
||||
</div>
|
||||
|
||||
<mat-card-title class="f-s-36 lh-normal section-sub-title">{{
|
||||
blogDetail()?.title }}
|
||||
</mat-card-title>
|
||||
<div class="d-flex align-items-center justify-content-center m-t-24 justify-content-between">
|
||||
<div class="d-flex align-items-center gap-24">
|
||||
<span class="f-s-14 d-flex align-items-center gap-8"><i-tabler name="eye" class="icon-18"></i-tabler>{{
|
||||
blogDetail()?.views }}</span>
|
||||
<span class="f-s-14 d-flex align-items-center gap-8"><i-tabler name="message-2"
|
||||
class="icon-18"></i-tabler>4</span>
|
||||
</div>
|
||||
<span class="f-s-14 d-flex align-items-center">
|
||||
<i-tabler name="point" class="icon-18"></i-tabler>
|
||||
{{ blogDetail()?.date }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
<mat-card-content class="heading-section">
|
||||
<h2 class="f-s-28 lh-normal m-y-12 section-sub-title">Main Heading & Points</h2>
|
||||
<p class="f-s-14">
|
||||
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the
|
||||
industry's standard dummy text ever since
|
||||
the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
|
||||
has survived not only five centuries,
|
||||
but also the leap into electronic typesetting,
|
||||
remaining essentially unchanged. It was popularised in the
|
||||
</p>
|
||||
<ul>
|
||||
<li class="f-s-14">Vivamus eu lacus scelerisque, placerat commodo lectus.</li>
|
||||
<li class="f-s-14">Etiam et ante at ex porta fringilla.</li>
|
||||
<li class="f-s-14">Nullam dignissim sem eu magna aliquet, sit amet volutpat tellus</li>
|
||||
</ul>
|
||||
<p class="f-s-14">
|
||||
Unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not
|
||||
only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was
|
||||
popularised in the
|
||||
</p>
|
||||
<mat-divider></mat-divider>
|
||||
<p class="f-s-14">
|
||||
We are a dedicated team of passionate product managers, developers, UX/UI designers, QA engineers experts
|
||||
helping businesses from new startups
|
||||
</p>
|
||||
<mat-divider></mat-divider>
|
||||
<p class="f-s-14">
|
||||
There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in
|
||||
some form, by injected humour, or randomised words which don't look even slightly believable making this the
|
||||
first true generator on the Internet. It uses a dictionary
|
||||
</p>
|
||||
<mat-divider class="m-b-16"></mat-divider>
|
||||
<h2 class="f-s-21 lh-normal">Tags</h2>
|
||||
<ul>
|
||||
<li class="f-s-14">Trends</li>
|
||||
<li class="f-s-14">Design</li>
|
||||
<li class="f-s-14">Research</li>
|
||||
</ul>
|
||||
|
||||
<mat-divider class="m-b-16"></mat-divider>
|
||||
<h2 class="f-s-21 lh-normal">Share</h2>
|
||||
<ul class="text-primary">
|
||||
<li class="f-s-14"><a class="text-primary text-decoration-none" href="javascript:void(0)">Facebook</a></li>
|
||||
<li class="f-s-14"><a class="text-primary text-decoration-none" href="javascript:void(0)">Twitter</a></li>
|
||||
<li class="f-s-14"><a class="text-primary text-decoration-none" href="javascript:void(0)">Linkedin</a></li>
|
||||
</ul>
|
||||
|
||||
<mat-divider class="m-b-16"></mat-divider>
|
||||
<h2 class="f-s-21 lh-normal">Join our newsletter</h2>
|
||||
<p class="f-s-14">Email address : <a href="javascript:void(0)" class="f-s-14 text-primary text-decoration-none">Subscribe</a></p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
|
||||
<!-- ----------------------------------------------------------------- -->
|
||||
<!-- If Blog isn't available -->
|
||||
<!-- ----------------------------------------------------------------- -->
|
||||
|
||||
@if (!blogDetail() || blogDetail().length === 0) {
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
<p>No blog post available.</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BlogDetailsComponent } from './blog-details.component';
|
||||
|
||||
describe('BlogDetailsComponent', () => {
|
||||
let component: BlogDetailsComponent;
|
||||
let fixture: ComponentFixture<BlogDetailsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [BlogDetailsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BlogDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, inject, OnInit, signal } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
import { FrontEndService } from 'src/app/services/apps/front-pages/front-end.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-blog-details',
|
||||
imports: [IconModule, MaterialModule, CommonModule,
|
||||
FooterComponent
|
||||
],
|
||||
templateUrl: './blog-details.component.html',
|
||||
styleUrl: './blog-details.component.scss'
|
||||
})
|
||||
export class BlogDetailsComponent implements OnInit {
|
||||
blogDetail = signal<any>(null);
|
||||
private frontendService = inject(FrontEndService);
|
||||
ngOnInit(): void {
|
||||
const selected = this.frontendService.getBlog()();
|
||||
|
||||
if (selected) {
|
||||
this.blogDetail.set(selected);
|
||||
} else {
|
||||
// Fallback if accessed directly (e.g., from sidebar or refresh)
|
||||
const defaultBlog = {
|
||||
id: 1,
|
||||
time: "2 mins Read",
|
||||
imgSrc: "/assets/images/blog/blog-img1.jpg",
|
||||
user: "/assets/images/profile/user-1.jpg",
|
||||
title: "As yen tumbles, gadget-loving Japan goes for secondhand iPhones",
|
||||
views: "9,125",
|
||||
category: "Social",
|
||||
comments: 3,
|
||||
date: "Mon, Dec 23"
|
||||
};
|
||||
this.blogDetail.set(defaultBlog);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<div class="banner-section bg-light-primary spacing-top-bottom">
|
||||
<div class="container">
|
||||
<p class="text-primary text-center text-uppercase f-s-14 m-t-0">
|
||||
Blog Page
|
||||
</p>
|
||||
<h1 class="text-center f-s-48 section-sub-title lh-normal">Latest blog & news</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spacing-top-bottom">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@for(cardimg of cardimgs; track cardimg.imgSrc) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow card2 position-relative card-hover cursor-pointer" (click)="getNavigate(cardimg)">
|
||||
<img mat-card-image src="{{ cardimg.imgSrc }}" alt="Photo of a Shiba Inu" />
|
||||
<div class="card-overlay h-100 d-flex align-items-end justify-content-end">
|
||||
<mat-chip class="m-r-16 bg-white">{{
|
||||
cardimg.time
|
||||
}}</mat-chip>
|
||||
</div>
|
||||
|
||||
<mat-card-content class="p-y-24">
|
||||
<div class="user-category">
|
||||
<div>
|
||||
<img src="{{ cardimg.user }}" class="rounded-circle" width="40" />
|
||||
</div>
|
||||
<mat-chip class="m-y-16 bg-light">{{
|
||||
cardimg.category
|
||||
}}</mat-chip>
|
||||
</div>
|
||||
<mat-card-title>{{ cardimg.title }}</mat-card-title>
|
||||
<div class="d-flex align-items-center justify-content-center m-t-24">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="m-r-12 f-s-14 d-flex align-items-center"><i-tabler name="eye"
|
||||
class="icon-18 m-r-4"></i-tabler>{{ cardimg.views }}</span>
|
||||
<span class="f-s-14 d-flex align-items-center"><i-tabler name="message-2"
|
||||
class="icon-18 m-r-4"></i-tabler>{{ cardimg.comments }}</span>
|
||||
</div>
|
||||
<span class="m-l-auto f-s-14 d-flex align-items-center">
|
||||
<i-tabler name="point" class="icon-14 m-r-4 d-flex"></i-tabler>
|
||||
{{ cardimg.date }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
|
||||
.social-btns {
|
||||
margin-top: 20px;
|
||||
|
||||
.btn-icon {
|
||||
width: 25px !important;
|
||||
height: 25px !important;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
tabler-icon {
|
||||
width: 16px !important;
|
||||
height: 16px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-add-story {
|
||||
font-size: 0.75rem;
|
||||
padding: 0.35rem 0.75rem;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BlogComponent } from './blog.component';
|
||||
|
||||
describe('BlogComponent', () => {
|
||||
let component: BlogComponent;
|
||||
let fixture: ComponentFixture<BlogComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [BlogComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BlogComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Component, inject, OnInit } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { cardimgs } from '../front-pagesData';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
import { Router } from '@angular/router';
|
||||
import { FrontEndService } from 'src/app/services/apps/front-pages/front-end.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-blog',
|
||||
imports: [IconModule, MaterialModule, FooterComponent,],
|
||||
templateUrl: './blog.component.html',
|
||||
styleUrl: './blog.component.scss'
|
||||
})
|
||||
export class BlogComponent implements OnInit {
|
||||
|
||||
private router = inject(Router);
|
||||
private frontendService = inject(FrontEndService);
|
||||
cardimgs = cardimgs;
|
||||
|
||||
ngOnInit() {
|
||||
console.log(cardimgs, 'cardimgs');
|
||||
}
|
||||
|
||||
getNavigate(cardimg: any) {
|
||||
console.log('cardimg--->', cardimg);
|
||||
this.frontendService.setBlog(cardimg);
|
||||
this.router.navigate(['front-pages/blog-details'])
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<div class="contact-content">
|
||||
<!-- Light Blue Section -->
|
||||
<div class="banner-section bg-light-primary p-y-80">
|
||||
<div class="container m-b-80 p-b-80">
|
||||
<div class="container-content">
|
||||
<p class="text-primary text-center text-uppercase f-s-14 m-t-0"> Contact us</p>
|
||||
<h1 class="text-center f-s-48 section-sub-title lh-normal">We'd love to hear from you</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-content">
|
||||
<form>
|
||||
<div class="container">
|
||||
<!-- Map stays inside, but will visually float out -->
|
||||
<div class="map-container overflow-hidden rounded">
|
||||
<iframe class="overflow-hidden rounded"
|
||||
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d6335071.017601874!2d7.472741070779207!3d34.000243243063756!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x126c2c82aeb63e77%3A0xb5b3d1a2f1304c8e!2sTunisia!5e0!3m2!1sen!2stn!4v1715499362503!5m2!1sen!2stn"
|
||||
width="100%" height="400" style="border: 0" allowfullscreen="" loading="lazy"
|
||||
referrerpolicy="no-referrer-when-downgrade"></iframe>
|
||||
</div>
|
||||
<div class="spacing-top-bottom">
|
||||
<div class="row">
|
||||
<div class="col-md-8 m-b-30">
|
||||
<div class="row ">
|
||||
<div class="col-md-6">
|
||||
<!-- input -->
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">First Name<span>*</span></mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||
<input matInput type="text" placeholder="First Name" />
|
||||
</mat-form-field>
|
||||
<!-- input -->
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Phone Number<span>*</span></mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||
<input matInput type="tel" placeholder="xxx xxx xxxx" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<!-- input -->
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Last Name<span>*</span></mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||
<input matInput type="text" placeholder="Last Name" />
|
||||
</mat-form-field>
|
||||
<!-- input -->
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Email<span>*</span></mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||
<input matInput type="mail" placeholder="Email address" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Enquire related to<span>*</span>
|
||||
</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100">
|
||||
<mat-select value="General Enquiry">
|
||||
<mat-option value="General Enquiry">General Enquiry</mat-option>
|
||||
<mat-option value="General Enquiry 2">General Enquiry 2</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<mat-label class="f-s-14 f-w-600 m-b-8 d-block">Message</mat-label>
|
||||
<mat-form-field appearance="outline" class="w-100" color="primary">
|
||||
<textarea matInput rows="5" placeholder="Write your message here"></textarea>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
<button mat-flat-button>Submit</button>
|
||||
</div>
|
||||
<div class="col-md-4 right-side-content">
|
||||
<mat-card class="shadow-none bg-primary rounded-8 p-8">
|
||||
<mat-card-content>
|
||||
<div>
|
||||
<h6 class="f-s-20 m-b-16 text-white">Reach Out Today</h6>
|
||||
<p class="f-s-14 m-0 text-white">
|
||||
Have questions or need assistance? We're just a message
|
||||
away.
|
||||
</p>
|
||||
</div>
|
||||
<mat-divider class="m-y-30"></mat-divider>
|
||||
<div>
|
||||
<h6 class="f-s-20 m-b-16 text-white">Our Location</h6>
|
||||
<p class="f-s-14 m-0 text-white">
|
||||
Visit us in person or find our contact details to connect
|
||||
with us directly.
|
||||
</p>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
.map-container{
|
||||
margin-top: -200px;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ContactComponent } from './contact.component';
|
||||
|
||||
describe('ContactComponent', () => {
|
||||
let component: ContactComponent;
|
||||
let fixture: ComponentFixture<ContactComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ContactComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ContactComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contact',
|
||||
imports: [MaterialModule,IconModule,FooterComponent],
|
||||
templateUrl: './contact.component.html',
|
||||
styleUrl: './contact.component.scss'
|
||||
})
|
||||
export class ContactComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<div class="footer-content">
|
||||
<div class="custom-container footer-dashboard">
|
||||
<div class="bg-light-primary rounded-8 footer-container m-b-80 overflow-hidden">
|
||||
<div class="row">
|
||||
<div class="col-lg-6">
|
||||
<div class="spacing-top-bottom spacing-left left-side-content">
|
||||
<h2 class="f-s-40 m-b-24 lh-normal section-sub-title">
|
||||
Develop with feature-rich Angular Dashboard
|
||||
</h2>
|
||||
<div class="m-b-24 hstack">
|
||||
<a href="authentication/login" target="_blank" mat-flat-button color="primary" class="">Member Login</a>
|
||||
<a href="authentication/side-register" target="_blank" mat-stroked-button color="primary"
|
||||
class="border-primary">Register as Member</a>
|
||||
</div>
|
||||
|
||||
<span class="f-s-14 f-w-600"> One-time purchase</span> - no
|
||||
recurring fees.
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 d-none d-lg-block">
|
||||
<img src="assets/images/front-pages/design-collection.png" alt="bg-img" class="imgStyleDash" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer-wrapper">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-6 m-b-30">
|
||||
<div class="listContainer">
|
||||
<h5 class="f-s-16 f-w-600 m-b-30">Applications</h5>
|
||||
<mat-list role="list" class="p-y-0">
|
||||
@for (item of applicationsItems; track item) {
|
||||
<a class="text-decoration-none d-block m-b-20" [routerLink]="[item.href]">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
}
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-6 m-b-30">
|
||||
<div class="listContainer">
|
||||
<h5 class="f-s-16 f-w-600 m-b-30">Forms</h5>
|
||||
<mat-list role="list" class="p-y-0">
|
||||
@for (item of formsItems; track item) {
|
||||
<a class="text-decoration-none d-block m-b-20" [routerLink]="[item.href]">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
}
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-6 m-b-30">
|
||||
<div class="listContainer">
|
||||
<h5 class="f-s-16 f-w-600 m-b-30">Tables</h5>
|
||||
<mat-list role="list" class="p-y-0">
|
||||
@for (item of tablesItems; track item) {
|
||||
<a class="text-decoration-none d-block m-b-20" [routerLink]="[item.href]">
|
||||
{{ item.title }}
|
||||
</a>
|
||||
}
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 col-6 m-b-30">
|
||||
<h5 class="f-s-16 f-w-600 m-b-30">Follow us</h5>
|
||||
<div class="d-flex align-items-center gap-20">
|
||||
@for (icon of socialIcons; track icon.src) {
|
||||
<img [src]="icon.src" [matTooltip]="icon.tooltip" alt="social-icon" width="22" height="22"
|
||||
class="cursor-pointer" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between p-y-30 b-t-1 flex-wrap">
|
||||
<!-- Left side -->
|
||||
<div class="d-flex align-items-center gap-4">
|
||||
<img src="assets/images/landingpage/favicon.png" alt="logo" width="20" height="15" />
|
||||
<h6 class="f-s-16 f-w-500">All rights reserved by Modernize.</h6>
|
||||
</div>
|
||||
|
||||
<!-- Right side -->
|
||||
<div class="d-flex justify-content-end align-items-center">
|
||||
<p class="f-s-16 m-0">
|
||||
Designed & Developed by
|
||||
<a href="https://adminmart.com/" target="_blank" class="text-decoration-none text-primary">
|
||||
AdminMart </a>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
.footer-content{
|
||||
.custom-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.imgStyleDash {
|
||||
position: absolute;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FooterComponent } from './footer.component';
|
||||
|
||||
describe('FooterComponent', () => {
|
||||
let component: FooterComponent;
|
||||
let fixture: ComponentFixture<FooterComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [FooterComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(FooterComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { RouterLink } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-footer',
|
||||
imports: [MaterialModule, IconModule, RouterLink],
|
||||
templateUrl: './footer.component.html',
|
||||
styleUrl: './footer.component.scss'
|
||||
})
|
||||
export class FooterComponent {
|
||||
applicationsItems = [
|
||||
{
|
||||
title: 'Kanban',
|
||||
href: "/apps/kanban"
|
||||
},
|
||||
{
|
||||
title: 'Invoice List',
|
||||
href: "/apps/invoice/list"
|
||||
},
|
||||
{
|
||||
title: 'eCommerce',
|
||||
href: "/apps/product/shop"
|
||||
},
|
||||
{
|
||||
title: 'Chats',
|
||||
href: "/apps/chat"
|
||||
},
|
||||
{
|
||||
title: 'Tickets',
|
||||
href: "/apps/tickets"
|
||||
},
|
||||
{
|
||||
title: 'Blog',
|
||||
href: "/apps/blog/post"
|
||||
},
|
||||
];
|
||||
|
||||
formsItems = [
|
||||
{
|
||||
title: 'Form Layout',
|
||||
href: "/forms/form-layouts"
|
||||
},
|
||||
{
|
||||
title: 'Form Horizontal',
|
||||
href: "/forms/form-horizontal"
|
||||
},
|
||||
{
|
||||
title: 'Form Wizard',
|
||||
href: "/forms/form-wizard"
|
||||
},
|
||||
{
|
||||
title: 'Form Vertical',
|
||||
href: "/forms/form-vertical"
|
||||
},
|
||||
{
|
||||
title: 'Form Toastr',
|
||||
href: "/forms/form-toastr"
|
||||
},
|
||||
];
|
||||
|
||||
tablesItems = [
|
||||
{
|
||||
title: 'Basic Table',
|
||||
href: "/tables/basic-table"
|
||||
},
|
||||
{
|
||||
title: 'Multi Header Footer Table',
|
||||
href: "/tables/multi-header-footer-table"
|
||||
},
|
||||
{
|
||||
title: 'Pagination Table',
|
||||
href: "/tables/pagination-table"
|
||||
},
|
||||
{
|
||||
title: 'Dynamic Table',
|
||||
href: "/tables/dynamic-table"
|
||||
},
|
||||
{
|
||||
title: 'HTTP Table',
|
||||
href: "/tables/http-table"
|
||||
},
|
||||
{
|
||||
title: 'Sortable Table',
|
||||
href: "/tables/sortable-table"
|
||||
},
|
||||
];
|
||||
|
||||
socialIcons = [
|
||||
{ src: 'assets/images/front-pages/icon-facebook.svg', tooltip: 'Facebook' },
|
||||
{ src: 'assets/images/front-pages/icon-twitter.svg', tooltip: 'Twitter' },
|
||||
{ src: 'assets/images/front-pages/icon-instagram.svg', tooltip: 'Instagram' },
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { HomepageComponent } from './homepage/homepage.component';
|
||||
import { AboutUsComponent } from './about-us/about-us.component';
|
||||
import { HomepageDetailsComponent } from './homepage-details/homepage-details.component';
|
||||
import { BlogComponent } from './blog/blog.component';
|
||||
import { PortfolioComponent } from './portfolio/portfolio.component';
|
||||
import { PricingComponent } from './pricing/pricing.component';
|
||||
import { ContactComponent } from './contact/contact.component';
|
||||
import { BlogDetailsComponent } from './blog-details/blog-details.component';
|
||||
|
||||
|
||||
export const FrontPagesRoutes: Routes = [
|
||||
|
||||
{
|
||||
path: '',
|
||||
component: HomepageComponent, // acts as layout shell
|
||||
children: [
|
||||
{ path: '', redirectTo: 'homepage', pathMatch: 'full' },
|
||||
{ path: 'homepage', component: HomepageDetailsComponent }, // real homepage content
|
||||
{ path: 'about', component: AboutUsComponent },
|
||||
{path:'blog',component:BlogComponent },
|
||||
{ path: 'portfolio', component: PortfolioComponent },
|
||||
{ path: 'pricing', component: PricingComponent },
|
||||
{ path: 'contact', component: ContactComponent },
|
||||
{ path: 'blog-details', component: BlogDetailsComponent },
|
||||
],
|
||||
},
|
||||
];
|
||||
768
theme/packages/dark/src/app/pages/front-pages/front-pagesData.ts
Normal file
@@ -0,0 +1,768 @@
|
||||
interface cardimgs {
|
||||
id: number;
|
||||
time: string;
|
||||
imgSrc: string;
|
||||
user: string;
|
||||
title: string;
|
||||
views: string;
|
||||
category: string;
|
||||
comments: number;
|
||||
date: string;
|
||||
}
|
||||
|
||||
interface productcards {
|
||||
id: number;
|
||||
imgSrc: string;
|
||||
title: string;
|
||||
price: string;
|
||||
rprice: string;
|
||||
date: string;
|
||||
}
|
||||
|
||||
interface Framework {
|
||||
src: string;
|
||||
alt: string;
|
||||
tooltip: string;
|
||||
}
|
||||
|
||||
interface followercards {
|
||||
id: number;
|
||||
imgSrc: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface setupCards {
|
||||
id: number;
|
||||
img: string;
|
||||
color: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
imgMain?:string;
|
||||
}
|
||||
|
||||
export const cardimgs: cardimgs[] = [
|
||||
{
|
||||
id: 1,
|
||||
time: '2 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img1.jpg',
|
||||
user: '/assets/images/profile/user-1.jpg',
|
||||
title: 'As yen tumbles, gadget-loving Japan goes for secondhand iPhones',
|
||||
views: '9,125',
|
||||
category: 'Social',
|
||||
comments: 3,
|
||||
date: 'Mon, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
time: '3 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img2.jpg',
|
||||
user: '/assets/images/profile/user-2.jpg',
|
||||
title:
|
||||
'Intel loses bid to revive antitrust case against patent foe Fortress',
|
||||
views: '9,125',
|
||||
category: 'Gadget',
|
||||
comments: 3,
|
||||
date: 'Sun, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
time: '4 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img3.jpg',
|
||||
user: '/assets/images/profile/user-3.jpg',
|
||||
title: 'COVID outbreak deepens as more lockdowns loom in China',
|
||||
views: '9,125',
|
||||
category: 'Health',
|
||||
comments: 12,
|
||||
date: 'Sat, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
time: '2 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img4.jpg',
|
||||
user: '/assets/images/profile/user-1.jpg',
|
||||
title: 'As yen tumbles, gadget-loving Japan goes for secondhand iPhones',
|
||||
views: '9,125',
|
||||
category: 'Social',
|
||||
comments: 3,
|
||||
date: 'Mon, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
time: '3 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img5.jpg',
|
||||
user: '/assets/images/profile/user-2.jpg',
|
||||
title:
|
||||
'Intel loses bid to revive antitrust case against patent foe Fortress',
|
||||
views: '9,125',
|
||||
category: 'Gadget',
|
||||
comments: 3,
|
||||
date: 'Sun, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
time: '4 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img6.jpg',
|
||||
user: '/assets/images/profile/user-3.jpg',
|
||||
title: 'COVID outbreak deepens as more lockdowns loom in China',
|
||||
views: '9,125',
|
||||
category: 'Health',
|
||||
comments: 12,
|
||||
date: 'Sat, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
time: '2 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img10.jpg',
|
||||
user: '/assets/images/profile/user-1.jpg',
|
||||
title: 'As yen tumbles, gadget-loving Japan goes for secondhand iPhones',
|
||||
views: '9,125',
|
||||
category: 'Social',
|
||||
comments: 3,
|
||||
date: 'Mon, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
time: '3 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img8.jpg',
|
||||
user: '/assets/images/profile/user-2.jpg',
|
||||
title:
|
||||
'Intel loses bid to revive antitrust case against patent foe Fortress',
|
||||
views: '9,125',
|
||||
category: 'Gadget',
|
||||
comments: 3,
|
||||
date: 'Sun, Dec 23',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
time: '4 mins Read',
|
||||
imgSrc: '/assets/images/blog/blog-img9.jpg',
|
||||
user: '/assets/images/profile/user-3.jpg',
|
||||
title: 'COVID outbreak deepens as more lockdowns loom in China',
|
||||
views: '9,125',
|
||||
category: 'Health',
|
||||
comments: 12,
|
||||
date: 'Sat, Dec 23',
|
||||
},
|
||||
];
|
||||
|
||||
export const productcards: productcards[] = [
|
||||
{
|
||||
id: 1,
|
||||
imgSrc: 'assets/images/products/s4.jpg',
|
||||
title: 'Boat Headphone',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 03, 2025',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
imgSrc: 'assets/images/products/s5.jpg',
|
||||
title: 'MacBook Air Pro',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 10, 2025',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
imgSrc: 'assets/images/products/s7.jpg',
|
||||
title: 'Red Velvet Dress',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 15, 2025',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
imgSrc: 'assets/images/products/s11.jpg',
|
||||
title: 'Soft Plush Teddy',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 12, 2025',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
imgSrc: 'assets/images/products/s2.jpg',
|
||||
title: 'Boat Bass Booster',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 14, 2025',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
imgSrc: 'assets/images/products/s6.jpg',
|
||||
title: 'MacBook Ultra Slim',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 18, 2025',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
imgSrc: 'assets/images/products/s8.jpg',
|
||||
title: 'Crimson Party Dress',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 20, 2025',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
imgSrc: 'assets/images/products/s12.jpg',
|
||||
title: 'Cuddly Teddy Gift',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 22, 2025',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
imgSrc: 'assets/images/products/s4.jpg',
|
||||
title: 'Boat Sonic Headset',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 25, 2025',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
imgSrc: 'assets/images/products/s5.jpg',
|
||||
title: 'MacBook Pro 2025',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 27, 2025',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
imgSrc: 'assets/images/products/s7.jpg',
|
||||
title: 'Evening Gown - Red',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 29, 2025',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
imgSrc: 'assets/images/products/s11.jpg',
|
||||
title: 'Fluffy Bear Surprise',
|
||||
price: '285',
|
||||
rprice: '375',
|
||||
date: 'Tue, Apr 30, 2025',
|
||||
},
|
||||
];
|
||||
|
||||
export const frameworks: Framework[] = [
|
||||
{
|
||||
src: 'assets/images/landingpage/frameworks/angular.svg',
|
||||
alt: 'Angular',
|
||||
tooltip: 'Angular',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/landingpage/frameworks/material.svg',
|
||||
alt: 'Angular Material',
|
||||
tooltip: 'Angular Material',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/landingpage/frameworks/logo-ts.svg',
|
||||
alt: 'Typescript',
|
||||
tooltip: 'Typescript',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/landingpage/frameworks/icon-tabler.svg',
|
||||
alt: 'Tabler Icon',
|
||||
tooltip: 'Tabler Icon',
|
||||
},
|
||||
];
|
||||
|
||||
export const tiles = [
|
||||
{
|
||||
id: 1,
|
||||
text: 'Light & Dark Color Schemes',
|
||||
cols: 1,
|
||||
rows: 1,
|
||||
color: '#FFF6E5',
|
||||
icon: 'svgs/icon-briefcase.svg',
|
||||
subtitle: 'Choose your preferred visual style effortlessly.',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'New Demos',
|
||||
cols: 2,
|
||||
rows: 2,
|
||||
color: '#E9F1FF',
|
||||
icon: 'logos/logoIcon.svg',
|
||||
img: 'landingpage/background/screen1.png',
|
||||
subtitle:
|
||||
'Brand new demos to help you build the perfect dashboard:<br><strong>Dark and Right-to-Left.</strong>',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
text: 'Code Improvements',
|
||||
cols: 1,
|
||||
rows: 1,
|
||||
color: '#E7FFF2',
|
||||
icon: 'logos/icon-speech-bubble.svg',
|
||||
subtitle: 'Benefit from continuous improvements and optimizations.',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
text: '12+ Ready to Use Application Designs',
|
||||
cols: 1,
|
||||
rows: 1,
|
||||
color: '#E4F4FF',
|
||||
icon: 'icon-layer.svg',
|
||||
img: 'landingpage/background/feature-apps.png',
|
||||
subtitle: 'Instantly deployable designs for your applications.',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
text: '50+ UI Components',
|
||||
cols: 1,
|
||||
rows: 1,
|
||||
color: '#FFECEC',
|
||||
icon: 'logos/icon-favorites.svg',
|
||||
subtitle: 'A rich collection for seamless user experiences.',
|
||||
},
|
||||
];
|
||||
|
||||
export const users = [
|
||||
{ name: 'Jenny Wilson', img: '/assets/images/profile/user-1.jpg' },
|
||||
{ name: 'Robert Fox', img: '/assets/images/profile/user-2.jpg' },
|
||||
{ name: 'Kristin Watson', img: '/assets/images/profile/user-3.jpg' },
|
||||
{ name: 'Darlene Robertson', img: '/assets/images/profile/user-4.jpg' },
|
||||
{ name: 'Jacob Jones', img: '/assets/images/profile/user-5.jpg' },
|
||||
];
|
||||
|
||||
export const plans = [
|
||||
{
|
||||
title: 'Single Use',
|
||||
description:
|
||||
'Use for single end product which end users can’t be charged for.',
|
||||
price: 49,
|
||||
period: 'one time pay',
|
||||
features: [
|
||||
{ text: 'Full source code', included: true },
|
||||
{ text: 'Documentation', included: true },
|
||||
{ text: 'Use in SaaS app', included: false },
|
||||
{ text: 'One Project', included: true, bold: true },
|
||||
{ text: 'One Year Technical Support', included: true },
|
||||
{ text: 'One Year Free Updates', included: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Multiple Use',
|
||||
description:
|
||||
'Use for unlimited end products end users can’t be charged for.',
|
||||
price: 89,
|
||||
period: 'one time pay',
|
||||
features: [
|
||||
{ text: 'Full source code', included: true },
|
||||
{ text: 'Documentation', included: true },
|
||||
{ text: 'Use in SaaS app', included: false },
|
||||
{ text: 'Unlimited Project', included: true, bold: true },
|
||||
{ text: 'One Year Technical Support', included: true },
|
||||
{ text: 'One Year Free Updates', included: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Extended Use',
|
||||
description:
|
||||
'Use for single end product which end users can be charged for.',
|
||||
price: 299,
|
||||
period: 'one time pay',
|
||||
popular: true,
|
||||
features: [
|
||||
{ text: 'Full source code', included: true },
|
||||
{ text: 'Documentation', included: true },
|
||||
{ text: 'Use in SaaS app', included: true },
|
||||
{ text: 'One Project', included: true, bold: true },
|
||||
{ text: 'One Year Technical Support', included: true },
|
||||
{ text: 'One Year Free Updates', included: true },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Unlimited Use',
|
||||
description:
|
||||
'Use in unlimited end products end users can be charged for.',
|
||||
price: 499,
|
||||
period: 'one time pay',
|
||||
features: [
|
||||
{ text: 'Full source code', included: true },
|
||||
{ text: 'Documentation', included: true },
|
||||
{ text: 'Use in SaaS app', included: true },
|
||||
{ text: 'Unlimited Project', included: true, bold: true },
|
||||
{ text: 'One Year Technical Support', included: true },
|
||||
{ text: 'One Year Free Updates', included: true },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const paymentLogos = [
|
||||
{ src: 'assets/images/front-pages/icon-visa.svg', alt: 'visa', tooltip: 'Visa' },
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-mastercard.svg',
|
||||
alt: 'mastercard',
|
||||
tooltip: 'Master Card',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-american-express.svg',
|
||||
alt: 'american express',
|
||||
tooltip: 'American Express',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-discover.svg',
|
||||
alt: 'discover',
|
||||
tooltip: 'Discover',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-paypal.svg',
|
||||
alt: 'paypal',
|
||||
tooltip: 'Paypal',
|
||||
},
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-masetro.svg',
|
||||
alt: 'maestro',
|
||||
tooltip: 'Maestro',
|
||||
},
|
||||
{ src: 'assets/images/front-pages/icon-jcb.svg', alt: 'jcb', tooltip: 'JCB' },
|
||||
{
|
||||
src: 'assets/images/front-pages/icon-diners.svg',
|
||||
alt: 'diners',
|
||||
tooltip: 'Diners',
|
||||
},
|
||||
];
|
||||
|
||||
export const faqList = [
|
||||
{
|
||||
question: 'What is included with my purchase?',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
{
|
||||
question: 'Are there any recurring fees?',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
{
|
||||
question: 'Can i use template on multiple projects? ',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
{
|
||||
question:
|
||||
'Can i use customize the admin dashboard template to match my brand?',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
{
|
||||
question: 'Are any restrictions on using the template?',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
{
|
||||
question: 'How can i get support after purchase? ',
|
||||
answer:
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse malesuada lacus ex, sit amet blandit leo lobortis eget.',
|
||||
},
|
||||
];
|
||||
|
||||
export const followercardsFirst: followercards[] = [
|
||||
{
|
||||
id: 1,
|
||||
imgSrc: '/assets/images/front-pages/icon-color.svg',
|
||||
title: '6 Themes Colors',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
imgSrc: '/assets/images/front-pages/icon-sidebar.svg',
|
||||
title: 'Dard & Light Sidebar',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
imgSrc: '/assets/images/front-pages/icon-components.svg',
|
||||
title: '50+ UI Components',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
imgSrc: '/assets/images/front-pages/icon-pages.svg',
|
||||
title: '65+ pages Templates',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
imgSrc: '/assets/images/front-pages/icon-color.svg',
|
||||
title: '6 Themes Colors',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
imgSrc: '/assets/images/front-pages/icon-sidebar.svg',
|
||||
title: 'Dard & Light Sidebar',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
imgSrc: '/assets/images/front-pages/icon-components.svg',
|
||||
title: '50+ UI Components',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
imgSrc: '/assets/images/front-pages/icon-pages.svg',
|
||||
title: '65+ pages Templates',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
imgSrc: '/assets/images/front-pages/icon-color.svg',
|
||||
title: '6 Themes Colors',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
imgSrc: '/assets/images/front-pages/icon-sidebar.svg',
|
||||
title: 'Dard & Light Sidebar',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
imgSrc: '/assets/images/front-pages/icon-components.svg',
|
||||
title: '50+ UI Components',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
imgSrc: '/assets/images/front-pages/icon-pages.svg',
|
||||
title: '65+ pages Templates',
|
||||
},
|
||||
];
|
||||
|
||||
export const followercardSecond: followercards[] = [
|
||||
{
|
||||
id: 1,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Material UI',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
imgSrc: '/assets/images/front-pages/icon-icons.svg',
|
||||
title: '3400+ icons',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
imgSrc: '/assets/images/front-pages/icon-responsive.svg',
|
||||
title: 'Fully responsive',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
imgSrc: '/assets/images/front-pages/icon-sass.svg',
|
||||
title: 'Sassbase css',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Material UI',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
imgSrc: '/assets/images/front-pages/icon-icons.svg',
|
||||
title: '3400+ icons',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
imgSrc: '/assets/images/front-pages/icon-responsive.svg',
|
||||
title: 'Fully responsive',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
imgSrc: '/assets/images/front-pages/icon-sass.svg',
|
||||
title: 'Sassbase css',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Material UI',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
imgSrc: '/assets/images/front-pages/icon-icons.svg',
|
||||
title: '3400+ icons',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
imgSrc: '/assets/images/front-pages/icon-responsive.svg',
|
||||
title: 'Fully responsive',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
imgSrc: '/assets/images/front-pages/icon-sass.svg',
|
||||
title: 'Sassbase css',
|
||||
},
|
||||
];
|
||||
export const followercardThird: followercards[] = [
|
||||
{
|
||||
id: 1,
|
||||
imgSrc: '/assets/images/front-pages/icon-customize.svg',
|
||||
title: 'Easy to Customize',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
imgSrc: '/assets/images/front-pages/icon-chart.svg',
|
||||
title: 'Lots of Chart Options',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
imgSrc: '/assets/images/front-pages/icon-table.svg',
|
||||
title: 'Lots of Table Examples',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
imgSrc: '/assets/images/front-pages/icon-update.svg',
|
||||
title: 'Regular Updates',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
imgSrc: '/assets/images/front-pages/icon-support.svg',
|
||||
title: 'Dedicated Support',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Easy to Customize',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
imgSrc: '/assets/images/front-pages/icon-icons.svg',
|
||||
title: 'Lots of Chart Options',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
imgSrc: '/assets/images/front-pages/icon-responsive.svg',
|
||||
title: 'Lots of Table Examples',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
imgSrc: '/assets/images/front-pages/icon-sass.svg',
|
||||
title: 'Regular Updates',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Dedicated Support',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
imgSrc: '/assets/images/front-pages/icon-framework.svg',
|
||||
title: 'Easy to Customize',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
imgSrc: '/assets/images/front-pages/icon-icons.svg',
|
||||
title: 'Lots of Chart Options',
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export const topcardsGrid = [
|
||||
{ title: 'Light & Dark Color Schemes', subtitle: 'Choose your preferred visual style effortlessly.',
|
||||
img: '/assets/images/svgs/icon-briefcase.svg', color: 'warning' },
|
||||
{ title: '12+ Ready to Use Application Designs', subtitle: 'Instantly deployable designs for your applications.',
|
||||
img: 'assets/icons/icon2.png', color: 'secondary',imgMain: '/assets/images/landingpage/background/feature-apps.png', },
|
||||
{ title: 'New Demos', subtitle: 'Brand new demos to help you build the perfect dashboard: <strong>Dark and Right-to-Left.</strong>',
|
||||
img: '/assets/images/front-pages/logoIcon.svg', color: 'primary',imgMain: '/assets/images/landingpage/background/screen1.png' },
|
||||
{ title: 'Code Improvements', subtitle: 'Benefit from continuous improvements and optimizations.',
|
||||
img: '/assets/images/front-pages/icon-speech-bubble.svg', color: 'success' },
|
||||
{ title: '50+ UI Components', subtitle: 'A rich collection for seamless user experiences.',
|
||||
img: '/assets/images/front-pages/icon-favorites.svg', color: 'error' },
|
||||
];
|
||||
|
||||
export const setupCards:setupCards[] = [
|
||||
{
|
||||
id: 1,
|
||||
color: 'warning',
|
||||
img: '/assets/images/svgs/icon-briefcase.svg',
|
||||
title: 'Light & Dark Color Schemes',
|
||||
subtitle: 'Choose your preferred visual style effortlessly.',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
color: 'secondary',
|
||||
img: '/assets/images/svgs/icon-connect.svg',
|
||||
title: '12+ Ready to Use Application Designs',
|
||||
subtitle: 'Instantly deployable designs for your applications.',
|
||||
imgMain: '/assets/images/landingpage/background/feature-apps.png'
|
||||
},
|
||||
|
||||
{
|
||||
id: 3,
|
||||
color: 'success',
|
||||
img: '/assets/images/svgs/icon-speech-bubble.svg',
|
||||
title: 'Code Improvements',
|
||||
subtitle: 'Benefit from continuous improvements and optimizations.',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
color: 'error',
|
||||
img: '/assets/images/svgs/icon-favorites.svg',
|
||||
title: '50+ UI Components',
|
||||
subtitle: 'A rich collection for seamless user experiences.',
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export const stats = [
|
||||
{
|
||||
label: 'Founded',
|
||||
value: '2019',
|
||||
description: 'When we founded Modernize',
|
||||
},
|
||||
{
|
||||
label: 'Growth',
|
||||
value: '1,400%',
|
||||
description: 'Revenue growth in 2024',
|
||||
},
|
||||
{
|
||||
label: 'Customers',
|
||||
value: '300k+',
|
||||
description: 'Customers on Modernize',
|
||||
},
|
||||
{
|
||||
label: 'Dashboards',
|
||||
value: '25k+',
|
||||
description: 'Dashboards built using Modernize',
|
||||
},
|
||||
];
|
||||
|
||||
export const team = [
|
||||
{id: 1,
|
||||
name: 'Alex Martinez',
|
||||
position: 'CEO & Co-Founder',
|
||||
image: 'assets/images/front-pages/user1.jpg'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Jordan Nguyen',
|
||||
position: 'CTO & Co-Founder',
|
||||
image: 'assets/images/front-pages/user2.jpg'
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Taylor Roberts',
|
||||
position: 'Product Manager',
|
||||
image: 'assets/images/front-pages/user3.jpg'
|
||||
},
|
||||
{id: 4,
|
||||
name: 'Morgan Patel',
|
||||
position: 'Lead Developer',
|
||||
image: 'assets/images/front-pages/user4.jpg'
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Andrew Grant',
|
||||
position: 'Product Manager',
|
||||
image: 'assets/images/front-pages/user5.jpg'
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Leo Pratt',
|
||||
position: 'Lead Developer',
|
||||
image: 'assets/images/front-pages/user3.jpg'
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
name: 'C. A. Nunez',
|
||||
position: 'CEO & Co-Founder',
|
||||
image: 'assets/images/front-pages/user2.jpg'
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
name: 'Leo Maxwell',
|
||||
position: 'Lead Developer',
|
||||
image: 'assets/images/front-pages/user1.jpg'
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,603 @@
|
||||
<div class="home-page">
|
||||
<div class="bg-light-primary home-page-header">
|
||||
<div class="header-container-content custom-container m-x-auto">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h1 class="banner-title text-center m-t-48">
|
||||
Most powerful &
|
||||
<span class="text-primary">developer friendly </span>
|
||||
dashboard
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row align-items-end justify-content-center">
|
||||
@if(!isMobileView){
|
||||
|
||||
<div class="col-md-3 d-none d-lg-block cardPosition">
|
||||
<img src="assets/images/front-pages/banner-top-left.svg" alt="banner-top-left"
|
||||
class="img-fluid rounded-8 float-image w-100" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="col-md-6 m-b-10">
|
||||
<div class="row m-t-24">
|
||||
<div class="col-12 d-flex gap-20 align-items-center justify-content-center chipContainer">
|
||||
<div class="social-chips flex-shrink-0">
|
||||
<img src="assets/images/profile/user-2.jpg" width="40" alt="social" class="rounded-circle" />
|
||||
<img src="assets/images/profile/user-3.jpg" width="40" alt="social" class="rounded-circle" />
|
||||
<img src="assets/images/profile/user-4.jpg" width="40" alt="social" class="rounded-circle" />
|
||||
</div>
|
||||
<div class="f-s-16 f-w-500">
|
||||
52,589+ developers & agencies using our templates
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-center m-t-24 gap-20 loginBtn">
|
||||
<a mat-flat-button color="primary" [routerLink]="'/authentication/login'"><span
|
||||
class="p-y-10">Login</span></a>
|
||||
<div class="d-flex align-items-center" matRipple [matRippleCentered]="centered"
|
||||
[matRippleDisabled]="disabled" [matRippleUnbounded]="unbounded" [matRippleRadius]="radius"
|
||||
[matRippleColor]="color" [ngClass]="{
|
||||
'rounded bg-light-primary': showBackground,
|
||||
'p-y-2': true,
|
||||
'p-x-7': true
|
||||
}" (click)="openDialog(true)">
|
||||
<button mat-mini-fab class="text-primary play-button m-l-10"
|
||||
aria-label="Example icon button with a delete icon">
|
||||
<i-tabler class="icon-18 d-flex margin-auto" name="player-play"></i-tabler></button><span
|
||||
class="textSee f-s-14 f-w-500 m-x-10">
|
||||
See how it works</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-20 justify-content-center framework m-t-32">
|
||||
@for (framework of frameworks; track framework.tooltip) {
|
||||
<a href="javascript:void(0)"
|
||||
class="rounded-8 m-b-0 bg-white icon-54 d-flex align-items-center justify-content-center"
|
||||
matTooltip="{{ framework.tooltip }}" matTooltipPosition="below">
|
||||
<img [src]="framework.src" [alt]="framework.alt" class="" width="28" height="28" />
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@if(!isMobileView){
|
||||
<div class="col-md-3 d-none d-lg-block cardPositionTwo">
|
||||
<img src="assets/images/front-pages/banner-top-right.svg" alt="banner-top-right"
|
||||
class="img-fluid rounded-8 float-image w-100" />
|
||||
</div>
|
||||
|
||||
}
|
||||
</div>
|
||||
@if (!isMobileView) {
|
||||
<div class="row d-none d-lg-block m-t-30">
|
||||
<div class="col-12">
|
||||
<img src="assets/images/front-pages/bottom-part.svg" alt="bottom-part" class="w-100 img-fluid d-block" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="introducing-section dashboardCards spacing-top-bottom">
|
||||
<div class="container card-container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<p class="text-center m-t-0">
|
||||
Introducing Modernize's Light & Dark Skins, Exceptional Dashboards,
|
||||
and Dynamic Pages - Stay Updated on What's New!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!--new-->
|
||||
<!-- DESKTOP VIEW -->
|
||||
@if (!isMobileView) {
|
||||
<div class="row m-t-24">
|
||||
<!-- Column 1: Light & Dark + 12+ Designs -->
|
||||
<div class="col-md-4">
|
||||
<div>
|
||||
@for (topcard of topcards; track topcard.title) {
|
||||
@if (topcard.title === 'Light & Dark Color Schemes' || topcard.title.includes('12+')) {
|
||||
<mat-card class="shadow-none text-center rounded-12 bg-light-{{ topcard.color }} card-box p-x-30 p-y-44">
|
||||
<mat-card-content>
|
||||
@if (topcard.title === 'Light & Dark Color Schemes') {
|
||||
<img [src]="topcard.img" alt="icon" width="40" />
|
||||
}
|
||||
<h6 class="f-s-16 m-t-16">{{ topcard.title }}</h6>
|
||||
<p class="f-s-14 m-t-16">{{ topcard.subtitle }}</p>
|
||||
@if (topcard.title.includes('12+')) {
|
||||
<img [src]="topcard.imgMain" alt="image" class="img-fluid w-100 m-t-16 m-b--48" />
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div>
|
||||
@for (topcard of topcards; track topcard.title)
|
||||
{
|
||||
@if
|
||||
(topcard.title.includes('New Demos')) {
|
||||
<mat-card class="shadow-none text-center rounded-12 bg-light-{{
|
||||
topcard.color
|
||||
}} card-box tall-card p-x-30 p-y-48">
|
||||
<mat-card-content>
|
||||
<img [src]="topcard.img" alt="icon" width="40" class="" />
|
||||
<h2 class="f-s-40 m-t-48 lh-lg section-sub-title">{{ topcard.title }}</h2>
|
||||
<p class="f-s-14 m-t-20 m-b-0" [innerHTML]="topcard.subtitle"></p>
|
||||
<img src="assets/images/landingpage/background/screen1.png" alt="demo" class="img-fluid w-100 m-t-48" />
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
} }
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Column 2: Code Improvements + UI Components -->
|
||||
<div class="col-md-4">
|
||||
<div>
|
||||
@for (topcard of topcards; track topcard.title) {
|
||||
@if (topcard.title.includes('Code Improvements') || topcard.title.includes('UI Components')) {
|
||||
<mat-card class="shadow-none text-center rounded-12 bg-light-{{ topcard.color }} card-box p-x-30 p-y-48">
|
||||
<mat-card-content>
|
||||
<img [src]="topcard.img" alt="icon" width="40" />
|
||||
<h6 class="f-s-16 m-t-16">{{ topcard.title }}</h6>
|
||||
<p class="f-s-14 m-t-16">{{ topcard.subtitle }}</p>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- MOBILE VIEW -->
|
||||
@else {
|
||||
<div class="grid-container m-t-24 m-x-0">
|
||||
@for (topcard of topcards; track topcard.title) {
|
||||
@if (!topcard.title.includes('New Demos')) {
|
||||
<mat-card class="shadow-none text-center rounded-12 bg-light-{{ topcard.color }} card-box p-x-24 p-y-32">
|
||||
<mat-card-content>
|
||||
@if (!topcard.title.includes('12+')) {
|
||||
<img [src]="topcard.img" alt="icon" width="40" />
|
||||
}
|
||||
<h6 class="f-s-16 m-t-16">{{ topcard.title }}</h6>
|
||||
<p class="f-s-14 m-t-16">{{ topcard.subtitle }}</p>
|
||||
|
||||
@if (topcard.title.includes('12+')) {
|
||||
<img [src]="topcard.imgMain" alt="image" class="img-fluid w-100 m-t-16" />
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
<div>
|
||||
@for (topcard of topcards; track topcard.title)
|
||||
{
|
||||
@if
|
||||
(topcard.title.includes('New Demos')) {
|
||||
<mat-card class="shadow-none text-center rounded-12 bg-light-{{
|
||||
topcard.color
|
||||
}} card-box tall-card p-x-32 p-y-48">
|
||||
<mat-card-content>
|
||||
<img [src]="topcard.img" alt="icon" width="40" class="" />
|
||||
<h6 class="f-s-40 m-t-32 tall-card-title section-sub-title">{{ topcard.title }}</h6>
|
||||
<p class="f-s-14 m-t-20" [innerHTML]="topcard.subtitle"></p>
|
||||
<img src="assets/images/landingpage/background/screen1.png" alt="demo" class="img-fluid w-100 m-t-30" />
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
} }
|
||||
</div>
|
||||
}
|
||||
|
||||
<!--end-->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-header">
|
||||
<mat-divider></mat-divider>
|
||||
<div class="container">
|
||||
<mat-tab-group headerPosition="below" [(selectedIndex)]="selectedIndex" class="profileTabs">
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<tabler-icon name="user-circle" class="m-r-10 icon-24"></tabler-icon>
|
||||
<span class="tab-label f-s-18 f-w-500">Team Scheduling</span>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<tabler-icon name="wallet" class="m-r-10 icon-24"></tabler-icon>
|
||||
<span class="tab-label f-s-18 f-w-500">Payments</span>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<tabler-icon name="app-window" class="m-r-10 icon-24"></tabler-icon>
|
||||
<span class="tab-label f-s-18 f-w-500">Embedding</span>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
<mat-tab>
|
||||
<ng-template mat-tab-label>
|
||||
<tabler-icon name="arrow-fork" class="m-r-10 icon-24"></tabler-icon>
|
||||
<span class="tab-label f-s-18 f-w-500">Workflows</span>
|
||||
</ng-template>
|
||||
</mat-tab>
|
||||
</mat-tab-group>
|
||||
|
||||
<!-- Tab content shown BELOW the tab group -->
|
||||
|
||||
<div class="row tab-header-content p-y-66 align-items-center">
|
||||
<div class="col-md-6">
|
||||
<div class="tabsimage">
|
||||
<img src="assets/images/landingpage/background/accordian1.jpg" alt="slider-group" class="img-fluid w-100" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 m-t-30">
|
||||
<div class="right-content m-l-24">
|
||||
<h2 class="f-s-40 lh-lg section-sub-title">Defend your focus</h2>
|
||||
<div class="m-y-30">
|
||||
<mat-accordion multi>
|
||||
<!-- Panel 0 -->
|
||||
<mat-expansion-panel #panel0 [expanded]="selectedIndex === 0 || selectedIndex === 3" hideToggle
|
||||
class="expansion-panel">
|
||||
<mat-expansion-panel-header>
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<span class="f-s-18 f-w-500">Factor in outside colleagues</span>
|
||||
<tabler-icon [name]="panel0.expanded ? 'minus' : 'plus'" class="m-l-8 icon-20"></tabler-icon>
|
||||
</div>
|
||||
</mat-expansion-panel-header>
|
||||
<div>
|
||||
<p class="f-s-16 m-y-0">
|
||||
Factor in availability for required attendees, and skip
|
||||
checking for conflicts for optional attendees.
|
||||
</p>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<!-- Panel 1 -->
|
||||
<mat-expansion-panel #panel1 [expanded]="selectedIndex === 1" hideToggle class="expansion-panel">
|
||||
<mat-expansion-panel-header>
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<span class="f-s-18 f-w-500">Combine teammate schedules</span>
|
||||
<tabler-icon [name]="panel1.expanded ? 'minus' : 'plus'" class="icon-20"></tabler-icon>
|
||||
</div>
|
||||
</mat-expansion-panel-header>
|
||||
<div>
|
||||
<p class="f-s-16 m-y-0">
|
||||
Factor in availability for required attendees, and skip
|
||||
checking for conflicts for optional attendees.
|
||||
</p>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
|
||||
<!-- Panel 2 & 3 merged -->
|
||||
<mat-expansion-panel #panel2 [expanded]="selectedIndex === 2" hideToggle class="expansion-panel">
|
||||
<mat-expansion-panel-header>
|
||||
<div class="d-flex align-items-center justify-content-between w-100">
|
||||
<span class="f-s-18 f-w-500">Round robin pooling</span>
|
||||
<tabler-icon [name]="panel2.expanded ? 'minus' : 'plus'" class="m-l-8 icon-20"></tabler-icon>
|
||||
</div>
|
||||
</mat-expansion-panel-header>
|
||||
<div>
|
||||
<p class="f-s-16 m-y-0">
|
||||
Factor in availability for required attendees, and skip
|
||||
checking for conflicts for optional attendees.
|
||||
</p>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
</div>
|
||||
|
||||
<a mat-flat-button color="primary">Learn More</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="our-leadership spacing-top p-b-48">
|
||||
<app-image-slider></app-image-slider>
|
||||
</div>
|
||||
|
||||
<div class="toolBar bg-primary p-y-16">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-center justify-content-center">
|
||||
<div class="social-chips flex-shrink-0">
|
||||
<img src="assets/images/profile/user-2.jpg" width="44" height="44" alt="social"
|
||||
class="rounded-circle m-x-1" />
|
||||
<img src="assets/images/profile/user-3.jpg" width="44" height="44" alt="social"
|
||||
class="rounded-circle m-x-1" />
|
||||
</div>
|
||||
<span class="text-white f-s-16 m-l-16">
|
||||
Save valuable time and effort spent searching for a solution.
|
||||
<a class="text-white f-w-600 m-l-8" href="#">Contact us now</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="template-slider spacing-top-bottom">
|
||||
<div class="custom-container">
|
||||
<div class="bg-light-primary rounded-pill spacing-top-bottom template-slider-content">
|
||||
<div class="spacing-left-right m-b-8">
|
||||
<h2 class="f-s-40 lh-normal section-sub-title">
|
||||
Discover Powerful Dozens of <br> Purpose-Fit Templates
|
||||
</h2>
|
||||
</div>
|
||||
<div class="demo-slider overflow-hidden d-flex gap-30 spacing-bottom">
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<a [routerLink]="['/apps/chat']">
|
||||
<img src="assets/images/front-pages/app-chat.jpg" alt="slide" class="img-fluid rounded-7 sliderImg" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<a (click)="onImageClick('/apps/email/inbox')">
|
||||
<img src="assets/images/front-pages/app-email.jpg" alt="slide" class="img-fluid rounded-7 sliderImg"
|
||||
[ngClass]="{
|
||||
'img-border': selectedPath === '/apps/email/inbox'
|
||||
}" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<a (click)="onImageClick('/dashboards/dashboard1')">
|
||||
<img src="assets/images/front-pages/demo-main.jpg" alt="slide" class="img-fluid rounded-7 sliderImg"
|
||||
[ngClass]="{
|
||||
'img-border': selectedPath === '/dashboards/dashboard1'
|
||||
}" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<img src="assets/images/front-pages/demo-dark.jpg" alt="slide" class="img-fluid rounded-7 sliderImg" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<a (click)="onImageClick('/front-pages/homepage')">
|
||||
<img src="assets/images/front-pages/demo-horizontal.jpg" alt="slide"
|
||||
class="img-fluid rounded-7 sliderImg" [ngClass]="{
|
||||
'img-border': selectedPath === '/front-pages/homepage'
|
||||
}" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<img src="assets/images/front-pages/demo-rtl.jpg" alt="slide" class="img-fluid rounded-7 sliderImg" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<img src="assets/images/front-pages/app-chat.jpg" alt="slide" class="img-fluid rounded-7 sliderImg" />
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="demo-slide">
|
||||
<img src="assets/images/front-pages/app-email.jpg" alt="slide" class="img-fluid rounded-7 sliderImg" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacing-left-right">
|
||||
<div class="row">
|
||||
<div class="col-md-4 text-center m-b-30">
|
||||
<h3 class="f-s-18 m-b-16">High Customizability</h3>
|
||||
<p class="f-s-14 m-0">
|
||||
Tailor the dashboard to your exact needs. Customize layouts, color
|
||||
schemes, and widgets effortlessly for a personalized user
|
||||
experience.
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-md-4 text-center m-b-30">
|
||||
<h3 class="f-s-18 m-b-16">Powerful Data Analytics</h3>
|
||||
<p class="f-s-14 m-0">
|
||||
Unlock the true potential of your data with our advanced analytics
|
||||
tools. Gain valuable insights and make data-driven decisions with
|
||||
ease.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 text-center m-b-30">
|
||||
<h3 class="f-s-18 m-b-16">Interactive Charts</h3>
|
||||
<p class="f-s-14 m-0">
|
||||
Visualize complex data sets beautifully with our interactive
|
||||
graphs and charts. Quickly grasp trends and patterns for smarter
|
||||
analysis.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="features spacing-bottom">
|
||||
<div class="container">
|
||||
<div class="row align-items-center justify-content-between">
|
||||
<!--row-->
|
||||
<div class="col-md-5 m-b-30">
|
||||
<div class="client-margin">
|
||||
<h2 class="lh-normal f-s-40 m-b-16 section-sub-title">
|
||||
What our clients <br> think <img src="assets/images/front-pages/logoIcon.svg" alt="logo" />
|
||||
about us?
|
||||
</h2>
|
||||
<p class="m-0">
|
||||
Our users' feedback is a testament to our commitment to quality
|
||||
and user satisfaction. Read what they have to say about their
|
||||
journey with us.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<mat-card class="cardWithShadow b-1 rounded-8 m-b-0 p-48">
|
||||
<mat-card-content>
|
||||
<mat-card-title class="f-s-24 f-w-600 m-b-24">Features availability</mat-card-title>
|
||||
|
||||
<div class="d-flex align-items-center gap-16 m-b-24">
|
||||
<div>
|
||||
<img [src]="currentUser().img" [alt]="currentUser().name" class="rounded-circle" width="40" />
|
||||
</div>
|
||||
<h6 class="f-s-14 f-w-600">{{ currentUser().name }}</h6>
|
||||
</div>
|
||||
|
||||
<p class="f-s-14 m-b-16 m-t-0">
|
||||
Our users' feedback is a testament to our commitment to quality
|
||||
and user satisfaction. Read what they have to say about their
|
||||
journey with us.
|
||||
</p>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="d-flex align-items-center gap-10 m-t-8">
|
||||
<button class="bg-light icon-32 d-flex align-items-center justify-content-center" mat-icon-button
|
||||
(click)="goPrev()">
|
||||
<i-tabler name="chevron-left"
|
||||
class="icon-18 d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
|
||||
<span class="f-s-14">{{ displayCount() }}</span>
|
||||
|
||||
<button class="bg-light icon-32 d-flex align-items-center justify-content-center" mat-icon-button
|
||||
(click)="goNext()">
|
||||
<i-tabler name="chevron-right"
|
||||
class="icon-18 d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="exceptional position-relative">
|
||||
<div class="custom-container">
|
||||
<div class="bg-light-primary rounded-8 exceptional-content spacing-top-bottom">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<h2 class="lh-normal text-center f-s-40 m-b-30 section-sub-title">
|
||||
Enjoy unparalleled features & exceptional flexibility.
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="m-t-0">
|
||||
<div class="demo-slider overflow-hidden d-flex gap-30">
|
||||
<div class="row flex-nowrap overflow-auto gap-20">
|
||||
@for (followercard of followercardsfirst; track followercard.title)
|
||||
{
|
||||
<div class="col-2">
|
||||
<mat-card class="cardWithShadow demo-slide rounded-8">
|
||||
<mat-card-content>
|
||||
<div class="d-flex align-items-center justify-content-center x-20">
|
||||
<img [src]="followercard.imgSrc" alt="icon" />
|
||||
<h6 class="m-0 f-w-500 f-s-14 m-x-8">
|
||||
{{ followercard.title }}
|
||||
</h6>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-slider overflow-hidden d-flex gap-30 m-t-2">
|
||||
<div class="row flex-nowrap overflow-auto gap-20">
|
||||
@for (followercard of followercardsecond; track followercard.title)
|
||||
{
|
||||
<div class="col-2">
|
||||
<mat-card class="cardWithShadow demo-slide-two rounded-8">
|
||||
<mat-card-content>
|
||||
<div class="d-flex align-items-center justify-content-center x-20">
|
||||
<img [src]="followercard.imgSrc" alt="icon" />
|
||||
<h6 class="m-0 f-w-500 f-s-14 m-x-8">
|
||||
{{ followercard.title }}
|
||||
</h6>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="demo-slider overflow-hidden d-flex gap-30 m-t-2">
|
||||
<div class="row flex-nowrap overflow-auto gap-20">
|
||||
@for (followercard of followercardthird; track followercard.title) {
|
||||
<div class="col-2">
|
||||
<mat-card class="cardWithShadow demo-slide rounded-8">
|
||||
<mat-card-content>
|
||||
<div class="d-flex align-items-center justify-content-center x-20">
|
||||
<img [src]="followercard.imgSrc" alt="icon" />
|
||||
<h6 class="m-0 f-w-500 f-s-14 m-x-8">
|
||||
{{ followercard.title }}
|
||||
</h6>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="asked-questions spacing-top-bottom">
|
||||
<div class="container">
|
||||
<h2 class="f-s-40 text-center lh-normal m-b-48 section-sub-title">Frequently Asked Questions</h2>
|
||||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<mat-accordion multi class="faq-accordion m-b-48 d-block">
|
||||
@for (item of faqList; track item) {
|
||||
<mat-expansion-panel [expanded]="expandedIndex === $index" (opened)="expandedIndex = $index"
|
||||
(closed)="expandedIndex = null" hideToggle class="b-1 expansion-panel m-b-16">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title class="f-s-18 m-x-0">{{
|
||||
item.question
|
||||
}}</mat-panel-title>
|
||||
|
||||
<tabler-icon [name]="expandedIndex === $index ? 'minus' : 'plus'" class="m-s-auto icon-20 m-x-0 p-0">
|
||||
</tabler-icon>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<p class="m-0">{{ item.answer }}</p>
|
||||
</mat-expansion-panel>
|
||||
}
|
||||
</mat-accordion>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="d-flex align-items-center justify-content-center gap-4 p-y-6 p-x-10 rounded border-dash">
|
||||
<span class="f-s-14">Still have a question?</span>
|
||||
<a target="_blank" href="https://discord.com/invite/XujgB8ww4n"
|
||||
class="text-decoration-underline text-dark f-s-14">Ask on discord</a>
|
||||
<span class="f-s-14">or</span>
|
||||
<a target="_blank" href="https://adminmart.com/support/"
|
||||
class="text-decoration-underline text-dark f-s-14">Submit a ticket</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<div>
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,189 @@
|
||||
.home-page {
|
||||
.custom-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.home-page-header {
|
||||
|
||||
.header-container-content {
|
||||
|
||||
.cardPosition {
|
||||
.float-image {
|
||||
animation: floatUpDown 6s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.cardPositionTwo {
|
||||
|
||||
.float-image {
|
||||
animation: floatUpDown 6s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.loginBtn {
|
||||
.play-button {
|
||||
background-color: transparent;
|
||||
border: 2px solid var(--mat-sys-primary); // or use your theme color
|
||||
color: var(--mat-sys-primary);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.textSee {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--mat-sys-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dashboardCards {
|
||||
|
||||
.card-container {
|
||||
|
||||
mat-card-content {
|
||||
padding: 0px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
box-shadow: 0px 6px 12px rgba(127, 145, 156, 0.12);
|
||||
|
||||
.profileTabs {
|
||||
background-color: var(--mdc-elevated-card-container-color) !important;
|
||||
|
||||
.mat-mdc-tab.mdc-tab-indicator--active {
|
||||
.mdc-tab__text-label {
|
||||
color: var(--mat-sys-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.template-slider {
|
||||
.template-slider-content {
|
||||
.demo-slider {
|
||||
.demo-slide {
|
||||
animation: slide3d 15s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.features {
|
||||
|
||||
.cardWithShadow {
|
||||
mat-card-content {
|
||||
padding: 0px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.exceptional {
|
||||
.exceptional-content {
|
||||
.demo-slider {
|
||||
.demo-slide {
|
||||
animation: slide3d 20s linear infinite;
|
||||
}
|
||||
|
||||
.demo-slide-two {
|
||||
animation: slide3dTwo 20s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.expansion-panel {
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
border-radius: 0 !important;
|
||||
border-bottom: 1px solid var(--mat-sys-outline);
|
||||
|
||||
.mat-expansion-panel-header {
|
||||
padding: 18px 0 !important;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.sliderImg {
|
||||
max-width: 380px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.img-border {
|
||||
border: 2px solid var(--mat-sys-secondary);
|
||||
/* Blue border, change color as needed */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.img-border:hover {
|
||||
border-color: var(--mat-sys-secondary);
|
||||
}
|
||||
|
||||
.border-dash {
|
||||
border: 1px dashed var(--mat-sys-outline); // Initial border color (Bootstrap primary)
|
||||
transition: border-color 0.3s ease;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--mat-sys-primary); // Use your Angular Material primary variable or a custom color
|
||||
}
|
||||
}
|
||||
|
||||
.faq-accordion {
|
||||
.mat-expansion-panel {
|
||||
border-radius: 8px !important;
|
||||
|
||||
.mat-expansion-panel-header {
|
||||
padding: 20px 21px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes floatUpDown {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
50% {
|
||||
transform: translateY(-6px); // smaller bounce
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide3d {
|
||||
from {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(-2028px, 0, 0); // adjust based on actual slide width
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slide3dTwo {
|
||||
from {
|
||||
transform: translate3d(-2028px, 0, 0); // Rightward (starts left)
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@media (max-width: 1199px) {
|
||||
.home-page-header {
|
||||
padding-bottom: 48px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HomepageDetailsComponent } from './homepage-details.component';
|
||||
|
||||
describe('HomepageDetailsComponent', () => {
|
||||
let component: HomepageDetailsComponent;
|
||||
let fixture: ComponentFixture<HomepageDetailsComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [HomepageDetailsComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(HomepageDetailsComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,131 @@
|
||||
import { Component, computed, DestroyRef, inject, signal } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import {
|
||||
faqList,
|
||||
followercardsFirst,
|
||||
followercardSecond,
|
||||
followercardThird,
|
||||
frameworks,
|
||||
tiles,
|
||||
users,
|
||||
topcardsGrid,
|
||||
} from '../front-pagesData';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MediaMatcher } from '@angular/cdk/layout';
|
||||
import { ImageSliderComponent } from '../image-slider/image-slider.component';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { TemplateVideoComponent } from '../template-video/template-video.component';
|
||||
import { Router, RouterModule } from '@angular/router';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-homepage-details',
|
||||
imports: [
|
||||
MaterialModule,
|
||||
IconModule,
|
||||
CommonModule,
|
||||
ImageSliderComponent,
|
||||
FooterComponent,
|
||||
RouterModule
|
||||
],
|
||||
templateUrl: './homepage-details.component.html',
|
||||
styleUrl: './homepage-details.component.scss',
|
||||
})
|
||||
export class HomepageDetailsComponent {
|
||||
|
||||
topcards=topcardsGrid;
|
||||
|
||||
|
||||
centered = false;
|
||||
disabled = false;
|
||||
unbounded = false;
|
||||
radius: number;
|
||||
color: string;
|
||||
showBackground: boolean = false;
|
||||
frameworks = frameworks;
|
||||
selectedIndex = 1;
|
||||
|
||||
readonly dialog = inject(MatDialog);
|
||||
private router = inject(Router);
|
||||
private destroyRef = inject(DestroyRef); // ✅ For automatic cleanup
|
||||
private mediaMatcher = inject(MediaMatcher); // ✅ Proper MediaMatcher injection
|
||||
|
||||
mobileQuery: MediaQueryList;
|
||||
isMobileView = false;
|
||||
|
||||
readonly panelOpenState = signal(false);
|
||||
tiles = tiles;
|
||||
hideCloserBtn: boolean = true;
|
||||
users = users;
|
||||
expandedIndex: number | null = null;
|
||||
currentIndex = signal(0); // Starting from 0
|
||||
faqList = faqList;
|
||||
selectedPath: string | null = null;
|
||||
clicked = false;
|
||||
|
||||
followercardsfirst = followercardsFirst;
|
||||
followercardsecond = followercardSecond;
|
||||
followercardthird = followercardThird;
|
||||
|
||||
currentUser = computed(() => this.users[this.currentIndex()]);
|
||||
displayCount = computed(() => `${this.currentIndex() + 1}/${this.users.length}`);
|
||||
|
||||
constructor() {
|
||||
const isSmallScreen = this.mediaMatcher.matchMedia('(max-width: 599px)');
|
||||
// ✅ Setup media query for max-width: 1199px
|
||||
this.mobileQuery = this.mediaMatcher.matchMedia('(max-width: 1199px)');
|
||||
this.isMobileView = this.mobileQuery.matches;
|
||||
|
||||
const listener = (e: MediaQueryListEvent) => {
|
||||
this.isMobileView = e.matches;
|
||||
};
|
||||
|
||||
// ✅ Listen to viewport changes
|
||||
this.mobileQuery.addEventListener('change', listener);
|
||||
|
||||
// ✅ Clean up listener on component destroy
|
||||
this.destroyRef.onDestroy(() => {
|
||||
this.mobileQuery.removeEventListener('change', listener);
|
||||
});
|
||||
}
|
||||
isOver(): boolean {
|
||||
return this.mediaMatcher.matchMedia('(max-width: 1199px)').matches;
|
||||
}
|
||||
|
||||
goPrev() {
|
||||
if (this.currentIndex() > 0) {
|
||||
this.currentIndex.update((i) => i - 1);
|
||||
}
|
||||
}
|
||||
|
||||
goNext() {
|
||||
if (this.currentIndex() < this.users.length - 1) {
|
||||
this.currentIndex.update((i) => i + 1);
|
||||
}
|
||||
}
|
||||
openDialog(showBackground:boolean){
|
||||
this.showBackground = showBackground;
|
||||
|
||||
const dialogRef = this.dialog.open(TemplateVideoComponent, {
|
||||
data: {},
|
||||
width: '1000px',
|
||||
});
|
||||
|
||||
dialogRef.afterClosed().subscribe((result) => {
|
||||
if (result === false) {
|
||||
this.showBackground = false; // Reset or take any action
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
onImageClick(path: string) {
|
||||
this.selectedPath = path;
|
||||
|
||||
setTimeout(() => {
|
||||
this.router.navigate([path]);
|
||||
}, 100); // brief delay to show border
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
<div>
|
||||
<mat-sidenav-container>
|
||||
<mat-sidenav-content class="landing-page">
|
||||
@if(hideCloserBtn){
|
||||
|
||||
<mat-toolbar
|
||||
class="bg-primary d-flex justify-content-between align-items-center heightToolbar position-relative overflow-hidden">
|
||||
|
||||
<!-- Center text -->
|
||||
<div class="text-center text-white f-s-14 f-w-500 flex-grow-1">
|
||||
<span class="text-white bg-secondary m-x-12 f-s-12 p-x-8 p-y-4 rounded">New</span>
|
||||
Frontend Pages Included!
|
||||
</div>
|
||||
|
||||
<!-- Right close icon -->
|
||||
<button mat-icon-button aria-label="Close" class="text-white" (click)="hideCloser()">
|
||||
<mat-icon>close</mat-icon>
|
||||
</button>
|
||||
|
||||
</mat-toolbar>
|
||||
|
||||
}
|
||||
<mat-toolbar class="topbar front-topbar topbar-xl m-auto bg-light-primary p-y-8"
|
||||
[ngClass]="{ 'fixed-topbar': isTopbarFixed }">
|
||||
<div class="custom-container full-width">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div class="branding p-x-0">
|
||||
<app-branding></app-branding>
|
||||
</div>
|
||||
|
||||
@if(!isMobileView){
|
||||
<div class="d-none d-lg-flex justify-content-between toolBarContent">
|
||||
<button mat-button class="m-x-8 f-s-15 f-w-500 nav-item" [routerLink]="['/front-pages/about']"
|
||||
[class.selected]="isActiveRoute('about')">
|
||||
About Us
|
||||
</button>
|
||||
<button mat-button class="m-x-8 f-s-14 f-w-500 nav-item" [class.selected]="isActiveRoute('blog')"
|
||||
[routerLink]="['/front-pages/blog']">
|
||||
Blogs
|
||||
</button>
|
||||
<button mat-button class="m-x-8 f-s-15 f-w-500 nav-item" [routerLink]="['/front-pages/portfolio']"
|
||||
[class.selected]="isActiveRoute('portfolio')">
|
||||
Portfolio
|
||||
<span class="bg-light-primary text-primary rounded f-w-600 p-x-8 p-y-4 f-s-12 m-l-4">
|
||||
New
|
||||
</span>
|
||||
</button>
|
||||
<button mat-button class="m-x-8 f-s-15 f-w-500 nav-item" [class.selected]="isActiveRoute('dashboard')"
|
||||
[routerLink]="['/dashboards/dashboard1']">
|
||||
Dashboard
|
||||
</button>
|
||||
|
||||
<button mat-button class="m-x-8 f-s-15 f-w-500 nav-item" [class.selected]="isActiveRoute('pricing')"
|
||||
[routerLink]="['/front-pages/pricing']">
|
||||
Pricing
|
||||
</button>
|
||||
|
||||
<button mat-button class="m-x-8 f-s-15 f-w-500 nav-item" [class.selected]="isActiveRoute('contact')"
|
||||
[routerLink]="['/front-pages/contact']">
|
||||
Contact
|
||||
</button>
|
||||
</div>
|
||||
<a mat-flat-button color="primary" class="" [routerLink]="'/authentication/login'">Login</a>
|
||||
} @if(isMobileView){
|
||||
<button mat-mini-fab class="bg-light" aria-label="Example icon button with a delete icon"
|
||||
(click)="customizerRight.toggle()">
|
||||
<i-tabler class="icon-18 d-flex" name="menu"></i-tabler>
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</mat-toolbar>
|
||||
|
||||
<div class="content-scroll">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</mat-sidenav-content>
|
||||
|
||||
<mat-sidenav class="mobile-sidebar" #customizerRight mode="over" position="start">
|
||||
|
||||
<div class="">
|
||||
<div class="branding">
|
||||
<app-branding></app-branding>
|
||||
</div>
|
||||
<div class="">
|
||||
<mat-list role="list">
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark" [routerLink]="['/front-pages/about']"
|
||||
[class.selected]="isActiveRoute('about')">
|
||||
About Us
|
||||
</button></mat-list-item>
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark" [class.selected]="isActiveRoute('blogs')"
|
||||
[routerLink]="['/front-pages/blog']">
|
||||
Blogs
|
||||
</button></mat-list-item>
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark" [routerLink]="['/front-pages/portfolio']"
|
||||
[class.selected]="isActiveRoute('portfolio')">
|
||||
Portfolio
|
||||
<span class="bg-light-primary text-primary rounded f-w-600 p-6 p-y-4 f-s-12">
|
||||
New
|
||||
</span>
|
||||
</button></mat-list-item>
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark" [class.selected]="isActiveRoute('dashboard')"
|
||||
[routerLink]="['/dashboards/dashboard1']">
|
||||
Dashboard
|
||||
</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark" [class.selected]="isActiveRoute('pricing')"
|
||||
[routerLink]="['/front-pages/pricing']">
|
||||
Pricing
|
||||
</button>
|
||||
</mat-list-item>
|
||||
<mat-list-item role="listitem">
|
||||
<button mat-button class="text-dark " [class.selected]="isActiveRoute('contact')"
|
||||
[routerLink]="['/front-pages/contact']">
|
||||
Contact
|
||||
</button></mat-list-item>
|
||||
<mat-list-item role="listitem" class="w-100">
|
||||
<a mat-flat-button color="primary" class="w-100" [routerLink]="'/authentication/login'">Get
|
||||
Started</a></mat-list-item>
|
||||
</mat-list>
|
||||
</div>
|
||||
</div>
|
||||
</mat-sidenav>
|
||||
</mat-sidenav-container>
|
||||
@if(showBackToTop){
|
||||
<div
|
||||
class="back-to-top bg-primary rounded-circle d-flex align-items-center justify-content-center shadow icon-54 cursor-pointer"
|
||||
(click)="scrollToTop()">
|
||||
<i-tabler name="arrow-up" class="icon-24 text-white"></i-tabler>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@@ -0,0 +1,32 @@
|
||||
.landing-page {
|
||||
.custom-container {
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.heightToolbar {
|
||||
height: 46px;
|
||||
background-size: cover;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(../../../../assets/images/front-pages/topbar-bg.png);
|
||||
}
|
||||
|
||||
.toolBarContent {
|
||||
.nav-item {
|
||||
&.selected {
|
||||
background-color: var(--mat-sys-primary-fixed-dim);
|
||||
color: var(--mat-sys-primary); // optional for visibility
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: var(--mat-sys-primary);
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { MediaMatcher } from '@angular/cdk/layout';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, HostListener, inject, ViewChild } from '@angular/core';
|
||||
import { MatSidenav } from '@angular/material/sidenav';
|
||||
import { ActivatedRoute, Router, RouterLink, RouterOutlet } from '@angular/router';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { BrandingComponent } from 'src/app/layouts/full/vertical/sidebar/branding.component';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
|
||||
@Component({
|
||||
selector: 'app-homepage',
|
||||
imports: [MaterialModule, BrandingComponent, RouterLink,
|
||||
IconModule, RouterOutlet, CommonModule],
|
||||
templateUrl: './homepage.component.html',
|
||||
styleUrl: './homepage.component.scss'
|
||||
})
|
||||
export class HomepageComponent {
|
||||
@ViewChild('customizerRight') customizerRight!: MatSidenav;
|
||||
selected: string = ''; // default selected
|
||||
mobileQuery: MediaQueryList;
|
||||
isMobileView = false;
|
||||
hideCloserBtn: boolean = true;
|
||||
private router = inject(Router)
|
||||
private mediaMatcher: MediaQueryList = matchMedia(`(max-width: 1199px)`);
|
||||
showBackToTop: boolean;
|
||||
isTopbarFixed: boolean;
|
||||
constructor(private route: ActivatedRoute) {
|
||||
const media = inject(MediaMatcher);
|
||||
this.mobileQuery = media.matchMedia('(max-width: 1199px)');
|
||||
this.isMobileView = this.mobileQuery.matches;
|
||||
|
||||
this.mobileQuery.addEventListener('change', (e) => {
|
||||
|
||||
this.isMobileView = e.matches;
|
||||
this.closeSidenavIfNeeded();
|
||||
});
|
||||
}
|
||||
closeSidenavIfNeeded() {
|
||||
if (!this.isMobileView && this.customizerRight?.opened) {
|
||||
this.customizerRight.close();
|
||||
}
|
||||
}
|
||||
isOver(): boolean {
|
||||
return this.mediaMatcher.matches;
|
||||
}
|
||||
|
||||
isActiveRoute(route: string): boolean {
|
||||
return this.router.url.includes(`/front-pages/${route}`);
|
||||
}
|
||||
hideCloser() {
|
||||
this.hideCloserBtn = false;
|
||||
}
|
||||
getNavigate() {
|
||||
this.router.navigate(['/dashboards/dashboard1'])
|
||||
}
|
||||
|
||||
scrollToTop(): void {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
@HostListener('window:scroll', [])
|
||||
onWindowScroll() {
|
||||
this.showBackToTop = window.scrollY > 300;
|
||||
this.isTopbarFixed = scrollY > 45;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<div class="img-slider-content">
|
||||
<div class="container img-slider">
|
||||
<div class="">
|
||||
<div class="row m-b-48">
|
||||
<div class="col-md-5">
|
||||
<h2 class="f-s-40 lh-lg m-b-24 section-sub-title">Our leadership</h2>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<p class="m-0">
|
||||
Our robust analytics offer rich insights into the information
|
||||
buyers want, informing where teams
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-7 m-t-24 position-relative d-flex flex-column justify-content-end align-items-end">
|
||||
<div class="d-flex gap-16">
|
||||
<button mat-icon-button class="d-flex align-items-center justify-content-center icon-48 bg-light" aria-label="Previous" (click)="prev()">
|
||||
<i-tabler name="arrow-left" class="d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button class="d-flex align-items-center justify-content-center icon-48 bg-light" aria-label="Next" (click)="next()">
|
||||
<i-tabler name="arrow-right" class="d-flex align-items-center justify-content-center"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@for (member of visibleTeamMembers(); track member.id){
|
||||
<div class="col-sm-6 col-md-3">
|
||||
<mat-card class="cardWithShadow productcard overflow-hidden rounded-8 position-relative shadow-none">
|
||||
<a routerLink="/widgets/cards">
|
||||
<img [src]="member.image" alt="imgSrc" class="w-100 h-100 rounded-7" mat-card-image />
|
||||
</a>
|
||||
<mat-card class="position-absolute info-card text-center p-y-16 p-x-10">
|
||||
<h3 class="f-w-600 m-b-8">{{ member.name }}</h3>
|
||||
<p class="f-s-14 m-y-0">{{ member.position }}</p>
|
||||
</mat-card>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,22 @@
|
||||
.img-slider-content {
|
||||
.img-slider {
|
||||
|
||||
.mat-mdc-card {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
|
||||
.productcard {
|
||||
position: relative;
|
||||
|
||||
.info-card {
|
||||
bottom: 42px; // controls overlap depth
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 90%;
|
||||
box-shadow: 0px 6px 12px rgba(127, 145, 156, 0.12);
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { ImageSliderComponent } from './image-slider.component';
|
||||
|
||||
describe('ImageSliderComponent', () => {
|
||||
let component: ImageSliderComponent;
|
||||
let fixture: ComponentFixture<ImageSliderComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [ImageSliderComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(ImageSliderComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Component, computed, signal } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { team } from '../front-pagesData';
|
||||
|
||||
@Component({
|
||||
selector: 'app-image-slider',
|
||||
imports: [MaterialModule,IconModule],
|
||||
templateUrl: './image-slider.component.html',
|
||||
styleUrl: './image-slider.component.scss'
|
||||
})
|
||||
export class ImageSliderComponent {
|
||||
team = team;
|
||||
// Signals
|
||||
currentPage = signal(0);
|
||||
pageSize = 4;
|
||||
|
||||
visibleTeamMembers = computed(() => {
|
||||
const start = this.currentPage() * this.pageSize;
|
||||
const end = start + this.pageSize;
|
||||
return this.team.slice(start, end);
|
||||
});
|
||||
|
||||
next() {
|
||||
console.log('next--->',this.visibleTeamMembers().map(m => m.id));
|
||||
const totalPages = Math.ceil(this.team.length / this.pageSize);
|
||||
if (this.currentPage() < totalPages - 1) {
|
||||
this.currentPage.update((p) => p + 1);
|
||||
}
|
||||
}
|
||||
|
||||
prev() {
|
||||
console.log(this.visibleTeamMembers().map(m => m.id));
|
||||
if (this.currentPage() > 0) {
|
||||
this.currentPage.update((p) => p - 1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-7 col-sm-11">
|
||||
<h2 class="f-s-40 text-center m-b-48 lh-normal section-sub-title">
|
||||
111,476+ Trusted developers & many tech giants as well
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@for(plan of plans;track plan){
|
||||
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||
<mat-card class="cardWithShadow b-1">
|
||||
<mat-card-content>
|
||||
|
||||
<div class="m-b-16 d-flex align-items-center">
|
||||
<h6 class="f-s-20 f-w-600 ">
|
||||
{{ plan.title }}
|
||||
@if (plan.popular) {
|
||||
<span class="bg-light-primary text-primary rounded f-w-600 f-s-12 p-y-2 p-x-8">
|
||||
Popular
|
||||
</span>
|
||||
}
|
||||
</h6>
|
||||
</div>
|
||||
<p class="f-s-12 m-b-32 m-t-0">{{ plan.description }}</p>
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="price-line m-t-32">
|
||||
<span class="f-s-40 f-w-600">${{ plan.price }}</span>
|
||||
<span class="f-s-14">/{{ plan.period }}</span>
|
||||
</div>
|
||||
<div class="m-y-32">
|
||||
@for(feature of plan.features; track feature) {
|
||||
<div class="d-flex align-items-center gap-8 m-b-12">
|
||||
<img
|
||||
[src]="feature.included ? '/assets/images/front-pages/icon-circle-check.svg' : '/assets/images/front-pages/icon-circle-x.svg'"
|
||||
alt="icon-facebook-dark" width="21" height="21" />
|
||||
|
||||
<span [ngClass]="{
|
||||
'f-w-600': feature.bold,
|
||||
'f-s-14 op-5': !feature.included,
|
||||
'f-s-14': feature.included
|
||||
}">
|
||||
{{ feature.text }}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button mat-flat-button color="primary" class="w-100 ">
|
||||
Purchase Now
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
</div>
|
||||
<div class="m-t-32">
|
||||
<p class="text-center f-s-14 m-b-0">Secured payment with PayPal & Razorpay</p>
|
||||
<div class="d-flex align-items-center justify-content-center m-t-32 m-x-0 gap-48 flex-wrap">
|
||||
@for( logo of paymentLogos;track logo){
|
||||
<img class="cursor-pointer" [src]="logo.src" [alt]="logo.alt" [matTooltip]="logo.tooltip"
|
||||
matTooltipPosition="below">
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PagePricingComponent } from './page-pricing.component';
|
||||
|
||||
describe('PagePricingComponent', () => {
|
||||
let component: PagePricingComponent;
|
||||
let fixture: ComponentFixture<PagePricingComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PagePricingComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PagePricingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { paymentLogos, plans } from '../front-pagesData';
|
||||
|
||||
@Component({
|
||||
selector: 'app-page-pricing',
|
||||
imports: [MaterialModule, IconModule, CommonModule],
|
||||
templateUrl: './page-pricing.component.html',
|
||||
styleUrl: './page-pricing.component.scss',
|
||||
})
|
||||
export class PagePricingComponent {
|
||||
plans = plans;
|
||||
|
||||
paymentLogos = paymentLogos;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<div class="banner-section bg-light-primary spacing-top-bottom">
|
||||
<div class="container">
|
||||
<p class="text-primary text-center text-uppercase f-s-14 m-t-0">
|
||||
Portfolio
|
||||
</p>
|
||||
<h1 class="text-center f-s-48 section-sub-title lh-normal">Explore Our Latest Works</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="spacing-top-bottom">
|
||||
<div class="container">
|
||||
<div class="d-flex align-items-center justify-content-between gap-3 flex-wrap m-b-24">
|
||||
<div class="d-flex align-items-center gap-8 m-b-10">
|
||||
<h5 class="f-w-500 f-s-20">Portfolio</h5>
|
||||
<div class="p-x-6 p-y-2 rounded-pill bg-secondary text-white">
|
||||
<div class="f-s-14 lh-sm">{{ filteredCount }} </div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search bar pushed to the right -->
|
||||
<mat-form-field appearance="outline" class="search-bar-style hide-hint">
|
||||
<mat-icon matPrefix>search</mat-icon>
|
||||
<input matInput placeholder="Search Photos" [(ngModel)]="searchText" (input)="onSearchChange()" />
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="row">
|
||||
@for(productcard of filteredCardImgs; track productcard.id) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow productcard overflow-hidden b-1 rounded">
|
||||
<a routerLink="/widgets/cards">
|
||||
<img src="{{ productcard.imgSrc }}" alt="imgSrc" class="w-100 object-cover" height="220" mat-card-image />
|
||||
</a>
|
||||
<mat-card-content class="p-b-24 p-t-12 position-relative">
|
||||
<mat-card-title class="mat-headline-2 f-s-16 m-b-4">
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<!-- Left Side: Text Content -->
|
||||
<div>
|
||||
<h6 class="f-s-16 lh-sm f-w-600">{{ productcard.title }}</h6>
|
||||
<p class="f-s-12 f-w-400 m-y-0">{{ productcard.date }}</p>
|
||||
</div>
|
||||
|
||||
<!-- Right Side: Icon -->
|
||||
<button mat-icon-button aria-label="Example icon button with a vertical three dot icon">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-title>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PortfolioComponent } from './portfolio.component';
|
||||
|
||||
describe('PortfolioComponent', () => {
|
||||
let component: PortfolioComponent;
|
||||
let fixture: ComponentFixture<PortfolioComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PortfolioComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PortfolioComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,37 @@
|
||||
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { productcards } from '../front-pagesData';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-portfolio',
|
||||
imports: [MaterialModule, IconModule, FooterComponent, CommonModule, FormsModule],
|
||||
templateUrl: './portfolio.component.html',
|
||||
styleUrl: './portfolio.component.scss'
|
||||
})
|
||||
export class PortfolioComponent implements OnInit {
|
||||
|
||||
filteredCards = productcards;
|
||||
|
||||
searchText: string = '';
|
||||
|
||||
filteredCardImgs = [...this.filteredCards]; // Initialize with full data
|
||||
filteredCount: number = this.filteredCardImgs.length;
|
||||
ngOnInit(): void {
|
||||
console.log('filteredCards', this.filteredCards)
|
||||
}
|
||||
onSearchChange() {
|
||||
const query = this.searchText.toLowerCase().trim();
|
||||
this.filteredCardImgs = this.filteredCards.filter(item =>
|
||||
item.title.toLowerCase().includes(query) ||
|
||||
item.date.toLowerCase().includes(query)
|
||||
);
|
||||
this.filteredCount = this.filteredCardImgs.length; // ✅ update the count here
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<div class="banner-section bg-light-primary spacing-top-bottom">
|
||||
<div class="container">
|
||||
<p class="text-primary text-center text-uppercase f-s-14 m-t-0">
|
||||
Pricing Page
|
||||
</p>
|
||||
<h1 class="text-center f-s-48 section-sub-title lh-normal">Choose Your Plan</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="page-pricing spacing-top-bottom">
|
||||
<div class="container">
|
||||
<app-page-pricing></app-page-pricing>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
<app-footer></app-footer>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PricingComponent } from './pricing.component';
|
||||
|
||||
describe('PricingComponent', () => {
|
||||
let component: PricingComponent;
|
||||
let fixture: ComponentFixture<PricingComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [PricingComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(PricingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { FooterComponent } from '../footer/footer.component';
|
||||
import { PagePricingComponent } from '../page-pricing/page-pricing.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-pricing',
|
||||
imports: [MaterialModule,IconModule,FooterComponent,PagePricingComponent],
|
||||
templateUrl: './pricing.component.html',
|
||||
styleUrl: './pricing.component.scss'
|
||||
})
|
||||
export class PricingComponent {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<mat-dialog-content class="p-b-0">
|
||||
<iframe width="100%" height="500" src="https://www.youtube.com/embed/n-J3dDy1kro?si=k441rPIuc1bmKXJ9" frameborder="0"
|
||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen
|
||||
class="rounded-8"></iframe>
|
||||
</mat-dialog-content>
|
||||
<div mat-dialog-actions>
|
||||
<!-- <button mat-flat-button> Close</button> -->
|
||||
<button mat-flat-button class="bg-light text-primary" (click)="closeDialog()">
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
@@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { TemplateVideoComponent } from './template-video.component';
|
||||
|
||||
describe('TemplateVideoComponent', () => {
|
||||
let component: TemplateVideoComponent;
|
||||
let fixture: ComponentFixture<TemplateVideoComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [TemplateVideoComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(TemplateVideoComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IconModule } from 'src/app/icon/icon.module';
|
||||
import { MaterialModule } from 'src/app/material.module';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
@Component({
|
||||
selector: 'app-template-video',
|
||||
imports: [MaterialModule,
|
||||
IconModule,],
|
||||
templateUrl: './template-video.component.html',
|
||||
styleUrl: './template-video.component.scss'
|
||||
})
|
||||
export class TemplateVideoComponent {
|
||||
constructor(private dialogRef: MatDialogRef<TemplateVideoComponent>){
|
||||
|
||||
}
|
||||
closeDialog(): void {
|
||||
this.dialogRef.close(false); // Pass false back to parent
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
export const BASIC_SLIDE_TOGGLE_TS_SNIPPET = ` import {Component} from '@angular/core';
|
||||
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
|
||||
|
||||
/**
|
||||
* @title slide-toggle
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-slide-toggle',
|
||||
imports: [MatSlideToggleModule],
|
||||
templateUrl: './slide-toggle.component.html'
|
||||
})
|
||||
export class AppSlideToggleComponent {
|
||||
constructor() {}
|
||||
}
|
||||
`;
|
||||
|
||||
export const FORM_SLIDE_TOGGLE_TS_SNIPPET = ` import {Component, inject} from '@angular/core';
|
||||
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
|
||||
import {FormBuilder, FormGroup, Validators, FormsModule, ReactiveFormsModule} from '@angular/forms';
|
||||
import {MatButtonModule} from '@angular/material/button';
|
||||
import { MatSlideToggleModule} from '@angular/material/slide-toggle';
|
||||
|
||||
/**
|
||||
* @title Slide-toggle with forms
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-slide-toggle',
|
||||
imports: [MatSlideToggleModule, FormsModule, MatButtonModule, ReactiveFormsModule,],
|
||||
templateUrl: './slide-toggle.component.html'
|
||||
})
|
||||
export class AppSlideToggleComponent {
|
||||
constructor() {}
|
||||
|
||||
private _formBuilder = inject(FormBuilder);
|
||||
|
||||
isChecked = true;
|
||||
formGroup = this._formBuilder.group({
|
||||
enableWifi: '',
|
||||
acceptTerms: ['', Validators.requiredTrue],
|
||||
});
|
||||
|
||||
alertFormValues(formGroup: FormGroup) {
|
||||
alert(JSON.stringify(formGroup.value, null, 2));
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CONFIGURATION_SLIDE_TOGGLE_TS_SNIPPET = ` import {Component} from '@angular/core';
|
||||
import {MatSlideToggleModule} from '@angular/material/slide-toggle';
|
||||
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import {MatCardModule} from '@angular/material/card';
|
||||
|
||||
/**
|
||||
* @title Configurable slide-toggle
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-slide-toggle',
|
||||
imports: [MatCardModule, MatRadioModule, FormsModule, MatCheckboxModule, MatSlideToggleModule],
|
||||
templateUrl: './slide-toggle.component.html'
|
||||
})
|
||||
export class AppSlideToggleComponent {
|
||||
constructor() {}
|
||||
|
||||
checked = false;
|
||||
disabled = false;
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Component, OnInit, inject } from '@angular/core';
|
||||
import {FormBuilder, FormGroup, Validators, ReactiveFormsModule} from '@angular/forms';
|
||||
import {
|
||||
MatSlideToggleModule,
|
||||
// _MatSlideToggleRequiredValidatorModule,
|
||||
} from '@angular/material/slide-toggle';
|
||||
import {MatCheckboxModule} from '@angular/material/checkbox';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {MatRadioModule} from '@angular/material/radio';
|
||||
import {MatCardModule} from '@angular/material/card';
|
||||
import {MatButtonModule} from '@angular/material/button';
|
||||
import { AppCodeViewComponent } from 'src/app/components/code-view/code-view.component';
|
||||
|
||||
// snippets
|
||||
import { BASIC_SLIDE_TOGGLE_HTML_SNIPPET, CONFIGURATION_SLIDE_TOGGLE_HTML_SNIPPET, FORM_SLIDE_TOGGLE_HTML_SNIPPET } from './code/slide-toggle-html-snippet';
|
||||
import { BASIC_SLIDE_TOGGLE_TS_SNIPPET, CONFIGURATION_SLIDE_TOGGLE_TS_SNIPPET, FORM_SLIDE_TOGGLE_TS_SNIPPET } from './code/slide-toggle-ts-snippet';
|
||||
|
||||
import { Highlight, HighlightAuto } from 'ngx-highlightjs';
|
||||
import { HighlightLineNumbers } from 'ngx-highlightjs/line-numbers';
|
||||
|
||||
@Component({
|
||||
selector: 'app-slide-toggle',
|
||||
imports: [MatCardModule, MatRadioModule, FormsModule, MatCheckboxModule, MatSlideToggleModule, ReactiveFormsModule, MatButtonModule,
|
||||
// _MatSlideToggleRequiredValidatorModule
|
||||
Highlight,
|
||||
HighlightAuto,
|
||||
HighlightLineNumbers,
|
||||
AppCodeViewComponent,
|
||||
],
|
||||
templateUrl: './slide-toggle.component.html'
|
||||
})
|
||||
export class AppSlideToggleComponent implements OnInit {
|
||||
|
||||
// 1 [Basic with Slide Toggle]
|
||||
codeForSlideToggleBasic = BASIC_SLIDE_TOGGLE_HTML_SNIPPET;
|
||||
codeForSlideToggleBasicTs = BASIC_SLIDE_TOGGLE_TS_SNIPPET;
|
||||
|
||||
// 2 [Form with Slide Toggle]
|
||||
codeForSlideToggleForm = FORM_SLIDE_TOGGLE_HTML_SNIPPET;
|
||||
codeForSlideToggleFormTs = FORM_SLIDE_TOGGLE_TS_SNIPPET;
|
||||
|
||||
// 3 [Configuration with Slide Toggle]
|
||||
codeForSlideToggleConfiguration = CONFIGURATION_SLIDE_TOGGLE_HTML_SNIPPET;
|
||||
codeForSlideToggleConfigurationTs = CONFIGURATION_SLIDE_TOGGLE_TS_SNIPPET;
|
||||
|
||||
// configuration
|
||||
checked = false;
|
||||
disabled = false;
|
||||
|
||||
private _formBuilder = inject(FormBuilder);
|
||||
|
||||
isChecked = true;
|
||||
formGroup = this._formBuilder.group({
|
||||
enableWifi: '',
|
||||
acceptTerms: ['', Validators.requiredTrue],
|
||||
});
|
||||
|
||||
alertFormValues(formGroup: FormGroup) {
|
||||
alert(JSON.stringify(formGroup.value, null, 2));
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
}
|
||||
@@ -0,0 +1,348 @@
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 1 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
|
||||
<div class="row">
|
||||
@for(topcard of topcards; track topcard) {
|
||||
<div class="col-lg-2 col-sm-4 col-6">
|
||||
<mat-card class="shadow-none text-center bg-light-{{ topcard.color }} shadow-none">
|
||||
<mat-card-content class="p-32">
|
||||
<img [src]="topcard.img" alt="users" width="40" class="rounded-circle" />
|
||||
<h4 class="f-s-14 f-w-600 text-{{ topcard.color }} m-t-8">
|
||||
{{ topcard.title }}
|
||||
</h4>
|
||||
<h6 class="m-t-4 f-s-21 f-w-600 text-{{ topcard.color }} m-t-8">
|
||||
{{ topcard.subtitle }}
|
||||
</h6>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 2 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row justify-content-center">
|
||||
@for(cardimg of cardimgs; track cardimg.imgSrc) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow card2 position-relative card-hover">
|
||||
<img mat-card-image src="{{ cardimg.imgSrc }}" alt="Photo of a Shiba Inu" />
|
||||
<div class="card-overlay h-100 d-flex align-items-end justify-content-end">
|
||||
<mat-chip class="f-s-12 f-w-600 m-y-16 m-r-16 bg-white">{{
|
||||
cardimg.time
|
||||
}}</mat-chip>
|
||||
</div>
|
||||
|
||||
<mat-card-content class="p-y-24">
|
||||
<div class="user-category">
|
||||
<div>
|
||||
<img src="{{ cardimg.user }}" class="rounded-circle" width="40" />
|
||||
</div>
|
||||
<mat-chip class="f-s-12 m-y-16 f-w-600 bg-light">{{
|
||||
cardimg.category
|
||||
}}</mat-chip>
|
||||
</div>
|
||||
<mat-card-title>{{ cardimg.title }}</mat-card-title>
|
||||
<div class="d-flex align-items-center justify-content-center m-t-24">
|
||||
<div class="d-flex align-items-center">
|
||||
<span class="m-r-12 f-s-14 d-flex align-items-center"><i-tabler name="eye"
|
||||
class="icon-18 m-r-4"></i-tabler>{{ cardimg.views }}</span>
|
||||
<span class="f-s-14 d-flex align-items-center"><i-tabler name="message-2"
|
||||
class="icon-18 m-r-4"></i-tabler>{{ cardimg.comments }}</span>
|
||||
</div>
|
||||
<span class="m-l-auto f-s-14 d-flex align-items-center">
|
||||
<i-tabler name="point" class="icon-14 m-r-4 d-flex"></i-tabler>
|
||||
{{ cardimg.date }}
|
||||
</span>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 3 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(productcard of productcards; track productcard.title) {
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card class="cardWithShadow productcard overflow-hidden">
|
||||
<a routerLink="/widgets/cards">
|
||||
<img src="{{ productcard.imgSrc }}" alt="imgSrc" class="w-100" mat-card-image />
|
||||
</a>
|
||||
<mat-card-content class="p-b-24 p-t-12 position-relative">
|
||||
<button mat-mini-fab class="icon-30 m-t--48 d-flex bg-primary text-white" matTooltip="Add to Cart">
|
||||
<i-tabler name="basket" class="icon-16 d-flex"></i-tabler>
|
||||
</button>
|
||||
<mat-card-title class="mat-headline-2 f-s-16 m-b-4 m-t-16">{{
|
||||
productcard.title
|
||||
}}</mat-card-title>
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div class="d-flex align-items-center">
|
||||
<h6 class="f-s-16 f-w-600">${{ productcard.price }}</h6>
|
||||
<span class="f-s-14 m-l-4 text-decoration-line-through">${{ productcard.rprice }}</span>
|
||||
</div>
|
||||
<div class="m-l-auto d-flex gap-4">
|
||||
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||
<span><i-tabler name="star" class="fill-warning icon-18"></i-tabler></span>
|
||||
</div>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 4 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(musiccard of musiccards; track musiccard.title) {
|
||||
<div class="col-lg-4">
|
||||
<mat-card class="cardWithShadow overflow-hidden">
|
||||
<div class="row m-0">
|
||||
<div class="col-6 p-24">
|
||||
<h5 class="f-w-600 f-s-18 m-0">{{ musiccard.title }}</h5>
|
||||
<span class="f-s-14">{{ musiccard.subtext }}</span>
|
||||
|
||||
<div class="d-flex align-items-center justify-content-between m-t-24">
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="player-skip-back" class="icon-16 d-flex"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button color="warn" class="d-flex justify-content-center">
|
||||
<i-tabler name="player-play" class="icon-16 d-flex"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="player-skip-forward" class="icon-16 d-flex"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<img src="{{ musiccard.imgSrc }}" width="240" height="180" class="h-100" alt="blog" />
|
||||
</div>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 5 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(followercard of followercards; track followercard.title) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ followercard.imgSrc }}" width="40" alt="user" class="rounded-circle" />
|
||||
<div class="m-l-16">
|
||||
<h6 class="m-0 f-w-600 f-s-16">{{ followercard.title }}</h6>
|
||||
<span class="d-flex align-items-center f-s-14"><i-tabler name="map-pin"
|
||||
class="icon-14 m-r-4"></i-tabler>{{ followercard.subtext }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button mat-flat-button color="primary" class="m-l-auto">
|
||||
Follow
|
||||
</button>
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 6 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(friendcard of friendcards; track friendcard.title) {
|
||||
<div class="col-sm-6 col-lg-3">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content class="p-y-24">
|
||||
<img src="{{ friendcard.imgSrc }}" alt="user" width="80" class="rounded-circle" />
|
||||
<mat-card-title class="m-t-16">{{ friendcard.title }}</mat-card-title>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="avatar-group m-r-8">
|
||||
<img src="/assets/images/profile/user-1.jpg" alt="user" class="rounded-circle" width="28" />
|
||||
<img src="/assets/images/profile/user-2.jpg" alt="user" class="rounded-circle" width="28" />
|
||||
<img src="/assets/images/profile/user-3.jpg" alt="user" class="rounded-circle" width="28" />
|
||||
</div>
|
||||
<span class="f-s-14">3 mutual friends</span>
|
||||
</div>
|
||||
<button mat-flat-button color="primary" class="w-100 m-t-24">
|
||||
Add Friend
|
||||
</button>
|
||||
<button mat-stroked-button color="warn" class="w-100 m-t-8">
|
||||
Remove
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 7 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(socialcard of socialcards; track socialcard.username) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow overflow-hidden">
|
||||
<mat-card-content class="text-center p-y-24">
|
||||
<img src="{{ socialcard.imgSrc }}" class="rounded-circle" width="80" />
|
||||
<mat-card-title class="f-s-18 m-b-0 m-t-16">{{
|
||||
socialcard.username
|
||||
}}</mat-card-title>
|
||||
<mat-card-subtitle class="f-s-12 f-s-14">{{
|
||||
socialcard.post
|
||||
}}</mat-card-subtitle>
|
||||
</mat-card-content>
|
||||
<div class="b-t-1 p-x-24 p-y-8 d-flex justify-content-center bg-light-primary">
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="brand-facebook" class="icon-18 d-flex text-primary"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="brand-instagram" class="icon-18 d-flex text-error"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="brand-github" class="icon-18 d-flex text-success"></i-tabler>
|
||||
</button>
|
||||
<button mat-icon-button class="d-flex justify-content-center">
|
||||
<i-tabler name="brand-twitter" class="icon-18 d-flex text-secondary"></i-tabler>
|
||||
</button>
|
||||
</div>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<!-- card 8 -->
|
||||
<!-- --------------------------------------------------------------------- -->
|
||||
<div class="row">
|
||||
@for(giftcard of giftcards; track giftcard.username) {
|
||||
<div class="col-sm-6 col-lg-4">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content class="p-y-24">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<mat-card-title class="f-s-16">{{
|
||||
giftcard.username
|
||||
}}</mat-card-title>
|
||||
<i-tabler name="gift" class="icon-18 text-primary"></i-tabler>
|
||||
</div>
|
||||
|
||||
<img src="{{ giftcard.imgSrc }}" alt="user" class="rounded w-100 m-t-8" />
|
||||
|
||||
<button mat-flat-button color="primary" class="w-100 m-t-8">
|
||||
Gift to Friend ($50.00)
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<!-- column -->
|
||||
<div class="col-lg-4">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content class="p-y-24">
|
||||
<mat-card-title>Payment Gateways</mat-card-title>
|
||||
<mat-card-subtitle class="f-s-14 p-b-16">Platform For Income</mat-card-subtitle>
|
||||
|
||||
@for(stat of stats; track stat.title) {
|
||||
<div class="m-t-32">
|
||||
<div class="d-flex align-items-center m-b-24">
|
||||
<span class="text-{{ stat.color }} bg-light-{{
|
||||
stat.color
|
||||
}} rounded icon-40 d-flex align-items-center justify-content-center">
|
||||
<img [src]="stat.img" alt="icon" />
|
||||
</span>
|
||||
|
||||
<div class="m-l-16 m-r-auto">
|
||||
<h6 class="f-s-16 f-w-600">{{ stat.title }}</h6>
|
||||
<span class="f-s-14">{{ stat.subtitle }}</span>
|
||||
</div>
|
||||
<span class="f-w-600 f-s-14"> +${{ stat.percent }} </span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<button mat-stroked-button color="primary" class="w-100 m-t-8">
|
||||
View all Transctions
|
||||
</button>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<!-- column -->
|
||||
<div class="col-lg-4">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content class="p-t-24">
|
||||
<mat-card-title>Upcoming Activity</mat-card-title>
|
||||
<mat-card-subtitle class="f-s-14 p-b-16">In New year</mat-card-subtitle>
|
||||
|
||||
@for(activity of activities; track activity.title) {
|
||||
<div>
|
||||
<div class="d-flex align-items-center p-y-16">
|
||||
<span class="text-{{ activity.color }} bg-light-{{
|
||||
activity.color
|
||||
}} rounded icon-40 d-flex align-items-center justify-content-center">
|
||||
<i-tabler name="{{ activity.icon }}" class="icon-18 d-flex"></i-tabler>
|
||||
</span>
|
||||
|
||||
<div class="m-l-16 m-r-auto">
|
||||
<h6 class="f-s-16 f-w-600">{{ activity.title }}</h6>
|
||||
<span class="f-s-14">{{ activity.subtitle }}</span>
|
||||
</div>
|
||||
<span class="f-s-14">{{ activity.time }} </span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
|
||||
<!-- column -->
|
||||
<div class="col-lg-4">
|
||||
<mat-card class="cardWithShadow">
|
||||
<mat-card-content class="p-y-24">
|
||||
<mat-card-title>Recent Transactions</mat-card-title>
|
||||
|
||||
<div class="timeline m-t-24">
|
||||
@for(stat of stats2; track stat.subtext) {
|
||||
<div class="timeline-item d-flex overflow-hidden">
|
||||
<div class="time text-right f-s-14">{{ stat.time }}</div>
|
||||
<div class="point d-flex align-items-center">
|
||||
<span class="timeline-badge border-{{ stat.color }} m-y-8"></span>
|
||||
<span class="timline-border d-block"></span>
|
||||
</div>
|
||||
<div class="desc">
|
||||
@if(stat.subtext) {
|
||||
<span class="f-s-14 lh-20">{{ stat.subtext }}</span>
|
||||
}
|
||||
|
||||
@if(stat.title) {
|
||||
<span class="f-s-14 lh-20 f-w-600 d-block">{{
|
||||
stat.title
|
||||
}}</span>
|
||||
}
|
||||
|
||||
@if(stat.link) {
|
||||
<a href="#" class="text-primary text-decoration-none f-s-14">#ML-3467</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { FrontEndService } from './front-end.service';
|
||||
|
||||
describe('FrontEndService', () => {
|
||||
let service: FrontEndService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(FrontEndService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
import { Injectable, signal } from '@angular/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class FrontEndService {
|
||||
|
||||
private blog = signal<any>(null);
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
||||
|
||||
setBlog(blogData: any) {
|
||||
this.blog.set(blogData);
|
||||
}
|
||||
|
||||
getBlog() {
|
||||
return this.blog;
|
||||
}
|
||||
}
|
||||
BIN
theme/packages/dark/src/assets/images/front-pages/app-chat.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
theme/packages/dark/src/assets/images/front-pages/app-email.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
BIN
theme/packages/dark/src/assets/images/front-pages/demo-dark.jpg
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 37 KiB |
BIN
theme/packages/dark/src/assets/images/front-pages/demo-main.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
theme/packages/dark/src/assets/images/front-pages/demo-rtl.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 109 KiB |