From 1497ee48777b35f96598c88b598b5e4bd501b754 Mon Sep 17 00:00:00 2001 From: afnanramadhan <13521011@std.stei.itb.ac.id> Date: Fri, 17 Nov 2023 00:14:07 +0700 Subject: [PATCH] feat: add content --- app/controllers/content.php | 8 + app/core/app.php | 5 +- app/views/content/index.php | 40 +++++ app/views/navbar/index.php | 4 + public/css/content.css | 186 ++++++++++++++++++++ public/css/navbar.css | 26 +++ public/js/content.js | 271 +++++++++++++++++++++++++++++ server/controller/auth/Content.php | 40 +++++ 8 files changed, 578 insertions(+), 2 deletions(-) create mode 100644 app/controllers/content.php create mode 100644 app/views/content/index.php create mode 100644 public/css/content.css create mode 100644 public/js/content.js create mode 100644 server/controller/auth/Content.php diff --git a/app/controllers/content.php b/app/controllers/content.php new file mode 100644 index 0000000..25898cc --- /dev/null +++ b/app/controllers/content.php @@ -0,0 +1,8 @@ +<?php + +class Content extends Controller { + public function index() { + $this->view('navbar/index'); + $this->view('content/index'); + } +} \ No newline at end of file diff --git a/app/core/app.php b/app/core/app.php index a061b2c..15b5065 100644 --- a/app/core/app.php +++ b/app/core/app.php @@ -16,8 +16,9 @@ class App { } else if ($url[0] == '') { $this->controller = 'home'; - } - else { + }else if ($url[0] == 'ontent') { + $this->controller = 'content'; + }else { $this->controller = 'error404'; } // else { diff --git a/app/views/content/index.php b/app/views/content/index.php new file mode 100644 index 0000000..b4603cd --- /dev/null +++ b/app/views/content/index.php @@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link rel="stylesheet" href="../../../public/css/content.css"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"> + <script defer src="../../../public/js/content.js"></script> + <script>window.onload = function() {showAll();};</script> + <title>NutriCraft</title> +</head> +<body> + <div> + <div class="content"> + <h1>NutriFacts</h1> + <div class="searchsort"> + <div class="searchcontainer"> + <i class="fas fa-search"></i> + <input class="searchinput" id="searchinput" type="text" placeholder="Search" onkeyup=searchDebounce()> + </div> + <div class="sortcontainer"> + <img src="../../../assets/sort.png" alt=""> + <select name="sortby" id="pet-select" onclick=Search()> + <option value="Alphabet" class="alpha">Alphabet</option> + <option value="Newest">Newest</option> + <option value="Oldest">Oldest</option> + </select> + </div> + </div> + <div id="isicontent" class="content"></div> + <div id="pagination" class="pagination"> + <button class="prev" onclick=prevPage()>«</button> + <div id="numberpage" class="buttons"> + </div> + + <button class="next" onclick=nextPage() >»</button> + </div> + </div> +</body> +</html> \ No newline at end of file diff --git a/app/views/navbar/index.php b/app/views/navbar/index.php index 5b40cc1..a8d48c1 100644 --- a/app/views/navbar/index.php +++ b/app/views/navbar/index.php @@ -22,6 +22,9 @@ <a href="/fact"> <button type="button" class="fact">Fact</button> </a> + <a href="/content"> + <button type="button" class="contentnav">Content</button> + </a> </div> <div id="login"> <?php @@ -73,6 +76,7 @@ if (isset($_COOKIE['user'])) { <a href="/home">Home</a> <a href="/meals">Meals</a> <a href="/fact">Fact</a> + <a href="/content">Content</a> </div> </div> </body> diff --git a/public/css/content.css b/public/css/content.css new file mode 100644 index 0000000..c5d3294 --- /dev/null +++ b/public/css/content.css @@ -0,0 +1,186 @@ +@import url('https://fonts.googleapis.com/css2?family=Nunito&display=swap'); + +*{ + font-family: 'Nunito', sans-serif; +} + +.content { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; +} + +.searchsort { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 20px; + margin-bottom: 20px; +} + +.searchsort input { + border: none; + outline: none; +} + +.searchsort div:hover, .searchsort div:focus-within { + border: 1px solid #288990; + transform: scale(1.001); /* Slightly scale up on hover */ + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); + +} + +.searchcontainer { + border: 1px solid #000000; + border-radius: 20px; + padding: 5px; + width: 40vw; +} + +.searchcontainer input { + width: 80%; + padding-left: 5px; +} + + +.sortcontainer { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + border: 1px solid #000000; + border-radius: 20px; + padding: 5px; +} + +.sortcontainer img { + width: 20px; + height: 20px; +} + +.sortcontainer select { + border: none; + outline: none; + background-color: transparent; +} + + +.video-card { + border: 1px solid #EF4800; + border-radius: 20px; + margin: 10px; + width: 60%; + overflow: hidden; +} + +.video-card:hover { + border: 1px solid #288990; + transform: scale(1.001); /* Slightly scale up on hover */ + box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); +} + +.cardcontent { + display: flex; + flex-direction: row; + background-color: #FFFFFF; + cursor: pointer; + gap: 20px; + /* border-bottom: 1px solid #EF4800; */ +} + +.cardcontent img { + width: 20%; + height: 10%; + border-bottom-left-radius: 0; + /* border-top-right-radius: 20px; */ + border-bottom-right-radius: 20px; +} + +.cardcontent h3{ + margin-top: 28px; + margin-bottom: 0; + font-size: 24px +} + +.cardcontent p { + margin-top: 5px; +} + +.video-content { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + max-height: 0; + overflow: hidden; + transition: max-height 0.3s ease-out; + +} + +.video-content video { + width: 95%; + height: 30vw; + /* margin: 23px; */ +} + +.pagination { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + /* gap: 10px; */ + margin-top: 20px; + margin-bottom: 50px; +} + +.pagination button { + border: 1px solid #EF4800; + background-color: transparent; + color: #EF4800; + width: 40px; + height: 40px; + border-radius: 10px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: background-color 0.3s ease, color 0.3s ease; +} + +.pagination button:hover { + background-color: #EF4800; + color: #FFFFFF; + transition: background-color 0.3s ease, color 0.3s ease; +} + +.pagination button:focus { + outline: none; +} + +.page{ + gap: 10px; + margin-left: 5px; + margin-right: 5px; +} + +.next{ + margin-left: 5px; +} + +.prev{ + margin-right: 5px; +} + + #selected { + background-color: #EF4800; + color: #FFFFFF; + transition: background-color 0.3s ease, color 0.3s ease; +} + +.buttons button:hover { + /* back color brigther orange than selected */ + background-color: #FF6B00; + color: #FFFFFF; + transition: background-color 0.3s ease, color 0.3s ease; +} \ No newline at end of file diff --git a/public/css/navbar.css b/public/css/navbar.css index ef89cb7..3cf17b5 100644 --- a/public/css/navbar.css +++ b/public/css/navbar.css @@ -128,6 +128,32 @@ body { } +.contentnav{ + /* transparent button */ + background-color: transparent; + border: none; + color: #000000; + text-align: center; + text-decoration: none; + font-size: 20px; + font-weight: bold; + cursor: pointer; + transform: scale(1); /* Default scale */ + transition: transform 0.3s; + /* animation underline on hover home */ + text-decoration: none; + text-decoration-color: transparent; + text-decoration-thickness: 2px; + text-underline-offset: 2px; + text-decoration-skip-ink: none; +} + +/* animation underline on hover home */ +.contentnav:hover{ + transform: scale(1.2); /* Increased scale */ + +} + .login{ background-color: #EF4800; border: none; diff --git a/public/js/content.js b/public/js/content.js new file mode 100644 index 0000000..6c68d33 --- /dev/null +++ b/public/js/content.js @@ -0,0 +1,271 @@ + +function toggleVideo(card) { + var content = card.querySelector('.video-content'); // Use card parameter to find .video-content within the clicked card + // console.log(content) + if (content && content.style.maxHeight) { // Check if content is not null + content.style.maxHeight = null; + } else if (content) { // Check if content is not null + content.style.maxHeight = "50vw"; + } +} + +let Page = 1; +let TotalPage; + +// Add a click event listener to a parent container (e.g., isicontent) +document.getElementById("isicontent").addEventListener("click", function(event) { + const target = event.target; + + // Check if the clicked element has the class .video-card + if (target.classList.contains("video-card")) { + toggleVideo(target); + } +}); + + +function capitalizeWords(str) { + return str.split(' ').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' '); + } + + + // masi salah +const pagination = () => { + const pageNumber = "pageNumber"; + const search = document.getElementById('searchinput').value; + const xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4){ + let response = this.response; + const startIndex = response.indexOf('['); + const jsonStr = response.substring(startIndex); + const jsonObject = JSON.parse(jsonStr); + + const numberpage = document.getElementById('numberpage'); + TotalPage=Math.ceil(jsonObject.length / 2); + let html = ""; + for (let i = 1; i <= Math.ceil(jsonObject.length / 2); i++) { + if(i == 1){ + html += `<button type='button' class="page" value=${i} id='selected' onclick='selectPage(); getPage(${i});' ">${i}</button>`; + }else{ + html += `<button type='button' class="page" value=${i} onclick='selectPage(); getPage(${i});' ">${i}</button>`; + } + } + numberpage.innerHTML = html; + } + }; + xhttp.open('GET', `../../server/controller/auth/Content.php?pageNumber=${pageNumber}&search=${search}`, true); + xhttp.send(); +} + + +// pagination(); +const Search = () => { + const search = capitalizeWords(document.getElementById('searchinput').value); + const select = document.getElementById('pet-select').value; + xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4){ + + let response = this.response; + const startIndex = response.indexOf('['); + const jsonStr = response.substring(startIndex); + const jsonObject = JSON.parse(jsonStr); + + // console.log(jsonStr); + + + const parentElement = document.getElementById("isicontent"); + + let html = ""; + for (let i = 0; i < jsonObject.length; i++) { + const content = jsonObject[i]; + html += ` + <div class="video-card" onclick="toggleVideo(this)"> + <div class="cardcontent"> + <img src="${content.path_photo}" alt=""> + <div class="card-title"> + <h3>${content.title}</h3> + <p>${content.highlight}</p> + </div> + </div> + <div class="video-content"> + <video src="${content.path_file}" controls></video> + </div> + </div> + `; + } + + parentElement.innerHTML = html; + } + + + pagination(); + }; + xhttp.open('GET', `../../server/controller/auth/Content.php?search=${search}&select=${select}&page=${Page}`, true); + xhttp.send(JSON.stringify({search: search, select: select})); + +} + +const showAll = () => { + const show = "all"; + const select = document.getElementById('pet-select').value; + // console.log(Page); + xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4){ + let response = this.response; + const startIndex = response.indexOf('['); + const jsonStr = response.substring(startIndex); + const jsonObject = JSON.parse(jsonStr); + // console.log(jsonStr); + + + const parentElement = document.getElementById("isicontent"); + let html = ""; + for (let i = 0; i < jsonObject.length; i++) { + const content = jsonObject[i]; + html += ` + <div class="video-card" onclick="toggleVideo(this)"> + <div class="cardcontent"> + <img src="${content.path_photo}" alt=""> + <div class="card-title"> + <h2>${content.title}</h2> + <p>${content.highlight}</p> + </div> + </div> + <div class="video-content"> + <video src="${content.path_file}" controls></video> + </div> + </div> + `; + } + {/* <div class="video-content"> + <iframe src="https://www.youtube.com/embed/l970HoJ7g7o?si=61k4a2ioQf4YfpFF" frameborder="0" allowfullscreen></iframe> + </div> */} + parentElement.innerHTML = html; + pagination(); + } + }; + xhttp.open('GET', `../../server/controller/auth/Content.php?show=${show}&Select=${select}&page=${Page}`, true); + xhttp.send(); + +} + +const selectpagination = () => { + const show = "all"; + const select = document.getElementById('pet-select').value; + // console.log(Page); + xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState === 4){ + let response = this.response; + const startIndex = response.indexOf('['); + const jsonStr = response.substring(startIndex); + const jsonObject = JSON.parse(jsonStr); + // console.log(jsonStr); + + + const parentElement = document.getElementById("isicontent"); + let html = ""; + for (let i = 0; i < jsonObject.length; i++) { + const content = jsonObject[i]; + html += ` + <div class="video-card" onclick="toggleVideo(this)"> + <div class="cardcontent"> + <img src="${content.path_photo}" alt=""> + <div class="card-title"> + <h3>${content.title}</h3> + <p>${content.highlight}</p> + </div> + </div> + <div class="video-content"> + <video src="${content.path_file}" controls></video> + </div> + </div> + `; + } + {/* <div class="video-content"> + <iframe src="https://www.youtube.com/embed/l970HoJ7g7o?si=61k4a2ioQf4YfpFF" frameborder="0" allowfullscreen></iframe> + </div> */} + parentElement.innerHTML = html; + } + }; + xhttp.open('GET', `../../server/controller/auth/Content.php?show=${show}&Select=${select}&page=${Page}`, true); + xhttp.send(); + +} + + +const prevPage = () =>{ + const search = document.getElementById('searchinput').value; + if(Page>1){ + Page-=1 + if(search==''){ + selectpagination(); + }else{ + Search(); + } + } +} + +const nextPage = () =>{ + const search = document.getElementById('searchinput').value; + if(Page<TotalPage){ + Page+=1 + // console.log(Page); + // console.log("HAI"); + if(search==''){ + showAll(); + }else{ + Search(); + } + } +} + +function getPage(pa){ + Page = pa; + // console.log(Page); +} + + +function debounce(func, timeout = 500){ + let timer; + return (...args) => { + clearTimeout(timer); + timer = setTimeout(() => { func.apply(this, args); }, timeout); + }; +} + +function selectPage (){ + const buttons = document.querySelectorAll('#numberpage button'); + // console.log(buttons); + // Add click event listeners to each button + buttons.forEach(button => { + button.addEventListener('click', () => { + // Remove the 'selected' id from the currently selected button + const currentlySelectedButton = document.querySelector('#selected'); + currentlySelectedButton.removeAttribute('id'); + + // Add the 'selected' id to the clicked button + button.id = 'selected'; + + // Optionally, you can add a CSS class to style the selected button + buttons.forEach(btn => btn.classList.remove('selected')); + button.classList.add('selected'); + }); + }); +} + + +document.getElementById('numberpage').addEventListener('click',()=>{ + const search = document.getElementById('searchinput').value; + if(search==''){ + console.log("HAI"); + selectpagination(); + }else{ + Search(); + } +}) + + +const searchDebounce = debounce(() => Search()); \ No newline at end of file diff --git a/server/controller/auth/Content.php b/server/controller/auth/Content.php new file mode 100644 index 0000000..049fa66 --- /dev/null +++ b/server/controller/auth/Content.php @@ -0,0 +1,40 @@ +<?php + +use data\Content; +require_once('../../handler/data/Content.php'); +require_once('../../db/Database.php'); + +$content = new Content(); + + +if(isset($_GET['select'])){ + $select = $_GET['select']; + $page = $_GET['page']; + $page = ($page-1)*10; + if(isset($_GET['search'])){ + $search = $_GET['search']; + $result = $content->FindByTitle($search, $select, $page); + }else{ + $result = $content->FindAllPaging($select, $page); + } + + echo json_encode($result); +} + +if(isset($_GET['show'])){ + $page = $_GET['page']; + $page = ($page-1)*2; + $select = $_GET['Select']; + $result = $content->FindAllPaging($select, $page); + echo json_encode($result); +} + +if(isset($_GET['pageNumber'])){ + if(isset($_GET['search'])){ + $search = $_GET['search']; + $result = $content->FindAllSearch($search); + }else{ + $result = $content->FindAll($search); + } + echo json_encode($result); +} \ No newline at end of file -- GitLab