From ae521c04641d8057b6337c36e2bfcd985b2316f4 Mon Sep 17 00:00:00 2001
From: bewe <93899302+bernarduswillson@users.noreply.github.com>
Date: Sat, 4 Nov 2023 18:09:09 +0700
Subject: [PATCH] feat: add exercise page

---
 app/controllers/Exercise.php |  15 +++
 app/views/exercise/index.php |  33 ++++++
 app/views/header/index.php   |   1 +
 app/views/navbar/index.php   |   4 +-
 public/css/exercise.css      | 215 +++++++++++++++++++++++++++++++++++
 public/js/exercise.js        |  32 ++++++
 6 files changed, 298 insertions(+), 2 deletions(-)
 create mode 100644 app/controllers/Exercise.php
 create mode 100644 app/views/exercise/index.php
 create mode 100644 public/css/exercise.css
 create mode 100644 public/js/exercise.js

diff --git a/app/controllers/Exercise.php b/app/controllers/Exercise.php
new file mode 100644
index 0000000..cfa5b25
--- /dev/null
+++ b/app/controllers/Exercise.php
@@ -0,0 +1,15 @@
+<?php
+
+class Exercise extends Controller {
+  public function index() {
+    $this->validateSession();
+
+    $data["pageTitle"] = "Test your knowledge!";
+    $data["languages"] = $this->model("LanguageModel")->getAllLanguage();
+
+    $this->view('header/index', $data);
+    $this->view('navbar/index');
+    $this->view('exercise/index', $data);
+    $this->view('footer/index');
+  }
+}
\ No newline at end of file
diff --git a/app/views/exercise/index.php b/app/views/exercise/index.php
new file mode 100644
index 0000000..03ab6eb
--- /dev/null
+++ b/app/views/exercise/index.php
@@ -0,0 +1,33 @@
+<?php
+?>
+
+<div class="exercise">
+  <div class="container exercise-container">
+    <h1 class="font-bold text-xl text-blue-purple-gradient">
+      Exercises
+    </h1>
+
+    <form id="search-filter-sort-form" action="" method="GET">
+      <div class="input-container">
+        <div class="filter-sort">
+          <select name="language" id="language-input" class="text-sm font-reg text-black">
+            <option value="" <?php echo empty($data["languages"]) ? "selected" : ""; ?>>All languages</option>
+            <?php foreach ($data["languages"] as $language): ?>
+              <option value="<?= $language["language_id"] ?>">
+                <?= $language["language_name"] ?>
+              </option>
+            <?php endforeach; ?>
+          </select>
+        </div>
+      </div>
+
+      <div class="card-container" id="exercise-container">
+      </div>
+    </form>
+  </div>
+</div>
+<script>
+  const languages = <?= json_encode($data["languages"]) ?>;
+</script>
+<!-- <script src="/public/js/search-filter-sort.js"></script> -->
+<script src="/public/js/exercise.js"></script>
\ No newline at end of file
diff --git a/app/views/header/index.php b/app/views/header/index.php
index e3745a2..c29fc91 100644
--- a/app/views/header/index.php
+++ b/app/views/header/index.php
@@ -28,5 +28,6 @@
     <link rel="stylesheet" href="/public/css/modal.css">
     <link rel="stylesheet" href="/public/css/video.css">
     <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/exercise.css">
   </head>
   <body>
\ No newline at end of file
diff --git a/app/views/navbar/index.php b/app/views/navbar/index.php
index f62751e..68277f0 100644
--- a/app/views/navbar/index.php
+++ b/app/views/navbar/index.php
@@ -35,8 +35,8 @@ $profile_pic = isset($_SESSION['profile_pic']) ? $_SESSION['profile_pic'] : '/pu
 
             <ul class="nav-menu">
                 <li><a href="<?php echo $username ? '/learn' : '/login'; ?>" class="text-sm text-black">Learn</a></li>
-                <li><a href="/#" class="text-sm text-black">Articles</a></li>
-                <li><a href="/#" class="text-sm text-black">Bootcamp</a></li>
+                <li><a href="/exercise" class="text-sm text-black">Exercise</a></li>
+                <li><a href="/merchandise" class="text-sm text-black">Merchandise</a></li>
             </ul>
         </div>
 
