diff --git a/Modules/Helpdesk/Livewire/TicketTimer.php b/Modules/Helpdesk/Livewire/TicketTimer.php index 3bae285f..f9f7a8d2 100644 --- a/Modules/Helpdesk/Livewire/TicketTimer.php +++ b/Modules/Helpdesk/Livewire/TicketTimer.php @@ -5,8 +5,8 @@ namespace Modules\Helpdesk\Livewire; use Carbon\Carbon; use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\QueryException; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Gate; use Illuminate\Validation\ValidationException; use Livewire\Component; use Modules\Helpdesk\Models\Ticket; @@ -25,7 +25,7 @@ class TicketTimer extends Component public int $elapsedSeconds = 0; /** - * Mount the ticket timer component. + * Mount the ticket timer and load any active database-backed timer. */ public function mount(Ticket $ticket): void { @@ -34,7 +34,7 @@ class TicketTimer extends Component } /** - * Start a user-specific timer for this ticket. + * Start a database-backed timer for the current authenticated user. * * @throws \Illuminate\Validation\ValidationException */ @@ -42,51 +42,47 @@ class TicketTimer extends Component { $user = $this->authenticatedUser(); - Gate::authorize('update', $this->ticket); - if ($this->activeUserTimerQuery($user)->exists()) { throw ValidationException::withMessages([ - 'timer' => 'You already have a running timer. End it before starting another one.', - ]); - } - - if ($this->activeAnyTicketTimerQuery($user)->exists()) { - throw ValidationException::withMessages([ - 'timer' => 'You already have a running timer on another ticket. End it before starting another one.', + 'timer' => 'You already have a running timer.', ]); } $startedAt = Carbon::now(); - TicketTimeLog::query()->create([ - 'ticket_id' => $this->ticket->getKey(), - 'user_id' => $user->getAuthIdentifier(), - 'minutes' => 0, - 'seconds' => 0, - 'description' => $this->normalisedDescription(), - 'started_at' => $startedAt, - 'ended_at' => null, - 'logged_at' => $startedAt, - ]); + try { + $timer = TicketTimeLog::query()->create([ + 'ticket_id' => $this->ticket->getKey(), + 'user_id' => $user->getAuthIdentifier(), + 'minutes' => 0, + 'seconds' => 0, + 'description' => $this->normalisedDescription(), + 'started_at' => $startedAt, + 'ended_at' => null, + 'logged_at' => $startedAt, + ]); + } catch (QueryException $exception) { + throw ValidationException::withMessages([ + 'timer' => 'You already have a running timer.', + ]); + } + $this->activeTimer = $timer->fresh(); + $this->elapsedSeconds = 0; $this->description = ''; $this->message = 'Timer started.'; - $this->refreshActiveTimer(); $this->dispatch('timer-started'); } /** - * End the active user timer and add the elapsed time to the ticket. + * End the current user's active timer and persist seconds/minutes. * * @throws \Illuminate\Validation\ValidationException */ public function endTimer(): void { $user = $this->authenticatedUser(); - - Gate::authorize('update', $this->ticket); - $timer = $this->activeUserTimerQuery($user)->first(); if (! $timer instanceof TicketTimeLog) { @@ -108,7 +104,14 @@ class TicketTimer extends Component 'logged_at' => $endedAt, ])->save(); - $this->updateTicketTimeSpentFromSeconds(); + $totalSeconds = (int) TicketTimeLog::query() + ->where('ticket_id', $this->ticket->getKey()) + ->whereNotNull('ended_at') + ->sum('seconds'); + + $this->ticket->forceFill([ + 'time_spent_minutes' => (int) ceil($totalSeconds / 60), + ])->save(); $this->activeTimer = null; $this->elapsedSeconds = 0; @@ -119,15 +122,15 @@ class TicketTimer extends Component } /** - * Render the ticket timer view. + * Render the timer view. */ - public function render(): mixed + public function render() { return view('helpdesk::livewire.ticket-timer'); } /** - * Refresh the active timer from the database. + * Refresh the active timer state from the database. */ private function refreshActiveTimer(): void { @@ -142,7 +145,7 @@ class TicketTimer extends Component $this->activeTimer = $this->activeUserTimerQuery($user)->first(); $this->elapsedSeconds = $this->activeTimer instanceof TicketTimeLog - ? (int) $this->activeTimer->started_at->diffInSeconds(Carbon::now()) + ? $this->activeTimer->started_at->diffInSeconds(Carbon::now()) : 0; } @@ -157,38 +160,6 @@ class TicketTimer extends Component ->whereNull('ended_at'); } - /** - * Build the active timer query for the authenticated user across all tickets. - */ - private function activeAnyTicketTimerQuery(Authenticatable $user): Builder - { - return TicketTimeLog::query() - ->where('user_id', $user->getAuthIdentifier()) - ->whereNull('ended_at'); - } - - /** - * Update the ticket's rounded minute total using stored seconds. - */ - private function updateTicketTimeSpentFromSeconds(): void - { - $totalSeconds = (int) TicketTimeLog::query() - ->where('ticket_id', $this->ticket->getKey()) - ->whereNotNull('ended_at') - ->sum('seconds'); - - if ($totalSeconds === 0) { - $totalSeconds = (int) TicketTimeLog::query() - ->where('ticket_id', $this->ticket->getKey()) - ->whereNotNull('ended_at') - ->sum('minutes') * 60; - } - - $this->ticket->forceFill([ - 'time_spent_minutes' => (int) ceil($totalSeconds / 60), - ])->save(); - } - /** * Return the authenticated user or fail validation cleanly. * @@ -200,7 +171,7 @@ class TicketTimer extends Component if (! $user instanceof Authenticatable) { throw ValidationException::withMessages([ - 'timer' => 'You must be signed in to use the ticket timer.', + 'timer' => 'You must be logged in to use the timer.', ]); } @@ -208,12 +179,12 @@ class TicketTimer extends Component } /** - * Return a safe note for the timer. + * Return the safe timer description. */ private function normalisedDescription(): string { $description = trim($this->description); - return $description !== '' ? $description : 'Work timer'; + return $description !== '' ? $description : 'Timer entry'; } } diff --git a/Modules/Helpdesk/Resources/views/livewire/ticket-show.blade.php b/Modules/Helpdesk/Resources/views/livewire/ticket-show.blade.php index df5e8ff6..a236820a 100644 --- a/Modules/Helpdesk/Resources/views/livewire/ticket-show.blade.php +++ b/Modules/Helpdesk/Resources/views/livewire/ticket-show.blade.php @@ -1,5 +1,5 @@ @php - use Illuminate\Support\Str; + use Illuminate\Support\Str;use Modules\Helpdesk\Models\TicketTimeLog; $currentUser = auth()->user(); $currentCompany = $currentUser?->company; @@ -8,7 +8,11 @@ Str::lower((string) ($currentCompany?->slug ?? '')) === 'mpba-limited' || Str::contains(Str::lower((string) ($currentCompany?->name ?? '')), 'mpba'); $visibleCommentCount = $ticket->comments->count(); - $ticketTimeLogs = collect($ticket->timeLogs ?? []); + $ticketTimeLogs = TicketTimeLog::query() + ->with('user') + ->where('ticket_id', $ticket->getKey()) + ->orderByDesc('started_at') + ->get(); @endphp