Skip to content

Commit 078e320

Browse files
committed
certs fix
1 parent 35c4f04 commit 078e320

6 files changed

Lines changed: 376 additions & 16 deletions

File tree

app/HackathonsPage.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace App;
4+
5+
use Illuminate\Database\Eloquent\Model;
6+
7+
class HackathonsPage extends Model
8+
{
9+
protected $table = 'hackathons_page';
10+
11+
protected $fillable = [
12+
'dynamic_content',
13+
'hero_title',
14+
'hero_subtitle',
15+
'intro_title',
16+
'intro_paragraph_1',
17+
'intro_paragraph_2',
18+
'details_title',
19+
'details_paragraph_1',
20+
'details_paragraph_2',
21+
'details_paragraph_3',
22+
'details_paragraph_4',
23+
'video_url',
24+
'recap_button_text',
25+
'recap_button_link',
26+
'toolkit_button_text',
27+
'toolkit_button_link',
28+
'locale_overrides',
29+
];
30+
31+
protected $casts = [
32+
'dynamic_content' => 'boolean',
33+
'locale_overrides' => 'array',
34+
];
35+
36+
public static function config(): self
37+
{
38+
$page = self::first();
39+
if ($page) {
40+
return $page;
41+
}
42+
43+
return self::create([
44+
'dynamic_content' => false,
45+
'locale_overrides' => null,
46+
]);
47+
}
48+
49+
public function contentForLocale(string $key, ?string $locale = null): string
50+
{
51+
$locale = $locale ?? app()->getLocale();
52+
$overrides = $this->locale_overrides ?? [];
53+
if (!empty($overrides[$locale][$key])) {
54+
return (string) $overrides[$locale][$key];
55+
}
56+
57+
$value = $this->getAttribute($key);
58+
return $value !== null ? (string) $value : '';
59+
}
60+
}

