diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts index bc1f14c..8807c02 100644 --- a/frontend/src/app/app.routes.ts +++ b/frontend/src/app/app.routes.ts @@ -107,8 +107,12 @@ export const routes: Routes = [ loadComponent: () => import('./pages/reference/staffpowers/staffpowers.component').then(m => m.StaffpowersComponent) }, { - path: 'forms/:form', - loadComponent: () => import('./pages/forms/forms.component').then(m => m.FormsComponent) + path: 'forms/appeal', + loadComponent: () => import('./pages/forms/appeal/appeal.component').then(m => m.AppealComponent), + canActivate: [AuthGuard], + data: { + requiredAuthorizations: ['SCOPE_user'] + } }, { path: 'forms', diff --git a/frontend/src/app/guards/auth.guard.ts b/frontend/src/app/guards/auth.guard.ts index 8259a34..f3f7196 100644 --- a/frontend/src/app/guards/auth.guard.ts +++ b/frontend/src/app/guards/auth.guard.ts @@ -2,6 +2,7 @@ import {Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; import {Observable} from 'rxjs'; import {AuthService} from '@services/auth.service'; +import {environment} from '@environment'; @Injectable({ providedIn: 'root' @@ -18,7 +19,9 @@ export class AuthGuard implements CanActivate { route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable | Promise | boolean | UrlTree { - + if (environment.defaultAuthStatus) { + return true; + } if (!this.authService.checkAuthStatus()) { return this.router.createUrlTree(['/']); } diff --git a/frontend/src/app/pages/forms/appeal/appeal.component.html b/frontend/src/app/pages/forms/appeal/appeal.component.html index 6ca9adc..3dd9cdf 100644 --- a/frontend/src/app/pages/forms/appeal/appeal.component.html +++ b/frontend/src/app/pages/forms/appeal/appeal.component.html @@ -1,5 +1,19 @@ - -
- -
-
+
+ +
+

Appeal

+
+
+
+
+
+
+
+

hi

+
+
+
+
+
+
diff --git a/frontend/src/app/pages/forms/appeal/appeal.component.scss b/frontend/src/app/pages/forms/appeal/appeal.component.scss index e69de29..0e02268 100644 --- a/frontend/src/app/pages/forms/appeal/appeal.component.scss +++ b/frontend/src/app/pages/forms/appeal/appeal.component.scss @@ -0,0 +1,16 @@ +:host { + display: block; +} + +.appeal-container { + display: flex; + flex-direction: column; + min-height: 80vh; +} + +main { + flex: 1; + display: flex; + flex-direction: column; + overflow-y: auto; +} diff --git a/frontend/src/app/pages/forms/appeal/appeal.component.ts b/frontend/src/app/pages/forms/appeal/appeal.component.ts index ac9652c..563a88f 100644 --- a/frontend/src/app/pages/forms/appeal/appeal.component.ts +++ b/frontend/src/app/pages/forms/appeal/appeal.component.ts @@ -1,21 +1,27 @@ -import {Component, OnInit} from '@angular/core'; -import {FormsComponent} from '../forms.component'; +import {AfterViewInit, Component, ElementRef, OnInit, Renderer2} from '@angular/core'; import {FormControl, FormGroup, Validators} from '@angular/forms'; import {AppealsService, MinecraftAppeal} from '@api'; +import {HeaderComponent} from '@header/header.component'; @Component({ selector: 'app-appeal', imports: [ - FormsComponent + HeaderComponent ], templateUrl: './appeal.component.html', styleUrl: './appeal.component.scss' }) -export class AppealComponent implements OnInit { +export class AppealComponent implements OnInit, AfterViewInit { public form: FormGroup; + private resizeObserver: ResizeObserver | null = null; + private boundHandleResize: any; - constructor(private appealApi: AppealsService) { + constructor( + private appealApi: AppealsService, + private elementRef: ElementRef, + private renderer: Renderer2 + ) { this.form = new FormGroup({ username: new FormControl('', {nonNullable: true, validators: [Validators.required]}), punishmentId: new FormControl('', {nonNullable: true, validators: [Validators.required]}), @@ -27,6 +33,62 @@ export class AppealComponent implements OnInit { ngOnInit() { } + ngAfterViewInit() { + this.setupResizeObserver(); + this.updateContainerHeight(); + + this.boundHandleResize = this.handleResize.bind(this); + window.addEventListener('resize', this.boundHandleResize); + + setTimeout(() => this.updateContainerHeight(), 0); + } + + ngOnDestroy() { + if (this.resizeObserver) { + this.resizeObserver.disconnect(); + this.resizeObserver = null; + } + + if (this.boundHandleResize) { + window.removeEventListener('resize', this.boundHandleResize); + } + } + + private handleResize() { + this.updateContainerHeight(); + } + + private setupResizeObserver() { + this.resizeObserver = new ResizeObserver(() => { + this.updateContainerHeight(); + }); + + const headerElement = document.querySelector('app-header'); + if (headerElement) { + this.resizeObserver.observe(headerElement); + } + + const footerElement = document.querySelector('footer'); + if (footerElement) { + this.resizeObserver.observe(footerElement); + } + } + + private updateContainerHeight() { + const headerElement = document.querySelector('app-header'); + const footerElement = document.querySelector('footer'); + + const container = this.elementRef.nativeElement.querySelector('.appeal-container'); + + if (headerElement && footerElement && container) { + const headerHeight = headerElement.getBoundingClientRect().height; + const footerHeight = footerElement.getBoundingClientRect().height; + + const calculatedHeight = `calc(100vh - ${headerHeight}px - ${footerHeight}px)`; + this.renderer.setStyle(container, 'min-height', calculatedHeight); + } + } + public onSubmit() { if (this.form === undefined) { console.error('Form is undefined'); @@ -35,7 +97,6 @@ export class AppealComponent implements OnInit { if (this.form.valid) { this.sendForm() } else { - // Mark all fields as touched to trigger validation display Object.keys(this.form.controls).forEach(field => { const control = this.form!.get(field); if (!(control instanceof FormGroup)) { diff --git a/frontend/src/app/pages/forms/forms.component.html b/frontend/src/app/pages/forms/forms.component.html index 526ce61..29f2061 100644 --- a/frontend/src/app/pages/forms/forms.component.html +++ b/frontend/src/app/pages/forms/forms.component.html @@ -1,18 +1,24 @@ + [overlay_gradient]="0.5">

{{ formTitle }}

- @if (!type) { - @for (formType of FormType | keyvalue; track formType) { - - } - } -
- -
+
+
+
+ +
+
+
diff --git a/frontend/src/app/pages/forms/forms.component.ts b/frontend/src/app/pages/forms/forms.component.ts index 35883a2..7fa00e9 100644 --- a/frontend/src/app/pages/forms/forms.component.ts +++ b/frontend/src/app/pages/forms/forms.component.ts @@ -1,66 +1,17 @@ -import {Component, Input, OnInit} from '@angular/core'; +import {Component, Input} from '@angular/core'; import {HeaderComponent} from '@header/header.component'; -import {MatDialog} from '@angular/material/dialog'; -import {ActivatedRoute} from '@angular/router'; -import {LoginDialogComponent} from '@shared-components/login/login.component'; -import { KeyValuePipe } from '@angular/common'; -import {FormType} from './form_type'; -import {MatButton} from '@angular/material/button'; -import {AuthService} from '@services/auth.service'; +import {RouterLink} from '@angular/router'; @Component({ selector: 'app-forms', imports: [ HeaderComponent, - MatButton, - KeyValuePipe -], + RouterLink + ], templateUrl: './forms.component.html', styleUrl: './forms.component.scss' }) -export class FormsComponent implements OnInit { +export class FormsComponent { @Input() formTitle: string = 'Form'; @Input() currentPage: string = 'forms'; - - public type: FormType | undefined; - - constructor(private authService: AuthService, - private dialog: MatDialog, - private route: ActivatedRoute, - ) { - this.route.paramMap.subscribe(async params => { - const code = params.get('code'); - - if (code) { - this.authService.login(code).subscribe(); - } else if (!this.authService.checkAuthStatus()) { - const dialogRef = this.dialog.open(LoginDialogComponent, { - width: '400px', - disableClose: true - }); - - dialogRef.afterClosed().subscribe(); - } - }); - } - - ngOnInit() { - this.route.paramMap.subscribe(params => { - switch (params.get('form')) { - case FormType.APPEAL: - this.type = FormType.APPEAL; - this.currentPage = 'appeal'; - break; - default: - throw new Error("Invalid type"); - } - }); - } - - protected readonly FormType = FormType; - protected readonly Object = Object; - - public setFormType(formType: FormType) { - this.type = formType; - } } diff --git a/frontend/src/app/services/auth.service.ts b/frontend/src/app/services/auth.service.ts index 5e36b27..7a3044a 100644 --- a/frontend/src/app/services/auth.service.ts +++ b/frontend/src/app/services/auth.service.ts @@ -5,12 +5,13 @@ import {catchError, tap} from 'rxjs/operators'; import {MatSnackBar} from '@angular/material/snack-bar'; import {JwtHelperService} from '@auth0/angular-jwt'; import {JwtClaims} from '@custom-types/jwt_interface' +import {environment} from '@environment'; @Injectable({ providedIn: 'root' }) export class AuthService { - private isAuthenticatedSubject = new BehaviorSubject(false); + private isAuthenticatedSubject = new BehaviorSubject(environment.defaultAuthStatus); public isAuthenticated$ = this.isAuthenticatedSubject.asObservable(); private userClaimsSubject = new BehaviorSubject(null); diff --git a/frontend/src/environments/environment.development.ts b/frontend/src/environments/environment.development.ts index 20608e6..2777fe3 100644 --- a/frontend/src/environments/environment.development.ts +++ b/frontend/src/environments/environment.development.ts @@ -1,4 +1,5 @@ export const environment = { production: false, - apiUrl: 'http://localhost:8080' + apiUrl: 'http://localhost:8080', + defaultAuthStatus: true }; diff --git a/frontend/src/environments/environment.ts b/frontend/src/environments/environment.ts index b1f3f30..8ab7852 100644 --- a/frontend/src/environments/environment.ts +++ b/frontend/src/environments/environment.ts @@ -1,4 +1,5 @@ export const environment = { production: true, - apiUrl: 'https://alttd.com' + apiUrl: 'https://alttd.com', + defaultAuthStatus: false };