Compare commits
No commits in common. "20ec3648c41844b3fe6527915aeae931f5f863f9" and "9311a1ccd6876a0e0800b77596d760e8b1984db6" have entirely different histories.
20ec3648c4
...
9311a1ccd6
|
|
@ -6,161 +6,156 @@
|
||||||
</div>
|
</div>
|
||||||
</app-header>
|
</app-header>
|
||||||
<main>
|
<main>
|
||||||
<app-full-size>
|
<section class="darkmodeSection appeal-container">
|
||||||
<section class="darkmodeSection appeal-container">
|
<div class="form-container">
|
||||||
<div class="form-container">
|
<div class="pages">
|
||||||
<div class="pages">
|
@if (currentPageIndex === 0) {
|
||||||
@if (currentPageIndex === 0) {
|
@if (history()?.length === 0) {
|
||||||
@if (history()?.length === 0) {
|
<section class="formPage">
|
||||||
<section class="formPage">
|
<img ngSrc="/public/img/logos/logo.png" alt="Discord" height="319" width="550"/>
|
||||||
<img ngSrc="/public/img/logos/logo.png" alt="Discord" height="319" width="550"/>
|
<h1>Punishment Appeal</h1>
|
||||||
<h1>Punishment Appeal</h1>
|
<p>You have no punishments to appeal.</p>
|
||||||
<p>You have no punishments to appeal.</p>
|
</section>
|
||||||
</section>
|
} @else {
|
||||||
} @else {
|
<section class="formPage">
|
||||||
<section class="formPage">
|
<img ngSrc="/public/img/logos/logo.png" alt="Discord" height="319" width="550"/>
|
||||||
<img ngSrc="/public/img/logos/logo.png" alt="Discord" height="319" width="550"/>
|
<h1>Punishment Appeal</h1>
|
||||||
<h1>Punishment Appeal</h1>
|
<p>We aim to respond within 48 hours.</p>
|
||||||
<p>We aim to respond within 48 hours.</p>
|
<button mat-raised-button (click)="nextPage()" [disabled]="history() == null">
|
||||||
<button mat-raised-button (click)="nextPage()" [disabled]="history() == null">
|
@if (history() == null) {
|
||||||
@if (history() == null) {
|
<mat-spinner></mat-spinner>
|
||||||
<mat-spinner></mat-spinner>
|
} @else {
|
||||||
} @else {
|
Next
|
||||||
Next
|
}
|
||||||
}
|
</button>
|
||||||
</button>
|
</section>
|
||||||
</section>
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@if (currentPageIndex === 1) {
|
@if (currentPageIndex === 1) {
|
||||||
|
<section class="formPage">
|
||||||
|
<div class="description">
|
||||||
|
<p>You are logged in as <strong>{{ authService.username() }}</strong>. If this is the correct account
|
||||||
|
please continue</p>
|
||||||
|
<br>
|
||||||
|
<p><strong>Notice: </strong> Submitting an appeal is <strong>not</strong> an instant process.
|
||||||
|
We will investigate the punishment you are appealing and respond within 48 hours.</p>
|
||||||
|
<p style="font-style: italic;">Appeals that seem to have been made with
|
||||||
|
little to no effort will be automatically denied.</p>
|
||||||
|
</div>
|
||||||
|
<button mat-raised-button (click)="nextPage()" [disabled]="authService.username() == null">
|
||||||
|
I, {{ authService.username() }}, understand and agree
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (currentPageIndex === 2) {
|
||||||
|
<section class="formPage">
|
||||||
|
<div class="description">
|
||||||
|
<h2>Please select the punishment you want to appeal</h2>
|
||||||
|
</div>
|
||||||
|
<mat-form-field>
|
||||||
|
<mat-label>Punishment</mat-label>
|
||||||
|
<mat-select (valueChange)="onPunishmentSelected($event)">
|
||||||
|
@for (punishment of history(); track punishment) {
|
||||||
|
<mat-option [value]="punishment">{{ punishment.type }} - {{ punishment.reason }}</mat-option>
|
||||||
|
}
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
@if (selectedPunishment() != null) {
|
||||||
|
<button mat-raised-button (click)="nextPage()" [disabled]="selectedPunishment() == null">
|
||||||
|
Appeal {{ selectedPunishment()!.type }}
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
}
|
||||||
|
|
||||||
|
<form [formGroup]="form">
|
||||||
|
@if (currentPageIndex === 3) {
|
||||||
<section class="formPage">
|
<section class="formPage">
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<p>You are logged in as <strong>{{ authService.username() }}</strong>. If this is the correct
|
<h2>Please enter your email.</h2>
|
||||||
account
|
<p style="font-style: italic">It does not have to be your minecraft email. You will have to verify
|
||||||
please continue</p>
|
it</p>
|
||||||
<br>
|
<mat-form-field appearance="fill" style="width: 100%;">
|
||||||
<p><strong>Notice: </strong> Submitting an appeal is <strong>not</strong> an instant process.
|
<mat-label>Email</mat-label>
|
||||||
We will investigate the punishment you are appealing and respond within 48 hours.</p>
|
<input matInput
|
||||||
<p style="font-style: italic;">Appeals that seem to have been made with
|
formControlName="email"
|
||||||
little to no effort will be automatically denied.</p>
|
placeholder="Email">
|
||||||
|
@if (form.controls.email.invalid && form.controls.email.touched) {
|
||||||
|
<mat-error>
|
||||||
|
@if (form.controls.email.errors?.['required']) {
|
||||||
|
Email is required
|
||||||
|
} @else if (form.controls.email.errors?.['email']) {
|
||||||
|
Please enter a valid email address
|
||||||
|
}
|
||||||
|
</mat-error>
|
||||||
|
}
|
||||||
|
</mat-form-field>
|
||||||
|
@if (emailIsValid()) {
|
||||||
|
<div class="valid-email">
|
||||||
|
<ng-container matSuffix>
|
||||||
|
<mat-icon>check</mat-icon>
|
||||||
|
<span>You have validated your email previously, and can continue to the next page!</span>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<button mat-raised-button (click)="nextPage()" [disabled]="authService.username() == null">
|
<button mat-raised-button (click)="validateMailOrNextPage()" [disabled]="form.controls.email.invalid">
|
||||||
I, {{ authService.username() }}, understand and agree
|
Next
|
||||||
</button>
|
</button>
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (currentPageIndex === 2) {
|
@if (currentPageIndex === 4) {
|
||||||
<section class="formPage">
|
<section class="formPage">
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<h2>Please select the punishment you want to appeal</h2>
|
<h2>Why should your {{ selectedPunishment()?.type }} be reduced or removed?</h2>
|
||||||
</div>
|
<p style="font-style: italic">Please take your time writing this, we're more likely to accept an
|
||||||
<mat-form-field>
|
appeal if effort was put into it.</p>
|
||||||
<mat-label>Punishment</mat-label>
|
<mat-form-field appearance="fill" style="width: 100%;">
|
||||||
<mat-select (valueChange)="onPunishmentSelected($event)">
|
<mat-label>Reason</mat-label>
|
||||||
@for (punishment of history(); track punishment) {
|
<textarea matInput formControlName="appeal" placeholder="Reason" rows="6"></textarea>
|
||||||
<mat-option [value]="punishment">{{ punishment.type }} - {{ punishment.reason }}</mat-option>
|
@if (form.controls.appeal.invalid && form.controls.appeal.touched) {
|
||||||
|
<mat-error>
|
||||||
|
@if (form.controls.appeal.errors?.['required']) {
|
||||||
|
Reason is required
|
||||||
|
} @else if (form.controls.appeal.errors?.['minlength']) {
|
||||||
|
Reason must be at least 10 characters
|
||||||
|
}
|
||||||
|
</mat-error>
|
||||||
}
|
}
|
||||||
</mat-select>
|
</mat-form-field>
|
||||||
</mat-form-field>
|
</div>
|
||||||
@if (selectedPunishment() != null) {
|
<button mat-raised-button (click)="onSubmit()" [disabled]="form.invalid">
|
||||||
<button mat-raised-button (click)="nextPage()" [disabled]="selectedPunishment() == null">
|
Submit Appeal
|
||||||
Appeal {{ selectedPunishment()!.type }}
|
</button>
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</section>
|
</section>
|
||||||
}
|
}
|
||||||
|
</form>
|
||||||
<form [formGroup]="form">
|
|
||||||
@if (currentPageIndex === 3) {
|
|
||||||
<section class="formPage">
|
|
||||||
<div class="description">
|
|
||||||
<h2>Please enter your email.</h2>
|
|
||||||
<p style="font-style: italic">It does not have to be your minecraft email. You will have to verify
|
|
||||||
it</p>
|
|
||||||
<mat-form-field appearance="fill" style="width: 100%;">
|
|
||||||
<mat-label>Email</mat-label>
|
|
||||||
<input matInput
|
|
||||||
formControlName="email"
|
|
||||||
placeholder="Email">
|
|
||||||
@if (form.controls.email.invalid && form.controls.email.touched) {
|
|
||||||
<mat-error>
|
|
||||||
@if (form.controls.email.errors?.['required']) {
|
|
||||||
Email is required
|
|
||||||
} @else if (form.controls.email.errors?.['email']) {
|
|
||||||
Please enter a valid email address
|
|
||||||
}
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
@if (emailIsValid()) {
|
|
||||||
<div class="valid-email">
|
|
||||||
<ng-container matSuffix>
|
|
||||||
<mat-icon>check</mat-icon>
|
|
||||||
<span>You have validated your email previously, and can continue to the next page!</span>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<button mat-raised-button (click)="validateMailOrNextPage()"
|
|
||||||
[disabled]="form.controls.email.invalid">
|
|
||||||
Next
|
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (currentPageIndex === 4) {
|
|
||||||
<section class="formPage">
|
|
||||||
<div class="description">
|
|
||||||
<h2>Why should your {{ selectedPunishment()?.type }} be reduced or removed?</h2>
|
|
||||||
<p style="font-style: italic">Please take your time writing this, we're more likely to accept an
|
|
||||||
appeal if effort was put into it.</p>
|
|
||||||
<mat-form-field appearance="fill" style="width: 100%;">
|
|
||||||
<mat-label>Reason</mat-label>
|
|
||||||
<textarea matInput formControlName="appeal" placeholder="Reason" rows="6"></textarea>
|
|
||||||
@if (form.controls.appeal.invalid && form.controls.appeal.touched) {
|
|
||||||
<mat-error>
|
|
||||||
@if (form.controls.appeal.errors?.['required']) {
|
|
||||||
Reason is required
|
|
||||||
} @else if (form.controls.appeal.errors?.['minlength']) {
|
|
||||||
Reason must be at least 10 characters
|
|
||||||
}
|
|
||||||
</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<button mat-raised-button (click)="onSubmit()" [disabled]="form.invalid">
|
|
||||||
Submit Appeal
|
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Navigation dots -->
|
|
||||||
@if (totalPages.length > 1) {
|
|
||||||
<div class="form-navigation">
|
|
||||||
<button mat-icon-button class="nav-button" (click)="previousPage()" [disabled]="isFirstPage()">
|
|
||||||
<mat-icon>navigate_before</mat-icon>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
@for (i of totalPages; track i) {
|
|
||||||
<div
|
|
||||||
class="nav-dot"
|
|
||||||
[class.active]="i === currentPageIndex"
|
|
||||||
(click)="goToPage(i)">
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<button mat-icon-button class="nav-button" (click)="nextPage()" [disabled]="isLastPage()">
|
|
||||||
<mat-icon>navigate_next</mat-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
|
||||||
</app-full-size>
|
<!-- Navigation dots -->
|
||||||
|
@if (totalPages.length > 1) {
|
||||||
|
<div class="form-navigation">
|
||||||
|
<button mat-icon-button class="nav-button" (click)="previousPage()" [disabled]="isFirstPage()">
|
||||||
|
<mat-icon>navigate_before</mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
@for (i of totalPages; track i) {
|
||||||
|
<div
|
||||||
|
class="nav-dot"
|
||||||
|
[class.active]="i === currentPageIndex"
|
||||||
|
(click)="goToPage(i)">
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<button mat-icon-button class="nav-button" (click)="nextPage()" [disabled]="isLastPage()">
|
||||||
|
<mat-icon>navigate_next</mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
.appeal-container {
|
.appeal-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
min-height: 80vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,14 @@
|
||||||
import {Component, computed, inject, OnDestroy, OnInit, signal} from '@angular/core';
|
import {
|
||||||
|
AfterViewInit,
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
ElementRef,
|
||||||
|
inject,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
Renderer2,
|
||||||
|
signal
|
||||||
|
} from '@angular/core';
|
||||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||||
import {AppealsService, EmailEntry, HistoryService, MailService, MinecraftAppeal, PunishmentHistory} from '@api';
|
import {AppealsService, EmailEntry, HistoryService, MailService, MinecraftAppeal, PunishmentHistory} from '@api';
|
||||||
import {HeaderComponent} from '@header/header.component';
|
import {HeaderComponent} from '@header/header.component';
|
||||||
|
|
@ -14,7 +24,6 @@ import {HistoryFormatService} from '@pages/reference/bans/history-format.service
|
||||||
import {MatDialog} from '@angular/material/dialog';
|
import {MatDialog} from '@angular/material/dialog';
|
||||||
import {VerifyMailDialogComponent} from '@pages/forms/verify-mail-dialog/verify-mail-dialog.component';
|
import {VerifyMailDialogComponent} from '@pages/forms/verify-mail-dialog/verify-mail-dialog.component';
|
||||||
import {Router} from '@angular/router';
|
import {Router} from '@angular/router';
|
||||||
import {FullSizeComponent} from '@shared-components/full-size/full-size.component';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-appeal',
|
selector: 'app-appeal',
|
||||||
|
|
@ -28,12 +37,11 @@ import {FullSizeComponent} from '@shared-components/full-size/full-size.componen
|
||||||
MatSelectModule,
|
MatSelectModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
FullSizeComponent,
|
|
||||||
],
|
],
|
||||||
templateUrl: './appeal.component.html',
|
templateUrl: './appeal.component.html',
|
||||||
styleUrl: './appeal.component.scss'
|
styleUrl: './appeal.component.scss'
|
||||||
})
|
})
|
||||||
export class AppealComponent implements OnInit, OnDestroy {
|
export class AppealComponent implements OnInit, OnDestroy, AfterViewInit {
|
||||||
|
|
||||||
private mailService = inject(MailService);
|
private mailService = inject(MailService);
|
||||||
private historyFormatService = inject(HistoryFormatService);
|
private historyFormatService = inject(HistoryFormatService);
|
||||||
|
|
@ -53,7 +61,10 @@ export class AppealComponent implements OnInit, OnDestroy {
|
||||||
protected emailIsValid = signal<boolean>(false);
|
protected emailIsValid = signal<boolean>(false);
|
||||||
protected dialog = inject(MatDialog);
|
protected dialog = inject(MatDialog);
|
||||||
|
|
||||||
constructor() {
|
constructor(
|
||||||
|
private elementRef: ElementRef,
|
||||||
|
private renderer: Renderer2
|
||||||
|
) {
|
||||||
this.form = new FormGroup({
|
this.form = new FormGroup({
|
||||||
email: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.email]}),
|
email: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.email]}),
|
||||||
appeal: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.minLength(10)]})
|
appeal: new FormControl('', {nonNullable: true, validators: [Validators.required, Validators.minLength(10)]})
|
||||||
|
|
@ -86,6 +97,16 @@ export class AppealComponent implements OnInit, OnDestroy {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.setupResizeObserver();
|
||||||
|
this.updateContainerHeight();
|
||||||
|
|
||||||
|
this.boundHandleResize = this.handleResize.bind(this);
|
||||||
|
window.addEventListener('resize', this.boundHandleResize);
|
||||||
|
|
||||||
|
setTimeout(() => this.updateContainerHeight(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
if (this.resizeObserver) {
|
if (this.resizeObserver) {
|
||||||
this.resizeObserver.disconnect();
|
this.resizeObserver.disconnect();
|
||||||
|
|
@ -97,6 +118,41 @@ export class AppealComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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() {
|
public onSubmit() {
|
||||||
if (this.form === undefined) {
|
if (this.form === undefined) {
|
||||||
console.error('Form is undefined');
|
console.error('Form is undefined');
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,8 @@
|
||||||
</div>
|
</div>
|
||||||
</app-header>
|
</app-header>
|
||||||
<main>
|
<main>
|
||||||
<app-full-size>
|
<section class="darkmodeSection">
|
||||||
<section class="darkmodeSection full-height flex">
|
<p>{{ message }}</p>
|
||||||
<div class="margin-auto">
|
</section>
|
||||||
<p>{{ message }}</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</app-full-size>
|
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
import {Component, inject, OnInit} from '@angular/core';
|
import {Component, inject, OnInit} from '@angular/core';
|
||||||
import {Router} from '@angular/router';
|
import {Router} from '@angular/router';
|
||||||
import {FullSizeComponent} from '@shared-components/full-size/full-size.component';
|
|
||||||
import {HeaderComponent} from '@header/header.component';
|
import {HeaderComponent} from '@header/header.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-sent',
|
selector: 'app-sent',
|
||||||
imports: [
|
imports: [
|
||||||
HeaderComponent,
|
HeaderComponent
|
||||||
FullSizeComponent
|
|
||||||
],
|
],
|
||||||
templateUrl: './sent.component.html',
|
templateUrl: './sent.component.html',
|
||||||
styleUrl: './sent.component.scss',
|
styleUrl: './sent.component.scss',
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div class="full-size-container">
|
|
||||||
<ng-content></ng-content>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
:host {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-size-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
@ -1,80 +0,0 @@
|
||||||
import {AfterViewInit, Component, ElementRef, Input, OnDestroy, Renderer2} from '@angular/core';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-full-size',
|
|
||||||
standalone: true,
|
|
||||||
imports: [],
|
|
||||||
templateUrl: './full-size.component.html',
|
|
||||||
styleUrl: './full-size.component.scss'
|
|
||||||
})
|
|
||||||
export class FullSizeComponent implements AfterViewInit, OnDestroy {
|
|
||||||
private resizeObserver: ResizeObserver | null = null;
|
|
||||||
private boundHandleResize: any;
|
|
||||||
|
|
||||||
// Optional extra offset in pixels to subtract from available height
|
|
||||||
@Input() extraOffset: number = 0;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private elementRef: ElementRef,
|
|
||||||
private renderer: Renderer2
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
|
||||||
this.setupResizeObserver();
|
|
||||||
this.updateContainerHeight();
|
|
||||||
|
|
||||||
this.boundHandleResize = this.handleResize.bind(this);
|
|
||||||
window.addEventListener('resize', this.boundHandleResize);
|
|
||||||
|
|
||||||
// Ensure first paint sets correct height
|
|
||||||
setTimeout(() => this.updateContainerHeight(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
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: HTMLElement | null = this.elementRef.nativeElement.querySelector('.full-size-container');
|
|
||||||
|
|
||||||
if (container) {
|
|
||||||
const headerHeight = headerElement ? headerElement.getBoundingClientRect().height : 0;
|
|
||||||
const footerHeight = footerElement ? footerElement.getBoundingClientRect().height : 0;
|
|
||||||
|
|
||||||
const totalOffset = headerHeight + footerHeight + (this.extraOffset || 0);
|
|
||||||
const calculatedHeight = `calc(100vh - ${totalOffset}px)`;
|
|
||||||
this.renderer.setStyle(container, 'height', calculatedHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -479,7 +479,3 @@ main .container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.margin-auto {
|
|
||||||
margin: auto
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user