Skip to content

Commit

Permalink
feat(server): improve interface to deal with large amount of datas + …
Browse files Browse the repository at this point in the history
…improve sharing message
  • Loading branch information
mathieuher committed Jan 5, 2025
1 parent ad578ed commit 696960e
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 152 deletions.
97 changes: 49 additions & 48 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
{
"name": "retroski",
"version": "1.1.2",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "biome lint --write src",
"format": "biome format --write src",
"postbuild": "cp src/.htaccess dist/"
},
"private": true,
"dependencies": {
"@angular/animations": "^19.0.5",
"@angular/common": "^19.0.5",
"@angular/compiler": "^19.0.5",
"@angular/core": "^19.0.5",
"@angular/forms": "^19.0.5",
"@angular/platform-browser": "^19.0.5",
"@angular/platform-browser-dynamic": "^19.0.5",
"@angular/router": "^19.0.5",
"@angular/service-worker": "^19.0.5",
"date-fns": "4.1.0",
"dexie": "^4.0.9",
"excalibur": "0.30.2",
"pocketbase": "0.22.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.0.5",
"@angular/cli": "^19.0.5",
"@angular/compiler-cli": "^19.0.5",
"@biomejs/biome": "1.9.4",
"@types/jasmine": "~5.1.0",
"@types/node": "22.10.2",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.6.3",
"vite": "^5.0.0"
}
}
"name": "retroski",
"version": "1.1.2",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "biome lint --write src",
"format": "biome format --write src",
"postbuild": "cp src/.htaccess dist/",
"preview": "http-server ./dist"
},
"private": true,
"dependencies": {
"@angular/animations": "^19.0.5",
"@angular/common": "^19.0.5",
"@angular/compiler": "^19.0.5",
"@angular/core": "^19.0.5",
"@angular/forms": "^19.0.5",
"@angular/platform-browser": "^19.0.5",
"@angular/platform-browser-dynamic": "^19.0.5",
"@angular/router": "^19.0.5",
"@angular/service-worker": "^19.0.5",
"date-fns": "4.1.0",
"dexie": "^4.0.9",
"excalibur": "0.30.2",
"pocketbase": "0.22.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.15.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^19.0.5",
"@angular/cli": "^19.0.5",
"@angular/compiler-cli": "^19.0.5",
"@biomejs/biome": "1.9.4",
"@types/jasmine": "~5.1.0",
"@types/node": "22.10.2",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.6.3",
"vite": "^5.0.0"
}
}
4 changes: 2 additions & 2 deletions roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
- Improve particles and performance
- Improve skier sprites when turning
- Define new default tracks, records and ghosts
- Improve online data list to match big items list
- Define premium url & link
- Add verification step
- ✔️ ~~Improve online data list to match big items list~~
- ✔️ ~~Add verification step~~
- ✔️ ~~Add password management step~~
- ✔️ ~~Use mailing server~~
- ✔️ ~~Implement async multiplayer~~
Expand Down
28 changes: 28 additions & 0 deletions src/app/common/scss/components.scss
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@
}

.retro-subtitle {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: var(--text-subtitle);
margin-top: 0.5rem;
margin-bottom: 0.25rem;
Expand All @@ -93,6 +96,22 @@
position: sticky;
top: 26px;
background-color: var(--color-surface);

.alternative {
cursor: pointer;
transition: color ease-in-out var(--transition-time);

&:not(:first-child) {
border-left: 1px solid var(--color-tertiary);
padding-left: 0.5rem;
font-size: var(--text-small);
}

&:not(.active) {
color: var(--color-tertiary-light);
font-weight: 300 !important;
}
}
}

.retro-text {
Expand Down Expand Up @@ -280,6 +299,15 @@
}
}

&.inactive {
border: 1px solid var(--color-disabled);
color: var(--color-disabled);

&:hover {
background-color: var(--color-disabled-lightest);
}
}

