diff --git a/public/logo.jpg b/public/logo.jpg deleted file mode 100644 index 6be2f14..0000000 Binary files a/public/logo.jpg and /dev/null differ diff --git a/public/logo.png b/public/logo.png new file mode 100644 index 0000000..54ca585 Binary files /dev/null and b/public/logo.png differ diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 78798c2..213a3e4 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,6 +1,10 @@ import { Routes } from '@angular/router'; import { Home } from './pages/home/home'; +import { Register } from './pages/register/register'; +import { LoginComponent } from './pages/login/login'; export const routes: Routes = [ { path: '', component: Home }, + { path: "register", component: Register }, + { path: "login", component: LoginComponent }, ]; diff --git a/src/app/components/cta-button/cta-button.html b/src/app/components/cta-button/cta-button.html index c3d7cae..db91947 100644 --- a/src/app/components/cta-button/cta-button.html +++ b/src/app/components/cta-button/cta-button.html @@ -1,10 +1,11 @@ - + + + + - -
- Somos a escolha certa para estar sempre conectado! + +
+ + Somos a escolha certa para estar sempre conectado! +
+ diff --git a/src/app/components/header/header.scss b/src/app/components/header/header.scss index 0f3ccff..e887fcb 100644 --- a/src/app/components/header/header.scss +++ b/src/app/components/header/header.scss @@ -2,13 +2,41 @@ /* HEADER PRINCIPAL */ /* ===================== */ .header-container { + position: sticky; + top: 0; + z-index: 1000; + width: 100%; - background: #ffffff; + /* mais transparente mesmo no topo */ + background: rgba(255, 255, 255, 0.75); font-family: 'Inter', sans-serif; display: flex; flex-direction: column; + + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); + + transition: + background-color 0.25s ease, + backdrop-filter 0.25s ease, + -webkit-backdrop-filter 0.25s ease, + box-shadow 0.25s ease, + border-color 0.25s ease; } +/* HEADER “FOSCO” QUANDO SCROLLADO – BEM TRANSPARENTE */ +.header-container.header-scrolled { + background: rgba(255, 255, 255, 0.22); /* quase vidro puro */ + backdrop-filter: blur(14px); + -webkit-backdrop-filter: blur(14px); + + box-shadow: 0 4px 24px rgba(0, 0, 0, 0.12); + border-bottom: 1px solid rgba(201, 30, 181, 0.3); +} + + + + /* ===================== */ /* TOP AREA (LOGO + MENU + BOTÕES) */ /* ===================== */ @@ -314,28 +342,39 @@ /* ===================== */ .header-bar { width: 100%; - height: 38.41px; - background: rgba(3, 15, 170, 0.93); + height: 34px; /* um pouco mais baixa */ + background: linear-gradient(90deg, #030FAA 0%, #6066FF 45%, #C91EB5 100%); display: flex; align-items: center; justify-content: center; + border-top: 1px solid rgba(255, 255, 255, 0.25); + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18); + @media (max-width: 480px) { - height: 34px; + height: 30px; } } .header-bar-text { color: #ffffff; - font-size: 16px; - font-weight: 700; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.08em; + text-transform: uppercase; - /* NOTEBOOKS 1200–1399px */ - @media (min-width: 1200px) and (max-width: 1399.98px) { - font-size: 15px; - } + /* “pill” para destacar o texto */ + padding: 4px 14px; + border-radius: 999px; + background: rgba(0, 0, 0, 0.12); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); @media (max-width: 480px) { - font-size: 14px; + font-size: 11.5px; + padding: 3px 10px; + letter-spacing: 0.06em; + text-align: center; } } + diff --git a/src/app/components/header/header.ts b/src/app/components/header/header.ts index 53cc8a0..ca0177c 100644 --- a/src/app/components/header/header.ts +++ b/src/app/components/header/header.ts @@ -1,11 +1,30 @@ -import { Component } from '@angular/core'; -import { RouterLink } from '@angular/router'; +import { Component, HostListener } from '@angular/core'; +import { RouterLink, Router, NavigationEnd } from '@angular/router'; +import { CommonModule } from '@angular/common'; @Component({ selector: 'app-header', - standalone: true, // ⬅️ importante para usar `imports` aqui - imports: [RouterLink], // ⬅️ habilita o uso de routerLink no template + standalone: true, + imports: [RouterLink, CommonModule], // ⬅️ CommonModule para usar *ngIf templateUrl: './header.html', - styleUrl: './header.scss', + styleUrls: ['./header.scss'], }) -export class Header { } +export class Header { + isScrolled = false; + isHome = true; // valor inicial (ao abrir normalmente cai na home) + + constructor(private router: Router) { + // escuta mudanças de rota para saber se está na home + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + const url = event.urlAfterRedirects || event.url; + this.isHome = (url === '/' || url === ''); + } + }); + } + + @HostListener('window:scroll', []) + onWindowScroll() { + this.isScrolled = window.scrollY > 10; // passou 10px de scroll, ativa o “fosco” + } +} diff --git a/src/app/pages/home/home.html b/src/app/pages/home/home.html index 165749c..fdd9d69 100644 --- a/src/app/pages/home/home.html +++ b/src/app/pages/home/home.html @@ -50,9 +50,13 @@
- + +
+
diff --git a/src/app/pages/home/home.ts b/src/app/pages/home/home.ts index e5911cf..9540652 100644 --- a/src/app/pages/home/home.ts +++ b/src/app/pages/home/home.ts @@ -1,34 +1,29 @@ import { Component } from '@angular/core'; -import { CommonModule } from '@angular/common'; // Importa CommonModule +import { CommonModule } from '@angular/common'; import { FeatureCardComponent } from '../../components/feature-card/feature-card'; import { CtaButtonComponent } from '../../components/cta-button/cta-button'; +import { Router } from '@angular/router'; // ⬅️ IMPORT CERTO (ANGULAR) @Component({ selector: 'app-home', - // 1. Marca o componente como autônomo - standalone: true, - // 2. Importa o que o template precisa: + standalone: true, imports: [ - CommonModule, // Para usar diretivas comuns (ngClass, ngIf, etc.) no seu home.html - FeatureCardComponent, // Para usar o seletor no seu home.html + CommonModule, + FeatureCardComponent, CtaButtonComponent ], templateUrl: './home.html', - styleUrl: './home.scss', + styleUrls: ['./home.scss'], // ⬅️ styleUrls (array) }) export class Home { - // Seus dados dos cards podem ser definidos aqui para uso no home.html: - /* - cardsData = [ - { title: 'Monitoramento Completo', iconClass: 'bi bi-laptop', description: '...' }, - // ... - ]; - */ + + // ⬅️ Aqui o Angular injeta o Router e guarda em this.router + constructor(private router: Router) {} iniciar(): void { - console.log('Botão COMEÇAR AGORA clicado! Redirecionando ou abrindo modal...'); - // Aqui você adicionaria sua lógica de navegação, como: - // this.router.navigate(['/cadastro']); - // Ou uma chamada para abrir um modal de registro. + // só pra debug, se quiser: + // console.log('Botão COMEÇAR AGORA clicado! Redirecionando para /register...'); + + this.router.navigate(['/register']); // ⬅️ agora this.router não é mais undefined } -} \ No newline at end of file +} diff --git a/src/app/pages/login/login.html b/src/app/pages/login/login.html new file mode 100644 index 0000000..42ae1e8 --- /dev/null +++ b/src/app/pages/login/login.html @@ -0,0 +1,49 @@ + diff --git a/src/app/pages/login/login.scss b/src/app/pages/login/login.scss new file mode 100644 index 0000000..89a68be --- /dev/null +++ b/src/app/pages/login/login.scss @@ -0,0 +1,119 @@ +/* ========================= */ +/* TELA DE LOGIN */ +/* ========================= */ + +/* Wrapper para centralizar o card entre header e footer */ +.login-wrapper { + min-height: calc(100vh - 60px); + + display: flex; + justify-content: center; /* login fica no centro */ + align-items: center; + + padding-top: 32px; + padding-right: 12px; + padding-bottom: 100px; /* mesmo “respiro” do cadastro */ + padding-left: 12px; + + background: url('../../../assets/wallpaper/registro_qualidade3.png') + no-repeat right center; + background-size: contain; + background-color: #efefef; + + @media (max-width: 992px) { + padding-left: 16px; + padding-right: 16px; + padding-bottom: 80px; + } + + @media (max-width: 576px) { + min-height: calc(100vh - 40px); + padding-top: 24px; + padding-bottom: 60px; + } +} + + +/* Card principal – mesmo estilo “glass” do cadastro, + mas SEM margin-left e centralizado pelo flex */ +.login-card { + background-color: transparent; + border-radius: 10px; + border: 2px solid #c91eb5; + + max-width: 500px; /* aumenta a largura como no cadastro */ + width: 100%; + min-height: 380px; /* um pouco menor que o cadastro, mas folgado */ + padding: 28px 24px; /* mesmo “respiro” interno */ + box-sizing: border-box; + + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); + + .mb-3, + .mb-4 { + margin-bottom: 0.9rem; + } +} + +/* Título centralizado rosa */ +.login-title { + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1.25rem !important; + + h2 { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 700; + font-size: 32px; + color: #c91eb5; + margin: 0; + } +} + +/* Labels – mesmo tamanho do cadastro */ +.form-label { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 500; + font-size: 14px; + color: #000000; +} + +/* Inputs iguais aos do cadastro (borda azul, maiores) */ +.form-control { + height: 38px; /* antes 34px */ + border-radius: 8px; + border: 2px solid #6066ff; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 500; + font-size: 14px; /* antes 13px */ + color: #000000; + + &::placeholder { + color: rgba(0, 0, 0, 0.5); + } +} + +/* Botão ENTRAR – rosa sólido, mesmo estilo do cadastrar */ +.login-btn-submit { + border-radius: 40px; + border: none; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 600; + font-size: 14px; + letter-spacing: 0.5px; + text-transform: uppercase; + padding: 9px 0; + background-color: #c91eb5; + color: #ffffff; + + &:hover { + filter: brightness(1.04); + } +} + +/* Mensagens de erro */ +.text-danger.small { + font-size: 11px; +} diff --git a/src/app/pages/login/login.ts b/src/app/pages/login/login.ts new file mode 100644 index 0000000..4235426 --- /dev/null +++ b/src/app/pages/login/login.ts @@ -0,0 +1,63 @@ +import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { + FormBuilder, + FormGroup, + Validators, + ReactiveFormsModule +} from '@angular/forms'; + +@Component({ + selector: 'app-login', + standalone: true, + imports: [CommonModule, ReactiveFormsModule], + templateUrl: './login.html', + styleUrls: ['./login.scss'] +}) +export class LoginComponent { + + loginForm: FormGroup; + isSubmitting = false; + + constructor(private fb: FormBuilder) { + this.loginForm = this.fb.group({ + username: ['', [Validators.required]], // “Usuário” do protótipo + password: ['', [Validators.required, Validators.minLength(6)]] + }); + } + + onSubmit(): void { + if (this.loginForm.invalid) { + this.loginForm.markAllAsTouched(); + return; + } + + this.isSubmitting = true; + + // Simulação de envio – preparado para API futura + console.log('Dados de login:', this.loginForm.value); + + // FUTURO: aqui você injeta seu AuthService e chama a API .NET: + /* + this.authService.login(this.loginForm.value).subscribe({ + next: () => { ... }, + error: () => { ... }, + complete: () => this.isSubmitting = false + }); + */ + + setTimeout(() => { + this.isSubmitting = false; + alert('Login enviado (simulado). Depois conectamos na API .NET 😉'); + }, 800); + } + + hasError(field: string, error?: string): boolean { + const control = this.loginForm.get(field); + if (!control) return false; + if (error) { + return control.touched && control.hasError(error); + } + return control.touched && control.invalid; + } +} diff --git a/src/app/pages/register/register.html b/src/app/pages/register/register.html index 6b0ba2e..886f256 100644 --- a/src/app/pages/register/register.html +++ b/src/app/pages/register/register.html @@ -1 +1,108 @@ -

register works!

+ + +
+
+ + +
+ + + +

Cadastre-se

+
+ + +
+ + +
+ + + +
+ Informe o seu nome completo (mínimo 3 caracteres). +
+
+ + +
+ + + +
+ E-mail é obrigatório. +
+
+ Informe um e-mail válido. +
+
+ + +
+ + + +
+ Informe um telefone válido. +
+
+ + +
+ + + +
+ A senha deve ter pelo menos 6 caracteres. +
+
+ + +
+ + + +
+ As senhas não conferem. +
+
+ + + + + + + +
+
+
diff --git a/src/app/pages/register/register.scss b/src/app/pages/register/register.scss index e69de29..b69c58c 100644 --- a/src/app/pages/register/register.scss +++ b/src/app/pages/register/register.scss @@ -0,0 +1,155 @@ +/* ========================= */ +/* TELA DE CADASTRO */ +/* ========================= */ + +/* Wrapper para centralizar o card entre header e footer */ +.register-wrapper { + /* ocupa quase a tela toda, mas sem exagero */ + min-height: calc(100vh - 60px); + + display: flex; + justify-content: flex-start; + align-items: center; + + /* respiro mais equilibrado */ + padding-top: 32px; + padding-right: 12px; + padding-bottom: 100px; /* ainda empurra o footer, mas menos que 140 */ + padding-left: 5vw; + + background: url('../../../assets/wallpaper/registro_qualidade2.png') + no-repeat right center; + background-size: contain; + background-color: #efefef; + + /* responsivo: em telas menores, centraliza o card e reduz paddings */ + @media (max-width: 992px) { + justify-content: center; + padding-left: 16px; + padding-right: 16px; + padding-bottom: 80px; + } + + @media (max-width: 576px) { + min-height: calc(100vh - 40px); + padding-top: 24px; + padding-bottom: 60px; + } +} + + + +/* Card principal – AGORA MAIS LARGO */ +.register-card { + background-color: transparent; + border-radius: 10px; + border: 2px solid #c91eb5; + + max-width: 500px; /* antes 340px ✅ aumenta a largura do card */ + width: 100%; + min-height: 500px; /* leve ajuste pra não ficar “apertado” */ + padding: 28px 24px; /* um pouco mais de “respiro” interno */ + box-sizing: border-box; + margin-left: 150px; + + backdrop-filter: blur(6px); + -webkit-backdrop-filter: blur(6px); + + .mb-3, + .mb-4 { + margin-bottom: 0.9rem; /* mantém espaçamento confortável */ + } +} + +/* Título: ícone + texto lado a lado */ +.register-title { + display: flex; + align-items: center; + justify-content: center; + gap: 6px; + margin-bottom: 1.25rem !important; + + h2 { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 700; + font-size: 32px; + color: #c91eb5; + margin: 0; + } +} + +/* Ícone ao lado do título */ +.register-icon { + display: flex; + align-items: center; + justify-content: center; + color: #c91eb5; + + i { + font-size: 32px; + } +} + +/* Labels */ +.form-label { + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 500; + font-size: 14px; /* um pouco maior pra acompanhar o card */ + color: #000000; +} + +/* Inputs com borda azul do protótipo – levemente maiores */ +.form-control { + height: 38px; /* antes 34px */ + border-radius: 8px; + border: 2px solid #6066ff; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 500; + font-size: 14px; /* antes 13px */ + color: #000000; + + &::placeholder { + color: rgba(0, 0, 0, 0.5); + } +} + +/* Botão principal (CADASTRAR) – rosa sólido */ +.register-btn { + border-radius: 40px; + border: none; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 600; + font-size: 14px; /* um tic maior */ + letter-spacing: 0.5px; + text-transform: uppercase; + padding: 9px 0; + background-color: #c91eb5; + color: #ffffff; + + &:hover { + filter: brightness(1.04); + } +} + +/* Botão "JÁ TEM UMA CONTA? ENTRE" – azul sólido */ +.login-btn { + border-radius: 40px; + border: none; + font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + font-weight: 600; + font-size: 13px; + letter-spacing: 0.5px; + text-transform: uppercase; + padding: 8px 0; + background-color: #030faa; + color: #ffffff; + + &:hover { + filter: brightness(1.04); + } +} + +/* Mensagens de erro */ +.text-danger.small { + font-size: 11px; +} diff --git a/src/app/pages/register/register.ts b/src/app/pages/register/register.ts index 38bed95..f6905de 100644 --- a/src/app/pages/register/register.ts +++ b/src/app/pages/register/register.ts @@ -1,11 +1,75 @@ +// src/app/pages/register.component.ts import { Component } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-register', - imports: [], + standalone: true, + imports: [CommonModule, ReactiveFormsModule, RouterLink], templateUrl: './register.html', - styleUrl: './register.scss', + styleUrls: ['./register.scss'] // ou .scss }) export class Register { + registerForm: FormGroup; + isSubmitting = false; + + constructor(private fb: FormBuilder) { + this.registerForm = this.fb.group({ + fullName: ['', [Validators.required, Validators.minLength(3)]], + email: ['', [Validators.required, Validators.email]], + phone: ['', [Validators.required]], + password: ['', [Validators.required, Validators.minLength(6)]], + confirmPassword: ['', [Validators.required]] + }, { + validators: [this.passwordsMatchValidator] + }); + } + + // Validador para confirmar senha + private passwordsMatchValidator(group: FormGroup) { + const pass = group.get('password')?.value; + const confirm = group.get('confirmPassword')?.value; + return pass === confirm ? null : { passwordsMismatch: true }; + } + + onSubmit(): void { + if (this.registerForm.invalid) { + this.registerForm.markAllAsTouched(); + return; + } + + this.isSubmitting = true; + + // Por enquanto: apenas exibe os dados e "simula" o envio + console.log('Dados de cadastro:', this.registerForm.value); + + // TODO FUTURO: quando a API .NET estiver pronta, + // você injeta um AuthService e envia para o backend: + /* + this.authService.register(this.registerForm.value).subscribe({ + next: () => { ... }, + error: () => { ... }, + complete: () => this.isSubmitting = false + }); + */ + + // Simulação de atraso só para UX (remova se quiser) + setTimeout(() => { + this.isSubmitting = false; + this.registerForm.reset(); + alert('Cadastro realizado (simulado). Quando a API estiver pronta, isso irá de fato registrar o usuário.'); + }, 800); + } + + hasError(field: string, error?: string): boolean { + const control = this.registerForm.get(field); + if (!control) return false; + if (error) { + return control.touched && control.hasError(error); + } + return control.touched && control.invalid; + } } diff --git a/src/assets/wallpaper/registro_qualidade.png b/src/assets/wallpaper/registro_qualidade.png new file mode 100644 index 0000000..4d3d12f Binary files /dev/null and b/src/assets/wallpaper/registro_qualidade.png differ diff --git a/src/assets/wallpaper/registro_qualidade2.png b/src/assets/wallpaper/registro_qualidade2.png new file mode 100644 index 0000000..e560b09 Binary files /dev/null and b/src/assets/wallpaper/registro_qualidade2.png differ diff --git a/src/assets/wallpaper/registro_qualidade3.png b/src/assets/wallpaper/registro_qualidade3.png new file mode 100644 index 0000000..041b466 Binary files /dev/null and b/src/assets/wallpaper/registro_qualidade3.png differ diff --git a/src/index.html b/src/index.html index 3fc585f..f2bb223 100644 --- a/src/index.html +++ b/src/index.html @@ -7,6 +7,7 @@ +