import { Component, inject, signal, OnInit } from '@angular/core'; import { ActivatedRoute, RouterLink } from '@angular/router'; import { ApiService } from '../../core/services/api.service'; import { ToastService } from '../../core/services/toast.service'; import { IDomainDetail, IService } from '../../core/types/api.types'; import { CardComponent, CardHeaderComponent, CardTitleComponent, CardDescriptionComponent, CardContentComponent, } from '../../ui/card/card.component'; import { ButtonComponent } from '../../ui/button/button.component'; import { BadgeComponent } from '../../ui/badge/badge.component'; import { TableComponent, TableHeaderComponent, TableBodyComponent, TableRowComponent, TableHeadComponent, TableCellComponent, } from '../../ui/table/table.component'; import { SkeletonComponent } from '../../ui/skeleton/skeleton.component'; @Component({ selector: 'app-domain-detail', standalone: true, imports: [ RouterLink, CardComponent, CardHeaderComponent, CardTitleComponent, CardDescriptionComponent, CardContentComponent, ButtonComponent, BadgeComponent, TableComponent, TableHeaderComponent, TableBodyComponent, TableRowComponent, TableHeadComponent, TableCellComponent, SkeletonComponent, ], template: `
Back to Domains @if (loading() && !domain()) { } @else if (domain()) {

{{ domain()!.domain.domain }}

{{ domain()!.domain.dnsProvider || 'Manual' }} @if (domain()!.domain.defaultWildcard) { Wildcard } @if (domain()!.domain.isObsolete) { Obsolete }
}
@if (domain()) {
Certificates
{{ domain()!.certificates.length }}
Requirements
{{ domain()!.requirements.length }}
Services
{{ domain()!.serviceCount }}
SSL Certificates Active certificates for this domain @if (domain()!.certificates.length === 0) {
No certificates
} @else { Domain Type Status Expires Issuer Actions @for (cert of domain()!.certificates; track cert.id) { {{ cert.certDomain }} {{ cert.isWildcard ? 'Wildcard' : 'Standard' }} {{ getCertStatus(cert) }} {{ formatDate(cert.expiryDate) }} ({{ getDaysRemaining(cert.expiryDate) }} days) {{ cert.issuer }} } }
Services Services using this domain @if (services().length === 0) {
No services using this domain
} @else { Service Domain Status Actions @for (svc of services(); track svc.name) { {{ svc.name }} {{ svc.domain }} {{ svc.status }} } }
}
`, }) export class DomainDetailComponent implements OnInit { private route = inject(ActivatedRoute); private api = inject(ApiService); private toast = inject(ToastService); domain = signal(null); services = signal([]); loading = signal(false); ngOnInit(): void { const domainName = this.route.snapshot.paramMap.get('domain'); if (domainName) { this.loadDomain(domainName); this.loadServices(domainName); } } async loadDomain(name: string): Promise { this.loading.set(true); try { const response = await this.api.getDomainDetail(name); if (response.success && response.data) { this.domain.set(response.data); } } catch { this.toast.error('Failed to load domain'); } finally { this.loading.set(false); } } async loadServices(domainName: string): Promise { try { const response = await this.api.getServices(); if (response.success && response.data) { this.services.set(response.data.filter(s => s.domain?.includes(domainName))); } } catch { // Silent fail } } formatDate(timestamp: number): string { return new Date(timestamp).toLocaleDateString(); } getDaysRemaining(timestamp: number): number { const now = Date.now(); return Math.floor((timestamp - now) / (1000 * 60 * 60 * 24)); } getCertStatus(cert: any): string { if (!cert.isValid) return 'Invalid'; const days = this.getDaysRemaining(cert.expiryDate); if (days < 0) return 'Expired'; if (days <= 30) return 'Expiring'; return 'Valid'; } getCertStatusVariant(cert: any): 'success' | 'warning' | 'destructive' { const status = this.getCertStatus(cert); switch (status) { case 'Valid': return 'success'; case 'Expiring': return 'warning'; default: return 'destructive'; } } async renewCertificate(domain: string): Promise { try { const response = await this.api.renewCertificate(domain); if (response.success) { this.toast.success('Certificate renewal initiated'); } else { this.toast.error(response.error || 'Failed to renew certificate'); } } catch { this.toast.error('Failed to renew certificate'); } } }