From 43af1a57799e4a2a3f64f0955844461651310661 Mon Sep 17 00:00:00 2001 From: hskwon Date: Mon, 24 Nov 2025 21:21:22 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EC=85=98=20=EA=B8=B0=EB=8A=A5=20=EA=B0=9C=EC=84=A0=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B3=B5=ED=86=B5=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 페이지네이션 로직을 별도 JS 파일로 분리 (public/js/pagination.js) * 쿠키 기반 per_page 값 저장 및 유지 * 페이지네이션 이벤트 핸들러 통합 * 중복 코드 제거 - 페이지네이션 UI 개선 * 처음으로/끝으로 이동 버튼 추가 * selectbox 너비 조정 (90px) * 서버사이드 selected 속성으로 옵션 매칭 개선 - 초기 페이지당 항목 수를 10개로 변경 * TenantController, UserController, DepartmentController, RoleController 기본값 수정 - layouts/app.blade.php * pagination.js 로드 추가 * 기존 인라인 스크립트 제거 변경 파일: - public/js/pagination.js (신규) - resources/views/layouts/app.blade.php - resources/views/partials/pagination.blade.php - app/Http/Controllers/Api/Admin/{Tenant,User,Department,Role}Controller.php --- .../Api/Admin/DepartmentController.php | 2 +- .../Controllers/Api/Admin/RoleController.php | 2 +- .../Api/Admin/TenantController.php | 2 +- .../Controllers/Api/Admin/UserController.php | 2 +- public/js/pagination.js | 126 ++++++++++++++++++ resources/views/layouts/app.blade.php | 1 + resources/views/partials/pagination.blade.php | 94 +++++++++---- 7 files changed, 201 insertions(+), 28 deletions(-) create mode 100644 public/js/pagination.js diff --git a/app/Http/Controllers/Api/Admin/DepartmentController.php b/app/Http/Controllers/Api/Admin/DepartmentController.php index b5432b5c..0885bb09 100644 --- a/app/Http/Controllers/Api/Admin/DepartmentController.php +++ b/app/Http/Controllers/Api/Admin/DepartmentController.php @@ -22,7 +22,7 @@ public function index(Request $request): JsonResponse { $departments = $this->departmentService->getDepartments( $request->all(), - $request->integer('per_page', 15) + $request->integer('per_page', 10) ); // HTMX 요청 시 HTML 반환 diff --git a/app/Http/Controllers/Api/Admin/RoleController.php b/app/Http/Controllers/Api/Admin/RoleController.php index 31316974..75ab765b 100644 --- a/app/Http/Controllers/Api/Admin/RoleController.php +++ b/app/Http/Controllers/Api/Admin/RoleController.php @@ -22,7 +22,7 @@ public function index(Request $request): JsonResponse { $roles = $this->roleService->getRoles( $request->all(), - $request->integer('per_page', 15) + $request->integer('per_page', 10) ); // HTMX 요청 시 HTML 반환 diff --git a/app/Http/Controllers/Api/Admin/TenantController.php b/app/Http/Controllers/Api/Admin/TenantController.php index 3ca3abbb..83dfd9ff 100644 --- a/app/Http/Controllers/Api/Admin/TenantController.php +++ b/app/Http/Controllers/Api/Admin/TenantController.php @@ -22,7 +22,7 @@ public function index(Request $request): JsonResponse { $tenants = $this->tenantService->getTenants( $request->all(), - $request->integer('per_page', 15) + $request->integer('per_page', 10) ); // HTMX 요청 시 HTML 반환 diff --git a/app/Http/Controllers/Api/Admin/UserController.php b/app/Http/Controllers/Api/Admin/UserController.php index 469577e9..8a71af77 100644 --- a/app/Http/Controllers/Api/Admin/UserController.php +++ b/app/Http/Controllers/Api/Admin/UserController.php @@ -22,7 +22,7 @@ public function index(Request $request): JsonResponse { $users = $this->userService->getUsers( $request->all(), - $request->integer('per_page', 15) + $request->integer('per_page', 10) ); // HTMX 요청인 경우 HTML 반환 diff --git a/public/js/pagination.js b/public/js/pagination.js new file mode 100644 index 00000000..35a58719 --- /dev/null +++ b/public/js/pagination.js @@ -0,0 +1,126 @@ +/** + * 공통 페이지네이션 스크립트 + * + * 기능: + * - 쿠키 기반 per_page 값 관리 + * - 페이지네이션 이벤트 핸들러 + * - HTMX 연동 + */ + +// ============================================ +// 쿠키 헬퍼 함수 +// ============================================ + +window.setCookie = function(name, value, days = 365) { + const date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + const expires = "expires=" + date.toUTCString(); + document.cookie = name + "=" + value + ";" + expires + ";path=/"; +}; + +window.getCookie = function(name) { + const nameEQ = name + "="; + const ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) == ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length); + } + return null; +}; + +window.getPerPageFromCookie = function() { + const savedPerPage = getCookie('pagination_per_page'); + return savedPerPage ? savedPerPage : '10'; // 기본값 10 +}; + +// ============================================ +// 페이지네이션 이벤트 핸들러 +// ============================================ + +// 페이지당 항목 수 변경 핸들러 +window.handlePerPageChange = function(perPage) { + console.log('handlePerPageChange called with:', perPage); + + // 쿠키에 저장 + setCookie('pagination_per_page', perPage); + console.log('Cookie saved. Reading back:', getCookie('pagination_per_page')); + + // 현재 페이지의 HTMX 타겟 찾기 + const target = document.querySelector('[hx-trigger*="filterSubmit"]'); + if (target) { + const perPageInput = document.getElementById('perPageInput'); + const pageInput = document.getElementById('pageInput'); + + if (perPageInput && pageInput) { + perPageInput.value = perPage; + pageInput.value = 1; // 페이지를 1로 초기화 + console.log('Triggering HTMX with per_page:', perPageInput.value); + htmx.trigger(target, 'filterSubmit'); + } + } +}; + +// 페이지 변경 핸들러 +window.handlePageChange = function(page) { + const target = document.querySelector('[hx-trigger*="filterSubmit"]'); + if (target) { + const pageInput = document.getElementById('pageInput'); + + if (pageInput) { + pageInput.value = page; + htmx.trigger(target, 'filterSubmit'); + } + } +}; + +// ============================================ +// 초기화 +// ============================================ + +document.addEventListener('DOMContentLoaded', function() { + // filterForm 찾기 + const filterForm = document.getElementById('filterForm'); + if (!filterForm) return; + + // hidden input이 이미 존재하는지 확인 + let perPageInput = document.getElementById('perPageInput'); + let pageInput = document.getElementById('pageInput'); + + // per_page input 생성 또는 업데이트 + if (!perPageInput) { + perPageInput = document.createElement('input'); + perPageInput.type = 'hidden'; + perPageInput.name = 'per_page'; + perPageInput.id = 'perPageInput'; + filterForm.appendChild(perPageInput); + } + perPageInput.value = getPerPageFromCookie(); + + // page input 생성 또는 업데이트 + if (!pageInput) { + pageInput = document.createElement('input'); + pageInput.type = 'hidden'; + pageInput.name = 'page'; + pageInput.id = 'pageInput'; + pageInput.value = '1'; + filterForm.appendChild(pageInput); + } +}); + +// ============================================ +// HTMX 이벤트 핸들러 +// ============================================ + +// HTMX afterSwap: 테이블 새로고침 시 selectbox 재설정 +document.body.addEventListener('htmx:afterSwap', function(event) { + // selectbox 설정을 약간 지연시켜 DOM이 완전히 렌더링된 후 실행 + setTimeout(function() { + const perPageSelect = document.getElementById('perPageSelect'); + if (perPageSelect) { + const savedPerPage = getPerPageFromCookie(); + console.log('HTMX afterSwap - Setting selectbox to:', savedPerPage); + perPageSelect.value = savedPerPage; + } + }, 50); +}); diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index e181c860..b4b2eeb3 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -7,6 +7,7 @@ @yield('title', 'Dashboard') - {{ config('app.name') }} @vite(['resources/css/app.css', 'resources/js/app.js']) + @stack('styles') diff --git a/resources/views/partials/pagination.blade.php b/resources/views/partials/pagination.blade.php index a77fabc0..2142e7fc 100644 --- a/resources/views/partials/pagination.blade.php +++ b/resources/views/partials/pagination.blade.php @@ -18,18 +18,16 @@ 이전 @else - @endif @if($paginator->hasMorePages()) - @@ -42,29 +40,53 @@ class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 t