= c0086ddb6a feature: implement ConnectedApp management with creation and editing support
- Added `ConnectedAppData` DTO for structured data representation.
- Implemented Livewire components for ConnectedApp list (`index`) and edit (`edit`).
- Integrated `ConnectedAppService` with CRUD operations.
- Updated routing to include ConnectedApp management paths.
- Enhanced UI with reusable components and dynamic dropdowns for protocols, providers, and statuses.
2026-05-14 14:03:53 +00:00

148 lines
4.6 KiB
PHP

<?php
use App\Concerns\HandlesOperations;
use App\Data\ConnectedApp\ConnectAppRequest;
use App\Data\ConnectedApp\ConnectionStatusData;
use App\Enums\ConnectionStatusEnum;
use App\Livewire\Forms\StoreConnectedAppFrom;
use App\Models\ConnectionProtocol;
use App\Models\ConnectionProvider;
use App\Models\ConnectionStatus;
use App\Services\ConnectedAppService;
use App\Services\ConnectionProtocolService;
use App\Services\ConnectionProviderService;
use App\Services\ConnectionStatusService;
use Illuminate\Database\Eloquent\Collection;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Lazy;
use Livewire\Component;
use Livewire\Attributes\Title;
use Mary\Traits\Toast;
use Spatie\LaravelData\DataCollection;
new
#[Lazy]
#[Title('Edit a connected app')]
class extends Component {
use HandlesOperations;
public StoreConnectedAppFrom $form;
protected ConnectedAppService $service;
public int $recordId = 0;
public function boot(ConnectedAppService $service): void
{
$this->service = $service;
}
public function mount(int $id): void
{
$this->attempt(
action: function () use ($id) {
$record = $this->service->getConnectedApp($id);
$this->form->set($record);
$this->recordId = $id;
},
onError: function () {
$this->redirectRoute('connected-apps.index', navigate: true);
},
showSuccess: false
);
}
#[Computed]
public function providers()
{
return ConnectionProvider::query()->get();
}
#[Computed]
public function protocols(): Collection
{
$protocolService = app(ConnectionProtocolService::class);
return $protocolService->getAll()->map(function (ConnectionProtocol $protocol) {
$protocol->name = strtoupper($protocol->name);
return $protocol;
});
}
/**
* @returns DataCollection<int, ConnectionStatus>
*/
#[Computed]
public function connectionStatuses(): DataCollection
{
$statusService = app(ConnectionStatusService::class);
return $statusService->getAll();
}
public function searchProvider(string $name): void
{
$providerService = app(ConnectionProviderService::class);
$this->providers = $providerService->search($name);
}
public function save(): void
{
$this->attempt(
action: function () {
$this->form->validate();
$serviceData = new ConnectAppRequest(
name: $this->form->name,
connectionProviderId: $this->form->providerId,
connectionProtocolId: $this->form->protocolId,
slug: str($this->form->name)->slug()->toString(),
connectionStatusId: $this->form->statusId,
);
$this->service->update($this->recordId, $serviceData);
$this->redirectRoute('connected-apps.index', navigate: true);
},
);
}
};
?>
<div>
<x-shared.card :title="__('Edit an connected app')" class="">
<form wire:submit="save" class="p-4 grid grid-cols-1 gap-4 md:grid-cols-2">
<x-input wire:model.live.blur="form.name" required :label="__('Name')"/>
<x-choices
required
wire:model="form.protocolId"
:label="__('Protocol')"
:single="true"
:options="$this->protocols"
placeholder="Select"
/>
<x-choices required
wire:model="form.providerId"
:label="__('Provider')"
placeholder="Search ..."
:single="true"
:options="$this->providers"
searchable
search-function="searchProvider"
debounce="300"
/>
<x-choices
required
wire:model="form.statusId"
:label="__('Status')"
:single="true"
:options="$this->connectionStatuses->toArray()"
placeholder="Select"
/>
<div class="md:col-span-2 flex gap-x-4 font-medium justify-end">
<x-shared.button>Cancel</x-shared.button>
<x-shared.button type="submit"
class="bg-blue-600 text-blue-50 hover:bg-blue-700 border-blue-600 min-w-20 flex justify-center items-center">
Save
</x-shared.button>
</div>
</form>
</x-shared.card>
</div>