feat: implement language selector component with responsive design for improved user experience across devices

This commit is contained in:
Ümit Tunç
2026-05-21 08:53:44 +03:00
parent 1eab2c856b
commit da0ee2477b
4 changed files with 184 additions and 40 deletions
+54 -7
View File
@@ -5,7 +5,10 @@ namespace App\Services;
use App\Models\HeaderTemplate;
use App\Models\SectionTemplate;
use App\Models\FooterTemplate;
use App\Models\Setting;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\View;
use Filament\Forms\Components\{
TextInput, Textarea, Select, Checkbox, CheckboxList,
Radio, Toggle, ToggleButtons, DateTimePicker, DatePicker,
@@ -294,11 +297,15 @@ class TemplateService
*/
protected static function getSelectOptions(string $fieldName): array
{
return config("template-options.{$fieldName}", [
$defaults = [
'option_1' => __('Option 1'),
'option_2' => __('Option 2'),
'option_3' => __('Option 3'),
]);
];
$options = config("template-options.{$fieldName}", $defaults);
return is_array($options) ? $options : $defaults;
}
/**
@@ -376,6 +383,15 @@ class TemplateService
}
// Handle custom blade components: {custom.component_name} or {custom.component-name}
if (str_contains($html, '{custom.language-selector}')) {
$desktopLanguage = view('components.custom.language-selector', [
'variant' => 'default',
])->render();
$html = str_replace('{custom.language-selector}', $desktopLanguage, $html);
$html = self::injectOffcanvasLanguageSelector($html);
}
preg_match_all('/\{custom\.([a-z][a-z_-]*)\}/i', $html, $customMatches);
if (!empty($customMatches[0])) {
foreach ($customMatches[0] as $index => $fullMatch) {
@@ -383,8 +399,12 @@ class TemplateService
if ($componentName) {
// Normalize component name to lowercase for consistent file system access
$componentName = strtolower($componentName);
if ($componentName === 'language-selector') {
continue;
}
$viewPath = "components.custom.{$componentName}";
if (view()->exists($viewPath)) {
if (View::exists($viewPath)) {
try {
$renderedComponent = view($viewPath)->render();
// Ensure rendered component is properly formatted
@@ -392,7 +412,7 @@ class TemplateService
$html = str_replace($fullMatch, $renderedComponent, $html);
} catch (\Exception $e) {
// Log the error for debugging
\Log::error("Custom component render error: {$viewPath}", [
Log::error("Custom component render error: {$viewPath}", [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
@@ -502,10 +522,10 @@ class TemplateService
// Handle setting.* placeholders - get value from Setting model
if ($type === 'setting' && $field) {
$value = setting($field, '');
// Get setting type to determine if it's a file/image
$settingModel = \App\Models\Setting::where('key', $field)->where('is_active', true)->first();
if ($settingModel && in_array($settingModel->type, ['file', 'image'])) {
$settingModel = Setting::findActiveByKey($field);
if ($settingModel && in_array($settingModel->type, ['file', 'image'], true)) {
// For file/image settings, use file type for formatting
$type = 'file';
}
@@ -660,5 +680,32 @@ class TemplateService
return $value;
}
/**
* Inject mobile language selector at the top of the first offcanvas menu body.
*/
protected static function injectOffcanvasLanguageSelector(string $html): string
{
if (str_contains($html, 'offcanvas-language-mobile-wrap')) {
return $html;
}
$mobileLanguage = view('components.custom.language-selector', [
'variant' => 'offcanvas',
'class' => 'offcanvas-language-mobile',
])->render();
$injection = '<div class="xl:!hidden lg:!hidden pb-4 mb-2 border-b border-white/10 offcanvas-language-mobile-wrap">'
. $mobileLanguage
. '</div>';
$pattern = '/(<div[^>]*class="[^"]*offcanvas-body[^"]*"[^>]*>)/i';
if (preg_match($pattern, $html)) {
return preg_replace($pattern, '$1' . $injection, $html, 1);
}
return $html;
}
}