Skip to content

Commit

Permalink
feat(hk): badge and room ad management (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
duckietm authored Jan 9, 2025
1 parent ba5235d commit 40204e6
Show file tree
Hide file tree
Showing 36 changed files with 1,174 additions and 88 deletions.
83 changes: 83 additions & 0 deletions app/Console/Commands/ImportAdsData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace App\Console\Commands;

use App\Models\WebsiteAd;
use App\Services\SettingsService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Collection;

class ImportAdsData extends Command
{
protected $signature = 'import:ads-data';
protected $description = 'Import ads data from the filesystem';

private const CHUNK_SIZE = 100;
private const ALLOWED_EXTENSIONS = ['jpeg', 'jpg', 'png', 'gif'];

public function handle(SettingsService $settingsService): void
{
$adsPath = $settingsService->getOrDefault('ads_path_filesystem');

if (!$this->validatePath($adsPath)) {
return;
}

$files = $this->getImageFiles($adsPath);

if (empty($files)) {
$this->warn('No valid image files found in the ads directory.');
return;
}

$this->processFiles($files);

$this->info('Ads data import completed successfully.');
}

private function validatePath(?string $adsPath): bool
{
if (empty($adsPath)) {
$this->error('Ads path is not configured in website_settings.');
return false;
}

if (!is_dir($adsPath)) {
$this->error("The ads path '{$adsPath}' does not exist in the filesystem.");
return false;
}

return true;
}

private function getImageFiles(string $adsPath): array
{
return array_filter(scandir($adsPath), function ($file) use ($adsPath) {
$filePath = $adsPath . DIRECTORY_SEPARATOR . $file;
return is_file($filePath) &&
in_array(strtolower(pathinfo($file, PATHINFO_EXTENSION)), self::ALLOWED_EXTENSIONS);
});
}

private function processFiles(array $files): void
{
// Get existing images to avoid duplicates
$existingImages = WebsiteAd::pluck('image')->toArray();

$newFiles = Collection::make($files)
->filter(fn($file) => !in_array($file, $existingImages))
->map(fn($file) => ['image' => $file])
->values();

$skippedCount = count($files) - $newFiles->count();
if ($skippedCount > 0) {
$this->warn("Skipped {$skippedCount} existing files.");
}

$newFiles->chunk(self::CHUNK_SIZE)->each(function ($chunk) {
WebsiteAd::insert($chunk->toArray());
$this->info("Processed " . $chunk->count() . " files.");
});
}
}
79 changes: 79 additions & 0 deletions app/Console/Commands/ImportBadgeData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\WebsiteBadgedata;
use App\Services\SettingsService;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Collection;

class ImportBadgeData extends Command
{
protected $signature = 'import:badge-data';
protected $description = 'Import badge data from JSON file';

private const CHUNK_SIZE = 100;
private const BADGE_PREFIX = 'badge_desc_';

public function __construct(
private readonly SettingsService $settingsService
) {
parent::__construct();
}

public function handle(): void
{
$jsonPath = $this->settingsService->getOrDefault('nitro_external_texts_file');

if (!$this->validateJsonFile($jsonPath)) {
return;
}

try {
$this->processBadgeData($jsonPath);
$this->info('Badge data imported successfully.');
} catch (\Exception $e) {
Log::error('Failed to import badge data: ' . $e->getMessage());
$this->error('Failed to import badge data. Check the logs for details.');
}
}

private function validateJsonFile(?string $jsonPath): bool
{
if (empty($jsonPath)) {
$this->error('The JSON file path is not configured in the website settings.');
return false;
}

if (!file_exists($jsonPath)) {
$this->error('The JSON file does not exist at the specified path: ' . $jsonPath);
return false;
}

return true;
}

private function processBadgeData(string $jsonPath): void
{
$badgeData = Collection::make(File::json($jsonPath))
->filter(fn($value, $key) => str_starts_with($key, self::BADGE_PREFIX))
->map(fn($value, $key) => [
'badge_key' => $key,
'badge_name' => str_replace(self::BADGE_PREFIX, '', $key),
'badge_description' => $value,
])
->values();

$badgeData->chunk(self::CHUNK_SIZE)->each(function ($chunk) {
WebsiteBadgedata::upsert(
$chunk->toArray(),
['badge_key'],
['badge_name', 'badge_description']
);

$this->info("Processed " . $chunk->count() . " badges.");
});
}
}
2 changes: 1 addition & 1 deletion app/Filament/Resources/Atom/CameraWebResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Filament\Forms\Components\Toggle;
use Filament\Forms\Form;
use Filament\Tables\Table;
use App\Filament\Resources\Atom\FotoResource\Pages;
use App\Filament\Resources\Atom\CameraWebResource\Pages;
use Filament\Resources\Resource;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Columns\TextColumn;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Filament\Resources\Atom\FotoResource\Pages;
namespace App\Filament\Resources\Atom\CameraWebResource\Pages;

use App\Filament\Resources\Atom\CameraWebResource;
use Filament\Actions;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Filament\Resources\Atom\FotoResource\Pages;
namespace App\Filament\Resources\Atom\CameraWebResource\Pages;

use App\Filament\Resources\Atom\CameraWebResource;
use Filament\Actions;
Expand Down
87 changes: 87 additions & 0 deletions app/Filament/Resources/Hotel/BadgeTextEditorResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace App\Filament\Resources\Hotel;

use App\Filament\Resources\Hotel\BadgeTextEditorResource\Pages;
use App\Models\WebsiteBadgedata;
use App\Services\SettingsService;
use Filament\Forms;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Columns\ImageColumn;
use Filament\Tables\Actions\Action;
use Filament\Tables\Actions\DeleteAction;
use Illuminate\Support\Facades\Log;

class BadgeTextEditorResource extends Resource
{
protected static ?string $model = WebsiteBadgedata::class;

protected static ?string $navigationGroup = 'Hotel';
protected static ?string $navigationIcon = 'heroicon-o-pencil-square';
protected static ?string $navigationLabel = 'Badge Editor';
protected static ?string $modelLabel = 'Badge Text';
protected static ?string $slug = 'hotel/badge-text-editor';

public static function form(Forms\Form $form): Forms\Form
{
return $form
->schema([
Forms\Components\TextInput::make('badge_key')
->required()
->label('Badge Key - You must add badge_desc_')
->default('badge_desc_')
->placeholder('e.g., badge_desc_XXXX'),
Forms\Components\TextInput::make('badge_name')
->required()
->label('Badge Name')
->placeholder('e.g., XXXX'),
Forms\Components\Textarea::make('badge_description')
->required()
->label('Badge Description')
->placeholder('Please add a description for the badge.'),
]);
}

public static function table(Tables\Table $table): Tables\Table
{
$settingsService = app(SettingsService::class);
$badgesPath = $settingsService->getOrDefault('badges_path', '/gamedata/c_images/album1584/');

return $table
->columns([
Tables\Columns\ImageColumn::make('badge_key')
->label('Badge Image')
->getStateUsing(function ($record) use ($badgesPath) {
$badgeName = str_replace('badge_desc_', '', $record->badge_key);
$imageUrl = asset($badgesPath . $badgeName . '.gif');
return $imageUrl;
})
->width(50)
->height(50),
TextColumn::make('badge_name')
->label('Badge Name')
->searchable()
->sortable(),
TextColumn::make('badge_description')
->label('Badge Description')
->searchable(),
])
->filters([])
->defaultSort('badge_key', 'asc')
->actions([
Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
]);
}

public static function getPages(): array
{
return [
'index' => Pages\ListBadgeTextEditors::route('/'),
'create' => Pages\CreateBadgeTextEditor::route('/create'),
'edit' => Pages\EditBadgeTextEditor::route('/{record}/edit'),
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Filament\Resources\Hotel\BadgeTextEditorResource\Pages;

use App\Filament\Resources\Hotel\BadgeTextEditorResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;

class CreateBadgeTextEditor extends CreateRecord
{
protected static string $resource = BadgeTextEditorResource::class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace App\Filament\Resources\Hotel\BadgeTextEditorResource\Pages;

use App\Filament\Resources\Hotel\BadgeTextEditorResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
use PDOException;
use Filament\Notifications\Notification;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\Model;

class EditBadgeTextEditor extends EditRecord
{
protected static string $resource = BadgeTextEditorResource::class;

protected function getActions(): array
{
return [Actions\DeleteAction::make()];
}

protected function mutateFormDataBeforeSave(array $data): array
{
return $data;
}

protected function afterSave(): void {}

protected function handleRecordUpdate(Model $record, array $data): Model
{
try {
return parent::handleRecordUpdate($record, $data);
} catch (PDOException $e) {
if ($e->getCode() === '23000') {
Log::error('Duplicate badge key error: ' . $e->getMessage());

Notification::make()
->title('Duplicate Badge Key')
->body('The badge key already exists. Please use a unique badge key.')
->danger()
->persistent()
->send();

return $record;
}
throw $e;
}
}
}
Loading

0 comments on commit 40204e6

Please sign in to comment.