improved dashboard
This commit is contained in:
parent
114c280734
commit
90168ba619
8 changed files with 781 additions and 47 deletions
|
|
@ -1,18 +1,67 @@
|
|||
<!-- Trading Dashboard App -->
|
||||
<div class="min-h-screen bg-gray-50">
|
||||
<app-sidebar></app-sidebar>
|
||||
<main class="main-content">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
<div class="app-layout">
|
||||
<!-- Sidebar -->
|
||||
<app-sidebar [opened]="sidenavOpened()" (navigationItemClick)="onNavigationClick($event)"></app-sidebar>
|
||||
|
||||
<!-- Main Content Area -->
|
||||
<div class="main-content" [class.main-content-closed]="!sidenavOpened()">
|
||||
<!-- Top Navigation Bar -->
|
||||
<mat-toolbar class="top-toolbar">
|
||||
<button mat-icon-button (click)="toggleSidenav()" class="mr-2">
|
||||
<mat-icon>menu</mat-icon>
|
||||
</button>
|
||||
<span class="text-lg font-semibold text-gray-800">{{ title }}</span>
|
||||
<span class="spacer"></span>
|
||||
<button mat-icon-button>
|
||||
<mat-icon>notifications</mat-icon>
|
||||
</button>
|
||||
<button mat-icon-button>
|
||||
<mat-icon>account_circle</mat-icon>
|
||||
</button>
|
||||
</mat-toolbar>
|
||||
|
||||
<!-- Page Content -->
|
||||
<div class="page-content">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.app-layout {
|
||||
display: flex;
|
||||
height: 100vh;
|
||||
background-color: #f9fafb;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin-left: 256px; /* Width of sidebar (w-64 = 16rem = 256px) */
|
||||
min-height: 100vh;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 256px; /* Width of sidebar */
|
||||
transition: margin-left 0.3s ease;
|
||||
}
|
||||
|
||||
.main-content-closed {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.top-toolbar {
|
||||
background-color: white;
|
||||
border-bottom: 1px solid #e5e7eb;
|
||||
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
}
|
||||
|
||||
.spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.page-content {
|
||||
flex: 1;
|
||||
padding: 1.5rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.main-content {
|
||||
margin-left: 0;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,22 @@
|
|||
/* Sidebar specific styles */
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 16rem; /* 256px */
|
||||
height: 100vh;
|
||||
background-color: white;
|
||||
border-right: 1px solid #e5e7eb;
|
||||
transform: translateX(0);
|
||||
transition: transform 0.3s ease-in-out;
|
||||
z-index: 1000;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sidebar-closed {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
<mat-sidenav
|
||||
[opened]="opened()"
|
||||
mode="side"
|
||||
class="w-64 bg-white border-r border-gray-200">
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sidebar" [class.sidebar-closed]="!opened()">
|
||||
<!-- Logo/Brand -->
|
||||
<div class="p-6 border-b border-gray-200">
|
||||
<h2 class="text-xl font-bold text-gray-900">
|
||||
|
|
@ -30,4 +27,4 @@
|
|||
}
|
||||
</div>
|
||||
</nav>
|
||||
</mat-sidenav>
|
||||
</aside>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { CommonModule } from '@angular/common';
|
|||
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { Router } from '@angular/router';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { filter } from 'rxjs/operators';
|
||||
|
||||
export interface NavigationItem {
|
||||
label: string;
|
||||
|
|
@ -37,15 +38,24 @@ export class SidebarComponent {
|
|||
{ label: 'Settings', icon: 'settings', route: '/settings' }
|
||||
];
|
||||
|
||||
constructor(private router: Router) {}
|
||||
constructor(private router: Router) {
|
||||
// Listen to route changes to update active state
|
||||
this.router.events.pipe(
|
||||
filter(event => event instanceof NavigationEnd)
|
||||
).subscribe((event: NavigationEnd) => {
|
||||
this.updateActiveRoute(event.urlAfterRedirects);
|
||||
});
|
||||
}
|
||||
|
||||
onNavigationClick(route: string) {
|
||||
this.navigationItemClick.emit(route);
|
||||
this.router.navigate([route]);
|
||||
|
||||
// Update active state
|
||||
this.updateActiveRoute(route);
|
||||
}
|
||||
|
||||
private updateActiveRoute(currentRoute: string) {
|
||||
this.navigationItems.forEach(item => {
|
||||
item.active = item.route === route;
|
||||
item.active = item.route === currentRoute;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,10 +34,9 @@
|
|||
</mat-card>
|
||||
|
||||
<mat-card class="p-6">
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<div class="flex items-center justify-between"> <div>
|
||||
<p class="text-sm text-gray-600">Last Update</p>
|
||||
<p class="text-lg font-semibold text-gray-900">{{ new Date().toLocaleTimeString() }}</p>
|
||||
<p class="text-lg font-semibold text-gray-900">{{ currentTime() }}</p>
|
||||
</div>
|
||||
<mat-icon class="text-purple-600 text-3xl">access_time</mat-icon>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -45,45 +45,52 @@ export class MarketDataComponent {
|
|||
},
|
||||
{
|
||||
symbol: 'GOOGL',
|
||||
price: 138.21,
|
||||
change: -1.82,
|
||||
changePercent: -1.30,
|
||||
volume: 23450000,
|
||||
marketCap: '1.75T',
|
||||
high52Week: 152.10,
|
||||
low52Week: 125.45
|
||||
price: 2847.56,
|
||||
change: -12.34,
|
||||
changePercent: -0.43,
|
||||
volume: 12450000,
|
||||
marketCap: '1.78T',
|
||||
high52Week: 3030.93,
|
||||
low52Week: 2193.62
|
||||
},
|
||||
{
|
||||
symbol: 'MSFT',
|
||||
price: 378.85,
|
||||
change: 4.12,
|
||||
changePercent: 1.10,
|
||||
volume: 34560000,
|
||||
marketCap: '2.82T',
|
||||
high52Week: 384.30,
|
||||
price: 415.26,
|
||||
change: 8.73,
|
||||
changePercent: 2.15,
|
||||
volume: 23180000,
|
||||
marketCap: '3.08T',
|
||||
high52Week: 468.35,
|
||||
low52Week: 309.45
|
||||
},
|
||||
{
|
||||
symbol: 'TSLA',
|
||||
price: 248.42,
|
||||
change: -3.21,
|
||||
changePercent: -1.28,
|
||||
volume: 67890000,
|
||||
marketCap: '789B',
|
||||
price: 248.50,
|
||||
change: -5.21,
|
||||
changePercent: -2.05,
|
||||
volume: 89760000,
|
||||
marketCap: '789.2B',
|
||||
high52Week: 299.29,
|
||||
low52Week: 138.80
|
||||
low52Week: 152.37
|
||||
},
|
||||
{
|
||||
symbol: 'AMZN',
|
||||
price: 145.67,
|
||||
change: 1.89,
|
||||
changePercent: 1.31,
|
||||
volume: 29340000,
|
||||
marketCap: '1.52T',
|
||||
high52Week: 155.20,
|
||||
price: 152.74,
|
||||
change: 3.18,
|
||||
changePercent: 2.12,
|
||||
volume: 34520000,
|
||||
marketCap: '1.59T',
|
||||
high52Week: 170.17,
|
||||
low52Week: 118.35
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
protected displayedColumns: string[] = ['symbol', 'price', 'change', 'changePercent', 'volume', 'marketCap'];
|
||||
|
||||
protected currentTime = signal<string>(new Date().toLocaleTimeString()); constructor() {
|
||||
// Update time every second
|
||||
setInterval(() => {
|
||||
this.currentTime.set(new Date().toLocaleTimeString());
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue