mirror of
https://github.com/TomasiDeveloping/PlayerManagement.git
synced 2026-04-16 17:22:21 +00:00
use counter
This commit is contained in:
parent
52f9e85eb5
commit
1b57b8babe
35
Api/Controllers/v1/StatsController.cs
Normal file
35
Api/Controllers/v1/StatsController.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using Application.DataTransferObjects.Stat;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using Asp.Versioning;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
|
namespace Api.Controllers.v1
|
||||||
|
{
|
||||||
|
[Route("api/v{version:apiVersion}/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
[ApiVersion("1.0")]
|
||||||
|
public class StatsController(IStatRepository statRepository, ILogger<StatsController> logger) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet("useCount")]
|
||||||
|
public async Task<ActionResult<AllianceUseToolCount>> GetUseCount(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var useCountResult = await statRepository.GetAllianceUseToolCountAsync(cancellationToken);
|
||||||
|
|
||||||
|
return useCountResult.IsFailure
|
||||||
|
? BadRequest(useCountResult.Error)
|
||||||
|
: Ok(useCountResult.Value);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.LogError(e, "{ErrorMessage}", e.Message);
|
||||||
|
return Problem(
|
||||||
|
detail: $"Failed to process {nameof(GetUseCount)}",
|
||||||
|
statusCode: StatusCodes.Status500InternalServerError,
|
||||||
|
title: "Internal server error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -36,6 +36,7 @@ public static class ApplicationDependencyInjection
|
|||||||
services.AddScoped<IApiKeyRepository, ApiKeyRepository>();
|
services.AddScoped<IApiKeyRepository, ApiKeyRepository>();
|
||||||
services.AddScoped<ICustomEventCategoryRepository, CustomEventCategoryRepository>();
|
services.AddScoped<ICustomEventCategoryRepository, CustomEventCategoryRepository>();
|
||||||
services.AddScoped<ICustomEventLeaderBoardRepository, CustomEventLeaderboardRepository>();
|
services.AddScoped<ICustomEventLeaderBoardRepository, CustomEventLeaderboardRepository>();
|
||||||
|
services.AddScoped<IStatRepository, StatRepository>();
|
||||||
|
|
||||||
|
|
||||||
services.AddTransient<IJwtService, JwtService>();
|
services.AddTransient<IJwtService, JwtService>();
|
||||||
|
|||||||
@ -0,0 +1,6 @@
|
|||||||
|
namespace Application.DataTransferObjects.Stat;
|
||||||
|
|
||||||
|
public class AllianceUseToolCount
|
||||||
|
{
|
||||||
|
public int Amount { get; set; }
|
||||||
|
}
|
||||||
9
Application/Interfaces/IStatRepository.cs
Normal file
9
Application/Interfaces/IStatRepository.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.Stat;
|
||||||
|
|
||||||
|
namespace Application.Interfaces;
|
||||||
|
|
||||||
|
public interface IStatRepository
|
||||||
|
{
|
||||||
|
Task<Result<AllianceUseToolCount>> GetAllianceUseToolCountAsync(CancellationToken cancellationToken);
|
||||||
|
}
|
||||||
20
Application/Repositories/StatRepository.cs
Normal file
20
Application/Repositories/StatRepository.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using Application.Classes;
|
||||||
|
using Application.DataTransferObjects.Stat;
|
||||||
|
using Application.Interfaces;
|
||||||
|
using Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Application.Repositories;
|
||||||
|
|
||||||
|
public class StatRepository(ApplicationContext dbContext) : IStatRepository
|
||||||
|
{
|
||||||
|
public async Task<Result<AllianceUseToolCount>> GetAllianceUseToolCountAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var allianceCount = await dbContext.Alliances.CountAsync(cancellationToken);
|
||||||
|
|
||||||
|
return Result.Success(new AllianceUseToolCount
|
||||||
|
{
|
||||||
|
Amount = allianceCount
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Ui/package-lock.json
generated
19
Ui/package-lock.json
generated
@ -26,6 +26,7 @@
|
|||||||
"bootswatch": "^5.3.3",
|
"bootswatch": "^5.3.3",
|
||||||
"jest-editor-support": "*",
|
"jest-editor-support": "*",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
|
"ngx-countup": "^13.2.0",
|
||||||
"ngx-mask": "^19.0.6",
|
"ngx-mask": "^19.0.6",
|
||||||
"ngx-pagination": "^6.0.3",
|
"ngx-pagination": "^6.0.3",
|
||||||
"ngx-spinner": "^17.0.0",
|
"ngx-spinner": "^17.0.0",
|
||||||
@ -6536,6 +6537,11 @@
|
|||||||
"node": ">= 0.10"
|
"node": ">= 0.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/countup.js": {
|
||||||
|
"version": "2.8.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.2.tgz",
|
||||||
|
"integrity": "sha512-UtRoPH6udaru/MOhhZhI/GZHJKAyAxuKItD2Tr7AbrqrOPBX/uejWBBJt8q86169AMqKkE9h9/24kFWbUk/Bag=="
|
||||||
|
},
|
||||||
"node_modules/critters": {
|
"node_modules/critters": {
|
||||||
"version": "0.0.24",
|
"version": "0.0.24",
|
||||||
"resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz",
|
"resolved": "https://registry.npmjs.org/critters/-/critters-0.0.24.tgz",
|
||||||
@ -10841,6 +10847,19 @@
|
|||||||
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/ngx-countup": {
|
||||||
|
"version": "13.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ngx-countup/-/ngx-countup-13.2.0.tgz",
|
||||||
|
"integrity": "sha512-8HpLinaRAg9qta8P/1BjP7IzVY8USNbn9981StlvYPNshLwZcmSmxKJIuHzE9zTL+y7ILWih2L4SDyJDfsIyVw==",
|
||||||
|
"dependencies": {
|
||||||
|
"countup.js": "^2.3.2",
|
||||||
|
"tslib": "^2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@angular/common": ">=13.0.0",
|
||||||
|
"@angular/core": ">=13.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/ngx-mask": {
|
"node_modules/ngx-mask": {
|
||||||
"version": "19.0.6",
|
"version": "19.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-mask/-/ngx-mask-19.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-mask/-/ngx-mask-19.0.6.tgz",
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
"bootswatch": "^5.3.3",
|
"bootswatch": "^5.3.3",
|
||||||
"jest-editor-support": "*",
|
"jest-editor-support": "*",
|
||||||
"moment": "^2.30.1",
|
"moment": "^2.30.1",
|
||||||
|
"ngx-countup": "^13.2.0",
|
||||||
"ngx-mask": "^19.0.6",
|
"ngx-mask": "^19.0.6",
|
||||||
"ngx-pagination": "^6.0.3",
|
"ngx-pagination": "^6.0.3",
|
||||||
"ngx-spinner": "^17.0.0",
|
"ngx-spinner": "^17.0.0",
|
||||||
|
|||||||
@ -138,6 +138,18 @@
|
|||||||
color: #ff3860;
|
color: #ff3860;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alliance-counter {
|
||||||
|
margin-top: 20px;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
text-align: center;
|
||||||
|
color: #ffffffcc;
|
||||||
|
}
|
||||||
|
.count {
|
||||||
|
color: #4fc3f7;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0 6px;
|
||||||
|
}
|
||||||
/* Footer */
|
/* Footer */
|
||||||
/*.footer {*/
|
/*.footer {*/
|
||||||
/* display: flex;*/
|
/* display: flex;*/
|
||||||
|
|||||||
@ -80,6 +80,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="alliance-counter" *ngIf="allianceCount !== null">
|
||||||
|
<span>Currently </span>
|
||||||
|
<span class="count">
|
||||||
|
<span [countUp]="allianceCount"></span>
|
||||||
|
</span>
|
||||||
|
<span> alliances use the tool</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="footer d-flex flex-wrap justify-content-center justify-content-md-between align-items-center px-3 py-3 mt-auto shadow-sm gap-2 small text-center">
|
<footer class="footer d-flex flex-wrap justify-content-center justify-content-md-between align-items-center px-3 py-3 mt-auto shadow-sm gap-2 small text-center">
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {Component, inject} from '@angular/core';
|
import {Component, inject, OnInit} from '@angular/core';
|
||||||
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
import {FormControl, FormGroup, Validators} from "@angular/forms";
|
||||||
import {AuthenticationService} from "../../services/authentication.service";
|
import {AuthenticationService} from "../../services/authentication.service";
|
||||||
import {Router} from "@angular/router";
|
import {Router} from "@angular/router";
|
||||||
@ -6,16 +6,15 @@ import {ToastrService} from "ngx-toastr";
|
|||||||
import {LoginRequestModel} from "../../models/login.model";
|
import {LoginRequestModel} from "../../models/login.model";
|
||||||
import {environment} from "../../../environments/environment";
|
import {environment} from "../../../environments/environment";
|
||||||
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
|
||||||
import {PlayerEditModalComponent} from "../../modals/player-edit-modal/player-edit-modal.component";
|
|
||||||
import {PlayerModel} from "../../models/player.model";
|
|
||||||
import {ForgotPasswordComponent} from "../forgot-password/forgot-password.component";
|
import {ForgotPasswordComponent} from "../forgot-password/forgot-password.component";
|
||||||
|
import {StatService} from "../../services/stat.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
templateUrl: './login.component.html',
|
templateUrl: './login.component.html',
|
||||||
styleUrl: './login.component.css'
|
styleUrl: './login.component.css'
|
||||||
})
|
})
|
||||||
export class LoginComponent {
|
export class LoginComponent implements OnInit {
|
||||||
|
|
||||||
public isPasswordType: boolean = true;
|
public isPasswordType: boolean = true;
|
||||||
public currentYear: number = new Date().getFullYear();
|
public currentYear: number = new Date().getFullYear();
|
||||||
@ -27,9 +26,11 @@ export class LoginComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
private readonly _authenticationService: AuthenticationService = inject(AuthenticationService);
|
private readonly _authenticationService: AuthenticationService = inject(AuthenticationService);
|
||||||
|
private readonly _statService: StatService = inject(StatService);
|
||||||
private readonly _router: Router = inject(Router);
|
private readonly _router: Router = inject(Router);
|
||||||
private readonly _toastr: ToastrService = inject(ToastrService);
|
private readonly _toastr: ToastrService = inject(ToastrService);
|
||||||
private readonly _modalService : NgbModal = inject(NgbModal);
|
private readonly _modalService : NgbModal = inject(NgbModal);
|
||||||
|
allianceCount: number | null = null;
|
||||||
|
|
||||||
get email() {
|
get email() {
|
||||||
return this.loginForm.get('email');
|
return this.loginForm.get('email');
|
||||||
@ -39,6 +40,18 @@ export class LoginComponent {
|
|||||||
return this.loginForm.get('password');
|
return this.loginForm.get('password');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.fetchAllianceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
fetchAllianceCount() {
|
||||||
|
this._statService.getAllianceUseCount().subscribe({
|
||||||
|
next: ((response => {
|
||||||
|
this.allianceCount = response;
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
onLogin(): void {
|
onLogin(): void {
|
||||||
if (this.loginForm.invalid) {
|
if (this.loginForm.invalid) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -65,6 +65,7 @@ import { CustomEventCategoryComponent } from './pages/custom-event/custom-event-
|
|||||||
import { CustomEventLeaderboardComponent } from './pages/custom-event/custom-event-leaderboard/custom-event-leaderboard.component';
|
import { CustomEventLeaderboardComponent } from './pages/custom-event/custom-event-leaderboard/custom-event-leaderboard.component';
|
||||||
import { CustomEventEventsComponent } from './pages/custom-event/custom-event-events/custom-event-events.component';
|
import { CustomEventEventsComponent } from './pages/custom-event/custom-event-events/custom-event-events.component';
|
||||||
import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
|
import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
|
||||||
|
import {CountUpModule} from "ngx-countup";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -140,7 +141,8 @@ import {NgxMaskDirective, NgxMaskPipe, provideNgxMask} from "ngx-mask";
|
|||||||
}),
|
}),
|
||||||
AgCharts,
|
AgCharts,
|
||||||
NgxMaskDirective,
|
NgxMaskDirective,
|
||||||
NgxMaskPipe
|
NgxMaskPipe,
|
||||||
|
CountUpModule
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
provideNgxMask(),
|
provideNgxMask(),
|
||||||
|
|||||||
@ -6,6 +6,10 @@ import {finalize} from "rxjs";
|
|||||||
export const spinnerInterceptor: HttpInterceptorFn = (req, next) => {
|
export const spinnerInterceptor: HttpInterceptorFn = (req, next) => {
|
||||||
const spinnerService: SpinnerService = inject(SpinnerService);
|
const spinnerService: SpinnerService = inject(SpinnerService);
|
||||||
|
|
||||||
|
if(req.url.includes('Stats/useCount')) {
|
||||||
|
return next(req);
|
||||||
|
}
|
||||||
|
|
||||||
spinnerService.busy();
|
spinnerService.busy();
|
||||||
|
|
||||||
return next(req).pipe(
|
return next(req).pipe(
|
||||||
|
|||||||
21
Ui/src/app/services/stat.service.ts
Normal file
21
Ui/src/app/services/stat.service.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import {inject, Injectable} from '@angular/core';
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import {HttpClient} from "@angular/common/http";
|
||||||
|
import {map, Observable} from "rxjs";
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class StatService {
|
||||||
|
|
||||||
|
private readonly _serviceUrl = environment.apiBaseUrl + 'Stats/';
|
||||||
|
private readonly _httpClient: HttpClient = inject(HttpClient);
|
||||||
|
|
||||||
|
getAllianceUseCount() : Observable<number> {
|
||||||
|
return this._httpClient.get<{amount: number}>(this._serviceUrl + 'useCount')
|
||||||
|
.pipe(
|
||||||
|
map(res => res.amount)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user