app/Nova/HackathonsPage.php

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<?php
2+
3+
namespace App\Nova;
4+
5+
use Illuminate\Http\Request;
6+
use Laravel\Nova\Fields\Boolean;
7+
use Laravel\Nova\Fields\ID;
8+
use Laravel\Nova\Fields\Text;
9+
use Laravel\Nova\Fields\Trix;
10+
use Laravel\Nova\Http\Requests\NovaRequest;
11+
use Laravel\Nova\Panel;
12+
13+
class HackathonsPage extends Resource
14+
{
15+
public static $group = 'Content';
16+
17+
public static $model = \App\HackathonsPage::class;
18+
19+
public static $title = 'id';
20+
21+
public static function label()
22+
{
23+
return 'Hackathons Page';
24+
}
25+
26+
public static function singularLabel()
27+
{
28+
return 'Hackathons Page';
29+
}
30+
31+
public static function uriKey(): string
32+
{
33+
return 'hackathons-page';
34+
}
35+
36+
public static function indexQuery(NovaRequest $request, $query)
37+
{
38+
return $query->where('id', 1);
39+
}
40+
41+
private static function localesSorted(): array
42+
{
43+
$locales = config('app.locales', ['en']);
44+
if (is_string($locales)) {
45+
$locales = array_map('trim', explode(',', $locales));
46+
}
47+
$locales = array_values(array_filter($locales));
48+
if (empty($locales)) {
49+
$locales = ['en'];
50+
}
51+
sort($locales);
52+
53+
return $locales;
54+
}
55+
56+
public function fields(Request $request): array
57+
{
58+
$translationKeys = [
59+
'hero_title' => 'Hero title',
60+
'hero_subtitle' => 'Hero subtitle',
61+
'intro_title' => 'Intro title',
62+
'intro_paragraph_1' => 'Intro paragraph 1',
63+
'intro_paragraph_2' => 'Intro paragraph 2',
64+
'details_title' => 'Details title',
65+
'details_paragraph_1' => 'Details paragraph 1',
66+
'details_paragraph_2' => 'Details paragraph 2',
67+
'details_paragraph_3' => 'Details paragraph 3',
68+
'details_paragraph_4' => 'Details paragraph 4',
69+
'recap_button_text' => 'Recap button text',
70+
'toolkit_button_text' => 'Toolkit button text',
71+
];
72+
73+
$longTextKeys = [
74+
'hero_subtitle',
75+
'intro_paragraph_1',
76+
'intro_paragraph_2',
77+
'details_paragraph_1',
78+
'details_paragraph_2',
79+
'details_paragraph_3',
80+
'details_paragraph_4',
81+
];
82+
83+
$translationFields = [];
84+
foreach (self::localesSorted() as $locale) {
85+
if ($locale === 'en') {
86+
continue;
87+
}
88+
89+
foreach ($translationKeys as $key => $label) {
90+
$fieldName = 'locale_' . $locale . '_' . $key;
91+
if (in_array($key, $longTextKeys, true)) {
92+
$translationFields[] = Trix::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
93+
->nullable()
94+
->resolveUsing(function () use ($locale, $key) {
95+
$overrides = $this->resource->locale_overrides ?? [];
96+
97+
return $overrides[$locale][$key] ?? '';
98+
})
99+
->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
100+
$overrides = $model->locale_overrides ?? [];
101+
$overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
102+
$model->locale_overrides = $overrides;
103+
});
104+
} else {
105+
$translationFields[] = Text::make($label . ' (' . strtoupper($locale) . ')', $fieldName)
106+
->nullable()
107+
->resolveUsing(function () use ($locale, $key) {
108+
$overrides = $this->resource->locale_overrides ?? [];
109+
110+
return $overrides[$locale][$key] ?? '';
111+
})
112+
->fillUsing(function ($request, $model, $attribute, $requestAttribute) use ($locale, $key) {
113+
$overrides = $model->locale_overrides ?? [];
114+
$overrides[$locale][$key] = $request->get($requestAttribute) ?: null;
115+
$model->locale_overrides = $overrides;
116+
});
117+
}
118+
}
119+
}
120+
121+
$fields = [
122+
ID::make()->onlyOnForms(),
123+
Boolean::make('Use dynamic content', 'dynamic_content')
124+
->help('Keep OFF to use current static template content. Turn ON to use the values below.'),
125+
126+
Panel::make('Hero', [
127+
Text::make('Hero title', 'hero_title')->nullable(),
128+
Trix::make('Hero subtitle', 'hero_subtitle')->nullable(),
129+
])->collapsable()->collapsedByDefault(),
130+
131+
Panel::make('Intro section', [
132+
Text::make('Intro title', 'intro_title')->nullable(),
133+
Trix::make('Intro paragraph 1', 'intro_paragraph_1')->nullable(),
134+
Trix::make('Intro paragraph 2', 'intro_paragraph_2')->nullable(),
135+
])->collapsable()->collapsedByDefault(),
136+
137+
Panel::make('Details section', [
138+
Text::make('Details title', 'details_title')->nullable(),
139+
Trix::make('Details paragraph 1', 'details_paragraph_1')->nullable(),
140+
Trix::make('Details paragraph 2', 'details_paragraph_2')->nullable(),
141+
Trix::make('Details paragraph 3', 'details_paragraph_3')->nullable(),
142+
Trix::make('Details paragraph 4', 'details_paragraph_4')->nullable(),
143+
Text::make('Video URL (embed)', 'video_url')->nullable(),
144+
Text::make('Recap button text', 'recap_button_text')->nullable(),
145+
Text::make('Recap button link', 'recap_button_link')->nullable(),
146+
Text::make('Toolkit button text', 'toolkit_button_text')->nullable(),
147+
Text::make('Toolkit button link', 'toolkit_button_link')->nullable(),
148+
])->collapsable()->collapsedByDefault(),
149+
];
150+
151+
if (!empty($translationFields)) {
152+
$fields[] = new Panel('Translations', $translationFields);
153+
}
154+
155+
return $fields;
156+
}
157+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\DB;
6+
use Illuminate\Support\Facades\Schema;
7+
8+
return new class extends Migration {
9+
public function up(): void
10+
{
11+
if (!Schema::hasTable('hackathons_page')) {
12+
Schema::create('hackathons_page', function (Blueprint $table) {
13+
$table->id();
14+
$table->boolean('dynamic_content')->default(false);
15+
$table->string('hero_title')->nullable();
16+
$table->text('hero_subtitle')->nullable();
17+
$table->string('intro_title')->nullable();
18+
$table->text('intro_paragraph_1')->nullable();
19+
$table->text('intro_paragraph_2')->nullable();
20+
$table->string('details_title')->nullable();
21+
$table->text('details_paragraph_1')->nullable();
22+
$table->text('details_paragraph_2')->nullable();
23+
$table->text('details_paragraph_3')->nullable();
24+
$table->text('details_paragraph_4')->nullable();
25+
$table->string('video_url')->nullable();
26+
$table->string('recap_button_text')->nullable();
27+
$table->string('recap_button_link')->nullable();
28+
$table->string('toolkit_button_text')->nullable();
29+
$table->string('toolkit_button_link')->nullable();
30+
$table->json('locale_overrides')->nullable();
31+
$table->timestamps();
32+
});
33+
}
34+
35+
if (DB::table('hackathons_page')->count() === 0) {
36+
DB::table('hackathons_page')->insert([
37+
'id' => 1,
38+
'dynamic_content' => false,
39+
'created_at' => now(),
40+
'updated_at' => now(),
41+
]);
42+
}
43+
}
44+
45+
public function down(): void
46+
{
47+
Schema::dropIfExists('hackathons_page');
48+
}
49+
};

