feat(dashboard): add price dashboard with Zonneplan integration
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Clients;
|
||||
|
||||
use App\Features\Dashboard\Contracts\PriceClient;
|
||||
use Exception;
|
||||
use Illuminate\Http\Client\Factory;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Throwable;
|
||||
|
||||
class ZonneplanPriceClient implements PriceClient
|
||||
{
|
||||
public function __construct(
|
||||
private readonly Factory $http,
|
||||
) {}
|
||||
|
||||
public function getElectricityPrices(): array
|
||||
{
|
||||
return $this->get('/energy-prices/electricity/upcoming');
|
||||
}
|
||||
|
||||
public function getGasPrices(): array
|
||||
{
|
||||
return $this->get('/energy-prices/gas/upcoming');
|
||||
}
|
||||
|
||||
/** @return array<int, array<string, mixed>> */
|
||||
private function get(string $path): array
|
||||
{
|
||||
try {
|
||||
$response = $this->http
|
||||
->baseUrl(config('api.baseurl'))
|
||||
->withQueryParameters([
|
||||
'secret' => config('api.key'),
|
||||
])
|
||||
->timeout(10)
|
||||
->retry(2, 100)
|
||||
->get($path);
|
||||
|
||||
$response->throw();
|
||||
|
||||
Log::info('Zonneplan API opgehaald', [
|
||||
'path' => $path,
|
||||
'status' => $response->status(),
|
||||
]);
|
||||
|
||||
return $response->json('data', []);
|
||||
} catch (Throwable $e) {
|
||||
Log::error('Zonneplan API aanroep mislukt', [
|
||||
'path' => $path,
|
||||
'message' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
throw new Exception(
|
||||
"Kon energieprijzen niet ophalen voor {$path}",
|
||||
previous: $e,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Contracts;
|
||||
|
||||
interface PriceClient
|
||||
{
|
||||
public function getElectricityPrices(): array;
|
||||
|
||||
public function getGasPrices(): array;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Contracts;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface PriceRepository
|
||||
{
|
||||
public function retrieveElectricity(): Collection;
|
||||
|
||||
public function retrieveGas(): Collection;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Controllers;
|
||||
|
||||
use App\Features\Dashboard\Data\DashboardData;
|
||||
use App\Features\Dashboard\Services\DashboardService;
|
||||
use App\Http\Controllers\Controller;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function index(DashboardService $dashboardService)
|
||||
{
|
||||
return inertia('dashboard::index', DashboardData::from($dashboardService->getDashboardData()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Data;
|
||||
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
class DashboardData extends Data
|
||||
{
|
||||
/**
|
||||
* @property array<ElectricityData> $electricity
|
||||
* @property array<GasData> $gas
|
||||
*/
|
||||
public function __construct(
|
||||
public array $electricity,
|
||||
public array $gas
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Data;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Spatie\LaravelData\Attributes\MapInputName;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
||||
|
||||
#[MapInputName(SnakeCaseMapper::class)]
|
||||
class ElectricityData extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public Carbon $startDate,
|
||||
public Carbon $endDate,
|
||||
public string $period,
|
||||
public ?int $marketPrice,
|
||||
public ?float $totalPriceTaxIncluded,
|
||||
public ?int $priceInclHandlingVat,
|
||||
public ?int $priceTaxWithVat,
|
||||
public ?string $pricingProfile,
|
||||
public ?int $carbonFootprintInGram,
|
||||
public ?int $sustainabilityScore,
|
||||
public Carbon $startDateDatetime,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Data;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Spatie\LaravelData\Attributes\MapInputName;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
||||
|
||||
#[MapInputName(SnakeCaseMapper::class)]
|
||||
class GasData extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public Carbon $startDate,
|
||||
public Carbon $endDate,
|
||||
public string $period,
|
||||
public int $marketPrice,
|
||||
public float $totalPriceTaxIncluded,
|
||||
public int $priceInclHandlingVat,
|
||||
public int $priceTaxWithVat,
|
||||
public Carbon $startDateDatetime,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Repositories;
|
||||
|
||||
use App\Features\Dashboard\Contracts\PriceClient;
|
||||
use App\Features\Dashboard\Contracts\PriceRepository as ContractsPriceRepository;
|
||||
use App\Features\Dashboard\Data\ElectricityData;
|
||||
use App\Features\Dashboard\Data\GasData;
|
||||
use Illuminate\Support\Collection;
|
||||
use Override;
|
||||
|
||||
class ZonneplanPriceRepository implements ContractsPriceRepository
|
||||
{
|
||||
public function __construct(
|
||||
public PriceClient $client
|
||||
) {}
|
||||
|
||||
#[Override]
|
||||
public function retrieveElectricity(): Collection
|
||||
{
|
||||
$data = $this->client->getElectricityPrices();
|
||||
|
||||
return collect(ElectricityData::collect($data));
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function retrieveGas(): Collection
|
||||
{
|
||||
$data = $this->client->getGasPrices();
|
||||
|
||||
return collect(GasData::collect($data));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Features\Dashboard\Services;
|
||||
|
||||
use App\Features\Dashboard\Contracts\PriceRepository;
|
||||
|
||||
class DashboardService
|
||||
{
|
||||
public function __construct(
|
||||
public PriceRepository $repository
|
||||
) {}
|
||||
|
||||
public function getDashboardData(): array
|
||||
{
|
||||
return [
|
||||
'electricity' => $this->repository->retrieveElectricity(),
|
||||
'gas' => $this->repository->retrieveGas(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,10 @@
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Features\Dashboard\Clients\ZonneplanPriceClient;
|
||||
use App\Features\Dashboard\Contracts\PriceClient;
|
||||
use App\Features\Dashboard\Contracts\PriceRepository;
|
||||
use App\Features\Dashboard\Repositories\ZonneplanPriceRepository;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Support\Facades\Date;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -15,7 +19,8 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
$this->app->bind(PriceRepository::class, ZonneplanPriceRepository::class);
|
||||
$this->app->bind(PriceClient::class, ZonneplanPriceClient::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Spatie\LaravelTypeScriptTransformer\LaravelData\Transformers\DataClassTransformer;
|
||||
use Spatie\LaravelTypeScriptTransformer\TypeScriptTransformerApplicationServiceProvider as BaseTypeScriptTransformerServiceProvider;
|
||||
use Spatie\TypeScriptTransformer\Formatters\PrettierFormatter;
|
||||
use Spatie\TypeScriptTransformer\Transformers\AttributedClassTransformer;
|
||||
use Spatie\TypeScriptTransformer\Transformers\EnumTransformer;
|
||||
use Spatie\TypeScriptTransformer\TypeScriptTransformerConfigFactory;
|
||||
use Spatie\TypeScriptTransformer\Writers\GlobalNamespaceWriter;
|
||||
|
||||
class TypeScriptTransformerServiceProvider extends BaseTypeScriptTransformerServiceProvider
|
||||
{
|
||||
protected function configure(TypeScriptTransformerConfigFactory $config): void
|
||||
{
|
||||
$config
|
||||
->transformer(AttributedClassTransformer::class)
|
||||
->transformer(EnumTransformer::class)
|
||||
->transformer(DataClassTransformer::class)
|
||||
->transformDirectories(app_path())
|
||||
->writer(new GlobalNamespaceWriter('generated.d.ts'))
|
||||
->replaceType(Carbon::class, 'string')
|
||||
->formatter(PrettierFormatter::class);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user