diff --git a/public/css/exercise.css b/public/css/exercise.css
new file mode 100644
index 0000000..67b3af5
--- /dev/null
+++ b/public/css/exercise.css
@@ -0,0 +1,215 @@
+/* ===#===#===#===#===#=== Mobile ===#===#===#===#===#=== */
+
+.exercise {
+    width: 100%;
+    padding-top: 120px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding-bottom: 60px;
+    min-height: 100vh;
+  } 
+  
+  .exercise .exercise-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 50px;
+  }
+  
+  .exercise .exercise-container #search-filter-sort-form {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 50px;
+    width: 100%;
+  }
+  
+  .exercise .exercise-container h1 {
+    text-align: center;
+  }
+  
+  /* === SORT === */
+  
+  .exercise .exercise-container .input-container .filter-sort .sort-container {
+    padding: 10px 14px;
+    border-radius: 50px;
+    position: relative;
+    cursor: pointer;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    user-select: none;
+    border: 1px solid var(--grey);
+    color: var(--black);
+  }
+  
+  .exercise .exercise-container .input-container .filter-sort .sort-container.active {
+    background-color: var(--orange);
+    border: 1px solid var(--orange);
+    color: var(--white);
+  }
+  
+  .exercise .exercise-container .input-container .filter-sort .sort-container input {
+    position: absolute;
+    opacity: 0%;
+    cursor: pointer;
+    height: 0;
+    width: 0;
+  }
+  
+  /* === EXERCISE CARD === */
+  
+  .exercise .exercise-container .card-container {
+    display: flex;
+    max-width: 600px;
+    flex-direction: column;
+    align-items: center;
+    gap: 10px;
+    width: 100%;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card {
+    border: 2px solid var(--orange);
+    padding: 10px 16px 16px 16px;
+    width: 100%;
+    border-radius: 10px;
+    background-color: var(--white);
+    cursor: pointer;
+    transition: all 0.15s ease-in-out;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card:hover {
+    background-color: #F5F5F5;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active {
+    background-color: var(--orange);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head {
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head .content {
+    display: flex;
+    flex-direction: column;
+    gap: -5px;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head .content h2 {
+    color: var(--orange);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head .content span {
+    color: var(--grey);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .exercise-head .content h2,
+  .exercise .exercise-container .card-container .exercise-card.active .exercise-head .content span {
+    color: var(--white);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head .check-icon {
+    display: inline;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card .exercise-head .white-check-icon {
+    display: none;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .exercise-head .check-icon {
+    display: none;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .exercise-head .white-check-icon {
+    display: inline;
+  }
+  
+  /* === VIDEO CARD === */
+  
+  .exercise .exercise-container .card-container .exercise-card .video-card-container {
+    display: none;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 10px;
+    width: 100%;
+    margin-top: 20px;
+    cursor: default;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card {
+    padding: 10px 16px;
+    width: 100%;
+    border-radius: 10px;
+    background-color: var(--white);
+  
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card .content {
+    display: flex;
+    flex-direction: column;
+    gap: -5px;
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card .content h3 {
+    color: var(--orange);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card .content span {
+    color: var(--grey);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card .watch-btn {
+    padding: 8px 16px;
+    border: 2px solid var(--orange);
+    background-color: var(--white);
+    border-radius: 50px;
+    color: var(--orange);
+  }
+  
+  .exercise .exercise-container .card-container .exercise-card.active .video-card-container .video-card .watch-btn:hover {
+    background-color: var(--orange);
+    color: var(--white);
+  }
+  
+  /* ===#===#===#===#===#=== Laptop ===#===#===#===#===#=== */
+  
+  @media (min-width: 1024px) {
+    
+    .exercise {
+      padding-top: 180px;
+      padding-bottom: 120px;
+    }
+    
+    .exercise .exercise-container {
+      gap: 50px;
+    }
+  
+    .exercise .exercise-container #search-filter-sort-form {
+      gap: 50px;
+    }
+  }
+  
+  /* ===#===#===#===#===#=== Desktop ===#===#===#===#===#=== */
+  
+  @media (min-width: 1440px) {
+  
+    .exercise .exercise-container .input-container .search-bar {
+      max-width: 800px;
+    }
+  
+    .exercise .exercise-container .card-container {
+      max-width: 1000px;
+    }
+    
+  }
\ No newline at end of file
diff --git a/public/js/exercise.js b/public/js/exercise.js
new file mode 100644
index 0000000..94c2274
--- /dev/null
+++ b/public/js/exercise.js
@@ -0,0 +1,32 @@
+fetch('http://localhost:5000/exercise')
+  .then(response => response.json())
+  .then(data => {
+    const exerciseContainer = document.getElementById('exercise-container');
+
+    // Process the data and update the HTML content
+    data.result.forEach(exercise => {
+      const exerciseCard = document.createElement('div');
+      exerciseCard.classList.add('exercise-card');
+
+      for (let i = 0; i < languages.length; i++) {
+        if (languages[i].language_id === exercise.language_id) {
+          language = languages[i].language_name;
+          break;
+        }
+      }
+
+      exerciseCard.innerHTML = `
+        <div class="exercise-head">
+          <div class="content">
+            <h2 class="font-bold text-md">${exercise.exe_name}</h2>
+            <span class="font-reg text-xs">${language} &#9679; ${exercise.difficulty} &#9679; ${exercise.category}</span>
+          </div>
+        </div>
+      `;
+
+      exerciseContainer.appendChild(exerciseCard);
+    });
+  })
+  .catch(error => {
+    console.error('Error:', error);
+  });
-- 
GitLab