Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project will be documented in this file.

## [1.5.0] - 2026-02-22

### Added
- Configurable background frame for printed card PDFs: supervisors set a system-wide default, users can upload a personal override in their profile, with automatic fallback to the built-in card back image

## [1.4.0] - 2026-02-21

### Added
Expand Down
139 changes: 139 additions & 0 deletions app/Filament/Pages/PdfSettings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php
/**
* Webtech-solutions 2025, All rights reserved.
*/

namespace App\Filament\Pages;

use App\Models\WebsiteSetting;
use Filament\Actions\Action;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Notifications\Notification;
use Filament\Pages\Page;

class PdfSettings extends Page implements HasForms
{
use InteractsWithForms;

protected static ?string $navigationIcon = 'heroicon-o-printer';

protected static ?string $navigationLabel = 'PDF Settings';

protected static ?string $navigationGroup = 'Administration';

protected static ?int $navigationSort = 10;

protected static string $view = 'filament.pages.pdf-settings';

public ?array $data = [];

/**
* Only supervisors can access this page.
*/
public static function canAccess(): bool
{
return auth()->check() && auth()->user()->isSupervisor();
}

/**
* Load current settings into the form.
*/
public function mount(): void
{
$this->form->fill([
'card_pdf_background' => WebsiteSetting::get('card_pdf_background'),
'card_pdf_overlay' => WebsiteSetting::get('card_pdf_overlay', 'dark'),
]);
}

/**
* Define the settings form.
*/
public function form(Form $form): Form
{
return $form
->schema([
Section::make('Card Print Background')
->description('Upload a default background image applied to all printed card PDFs. Users may override this with their own background in their profile.')
->icon('heroicon-o-photo')
->schema([
FileUpload::make('card_pdf_background')
->label('Default Card Background Image')
->disk('public')
->directory('pdf-backgrounds')
->image()
->imageEditor()
->maxSize(5120)
->helperText('Recommended: match your card dimensions. Falls back to the built-in card back image if not set.')
->columnSpanFull(),
Select::make('card_pdf_overlay')
->label('Default Overlay Style')
->options([
'dark' => 'Dark — dark overlay, light text (best for light backgrounds)',
'light' => 'Light — light overlay, dark text (best for light backgrounds)',
])
->default('dark')
->required()
->helperText('Controls the overlay tint and text colours applied over the card background. Decks can override this individually.')
->columnSpanFull(),
]),
])
->statePath('data');
}

/**
* Save the settings to the database.
*/
public function save(): void
{
$data = $this->form->getState();

WebsiteSetting::updateOrCreate(
['key' => 'card_pdf_background'],
[
'value' => $data['card_pdf_background'] ?? null,
'type' => 'text',
'group' => 'general',
'label' => 'Card PDF Background',
'description' => 'System-wide default background image for printed card PDFs.',
'order' => 1,
]
);

WebsiteSetting::updateOrCreate(
['key' => 'card_pdf_overlay'],
[
'value' => $data['card_pdf_overlay'] ?? 'dark',
'type' => 'text',
'group' => 'general',
'label' => 'Card PDF Overlay Style',
'description' => 'System-wide default overlay style (dark or light) for printed card PDFs.',
'order' => 2,
]
);

Notification::make()
->title('PDF settings saved successfully.')
->success()
->send();
}

/**
* Get the header actions.
*/
protected function getHeaderActions(): array
{
return [
Action::make('save')
->label('Save Settings')
->icon('heroicon-o-check')
->color('primary')
->action('save'),
];
}
}
26 changes: 26 additions & 0 deletions app/Filament/Resources/DeckResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use App\Models\Deck;
use App\Models\Game;
use Filament\Forms;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Select;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
Expand Down Expand Up @@ -83,6 +85,30 @@ public static function form(Form $form): Form
->collapsible(),
])
->columns(2),
Forms\Components\Section::make('Print Settings')
->description('Customize how this deck looks when printed as a PDF')
->schema([
FileUpload::make('pdf_background')
->label('Card Background Image')
->disk('public')
->directory('pdf-backgrounds')
->image()
->imageEditor()
->maxSize(5120)
->helperText('Overrides the system default. Appears behind each card illustration in the printed PDF.')
->columnSpanFull(),
Select::make('pdf_overlay')
->label('Overlay Style')
->options([
'dark' => 'Dark — dark overlay, light text',
'light' => 'Light — light overlay, dark text',
])
->placeholder('Use system default')
->helperText('Overrides the system default overlay style for this deck only.')
->columnSpanFull(),
])
->collapsible(),

