From 95f50b00a90d846e6a5eff72cab2c9f2e5f90ec6 Mon Sep 17 00:00:00 2001 From: bernardhanna Date: Mon, 9 Feb 2026 15:34:56 +0000 Subject: [PATCH] make adding slides dynamic --- app/HomeSlide.php | 13 ++++++--- app/Http/Controllers/HomeController.php | 10 +++++++ app/Nova/HomeSlide.php | 14 +++++---- ...150000_add_open_new_tab_to_home_slides.php | 29 +++++++++++++++++++ resources/views/static/home.blade.php | 14 +++++---- 5 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 database/migrations/2026_02_09_150000_add_open_new_tab_to_home_slides.php diff --git a/app/HomeSlide.php b/app/HomeSlide.php index a5a526d57..5cc5c8a8d 100644 --- a/app/HomeSlide.php +++ b/app/HomeSlide.php @@ -11,8 +11,10 @@ class HomeSlide extends Model 'description', 'url', 'button_text', + 'open_primary_new_tab', 'url2', 'button2_text', + 'open_second_new_tab', 'image', 'position', 'active', @@ -25,6 +27,8 @@ class HomeSlide extends Model 'show_countdown' => 'boolean', 'countdown_target' => 'datetime', 'position' => 'integer', + 'open_primary_new_tab' => 'boolean', + 'open_second_new_tab' => 'boolean', ]; public function scopeActive($query) @@ -38,16 +42,17 @@ public function scopeOrdered($query) } /** - * Full URL for image (prefix with base URL if stored as path). + * Full URL for image. Use asset() for paths so images in public/ resolve correctly. */ public function getImageUrlAttribute(): ?string { if (empty($this->image)) { return null; } - if (str_starts_with($this->image, 'http://') || str_starts_with($this->image, 'https://')) { - return $this->image; + $value = trim($this->image); + if (str_starts_with($value, 'http://') || str_starts_with($value, 'https://')) { + return $value; } - return url(ltrim($this->image, '/')); + return asset(ltrim($value, '/')); } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 97d98c648..9a37bd753 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -30,8 +30,10 @@ private function getActivities() 'description' => $slide->description ?? '', 'url' => $slide->url, 'btn_lang' => $slide->button_text, + 'open_primary_new_tab' => $slide->open_primary_new_tab ?? false, 'url2' => $slide->url2, 'btn2_lang' => $slide->button2_text, + 'open_second_new_tab' => $slide->open_second_new_tab ?? false, 'image' => $slide->image_url, 'show_countdown' => $slide->show_countdown, 'countdown_target' => $slide->countdown_target?->toIso8601String(), @@ -54,8 +56,10 @@ private function getActivities() 'description' => 'home.banner5_description', 'url' => '/future-ready-csr', 'btn_lang' => 'home.learn_more', + 'open_primary_new_tab' => false, 'url2' => null, 'btn2_lang' => null, + 'open_second_new_tab' => false, 'image' => $defaultImages[0] ?? null, 'show_countdown' => false, 'countdown_target' => null, @@ -65,8 +69,10 @@ private function getActivities() 'description' => 'home.banner4_description', 'url' => 'https://codeweek.eu/blog/code-week-digital-educator-awards-2025/', 'btn_lang' => 'home.view_winners', + 'open_primary_new_tab' => false, 'url2' => 'https://codeweek.eu/blog/code-week-digital-educator-awards-2025/', 'btn2_lang' => null, + 'open_second_new_tab' => false, 'image' => $defaultImages[1] ?? null, 'show_countdown' => false, 'countdown_target' => null, @@ -76,8 +82,10 @@ private function getActivities() 'description' => 'home.banner6_description', 'url' => 'https://airtable.com/appW5W6DJ6CI6SVdH/pagLDrU2NQja9F2vu/form', 'btn_lang' => 'home.register_here', + 'open_primary_new_tab' => false, 'url2' => null, 'btn2_lang' => null, + 'open_second_new_tab' => false, 'image' => $defaultImages[2] ?? null, 'show_countdown' => false, 'countdown_target' => null, @@ -87,8 +95,10 @@ private function getActivities() 'description' => 'home.when_text', 'url' => '/guide', 'btn_lang' => 'home.get_involved', + 'open_primary_new_tab' => false, 'url2' => '/blog/code-week-25-programme/', 'btn2_lang' => null, + 'open_second_new_tab' => false, 'image' => $defaultImages[3] ?? null, 'show_countdown' => false, 'countdown_target' => null, diff --git a/app/Nova/HomeSlide.php b/app/Nova/HomeSlide.php index 7cef72a37..d70df9bbf 100644 --- a/app/Nova/HomeSlide.php +++ b/app/Nova/HomeSlide.php @@ -42,21 +42,25 @@ public function fields(Request $request): array ID::make()->sortable(), Text::make('Title', 'title') ->rules('required') - ->help('Lang key (e.g. home.banner1_title) or plain text.'), + ->help('Use a lang key (e.g. home.banner1_title) for translated content, or type plain text.'), Textarea::make('Description', 'description') ->nullable() - ->help('Lang key or plain text.'), + ->help('Use a lang key for translated content, or plain text.'), Text::make('Primary button URL', 'url')->rules('required')->hideFromIndex(), Text::make('Primary button label', 'button_text') ->rules('required') - ->help('Lang key (e.g. home.learn_more) or plain text.'), + ->help('Lang key (e.g. home.learn_more) for translation, or plain text.'), + Boolean::make('Open primary link in new tab', 'open_primary_new_tab') + ->help('Open the primary button link in a new window/tab.'), Text::make('Second button URL', 'url2')->nullable()->hideFromIndex(), Text::make('Second button label', 'button2_text') ->nullable() - ->help('Leave empty to hide second button.'), + ->help('Leave empty to hide second button. Use lang key for translation.'), + Boolean::make('Open second link in new tab', 'open_second_new_tab') + ->help('Open the second button link in a new window/tab.'), Text::make('Image', 'image') ->nullable() - ->help('Path e.g. /images/homepage/slide1.png or full URL. Used as slide background.'), + ->help('Path from site root e.g. images/dream-jobs/dream_jobs_bg.png (no leading slash), or full URL. Used as slide background.'), Number::make('Position', 'position') ->min(0) ->default(0) diff --git a/database/migrations/2026_02_09_150000_add_open_new_tab_to_home_slides.php b/database/migrations/2026_02_09_150000_add_open_new_tab_to_home_slides.php new file mode 100644 index 000000000..6d07cb9e4 --- /dev/null +++ b/database/migrations/2026_02_09_150000_add_open_new_tab_to_home_slides.php @@ -0,0 +1,29 @@ +boolean('open_primary_new_tab')->default(false)->after('button_text'); + $table->boolean('open_second_new_tab')->default(false)->after('button2_text'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('home_slides', function (Blueprint $table) { + $table->dropColumn(['open_primary_new_tab', 'open_second_new_tab']); + }); + } +}; diff --git a/resources/views/static/home.blade.php b/resources/views/static/home.blade.php index 6b352347d..59db15a21 100644 --- a/resources/views/static/home.blade.php +++ b/resources/views/static/home.blade.php @@ -90,7 +90,7 @@ function countdownTimer(targetDate) {

- @lang($activity['title']) + {{ __($activity['title']) }}

@@ -98,14 +98,16 @@ class="text-xl md:text-2xl leading-8 text-[#333E48] p-0 mb-4 max-md:max-w-full m

- @lang($activity['btn_lang']) + href="{{ $activity['url'] }}" + @if(!empty($activity['open_primary_new_tab'])) target="_blank" rel="noopener noreferrer" @endif> + {{ __($activity['btn_lang']) }} - @if (isset($activity['btn2_lang']) && !is_null($activity['btn2_lang'])) + @if (isset($activity['btn2_lang']) && !is_null($activity['btn2_lang']) && $activity['btn2_lang'] !== '') - @lang($activity['btn2_lang']) + href="{{ $activity['url2'] }}" + @if(!empty($activity['open_second_new_tab'])) target="_blank" rel="noopener noreferrer" @endif> + {{ __($activity['btn2_lang']) }}