database/seeders/DatabaseSeeder.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public function run(): void
3131
$this->call(ResourceEditorRoleSeeder::class);
3232
$this->call(DreamJobRoleModelSeeder::class);
3333
$this->call(DreamJobsPageSeeder::class);
34+
$this->call(HackathonsPageSeeder::class);
3435

3536
$this->call(SchoolSeeder::class);
3637

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
namespace Database\Seeders;
4+
5+
use App\HackathonsPage;
6+
use Illuminate\Database\Seeder;
7+
use Illuminate\Support\Facades\Schema;
8+
9+
class HackathonsPageSeeder extends Seeder
10+
{
11+
public function run(): void
12+
{
13+
if (!Schema::hasTable('hackathons_page')) {
14+
return;
15+
}
16+
17+
HackathonsPage::firstOrCreate(
18+
['id' => 1],
19+
[
20+
'dynamic_content' => false,
21+
'hero_title' => 'Hackathons',
22+
'hero_subtitle' => 'Bring your ideas to life!',
23+
'intro_title' => 'Hackathons',
24+
'intro_paragraph_1' => "A hackathon is an event where participants with diverse skills collaborate to tackle global challenges. Participants form teams to brainstorm, design, and code, aiming to produce a working solution or prototype by the event's conclusion. Beyond fostering innovation and teamwork, EU Code Week hackathons offer a platform for young enthusiasts to learn, showcase their talents, and connect with like-minded peers.",
25+
'intro_paragraph_2' => 'Adapting the traditional hackathon format, the EU Code Week Hackathons take into consideration the age of the participants and cater to the unique skills, insights, and interests of adolescents. The aim of the EU Code Week Hackathons is to inspire young people to develop their coding and problem-solving skills by engaging them in collaborative, creative, and innovative projects.',
26+
'details_title' => 'EU Code Week Hackathons 2025-26',
27+
'details_paragraph_1' => 'EU Code Week Hackathons share a common theme that strengthens connection and belonging among young innovators across Europe. The central theme for the 2025 edition is <strong>From Code to Community: Bridging Digital Skills and Social Impact.</strong>.',
28+
'details_paragraph_2' => 'The ten national hackathons — <strong><a href="https://codeweek.eu/blog/hackathons-italy/">Italy (Florence)</a>, <a href="https://codeweek.eu/blog/hackathons-italy/">Italy (Turin)</a>, <a href="https://codeweek.eu/blog/greek-hackathon-2025/">Greece</a>, <a href="https://codeweek.eu/blog/eu-code-week-hackathons-croatia/">Croatia</a>, <a href="https://codeweek.eu/blog/eu-code-week-hackathons-ukraine/">Ukraine</a>, Turkey, Spain, Lithuania, <a href="https://codeweek.eu/blog/eu-code-week-hackathons-slovenia/">Slovenia</a>, and France</strong> — mark a vibrant journey of creativity and collaboration. <strong>Italy (Florence)</strong> opened the series with its event in October 2025, while all other national hackathons are taking place <strong>from now until the end of January 2026</strong>. Each event invites teams of young people aged 15 to 19 to learn, innovate, and develop digital solutions that tackle real societal challenges.',
29+
'details_paragraph_3' => 'Join us online for the <strong>EU Finals on 11 March 2026</strong>, where all national finalists will present their projects and celebrate their shared achievements. Expect inspiring ideas, expert jury insights, and plenty of positive energy — a celebration of how young people use technology to make a difference.',
30+
'details_paragraph_4' => 'Be part of the excitement as we honour the outstanding teams shaping the future of digital innovation!',
31+
'video_url' => 'https://www.youtube.com/embed/fx0zJCpUTa8',
32+
'recap_button_text' => 'Hackathons Final 2024 Recap',
33+
'recap_button_link' => 'https://eventornado.com/event/eu-codeweek-hackathon2024#Finals%20-%20EU%20Code%20Week%20Hackathon%202024',
34+
'toolkit_button_text' => 'Hackathon 2025 Toolkit',
35+
'toolkit_button_link' => '/docs/C4EU_D2.7 Code Week Event Hackathon Design & Toolkit Final 18.06.2025.pdf',
36+
]
37+
);
38+
}
39+
}

0 commit comments

Comments
 (0)