import { Component, inject, signal } from '@angular/core'; import { CommonModule } from '@angular/common'; import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { Actions } from '@ngrx/effects'; import { Store } from '@ngrx/store'; import { NgIcon, provideIcons } from '@ng-icons/core'; import { lucideUserPlus } from '@ng-icons/lucide'; import { firstValueFrom } from 'rxjs'; import { AuthenticationService } from '../../application/services/authentication.service'; import { ServerDirectoryFacade } from '../../../server-directory'; import { buildLoginReturnQueryParams, resolveSafeReturnUrl, waitForAuthenticationOutcome } from '../../domain/logic/auth-navigation.rules'; import { UsersActions } from '../../../../store/users/users.actions'; import { User } from '../../../../shared-kernel'; import { AppI18nService, APP_TRANSLATE_IMPORTS } from '../../../../core/i18n'; import { AutoFocusDirective, SelectOnFocusDirective } from '../../../../shared/directives'; @Component({ selector: 'app-register', standalone: true, imports: [ CommonModule, FormsModule, NgIcon, AutoFocusDirective, SelectOnFocusDirective, ...APP_TRANSLATE_IMPORTS ], viewProviders: [provideIcons({ lucideUserPlus })], templateUrl: './register.component.html' }) /** * Registration form allowing new users to create an account on a selected server. */ export class RegisterComponent { serversSvc = inject(ServerDirectoryFacade); servers = this.serversSvc.servers; username = ''; displayName = ''; password = ''; serverId: string | undefined = this.serversSvc.activeServer()?.id; error = signal(null); private readonly appI18n = inject(AppI18nService); private auth = inject(AuthenticationService); private actions$ = inject(Actions); private store = inject(Store); private route = inject(ActivatedRoute); private router = inject(Router); /** TrackBy function for server list rendering. */ trackById(_index: number, item: { id: string }) { return item.id; } /** Validate and submit the registration form, then navigate to search on success. */ submit() { this.error.set(null); const sid = this.serverId || this.serversSvc.activeServer()?.id; this.auth.register({ username: this.username.trim(), password: this.password, displayName: this.displayName.trim(), serverId: sid }).subscribe({ next: async (resp) => { if (sid) this.serversSvc.setActiveServer(sid); const homeSignalServerUrl = this.serversSvc.servers().find((server) => server.id === sid)?.url ?? this.serversSvc.activeServer()?.url; const user: User = { id: resp.id, oderId: resp.id, username: resp.username, displayName: resp.displayName, status: 'online', role: 'member', joinedAt: Date.now(), homeSignalServerUrl }; this.store.dispatch(UsersActions.authenticateUser({ user })); const outcome = await firstValueFrom(waitForAuthenticationOutcome(this.actions$)); if (outcome.kind === 'failure') { this.error.set(outcome.error); return; } const returnUrl = resolveSafeReturnUrl(this.route.snapshot.queryParamMap.get('returnUrl')); await this.router.navigateByUrl(returnUrl); }, error: (err) => { this.error.set(err?.error?.error || this.appI18n.instant('auth.register.failed')); } }); } /** Navigate to the login page. */ goLogin() { this.router.navigate(['/login'], { queryParams: buildLoginReturnQueryParams(this.router.url) }); } }