validate([ 'subject' => 'required|string|max:255', 'message' => 'required|string', ]); try { $ticket = Ticket::create([ 'user_id' => auth()->id(), 'ticket_id' => strtoupper(Str::random(6)), 'subject' => $this->subject, 'message' => $this->message, 'ip_address' => $this->getClientIp(), 'last_response_at' => now(), ]); $this->dispatch('showAlert', ['type' => 'success', 'message' => 'Your ticket has been created successfully!']); $this->dispatch('closeModal'); $this->reset(['subject', 'message']); $this->tickets = Ticket::with('responses') ->where('user_id', auth()->id()) ->get(); } catch (Exception $exception) { $this->dispatch('showAlert', ['type' => 'error', 'message' => 'Something went wrong!']); } } public function reply($ticket_id) { $this->validate([ 'response' => 'required|string', ]); try { if (! is_numeric($ticket_id)) { $this->dispatch('showAlert', ['type' => 'error', 'message' => 'Invalid ticket ID.']); return; } $ticket = Ticket::find($ticket_id); if (! $ticket) { $this->dispatch('showAlert', ['type' => 'error', 'message' => 'Ticket not found.']); return; } TicketResponse::create([ 'ticket_id' => $ticket_id, 'user_id' => auth()->id(), 'response' => $this->response, 'ip_address' => $this->getClientIp(), ]); $ticket->last_response_at = now(); $ticket->save(); $this->dispatch('showAlert', ['type' => 'success', 'message' => 'Reply sent successfully!']); $this->reset(['response']); $this->tickets = Ticket::with('responses') ->where('user_id', auth()->id()) ->get(); } catch (Exception $exception) { session()->flash('error', 'Something went wrong!'); } } public function close($ticket_id) { if (! is_numeric($ticket_id)) { $this->dispatch('showAlert', ['type' => 'error', 'message' => 'Invalid ticket ID.']); return; } $ticket = Ticket::find($ticket_id); if (! $ticket) { $this->dispatch('showAlert', ['type' => 'error', 'message' => 'Ticket not found.']); return; } $ticket->status = 'closed'; $ticket->save(); $this->tickets = Ticket::with('responses') ->where('user_id', auth()->id()) ->get(); $this->updateTicketCounts(); $this->dispatch('showAlert', ['type' => 'error', 'message' => 'This ticket has been closed!']); } public function mount() { $this->tickets = Ticket::with('responses') ->where('user_id', auth()->id()) ->get(); $this->updateTicketCounts(); } public function updateTicketCounts() { $this->open = $this->tickets->filter(function ($ticket) { return in_array($ticket->status, ['open', 'pending']); })->count(); $this->closed = $this->tickets->filter(function ($ticket) { return $ticket->status === 'closed'; })->count(); } protected function getClientIp() { // Cloudflare or other proxies may send the original client IP in X-Forwarded-For header $ip = Request::header('X-Forwarded-For'); // X-Forwarded-For can contain a comma-separated list of IPs, so we need to get the first one if ($ip) { return explode(',', $ip)[0]; // Get the first IP in the list } // Fallback to the real IP if no X-Forwarded-For header return Request::ip(); } public function render() { return view('livewire.dashboard.support')->layout('components.layouts.dashboard'); } }