Fix: Update all components to match Synthwave design showcase
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -11,46 +11,46 @@ import { Router, ActivatedRoute } from '@angular/router';
|
||||
providers: [MailService],
|
||||
template: `
|
||||
<div class="glass-panel p-6">
|
||||
<h2 class="text-lg font-orbitron font-bold text-synth-cyan mb-6 flex items-center gap-2">
|
||||
<span class="text-synth-pink">✉️</span> COMPOSE MESSAGE
|
||||
<h2 class="text-lg font-orbitron font-bold text-cyan-500 mb-6 flex items-center gap-2">
|
||||
<span class="text-pink-500">✉️</span> COMPOSE MESSAGE
|
||||
</h2>
|
||||
|
||||
@if (success) {
|
||||
<div class="mb-4 p-3 rounded-lg bg-synth-cyan/20 border border-synth-cyan/40 text-synth-cyan text-sm font-mono">
|
||||
<div class="mb-4 p-3 rounded-lg bg-cyan-500/20 border border-cyan-500/40 text-cyan-500 text-sm font-mono">
|
||||
Message sent successfully!
|
||||
</div>
|
||||
}
|
||||
|
||||
<form (ngSubmit)="onSend()" class="space-y-4">
|
||||
<div>
|
||||
<label for="to" class="block text-xs font-mono text-synth-cyan mb-1">TO</label>
|
||||
<label for="to" class="block text-xs font-mono text-cyan-500 mb-1">TO</label>
|
||||
<input id="to" type="email" [(ngModel)]="to" name="to" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all"
|
||||
placeholder="recipient@example.com">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="subject" class="block text-xs font-mono text-synth-cyan mb-1">SUBJECT</label>
|
||||
<label for="subject" class="block text-xs font-mono text-cyan-500 mb-1">SUBJECT</label>
|
||||
<input id="subject" type="text" [(ngModel)]="subject" name="subject" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all"
|
||||
placeholder="Enter subject...">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<label for="body" class="text-xs font-mono text-synth-cyan">BODY</label>
|
||||
<label for="body" class="text-xs font-mono text-cyan-500">BODY</label>
|
||||
<label class="flex items-center gap-2 cursor-pointer">
|
||||
<span class="text-xs font-mono text-slate-400">HTML</span>
|
||||
<input type="checkbox" [(ngModel)]="isHtml" name="isHtml" class="sr-only">
|
||||
<span class="w-10 h-5 rounded-full bg-synth-dark/50 border border-synth-cyan/30 relative transition-all"
|
||||
[class.bg-synth-cyan/30]="isHtml" [class.border-synth-cyan]="isHtml">
|
||||
<span class="absolute top-0.5 left-0.5 w-3.5 h-3.5 rounded-full bg-synth-cyan transition-all"
|
||||
<span class="w-10 h-5 rounded-full bg-slate-900/50 border border-cyan-500/30 relative transition-all"
|
||||
[class.bg-cyan-500/30]="isHtml" [class.border-cyan-500]="isHtml">
|
||||
<span class="absolute top-0.5 left-0.5 w-3.5 h-3.5 rounded-full bg-cyan-500 transition-all"
|
||||
[class.translate-x-5]="isHtml"></span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
<textarea id="body" [(ngModel)]="body" name="body" rows="10" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all resize-none"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-500 transition-all resize-none"
|
||||
[placeholder]="isHtml ? 'Write HTML or Markdown...' : 'Write your message...'"></textarea>
|
||||
@if (isHtml) {
|
||||
<p class="text-xs text-slate-500 font-mono mt-1">💡 Supports Markdown: **bold**, *italic*, - lists, \`\`\`code\`\`\`</p>
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
<div class="space-y-4">
|
||||
<h2 class="text-lg font-orbitron font-bold text-synth-cyan flex items-center gap-2">
|
||||
<span class="text-synth-pink">👥</span> Contacts
|
||||
<h2 class="text-lg font-orbitron font-bold text-cyan-300 flex items-center gap-2">
|
||||
<span class="text-pink-500">👥</span> CONTACTS
|
||||
<span class="text-sm font-mono text-slate-400 ml-auto">{{ contacts().length }} contacts</span>
|
||||
</h2>
|
||||
|
||||
<!-- Форма добавления -->
|
||||
<div class="glass-panel p-4">
|
||||
<h3 class="text-sm font-orbitron font-bold text-synth-yellow mb-3">
|
||||
{{ editingContact() ? 'Edit Contact' : 'Add New Contact' }}
|
||||
<div class="glass-panel p-5">
|
||||
<h3 class="text-sm font-orbitron font-bold text-yellow-400 mb-3 flex items-center gap-2">
|
||||
<span class="text-pink-500">✏️</span> {{ editingContact() ? 'EDIT CONTACT' : 'ADD NEW CONTACT' }}
|
||||
</h3>
|
||||
<form (ngSubmit)="saveContact()" class="grid grid-cols-1 md:grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label class="block text-xs font-mono text-slate-400 mb-1">Name</label>
|
||||
<label class="block text-xs font-mono text-pink-400 mb-1">NAME</label>
|
||||
<input type="text" [(ngModel)]="formName" name="name"
|
||||
class="w-full bg-synth-dark/50 border border-synth-cyan/20 rounded-lg px-3 py-2 text-sm font-mono text-white focus:border-synth-cyan focus:outline-none focus:ring-1 focus:ring-synth-cyan/50"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-2.5 text-sm font-mono text-slate-200 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="John Doe">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-mono text-slate-400 mb-1">Email *</label>
|
||||
<label class="block text-xs font-mono text-pink-400 mb-1">EMAIL *</label>
|
||||
<input type="email" [(ngModel)]="formEmail" name="email" required
|
||||
class="w-full bg-synth-dark/50 border border-synth-cyan/20 rounded-lg px-3 py-2 text-sm font-mono text-white focus:border-synth-cyan focus:outline-none focus:ring-1 focus:ring-synth-cyan/50"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-2.5 text-sm font-mono text-slate-200 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="john@example.com">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-mono text-slate-400 mb-1">Phone</label>
|
||||
<label class="block text-xs font-mono text-pink-400 mb-1">PHONE</label>
|
||||
<input type="text" [(ngModel)]="formPhone" name="phone"
|
||||
class="w-full bg-synth-dark/50 border border-synth-cyan/20 rounded-lg px-3 py-2 text-sm font-mono text-white focus:border-synth-cyan focus:outline-none focus:ring-1 focus:ring-synth-cyan/50"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-2.5 text-sm font-mono text-slate-200 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="+1 234 567 8900">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-mono text-slate-400 mb-1">Company</label>
|
||||
<label class="block text-xs font-mono text-pink-400 mb-1">COMPANY</label>
|
||||
<input type="text" [(ngModel)]="formCompany" name="company"
|
||||
class="w-full bg-synth-dark/50 border border-synth-cyan/20 rounded-lg px-3 py-2 text-sm font-mono text-white focus:border-synth-cyan focus:outline-none focus:ring-1 focus:ring-synth-cyan/50"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-2.5 text-sm font-mono text-slate-200 focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="Acme Corp">
|
||||
</div>
|
||||
<div class="md:col-span-2 flex gap-2">
|
||||
<button type="submit"
|
||||
class="px-4 py-2 bg-synth-pink/20 border border-synth-pink/40 rounded-lg text-sm font-mono text-synth-pink hover:bg-synth-pink/30 transition-all">
|
||||
{{ editingContact() ? '💾 Update' : '➕ Add' }}
|
||||
class="cyber-btn px-6 py-2 rounded-xl text-xs font-bold">
|
||||
{{ editingContact() ? '💾 UPDATE' : '➕ ADD' }}
|
||||
</button>
|
||||
@if (editingContact()) {
|
||||
<button type="button" (click)="cancelEdit()"
|
||||
class="px-4 py-2 bg-slate-700/50 border border-slate-600/40 rounded-lg text-sm font-mono text-slate-300 hover:bg-slate-600/50 transition-all">
|
||||
✖ Cancel
|
||||
class="px-4 py-2 rounded-xl text-xs font-mono text-slate-400 border border-slate-600/40 hover:text-slate-200 hover:border-slate-400 transition-all">
|
||||
✖ CANCEL
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Список контактов -->
|
||||
<div class="glass-panel p-4">
|
||||
<div class="glass-panel p-5">
|
||||
@if (contacts().length === 0) {
|
||||
<div class="text-center py-12 text-slate-400 font-mono">
|
||||
<p class="text-4xl mb-4">📇</p>
|
||||
@@ -59,28 +59,34 @@
|
||||
} @else {
|
||||
<div class="space-y-2">
|
||||
@for (contact of contacts(); track contact.id) {
|
||||
<div class="flex items-center gap-3 p-3 rounded-xl border border-synth-cyan/10 hover:border-synth-cyan/40 hover:bg-synth-cyan/5 transition-all">
|
||||
<div class="w-10 h-10 rounded-full bg-synth-purple/30 flex items-center justify-center text-synth-cyan font-bold text-lg">
|
||||
<div class="flex items-center gap-3 p-3 rounded-xl border border-cyan-500/10 hover:border-cyan-500/40 hover:bg-cyan-500/5 transition-all">
|
||||
<div class="w-10 h-10 rounded-full bg-purple-500/30 flex items-center justify-center text-cyan-400 font-bold text-lg">
|
||||
{{ (contact.name || contact.email).charAt(0).toUpperCase() }}
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-mono text-white truncate">{{ contact.name || '(No name)' }}</div>
|
||||
<div class="font-mono text-slate-200 truncate">{{ contact.name || '(No name)' }}</div>
|
||||
<div class="text-xs text-slate-400 font-mono truncate">{{ contact.email }}</div>
|
||||
@if (contact.phone || contact.company) {
|
||||
<div class="text-xs text-slate-500 font-mono">
|
||||
<span *ngIf="contact.company">{{ contact.company }}</span>
|
||||
<span *ngIf="contact.company && contact.phone"> • </span>
|
||||
<span *ngIf="contact.phone">{{ contact.phone }}</span>
|
||||
@if (contact.company) {
|
||||
{{ contact.company }}
|
||||
}
|
||||
@if (contact.company && contact.phone) {
|
||||
•
|
||||
}
|
||||
@if (contact.phone) {
|
||||
{{ contact.phone }}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
<div class="flex gap-1">
|
||||
<button (click)="editContact(contact)"
|
||||
class="px-2 py-1 text-xs font-mono text-synth-cyan hover:bg-synth-cyan/10 rounded transition-all">
|
||||
class="px-2 py-1 text-xs font-mono text-cyan-400 hover:bg-cyan-500/10 rounded-lg transition-all">
|
||||
✏️
|
||||
</button>
|
||||
<button (click)="deleteContact(contact.id!)"
|
||||
class="px-2 py-1 text-xs font-mono text-synth-pink hover:bg-synth-pink/10 rounded transition-all">
|
||||
class="px-2 py-1 text-xs font-mono text-pink-400 hover:bg-pink-500/10 rounded-lg transition-all">
|
||||
🗑️
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MailService } from '../../services/mail.service';
|
||||
import { Contact } from '../../models/mail.models';
|
||||
|
||||
@Component({
|
||||
selector: 'app-contacts',
|
||||
standalone: true,
|
||||
imports: [FormsModule, CommonModule],
|
||||
imports: [FormsModule],
|
||||
providers: [MailService],
|
||||
templateUrl: './contacts.component.html',
|
||||
styles: ``
|
||||
|
||||
@@ -18,7 +18,7 @@ import { of } from 'rxjs';
|
||||
<div class="glass-panel p-4">
|
||||
<div class="flex gap-3">
|
||||
<input [(ngModel)]="searchQuery" (keyup.enter)="loadMessages()"
|
||||
class="flex-1 bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-2 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="flex-1 bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-2 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="🔍 Search messages...">
|
||||
<button (click)="loadMessages()" class="cyber-btn px-6 py-2 rounded-xl text-xs font-bold">
|
||||
SEARCH
|
||||
@@ -28,8 +28,8 @@ import { of } from 'rxjs';
|
||||
|
||||
<!-- Список писем -->
|
||||
<div class="glass-panel p-4">
|
||||
<h2 class="text-lg font-orbitron font-bold text-synth-cyan mb-4 flex items-center gap-2">
|
||||
<span class="text-synth-pink">📬</span> {{ folderName() }}
|
||||
<h2 class="text-lg font-orbitron font-bold text-cyan-300 mb-4 flex items-center gap-2">
|
||||
<span class="text-pink-500">📬</span> {{ folderName() }}
|
||||
<span class="text-sm font-mono text-slate-400 ml-auto">{{ messages()?.length || 0 }} messages</span>
|
||||
</h2>
|
||||
|
||||
@@ -42,12 +42,12 @@ import { of } from 'rxjs';
|
||||
<div class="space-y-2">
|
||||
@for (msg of messages() || []; track msg.id) {
|
||||
<a routerLink="/message/{{ msg.id }}"
|
||||
class="block p-4 rounded-xl border border-synth-cyan/10 hover:border-synth-cyan/40 hover:bg-synth-cyan/5 transition-all cursor-pointer group">
|
||||
class="block p-4 rounded-xl border border-cyan-500/10 hover:border-cyan-500/40 hover:bg-cyan-500/5 transition-all cursor-pointer group">
|
||||
<div class="flex items-start gap-3">
|
||||
<!-- Индикатор прочитанности -->
|
||||
<div class="mt-1">
|
||||
@if (!msg.read) {
|
||||
<span class="w-3 h-3 rounded-full bg-synth-pink inline-block shadow-[0_0_8px_rgba(255,0,127,0.8)]"></span>
|
||||
<span class="w-3 h-3 rounded-full bg-pink-500 inline-block shadow-[0_0_8px_rgba(255,0,127,0.8)]"></span>
|
||||
} @else {
|
||||
<span class="w-3 h-3 rounded-full border border-slate-500 inline-block"></span>
|
||||
}
|
||||
@@ -59,15 +59,15 @@ import { of } from 'rxjs';
|
||||
{{ msg.senderName || msg.sender }}
|
||||
</span>
|
||||
@if (msg.spam) {
|
||||
<span class="px-2 py-0.5 text-xs rounded-full bg-synth-yellow/20 text-synth-yellow font-mono">
|
||||
<span class="px-2 py-0.5 text-xs rounded-full bg-yellow-500/20 text-yellow-400 font-mono">
|
||||
SPAM
|
||||
</span>
|
||||
}
|
||||
@if (msg.flagged) {
|
||||
<span class="text-synth-yellow text-xs">★</span>
|
||||
<span class="text-yellow-400 text-xs">★</span>
|
||||
}
|
||||
</div>
|
||||
<div class="text-sm text-synth-cyan font-rajdhani truncate group-hover:text-synth-pink transition-colors">
|
||||
<div class="text-sm text-cyan-400 font-rajdhani truncate group-hover:text-pink-400 transition-colors">
|
||||
{{ msg.subject || '(No subject)' }}
|
||||
</div>
|
||||
<div class="text-xs text-slate-400 font-mono truncate">
|
||||
@@ -80,7 +80,7 @@ import { of } from 'rxjs';
|
||||
{{ msg.sentAt | date:'MMM d, HH:mm' }}
|
||||
</div>
|
||||
@if (msg.hasAttachments) {
|
||||
<span class="text-xs text-synth-purple font-mono">📎 {{ msg.attachmentCount }}</span>
|
||||
<span class="text-xs text-purple-400 font-mono">📎 {{ msg.attachmentCount }}</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,19 +94,19 @@ import { of } from 'rxjs';
|
||||
@if (totalPages() > 1) {
|
||||
<div class="glass-panel p-4 flex items-center justify-center gap-2">
|
||||
<button (click)="goToPage(page() - 1)" [disabled]="page() === 0"
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-synth-cyan border border-synth-cyan/30 hover:bg-synth-cyan/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-cyan-400 border border-cyan-500/30 hover:bg-cyan-500/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
|
||||
← Prev
|
||||
</button>
|
||||
@for (p of pageNumbers; track p) {
|
||||
<button (click)="goToPage(p)"
|
||||
[class.bg-synth-pink/20]="p === page()" [class.text-synth-pink]="p === page()"
|
||||
[class.border-synth-pink]="p === page()"
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-slate-400 border border-synth-cyan/20 hover:bg-synth-cyan/10 hover:text-synth-cyan transition-all">
|
||||
[class.bg-pink-500/20]="p === page()" [class.text-pink-400]="p === page()"
|
||||
[class.border-pink-500]="p === page()"
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-slate-400 border border-cyan-500/20 hover:bg-cyan-500/10 hover:text-cyan-300 transition-all">
|
||||
{{ p + 1 }}
|
||||
</button>
|
||||
}
|
||||
<button (click)="goToPage(page() + 1)" [disabled]="page() >= totalPages() - 1"
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-synth-cyan border border-synth-cyan/30 hover:bg-synth-cyan/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
|
||||
class="px-3 py-1 rounded-lg text-xs font-mono text-cyan-400 border border-cyan-500/30 hover:bg-cyan-500/10 disabled:opacity-30 disabled:cursor-not-allowed transition-all">
|
||||
Next →
|
||||
</button>
|
||||
<span class="text-xs font-mono text-slate-500 ml-2">
|
||||
|
||||
@@ -1,49 +1,93 @@
|
||||
import { Component, inject, signal } from '@angular/core';
|
||||
import { Component, inject, signal, effect } from '@angular/core';
|
||||
import { RouterOutlet, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { AuthService } from '../../services/auth.service';
|
||||
import { MailService } from '../../services/mail.service';
|
||||
import { Folder } from '../../models/mail.models';
|
||||
|
||||
const THEMES = [
|
||||
{ value: 'theme-cyber-magenta', label: '💖 Cyber Magenta' },
|
||||
{ value: 'theme-neon-cyan', label: '🩵 Neon Cyan' },
|
||||
{ value: 'theme-sunset-orange', label: '🧡 Sunset Orange' },
|
||||
{ value: 'theme-matrix-green', label: '💚 Matrix Green' },
|
||||
];
|
||||
|
||||
@Component({
|
||||
selector: 'app-layout',
|
||||
standalone: true,
|
||||
imports: [RouterOutlet, RouterLink, RouterLinkActive],
|
||||
template: `
|
||||
<div class="min-h-screen relative" [class.light-theme]="isLightTheme()">
|
||||
<!-- Synthwave фон -->
|
||||
<div class="synth-bg" aria-hidden="true">
|
||||
<div #root class="min-h-screen relative theme-cyber-magenta" [class.light-theme]="isLightTheme()" [class.high-contrast]="isHighContrast()">
|
||||
<!-- Synthwave анимированный фон -->
|
||||
<div class="synth-stage" aria-hidden="true">
|
||||
<div class="synth-sun"></div>
|
||||
<div class="synth-grid">
|
||||
<div class="synth-grid-plane"></div>
|
||||
<div class="synth-mountains"></div>
|
||||
<div class="grid-container">
|
||||
<div class="grid-plane"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Контент -->
|
||||
<div class="relative z-10 flex flex-col min-h-screen">
|
||||
<!-- Шапка -->
|
||||
<header class="glass-panel rounded-none border-t-0 border-x-0 p-4 sticky top-0 z-40 backdrop-blur-xl">
|
||||
<div class="max-w-7xl mx-auto flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-synth-pink to-synth-cyan flex items-center justify-center text-synth-dark font-black text-xl font-orbitron shadow-[0_0_15px_rgba(255,0,127,0.8)]">
|
||||
<header class="p-4 lg:p-6 border-b border-cyan-500/20 glass-panel rounded-none border-t-0 border-x-0 sticky top-0 z-40 backdrop-blur-xl">
|
||||
<div class="max-w-7xl mx-auto flex flex-col md:flex-row items-center justify-between gap-4">
|
||||
|
||||
<!-- Логотип -->
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="w-10 h-10 rounded-lg bg-gradient-to-br from-pink-500 to-cyan-400 flex items-center justify-center text-slate-950 font-black text-xl shadow-[0_0_15px_rgba(255,0,127,0.8)] font-orbitron">
|
||||
M
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-2xl font-orbitron font-extrabold tracking-wider neon-text-primary">
|
||||
MAIL<span class="text-synth-cyan font-normal">SERVER</span>
|
||||
<h1 class="text-2xl font-extrabold font-orbitron tracking-wider neon-text-primary">
|
||||
MAIL<span class="text-cyan-400 font-normal">SERVER</span>
|
||||
</h1>
|
||||
<p class="text-xs text-synth-cyan/70 font-mono tracking-widest uppercase">Synthwave Edition</p>
|
||||
<p class="text-xs text-cyan-300/70 font-mono tracking-widest uppercase">Synthwave Edition</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<!-- Переключатель темы -->
|
||||
<button (click)="toggleTheme()" class="cyber-btn px-3 py-2 rounded-lg text-xs font-bold" [title]="isLightTheme() ? 'Переключить на тёмную тему' : 'Переключить на светлую тему'">
|
||||
<!-- Статистика -->
|
||||
<div class="flex items-center space-x-4 bg-slate-950/60 px-4 py-2 rounded-full border border-pink-500/30 text-xs font-mono">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span class="w-2 h-2 rounded-full bg-emerald-400 animate-ping"></span>
|
||||
<span class="text-slate-300">SMTP: <span class="text-emerald-400 font-bold">ONLINE</span></span>
|
||||
</div>
|
||||
<span class="text-slate-600">|</span>
|
||||
<div class="text-slate-300">User: <span class="text-cyan-400 font-bold">{{ email }}</span></div>
|
||||
<span class="text-slate-600">|</span>
|
||||
<div class="text-slate-300">Folders: <span class="text-pink-400 font-bold">{{ folders().length }}</span></div>
|
||||
</div>
|
||||
|
||||
<!-- Контроли -->
|
||||
<div class="flex items-center space-x-3">
|
||||
<!-- Выбор цветовой темы -->
|
||||
<div class="relative">
|
||||
<select #themeSelect (change)="onThemeChange(themeSelect.value)"
|
||||
class="bg-slate-900/90 text-cyan-300 border border-cyan-500/40 rounded-lg px-3 py-1.5 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 cursor-pointer">
|
||||
@for (theme of themes; track theme.value) {
|
||||
<option [value]="theme.value" [selected]="currentTheme() === theme.value">
|
||||
{{ theme.label }}
|
||||
</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- High Contrast -->
|
||||
<button (click)="toggleHighContrast()"
|
||||
[attr.aria-pressed]="isHighContrast()"
|
||||
title="Toggle High Contrast Mode"
|
||||
class="px-3 py-1.5 rounded-lg border border-cyan-500/40 bg-slate-900/80 text-xs font-mono hover:bg-cyan-500/20 focus:outline-none focus:ring-2 focus:ring-pink-500 transition-all flex items-center gap-1.5">
|
||||
<span class="text-yellow-400">◐</span>
|
||||
<span>Contrast</span>
|
||||
</button>
|
||||
|
||||
<!-- Light/Dark -->
|
||||
<button (click)="toggleTheme()" class="cyber-btn px-3 py-1.5 rounded-lg text-xs font-bold">
|
||||
{{ isLightTheme() ? '🌙 Dark' : '☀️ Light' }}
|
||||
</button>
|
||||
|
||||
<span class="text-sm font-mono text-slate-400">{{ email }}</span>
|
||||
<button (click)="onLogout()" class="cyber-btn px-4 py-2 rounded-lg text-xs font-bold">
|
||||
<i class="mr-1">⏻</i> Logout
|
||||
<!-- Logout -->
|
||||
<button (click)="onLogout()" class="cyber-btn px-4 py-1.5 rounded-lg text-xs font-bold">
|
||||
⏻ Logout
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -51,21 +95,21 @@ import { Folder } from '../../models/mail.models';
|
||||
|
||||
<!-- Основная область -->
|
||||
<div class="flex flex-1 max-w-7xl mx-auto w-full p-4 gap-4">
|
||||
<!-- Боковая панель с папками -->
|
||||
<!-- Боковая панель -->
|
||||
<aside class="w-64 flex-shrink-0">
|
||||
<div class="glass-panel p-4">
|
||||
<h2 class="text-sm font-orbitron font-bold text-synth-cyan mb-3 flex items-center gap-2">
|
||||
<span class="text-synth-pink">📁</span> FOLDERS
|
||||
<h2 class="text-sm font-orbitron font-bold text-cyan-300 mb-3 flex items-center gap-2">
|
||||
<span class="text-pink-500">📁</span> FOLDERS
|
||||
</h2>
|
||||
<nav class="space-y-1">
|
||||
@for (folder of folders(); track folder.id) {
|
||||
<a routerLink="/inbox" [queryParams]="{folderId: folder.id}"
|
||||
routerLinkActive="bg-synth-pink/20 text-synth-pink border-synth-pink"
|
||||
[queryParamsHandling]=" 'merge'"
|
||||
class="block px-3 py-2 rounded-lg text-sm font-rajdhani text-slate-300 hover:bg-synth-cyan/10 hover:text-synth-cyan border border-transparent transition-all">
|
||||
routerLinkActive="bg-pink-500/20 text-pink-400 border-pink-500"
|
||||
[queryParamsHandling]="'merge'"
|
||||
class="block px-3 py-2 rounded-lg text-sm font-rajdhani text-slate-300 hover:bg-cyan-500/10 hover:text-cyan-300 border border-transparent transition-all">
|
||||
{{ folder.name }}
|
||||
@if (folder.unreadCount > 0) {
|
||||
<span class="ml-2 px-2 py-0.5 text-xs rounded-full bg-synth-pink/30 text-synth-pink font-mono">
|
||||
<span class="ml-2 px-2 py-0.5 text-xs rounded-full bg-pink-500/30 text-pink-400 font-mono">
|
||||
{{ folder.unreadCount }}
|
||||
</span>
|
||||
}
|
||||
@@ -77,8 +121,8 @@ import { Folder } from '../../models/mail.models';
|
||||
<!-- Контакты -->
|
||||
<div class="glass-panel p-4 mt-4">
|
||||
<a routerLink="/contacts"
|
||||
routerLinkActive="bg-synth-cyan/20 text-synth-cyan border-synth-cyan"
|
||||
class="block px-3 py-2 rounded-lg text-sm font-rajdhani text-slate-300 hover:bg-synth-cyan/10 hover:text-synth-cyan border border-transparent transition-all">
|
||||
routerLinkActive="bg-cyan-500/20 text-cyan-300 border-cyan-500"
|
||||
class="block px-3 py-2 rounded-lg text-sm font-rajdhani text-slate-300 hover:bg-cyan-500/10 hover:text-cyan-300 border border-transparent transition-all">
|
||||
👥 Contacts
|
||||
</a>
|
||||
</div>
|
||||
@@ -96,6 +140,17 @@ import { Folder } from '../../models/mail.models';
|
||||
<router-outlet />
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Футер -->
|
||||
<footer class="p-4 border-t border-cyan-500/20 glass-panel rounded-none border-b-0 border-x-0 mt-6 text-center text-xs font-mono text-slate-400">
|
||||
<div class="max-w-7xl mx-auto flex flex-col sm:flex-row items-center justify-between gap-2">
|
||||
<div>MAILSERVER SYNTHWAVE © 2026</div>
|
||||
<div class="flex items-center space-x-4">
|
||||
<span class="text-cyan-400">◉ A11Y READY</span>
|
||||
<span class="text-pink-400">⚡ HIGH PERF CSS3D</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
@@ -108,15 +163,38 @@ export default class LayoutComponent {
|
||||
email = this.authService.getEmail() || '';
|
||||
folders = signal<Folder[]>([]);
|
||||
isLightTheme = signal(false);
|
||||
isHighContrast = signal(false);
|
||||
currentTheme = signal('theme-cyber-magenta');
|
||||
themes = THEMES;
|
||||
|
||||
constructor() {
|
||||
this.loadFolders();
|
||||
// Загружаем сохранённую тему
|
||||
const saved = localStorage.getItem('theme');
|
||||
if (saved === 'light') {
|
||||
// Загружаем сохранённые настройки
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme === 'light') {
|
||||
this.isLightTheme.set(true);
|
||||
document.documentElement.classList.add('light-theme');
|
||||
}
|
||||
const savedPalette = localStorage.getItem('palette');
|
||||
if (savedPalette) {
|
||||
this.currentTheme.set(savedPalette);
|
||||
}
|
||||
const savedContrast = localStorage.getItem('highContrast');
|
||||
if (savedContrast === 'true') {
|
||||
this.isHighContrast.set(true);
|
||||
}
|
||||
|
||||
// Применяем тему при изменении
|
||||
effect(() => {
|
||||
const root = document.documentElement;
|
||||
// Удаляем все theme классы
|
||||
THEMES.forEach(t => root.classList.remove(t.value));
|
||||
root.classList.add(this.currentTheme());
|
||||
});
|
||||
}
|
||||
|
||||
onThemeChange(theme: string): void {
|
||||
this.currentTheme.set(theme);
|
||||
localStorage.setItem('palette', theme);
|
||||
}
|
||||
|
||||
toggleTheme(): void {
|
||||
@@ -131,6 +209,18 @@ export default class LayoutComponent {
|
||||
}
|
||||
}
|
||||
|
||||
toggleHighContrast(): void {
|
||||
const hc = !this.isHighContrast();
|
||||
this.isHighContrast.set(hc);
|
||||
if (hc) {
|
||||
document.documentElement.classList.add('high-contrast');
|
||||
localStorage.setItem('highContrast', 'true');
|
||||
} else {
|
||||
document.documentElement.classList.remove('high-contrast');
|
||||
localStorage.setItem('highContrast', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
loadFolders(): void {
|
||||
this.mailService.getFolders().subscribe({
|
||||
next: (folders) => this.folders.set(folders),
|
||||
|
||||
@@ -9,58 +9,59 @@ import { Router } from '@angular/router';
|
||||
standalone: true,
|
||||
imports: [RouterLink, FormsModule],
|
||||
template: `
|
||||
<div class="min-h-screen relative flex items-center justify-center">
|
||||
<!-- Synthwave фон -->
|
||||
<div class="synth-bg" aria-hidden="true">
|
||||
<div class="min-h-screen relative flex items-center justify-center theme-cyber-magenta">
|
||||
<!-- Synthwave анимированный фон -->
|
||||
<div class="synth-stage" aria-hidden="true">
|
||||
<div class="synth-sun"></div>
|
||||
<div class="synth-grid">
|
||||
<div class="synth-grid-plane"></div>
|
||||
<div class="synth-mountains"></div>
|
||||
<div class="grid-container">
|
||||
<div class="grid-plane"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Форма логина -->
|
||||
<div class="relative z-10 w-full max-w-md px-4">
|
||||
<div class="glass-panel p-8">
|
||||
<div class="glass-panel p-8 border-2 border-cyan-400 shadow-[0_0_50px_rgba(0,240,255,0.4)]">
|
||||
<div class="text-center mb-8">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-gradient-to-br from-synth-pink to-synth-cyan flex items-center justify-center text-synth-dark font-black text-2xl font-orbitron shadow-[0_0_20px_rgba(255,0,127,0.8)] mb-4">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-gradient-to-br from-pink-500 to-cyan-400 flex items-center justify-center text-slate-950 font-black text-2xl font-orbitron shadow-[0_0_20px_rgba(255,0,127,0.8)] mb-4">
|
||||
M
|
||||
</div>
|
||||
<h1 class="text-3xl font-orbitron font-extrabold tracking-wider neon-text-primary mb-2">
|
||||
MAIL<span class="text-synth-cyan font-normal">SERVER</span>
|
||||
<h1 class="text-3xl font-extrabold font-orbitron tracking-wider neon-text-primary mb-2">
|
||||
MAIL<span class="text-cyan-400 font-normal">SERVER</span>
|
||||
</h1>
|
||||
<p class="text-sm text-slate-400 font-mono">Sign in to your mailbox</p>
|
||||
<p class="text-sm text-cyan-300/70 font-mono tracking-widest uppercase">Synthwave Edition</p>
|
||||
</div>
|
||||
|
||||
@if (error) {
|
||||
<div class="mb-4 p-3 rounded-lg bg-synth-pink/20 border border-synth-pink/40 text-synth-pink text-sm font-mono">
|
||||
<div class="mb-4 p-3 rounded-lg bg-pink-500/20 border border-pink-500/40 text-pink-400 text-sm font-mono">
|
||||
{{ error }}
|
||||
</div>
|
||||
}
|
||||
|
||||
<form (ngSubmit)="onLogin()" class="space-y-4">
|
||||
<div>
|
||||
<label for="email" class="block text-xs font-mono text-synth-cyan mb-1">EMAIL</label>
|
||||
<label for="email" class="block text-xs font-mono text-pink-400 mb-1">EMAIL</label>
|
||||
<input id="email" type="email" [(ngModel)]="email" name="email" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="user@example.com">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-xs font-mono text-synth-cyan mb-1">PASSWORD</label>
|
||||
<label for="password" class="block text-xs font-mono text-pink-400 mb-1">PASSWORD</label>
|
||||
<input id="password" type="password" [(ngModel)]="password" name="password" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="••••••••">
|
||||
</div>
|
||||
|
||||
<button type="submit" [disabled]="loading"
|
||||
class="cyber-btn w-full py-3 rounded-xl text-sm font-bold mt-6">
|
||||
{{ loading ? 'CONNECTING...' : 'LOGIN' }}
|
||||
{{ loading ? '⏳ CONNECTING...' : '⚡ LOGIN' }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-sm text-slate-400 mt-6">
|
||||
<p class="text-center text-sm text-slate-400 mt-6 font-rajdhani">
|
||||
No account?
|
||||
<a routerLink="/register" class="text-synth-cyan hover:text-synth-pink font-mono transition-colors">
|
||||
<a routerLink="/register" class="text-cyan-400 hover:text-pink-400 font-mono transition-colors">
|
||||
Register here
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -13,24 +13,24 @@ import { Message } from '../../models/mail.models';
|
||||
@if (message) {
|
||||
<div class="glass-panel p-6">
|
||||
<!-- Заголовок письма -->
|
||||
<div class="mb-6 pb-4 border-b border-synth-cyan/20">
|
||||
<div class="mb-6 pb-4 border-b border-cyan-500/20">
|
||||
<h1 class="text-xl font-orbitron font-bold neon-text-secondary mb-3">
|
||||
{{ message.subject || '(No subject)' }}
|
||||
</h1>
|
||||
|
||||
<div class="flex items-center gap-4 text-sm font-mono">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-synth-cyan">FROM:</span>
|
||||
<span class="text-cyan-500">FROM:</span>
|
||||
<span class="text-slate-200">{{ message.senderName || message.sender }}</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-synth-cyan">DATE:</span>
|
||||
<span class="text-cyan-500">DATE:</span>
|
||||
<span class="text-slate-200">{{ message.sentAt | date:'MMM d, y, HH:mm' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (message.spam) {
|
||||
<div class="mt-3 px-3 py-1.5 inline-block rounded-full bg-synth-yellow/20 border border-synth-yellow/40 text-synth-yellow text-xs font-mono">
|
||||
<div class="mt-3 px-3 py-1.5 inline-block rounded-full bg-yellow-500/20 border border-yellow-500/40 text-yellow-500 text-xs font-mono">
|
||||
⚠️ MARKED AS SPAM
|
||||
</div>
|
||||
}
|
||||
@@ -45,8 +45,8 @@ import { Message } from '../../models/mail.models';
|
||||
|
||||
<!-- Вложения -->
|
||||
@if (message.hasAttachments) {
|
||||
<div class="mb-6 p-4 rounded-xl bg-synth-darker/60 border border-synth-purple/30">
|
||||
<h3 class="text-sm font-orbitron font-bold text-synth-purple mb-3">
|
||||
<div class="mb-6 p-4 rounded-xl bg-slate-950/60 border border-purple-500/30">
|
||||
<h3 class="text-sm font-orbitron font-bold text-purple-500 mb-3">
|
||||
📎 ATTACHMENTS ({{ message.attachmentCount }})
|
||||
</h3>
|
||||
<p class="text-xs text-slate-400 font-mono">
|
||||
@@ -56,19 +56,19 @@ import { Message } from '../../models/mail.models';
|
||||
}
|
||||
|
||||
<!-- Действия -->
|
||||
<div class="flex gap-3 pt-4 border-t border-synth-cyan/20">
|
||||
<div class="flex gap-3 pt-4 border-t border-cyan-500/20">
|
||||
<a routerLink="/inbox" class="cyber-btn px-6 py-2 rounded-xl text-xs font-bold">
|
||||
← BACK TO INBOX
|
||||
</a>
|
||||
<a [routerLink]="['/compose']" [queryParams]="{replyTo: message.sender, subject: 'Re: ' + (message.subject || '')}"
|
||||
class="px-6 py-2 rounded-xl text-xs font-mono text-synth-cyan border border-synth-cyan/40 hover:bg-synth-cyan/20 transition-all">
|
||||
class="px-6 py-2 rounded-xl text-xs font-mono text-cyan-500 border border-cyan-500/40 hover:bg-cyan-500/20 transition-all">
|
||||
↩️ REPLY
|
||||
</a>
|
||||
<a [routerLink]="['/compose']" [queryParams]="{forwardTo: '', forwardSubject: 'Fwd: ' + (message.subject || ''), forwardBody: message.body}"
|
||||
class="px-6 py-2 rounded-xl text-xs font-mono text-synth-purple border border-synth-purple/40 hover:bg-synth-purple/20 transition-all">
|
||||
class="px-6 py-2 rounded-xl text-xs font-mono text-purple-500 border border-purple-500/40 hover:bg-purple-500/20 transition-all">
|
||||
➡️ FORWARD
|
||||
</a>
|
||||
<button (click)="onDelete()" class="px-6 py-2 rounded-xl text-xs font-mono text-synth-pink border border-synth-pink/40 hover:bg-synth-pink/20 transition-all">
|
||||
<button (click)="onDelete()" class="px-6 py-2 rounded-xl text-xs font-mono text-pink-500 border border-pink-500/40 hover:bg-pink-500/20 transition-all">
|
||||
🗑️ DELETE
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -9,70 +9,71 @@ import { Router } from '@angular/router';
|
||||
standalone: true,
|
||||
imports: [RouterLink, FormsModule],
|
||||
template: `
|
||||
<div class="min-h-screen relative flex items-center justify-center">
|
||||
<!-- Synthwave фон -->
|
||||
<div class="synth-bg" aria-hidden="true">
|
||||
<div class="min-h-screen relative flex items-center justify-center theme-cyber-magenta">
|
||||
<!-- Synthwave анимированный фон -->
|
||||
<div class="synth-stage" aria-hidden="true">
|
||||
<div class="synth-sun"></div>
|
||||
<div class="synth-grid">
|
||||
<div class="synth-grid-plane"></div>
|
||||
<div class="synth-mountains"></div>
|
||||
<div class="grid-container">
|
||||
<div class="grid-plane"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Форма регистрации -->
|
||||
<div class="relative z-10 w-full max-w-md px-4">
|
||||
<div class="glass-panel p-8">
|
||||
<div class="glass-panel p-8 border-2 border-cyan-400 shadow-[0_0_50px_rgba(0,240,255,0.4)]">
|
||||
<div class="text-center mb-8">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-gradient-to-br from-synth-pink to-synth-cyan flex items-center justify-center text-synth-dark font-black text-2xl font-orbitron shadow-[0_0_20px_rgba(255,0,127,0.8)] mb-4">
|
||||
<div class="w-16 h-16 mx-auto rounded-xl bg-gradient-to-br from-pink-500 to-cyan-400 flex items-center justify-center text-slate-950 font-black text-2xl font-orbitron shadow-[0_0_20px_rgba(255,0,127,0.8)] mb-4">
|
||||
M
|
||||
</div>
|
||||
<h1 class="text-3xl font-orbitron font-extrabold tracking-wider neon-text-primary mb-2">
|
||||
MAIL<span class="text-synth-cyan font-normal">SERVER</span>
|
||||
<h1 class="text-3xl font-extrabold font-orbitron tracking-wider neon-text-primary mb-2">
|
||||
MAIL<span class="text-cyan-400 font-normal">SERVER</span>
|
||||
</h1>
|
||||
<p class="text-sm text-slate-400 font-mono">Create your mailbox</p>
|
||||
<p class="text-sm text-cyan-300/70 font-mono tracking-widest uppercase">Create your mailbox</p>
|
||||
</div>
|
||||
|
||||
@if (error) {
|
||||
<div class="mb-4 p-3 rounded-lg bg-synth-pink/20 border border-synth-pink/40 text-synth-pink text-sm font-mono">
|
||||
<div class="mb-4 p-3 rounded-lg bg-pink-500/20 border border-pink-500/40 text-pink-400 text-sm font-mono">
|
||||
{{ error }}
|
||||
</div>
|
||||
}
|
||||
@if (success) {
|
||||
<div class="mb-4 p-3 rounded-lg bg-synth-cyan/20 border border-synth-cyan/40 text-synth-cyan text-sm font-mono">
|
||||
Account created! You can now login.
|
||||
<div class="mb-4 p-3 rounded-lg bg-cyan-500/20 border border-cyan-500/40 text-cyan-400 text-sm font-mono">
|
||||
Account created! Redirecting to login...
|
||||
</div>
|
||||
}
|
||||
|
||||
<form (ngSubmit)="onRegister()" class="space-y-4">
|
||||
<div>
|
||||
<label for="displayName" class="block text-xs font-mono text-synth-cyan mb-1">DISPLAY NAME</label>
|
||||
<label for="displayName" class="block text-xs font-mono text-pink-400 mb-1">DISPLAY NAME</label>
|
||||
<input id="displayName" type="text" [(ngModel)]="displayName" name="displayName" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="John Doe">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="email" class="block text-xs font-mono text-synth-cyan mb-1">EMAIL</label>
|
||||
<label for="email" class="block text-xs font-mono text-pink-400 mb-1">EMAIL</label>
|
||||
<input id="email" type="email" [(ngModel)]="email" name="email" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="user@example.com">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password" class="block text-xs font-mono text-synth-cyan mb-1">PASSWORD</label>
|
||||
<label for="password" class="block text-xs font-mono text-pink-400 mb-1">PASSWORD</label>
|
||||
<input id="password" type="password" [(ngModel)]="password" name="password" required
|
||||
class="w-full bg-synth-darker/80 border border-synth-cyan/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-synth-pink focus:border-synth-cyan transition-all"
|
||||
class="w-full bg-slate-950/80 border border-cyan-500/40 rounded-xl px-4 py-3 text-sm text-slate-200 font-mono focus:outline-none focus:ring-2 focus:ring-pink-500 focus:border-cyan-400 transition-all"
|
||||
placeholder="••••••••">
|
||||
</div>
|
||||
|
||||
<button type="submit" [disabled]="loading"
|
||||
class="cyber-btn w-full py-3 rounded-xl text-sm font-bold mt-6">
|
||||
{{ loading ? 'CREATING...' : 'REGISTER' }}
|
||||
{{ loading ? '⏳ CREATING...' : '⚡ REGISTER' }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<p class="text-center text-sm text-slate-400 mt-6">
|
||||
<p class="text-center text-sm text-slate-400 mt-6 font-rajdhani">
|
||||
Already have an account?
|
||||
<a routerLink="/login" class="text-synth-cyan hover:text-synth-pink font-mono transition-colors">
|
||||
<a routerLink="/login" class="text-cyan-400 hover:text-pink-400 font-mono transition-colors">
|
||||
Login here
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user