Forms\Components\Section::make('Cards in Deck')
->description('There is the list of cards on this deck')
->schema([
Expand Down
2 changes: 2 additions & 0 deletions app/Models/Deck.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Deck extends Model
'deck_name',
'deck_description',
'deck_data',
'pdf_background',
'pdf_overlay',
];

public function game()
Expand Down
41 changes: 33 additions & 8 deletions app/Services/DeckPdfService.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use App\Models\Card;
use App\Models\Deck;
use App\Models\WebsiteSetting;
use Barryvdh\DomPDF\Facade\Pdf;
use Illuminate\Support\Facades\Storage;

Expand Down Expand Up @@ -61,19 +62,38 @@ public function expandCards(Deck $deck): array
}

/**
* Resolve the filesystem path for a card image, falling back to the placeholder.
* Resolve the background image for the card layer:
* - If the card has its own illustration, use that.
* - Otherwise fall through: deck override → system default → built-in placeholder.
*/
protected function resolveImagePath(Card $card): string
protected function resolveImagePath(Card $card, Deck $deck): string
{
$placeholder = public_path('images/cardsforge-back.png');
if (!empty($card->image)) {
$path = Storage::disk('public')->path($card->image);
if (file_exists($path)) {
return $path;
}
}

if (empty($card->image)) {
return $placeholder;
// 1. Deck override
if (!empty($deck->pdf_background)) {
$path = Storage::disk('public')->path($deck->pdf_background);
if (file_exists($path)) {
return $path;
}
}

$path = Storage::disk('public')->path($card->image);
// 2. System default
$setting = WebsiteSetting::get('card_pdf_background');
if (!empty($setting)) {
$path = Storage::disk('public')->path($setting);
if (file_exists($path)) {
return $path;
}
}

return file_exists($path) ? $path : $placeholder;
// 3. Built-in fallback
return public_path('images/cardsforge-back.png');
}

/**
Expand All @@ -88,13 +108,17 @@ public function download(Deck $deck): \Symfony\Component\HttpFoundation\Streamed
$cardWidth = $deck->game->card_width_mm ?? 63.5;
$cardHeight = $deck->game->card_height_mm ?? 88.9;

// Resolve overlay mode: deck → system default → 'dark'
$overlayMode = $deck->pdf_overlay
?? WebsiteSetting::get('card_pdf_overlay', 'dark');

$pagesData = [];
foreach ($pages as $pageCards) {
$pageItems = [];
foreach ($pageCards as $card) {
$pageItems[] = [
'card' => $card,
'imagePath' => $this->resolveImagePath($card),
'imagePath' => $this->resolveImagePath($card, $deck),
];
}
$pagesData[] = $pageItems;
Expand All @@ -105,6 +129,7 @@ public function download(Deck $deck): \Symfony\Component\HttpFoundation\Streamed
'pages' => $pagesData,
'cardWidth' => $cardWidth,
'cardHeight' => $cardHeight,
'overlayMode' => $overlayMode,
])
->setPaper('a4', 'portrait')
->setOption('isHtml5ParserEnabled', true)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* Webtech-solutions 2025, All rights reserved.
*/

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('pdf_background')->nullable()->after('avatar_url');
});
}

public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('pdf_background');
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Webtech-solutions 2025, All rights reserved.
*/

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('decks', function (Blueprint $table) {
$table->string('pdf_background')->nullable()->after('deck_description');
});

Schema::table('users', function (Blueprint $table) {
$table->dropColumn('pdf_background');
});
}

public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->string('pdf_background')->nullable()->after('avatar_url');
});

Schema::table('decks', function (Blueprint $table) {
$table->dropColumn('pdf_background');
});
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* Webtech-solutions 2025, All rights reserved.
*/

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
public function up(): void
{
Schema::table('decks', function (Blueprint $table) {
$table->string('pdf_overlay')->nullable()->default(null)->after('pdf_background');
});
}

public function down(): void
{
Schema::table('decks', function (Blueprint $table) {
$table->dropColumn('pdf_overlay');
});
}
};
5 changes: 5 additions & 0 deletions resources/views/filament/pages/pdf-settings.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<x-filament-panels::page>
<x-filament-panels::form wire:submit="save">
{{ $this->form }}
</x-filament-panels::form>
</x-filament-panels::page>
Loading
Loading