Remove redundant unit tests for CommunityComponent and RanksComponent, enhance community.component with dynamic team member display and toggle functionality, update routing for community links, and set stricter field constraints in team schema.

This commit is contained in:
akastijn 2025-11-08 18:45:03 +01:00
parent 042a6450c2
commit a05a751628
8 changed files with 162 additions and 70 deletions

View File

@ -9,34 +9,74 @@
<main>
<section class="darkmodeSection">
<div class="customContainer">
<h2>Current Nitro Boosters</h2>
<div class="container teamContainer">
<h2 class="sectionTitle">Current Nitro Boosters</h2>
@for (member of getTeamMembers('discord') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Nitro booster</p>
</div>
}
</div>
</section>
<section id="social" class="darkmodeSectionThree">
<div class="container" style="padding: 50px 0 0 0; justify-content: center;">
<div class="container teamContainer">
<h2 class="sectionTitle">Social Media</h2>
@for (member of getTeamMembers('socialmedia') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Social media</p>
</div>
}
</div>
<div style="display: flex; justify-content: center; padding-bottom: 30px;">
<p style="text-align: center;">We're currently not looking for more people to help manage our socials.</p>
</div>
</section>
<section id="crateTeam" class="darkmodeSection">
<div class="container" style="padding: 50px 0 0 0; justify-content: center;">
<div class="container teamContainer">
<h2 class="sectionTitle">Crate Team</h2>
@for (member of getTeamMembers('crate') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Crate team</p>
</div>
}
</div>
</section>
<section class="darkmodeSectionThree">
<div class="container" style="padding: 50px 0 0 0; justify-content: center;">
<div class="container teamContainer">
<h2 class="sectionTitle">Event Leaders</h2>
@for (member of getTeamMembers('eventleader') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Event leaders</p>
</div>
}
</div>
<div style="display: flex; justify-content: center; padding-bottom: 30px;">
<p style="text-align: center;">We're currently not looking for more Event Leaders.</p>
</div>
</section>
<section class="darkmodeSection">
<div class="container" style="padding: 50px 0 0 0; justify-content: center;">
<div class="container teamContainer">
<h2 class="sectionTitle">Event Team</h2>
@for (member of getTeamMembers('eventteam') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Event team</p>
</div>
}
</div>
<div style="display: flex; justify-content: center; padding-bottom: 30px;">
<div style="flex-direction: column;">
@ -47,15 +87,32 @@
</div>
</section>
<section class="darkmodeSectionThree">
<div class="container" style="padding: 50px 0 0 0; justify-content: center;">
<div class="container teamContainer">
<h2 class="sectionTitle">YouTubers & Streamers</h2>
@for (member of getTeamMembers('youtube') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Youtuber</p>
</div>
}
@for (member of getTeamMembers('twitch') | async; track member) {
<div class="member">
<img [ngSrc]="getAvatarUrl(member)" alt="{{member.name}}'s Minecraft skin"
height="160" width="160" style="width: 160px;">
<h2>{{ member.name }}</h2>
<p>Streamer</p>
</div>
}
</div>
<div style="display: flex; justify-content: center; padding-bottom: 30px;">
<div style="flex-direction: column;">
<p style="text-align: center;"><a style="cursor: pointer;" id="reqButton">Show Requirements...</a></p>
<p style="text-align: center;"><a style="cursor: pointer;" (click)="toggleSection('yt-stream-req')"
id="reqButton">{{ getTextForSection('yt-stream-req') }}</a></p>
</div>
</div>
<div id="req" class="hide" style="display: flex; justify-content: center; padding-bottom: 30px;">
<div [hidden]="!isToggled('yt-stream-req')" [class.requirementSection]="isToggled('yt-stream-req')">
<div style="flex-direction: column; justify-content: center; max-width: 800px;">
<p style="text-align: center;"><span style="font-family: 'opensans-bold', sans-serif;">Requirements:</span>
</p>

View File

