From f1c5fb41d3f6f128f77b3865ba49c526602c159c Mon Sep 17 00:00:00 2001 From: bernardhanna Date: Wed, 25 Feb 2026 17:09:22 +0000 Subject: [PATCH 1/2] explor epath heading --- app/Console/Commands/CertificateSendWindow.php | 12 ++++++++++-- .../Controllers/CertificateBackendController.php | 4 ++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/Console/Commands/CertificateSendWindow.php b/app/Console/Commands/CertificateSendWindow.php index e058bde7c..7d548e886 100644 --- a/app/Console/Commands/CertificateSendWindow.php +++ b/app/Console/Commands/CertificateSendWindow.php @@ -83,13 +83,16 @@ private function sendWindowForType(int $edition, string $type, int $limit, bool $queued = 0; $failed = 0; + $failures = []; foreach ($rows as $excellence) { $bar->advance(); $user = $excellence->user; if (! $user || ! $user->email) { + $err = 'No user or email'; $failed++; - $excellence->update(['certificate_sent_error' => 'No user or email']); + $excellence->update(['certificate_sent_error' => $err]); + $failures[] = ['id' => $excellence->id, 'email' => $user?->email ?? '-', 'error' => $err]; continue; } @@ -105,14 +108,19 @@ private function sendWindowForType(int $edition, string $type, int $limit, bool ]); $queued++; } catch (\Throwable $e) { + $err = $e->getMessage(); $failed++; - $excellence->update(['certificate_sent_error' => $e->getMessage()]); + $excellence->update(['certificate_sent_error' => $err]); + $failures[] = ['id' => $excellence->id, 'email' => $user->email, 'error' => $err]; } } $bar->finish(); $this->newLine(); $this->line(" [{$type}] Done. Queued: {$queued}, Failed: {$failed}."); + if ($failed > 0 && count($failures) > 0) { + $this->table(['id', 'email', 'error'], $failures); + } return ['processed' => $rows->count(), 'queued' => $queued, 'failed' => $failed]; } diff --git a/app/Http/Controllers/CertificateBackendController.php b/app/Http/Controllers/CertificateBackendController.php index fe293b73c..0c7878222 100644 --- a/app/Http/Controllers/CertificateBackendController.php +++ b/app/Http/Controllers/CertificateBackendController.php @@ -78,6 +78,8 @@ public function listRecipients(Request $request): JsonResponse ->where('edition', $edition) ->where('type', $type) ->with('user') + ->orderByRaw('CASE WHEN certificate_sent_error IS NOT NULL THEN 0 ELSE 1 END') + ->orderByRaw('CASE WHEN certificate_generation_error IS NOT NULL THEN 0 ELSE 1 END') ->orderBy('id'); if ($search !== '') { @@ -352,6 +354,8 @@ public function errorsList(Request $request) $q->whereNotNull('certificate_generation_error')->orWhereNotNull('certificate_sent_error'); }) ->with('user') + ->orderByRaw('CASE WHEN certificate_sent_error IS NOT NULL THEN 0 ELSE 1 END') + ->orderByRaw('CASE WHEN certificate_generation_error IS NOT NULL THEN 0 ELSE 1 END') ->orderBy('id') ->get(); From ebe0b221de7192f481b64ce646759ea8314c027f Mon Sep 17 00:00:00 2001 From: bernardhanna Date: Fri, 27 Feb 2026 13:48:37 +0000 Subject: [PATCH 2/2] head fix --- app/Nova/HomeSlide.php | 57 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/app/Nova/HomeSlide.php b/app/Nova/HomeSlide.php index a6b30abc3..e23ec8a69 100644 --- a/app/Nova/HomeSlide.php +++ b/app/Nova/HomeSlide.php @@ -95,6 +95,36 @@ public static function localeOptions(): array private const OVERRIDE_KEYS = ['title', 'description', 'button_text', 'button2_text']; + private static function isAbsoluteImageUrl(?string $value): bool + { + if (! is_string($value) || trim($value) === '') { + return false; + } + + return str_starts_with($value, 'http://') || str_starts_with($value, 'https://'); + } + + private static function fillImageFromInputs($request, $model): void + { + $path = trim((string) $request->get('image_path_input', '')); + $url = trim((string) $request->get('image_url_input', '')); + + // URL wins when both are provided. + if ($url !== '') { + $model->image = $url; + return; + } + + if ($path !== '') { + $model->image = ltrim($path, '/'); + return; + } + + if ($request->exists('image_path_input') || $request->exists('image_url_input')) { + $model->image = null; + } + } + private static function parseOverrideAttribute(string $attribute): ?array { if (! str_starts_with($attribute, 'override_') || strlen($attribute) < 12) { @@ -227,9 +257,32 @@ public function fields(Request $request): array ->help('Leave empty to hide second button. Lang key or plain text.'), 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') + Text::make('Image (saved value)', 'image') + ->exceptOnForms() ->nullable() - ->help('Path from site root e.g. images/dream-jobs/dream_jobs_bg.png (no leading slash), or full URL. Used as slide background.'), + ->help('Stored image reference used by the homepage slider.'), + Text::make('Image path (site root)', 'image_path_input') + ->onlyOnForms() + ->nullable() + ->resolveUsing(function () { + $image = $this->resource->image; + return self::isAbsoluteImageUrl($image) ? '' : (string) ($image ?? ''); + }) + ->fillUsing(function ($request, $model) { + self::fillImageFromInputs($request, $model); + }) + ->help('Option 1: local path like images/dream-jobs/dream_jobs_bg.png (no leading slash).'), + Text::make('Image URL (full)', 'image_url_input') + ->onlyOnForms() + ->nullable() + ->resolveUsing(function () { + $image = $this->resource->image; + return self::isAbsoluteImageUrl($image) ? (string) $image : ''; + }) + ->fillUsing(function ($request, $model) { + self::fillImageFromInputs($request, $model); + }) + ->help('Option 2: full URL, e.g. https://codeweek-resources.s3.eu-west-1.amazonaws.com/...'), Number::make('Position', 'position') ->min(0) ->default(0)