From fb1c28a0ba3d03ab64230cdf17b0f8014661f6f2 Mon Sep 17 00:00:00 2001 From: Jonathan van Rij Date: Mon, 16 Feb 2026 15:09:41 +0100 Subject: [PATCH] fixing bugs --- app/Http/Controllers/SessionController.php | 2 +- app/Nova/AnswerResource.php | 1 + app/Nova/Dashboards/Main.php | 14 ++++-- app/Nova/Metrics/ScreeningsTrend.php | 33 ++++++++++++++ app/Nova/Metrics/SessionsTrend.php | 33 ++++++++++++++ app/Nova/Metrics/TotalScreenings.php | 47 +++++++++++++++++++ app/Nova/Metrics/TotalSessions.php | 35 +++++++++++++++ app/Nova/QuestionGroupResource.php | 2 +- app/Nova/Resource.php | 11 +++++ app/Nova/SessionResource.php | 6 +-- app/Nova/User.php | 9 ++-- app/Providers/NovaServiceProvider.php | 6 ++- database/seeders/TestCategorySeeder.php | 52 ++++++++++++++++++++++ resources/js/Pages/Session/Show.vue | 6 ++- 14 files changed, 238 insertions(+), 19 deletions(-) create mode 100644 app/Nova/Metrics/ScreeningsTrend.php create mode 100644 app/Nova/Metrics/SessionsTrend.php create mode 100644 app/Nova/Metrics/TotalScreenings.php create mode 100644 app/Nova/Metrics/TotalSessions.php create mode 100644 database/seeders/TestCategorySeeder.php diff --git a/app/Http/Controllers/SessionController.php b/app/Http/Controllers/SessionController.php index 06d984c..5ba8c57 100644 --- a/app/Http/Controllers/SessionController.php +++ b/app/Http/Controllers/SessionController.php @@ -191,7 +191,7 @@ private function validateDetailsAnswer($question, $answer, array &$errors): void } } - if (! $hasRadioButtons && $details !== null && $details !== '') { + if (! $hasRadioButtons && $details !== null && $details !== '' && $details !== 'optional') { if (! $answer || empty(trim(Arr::get($answer->toArray(), 'text_value', '')))) { $errors[] = "Question '{$question->text}' requires a text response."; } diff --git a/app/Nova/AnswerResource.php b/app/Nova/AnswerResource.php index b57080d..14afaaa 100644 --- a/app/Nova/AnswerResource.php +++ b/app/Nova/AnswerResource.php @@ -14,6 +14,7 @@ final class AnswerResource extends Resource { + /** * The model the resource corresponds to. * diff --git a/app/Nova/Dashboards/Main.php b/app/Nova/Dashboards/Main.php index 127e931..7fe2652 100644 --- a/app/Nova/Dashboards/Main.php +++ b/app/Nova/Dashboards/Main.php @@ -1,11 +1,16 @@ countByDays($request, Screening::class); + } + + public function name(): string + { + return 'Screenings'; + } + + public function ranges(): array + { + return [ + 30 => '30 Days', + 60 => '60 Days', + 90 => '90 Days', + ]; + } +} diff --git a/app/Nova/Metrics/SessionsTrend.php b/app/Nova/Metrics/SessionsTrend.php new file mode 100644 index 0000000..e31d428 --- /dev/null +++ b/app/Nova/Metrics/SessionsTrend.php @@ -0,0 +1,33 @@ +countByDays($request, Session::class); + } + + public function name(): string + { + return 'Sessions'; + } + + public function ranges(): array + { + return [ + 30 => '30 Days', + 60 => '60 Days', + 90 => '90 Days', + ]; + } + + public $cacheFor = null; +} diff --git a/app/Nova/Metrics/TotalScreenings.php b/app/Nova/Metrics/TotalScreenings.php new file mode 100644 index 0000000..9666d41 --- /dev/null +++ b/app/Nova/Metrics/TotalScreenings.php @@ -0,0 +1,47 @@ +count($request, Screening::class); + } + + /** + * Get the displayable name of the metric. + */ + public function name(): string + { + return 'Total Screenings'; + } + + /** + * Get the ranges available for the metric. + */ + public function ranges(): array + { + return [ + 30 => '30 Days', + 60 => '60 Days', + 365 => '365 Days', + 'TODAY' => 'Today', + 'ALL' => 'All Time', + ]; + } + + /** + * Determine the amount of time the results should be cached. + */ + public $cacheFor = null; +} diff --git a/app/Nova/Metrics/TotalSessions.php b/app/Nova/Metrics/TotalSessions.php new file mode 100644 index 0000000..07f6ab2 --- /dev/null +++ b/app/Nova/Metrics/TotalSessions.php @@ -0,0 +1,35 @@ +count($request, Session::class); + } + + public function name(): string + { + return 'Total Sessions'; + } + + public function ranges(): array + { + return [ + 30 => '30 Days', + 60 => '60 Days', + 365 => '365 Days', + 'TODAY' => 'Today', + 'ALL' => 'All Time', + ]; + } + + public $cacheFor = null; +} diff --git a/app/Nova/QuestionGroupResource.php b/app/Nova/QuestionGroupResource.php index 65957dc..f5e2877 100644 --- a/app/Nova/QuestionGroupResource.php +++ b/app/Nova/QuestionGroupResource.php @@ -42,7 +42,7 @@ final class QuestionGroupResource extends Resource * * @var bool */ - public static $displayInNavigation = false; + public static $displayInNavigation = true; /** * Get the displayable label of the resource. diff --git a/app/Nova/Resource.php b/app/Nova/Resource.php index 0b2c865..9318053 100644 --- a/app/Nova/Resource.php +++ b/app/Nova/Resource.php @@ -9,6 +9,17 @@ abstract class Resource extends NovaResource { + public static function perPageOptions() + { + return [50, 100, 150]; + } + + public static function perPageViaRelationshipOptions() + { + return [10, 25, 50]; + } + + /** * Build an "index" query for the given resource. */ diff --git a/app/Nova/SessionResource.php b/app/Nova/SessionResource.php index d0cc6f4..f1dd06a 100644 --- a/app/Nova/SessionResource.php +++ b/app/Nova/SessionResource.php @@ -108,8 +108,7 @@ public function fields(NovaRequest $request): array ]) ->displayUsingLabels() ->sortable() - ->filterable() - ->readonly(), + ->filterable(), Number::make('Score') ->sortable() @@ -125,8 +124,7 @@ public function fields(NovaRequest $request): array ]) ->displayUsingLabels() ->sortable() - ->filterable() - ->readonly(), + ->filterable(), Textarea::make('Additional Comments') ->rules('nullable'), diff --git a/app/Nova/User.php b/app/Nova/User.php index b614df0..3948212 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -74,19 +74,16 @@ public function fields(NovaRequest $request): array Text::make('Job Title', 'job_title') ->sortable() ->filterable() - ->copyable() - ->readonly(), + ->copyable(), Text::make('Department') ->sortable() ->filterable() - ->copyable() - ->readonly(), + ->copyable(), Text::make('Phone') ->sortable() - ->copyable() - ->readonly(), + ->copyable(), Password::make('Password') ->onlyOnForms() diff --git a/app/Providers/NovaServiceProvider.php b/app/Providers/NovaServiceProvider.php index 210b3f0..a26c953 100644 --- a/app/Providers/NovaServiceProvider.php +++ b/app/Providers/NovaServiceProvider.php @@ -6,6 +6,7 @@ use App\Nova\CategoryResource; use App\Nova\Dashboards\Main; use App\Nova\LogResource; +use App\Nova\QuestionGroupResource; use App\Nova\QuestionResource; use App\Nova\ScreeningResource; use App\Nova\SessionResource; @@ -31,10 +32,11 @@ public function boot(): void MenuSection::dashboard(Main::class)->icon('home'), MenuSection::make('Questionnaire', [ - MenuItem::resource(CategoryResource::class), MenuItem::resource(QuestionResource::class), - MenuItem::resource(ScreeningResource::class), + MenuItem::resource(QuestionGroupResource::class), + MenuItem::resource(CategoryResource::class), MenuItem::resource(SessionResource::class), + MenuItem::resource(ScreeningResource::class), ])->icon('clipboard-document-list')->collapsible(), MenuSection::make('Logs', [ diff --git a/database/seeders/TestCategorySeeder.php b/database/seeders/TestCategorySeeder.php new file mode 100644 index 0000000..e27799f --- /dev/null +++ b/database/seeders/TestCategorySeeder.php @@ -0,0 +1,52 @@ +insertGetId([ + 'name' => 'Test', + 'sort_order' => 99, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $groupId = DB::table('question_groups')->insertGetId([ + 'category_id' => $categoryId, + 'name' => 'Test Group', + 'sort_order' => 1, + 'description' => null, + 'scoring_instructions' => null, + 'created_at' => now(), + 'updated_at' => now(), + ]); + + $questions = []; + for ($i = 1; $i <= 5; $i++) { + $questions[] = [ + 'question_group_id' => $groupId, + 'text' => "Test question {$i}", + 'has_yes' => true, + 'has_no' => true, + 'has_na' => true, + 'details' => 'optional', + 'sort_order' => $i, + 'is_scored' => true, + 'created_at' => now(), + 'updated_at' => now(), + ]; + } + + DB::table('questions')->insert($questions); + } +} diff --git a/resources/js/Pages/Session/Show.vue b/resources/js/Pages/Session/Show.vue index bf97df5..5cd4d31 100644 --- a/resources/js/Pages/Session/Show.vue +++ b/resources/js/Pages/Session/Show.vue @@ -118,8 +118,8 @@ const validate = () => { return } - // Rule 3: Text-only questions (no radio buttons, has details) - if (!hasRadioButtons && question.details && !answer.text_value?.trim()) { + // Rule 3: Text-only questions (no radio buttons, has required details) + if (!hasRadioButtons && question.details && question.details !== 'optional' && !answer.text_value?.trim()) { errors[question.id] = 'Please enter a response' return } @@ -161,7 +161,9 @@ const completeSession = async () => { } completing = true + clearTimeout(saveTimeout) router.put(`/sessions/${props.session.id}`, { + answers: { ...answerData }, complete: true, }) }