columns = $columns; $this->rows = collect($rows)->map(function ($row) { return is_array($row) ? $row : (array) $row; })->values()->all(); $this->addRoute = $addRoute; $this->rowKey = $rowKey; } /** * ACTION FUNCTIONALITIES [READ, UPDATE, DELETE] */ //VIEW public function viewRow($id) { // $this->modalData = collect($this->rows)->firstWhere($this->rowKey, $id) ?? []; // $this->modalMode = 'view'; // $this->showModal = true; return redirect()->to($this->viewRoute . '?uuid=' . $id); } //UPDATE || EDIT public function editRow($id) { return redirect()->to($this->updateRoute . '?uuid=' . $id); } //DELETE, HANDLES DELETE ENDPOINT public function deleteRow($id) { $token = Session::get('user')['access_token'] ?? null; $url = rtrim(config('services.backend_api.url'), '/') . '/' . $this->deleteEndpoint . '/' . $id; try { $response = Http::withToken($token)->delete($url); if ($response->successful()) { $this->fetchData(); } else { $errors = $response->json('errors') ?? []; foreach ($errors as $field => $messages) { $this->addError("modalData.$field", is_array($messages) ? $messages[0] : $messages); } } } catch (\Exception $e) { logger()->error('DeleteRow error: ' . $e->getMessage()); $this->addError('modalData', 'Something went wrong. Please try again.'); } } //SETS THE ID OF THE ITEM FOR DECISIONING public function confirmDelete($id) { $this->confirmingDeleteId = $id; } //HANDLES DELETE CONFIRMATION AND CALLS deleteRow() FUNCTION public function deleteConfirmed() { if (!$this->confirmingDeleteId) return; $this->deleteRow($this->confirmingDeleteId); // Reset the confirmation state $this->confirmingDeleteId = null; $this->forceRender(); } /** * EXPORT THE DATA FROM THE TABLE */ public function export() { $filename = 'export-data.csv'; $columns = collect($this->columns)->pluck('label')->toArray(); $rows = $this->getFilteredRows()->map(function ($row) { return collect($this->columns)->map(function ($column) use ($row) { return $row[$column['field']] ?? ''; })->toArray(); }); return response()->streamDownload(function () use ($columns, $rows) { $handle = fopen('php://output', 'w'); fputcsv($handle, $columns); foreach ($rows as $row) { fputcsv($handle, $row); } fclose($handle); }, $filename, [ 'Content-Type' => 'text/csv', ]); } /** * MODAL OPEN OR CLOSE FUNCTIONALITY */ public function closeModal() { $this->showModal = false; $this->modalData = []; } /** * SEARCH */ public function updatedSearch() { $this->selected = []; $this->page = 1; $this->forceRender(); } /** * SORT BY START AND END DATE */ public function updatedStartDate() { $this->page = 1; $this->forceRender(); } public function updatedEndDate() { $this->page = 1; $this->forceRender(); } /** * SELECT ROW AND SELECT ALL ROWS */ public function selectRow($rowId) { if (in_array($rowId, $this->selected)) { $this->selected = array_diff($this->selected, [$rowId]); } else { $this->selected[] = $rowId; } } public function confirmBulkDelete() { if (empty($this->selected)) return; $this->confirmingBulkDelete = true; } public function deleteAllSelected() { if (empty($this->selected)) return; $token = Session::get('user')['access_token'] ?? null; $url = rtrim(config('services.backend_api.url'), '/') . '/' . $this->deleteAllEndpoint; try { $payload = [ $this->rowKey => $this->selected, ]; $response = Http::withToken($token)->delete($url, $payload); if ($response->successful()) { $this->selected = []; $this->selectAll = false; $this->confirmingBulkDelete = false; $this->fetchData(); } else { $errors = $response->json('errors') ?? []; foreach ($errors as $field => $messages) { $this->addError("bulkDelete.$field", is_array($messages) ? $messages[0] : $messages); } } } catch (\Exception $e) { logger()->error('Bulk delete error: ' . $e->getMessage()); $this->addError('bulkDelete', 'Something went wrong while deleting selected rows.'); } } public function selectAllRows() { $currentRows = $this->getPaginatedRows(); if ($this->selectAll) { $this->selected = collect($currentRows)->pluck($this->rowKey)->toArray(); } else { $this->selected = []; } } public function sortBy($field) { if ($this->sortField === $field) { $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; } else { $this->sortField = $field; $this->sortDirection = 'asc'; } $this->page = 1; $this->forceRender(); } public function gotoPage($page) { $totalRows = $this->getFilteredRows()->count(); $lastPage = max(1, ceil($totalRows / $this->perPage)); $newPage = min(max(1, (int) $page), $lastPage); $this->page = $newPage; $this->forceRender(); Log::info("Page updated to: {$this->page}, Total Rows: {$totalRows}, Last Page: {$lastPage}"); } private function forceRender() { $this->renderKey++; // Increment to force Livewire to re-render } private function getFilteredRows() { $filteredRows = collect($this->rows); // Apply search filtering if ($this->hasSearch && $this->search) { $filteredRows = $filteredRows->filter(function ($row) { foreach ($this->columns as $column) { if (stripos($row[$column['field']] ?? '', $this->search) !== false) { return true; } } return false; }); } // Apply date filtering if (!$this->hasSearch && ($this->startDate || $this->endDate)) { $filteredRows = $filteredRows->filter(function ($row) { $date = $row['created_at'] ?? null; if ($date) { $date = strtotime($date); $start = $this->startDate ? strtotime($this->startDate) : null; $end = $this->endDate ? strtotime($this->endDate) : null; if ($start && $date < $start) { return false; } if ($end && $date > $end) { return false; } } return true; }); } // Apply sorting if ($this->sortField) { $filteredRows = $filteredRows->sortBy($this->sortField, SORT_REGULAR, $this->sortDirection === 'desc'); } return $filteredRows->values(); } private function getPaginatedRows() { $filteredRows = $this->getFilteredRows(); $start = ($this->page - 1) * $this->perPage; $paginated = $filteredRows->slice($start, $this->perPage)->values()->toArray(); // Force Livewire to detect the change by serializing and unserializing $result = json_decode(json_encode($paginated), true); Log::info("Paginated rows count: " . count($result) . ", Start: {$start}, Page: {$this->page}, First Username: " . ($result[0]['username'] ?? 'N/A')); return $result; } public function render() { $filteredRows = $this->getFilteredRows(); $total = $filteredRows->count(); $lastPage = max(1, ceil($total / $this->perPage)); $this->page = min(max(1, $this->page), $lastPage); $paginatedRows = $this->getPaginatedRows(); Log::info("Rendering - Total Rows: {$total}, Current Page: {$this->page}, Last Page: {$lastPage}, Displayed Rows: " . count($paginatedRows)); return view('livewire.components.table', [ 'rows' => $paginatedRows, 'totalRows' => $total, 'perPage' => $this->perPage, 'currentPage' => $this->page, 'lastPage' => $lastPage, 'renderKey' => $this->renderKey, ]); } }