get('limit', $request->get('per_page', 20)), 200); $query = Mail::query()->with(['customer', 'template'])->orderByDesc('created_at'); // sort=field_asc|field_desc if ($sort = $request->get('sort')) { $parts = explode('_', $sort); $dir = array_pop($parts); $col = implode('_', $parts); $allowed = ['created_at', 'subject', 'status', 'to']; if (in_array($col, $allowed, true) && in_array($dir, ['asc', 'desc'], true)) { $query->reorder($col, $dir); } } if ($status = $request->get('status')) { $query->where('status', array_search($status, Mail::STATUS_MAP, true) ?: $status); } if ($customerId = $request->get('customer_id')) { $query->where('customer_id', (int) $customerId); } if ($search = trim((string) $request->get('search', ''))) { $query->where(function ($q) use ($search) { $q->where('to', 'like', "%{$search}%") ->orWhere('subject', 'like', "%{$search}%"); }); } $paginator = $query->paginate($limit); return response()->json([ 'error' => false, 'data' => [ 'items' => $paginator->getCollection()->map($this->mapLog(...))->all(), 'total' => $paginator->total(), 'per_page' => $paginator->perPage(), 'current_page' => $paginator->currentPage(), 'last_page' => $paginator->lastPage(), ], ]); } public function show(int $id): JsonResponse { $log = Mail::with(['customer', 'template'])->find($id); if (!$log) { return response()->json(['error' => true, 'message' => 'Không tìm thấy email log'], 404); } return response()->json(['error' => false, 'data' => $this->mapLog($log)]); } private function mapLog(Mail $log): array { return [ 'id' => $log->id, 'to_email' => $log->to, 'to_name' => $log->customer->fullname ?? null, 'customer_id' => $log->customer_id, 'subject' => $log->subject, 'template' => $log->template->name ?? '—', 'status' => $log->status, 'error_message' => null, 'sent_at' => $log->status === 'sent' ? $log->created_at : null, 'created_at' => $log->created_at, ]; } }