Include necessary info directly in get consumption entries response dto
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,14 +1,16 @@
|
|||||||
import {inject, Injectable} from '@angular/core';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import {HttpClient} from '@angular/common/http';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import {API_BASE_PATH} from '../api-base-path';
|
import { GetConsumptionEntriesResponse } from '@vegasco-web/api/consumptions/get-consumption-entries-response';
|
||||||
import {map, Observable} from 'rxjs';
|
import { map, Observable } from 'rxjs';
|
||||||
|
import { API_BASE_PATH } from '../api-base-path';
|
||||||
|
import { ConsumptionEntry } from './consumption-entry';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class ConsumptionClient {
|
export class ConsumptionClient {
|
||||||
private readonly http = inject(HttpClient);
|
private readonly http = inject(HttpClient);
|
||||||
private readonly apiBasePath = inject(API_BASE_PATH, {optional: true});
|
private readonly apiBasePath = inject(API_BASE_PATH, { optional: true });
|
||||||
|
|
||||||
getAll(): Observable<GetConsumptionEntriesResponse> {
|
getAll(): Observable<GetConsumptionEntriesResponse> {
|
||||||
return this.http.get<GetConsumptionEntriesResponse>(`${this.apiBasePath}/v1/consumptions`);
|
return this.http.get<GetConsumptionEntriesResponse>(`${this.apiBasePath}/v1/consumptions`);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
interface ConsumptionEntry {
|
export interface ConsumptionEntry {
|
||||||
id: string;
|
id: string;
|
||||||
dateTime: string;
|
dateTime: string;
|
||||||
distance: number;
|
distance: number;
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
export interface GetConsumptionEntriesEntry {
|
||||||
|
id: string;
|
||||||
|
dateTime: string;
|
||||||
|
distance: number;
|
||||||
|
amount: number;
|
||||||
|
car: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
interface GetConsumptionEntriesResponse {
|
import { GetConsumptionEntriesEntry } from "./get-consumption-entries-entry";
|
||||||
consumptions: ConsumptionEntry[];
|
|
||||||
|
export interface GetConsumptionEntriesResponse {
|
||||||
|
consumptions: GetConsumptionEntriesEntry[];
|
||||||
}
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
export interface Consumption {
|
|
||||||
id: string;
|
|
||||||
dateTime: string;
|
|
||||||
distance: number;
|
|
||||||
amount: number;
|
|
||||||
ignoreInCalculation: boolean;
|
|
||||||
carId: string;
|
|
||||||
car: Car;
|
|
||||||
}
|
|
||||||
@@ -3,17 +3,17 @@ import { HttpErrorResponse } from '@angular/common/http';
|
|||||||
import { Component, DestroyRef, inject, input, output } from '@angular/core';
|
import { Component, DestroyRef, inject, input, output } from '@angular/core';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||||
import {
|
|
||||||
matCalendarMonthSharp,
|
|
||||||
matDeleteSharp,
|
|
||||||
matStraightenSharp,
|
|
||||||
matLocalGasStationSharp,
|
|
||||||
} from '@ng-icons/material-icons/sharp';
|
|
||||||
import {
|
import {
|
||||||
matDirectionsCarOutline,
|
matDirectionsCarOutline,
|
||||||
} from '@ng-icons/material-icons/outline';
|
} from '@ng-icons/material-icons/outline';
|
||||||
|
import {
|
||||||
|
matCalendarMonthSharp,
|
||||||
|
matDeleteSharp,
|
||||||
|
matLocalGasStationSharp,
|
||||||
|
matStraightenSharp,
|
||||||
|
} from '@ng-icons/material-icons/sharp';
|
||||||
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
||||||
import { Consumption } from '@vegasco-web/api/models/consumption';
|
import { GetConsumptionEntriesEntry } from '@vegasco-web/api/consumptions/get-consumption-entries-entry';
|
||||||
import { RoutingService } from '@vegasco-web/services/routing.service';
|
import { RoutingService } from '@vegasco-web/services/routing.service';
|
||||||
import { ConfirmationService, MessageService } from 'primeng/api';
|
import { ConfirmationService, MessageService } from 'primeng/api';
|
||||||
import { ButtonModule } from 'primeng/button';
|
import { ButtonModule } from 'primeng/button';
|
||||||
@@ -45,9 +45,9 @@ import { catchError, EMPTY, Observable, tap, throwError } from 'rxjs';
|
|||||||
styleUrl: './entry-card.component.scss'
|
styleUrl: './entry-card.component.scss'
|
||||||
})
|
})
|
||||||
export class EntryCardComponent {
|
export class EntryCardComponent {
|
||||||
readonly entry = input.required<Consumption>();
|
readonly entry = input.required<GetConsumptionEntriesEntry>();
|
||||||
|
|
||||||
readonly entryDeleted = output<Consumption>();
|
readonly entryDeleted = output<GetConsumptionEntriesEntry>();
|
||||||
|
|
||||||
private readonly routingService = inject(RoutingService);
|
private readonly routingService = inject(RoutingService);
|
||||||
private readonly consumptionClient = inject(ConsumptionClient);
|
private readonly consumptionClient = inject(ConsumptionClient);
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
import { AsyncPipe, CommonModule } from '@angular/common';
|
import { AsyncPipe, CommonModule } from '@angular/common';
|
||||||
|
import { HttpErrorResponse } from '@angular/common/http';
|
||||||
import { Component, DestroyRef, inject, OnInit } from '@angular/core';
|
import { Component, DestroyRef, inject, OnInit } from '@angular/core';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
import { FormControl, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { RouterLink } from '@angular/router';
|
import { RouterLink } from '@angular/router';
|
||||||
|
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
||||||
|
import {
|
||||||
|
matAddSharp,
|
||||||
|
} from '@ng-icons/material-icons/sharp';
|
||||||
|
import { CarClient } from '@vegasco-web/api/cars/car-client';
|
||||||
|
import { ConsumptionClient } from '@vegasco-web/api/consumptions/consumption-client';
|
||||||
|
import { GetConsumptionEntriesEntry } from '@vegasco-web/api/consumptions/get-consumption-entries-entry';
|
||||||
import { MessageService } from 'primeng/api';
|
import { MessageService } from 'primeng/api';
|
||||||
import { ButtonModule } from 'primeng/button';
|
import { ButtonModule } from 'primeng/button';
|
||||||
import { DataViewModule } from 'primeng/dataview';
|
import { DataViewModule } from 'primeng/dataview';
|
||||||
@@ -20,14 +28,9 @@ import {
|
|||||||
tap,
|
tap,
|
||||||
throwError
|
throwError
|
||||||
} from 'rxjs';
|
} from 'rxjs';
|
||||||
import { EntriesOverviewService } from './services/entries-overview.service';
|
|
||||||
import { EntryCardComponent } from './components/entry-card/entry-card.component';
|
|
||||||
import {
|
|
||||||
matAddSharp,
|
|
||||||
} from '@ng-icons/material-icons/sharp';
|
|
||||||
import { NgIconComponent, provideIcons } from '@ng-icons/core';
|
|
||||||
import { HttpErrorResponse } from '@angular/common/http';
|
|
||||||
import { SelectedCarService } from '../services/selected-car.service';
|
import { SelectedCarService } from '../services/selected-car.service';
|
||||||
|
import { EntryCardComponent } from './components/entry-card/entry-card.component';
|
||||||
|
import { ConsumptionEntry } from '@vegasco-web/api/consumptions/consumption-entry';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-entries',
|
selector: 'app-entries',
|
||||||
@@ -48,18 +51,18 @@ import { SelectedCarService } from '../services/selected-car.service';
|
|||||||
provideIcons({
|
provideIcons({
|
||||||
matAddSharp,
|
matAddSharp,
|
||||||
}),
|
}),
|
||||||
EntriesOverviewService,
|
|
||||||
],
|
],
|
||||||
templateUrl: './entries.component.html',
|
templateUrl: './entries.component.html',
|
||||||
styleUrl: './entries.component.scss'
|
styleUrl: './entries.component.scss'
|
||||||
})
|
})
|
||||||
export class EntriesComponent implements OnInit {
|
export class EntriesComponent implements OnInit {
|
||||||
private readonly entriesOverviewService = inject(EntriesOverviewService);
|
private readonly carClient = inject(CarClient);
|
||||||
|
private readonly consumptionClient = inject(ConsumptionClient);
|
||||||
private readonly messageService = inject(MessageService);
|
private readonly messageService = inject(MessageService);
|
||||||
private readonly selectedCarService = inject(SelectedCarService);
|
private readonly selectedCarService = inject(SelectedCarService);
|
||||||
private readonly destroyRef = inject(DestroyRef);
|
private readonly destroyRef = inject(DestroyRef);
|
||||||
|
|
||||||
protected readonly consumptionEntries$: Observable<ConsumptionEntry[]>;
|
protected readonly consumptionEntries$: Observable<GetConsumptionEntriesEntry[]>;
|
||||||
protected readonly cars$: Observable<Car[]>;
|
protected readonly cars$: Observable<Car[]>;
|
||||||
|
|
||||||
protected readonly skeletonsIterationSource = Array(10).fill(0);
|
protected readonly skeletonsIterationSource = Array(10).fill(0);
|
||||||
@@ -69,9 +72,10 @@ export class EntriesComponent implements OnInit {
|
|||||||
private readonly deletedEntries$ = new BehaviorSubject(<string[]>[]);
|
private readonly deletedEntries$ = new BehaviorSubject(<string[]>[]);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
const entries = this.entriesOverviewService.getEntries()
|
const entries = this.consumptionClient.getAll()
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntilDestroyed(),
|
takeUntilDestroyed(),
|
||||||
|
map(response => response.consumptions),
|
||||||
catchError((error) => this.handleGetEntriesError(error))
|
catchError((error) => this.handleGetEntriesError(error))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -92,13 +96,14 @@ export class EntriesComponent implements OnInit {
|
|||||||
return nonDeletedEntries;
|
return nonDeletedEntries;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nonDeletedEntries.filter(entry => entry.carId === selectedCar.id);
|
return nonDeletedEntries.filter(entry => entry.car.id === selectedCar.id);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.cars$ = this.entriesOverviewService.getCars()
|
this.cars$ = this.carClient.getAll()
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntilDestroyed(),
|
takeUntilDestroyed(),
|
||||||
|
map(response => response.cars),
|
||||||
map((cars) => cars
|
map((cars) => cars
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))),
|
.sort((a, b) => a.name.localeCompare(b.name))),
|
||||||
tap((cars) => {
|
tap((cars) => {
|
||||||
@@ -129,7 +134,7 @@ export class EntriesComponent implements OnInit {
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
onEntryDeleted(entry: ConsumptionEntry): void {
|
onEntryDeleted(entry: GetConsumptionEntriesEntry): void {
|
||||||
this.deletedEntries$.next([...this.deletedEntries$.value, entry.id]);
|
this.deletedEntries$.next([...this.deletedEntries$.value, entry.id]);
|
||||||
this.messageService.add({
|
this.messageService.add({
|
||||||
severity: 'success',
|
severity: 'success',
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
import { inject, Injectable } from "@angular/core";
|
|
||||||
import { CarClient } from "@vegasco-web/api/cars/car-client";
|
|
||||||
import { ConsumptionClient } from "@vegasco-web/api/consumptions/consumption-client";
|
|
||||||
import { Consumption } from "@vegasco-web/api/models/consumption";
|
|
||||||
import { RoutingService } from "@vegasco-web/services/routing.service";
|
|
||||||
import { combineLatest, map, Observable, shareReplay } from "rxjs";
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class EntriesOverviewService {
|
|
||||||
private readonly carClient = inject(CarClient);
|
|
||||||
private readonly consumptionClient = inject(ConsumptionClient);
|
|
||||||
|
|
||||||
private cachedCars$: Observable<Car[]> | null = null;
|
|
||||||
|
|
||||||
private ensureCarsAreCached(): void {
|
|
||||||
if (this.cachedCars$ !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cachedCars$ = this.carClient.getAll()
|
|
||||||
.pipe(
|
|
||||||
map(response => response.cars),
|
|
||||||
shareReplay(1)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getEntries(): Observable<Consumption[]> {
|
|
||||||
this.ensureCarsAreCached();
|
|
||||||
|
|
||||||
const entries$ = this.consumptionClient.getAll()
|
|
||||||
.pipe(map(response => response.consumptions));
|
|
||||||
|
|
||||||
return combineLatest([this.cachedCars$!, entries$])
|
|
||||||
.pipe(
|
|
||||||
map(([cars, entries]) => {
|
|
||||||
return entries
|
|
||||||
.sort((a, b) => b.dateTime.localeCompare(a.dateTime))
|
|
||||||
.map((entry): Consumption => ({
|
|
||||||
...entry,
|
|
||||||
car: cars.find(car => car.id === entry.carId)!
|
|
||||||
}));
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
getCars(): Observable<Car[]> {
|
|
||||||
this.ensureCarsAreCached();
|
|
||||||
return this.cachedCars$!;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Http.HttpResults;
|
using Microsoft.AspNetCore.Http.HttpResults;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Vegasco.Server.Api.Cars;
|
||||||
using Vegasco.Server.Api.Persistence;
|
using Vegasco.Server.Api.Persistence;
|
||||||
|
|
||||||
namespace Vegasco.Server.Api.Consumptions;
|
namespace Vegasco.Server.Api.Consumptions;
|
||||||
@@ -17,7 +18,18 @@ public static class GetConsumptions
|
|||||||
DateTimeOffset DateTime,
|
DateTimeOffset DateTime,
|
||||||
double Distance,
|
double Distance,
|
||||||
double Amount,
|
double Amount,
|
||||||
Guid CarId);
|
CarDto Car,
|
||||||
|
double? LiterPer100Km);
|
||||||
|
|
||||||
|
public record CarDto(
|
||||||
|
Guid Id,
|
||||||
|
string Name)
|
||||||
|
{
|
||||||
|
public static CarDto FromCar(Car car)
|
||||||
|
{
|
||||||
|
return new CarDto(car.Id.Value, car.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class Request
|
public class Request
|
||||||
{
|
{
|
||||||
@@ -39,16 +51,37 @@ public static class GetConsumptions
|
|||||||
ApplicationDbContext dbContext,
|
ApplicationDbContext dbContext,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
List<ResponseDto> consumptions = await dbContext.Consumptions
|
List<Consumption> consumptions = await dbContext.Consumptions
|
||||||
.OrderByDescending(x => x.DateTime)
|
.OrderByDescending(x => x.DateTime)
|
||||||
.Select(x =>
|
.Include(x => x.Car)
|
||||||
new ResponseDto(x.Id.Value, x.DateTime, x.Distance, x.Amount, x.CarId.Value))
|
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
ApiResponse apiResponse = new()
|
List<ResponseDto> responses = [];
|
||||||
|
|
||||||
|
for (int i = 0; i < consumptions.Count; i++)
|
||||||
{
|
{
|
||||||
Consumptions = consumptions
|
Consumption consumption = consumptions[i];
|
||||||
};
|
|
||||||
|
double? literPer100Km = null;
|
||||||
|
|
||||||
|
bool isLast = i == consumptions.Count - 1;
|
||||||
|
if (!isLast)
|
||||||
|
{
|
||||||
|
Consumption previousConsumption = consumptions[i + 1];
|
||||||
|
double distanceDiff = consumption.Distance - previousConsumption.Distance;
|
||||||
|
literPer100Km = consumption.Amount / (distanceDiff / 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
responses.Add(new ResponseDto(
|
||||||
|
consumption.Id.Value,
|
||||||
|
consumption.DateTime,
|
||||||
|
consumption.Distance,
|
||||||
|
consumption.Amount,
|
||||||
|
CarDto.FromCar(consumption.Car),
|
||||||
|
literPer100Km));
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiResponse apiResponse = new() { Consumptions = responses };
|
||||||
return TypedResults.Ok(apiResponse);
|
return TypedResults.Ok(apiResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ public class GetConsumptionsTests : IAsyncLifetime
|
|||||||
// Arrange
|
// Arrange
|
||||||
List<CreateConsumption.Response> createdConsumptions = [];
|
List<CreateConsumption.Response> createdConsumptions = [];
|
||||||
const int numberOfConsumptions = 3;
|
const int numberOfConsumptions = 3;
|
||||||
for (var i = 0; i < numberOfConsumptions; i++)
|
for (int i = 0; i < numberOfConsumptions; i++)
|
||||||
{
|
{
|
||||||
CreateConsumption.Response createdConsumption = await CreateConsumptionAsync();
|
CreateConsumption.Response createdConsumption = await CreateConsumptionAsync();
|
||||||
createdConsumptions.Add(createdConsumption);
|
createdConsumptions.Add(createdConsumption);
|
||||||
@@ -42,8 +42,16 @@ public class GetConsumptionsTests : IAsyncLifetime
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
var apiResponse = await response.Content.ReadFromJsonAsync<GetConsumptions.ApiResponse>();
|
GetConsumptions.ApiResponse? apiResponse =
|
||||||
apiResponse!.Consumptions.Should().BeEquivalentTo(createdConsumptions);
|
await response.Content.ReadFromJsonAsync<GetConsumptions.ApiResponse>();
|
||||||
|
|
||||||
|
apiResponse.Should().NotBeNull();
|
||||||
|
apiResponse.Consumptions.Should().HaveCount(createdConsumptions.Count);
|
||||||
|
apiResponse.Consumptions.Should().BeEquivalentTo(createdConsumptions, o => o.ExcludingMissingMembers());
|
||||||
|
apiResponse.Consumptions
|
||||||
|
.Select(x => x.Car.Id)
|
||||||
|
.Should()
|
||||||
|
.BeEquivalentTo(createdConsumptions, o => o.ExcludingMissingMembers());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -56,26 +64,32 @@ public class GetConsumptionsTests : IAsyncLifetime
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
var apiResponse = await response.Content.ReadFromJsonAsync<GetConsumptions.ApiResponse>();
|
GetConsumptions.ApiResponse? apiResponse =
|
||||||
|
await response.Content.ReadFromJsonAsync<GetConsumptions.ApiResponse>();
|
||||||
apiResponse!.Consumptions.Should().BeEmpty();
|
apiResponse!.Consumptions.Should().BeEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CreateConsumption.Response> CreateConsumptionAsync()
|
private async Task<CreateConsumption.Response> CreateConsumptionAsync()
|
||||||
{
|
{
|
||||||
CreateCar.Response createdCarResponse = await CreateCarAsync();
|
CreateCar.Response createdCarResponse = await CreateCarAsync();
|
||||||
CreateConsumption.Request createConsumptionRequest = _consumptionFaker.CreateConsumptionRequest(createdCarResponse.Id);
|
CreateConsumption.Request createConsumptionRequest =
|
||||||
using HttpResponseMessage response = await _factory.HttpClient.PostAsJsonAsync("v1/consumptions", createConsumptionRequest);
|
_consumptionFaker.CreateConsumptionRequest(createdCarResponse.Id);
|
||||||
|
using HttpResponseMessage response =
|
||||||
|
await _factory.HttpClient.PostAsJsonAsync("v1/consumptions", createConsumptionRequest);
|
||||||
response.EnsureSuccessStatusCode();
|
response.EnsureSuccessStatusCode();
|
||||||
var createdConsumption = await response.Content.ReadFromJsonAsync<CreateConsumption.Response>();
|
CreateConsumption.Response? createdConsumption =
|
||||||
|
await response.Content.ReadFromJsonAsync<CreateConsumption.Response>();
|
||||||
return createdConsumption!;
|
return createdConsumption!;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CreateCar.Response> CreateCarAsync()
|
private async Task<CreateCar.Response> CreateCarAsync()
|
||||||
{
|
{
|
||||||
CreateCar.Request createCarRequest = new CarFaker().CreateCarRequest();
|
CreateCar.Request createCarRequest = new CarFaker().CreateCarRequest();
|
||||||
using HttpResponseMessage createCarResponse = await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest);
|
using HttpResponseMessage createCarResponse =
|
||||||
|
await _factory.HttpClient.PostAsJsonAsync("v1/cars", createCarRequest);
|
||||||
createCarResponse.EnsureSuccessStatusCode();
|
createCarResponse.EnsureSuccessStatusCode();
|
||||||
var createdCarResponse = await createCarResponse.Content.ReadFromJsonAsync<CreateCar.Response>();
|
CreateCar.Response? createdCarResponse =
|
||||||
|
await createCarResponse.Content.ReadFromJsonAsync<CreateCar.Response>();
|
||||||
return createdCarResponse!;
|
return createdCarResponse!;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user