diff --git a/public/css/filmList.css b/public/css/filmList.css index fe82a6f21876364763bcf4eb57e9e28b1ee7fba6..64daea74dbf1841732072c73d1563fcded693e36 100644 --- a/public/css/filmList.css +++ b/public/css/filmList.css @@ -10,6 +10,19 @@ background: var(--neutral-grey-base, #404650); } +.search-filter { + display: flex; +} + +.film-page-container { + flex-direction: column; + justify-content: center; + align-items: center; + padding: 12px 0px 12px 0px; + width: 80%; + margin: auto; +} + .sort-filter { display: flex; gap: 12px; diff --git a/public/files/img/.gitkeep b/public/files/img/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/public/files/trailer/.gitkeep b/public/files/trailer/.gitkeep deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/public/js/filmList.js b/public/js/filmList.js index cc84d2030eb6d2a29af9105b5b30d0ad8e9573a2..d3e1fe9daff93c37785b0279a46cf75514aa0841 100644 --- a/public/js/filmList.js +++ b/public/js/filmList.js @@ -4,26 +4,27 @@ const sort_order = document.getElementById("sort-order") const genre = document.getElementById("filter-genre") const released_year = document.getElementById("filter-year") const urlParams = new URLSearchParams(window.location.search); +const paginationData = document.getElementById('pagination-data'); +let totalPageCount = paginationData.getAttribute('data-total-pages'); let currentPage = parseInt(urlParams.get('page')) || 1; const film_cards = document.getElementById("film-card-list") -const prev_page = document.getElementById("prev-page") -const next_page = document.getElementById("next-page") const utils = new Utils() async function searchFilterHandler() { try { const httpClient = new HttpClient(); - const search = search_bar.value !== undefined ? search_bar.value : "tesss"; - let isDesc = sort_order.value !== 'asc'; - console.log(isDesc) + const search = search_bar.value !== undefined ? search_bar.value : ""; + let url = `/search?q=${search_bar.value}&genre=${genre.value}&year=${released_year.value}&order=${sort_by.value}&sort=${sort_order.value}&page=${currentPage}` - httpClient.get(`/search?q=${search}&genre=${genre.value}&year=${released_year.value}&order=${sort_by.value}&desc=${isDesc}&page=${currentPage}`).then( + httpClient.get(url).then( (response) => { console.log(response) if (response.status === 200) { const responseData = response.data; updateFilmCards(responseData['films']); + totalPageCount = responseData['total_page']; + generatePaginationLinks() } else { console.error("Error:", response); } @@ -35,22 +36,54 @@ async function searchFilterHandler() { } } +function generatePaginationLinks() { + const paginationContainer = document.getElementById("pagination-container") + paginationContainer.innerHTML = ""; + console.log(totalPageCount) + + for (let i = 1; i <= totalPageCount; i++) { + const pageLink = document.createElement("a"); + pageLink.textContent = i; + pageLink.href = `?page=${i}`; + pageLink.classList.add("page-number"); + if (i === currentPage) { + pageLink.classList.add("active"); + } + pageLink.addEventListener('click', (e) => { + e.preventDefault(); + currentPage = i; + searchFilterHandler(); + }); + + paginationContainer.appendChild(pageLink); + } +} + function updateFilmCards(films) { film_cards.innerHTML = "" film_cards.innerHTML = films.map((film) => ` <div class='film-card'> - <div class='film-image' style='background-image: url(${film.image_path});'></div> + <div class='film-image' style="background-image: url('public/${film.image_path}');"></div> <div class='film-title'>${film.title}</div> </div> `).join(''); } +for (let i = 1; i <= totalPageCount; i++) { + const pageLink = document.getElementById(`page-${i}`); + if (pageLink) { + pageLink.addEventListener('click', (e) => { + e.preventDefault(); + currentPage = i; + searchFilterHandler(); + }); + } +} -search_bar.addEventListener('change', utils.debounce(searchFilterHandler, 300)); +search_bar.addEventListener('input', utils.debounce(searchFilterHandler, 300)); sort_by.addEventListener('change', utils.debounce(searchFilterHandler, 300)); sort_order.addEventListener('change', utils.debounce(searchFilterHandler, 300)); genre.addEventListener('change', utils.debounce(searchFilterHandler, 300)); released_year.addEventListener('change', utils.debounce(searchFilterHandler, 300)); -prev_page.addEventListener('click', utils.debounce(searchFilterHandler, 300)); -next_page.addEventListener('click', utils.debounce(searchFilterHandler, 300)); \ No newline at end of file +generatePaginationLinks() \ No newline at end of file diff --git a/src/base/BaseRepository.php b/src/base/BaseRepository.php index 7848a3b58cc83e2e670c4b155dcde0e88bc2267f..f41f9c9bbf5e07795de1dae7ba6c272fd1c24564 100644 --- a/src/base/BaseRepository.php +++ b/src/base/BaseRepository.php @@ -46,26 +46,28 @@ abstract class BaseRepository { $sql = "SELECT COUNT(*) FROM $this->tableName"; - // Mapping where - if (count($where) > 0) { - foreach ($where as $key => $value) { - $columns = [$key]; - if (isset($value[3]) and is_array(($value[3]))) { - $columns = [$key] + $value[3]; - } - $subConditions = []; - foreach ($columns as $column) { - if (isset($value[2]) and $value[2] == 'LIKE') { - $subConditions[] = "LOWER($column) LIKE LOWER(:$column)"; - } else { - $subConditions[] = "$column = :$column"; + $conditions = []; + + // Mapping where + if (count($where) > 0) { + foreach ($where as $key => $value) { + $columns = [$key]; + if (isset($value[3]) and is_array(($value[3]))) { + $columns = [$key] + $value[3]; + } + $subConditions = []; + foreach ($columns as $column) { + if (isset($value[2]) and $value[2] == 'LIKE') { + $subConditions[] = "LOWER($column) LIKE LOWER(:$column)"; + } else { + $subConditions[] = "$column = :$column"; + } + } + $conditions[] = "(" . implode(" OR ", $subConditions) . ")"; } - } - $conditions[] = "(" . implode(" OR ", $subConditions) . ")"; - } - $sql .= " WHERE " . implode(" AND ", $conditions); - } + $sql .= " WHERE " . implode(" AND ", $conditions); + } // Hydrating statement, for sanitizing $stmt = $this->pdo->prepare($sql); @@ -85,6 +87,8 @@ abstract class BaseRepository } $stmt->execute(); + + return $stmt->fetchColumn(); } @@ -93,7 +97,7 @@ abstract class BaseRepository $order = null, $pageNo = null, $pageSize = null, - $isDesc = false, + $sort = "asc", ) { $sql = "SELECT * FROM $this->tableName"; @@ -124,7 +128,7 @@ abstract class BaseRepository $sql .= " ORDER BY $order"; } - if ($isDesc) { + if ($sort == "desc") { $sql .= " DESC"; } @@ -188,9 +192,6 @@ abstract class BaseRepository $stmt->bindValue(":$key", $value[0], $value[1]); } } - - $stmt->execute(); - return $stmt->fetch(); } diff --git a/src/controllers/FilmController.php b/src/controllers/FilmController.php index 3c71274bda1e31efe85cde2787f545677cf40259..5589d2d03d10dd1bc0b42d8b1ba65a8b6950ea92 100644 --- a/src/controllers/FilmController.php +++ b/src/controllers/FilmController.php @@ -24,20 +24,22 @@ class FilmController extends BaseController $this->favorite_handler = FavoriteService::getInstance(); } - protected function get($urlParams) - { - $uri = Request::getURL(); - $page = (isset($_GET['page']) and (int) $_GET['page'] >= 1) ? $_GET['page'] : 1; - $word = $_GET['q'] ?? ""; - $genre = $_GET['genre'] ?? 'all'; - $released_year = $_GET['year'] ?? 'all'; - $isDesc = $_GET['desc'] ?? false; - $order = $_GET['order'] ?? 'title'; - $data = $this->service->searchAndFilter($word, $order, $isDesc, $genre, $released_year, $page); + protected function get($urlParams) + { + $uri = Request::getURL(); + $page = (isset($_GET['page']) and (int) $_GET['page'] >= 1) ? $_GET['page'] : 1; + $word = $_GET['q'] ?? ""; + $genre = $_GET['genre'] ?? 'all'; + $released_year = $_GET['year'] ?? 'all'; + $isDesc = $_GET['sort'] ?? "asc"; + $order = $_GET['order'] ?? 'title'; + $data = $this->service->searchAndFilter($word, $order, $isDesc, $genre, $released_year, $page); + $row_count = $this->service->countRowBySearchAndFilter($word, $genre, $released_year); if ($uri == "/films") { $data['genres'] = $this->service->getAllCategoryValues('genre'); $data['released_years'] = $this->service->getAllCategoryValues('released_year'); + $data['total_page'] = ceil($row_count/4); parent::render($data, 'films', "layouts/base"); } elseif ($uri == '/film-details') { @@ -52,6 +54,7 @@ class FilmController extends BaseController $films[] = $film->toResponse(); } $data['films'] = $films; + $data['total_page'] = ceil($row_count/4); response::send_json_response($data); } diff --git a/src/repositories/FilmRepository.php b/src/repositories/FilmRepository.php index e423cf7acb31c2d4c83ca493c6bbb913265ece75..3fa2bf48e8a7c92f1c76a7a8d21d369fe10582c0 100644 --- a/src/repositories/FilmRepository.php +++ b/src/repositories/FilmRepository.php @@ -29,16 +29,10 @@ class FilmRepository extends BaseRepository return $this->findOne(['film_id' => [$film_id, PDO::PARAM_INT]]); } - public function getAllBySearchAndFilter( - $word, - $order = 'title', - $isDesc = false, - $genre = 'all', - $released_year = 'all', - $pageNo = 1, - $limit = 10 - ) { - $where = []; + public function getAllBySearchAndFilter($word, $order = 'title', $isDesc= "asc", $genre = 'all', + $released_year = 'all', $pageNo = 1, $limit = 4) + { + $where = []; if (isset($genre) and !empty($genre) and $genre != 'all') { $where['genre'] = [$genre, PDO::PARAM_STR, 'LIKE']; diff --git a/src/services/FilmService.php b/src/services/FilmService.php index 8750dcd7b46a4896e47070c96006b0bd13b1c5ad..eb143a71d03508ec93bfc03d6b6e2bb2e49b6847 100644 --- a/src/services/FilmService.php +++ b/src/services/FilmService.php @@ -114,4 +114,10 @@ class FilmService extends BaseService { return $this->repository->deleteById($film_id); } + + public function countRowBySearchAndFilter($word, $genre = 'all', $released_year = 'all') + { + return $this->repository->countRowBySearchAndFilter($word, $genre, $released_year); + } + } diff --git a/views/films.php b/views/films.php index 4cbba5bc005997fe8b89a2fd1679f496355ac4b5..59d37cb5f73e67481d524586ab3acbf9beae9303 100644 --- a/views/films.php +++ b/views/films.php @@ -1,49 +1,53 @@ -<div> - <div class="search-bar" id="search-bar"> - <input type="text" id="search-input" placeholder="Search film title or director"> - </div> +<div class="film-page-container"> + <div class="search-filter"> + <div class="search-bar" id="search-bar"> + <input type="text" id="search-input" placeholder="Search film title or director"> + </div> - <div class="sort-filter"> - <select id="sort-by"> - <option value="title">Sort by Title</option> - <option value="released_year">Sort by Released Year</option> - </select> + <div class="sort-filter"> + <select id="sort-by"> + <option value="title">Sort by Title</option> + <option value="released_year">Sort by Released Year</option> + </select> - <select id="sort-order"> - <option value="asc">Ascending</option> - <option value="desc">Descending</option> - </select> + <select id="sort-order"> + <option value="asc">Ascending</option> + <option value="desc">Descending</option> + </select> - <select id="filter-genre"> - <option value="all">All Genre</option> - <?php - if (isset($data['genres'])) { - foreach ($data['genres'] as $genre) { - echo "<option value='$genre'>$genre</option>"; + <select id="filter-genre"> + <option value="all">All Genre</option> + <?php + if (isset($data['genres'])) { + foreach ($data['genres'] as $genre) { + echo "<option value='$genre'>$genre</option>"; + } } - } - ?> - </select> + ?> + </select> - <select id="filter-year"> - <option value="all">All Released Year</option> - <?php - if (isset($data['released_years'])) { - foreach ($data['released_years'] as $year) { - echo "<option value='$year'>$year</option>"; + <select id="filter-year"> + <option value="all">All Released Year</option> + <?php + if (isset($data['released_years'])) { + foreach ($data['released_years'] as $year) { + echo "<option value='$year'>$year</option>"; + } } - } - ?> - </select> + ?> + </select> + </div> </div> + + <div class="film-card-container" id="film-card-list"> <?php if (isset($data['films'])) { foreach ($data['films'] as $film) { echo "<div class='film-card'> <a href='/film-details?film_id=$film->film_id'> - <div class='film-image' style='background-image: url($film->image_path);'></div> + <div class='film-image' style='background-image: url(public/$film->image_path);'></div> <div class='film-title'> $film->title </div> </a> </div>"; @@ -52,18 +56,13 @@ ?> </div> - <div class="pagination"> - <button id="prev-page">Previous</button> - <?php - $totalPages = $data['total_page']; - $currentPage = $_GET['page'] ?? 1; + <div id="pagination-data" data-total-pages="<?php echo $data['total_page']; ?>"> - for ($i = 1; $i <= $totalPages; $i++) { - echo "<a href='?page=$i' id='current-page' class='page-number " . ($i == $currentPage ? 'active' : '') . "'>$i</a>"; - } - ?> - <button id="next-page">Next</button> </div> + <div id="pagination-container"> + + </div> + <script defer src="/public/js/httpClient.js"></script> <script defer src="/public/js/utils.js"></script> <script defer src="/public/js/filmList.js"></script>