added more translations and added the new layout wizard

This commit is contained in:
Codex Agent
2025-12-11 16:55:12 +01:00
parent b4417db5cd
commit 57be7d0030
15 changed files with 4951 additions and 2897 deletions

View File

@@ -132,6 +132,7 @@ class EventJoinTokenController extends Controller
'metadata.layout_customization.instructions.*' => ['nullable', 'string', 'max:160'],
'metadata.layout_customization.logo_url' => ['nullable', 'string', 'max:2048'],
'metadata.layout_customization.logo_data_url' => ['nullable', 'string'],
'metadata.layout_customization.background_preset' => ['nullable', 'string', 'max:120'],
'metadata.layout_customization.accent_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
'metadata.layout_customization.text_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
'metadata.layout_customization.background_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],

View File

@@ -14,6 +14,17 @@ use SimpleSoftwareIO\QrCode\Facades\QrCode;
class EventJoinTokenLayoutController extends Controller
{
/**
* Mapping of preset keys to portrait background assets.
*
* @var array<string, string>
*/
private const BACKGROUND_PRESETS = [
'bg-blue-floral' => 'storage/layouts/backgrounds-portrait/bg-blue-floral.png',
'bg-goldframe' => 'storage/layouts/backgrounds-portrait/bg-goldframe.png',
'gr-green-floral' => 'storage/layouts/backgrounds-portrait/gr-green-floral.png',
];
public function index(Request $request, Event $event, EventJoinToken $joinToken)
{
$this->ensureBelongsToEvent($event, $joinToken);
@@ -59,6 +70,7 @@ class EventJoinTokenLayoutController extends Controller
$backgroundStyle = $this->buildBackgroundStyle($layoutConfig);
$eventName = $this->resolveEventName($event);
$backgroundImage = $layoutConfig['background_image'] ?? null;
$viewData = [
'layout' => $layoutConfig,
@@ -68,6 +80,7 @@ class EventJoinTokenLayoutController extends Controller
'tokenUrl' => $tokenUrl,
'qrPngDataUri' => $qrPngDataUri,
'backgroundStyle' => $backgroundStyle,
'backgroundImage' => $backgroundImage,
'customization' => $joinToken->metadata['layout_customization'] ?? null,
'advancedLayout' => $this->buildAdvancedLayout(
$layoutConfig,
@@ -200,11 +213,23 @@ class EventJoinTokenLayoutController extends Controller
$layout['logo_url'] = $customization['logo_url'];
}
if (! empty($customization['background_preset']) && is_string($customization['background_preset'])) {
$presetImage = $this->resolveBackgroundPreset($customization['background_preset']);
if ($presetImage) {
$layout['background_image'] = $presetImage;
$layout['background_preset'] = $customization['background_preset'];
}
}
return $layout;
}
private function buildBackgroundStyle(array $layout): string
{
if (! empty($layout['background_image']) && is_string($layout['background_image'])) {
return sprintf('url(%s) center center / cover no-repeat', $layout['background_image']);
}
$gradient = $layout['background_gradient'] ?? null;
if (is_array($gradient) && ! empty($gradient['stops'])) {
@@ -239,6 +264,11 @@ class EventJoinTokenLayoutController extends Controller
$text = $layout['text'] ?? '#0F172A';
$secondary = $layout['secondary'] ?? '#1F2937';
$badge = $layout['badge'] ?? $accent;
$backgroundImage = $layout['background_image'] ?? null;
if (! $backgroundImage && ! empty($customization['background_preset']) && is_string($customization['background_preset'])) {
$backgroundImage = $this->resolveBackgroundPreset($customization['background_preset']);
}
$resolved = [];
@@ -306,6 +336,7 @@ class EventJoinTokenLayoutController extends Controller
'width' => $width,
'height' => $height,
'background' => $layout['background'] ?? '#FFFFFF',
'background_image' => $backgroundImage,
'background_gradient' => $layout['background_gradient'] ?? null,
'accent' => $accent,
'text' => $text,
@@ -317,6 +348,30 @@ class EventJoinTokenLayoutController extends Controller
];
}
private function resolveBackgroundPreset(string $preset): ?string
{
$path = self::BACKGROUND_PRESETS[$preset] ?? null;
if (! $path) {
return null;
}
$fullPath = public_path($path);
if (! file_exists($fullPath) || ! is_readable($fullPath)) {
return null;
}
$mime = mime_content_type($fullPath) ?: 'image/png';
$data = @file_get_contents($fullPath);
if ($data === false) {
return null;
}
return 'data:'.$mime.';base64,'.base64_encode($data);
}
private function resolveElementContent(string $type, array $customization, array $layout, string $eventName, string $tokenUrl, $fallback = null): ?string
{
return match ($type) {