This commit is contained in:
2025-12-21 22:35:38 +01:00
parent 3c64f328e2
commit 9bd2e630e6
38 changed files with 736 additions and 684 deletions

View File

@@ -9,10 +9,10 @@ describe('DriverRegistrationStatusPresenter', () => {
});
describe('present', () => {
it('should map parameters to view model for registered driver', () => {
presenter.present(true, 'race-123', 'driver-456');
it('should map parameters to response model for registered driver', () => {
presenter.present({ isRegistered: true, raceId: 'race-123', driverId: 'driver-456' });
const result = presenter.viewModel;
const result = presenter.getResponseModel();
expect(result).toEqual({
isRegistered: true,
@@ -21,10 +21,10 @@ describe('DriverRegistrationStatusPresenter', () => {
});
});
it('should map parameters to view model for unregistered driver', () => {
presenter.present(false, 'race-789', 'driver-101');
it('should map parameters to response model for unregistered driver', () => {
presenter.present({ isRegistered: false, raceId: 'race-789', driverId: 'driver-101' });
const result = presenter.viewModel;
const result = presenter.getResponseModel();
expect(result).toEqual({
isRegistered: false,
@@ -36,11 +36,11 @@ describe('DriverRegistrationStatusPresenter', () => {
describe('reset', () => {
it('should reset the result', () => {
presenter.present(true, 'race-123', 'driver-456');
expect(presenter.viewModel).toBeDefined();
presenter.present({ isRegistered: true, raceId: 'race-123', driverId: 'driver-456' });
expect(presenter.getResponseModel()).toBeDefined();
presenter.reset();
expect(() => presenter.viewModel).toThrow('Presenter not presented');
expect(() => presenter.getResponseModel()).toThrow('Presenter not presented');
});
});
});

View File

@@ -9,6 +9,10 @@ export class DriverRegistrationStatusPresenter
{
private responseModel: DriverRegistrationStatusDTO | null = null;
reset(): void {
this.responseModel = null;
}
present(result: IsDriverRegisteredForRaceResult): void {
this.responseModel = {
isRegistered: result.isRegistered,

View File

@@ -1,29 +1,15 @@
import type { Result } from '@core/shared/application/Result';
import type { ApplicationErrorCode } from '@core/shared/errors/ApplicationErrorCode';
import { DriversLeaderboardDTO } from '../dtos/DriversLeaderboardDTO';
import type {
GetDriversLeaderboardResult,
GetDriversLeaderboardErrorCode,
} from '@core/racing/application/use-cases/GetDriversLeaderboardUseCase';
import type { UseCaseOutputPort } from '@core/shared/application/UseCaseOutputPort';
export type DriversLeaderboardApplicationError = ApplicationErrorCode<
GetDriversLeaderboardErrorCode,
{ message: string }
>;
export class DriversLeaderboardPresenter implements UseCaseOutputPort<GetDriversLeaderboardResult> {
private responseModel: DriversLeaderboardDTO | null = null;
export class DriversLeaderboardPresenter {
present(
result: Result<GetDriversLeaderboardResult, DriversLeaderboardApplicationError>,
): DriversLeaderboardDTO {
if (result.isErr()) {
const error = result.unwrapErr();
throw new Error(error.details?.message ?? 'Failed to load drivers leaderboard');
}
const output = result.unwrap();
return {
drivers: output.items.map(item => ({
present(result: GetDriversLeaderboardResult): void {
this.responseModel = {
drivers: result.items.map(item => ({
id: item.driver.id,
name: item.driver.name.toString(),
rating: item.rating,
@@ -36,9 +22,14 @@ export class DriversLeaderboardPresenter {
rank: item.rank,
avatarUrl: item.avatarUrl,
})),
totalRaces: output.items.reduce((sum, d) => sum + d.racesCompleted, 0),
totalWins: output.items.reduce((sum, d) => sum + d.wins, 0),
activeCount: output.items.filter(d => d.isActive).length,
totalRaces: result.totalRaces,
totalWins: result.totalWins,
activeCount: result.activeCount,
};
}
getResponseModel(): DriversLeaderboardDTO {
if (!this.responseModel) throw new Error('Presenter not presented');
return this.responseModel;
}
}