improvements
This commit is contained in:
@@ -8,12 +8,14 @@
|
||||
use App\Models\Session;
|
||||
use App\Services\ActivityLogger;
|
||||
use App\Services\ScoringService;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
use Inertia\Response as InertiaResponse;
|
||||
|
||||
final class SessionController extends Controller
|
||||
{
|
||||
@@ -37,7 +39,7 @@ public function store(Request $request): RedirectResponse
|
||||
/**
|
||||
* Display the session questionnaire with category, question groups, questions, and existing answers.
|
||||
*/
|
||||
public function show(Session $session): Response
|
||||
public function show(Session $session): InertiaResponse
|
||||
{
|
||||
$session->load('category', 'user');
|
||||
|
||||
@@ -51,14 +53,10 @@ public function show(Session $session): Response
|
||||
|
||||
$answers = $session->answers()->get()->keyBy('question_id');
|
||||
|
||||
$scoringService = new ScoringService;
|
||||
$score = $scoringService->calculateScore($session);
|
||||
|
||||
return Inertia::render('Session/Show', [
|
||||
'session' => $session,
|
||||
'questionGroups' => $questionGroups,
|
||||
'answers' => $answers,
|
||||
'score' => $score,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -201,7 +199,7 @@ private function validateDetailsAnswer($question, $answer, array &$errors): void
|
||||
/**
|
||||
* Display the final session result.
|
||||
*/
|
||||
public function result(Session $session): Response
|
||||
public function result(Session $session): InertiaResponse
|
||||
{
|
||||
$session->load('category');
|
||||
|
||||
@@ -212,4 +210,30 @@ public function result(Session $session): Response
|
||||
'categoryName' => $session->category->name,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and download a PDF export of the completed session result.
|
||||
*/
|
||||
public function pdf(Session $session): Response
|
||||
{
|
||||
abort_unless($session->user_id === auth()->id(), 403);
|
||||
abort_unless($session->status === 'completed', 403);
|
||||
|
||||
$session->load(['user', 'category', 'answers.question']);
|
||||
|
||||
$questionGroups = $session->category
|
||||
->questionGroups()
|
||||
->with(['questions' => fn ($q) => $q->orderBy('sort_order')])
|
||||
->orderBy('sort_order')
|
||||
->get();
|
||||
|
||||
ActivityLogger::log('session_pdf_downloaded', $session->user_id, sessionId: $session->id, categoryId: $session->category_id);
|
||||
|
||||
$pdf = Pdf::loadView('pdf.session-result', [
|
||||
'session' => $session,
|
||||
'questionGroups' => $questionGroups,
|
||||
]);
|
||||
|
||||
return $pdf->download("go-no-go-{$session->id}.pdf");
|
||||
}
|
||||
}
|
||||
|
||||
40
app/Jobs/CloseSessionsJob.php
Normal file
40
app/Jobs/CloseSessionsJob.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\Session;
|
||||
use App\Services\ActivityLogger;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Queue\Queueable;
|
||||
|
||||
final class CloseSessionsJob implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Find all in-progress sessions idle for more than 12 hours and mark them as
|
||||
* 'unfinished' status, logging each closure individually via ActivityLogger.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
Session::query()
|
||||
->where('status', 'in_progress')
|
||||
->where('created_at', '<', now()->subHours(12))
|
||||
->each(function (Session $session): void {
|
||||
$session->update([
|
||||
'status' => 'unfinished',
|
||||
'completed_at' => now(),
|
||||
]);
|
||||
|
||||
ActivityLogger::log(
|
||||
'session_auto_closed',
|
||||
$session->user_id,
|
||||
sessionId: $session->id,
|
||||
categoryId: $session->category_id,
|
||||
metadata: ['reason' => 'idle_12h'],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
namespace App\Nova;
|
||||
|
||||
use App\Nova\Actions\DownloadExcel;
|
||||
use Illuminate\Support\Str;
|
||||
use Laravel\Nova\Fields\BelongsTo;
|
||||
use Laravel\Nova\Fields\Boolean;
|
||||
use Laravel\Nova\Fields\DateTime;
|
||||
use Laravel\Nova\Fields\HasMany;
|
||||
use Laravel\Nova\Fields\ID;
|
||||
use Laravel\Nova\Fields\Number;
|
||||
@@ -15,7 +15,6 @@
|
||||
use Laravel\Nova\Fields\Text;
|
||||
use Laravel\Nova\Fields\Textarea;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use App\Nova\Actions\DownloadExcel;
|
||||
|
||||
final class QuestionResource extends Resource
|
||||
{
|
||||
@@ -90,8 +89,6 @@ public function fields(NovaRequest $request): array
|
||||
->filterable()
|
||||
->help('The group this question belongs to. Questions are shown together by group in the questionnaire.'),
|
||||
|
||||
|
||||
|
||||
Textarea::make('Text')
|
||||
->rules('required')
|
||||
->updateRules('required')
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
namespace App\Nova;
|
||||
|
||||
use App\Nova\Actions\DownloadExcel;
|
||||
use Laravel\Nova\Fields\BelongsTo;
|
||||
use Laravel\Nova\Fields\DateTime;
|
||||
use Laravel\Nova\Fields\HasMany;
|
||||
@@ -12,7 +13,6 @@
|
||||
use Laravel\Nova\Fields\Select;
|
||||
use Laravel\Nova\Fields\Textarea;
|
||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
||||
use App\Nova\Actions\DownloadExcel;
|
||||
|
||||
final class SessionResource extends Resource
|
||||
{
|
||||
@@ -107,12 +107,13 @@ public function fields(NovaRequest $request): array
|
||||
->options([
|
||||
'in_progress' => 'In Progress',
|
||||
'completed' => 'Completed',
|
||||
'unfinished' => 'Unfinished',
|
||||
'abandoned' => 'Abandoned',
|
||||
])
|
||||
->displayUsingLabels()
|
||||
->sortable()
|
||||
->filterable()
|
||||
->help('The current state of this session. "In Progress" means the user has not yet submitted, "Completed" means submitted, "Abandoned" means the user left without finishing.'),
|
||||
->help('The current state of this session. "In Progress" means the user has not yet submitted, "Completed" means submitted, "Unfinished" means the session was auto-closed after inactivity, "Abandoned" means the user left without finishing.'),
|
||||
|
||||
Number::make('Score')
|
||||
->sortable()
|
||||
|
||||
Reference in New Issue
Block a user