diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 06022b9..5d2acd6 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -11,7 +11,7 @@ import { authGuard } from './guards/auth.guard'; import { DadosUsuarios } from './pages/dados-usuarios/dados-usuarios'; import { VigenciaComponent } from './pages/vigencia/vigencia'; import { TrocaNumero } from './pages/troca-numero/troca-numero'; -import { Relatorios } from './pages/relatorios/relatorios'; +import { Dashboard } from './pages/dashboard/dashboard'; export const routes: Routes = [ { path: '', component: Home }, @@ -26,10 +26,10 @@ export const routes: Routes = [ { path: 'trocanumero', component: TrocaNumero, canActivate: [authGuard] }, // ✅ rota correta - { path: 'relatorios', component: Relatorios, canActivate: [authGuard] }, + { path: 'dashboard', component: Dashboard, canActivate: [authGuard] }, - // ✅ compatibilidade: se alguém acessar /portal/relatorios, manda pra /relatorios - { path: 'portal/relatorios', redirectTo: 'relatorios', pathMatch: 'full' }, + // ✅ compatibilidade: se alguém acessar /portal/dashboard, manda pra /dashboard + { path: 'portal/dashboard', redirectTo: 'dashboard', pathMatch: 'full' }, { path: '**', redirectTo: '' }, ]; diff --git a/src/app/app.ts b/src/app/app.ts index f4b13c7..93920fa 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -33,7 +33,7 @@ export class AppComponent { '/dadosusuarios', '/vigencia', '/trocanumero', - '/relatorios', // ✅ ADICIONADO: esconde footer na página de relatórios + '/dashboard', // ✅ ADICIONADO: esconde footer na página de dashboard ]; constructor( diff --git a/src/app/components/header/header.html b/src/app/components/header/header.html index 97763e0..81d7242 100644 --- a/src/app/components/header/header.html +++ b/src/app/components/header/header.html @@ -3,19 +3,54 @@ -
- +
+
+ - - + +
+ + + LIVE + + + + +
+ + +
+ + Perfil + + +
-
- LineGestão -
- +
@@ -58,7 +93,7 @@ (click)="$event.stopPropagation()" >
- @@ -69,8 +104,8 @@
- - Relatórios + + Dashboard diff --git a/src/app/components/header/header.scss b/src/app/components/header/header.scss index 0275bf3..d9449af 100644 --- a/src/app/components/header/header.scss +++ b/src/app/components/header/header.scss @@ -30,6 +30,20 @@ gap: 12px; } +.logged-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + width: 100%; +} + +.logged-actions { + display: flex; + align-items: center; + gap: 10px; +} + /* Logo */ .logo-area { display: flex; @@ -123,22 +137,99 @@ } } -/* Faixa home */ -.header-bar { - margin-top: 10px; - width: 100%; - height: 34px; - display: flex; +/* ✅ Status e opções (logado) */ +.status-pill { + display: inline-flex; align-items: center; - justify-content: center; - background: linear-gradient(90deg, #0B2BD6 0%, #6A55FF 40%, #E33DCF 100%); + gap: 8px; + padding: 6px 12px; + border-radius: 999px; + background: rgba(16, 185, 129, 0.12); + color: #0f766e; + font-weight: 800; + font-size: 12px; + letter-spacing: 0.06em; } -.header-bar-text { - color: #ffffff; - font-size: 15px; - font-weight: 800; - font-family: 'Poppins', sans-serif; +.status-dot { + width: 10px; + height: 10px; + border-radius: 50%; + background: #22c55e; + box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.18); +} + +.btn-bell { + width: 42px; + height: 42px; + border-radius: 12px; + + i { + font-size: 18px; + } +} + +.options-menu { + position: relative; + display: flex; + align-items: center; +} + +.options-trigger { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 8px 14px; + border-radius: 12px; + border: 1px solid rgba(0,0,0,0.1); + background: #fff; + font-weight: 700; + color: var(--text-main); + cursor: pointer; + transition: border-color 0.2s ease, box-shadow 0.2s ease; + + i { + font-size: 12px; + } + + &:hover { + border-color: rgba(227, 61, 207, 0.35); + box-shadow: 0 12px 22px rgba(0,0,0,0.08); + } +} + +.options-dropdown { + position: absolute; + right: 0; + top: calc(100% + 8px); + min-width: 200px; + padding: 8px 0; + border-radius: 14px; + border: 1px solid rgba(0,0,0,0.08); + background: #fff; + box-shadow: 0 18px 40px rgba(0,0,0,0.12); + z-index: 1200; +} + +.options-item { + display: flex; + align-items: center; + width: 100%; + padding: 10px 16px; + font-weight: 700; + color: rgba(17, 18, 20, 0.85); + text-decoration: none; + background: transparent; + border: none; + cursor: pointer; + + &:hover { + background: rgba(227, 61, 207, 0.08); + } + + &.danger { + color: #c2410c; + } } /* ========================= */ diff --git a/src/app/components/header/header.ts b/src/app/components/header/header.ts index ebbc5ba..37c52b5 100644 --- a/src/app/components/header/header.ts +++ b/src/app/components/header/header.ts @@ -3,6 +3,7 @@ import { RouterLink, Router, NavigationEnd } from '@angular/router'; import { CommonModule, isPlatformBrowser } from '@angular/common'; import { PLATFORM_ID } from '@angular/core'; import { filter } from 'rxjs/operators'; +import { AuthService } from '../../services/auth.service'; @Component({ selector: 'app-header', @@ -15,6 +16,7 @@ export class Header { isScrolled = false; menuOpen = false; + optionsOpen = false; isLoggedHeader = false; isHome = false; @@ -25,11 +27,12 @@ export class Header { '/dadosusuarios', '/vigencia', '/trocanumero', - '/relatorios', // ✅ ADICIONADO + '/dashboard', // ✅ ADICIONADO ]; constructor( private router: Router, + private authService: AuthService, @Inject(PLATFORM_ID) private platformId: object ) { // ✅ resolve no carregamento inicial @@ -42,6 +45,7 @@ export class Header { const rawUrl = event.urlAfterRedirects || event.url; this.syncHeaderState(rawUrl); this.menuOpen = false; + this.optionsOpen = false; }); } @@ -63,15 +67,35 @@ export class Header { this.menuOpen = false; } + toggleOptions() { + this.optionsOpen = !this.optionsOpen; + } + + closeOptions() { + this.optionsOpen = false; + } + + logout() { + this.authService.logout(); + this.optionsOpen = false; + this.router.navigate(['/']); + } + @HostListener('window:scroll', []) onWindowScroll() { if (!isPlatformBrowser(this.platformId)) return; this.isScrolled = window.scrollY > 10; } + @HostListener('document:click', []) + onDocumentClick() { + this.optionsOpen = false; + } + @HostListener('document:keydown.escape', []) onEsc() { if (!isPlatformBrowser(this.platformId)) return; this.closeMenu(); + this.closeOptions(); } } diff --git a/src/app/pages/relatorios/relatorios.html b/src/app/pages/dashboard/dashboard.html similarity index 98% rename from src/app/pages/relatorios/relatorios.html rename to src/app/pages/dashboard/dashboard.html index 5088116..35a2e2e 100644 --- a/src/app/pages/relatorios/relatorios.html +++ b/src/app/pages/dashboard/dashboard.html @@ -1,10 +1,10 @@ -
+
- Relatórios + Dashboard

Resumo e indicadores do ambiente.

diff --git a/src/app/pages/relatorios/relatorios.scss b/src/app/pages/dashboard/dashboard.scss similarity index 99% rename from src/app/pages/relatorios/relatorios.scss rename to src/app/pages/dashboard/dashboard.scss index a2546d1..18a401f 100644 --- a/src/app/pages/relatorios/relatorios.scss +++ b/src/app/pages/dashboard/dashboard.scss @@ -24,7 +24,7 @@ display: none !important; } -.relatorios-page { +.dashboard-page { width: 100%; overflow-x: hidden; } diff --git a/src/app/pages/relatorios/relatorios.ts b/src/app/pages/dashboard/dashboard.ts similarity index 96% rename from src/app/pages/relatorios/relatorios.ts rename to src/app/pages/dashboard/dashboard.ts index ee40fce..ae3ad0f 100644 --- a/src/app/pages/relatorios/relatorios.ts +++ b/src/app/pages/dashboard/dashboard.ts @@ -88,7 +88,7 @@ type DashboardKpisDto = { userDataComEmail: number; }; -type RelatoriosDashboardDto = { +type DashboardDto = { kpis: DashboardKpisDto; topClientes: TopClienteDto[]; @@ -105,13 +105,13 @@ type RelatoriosDashboardDto = { }; @Component({ - selector: 'app-relatorios', + selector: 'app-dashboard', standalone: true, imports: [CommonModule], - templateUrl: './relatorios.html', - styleUrls: ['./relatorios.scss'], + templateUrl: './dashboard.html', + styleUrls: ['./dashboard.scss'], }) -export class Relatorios implements OnInit, AfterViewInit, OnDestroy { +export class Dashboard implements OnInit, AfterViewInit, OnDestroy { @ViewChild('chartMureg12') chartMureg12?: ElementRef; @ViewChild('chartTroca12') chartTroca12?: ElementRef; @ViewChild('chartStatusPie') chartStatusPie?: ElementRef; @@ -202,17 +202,17 @@ export class Relatorios implements OnInit, AfterViewInit, OnDestroy { } catch { this.loading = false; this.errorMsg = - 'Falha ao carregar Relatórios. Verifique se a API está rodando e o endpoint /api/relatorios/dashboard está acessível.'; + 'Falha ao carregar Dashboard. Verifique se a API está rodando e o endpoint /api/dashboard está acessível.'; } } - private async fetchDashboardReal(): Promise { + private async fetchDashboardReal(): Promise { if (!isPlatformBrowser(this.platformId)) throw new Error('SSR não suportado para charts'); - const url = `${this.baseApi}/relatorios/dashboard`; - return await firstValueFrom(this.http.get(url)); + const url = `${this.baseApi}/dashboard`; + return await firstValueFrom(this.http.get(url)); } - private applyDto(dto: RelatoriosDashboardDto) { + private applyDto(dto: DashboardDto) { const k = dto.kpis; this.kpis = [ diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts index 52b8c48..34ef817 100644 --- a/src/app/pages/login/login.ts +++ b/src/app/pages/login/login.ts @@ -117,18 +117,18 @@ export class LoginComponent { const nome = this.getNameFromToken(token); console.log('👤 Nome extraído:', nome); - console.log('🔄 Tentando ir para /relatorios...'); - this.router.navigate(['/relatorios'], { + console.log('🔄 Tentando ir para /dashboard...'); + this.router.navigate(['/dashboard'], { state: { toastMessage: `Bem-vindo, ${nome}!` } }).then(sucesso => { if (sucesso) console.log('✅ Navegação funcionou!'); - else console.error('❌ Navegação falhou! A rota "/relatorios" existe?'); + else console.error('❌ Navegação falhou! A rota "/dashboard" existe?'); }); } catch (e) { console.error('❌ Erro ao processar token ou navegar:', e); // Força a ida mesmo se o nome falhar - this.router.navigate(['/relatorios']); + this.router.navigate(['/dashboard']); } }, error: (err) => {