From bc76734a727b702d7ff69e93cbfd632c3a86648a Mon Sep 17 00:00:00 2001
From: bernardhanna
Date: Wed, 25 Feb 2026 11:20:30 +0000
Subject: [PATCH] c404 fix
---
app/HackathonsPage.php | 2 +
app/Nova/DreamJobsPage.php | 72 ++-------------
app/Nova/HackathonsPage.php | 90 ++-----------------
...16_140000_create_hackathons_page_table.php | 2 +
..._extra_button_to_hackathons_page_table.php | 37 ++++++++
resources/views/hackathons/index.blade.php | 8 ++
6 files changed, 63 insertions(+), 148 deletions(-)
create mode 100644 database/migrations/2026_02_16_141000_add_extra_button_to_hackathons_page_table.php
diff --git a/app/HackathonsPage.php b/app/HackathonsPage.php
index fa732ce1a..60f511146 100644
--- a/app/HackathonsPage.php
+++ b/app/HackathonsPage.php
@@ -21,6 +21,8 @@ class HackathonsPage extends Model
'details_paragraph_3',
'details_paragraph_4',
'video_url',
+ 'extra_button_text',
+ 'extra_button_link',
'recap_button_text',
'recap_button_link',
'toolkit_button_text',
diff --git a/app/Nova/DreamJobsPage.php b/app/Nova/DreamJobsPage.php
index 7b56d4db6..25b7a4c6a 100644
--- a/app/Nova/DreamJobsPage.php
+++ b/app/Nova/DreamJobsPage.php
@@ -4,6 +4,7 @@
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Boolean;
+use Laravel\Nova\Fields\Code;
use Laravel\Nova\Fields\HasMany;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
@@ -39,70 +40,8 @@ public static function indexQuery(NovaRequest $request, $query)
return $query->where('id', 1);
}
- private static function localesSorted(): array
- {
- $locales = config('app.locales', ['en']);
- if (is_string($locales)) {
- $locales = array_map('trim', explode(',', $locales));
- }
- $locales = array_values(array_filter($locales));
- if (empty($locales)) {
- $locales = ['en'];
- }
- sort($locales);
-
- return $locales;
- }
-
public function fields(Request $request): array
{
- $translationKeys = [
- 'hero_intro' => 'Hero intro',
- 'hero_cta_text' => 'Hero button text',
- 'about_title' => 'About title',
- 'about_description' => 'About description',
- 'role_models_title' => 'Role models section title',
- 'resources_title' => 'Resources section title',
- ];
-
- $translationFields = [];
- foreach (self::localesSorted() as $locale) {
- if ($locale === 'en') {
- continue;
- }
- foreach ($translationKeys as $key => $label) {
- $isLongText = in_array($key, ['hero_intro', 'about_description'], true);
- $fieldName = 'locale_' . $locale . '_' . $key;
- if ($isLongText) {
- $translationFields[] = Textarea::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
- ->nullable()
- ->resolveUsing(function () use ($locale, $key) {
- $overrides = $this->resource->locale_overrides ?? [];
-
- return $overrides[$locale][$key] ?? '';
- })
- ->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
- $overrides = $model->locale_overrides ?? [];
- $overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
- $model->locale_overrides = $overrides;
- });
- } else {
- $translationFields[] = Text::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
- ->nullable()
- ->resolveUsing(function () use ($locale, $key) {
- $overrides = $this->resource->locale_overrides ?? [];
-
- return $overrides[$locale][$key] ?? '';
- })
- ->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
- $overrides = $model->locale_overrides ?? [];
- $overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
- $model->locale_overrides = $overrides;
- });
- }
- }
- }
-
$resourcesPanelFields = [
Boolean::make('Use dynamic content for this section', 'resources_dynamic'),
Text::make('Resources section title', 'resources_title')->nullable(),
@@ -136,12 +75,13 @@ public function fields(Request $request): array
Panel::make('Resources section (global for all role model pages)', $resourcesPanelFields)
->collapsable()
->collapsedByDefault(),
+ Panel::make('Translations (JSON)', [
+ Code::make('Locale overrides', 'locale_overrides')
+ ->json()
+ ->help('Optional per-locale overrides. Example: {"fr":{"hero_intro":"..."}}'),
+ ])->collapsable()->collapsedByDefault(),
];
- if (!empty($translationFields)) {
- $fields[] = new Panel('Translations', $translationFields);
- }
-
return $fields;
}
}
diff --git a/app/Nova/HackathonsPage.php b/app/Nova/HackathonsPage.php
index 172c735c5..1351c1bf0 100644
--- a/app/Nova/HackathonsPage.php
+++ b/app/Nova/HackathonsPage.php
@@ -4,6 +4,7 @@
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Boolean;
+use Laravel\Nova\Fields\Code;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Trix;
@@ -38,86 +39,8 @@ public static function indexQuery(NovaRequest $request, $query)
return $query->where('id', 1);
}
- private static function localesSorted(): array
- {
- $locales = config('app.locales', ['en']);
- if (is_string($locales)) {
- $locales = array_map('trim', explode(',', $locales));
- }
- $locales = array_values(array_filter($locales));
- if (empty($locales)) {
- $locales = ['en'];
- }
- sort($locales);
-
- return $locales;
- }
-
public function fields(Request $request): array
{
- $translationKeys = [
- 'hero_title' => 'Hero title',
- 'hero_subtitle' => 'Hero subtitle',
- 'intro_title' => 'Intro title',
- 'intro_paragraph_1' => 'Intro paragraph 1',
- 'intro_paragraph_2' => 'Intro paragraph 2',
- 'details_title' => 'Details title',
- 'details_paragraph_1' => 'Details paragraph 1',
- 'details_paragraph_2' => 'Details paragraph 2',
- 'details_paragraph_3' => 'Details paragraph 3',
- 'details_paragraph_4' => 'Details paragraph 4',
- 'recap_button_text' => 'Recap button text',
- 'toolkit_button_text' => 'Toolkit button text',
- ];
-
- $longTextKeys = [
- 'hero_subtitle',
- 'intro_paragraph_1',
- 'intro_paragraph_2',
- 'details_paragraph_1',
- 'details_paragraph_2',
- 'details_paragraph_3',
- 'details_paragraph_4',
- ];
-
- $translationFields = [];
- foreach (self::localesSorted() as $locale) {
- if ($locale === 'en') {
- continue;
- }
-
- foreach ($translationKeys as $key => $label) {
- $fieldName = 'locale_' . $locale . '_' . $key;
- if (in_array($key, $longTextKeys, true)) {
- $translationFields[] = Trix::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
- ->nullable()
- ->resolveUsing(function () use ($locale, $key) {
- $overrides = $this->resource->locale_overrides ?? [];
-
- return $overrides[$locale][$key] ?? '';
- })
- ->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
- $overrides = $model->locale_overrides ?? [];
- $overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
- $model->locale_overrides = $overrides;
- });
- } else {
- $translationFields[] = Text::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
- ->nullable()
- ->resolveUsing(function () use ($locale, $key) {
- $overrides = $this->resource->locale_overrides ?? [];
-
- return $overrides[$locale][$key] ?? '';
- })
- ->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
- $overrides = $model->locale_overrides ?? [];
- $overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
- $model->locale_overrides = $overrides;
- });
- }
- }
- }
-
$fields = [
ID::make()->onlyOnForms(),
Boolean::make('Use dynamic content', 'dynamic_content')
@@ -141,17 +64,20 @@ public function fields(Request $request): array
Trix::make('Details paragraph 3', 'details_paragraph_3')->nullable(),
Trix::make('Details paragraph 4', 'details_paragraph_4')->nullable(),
Text::make('Video URL (embed)', 'video_url')->nullable(),
+ Text::make('Extra button text (optional)', 'extra_button_text')->nullable(),
+ Text::make('Extra button link (optional)', 'extra_button_link')->nullable(),
Text::make('Recap button text', 'recap_button_text')->nullable(),
Text::make('Recap button link', 'recap_button_link')->nullable(),
Text::make('Toolkit button text', 'toolkit_button_text')->nullable(),
Text::make('Toolkit button link', 'toolkit_button_link')->nullable(),
])->collapsable()->collapsedByDefault(),
+ Panel::make('Translations (JSON)', [
+ Code::make('Locale overrides', 'locale_overrides')
+ ->json()
+ ->help('Optional per-locale overrides. Example: {"fr":{"hero_title":"Hackathons"}}'),
+ ])->collapsable()->collapsedByDefault(),
];
- if (!empty($translationFields)) {
- $fields[] = new Panel('Translations', $translationFields);
- }
-
return $fields;
}
}
diff --git a/database/migrations/2026_02_16_140000_create_hackathons_page_table.php b/database/migrations/2026_02_16_140000_create_hackathons_page_table.php
index eeb8f5a93..b9b976bf9 100644
--- a/database/migrations/2026_02_16_140000_create_hackathons_page_table.php
+++ b/database/migrations/2026_02_16_140000_create_hackathons_page_table.php
@@ -23,6 +23,8 @@ public function up(): void
$table->text('details_paragraph_3')->nullable();
$table->text('details_paragraph_4')->nullable();
$table->string('video_url')->nullable();
+ $table->string('extra_button_text')->nullable();
+ $table->string('extra_button_link')->nullable();
$table->string('recap_button_text')->nullable();
$table->string('recap_button_link')->nullable();
$table->string('toolkit_button_text')->nullable();
diff --git a/database/migrations/2026_02_16_141000_add_extra_button_to_hackathons_page_table.php b/database/migrations/2026_02_16_141000_add_extra_button_to_hackathons_page_table.php
new file mode 100644
index 000000000..0db51f8d3
--- /dev/null
+++ b/database/migrations/2026_02_16_141000_add_extra_button_to_hackathons_page_table.php
@@ -0,0 +1,37 @@
+string('extra_button_text')->nullable()->after('video_url');
+ });
+ }
+
+ if (Schema::hasTable('hackathons_page') && !Schema::hasColumn('hackathons_page', 'extra_button_link')) {
+ Schema::table('hackathons_page', function (Blueprint $table) {
+ $table->string('extra_button_link')->nullable()->after('extra_button_text');
+ });
+ }
+ }
+
+ public function down(): void
+ {
+ if (Schema::hasTable('hackathons_page') && Schema::hasColumn('hackathons_page', 'extra_button_link')) {
+ Schema::table('hackathons_page', function (Blueprint $table) {
+ $table->dropColumn('extra_button_link');
+ });
+ }
+
+ if (Schema::hasTable('hackathons_page') && Schema::hasColumn('hackathons_page', 'extra_button_text')) {
+ Schema::table('hackathons_page', function (Blueprint $table) {
+ $table->dropColumn('extra_button_text');
+ });
+ }
+ }
+};
diff --git a/resources/views/hackathons/index.blade.php b/resources/views/hackathons/index.blade.php
index 41a908e33..68888f48b 100644
--- a/resources/views/hackathons/index.blade.php
+++ b/resources/views/hackathons/index.blade.php
@@ -150,6 +150,14 @@ class="animation-element move-background duration-[1.5s] absolute z-0 lg:-bottom
@endif