diff --git a/Dockerfile b/Dockerfile index ed963e0d7ba40f22abc61916e935d34f4b65e5ba..4a99758304cf6d67bf337c51109ad2abfde5968b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,4 +8,17 @@ COPY ./app /var/www/html RUN echo "ServerName localhost:80" >> /etc/apache2/apache2.conf CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] +RUN sudo chown www-data:www-data /var/www/html/public/img/anime/ +RUN sudo chmod 755 /var/www/html/public/img/anime/ + +RUN sudo chown www-data:www-data /var/www/html/public/img/client/ +RUN sudo chmod 755 /var/www/html/public/img/client/ + +RUN sudo chown www-data:www-data /var/www/html/public/img/studio/ +RUN sudo chmod 755 /var/www/html/public/img/studio/ + +RUN sudo chown www-data:www-data /var/www/html/public/vid/ +RUN sudo chmod 755 /var/www/html/public/vid/ + + RUN service apache2 restart \ No newline at end of file diff --git a/app/api/anime/filter.php b/app/api/anime/filter.php new file mode 100644 index 0000000000000000000000000000000000000000..a9e8d5e4d6b389f4c921e7f85a3dc7b0b94374df --- /dev/null +++ b/app/api/anime/filter.php @@ -0,0 +1,36 @@ +<?php + +require_once(dirname(__DIR__,2).'/define.php'); +require_once(BASE_DIR.'/models/Anime.php'); + +$first = true; + +$a = new Anime(); +$genreFilter = $_POST['filter-genre'] != "Any" ? 'genre='.$_POST['filter-genre'] : ""; +$typeFilter = $_POST['filter-type'] != "Any" ? 'type='.$_POST['filter-type'] : ""; +$statusFilter = $_POST['filter-status'] != "Any" ? 'status='.$_POST['filter-status'] : ""; +$ratingFilter = $_POST['filter-rating'] != "Any" ? 'rating='.$_POST['filter-rating'] : ""; +$studioFilter = $_POST['filter-studio'] != "Any" ? 'studio='.$_POST['filter-studio'] : ""; +$sortFilter = $_POST['filter-sort'] != "Any" ? 'sort='.$_POST['filter-sort'] : ""; + +$filterArray = array ( + $genreFilter, $typeFilter, $statusFilter, $ratingFilter, $studioFilter, $sortFilter +); +$url = '/?anime/'; + +foreach($filterArray as $f){ + if ($first){ + if ($f != ""){ + $url = $url.$f; + $first = false; + } + } else { + if ($f != ""){ + $url = $url.'&'.$f; + } + } +} +$url = $first ? $url.'page=1' : $url.'&page=1'; + +header("Location: ".$url); +?> \ No newline at end of file diff --git a/app/api/anime_list/add.php b/app/api/anime_list/add.php index c9bcb5882a028983c2594410e01cc8cd7da9531e..d9c14696af5d378e5a3c2b38851102095cb4caad 100644 --- a/app/api/anime_list/add.php +++ b/app/api/anime_list/add.php @@ -4,28 +4,20 @@ require_once(BASE_DIR.'/models/Anime_List.php'); $al = new Anime_List(); -if (isset($_GET['client_id']) && isset($_GET['anime_id'])) { - $client_id = $_GET['client_id']; - $anime_id = $_GET['anime_id']; +$aid = $_POST['anime_id']; +$cid = $_POST['client_id']; - $data = [ - 'client_id' => $client_id, - 'anime_id' => $anime_id, - 'user_score' => null, - 'progress' => null, - 'watch_status' => null, - 'review' => null - ]; - - if ($al->insertAnimeList($data)) { - if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER']) { - header("Location: " . $_SERVER['HTTP_REFERER'] . "/?message=Added Succesfully"); - } else { - header("Location: /?message=Added Succesfully"); - } - exit(); - } else { - header('Location: /?error=Failed to add'); - } -} -?> +$animeListArr = array ( + 'client_id' => $cid, + 'anime_id' => $aid, + 'user_score'=> null, + 'progress' => null, + 'watch_status' => 'PLAN TO WATCH', + 'review' => null +); + +$al->insertAnimeList($animeListArr); +header('Location: /?anime/detail/'.$aid); + + +?> \ No newline at end of file diff --git a/app/api/anime_list/delete.php b/app/api/anime_list/delete.php index f3dc9e37abfd51c1dfb3f5befc64cb85839fb36f..92114b39eda24f4d201262a8aa97d7b359b37576 100644 --- a/app/api/anime_list/delete.php +++ b/app/api/anime_list/delete.php @@ -2,20 +2,15 @@ require_once(dirname(__DIR__,2).'/define.php'); require_once(BASE_DIR.'/models/Anime_List.php'); -if (isset($_GET['id'])) { - $id = $_GET['id']; - $al = new Anime_List(); +$al = new Anime_List(); + +$aid = $_POST['anime_id']; +$cid = $_POST['client_id']; + +$list_id = $al->getAnimeListByAnimeClientID($aid, $cid)['list_id']; + +$al->deleteAnimeList($list_id); +header('Location: /?anime/detail/'.$aid); - if ($al->deleteAnimeList($id)) { - if (isset($_SERVER['HTTP_REFERER']) && $_SERVER['HTTP_REFERER']) { - header("Location: " . $_SERVER['HTTP_REFERER'] . "/?message=Deleted Succesfully"); - } else { - header("Location: /?message=Deleted Succesfully"); - } - exit(); - } else { - header('Location: /?error=Failed to delete ' . $id); - } -} ?> \ No newline at end of file diff --git a/app/api/auth/signup.php b/app/api/auth/signup.php index 4c706f345a35056ffdf5a223d99f9c7058a84eb0..945f2ff1c316382cfbe6f6ca15a65c7ab80adcc5 100644 --- a/app/api/auth/signup.php +++ b/app/api/auth/signup.php @@ -2,16 +2,42 @@ require_once(dirname(__DIR__,2).'/define.php'); require_once(BASE_DIR.'/models/Client.php'); -session_start(); -if (isset($_POST['username']) && isset($_POST['email'])){ - $c = new Client(); - $username = $c->getClientByUsername($_POST['username']); - $email = $c->getClientByEmail($_POST['email']); - // echo $username['client_id']; - if (!$username || !$email){ - $_SESSION['error'] = 'Username or Email already exists'; - header('Location: /?signup'); +$c = new Client(); +$xml = file_get_contents('php://input'); +$data = json_decode($xml, true); + +if (isset($data['email'])){ + $email = $c->getClientByEmail($data['email']); + if (!$email){ + http_response_code(200); + echo json_encode(array( + 'status' => 'success', + 'message' => 'Email is allowed' + )); + // $_SESSION['error'] = 'Username or Email already exists'; + // header('Location: /?signup'); + } else { + echo json_encode(array( + 'status' => 'error', + 'message' => 'Email already exists' + )); + } +} + +if (isset($data['username'])){ + $username = $c->getClientByUsername($data['username']); + if (!$username){ + http_response_code(200); + echo json_encode(array( + 'status' => 'success', + 'message' => 'Username is allowed' + )); + } else { + echo json_encode(array( + 'status' => 'error', + 'message' => 'Username already exists' + )); } } diff --git a/app/api/client/edit.php b/app/api/client/edit.php index 425495c2000b51120243bcdd7b5024c7916bb383..dabc82a99b10a327ae526ea5e835fdf7da273688 100644 --- a/app/api/client/edit.php +++ b/app/api/client/edit.php @@ -11,6 +11,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { echo "No client ID provided. Cannot proceed with edit."; exit(); } + $data = [ 'client_id' => $_POST['client_id'], 'username' => $_POST['username'], @@ -61,6 +62,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") { $counter = 1; while (file_exists($target_file)) { $info = pathinfo($original_name); + chown($$info['dirname'], 0755); $target_file = $info['dirname'] . '/' . $info['filename'] . '_' . $counter . '.' . $info['extension']; $counter++; } diff --git a/app/controller/AnimeController.php b/app/controller/AnimeController.php index 7b5b4fa2f6eca99c32ec289a76061ad24a995733..8693a859f403e16a7c8ac71b7f89337c33cc2caa 100644 --- a/app/controller/AnimeController.php +++ b/app/controller/AnimeController.php @@ -4,8 +4,11 @@ require_once(dirname(__DIR__,1).'/define.php'); require_once(BASE_DIR.'/models/Controller.php'); class AnimeController extends Controller { - public function index(){ - $this->view('Anime/index'); + public function index($path = "page=1"){ + $this->view('Anime/index', + array( + 'path' => $path + )); } public function detail($id) { $this->view('Anime/detail', array('id' => $id)); diff --git a/app/controller/StudioController.php b/app/controller/StudioController.php index 212b8b2caaa10e4649a9914384dc86a46cba6a08..99caab0b34bd6bba8b1645e055cbd336caceff70 100644 --- a/app/controller/StudioController.php +++ b/app/controller/StudioController.php @@ -4,8 +4,11 @@ require_once(dirname(__DIR__,1).'/define.php'); require_once(BASE_DIR.'/models/Controller.php'); class StudioController extends Controller { - public function index(){ - $this->view('Studio/index'); + public function index($path = "page=1"){ + $this->view('Studio/index', + array( + 'path' => $path + )); } public function detail($id) { $this->view('Studio/detail', array('id' => $id)); diff --git a/app/controller/TrailerController.php b/app/controller/TrailerController.php index 9c536019b5543646732fb52ee075e614cd550193..900d682d3624b06ccaaf4576c851a68e2951c8c6 100644 --- a/app/controller/TrailerController.php +++ b/app/controller/TrailerController.php @@ -4,7 +4,10 @@ require_once(dirname(__DIR__,1).'/define.php'); require_once(BASE_DIR.'/models/Controller.php'); class TrailerController extends Controller { - public function index(){ - $this->view('Trailer/index'); + public function index($path = "page=1"){ + $this->view('Trailer/index', + array( + 'path' => $path + )); } } \ No newline at end of file diff --git a/app/models/anime.php b/app/models/anime.php index e9bc701fb0f3e4624181f8af6f53757eb47c1f7c..4915a1da43b7d20334793f63be52b87950865bf3 100644 --- a/app/models/anime.php +++ b/app/models/anime.php @@ -85,6 +85,16 @@ class Anime { return $this->db->fetchAllData(); } + public function getAllAnimeWithTrailerLimit($limit, $offset){ + if ($limit) { + $this->db->query('SELECT * FROM ' . $this->table . ' WHERE NOT trailer IS NULL ORDER BY release_date DESC LIMIT '.$limit.' OFFSET '.$offset); + return $this->db->fetchAllData(); + } else { + return $this->getAllAnimeWithTrailer(); + } + + } + public function get5LatestAnimeReview(){ $this->db->query('SELECT a.anime_id, a.title, c.client_id, c.username, l.user_score, l.review FROM anime_list l JOIN '.$this->table.' a ON l.anime_id = a.anime_id JOIN client c ON l.client_id = c.client_id @@ -125,5 +135,61 @@ class Anime { return $this->db->fetchAllData(); } + public function getAllAnimeWithFilter($genre, $type, $status, $rating, $studio, $sortColumn, $desc, $limit, $offset) + { + $first = true; + $genreQuery = $genre ? " genre.name = ".$this->db->processDataType($genre) : ""; + $typeQuery = $type ? " anime.type = ".$this->db->processDataType($type) : ""; + $statusQuery = $status ? " anime.status = ".$this->db->processDataType($status) : ""; + $ratingQuery = $rating ? " anime.rating = ".$this->db->processDataType($rating) : ""; + $studioQuery = $studio ? " studio.studio_id = ".$studio : ""; + $limitQuery = $limit ? ' LIMIT '.$limit.' OFFSET '.$offset : ""; + + + if ($sortColumn){ + if ($desc){ + $sortQuery = " ORDER BY anime.".$sortColumn." DESC "; + } else { + $sortQuery = " ORDER BY anime.".$sortColumn." ASC "; + } + } else { + $sortQuery = ''; + } + + + $fullQuery = + " SELECT anime.anime_id, anime.title, anime.release_date, anime.image, anime.score, anime.type, anime.status + FROM anime + JOIN anime_genre ON anime_genre.anime_id = anime.anime_id + JOIN genre ON anime_genre.genre_id = genre.genre_id + JOIN studio ON studio.studio_id = anime.studio_id "; + + + $additionalQuery = array ( + $genreQuery, $typeQuery, $statusQuery, $ratingQuery, $studioQuery + ); + + foreach($additionalQuery as $q){ + if ($first){ + if ($q != ""){ + $fullQuery = $fullQuery." WHERE ".$q; + $first = false; + } + } else { + if ($q != ""){ + $fullQuery = $fullQuery." AND ".$q; + } + } + } + + $fullQuery = $fullQuery.' GROUP BY anime.anime_id '; + $fullQuery = $fullQuery.$sortQuery; + $fullQuery = $fullQuery.$limitQuery; + + $this->db->query($fullQuery); + return $this->db->fetchAllData(); + + } + } \ No newline at end of file diff --git a/app/models/studio.php b/app/models/studio.php index f2228b7ca57732d3ea8df4ddfc0bd9170c48fdaf..0930e8f94a7e026053d58a6fa5771129bf0f7afb 100644 --- a/app/models/studio.php +++ b/app/models/studio.php @@ -72,4 +72,15 @@ class Studio { $this->db->query('SELECT s.studio_id, s.name, s.description, s.established_date, s.image , AVG(score) AS avg FROM '.$this->table.' s JOIN anime a ON a.studio_id = s.studio_id GROUP BY s.studio_id ORDER BY AVG(score) DESC LIMIT 5'); return $this->db->fetchAllData(); } + + public function getAllStudioLimit($limit, $offset){ + if ($limit){ + $this->db->query('SELECT * FROM '.$this->table.' ORDER BY studio_id LIMIT '.$limit.' OFFSET '.$offset); + return $this->db->fetchAllData(); + } else { + return $this->getAllStudio(); + } + + } + } \ No newline at end of file diff --git a/app/public/handler/anime.js b/app/public/handler/anime.js new file mode 100644 index 0000000000000000000000000000000000000000..36ed66245827882983190c4e5d78d4be3e3a6f98 --- /dev/null +++ b/app/public/handler/anime.js @@ -0,0 +1,3 @@ +function handleSearch(){ + let val = document.getElementById('search-bar').value; +} \ No newline at end of file diff --git a/app/public/handler/signup.js b/app/public/handler/signup.js index 78b376ca33b89ff69d6c67aa77c7ea3186c5c848..dbc8e831cbffe0bde403e9bbd66ee034faff324a 100644 --- a/app/public/handler/signup.js +++ b/app/public/handler/signup.js @@ -13,8 +13,23 @@ function checkEmail() { document.getElementById("email").style.borderColor = 'red'; document.getElementById("email-errmsg").innerHTML = "Invalid email detected"; } else { - document.getElementById("email").style.borderColor = 'blue'; - document.getElementById("email-errmsg").innerHTML = ""; + const xhr = new XMLHttpRequest(); + xhr.open('POST', '../../api/auth/signup.php', true); + xhr.onload = function(){ + if (this.status == 200){ + let response = JSON.parse(this.responseText); + console.log(response); + if (response.status == "success"){ + document.getElementById("email").style.borderColor = 'blue'; + document.getElementById("email-errmsg").innerHTML = ""; + } else { + document.getElementById("email").style.borderColor = 'red'; + document.getElementById("email-errmsg").innerHTML = response.message; + } + } + checkSubmitButton(); + } + xhr.send(JSON.stringify({"email": email})); } checkSubmitButton(); } @@ -23,12 +38,26 @@ function checkUsername() { let username = document.getElementById("username").value; let passed = username.match(/^[0-9a-zA-Z]*$/) && username.length >=5; - if (!passed){ - document.getElementById('username').style.borderColor = 'red'; - document.getElementById('username-errmsg').innerHTML = "Username can only be alphanumeric with at lease 5 characters long"; + if (!passed) { + document.getElementById("username").style.borderColor = 'red'; + document.getElementById("username-errmsg").innerHTML = "Invalid username detected"; } else { - document.getElementById("username").style.borderColor = 'blue'; - document.getElementById('username-errmsg').innerHTML = ""; + const xhr = new XMLHttpRequest(); + xhr.open('POST', '../../api/auth/signup.php', true); + xhr.onload = function(){ + if (this.status == 200){ + let response = JSON.parse(this.responseText); + if (response.status == "success"){ + document.getElementById("username").style.borderColor = 'blue'; + document.getElementById("username-errmsg").innerHTML = ""; + } else { + document.getElementById("username").style.borderColor = 'red'; + document.getElementById("username-errmsg").innerHTML = response.message; + } + } + checkSubmitButton(); + } + xhr.send(JSON.stringify({"username": username})); } checkSubmitButton(); } diff --git a/app/public/img/client/1204138.jpg b/app/public/img/client/1204138.jpg new file mode 100644 index 0000000000000000000000000000000000000000..499678ac20123181b9d4f735d60622998f4e54d0 Binary files /dev/null and b/app/public/img/client/1204138.jpg differ diff --git a/app/public/img/client/test.jpg b/app/public/img/client/test.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f42713deb1a43654cb743714f8095d64d0248e0 Binary files /dev/null and b/app/public/img/client/test.jpg differ diff --git a/app/public/img/left_arrow_icon.png b/app/public/img/left_arrow_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d9315870250701333c7d0357183ba18e6b15e39f Binary files /dev/null and b/app/public/img/left_arrow_icon.png differ diff --git a/app/public/img/right_arrow_icon.png b/app/public/img/right_arrow_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1f7d441086c7c861301ab43d76a4fadc37b96d44 Binary files /dev/null and b/app/public/img/right_arrow_icon.png differ diff --git a/app/public/style/anime.css b/app/public/style/anime.css index e81e8f60bd248edca396f2e74f5e6afb5ee0c017..b2aa1ec7a7b1d91466a49aa6174ba10869b22024 100644 --- a/app/public/style/anime.css +++ b/app/public/style/anime.css @@ -1,6 +1,6 @@ .filter-flex { display: flex; - flex-wrap: wrap; + flex-direction: column; justify-content: center; align-items: center; background-color: #dedede; @@ -9,6 +9,90 @@ gap: 5px; } +.filter-part { + display: flex; + flex-wrap: wrap; + flex-direction: row; + justify-content: center; + align-items: end; + gap: 30px; + padding: 0px 20px; +} + +.filter-block{ + display: flex; + flex-direction: column; +} + +.filter-label { + font-weight: bold; + margin-bottom: 5px; +} + +.filter-select select { + display: none; +} + +.filter-select { + border-radius: 10px; + padding: 5px 10px; + border: black 2px solid; + min-width: 150px; + cursor: pointer; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.filter-select:focus { + scale: 115%; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.filter-submit-btn{ + background-color: white; + border: rgb(19, 146, 250) 2px solid; + padding: 10px 15px; + border-radius: 10px; + color: rgb(19, 146, 250); + cursor: pointer; + font-weight: bold; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.filter-submit-btn:hover{ + transition: ease-in-out; + transition-duration: 0.2s; + background-color: rgb(19, 146, 250); + color: white; +} + +.search-part { + display: flex; + flex-wrap: wrap; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 0px 20px; +} + +.search-bar { + width: 350px; + color: black; + padding: 5px 10px; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.search-bar:focus { + transition: ease-in-out; + transition-duration: 0.2s; + scale: 110%; + border: black 2px solid; +} + + .genre-button { min-width: 100px; max-width: 250px; diff --git a/app/public/style/global.css b/app/public/style/global.css index 0b0e76a2215cfe1787121dcb312645b3ba3d044f..4aafdda0e415c57f5b1dec1b9451fc11c868eed0 100644 --- a/app/public/style/global.css +++ b/app/public/style/global.css @@ -401,4 +401,34 @@ footer { background: #ababab; transition: ease-in-out; transition-duration:0.2s; -} \ No newline at end of file +} + +.button-container { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 25px; + padding: 15px 0px; + background-color: transparent; +} + +.page-arrow{ + width: 25px; + padding: 10px; + border-radius: 100%; + cursor: pointer; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.page-arrow:hover{ + background-color: #dbdbdb; + transition: ease-in-out; + transition-duration: 0.2s; +} + +.page-number{ + font-weight: bold; + font-size: 18px; +} diff --git a/app/views/Client/detail.php b/app/views/Client/detail.php index 6a819509728f6d362b5e10c13386e1da8e41b370..1edaaa7dd605e7d5465d23bed2d9bbc3093abf75 100644 --- a/app/views/Client/detail.php +++ b/app/views/Client/detail.php @@ -53,10 +53,11 @@ $isUser = $c->getClientByUsername($_SESSION['username'])['client_id'] == $id; <label for="editAdminStatus">Status:</label> <select id="editAdminStatus" name="admin_status"> <?php + $value = $client['admin_status'] ? "true" : "client"; $option = $client['admin_status'] ? 'Admin' : 'Client'; echo " - <option value='$client[admin_status]'>$option</option> + <option value='$value'>$option</option> "; ?> </select> @@ -134,9 +135,9 @@ $isUser = $c->getClientByUsername($_SESSION['username'])['client_id'] == $id; <div class='client-right-container'> <div class='client-bio-container'> <?php - $bio = $client['bio'] ?? "No bio details"; + $bio = (!$client['bio'] || $client['bio'] == "") ? "No bio details" : $client['bio']; echo " - <div style='margin:20px 20px'> $client[bio] </div> + <div style='margin:20px 20px'> $bio</div> "; ?> </div> diff --git a/app/views/anime/detail.php b/app/views/anime/detail.php index 792aac76016047dfaf05bcbfeeb05e3905e45409..42dd02b6f687b570f4ed9e8395f612d68a36e5fb 100644 --- a/app/views/anime/detail.php +++ b/app/views/anime/detail.php @@ -92,16 +92,22 @@ $list = $al->getAnimeListByAnimeClientID($id, $client_id) <center> <?php - if (!$list){ + if (!$al->getAnimeListByAnimeClientID($id, $client_id)){ echo" - <button class='add-list-btn' - data-anime-id='$anime[anime_id]' - data-client-id='$client_id'> - Add to My List - </button> + <form action='/api/anime_list/add.php' method='post'> + <input type='hidden' id='anime_id' name='anime_id' value='$id'> + <input type='hidden' id='client_id' name='client_id' value='$client_id'> + <button type='submit' class='add-list-btn' > Add to My List </button> + </form'> "; } else { - echo"<button class='remove-list-btn' data-list-id=$list[list_id]>Remove from My List</button>"; + echo" + <form action='/api/anime_list/delete.php' method='post'> + <input type='hidden' id='anime_id' name='anime_id' value='$id'> + <input type='hidden' id='client_id' name='client_id' value='$client_id'> + <button type='submit' class='remove-list-btn' > Remove from My List </button> + </form'> + "; } ?> </center> diff --git a/app/views/anime/index.php b/app/views/anime/index.php index 7ac5c6d2c81c41488723aff1bfa602bcf8d46dd4..7531ce7ddb0646f4079ff9bfaf0066f63a17dc9a 100644 --- a/app/views/anime/index.php +++ b/app/views/anime/index.php @@ -4,9 +4,77 @@ require_once(dirname(__DIR__,2).'/define.php'); require_once(BASE_DIR.'/views/includes/header.php'); require_once(BASE_DIR.'/models/Anime.php'); require_once(BASE_DIR.'/models/Genre.php'); +require_once(BASE_DIR.'/models/Studio.php'); $a = new Anime(); +$s = new Studio(); $g = new Genre(); +$path = $data['path']; + +$genreFilter = null; +$typeFilter = null; +$statusFilter = null; +$ratingFilter = null; +$studioFilter = null; +$sortColumn = null; +$desc = null; +$page = 1; +$limitPerPage = 12; + +$filter = explode('&', $path); +foreach($filter as $f){ + $temp = explode('=', $f); + if ($temp[0] == 'genre'){ + $genreFilter = $temp[1]; + } + else if ($temp[0] == 'type'){ + $typeFilter = $temp[1]; + } + else if ($temp[0] == 'status'){ + $statusFilter = $temp[1]; + } + else if ($temp[0] == 'rating'){ + $ratingFilter = $temp[1]; + } + else if ($temp[0] == 'studio'){ + $studioFilter = $temp[1]; + } + else if ($temp[0] == 'page'){ + $page = (int) $temp[1]; + } + else if ($temp[0] == 'sort'){ + $sortArr = explode('.', $temp[1]); + $sortColumn = $sortArr[0]; + $desc = $sortArr[1] == 'desc' ? true : false; + } +} + + +$animes = $a->getAllAnimeWithFilter( + $genreFilter, + $typeFilter, + $statusFilter, + $ratingFilter, + $studioFilter, + $sortColumn, + $desc, + $limitPerPage, + ($page-1) * $limitPerPage +); + +$totalAnime = +count($a->getAllAnimeWithFilter( + $genreFilter, + $typeFilter, + $statusFilter, + $ratingFilter, + $studioFilter, + $sortColumn, + $desc, + null, + null +)); +$maxPage = ceil($totalAnime/$limitPerPage); ?> @@ -17,26 +85,99 @@ $g = new Genre(); <link rel="stylesheet" href="../../public/style/global.css"> <link rel='stylesheet' href="../../public/style/anime.css"> <script src='/public/handler/navbar.js'></script> + <script src='/public/handler/anime.js'></script> </head> - <body> <div class="filter-flex"> - <?php - $genres = $g->getAllGenre(); - foreach($genres as $genre){ - echo " - <div class='genre-button'> - $genre[name] - </div> - "; - } - ?> + <form action='/api/anime/filter.php' method='post' class='filter-part'> + <div class="filter-block"> + <label class='filter-label' for='filter-genre'>Genre </label> + <select class='filter-select' id='filter-genre' name='filter-genre' placeholder='Genre'> + <?php + $genres = $g->getAllGenre(); + echo "<option value='Any'> Any </option>"; + foreach($genres as $genre){ + echo " + <option value=$genre[name]> $genre[name] </option> + "; + } + ?> + </select> + </div> + + <div class="filter-block"> + <label class='filter-label' for='filter-type'>Type </label> + <select class='filter-select' id='filter-type' name='filter-type' placeholder='Type'> + <option value='Any'> Any </option> + <option value="TV">TV</option> + <option value="MOVIE">Movie</option> + <option value="OVA">OVA</option> + </select> + </div> + + <div class="filter-block"> + <label class='filter-label' for='filter-status'>Status </label> + <select class='filter-select' id='filter-status' name='filter-status' placeholder='Status'> + <option value='Any'> Any </option> + <option value="ON-GOING">On Going</option> + <option value="COMPLETED">Completed</option> + <option value="HIATUS">Hiatus</option> + <option value="UPCOMING">Upcoming</option> + </select> + </div> + + <div class="filter-block"> + <label class='filter-label' for='filter-rating'>Rating </label> + <select class='filter-select' id='filter-rating' name='filter-rating' placeholder='Rating'> + <option value='Any'> Any </option> + <option value="G">G</option> + <option value="PG-13">PG-13</option> + <option value="R(17+)">R(17+)</option> + <option value="Rx">Rx</option> + </select> + </div> + + <div class="filter-block"> + <label class='filter-label' for='filter-studio'>Studio </label> + <select class='filter-select' id='filter-studio' name='filter-studio' placeholder='Studio'> + <?php + $studios = $s->getAllStudio(); + echo "<option value='Any'> Any </option>"; + // Special for studio, use Studio ID + foreach($studios as $studio){ + echo " + <option value=$studio[studio_id]> $studio[name] </option> + "; + } + ?> + </select> + </div> + + <div class="filter-block"> + <label class='filter-label' for='filter-sort'>Sort </label> + <select class='filter-select' id='filter-sort' name='filter-sort' placeholder='Sort'> + <option value='Any'> None </option> + <option value="title.asc">Title Ascending</option> + <option value="title.desc">Title Descending</option> + <option value="score.asc">Score Ascending</option> + <option value="score.desc">Score Descending</option> + <option value="release_date.asc">Release Date Ascending</option> + <option value="release_date.desc">Release Date Descending</option> + </select> + </div> + + <input class='filter-submit-btn' type='submit' value='Submit Filter'> + </form> + <div class='search-part'> + <div class='search-bar'> + <input class='search-bar' id='search-bar' type='text' onkeyup='handleSearch()' placeholder='Search...'> + </div> + </div> </div> <div class="flex-wrap"> <?php - $animes = $a->getAllAnime(); foreach($animes as $anime){ $year = date('Y', strtotime($anime['release_date'])) ?? ''; $month = date('M', strtotime($anime['release_date'])) ?? ''; @@ -62,6 +203,36 @@ $g = new Genre(); } ?> </div> + <div class='button-container'> + <?php + array_pop($filter); + $prevPage = $page == 1? 'page=1' : 'page='.$page-1; + $nextPage = $page == $maxPage ? 'page='.$maxPage : 'page='.$page+1; + $new_url = '/?anime/'; + $first = true; + foreach($filter as $f){ + if ($first){ + $first = false; + $new_url = $new_url.$f; + } else { + $new_url = $new_url.'&'.$f; + } + } + $prev_url = $first ? $new_url.$prevPage : $new_url.'&'.$prevPage; + $next_url = $first ? $new_url.$nextPage : $new_url.'&'.$nextPage; + echo " + <a href='$prev_url'> + <img class='page-arrow' id='left-arrow' src='/public/img/left_arrow_icon.png' alt='Left Arrow' /> + </a> + <div class='page-number'> ".$page." / ".$maxPage." </div> + <a href='$next_url'> + <img class='page-arrow' id='right-arrow' src='/public/img/right_arrow_icon.png' alt='Right Arrow' /> + </a> + "; + + ?> + </div> + </body> <?php diff --git a/app/views/includes/header.php b/app/views/includes/header.php index 605ba7de0d44b6434178c1c7c1eed6b9e7535549..32139cfc50706e6b8baf5fdfa9d6ec69bfa9ec46 100644 --- a/app/views/includes/header.php +++ b/app/views/includes/header.php @@ -17,9 +17,9 @@ $c = new Client(); <div class='navbar'> <ul class='nav-links'> <li><a href='/'>Home</a></li> - <li><a href='/?anime'>Anime</a></li> - <li><a href='/?studio'>Studio</a></li> - <li><a href='/?trailer'>Trailer</a></li> + <li><a href='/?anime/page=1'>Anime</a></li> + <li><a href='/?studio/page=1'>Studio</a></li> + <li><a href='/?trailer/page=1'>Trailer</a></li> </ul> <?php @@ -95,6 +95,3 @@ $c = new Client(); </div> </div> -<!-- <div class='search-bar'> - <input type='text' placeholder='Search Anime/Genre/Studi/Trailer'> -</div> --> \ No newline at end of file diff --git a/app/views/signup/index.php b/app/views/signup/index.php index bf7a4fd910dd3d4aba84de1954403fe2ebf968db..06b8ac3a69196450cc1ebc93387fe901d21585e7 100644 --- a/app/views/signup/index.php +++ b/app/views/signup/index.php @@ -23,15 +23,17 @@ require_once(dirname(__DIR__,2).'/define.php'); <form action="/api/auth/signup.php" method="post" class='form'> <div class="form-group"> <label class='form-label' for="email">E-mail</label> - <input - class="form-input" - type="email" - id="email" - name="email" - placeholder="Enter your email." - onkeyup="checkEmail()" + <input + class='form-input' + type='email' + id='email' + name='email' + placeholder='Enter your email.' + onkeyup='checkEmail()' required /> + + <div id="email-errmsg" class='form-err-message'></div> </div> diff --git a/app/views/studio/index.php b/app/views/studio/index.php index 730b3769679c928a9c357e6b0691deedb1de3cdb..736f34a5658c346a97fb15cf52c02ddee62f6d9a 100644 --- a/app/views/studio/index.php +++ b/app/views/studio/index.php @@ -7,6 +7,16 @@ require_once(BASE_DIR.'/models/Anime.php'); $s = new Studio(); $a = new Anime(); + +$page = 1; +$limitPerPage = 12; + +$path = $data['path']; +$temp = explode('=', $path); +$page = $temp[1]; + +$count = count($s->getAllStudio()); +$maxPage = ceil($count/$limitPerPage); ?> <!DOCTYPE html> @@ -23,7 +33,7 @@ $a = new Anime(); <body> <div class="flex-wrap"> <?php - $studios = $s->getAllStudio(); + $studios = $s->getAllStudioLimit($limitPerPage, ($page-1)*$limitPerPage); foreach($studios as $studio){ $anime_count = count($a->getAllAnimeByStudioID($studio['studio_id'])); $year = $studio['established_date'] ?? 'No information'; @@ -46,6 +56,26 @@ $a = new Anime(); } ?> </div> + + <div class='button-container'> + <?php + $prevPage = $page == 1? 'page=1' : 'page='.$page-1; + $nextPage = $page == $maxPage ? 'page='.$maxPage : 'page='.$page+1; + $new_url = '/?studio/'; + $prev_url = $new_url.$prevPage; + $next_url = $new_url.$nextPage; + echo " + <a href='$prev_url'> + <img class='page-arrow' id='left-arrow' src='/public/img/left_arrow_icon.png' alt='Left Arrow' /> + </a> + <div class='page-number'> ".$page." / ".$maxPage." </div> + <a href='$next_url'> + <img class='page-arrow' id='right-arrow' src='/public/img/right_arrow_icon.png' alt='Right Arrow' /> + </a> + "; + + ?> + </div> </body> </html> diff --git a/app/views/trailer/index.php b/app/views/trailer/index.php index f103d276e51c253e78d8486357d280e532966ffc..f6b2fef52cce62baa178cedfca8b99eecc37e434 100644 --- a/app/views/trailer/index.php +++ b/app/views/trailer/index.php @@ -5,6 +5,13 @@ require_once(BASE_DIR.'/views/includes/header.php'); require_once(BASE_DIR.'/models/Anime.php'); $a = new Anime(); +$limitPerPage = 12; +$path = $data['path']; +$temp = explode('=', $path); +$page = $temp[1]; + +$count = count($a->getAllAnimeWithTrailer()); +$maxPage = ceil($count/$limitPerPage); ?> <!DOCTYPE html> @@ -29,7 +36,7 @@ $a = new Anime(); <div class="flex-wrap"> <?php - $animes = $a->getAllAnimeWithTrailer(); + $animes = $a->getAllAnimeWithTrailerLimit($limitPerPage, ($page-1)*$limitPerPage); foreach($animes as $anime){ $year = date('Y', strtotime($anime['release_date'])) ?? ''; $image = $anime['image'] ?? '../../public/img/placeholder.jpg'; @@ -50,6 +57,25 @@ $a = new Anime(); ?> </div> + <div class='button-container'> + <?php + $prevPage = $page == 1? 'page=1' : 'page='.$page-1; + $nextPage = $page == $maxPage ? 'page='.$maxPage : 'page='.$page+1; + $new_url = '/?trailer/'; + $prev_url = $new_url.$prevPage; + $next_url = $new_url.$nextPage; + echo " + <a href='$prev_url'> + <img class='page-arrow' id='left-arrow' src='/public/img/left_arrow_icon.png' alt='Left Arrow' /> + </a> + <div class='page-number'> ".$page." / ".$maxPage." </div> + <a href='$next_url'> + <img class='page-arrow' id='right-arrow' src='/public/img/right_arrow_icon.png' alt='Right Arrow' /> + </a> + "; + + ?> + </div> </body> </html>