| @@ -15,6 +15,11 @@ export default { | |||
| DatePicker, | |||
| }, | |||
| setup() { | |||
| const searchPage = ref(); | |||
| const currentPage = ref(1); | |||
| const totalPages = ref(1); | |||
| const paginate = ref(20); | |||
| const page = ref(1); | |||
| const pdfLoading = ref(false); | |||
| const csvLoading = ref(false); | |||
| const filterLoading = ref(false); | |||
| @@ -23,6 +28,27 @@ export default { | |||
| const logs = ref(); | |||
| const startDate = ref(); | |||
| const endDate = ref(); | |||
| const visiblePages = computed(() => { | |||
| const pages = []; | |||
| if (totalPages.value <= 5) { | |||
| for (let i = 1; i <= totalPages.value; i++) { | |||
| pages.push(i); | |||
| } | |||
| } else { | |||
| let start = currentPage.value - 2; | |||
| let end = currentPage.value + 2; | |||
| if (start < 1) start = 1; | |||
| if (end > totalPages.value) end = totalPages.value; | |||
| for (let i = start; i <= end; i++) { | |||
| pages.push(i); | |||
| } | |||
| } | |||
| return pages; | |||
| }); | |||
| const exportFile = (param) => { | |||
| if (param === "pdf") { | |||
| console.log("pdf"); | |||
| @@ -101,7 +127,7 @@ export default { | |||
| selectedUser.value || "" | |||
| }&start_date=${startDate.value || ""}&end_date=${ | |||
| endDate.value || "" | |||
| }`, | |||
| }&paginate=${paginate.value || 10}&page=${page.value || 1}`, | |||
| { | |||
| headers: { | |||
| "Content-Type": "application/json", | |||
| @@ -111,13 +137,45 @@ export default { | |||
| ) | |||
| .then((resp) => { | |||
| filterLoading.value = false; | |||
| logs.value = resp.data.data; | |||
| logs.value = resp.data.data.data; | |||
| currentPage.value = resp.data.data.current_page; | |||
| totalPages.value = resp.data.data.last_page; | |||
| }) | |||
| .catch(() => { | |||
| filterLoading.value = false; | |||
| }); | |||
| }; | |||
| function handlePageInput() { | |||
| if (searchPage.value < 1) { | |||
| searchPage.value = 1; | |||
| } else if (searchPage.value > totalPages.value) { | |||
| searchPage.value = totalPages.value; | |||
| } | |||
| if (searchPage.value >= 1 && searchPage.value <= totalPages.value) { | |||
| page.value = searchPage.value; | |||
| } | |||
| } | |||
| watch(page, () => { | |||
| getLogs(); | |||
| }); | |||
| const nextPage = () => { | |||
| if (currentPage.value < totalPages.value) { | |||
| page.value++; | |||
| getLogs(); | |||
| } | |||
| }; | |||
| const prevPage = () => { | |||
| if (currentPage.value > 1) { | |||
| page.value--; | |||
| getLogs(); | |||
| } | |||
| }; | |||
| const handleLocationUpdate = () => { | |||
| location.reload(); | |||
| }; | |||
| @@ -189,6 +247,15 @@ export default { | |||
| pdfLoading, | |||
| csvLoading, | |||
| exportFile, | |||
| currentPage, | |||
| totalPages, | |||
| nextPage, | |||
| prevPage, | |||
| page, | |||
| handlePageInput, | |||
| searchPage, | |||
| visiblePages, | |||
| }; | |||
| }, | |||
| }; | |||
| @@ -309,6 +376,78 @@ export default { | |||
| </div> | |||
| </div> | |||
| </BRow> | |||
| <BRow> | |||
| <BCol sm="12"> | |||
| <div class="d-flex justify-content-center"> | |||
| <nav aria-label="Page navigation"> | |||
| <ul class="pagination"> | |||
| <li class="page-item" :class="{ disabled: currentPage === 1 }"> | |||
| <span class="page-link" @click="prevPage">قبلی</span> | |||
| </li> | |||
| <li v-if="currentPage > 2" class="page-item" @click="page = 1"> | |||
| <a class="page-link" href="javascript:void(0)">1</a> | |||
| </li> | |||
| <li v-if="currentPage > 3" class="page-item" disabled> | |||
| <span class="page-link">...</span> | |||
| </li> | |||
| <li | |||
| v-for="n in visiblePages" | |||
| :key="n" | |||
| class="page-item" | |||
| :class="{ active: currentPage === n }" | |||
| > | |||
| <a | |||
| class="page-link" | |||
| href="javascript:void(0)" | |||
| @click="page = n" | |||
| > | |||
| {{ n }} | |||
| </a> | |||
| </li> | |||
| <li | |||
| v-if="currentPage < totalPages - 2" | |||
| class="page-item" | |||
| disabled | |||
| > | |||
| <span class="page-link">...</span> | |||
| </li> | |||
| <li | |||
| v-if="currentPage < totalPages - 1" | |||
| class="page-item" | |||
| @click="page = totalPages" | |||
| > | |||
| <a class="page-link" href="javascript:void(0)">{{ | |||
| totalPages | |||
| }}</a> | |||
| </li> | |||
| <li | |||
| class="page-item" | |||
| :class="{ disabled: currentPage === totalPages }" | |||
| > | |||
| <span class="page-link" @click="nextPage">بعدی</span> | |||
| </li> | |||
| </ul> | |||
| </nav> | |||
| </div> | |||
| </BCol> | |||
| <BCol sm="4"> | |||
| <div class="ms-0 search-number"> | |||
| <input | |||
| v-model="searchPage" | |||
| type="text" | |||
| class="form-control" | |||
| placeholder="برو به صفحه" | |||
| :max="totalPages" | |||
| min="1" | |||
| @input="handlePageInput" | |||
| /> | |||
| </div> | |||
| </BCol> | |||
| </BRow> | |||
| </Layout> | |||
| </template> | |||
| @@ -333,4 +472,46 @@ export default { | |||
| animation: spin 1s linear infinite; | |||
| margin: 20px auto; /* Center the loader */ | |||
| } | |||
| .search-number { | |||
| display: flex; | |||
| align-items: center; | |||
| } | |||
| .search-number input { | |||
| width: 150px; | |||
| padding: 0.5rem; | |||
| font-size: 1rem; | |||
| border-radius: 0.375rem; | |||
| margin-bottom: 7px; | |||
| border: 1px solid #ced4da; | |||
| transition: border-color 0.3s ease, box-shadow 0.3s ease; | |||
| } | |||
| .search-number input:focus { | |||
| border-color: #007bff; | |||
| box-shadow: 0 0 0 0.2rem rgba(38, 143, 255, 0.25); | |||
| } | |||
| .search-number input::placeholder { | |||
| color: #6c757d; | |||
| } | |||
| .search-number input:disabled { | |||
| background-color: #f8f9fa; | |||
| cursor: not-allowed; | |||
| } | |||
| .pagination { | |||
| display: flex; | |||
| flex-wrap: wrap; | |||
| gap: 5px; | |||
| } | |||
| .page-item { | |||
| flex: 0 0 auto; | |||
| } | |||
| .page-link { | |||
| cursor: pointer; | |||
| user-select: none; | |||
| } | |||
| </style> | |||