@ -1,12 +1,32 @@
.customContainer {
width: 80%;
max-width: 1020px;
margin: auto;
padding: 80px 0;
.sectionTitle {
flex: 0 0 100%;
text-align: center;
padding-bottom: 20px;
font-size: 2em;
}
.member {
width: 33%;
min-width: 250px;
padding-bottom: 50px;
text-align: center;
}
.hide {
display: none !important;
.member img {
padding-bottom: 15px;
}
.member p {
font-family: 'opensans-bold', sans-serif;
}
.teamContainer {
padding: 50px 0 0 0;
justify-content: center;
}
.requirementSection {
display: flex;
justify-content: center;
padding-bottom: 30px;
}

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { CommunityComponent } from './community.component';
describe('CommunityComponent', () => {
let component: CommunityComponent;
let fixture: ComponentFixture<CommunityComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CommunityComponent]
})
.compileComponents();
fixture = TestBed.createComponent(CommunityComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,14 +1,66 @@
import {Component} from '@angular/core';
import {Component, inject} from '@angular/core';
import {HeaderComponent} from "@header/header.component";
import {map, Observable, shareReplay} from 'rxjs';
import {Player, TeamService} from '@api';
import {ScrollService} from '@services/scroll.service';
import {AsyncPipe, NgOptimizedImage} from '@angular/common';
@Component({
selector: 'app-community',
imports: [
HeaderComponent
HeaderComponent,
AsyncPipe,
NgOptimizedImage
],
templateUrl: './community.component.html',
styleUrl: './community.component.scss'
})
export class CommunityComponent {
private teamMembersCache: { [key: string]: Observable<Player[]> } = {};
protected scrollService: ScrollService = inject(ScrollService)
protected teamService: TeamService = inject(TeamService)
public getTeamMembers(team: string): Observable<Player[]> {
if (!this.teamMembersCache[team]) {
this.teamMembersCache[team] = this.teamService.getTeamMembers(team).pipe(
map(res => this.removeDuplicates(res)),
shareReplay(1)
);
}
return this.teamMembersCache[team];
}
private removeDuplicates(array: Player[]): Player[] {
return array.filter((player, index, self) =>
index === self.findIndex((p) => p.uuid === player.uuid)
);
}
public getAvatarUrl(entry: Player): string {
let uuid = entry.uuid.replace('-', '');
return `https://crafatar.com/avatars/${uuid}?overlay`;
}
public toggledSections: string[] = [];
public isToggled(section: string) {
return this.toggledSections.includes(section);
}
public toggleSection(section: string) {
if (this.isToggled(section)) {
this.toggledSections = this.toggledSections.filter(s => s !== section);
} else {
this.toggledSections.push(section);
}
}
public getTextForSection(section: string) {
if (this.isToggled(section)) {
return 'Hide Requirements...';
} else {
return 'Show Requirements...';
}
}
}

View File

@ -197,27 +197,32 @@
<tbody>
<tr>
<td data-label="Rank" class="rankTitle">[<span class="rank5">Social Media</span>]</td>
<td data-label="Requirements">See requirements on the <a href="/community.php">Community</a> page</td>
<td data-label="Requirements">See requirements on the <a [routerLink]="['/community']">Community</a> page
</td>
<td data-label="Perks" class="perks">/record<br>/ptime<br>/pweather</td>
</tr>
<tr>
<td data-label="Rank" class="rankTitle">[<span class="rank5">Streamer</span>]</td>
<td data-label="Requirements">See requirements on the <a href="/community.php">Community</a> page</td>
<td data-label="Requirements">See requirements on the <a [routerLink]="['/community']">Community</a> page
</td>
<td data-label="Perks" class="perks">/record<br>/ptime<br>/pweather</td>
</tr>
<tr>
<td data-label="Rank" class="rankTitle">[<span class="rank5">YouTube</span>]</td>
<td data-label="Requirements">See requirements on the <a href="/community.php">Community</a> page</td>
<td data-label="Requirements">See requirements on the <a [routerLink]="['/community']">Community</a> page
</td>
<td data-label="Perks" class="perks">/record<br>/ptime<br>/pweather</td>
</tr>
<tr>
<td data-label="Rank" class="rankTitle">[<span class="rank5">Event Leader</span>]</td>
<td data-label="Requirements">See requirements on the <a href="/community.php">Community</a> page</td>
<td data-label="Requirements">See requirements on the <a [routerLink]="['/community']">Community</a> page
</td>
<td data-label="Perks" class="perks">Build perms on event server</td>
</tr>
<tr>
<td data-label="Rank" class="rankTitle">[<span class="rank5">Event Team</span>]</td>
<td data-label="Requirements">See requirements on the <a href="/community.php">Community</a> page</td>
<td data-label="Requirements">See requirements on the <a [routerLink]="['/community']">Community</a> page
</td>
<td data-label="Perks" class="perks">Build perms on event server</td>
</tr>
</tbody>

View File

@ -1,23 +0,0 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RanksComponent } from './ranks.component';
describe('RanksComponent', () => {
let component: RanksComponent;
let fixture: ComponentFixture<RanksComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [RanksComponent]
})
.compileComponents();
fixture = TestBed.createComponent(RanksComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,10 +1,12 @@
import {Component} from '@angular/core';
import {HeaderComponent} from "@header/header.component";
import {RouterLink} from '@angular/router';
@Component({
selector: 'app-ranks',
imports: [
HeaderComponent
HeaderComponent,
RouterLink
],
templateUrl: './ranks.component.html',
styleUrl: './ranks.component.scss'

View File

@ -12,6 +12,8 @@ getTeam:
description: The group name of the team
schema:
type: string
example: owner
maxLength: 32
responses:
'200':
description: successful operation