.icon {
font-size: var(--icon-small);
}
Expand Down
1 change: 1 addition & 0 deletions src/app/common/scss/variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ html {
--color-error-darkest: #700002;
--color-text: var(--color-primary);
--color-disabled: #9c9c9c;
--color-disabled-lightest: #d1d1d1;

--text-font-family: "Kode mono", monospace;
--text-big: 32px;
Expand Down
181 changes: 110 additions & 71 deletions src/app/pages/online-event/online-event.component.html
Original file line number Diff line number Diff line change
@@ -1,83 +1,122 @@
<app-toolbar>
<ng-container ngProjectAs="left-actions">
<app-button-icon
icon="close"
(click)="goBack()"
></app-button-icon>
<app-button-icon icon="close" (click)="goBack()"></app-button-icon>
</ng-container>
</app-toolbar>
<div class="retro-content">
@if (event()) {
<div class="retro-title">Event : <span class="tertiary">{{ event()!.name }}</span></div>
<div class="retro-text">Track : <span class="tertiary">{{ track()?.fullName }}</span></div>
<div class="retro-text">Event type : <span class="tertiary">{{ event()!.racesLimit ? 'Race' : 'Time-attack' }}</span></div>
@if (!event()!.racesLimit) {
<div class="retro-subtitle">Ranking</div>
} @else {
<div class="retro-subtitle">Race final ranking</div>
}
<div class="retro-list">
@for (ranking of rankings(); track ranking; let index = $index) {
<app-ranking-line
[class.current]="ranking.name === user?.name"
[position]="index + 1"
[name]="ranking.name"
[time]="index === 0 ? ranking.formattedTime : ranking.getDiffTime(rankings()![0].time)"
[isDiff]="index > 0"
>
</app-ranking-line>
}
@if (!rankings()) {
<div class="retro-placeholder">Loading ranking</div>
} @else if(!rankings()?.length) {
@if (event()!.racesLimit) {
<div class="retro-placeholder">No riders have finished all races yet</div>
} @else {
<div class="retro-placeholder">No riders have completed a ride yet</div>
}
}
<div class="retro-title">
Event : <span class="tertiary">{{ event()!.name }}</span>
</div>
<div class="retro-text">
Track : <span class="tertiary">{{ track()?.fullName }}</span>
</div>
<div class="retro-text">
Event type :
<span class="tertiary">{{
event()!.racesLimit ? "Race" : "Time-attack"
}}</span>
</div>
<div class="retro-subtitle">
<span
class="alternative"
[class.active]="rankingsDisplay() === 'top'"
(click)="rankingsDisplay.set('top')"
>
Top 10
</span>
<span
class="alternative"
[class.active]="rankingsDisplay() === 'full'"
(click)="rankingsDisplay.set('full')"
>
Full ranking
</span>
</div>
<div class="retro-list">
@for (ranking of (rankingsDisplay() === 'top' ? topRankings() :
rankings()); track ranking; let index = $index) {
<app-ranking-line
[class.current]="ranking.name === user?.name"
[position]="index + 1"
[name]="ranking.name"
[time]="
index === 0
? ranking.formattedTime
: ranking.getDiffTime(rankings()![0].time)
"
[isDiff]="index > 0"
>
</app-ranking-line>
} @if (!rankings()) {
<div class="retro-placeholder">Loading ranking</div>
} @else if(!rankings()?.length) { @if (event()!.racesLimit) {
<div class="retro-placeholder">
No riders have finished all races yet
</div>
<div class="retro-subtitle">All results</div>
<div class="retro-list">
@for (result of results(); track result) {
<app-result-line
[type]="event()!.racesLimit ? 'race' : 'time-attack'"
[rideNumber]="result.rideNumber"
[name]="result.rider"
[time]="result.formattedTime"
[current]="result.rider === user?.name"
></app-result-line>
}
@if (!results()) {
<div class="retro-placeholder">Loading results</div>
} @else if(!results()?.length) {
<div class="retro-placeholder">No results yet</div>
}
</div>
@if (event()!.racesLimit) {
<div class="retro-subtitle">Remaining races
@if (remainingRaces()?.length) {
({{ remainingRaces()?.length }}/{{ event()!.racesLimit }})
}
</div>
@for (race of remainingRaces(); track race; let index = $index) {
<app-result-line
type="race"
[rideNumber]="race"
[current]="index === 0"
[track]="track()?.fullName"
></app-result-line>
}
@if (!remainingRaces()) {
<div class="retro-placeholder">Loading remaining races</div>
} @else if(!remainingRaces()?.length) {
<div class="retro-placeholder">You have completed all races</div>
}
} @else {
<div class="retro-placeholder">No riders have completed a ride yet</div>
} }
</div>
<div class="retro-subtitle">
<span
class="alternative"
[class.active]="resultsDisplay() === 'last'"
(click)="resultsDisplay.set('last')"
>
Last results
</span>
<span
class="alternative"
[class.active]="resultsDisplay() === 'all'"
(click)="resultsDisplay.set('all')"
>
All results
</span>
</div>
<div class="retro-list">
@for (result of (resultsDisplay() === 'last' ? lastResults() :
results()); track result) {
<app-result-line
[type]="event()!.racesLimit ? 'race' : 'time-attack'"
[rideNumber]="result.rideNumber"
[name]="result.rider"
[time]="result.formattedTime"
[current]="result.rider === user?.name"
></app-result-line>
} @if (!results()) {
<div class="retro-placeholder">Loading results</div>
} @else if(!results()?.length) {
<div class="retro-placeholder">No results yet</div>
}
} @else {
<div class="retro-placeholder">Loading event</div>
</div>
@if (event()!.racesLimit) {
<div class="retro-subtitle">
Remaining races @if (remainingRaces()?.length) { ({{
remainingRaces()?.length
}}/{{ event()!.racesLimit }}) }
</div>
@for (race of remainingRaces(); track race; let index = $index) {
<app-result-line
type="race"
[rideNumber]="race"
[current]="index === 0"
[track]="track()?.fullName"
></app-result-line>
} @if (!remainingRaces()) {
<div class="retro-placeholder">Loading remaining races</div>
} @else if(!remainingRaces()?.length) {
<div class="retro-placeholder">You have completed all races</div>
} } } @else {
<div class="retro-placeholder">Loading event</div>
}
</div>
<div class="retro-footer">
<button class="retro-button" routerLink="/online-race/{{ event()?.id }}" [disabled]="event()?.racesLimit && !remainingRaces()?.length">Start riding</button>
<button
class="retro-button"
routerLink="/online-race/{{ event()?.id }}"
[disabled]="event()?.racesLimit && !remainingRaces()?.length"
>
Start riding
</button>
</div>
14 changes: 13 additions & 1 deletion src/app/pages/online-event/online-event.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { ChangeDetectionStrategy, Component, computed, inject, type Signal } from '@angular/core';
import {
ChangeDetectionStrategy,
Component,
computed,
inject,
signal,
type WritableSignal,
type Signal
} from '@angular/core';
import { RankingLineComponent } from '../../common/components/ranking-line/ranking-line.component';
import { ToolbarComponent } from '../../common/components/toolbar/toolbar.component';
import { ButtonIconComponent } from '../../common/components/button-icon/button-icon.component';
Expand Down Expand Up @@ -26,9 +34,13 @@ export class OnlineEventComponent {
protected event: Signal<OnlineEvent | undefined>;
protected track: Signal<Track | undefined>;
protected results: Signal<EventResult[] | undefined>;
protected lastResults = computed(() => this.results()?.slice(0, 10));
protected rankings: Signal<EventRanking[] | undefined>;
protected topRankings = computed(() => this.rankings()?.slice(0, 10));
protected remainingRaces: Signal<number[] | undefined>;
protected user: User | null;
protected rankingsDisplay: WritableSignal<'top' | 'full'> = signal('top');
protected resultsDisplay: WritableSignal<'last' | 'all'> = signal('last');

private eventService = inject(EventService);
private route = inject(ActivatedRoute);
Expand Down
Loading

0 comments on commit 696960e

Please sign in to comment.