Files
Epicnabbo-Catalogus-Updated…/Updated_Cms/app/Filament/Pages/BadgePage.php
T
2026-01-20 20:17:04 +01:00

339 lines
13 KiB
PHP

<?php
namespace App\Filament\Pages;
use App\Filament\Traits\TranslatableResource;
use App\Services\Parsers\ExternalTextsParser;
use Filament\Actions\Action as PageAction;
use Filament\Actions\ActionGroup;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Components\Utilities\Set;
use Filament\Schemas\Schema;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Throwable;
class BadgePage extends Page
{
use InteractsWithForms, TranslatableResource;
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-document-text';
protected static string|\UnitEnum|null $navigationGroup = 'Hotel';
protected string $view = 'filament.pages.badge-page';
protected static string $translateIdentifier = 'badge-resource';
public bool $badgeWasPreviouslyCreated = false;
/**
* @var array<string, mixed>
*/
public array $data = [];
public static string $roleName = 'badge_page';
public static function canAccess(): bool
{
return auth()->check() && auth()->user()?->can('view::admin::' . static::$roleName) === true;
}
#[\Override]
public function getTitle(): string|Htmlable
{
return __(
sprintf('filament::resources.resources.%s.navigation_label', static::$translateIdentifier),
);
}
public function form(Schema $schema): Schema
{
return $schema
->components([
Section::make(__('filament::resources.tabs.Main'))
->schema([
TextInput::make('code')
->label(__('filament::resources.inputs.badge_code'))
->helperText(__('filament::resources.helpers.badge_code_helper'))
->afterStateUpdated(function (?string $state, Set $set): void {
$set('code', strtoupper($state ?? ''));
})
->suffixAction(fn (): PageAction => PageAction::make('search')->icon('heroicon-o-magnifying-glass')->action(fn () => $this->searchBadgesByCode()),
),
TextInput::make('image')
->label(__('filament::resources.inputs.badge_image'))
->placeholder('...')
->autocomplete()
->visible(fn (Get $get) => isset($this->data['image']))
->prefixAction(
fn (?string $state): PageAction => PageAction::make('visit')
->icon('heroicon-s-arrow-top-right-on-square')
->tooltip(__('filament::resources.common.Open link'))
->url($state)
->visible(fn () => ! in_array($state, [null, '', '0'], true))
->openUrlInNewTab(),
),
]),
Section::make('Nitro Texts')
->collapsible()
->visible(fn () => isset($this->data['nitro']) && ! empty($this->data['nitro']))
->schema([
TextInput::make('nitro.title')
->label(__('filament::resources.inputs.badge_title'))
->placeholder('...')
->visible(fn () => is_array($this->data['nitro']) && array_key_exists('title', $this->data['nitro'])),
TextInput::make('nitro.description')
->label(__('filament::resources.inputs.badge_description'))
->placeholder('...')
->visible(fn () => is_array($this->data['nitro']) && array_key_exists('description', $this->data['nitro'])),
]),
Section::make('Flash Texts')
->collapsible()
->visible(fn () => isset($this->data['flash']) && ! empty($this->data['flash']))
->schema([
TextInput::make('flash.title')
->label(__('filament::resources.inputs.badge_title'))
->placeholder('...')
->visible(fn () => is_array($this->data['flash']) && array_key_exists('title', $this->data['flash'])),
TextInput::make('flash.description')
->label(__('filament::resources.inputs.badge_description'))
->placeholder('...')
->visible(fn () => is_array($this->data['flash']) && array_key_exists('description', $this->data['flash'])),
]),
])
->statePath('data');
}
private function searchBadgesByCode(): void
{
$badgeCode = is_string($this->data['code'] ?? null) ? $this->data['code'] : null;
if (empty($badgeCode)) {
Notification::make()
->color('danger')
->icon('heroicon-o-exclamation-triangle')
->title(__('filament::resources.notifications.badge_code_required'))
->send();
return;
}
$badgeData = app(ExternalTextsParser::class)->getBadgeData((string) $badgeCode);
$nitro = is_array($badgeData['nitro'] ?? null) ? $badgeData['nitro'] : [];
$flash = is_array($badgeData['flash'] ?? null) ? $badgeData['flash'] : [];
$this->badgeWasPreviouslyCreated = ! empty($nitro) || ! empty($flash);
if ($this->badgeWasPreviouslyCreated) {
Notification::make()
->icon('heroicon-o-check-circle')
->iconColor('success')
->color('success')
->title(__('filament::resources.notifications.badge_found'))
->send();
$this->data = [
'code' => (string) $badgeCode,
...$this->getDefaultDataBehavior(
is_string($badgeData['image'] ?? null) ? $badgeData['image'] : null,
is_string($nitro['title'] ?? null) ? $nitro['title'] : null,
is_string($nitro['description'] ?? null) ? $nitro['description'] : null,
is_string($flash['title'] ?? null) ? $flash['title'] : null,
is_string($flash['description'] ?? null) ? $flash['description'] : null,
),
];
return;
}
Notification::make()
->color('success')
->icon('heroicon-o-check-circle')
->iconColor('success')
->title(__('filament::resources.notifications.create_badge'))
->send();
$this->data = [
'code' => (string) $badgeCode,
...$this->getDefaultDataBehavior(),
];
}
/**
* @return array<string, mixed>
*/
private function getDefaultDataBehavior(
?string $badgeImageUrl = null,
?string $nitroTitle = null,
?string $nitroDesc = null,
?string $flashTitle = null,
?string $flashDesc = null,
): array {
return [
'image' => $badgeImageUrl ?? '',
'nitro' => [
'title' => $nitroTitle ?? '',
'description' => $nitroDesc ?? '',
],
'flash' => [
'title' => $flashTitle ?? '',
'description' => $flashDesc ?? '',
],
];
}
public function create(): void
{
$nitroEnabled = config('hotel.client.nitro.enabled');
$flashEnabled = config('hotel.client.flash.enabled');
// image and code fields are required when creating a new badge
if (! $this->badgeWasPreviouslyCreated && (empty($this->data['image']) || empty($this->data['code']))) {
$notificationTitle = empty($this->data['image']) ?
__('filament::resources.notifications.badge_image_required') :
__('filament::resources.notifications.badge_code_required');
Notification::make()
->icon('heroicon-o-exclamation-triangle')
->iconColor('danger')
->color('danger')
->title($notificationTitle)
->send();
return;
}
$externalTextsParser = app(ExternalTextsParser::class);
if ((empty($this->data['nitro']) && $nitroEnabled) || (empty($this->data['flash']) && $flashEnabled)) {
Notification::make()
->icon('heroicon-o-exclamation-triangle')
->iconColor('danger')
->color('danger')
->title(__('filament::resources.notifications.badge_texts_required'))
->send();
return;
}
try {
$this->uploadBadgeImage($externalTextsParser);
if (! empty($this->data['nitro']) && $nitroEnabled) {
$code = is_string($this->data['code'] ?? null) ? $this->data['code'] : '';
$nitro = is_array($this->data['nitro']) ? $this->data['nitro'] : [];
$title = is_string($nitro['title'] ?? null) ? $nitro['title'] : '';
$desc = is_string($nitro['description'] ?? null) ? $nitro['description'] : '';
$externalTextsParser->updateNitroBadgeTexts($code, $title, $desc);
}
if (! empty($this->data['flash']) && $flashEnabled) {
$code = is_string($this->data['code'] ?? null) ? $this->data['code'] : '';
$flash = is_array($this->data['flash']) ? $this->data['flash'] : [];
$title = is_string($flash['title'] ?? null) ? $flash['title'] : '';
$desc = is_string($flash['description'] ?? null) ? $flash['description'] : '';
$externalTextsParser->updateFlashBadgeTexts($code, $title, $desc);
}
} catch (Throwable $exception) {
Log::channel('badge')->error('[ORION BADGE RESOURCE] - ERROR: ' . $exception->getMessage());
Notification::make()
->icon('heroicon-o-exclamation-triangle')
->iconColor('danger')
->color('danger')
->title(__('filament::resources.notifications.badge_update_failed'))
->send();
return;
}
$this->data['image'] = $externalTextsParser->getBadgeImageUrl(is_string($this->data['code'] ?? null) ? $this->data['code'] : '');
$this->badgeWasPreviouslyCreated = true;
Notification::make()
->icon('heroicon-o-check-circle')
->iconColor('success')
->color('success')
->title(__('filament::resources.notifications.badge_updated'))
->send();
}
protected function uploadBadgeImage(ExternalTextsParser $parser): void
{
$imageUrl = is_string($this->data['image'] ?? null) ? $this->data['image'] : '';
$code = is_string($this->data['code'] ?? null) ? $this->data['code'] : '';
if ($imageUrl === '' || ! filter_var($imageUrl, FILTER_VALIDATE_URL)) {
return;
}
if ($imageUrl === $parser->getBadgeImageUrl($code)) {
return;
}
$image = Http::get($imageUrl);
if (! $image->successful()) {
return;
}
$contentType = $image->header('content-type');
$gdImage = match ($contentType) {
'image/png' => imagecreatefrompng($imageUrl),
'image/gif' => imagecreatefromgif($imageUrl),
'image/jpeg' => imagecreatefromjpeg($imageUrl),
default => false
};
if ($gdImage === false) {
Notification::make()
->icon('heroicon-o-exclamation-triangle')
->iconColor('danger')
->color('danger')
->title(__('filament::resources.notifications.badge_image_upload_failed'))
->send();
return;
}
$basePath = config('hotel.client.flash.relative_files_path');
$basePathStr = is_string($basePath) ? $basePath : '';
$uploadPath = public_path(sprintf('%s%s%s.gif', rtrim($basePathStr, '\//'), '/c_images/album1584/', $code));
imagegif($gdImage, $uploadPath);
}
/**
* @return array<\Filament\Actions\Action|ActionGroup>
*/
/**
* @return array<\Filament\Actions\Action|ActionGroup>
*/
protected function getHeaderActions(): array
{
return [
PageAction::make('save')
->label(__('filament::resources.common.Update'))
->action(fn () => $this->create())
->color('primary')
->visible(fn () => isset($this->data['code']) && $this->badgeWasPreviouslyCreated),
PageAction::make('create')
->label(__('filament::resources.common.Create'))
->action(fn () => $this->create())
->color('success')
->visible(fn () => isset($this->data['code']) && ! $this->badgeWasPreviouslyCreated),
];
}
}