From 8fe34f272a235884c65c7700f7f749fdbabe783f Mon Sep 17 00:00:00 2001
From: williamnixon20 <75229742+williamnixon20@users.noreply.github.com>
Date: Fri, 6 Oct 2023 15:59:29 +0700
Subject: [PATCH] tidying up frontend css,logic

---
 public/components/Footer.php            |   5 +
 public/components/Navbar.php            |   4 -
 public/components/Pagination.php        |  47 ++-
 public/css/login.css                    |  66 +++++
 public/css/styles.css                   | 361 +++++++++++++++++-------
 public/images/logo.jpeg                 | Bin 0 -> 4363 bytes
 public/images/placeholder.png           | Bin 0 -> 2181 bytes
 public/js/login.js                      | 129 ++++-----
 public/js/sighting.js                   |  19 +-
 public/view/cats.php                    |  81 +++---
 public/view/home.php                    | 123 ++------
 public/view/login.php                   |  46 +--
 public/view/sighting.php                | 120 ++++----
 public/view/users.php                   |   5 +-
 src/bases/BaseRepository.php            |   4 +-
 src/repositories/SightingRepository.php |  92 +++---
 16 files changed, 654 insertions(+), 448 deletions(-)
 create mode 100644 public/components/Footer.php
 create mode 100644 public/css/login.css
 create mode 100644 public/images/logo.jpeg
 create mode 100644 public/images/placeholder.png

diff --git a/public/components/Footer.php b/public/components/Footer.php
new file mode 100644
index 0000000..7be83cc
--- /dev/null
+++ b/public/components/Footer.php
@@ -0,0 +1,5 @@
+<footer>
+    <p>&copy;
+        <?= date('Y') ?> Kuchenk ITB
+    </p>
+</footer>
\ No newline at end of file
diff --git a/public/components/Navbar.php b/public/components/Navbar.php
index c2c26e9..3e3f0aa 100644
--- a/public/components/Navbar.php
+++ b/public/components/Navbar.php
@@ -4,12 +4,8 @@
         <li><a href="cat">Cats</a></li>
         <li><a href="sighting">Sightings</a></li>
         <?php
-        // Check if the user is logged in (You will need to implement this logic)
         $loggedIn = isset($_SESSION['user_id']);
         $isAdmin = isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'];
-//        echo isset($_SESSION['isAdmin'])===1;
-//        echo ('<script>console.log('.$isAdmin.')</script>')  ;
-//        echo "<li><a>$loggedIn</a></li>";
         if ($isAdmin) {
             echo '<li><a href="user">Manage Users</a></li>';
         }
diff --git a/public/components/Pagination.php b/public/components/Pagination.php
index 12faf5e..958ac59 100644
--- a/public/components/Pagination.php
+++ b/public/components/Pagination.php
@@ -4,7 +4,6 @@
 // 2. Di controller sebelum render page, query total count dari database simpan di variabel $_count.
 // 3. Pastiin di service/repo ada fungsi buat ngurusin order by, limit, dst.
 // For more information, refer to GET /cats di cats controller.
-
 function generatePaginationLinks($currentPage, $totalPages, $queryParams)
 {
     $html = '<div class="pagination">';
@@ -12,12 +11,20 @@ function generatePaginationLinks($currentPage, $totalPages, $queryParams)
     // Build the query string with the existing parameters
     $queryString = http_build_query($queryParams);
 
+    // Calculate the range of visible page links
+    $visiblePages = 2; // You can adjust this number as needed
+
     // Previous button
     if ($currentPage > 1) {
         $html .= '<a href="?pageNo=' . ($currentPage - 1) . '&' . $queryString . '" class="prev-page">Previous</a>';
     }
 
-    for ($i = 1; $i <= $totalPages; $i++) {
+    // Display ellipsis if there are many pages before the current page
+    if ($currentPage > ($visiblePages + 1)) {
+        $html .= '<span class="ellipsis">...</span>';
+    }
+
+    for ($i = max(1, $currentPage - $visiblePages); $i <= min($totalPages, $currentPage + $visiblePages); $i++) {
         if ($i === $currentPage) {
             $html .= '<span class="current-page">' . $i . '</span>';
         } else {
@@ -25,15 +32,49 @@ function generatePaginationLinks($currentPage, $totalPages, $queryParams)
         }
     }
 
+    // Display ellipsis if there are many pages after the current page
+    if ($currentPage < ($totalPages - $visiblePages)) {
+        $html .= '<span class="ellipsis">...</span>';
+    }
+
     // Next button
     if ($currentPage < $totalPages) {
-        $html .= '<a href="?pageNo=' . ($currentPage + 1) . '&&' . $queryString . '" class="next-page">Next</a>';
+        $html .= '<a href="?pageNo=' . ($currentPage + 1) . '&' . $queryString . '" class="next-page">Next</a>';
     }
 
     $html .= '</div>';
     return $html;
 }
 
+// function generatePaginationLinks($currentPage, $totalPages, $queryParams)
+// {
+//     $html = '<div class="pagination">';
+
+//     // Build the query string with the existing parameters
+//     $queryString = http_build_query($queryParams);
+
+//     // Previous button
+//     if ($currentPage > 1) {
+//         $html .= '<a href="?pageNo=' . ($currentPage - 1) . '&' . $queryString . '" class="prev-page">Previous</a>';
+//     }
+
+//     for ($i = 1; $i <= $totalPages; $i++) {
+//         if ($i === $currentPage) {
+//             $html .= '<span class="current-page">' . $i . '</span>';
+//         } else {
+//             $html .= '<a href="?pageNo=' . $i . '&' . $queryString . '">' . $i . '</a>';
+//         }
+//     }
+
+//     // Next button
+//     if ($currentPage < $totalPages) {
+//         $html .= '<a href="?pageNo=' . ($currentPage + 1) . '&&' . $queryString . '" class="next-page">Next</a>';
+//     }
+
+//     $html .= '</div>';
+//     return $html;
+// }
+
 $totalCount = $_count; // Total number of cats
 $pageSize = isset($_GET['pageSize']) ? intval($_GET['pageSize']) : 10; // Number of cats per page
 $totalPages = ceil($totalCount / $pageSize);
diff --git a/public/css/login.css b/public/css/login.css
new file mode 100644
index 0000000..6bf0a0c
--- /dev/null
+++ b/public/css/login.css
@@ -0,0 +1,66 @@
+        body {
+            background-color: #f7f7f7;
+            font-family: Arial, sans-serif;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            height: 100vh;
+            margin: 0;
+        }
+
+        .login-container {
+            background-color: #fff;
+            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+            border-radius: 5px;
+            padding: 70px;
+            margin: 20px;
+            width: 350px;
+        }
+
+        .login-logo {
+            text-align: center;
+            margin-bottom: 20px;
+        }
+
+        .login-logo img {
+            max-width: 150px;
+        }
+
+        .login-title {
+            text-align: center;
+            font-size: 24px;
+            margin-bottom: 20px;
+        }
+
+        .login-form {
+            text-align: center;
+        }
+
+        .login-label {
+            font-size: 16px;
+            display: block;
+            margin-bottom: 5px;
+        }
+
+        .login-input {
+            width: 100%;
+            height: 40px;
+            border: 1px solid #ccc;
+            border-radius: 5px;
+            font-size: 16px;
+        }
+
+        .login-button {
+            background-color: #007bff;
+            color: #fff;
+            padding: 10px 20px;
+            border: none;
+            border-radius: 5px;
+            font-size: 16px;
+            cursor: pointer;
+            transition: background-color 0.3s;
+        }
+
+        .login-button:hover {
+            background-color: #0056b3;
+        }
diff --git a/public/css/styles.css b/public/css/styles.css
index f39b28d..f090cf5 100644
--- a/public/css/styles.css
+++ b/public/css/styles.css
@@ -24,7 +24,7 @@ nav ul li a:hover {
     text-decoration: underline;
 }
 
-/* Logout button styles (customize as needed) */
+/* Logout button styles*/
 .logout-button {
     background-color: #f00;
     color: #fff;
@@ -33,7 +33,7 @@ nav ul li a:hover {
     cursor: pointer;
 }
 
-/* Register and Login link styles (customize as needed) */
+/* Register and Login link styles */
 .register-link,
 .login-link {
     color: #fff;
@@ -41,138 +41,59 @@ nav ul li a:hover {
     margin-right: 10px;
 }
 
-/* Apply styles for the logout button, register, and login links */
-/* styles.css */
 
-/* Style for the cat card container */
-.cat-card, .sighting-card, .user-card {
-    border: 1px solid #ccc;
-    padding: 16px;
-    margin: 16px;
-    background-color: #fff;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-    border-radius: 5px;
-}
 
-/* Style for the cat image */
-.cat-image {
-    max-width: 100%;
-    height: auto;
-}
-
-/* Style for the cat audio player */
 .cat-audio {
     width: 100%;
 }
 
-/* Style for the cat card title */
 .cat-title, .user-card {
     font-size: 24px;
     margin: 8px 0;
 }
 
-/* Style for the cat card details */
+
 .cat-details, .user-card {
     font-size: 16px;
     margin: 8px 0;
 }
 
-/* styles.css */
-
-/* Style for the container that holds the cat cards */
-.cat-cards-container, .sighting-cards-container, .user-cards-container {
-    display: grid;
-    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); /* Responsive grid with minimum 300px width */
-    grid-gap: 16px; /* Spacing between cat cards */
-}
-
-/* Style for each cat card
-.cat-card {
-    border: 1px solid #ccc;
-    padding: 16px;
-    background-color: #fff;
-    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-    border-radius: 5px;
-} */
-
-/* Style for the cat image */
-.cat-image {
-    max-width: 100%;
-    height: auto;
-}
-
-/* Style for the cat audio player */
-.cat-audio {
-    width: 100%;
-}
-
-/* Style for the cat card title */
 .cat-title {
     font-size: 24px;
     margin: 8px 0;
-    color: #333; /* Text color */
-}
-
-/* Style for the cat card details */
-.cat-details {
-    font-size: 16px;
-    margin: 8px 0;
-    color: #777; /* Text color */
+    color: #333;
 }
 
-/* styles.css */
-
-/* ... Previous styles ... */
 
-/* Style for the cat description */
 .cat-description {
     font-size: 14px;
     margin: 8px 0;
-    color: #555; /* Text color */
+    color: #555; 
 }
 
-/* Style for the cat location */
 .cat-location {
     font-size: 14px;
     margin: 8px 0;
-    color: #555; /* Text color */
+    color: #555; 
 }
 
-/* Style for the cat spayed status */
 .cat-spayed {
     font-size: 14px;
     margin: 8px 0;
-    color: #555; /* Text color */
+    color: #555; 
 }
 
-/* Style for the cat added timestamp */
 .cat-added {
     font-size: 14px;
     margin: 8px 0;
-    color: #555; /* Text color */
+    color: #555; 
 }
-/* 
-/* Style for the delete button */
-/* .delete-button {
-    position: absolute;
-    top: 10px;
-    right: 10px;
-    background-color: red;
-    color: white;
-    border: none;
-    border-radius: 50%;
-    padding: 5px 10px;
-    text-align: center;
-    cursor: pointer;
-    text-decoration: none;
-} */
 
-/* Style for each cat card */
+
 .cat-card, .sighting-card, .user-card {
-    position: relative; /* Add relative positioning to the cat card */
+    position: relative; 
     border: 1px solid #ccc;
-    padding: 16px;
-    background-color: #fff;
+    padding: 5px;
     box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
     border-radius: 5px;
 }
@@ -182,7 +103,7 @@ nav ul li a:hover {
     top: 10px;
     right: 10px;
     background-color: red;
-    color: white;
+    color: #ffffff;
     border: none;
     border-radius: 50%;
     padding: 5px 10px;
@@ -191,7 +112,6 @@ nav ul li a:hover {
     text-decoration: none;
 }
 
-/* Style for the Add Cat Button */
 .add-button {
     position: fixed;
     bottom: 20px;
@@ -206,8 +126,6 @@ nav ul li a:hover {
 }
 
 
-/** form**/
-/* Style for form container */
 .modal {
     display: flex;
     align-items: center;
@@ -224,6 +142,7 @@ nav ul li a:hover {
 }
 
 .modal-content {
+    position:fixed;
     background-color: #fff;
     margin: 15% auto;
     padding: 20px;
@@ -245,7 +164,7 @@ nav ul li a:hover {
 
 /* Style for form elements */
 .form-group {
-    margin-bottom: 15px;
+    margin: 10px;
 }
 
 label {
@@ -254,16 +173,17 @@ label {
 
 .form-control {
     width: 100%;
-    padding: 10px;
+    height: 50px;
     border: 1px solid #ccc;
     border-radius: 5px;
     font-size: 16px;
 }
 
-select.form-control {
-    height: 35px;
+.form-control select {
+    height: 50px; 
 }
 
+
 .file-input {
     border: none;
     padding: 0;
@@ -286,7 +206,7 @@ select.form-control {
 }
 
 /* Styling for the edit cat modal */
-#edit-cat-modal {
+.modal {
     display: none;
     position: fixed;
     z-index: 1;
@@ -329,8 +249,7 @@ label {
 input[type="text"],
 textarea,
 select {
-    width: 100%;
-    padding: 10px;
+    padding: 5px;
     border: 1px solid #ccc;
     border-radius: 5px;
 }
@@ -477,3 +396,243 @@ button[type="submit"] {
     margin-right: 5px;
 }
 
+
+
+/** home page **/
+
+  body {
+    font-family: Arial, sans-serif;
+    background-color: #f5f5f5;
+    margin: 0;
+    padding: 0;
+    display: flex;
+    flex-direction: column;
+    min-height: 100vh;
+  }
+
+  header {
+    background-color: #333;
+    color: #fff;
+    padding: 20px 0;
+    text-align: center;
+  }
+
+  h1 {
+    font-size: 36px;
+    margin: 0;
+  }
+
+  .container {
+    max-width: 1200px;
+    margin: 0 auto;
+    padding: 20px;
+    flex: 1;
+  }
+
+  .intro {
+    text-align: center;
+    margin-bottom: 40px;
+  }
+
+  .cta-button {
+    display: inline-block;
+    padding: 15px 30px;
+    background-color: #007BFF;
+    color: #fff;
+    text-decoration: none;
+    border-radius: 5px;
+    font-weight: bold;
+  }
+
+  .cta-button:hover {
+    background-color: #0056b3;
+  }
+
+  .features {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+    gap: 20px;
+  }
+
+  .feature {
+    flex: 1;
+    background-color: #fff;
+    box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
+    border-radius: 5px;
+    text-align: center;
+    padding: 20px;
+    transition: transform 0.2s ease-in-out;
+  }
+
+  .feature h2 {
+    font-size: 24px;
+    margin-bottom: 10px;
+  }
+
+  .feature p {
+    font-size: 16px;
+    color: #555;
+  }
+
+  .feature:hover {
+    transform: translateY(-5px);
+  }
+
+  footer {
+    background-color: #333;
+    color: #fff;
+    text-align: center;
+    padding: 20px 0;
+  }
+
+
+  .feature a {
+    text-decoration: none;
+    color: inherit;
+  }
+
+  .feature a:hover {
+    color: #007BFF;
+  }
+
+  /** Pagination styles **/
+.pagination {
+  text-align: center;
+  margin-top: 20px; 
+  margin-bottom: 20px;
+}
+
+.pagination a {
+  display: inline-block;
+  padding: 5px 10px;
+  margin: 2px;
+  border: 1px solid #ccc;
+  text-decoration: none;
+  color: #333;
+}
+
+.pagination .current-page {
+  font-weight: bold;
+  background-color: #007BFF;
+  color: #fff;
+  padding: 5px 10px;
+  margin: 2px;
+  border: 1px solid #007BFF;
+}
+
+.pagination .ellipsis {
+  margin: 2px;
+  padding: 5px 10px;
+  color: #999;
+}
+
+.pagination a.prev-page,
+.pagination a.next-page {
+  background-color: #007BFF;
+  color: #fff;
+}
+
+.pagination a.prev-page:hover,
+.pagination a.next-page:hover {
+  background-color: #0056b3;
+}
+
+.cat-cards-container, .sighting-cards-container, .user-cards-container {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
+    grid-gap: 16px; 
+    margin: 10px;
+}
+
+/* Cat card styles */
+.cat-card {
+  border: 1px solid #ccc;
+  border-radius: 5px;
+  padding: 10px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  text-align: center;
+  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
+  background-color: #fff;
+}
+
+
+.cat-image-container {
+  margin-bottom: 10px;
+}
+
+.cat-image {
+  width: 350px;
+  height: 350px; 
+  object-fit: cover;
+  border-radius: 10px;
+}
+
+.cat-details {
+  text-align: left;
+  flex-grow: 1;
+  width: 80%;
+}
+
+.cat-title {
+  font-size: 24px;
+  margin: 10px 0;
+  color: #333;
+}
+
+.cat-description {
+  font-size: 16px;
+  color: #555;
+  margin-bottom: 20px;
+}
+
+.cat-metadata {
+  display: flex;
+  flex-direction: column;
+  align-items: flex-start;
+  margin-bottom: 20px;
+}
+
+.cat-metadata-item {
+  margin-bottom: 5px;
+}
+
+.cat-metadata-item strong {
+  font-weight: bold;
+  margin-right: 5px;
+}
+
+.cat-audio {
+  width: 100%; 
+  margin-bottom: 10px;
+}
+
+.cat-audio::-webkit-media-controls-panel {
+  background-color: #f5f5f5; 
+}
+
+.cat-audio::-webkit-media-controls-play-button {
+  color: #007BFF; 
+}
+
+.cat-audio::-webkit-media-controls-volume-slider {
+  width: 80px; 
+}
+
+/* Edit button styles */
+.edit-button {
+  background-color: #007BFF; 
+  color: #fff; 
+  padding: 10px 20px;
+  border: none;
+  border-radius: 5px;
+  cursor: pointer;
+  font-size: 16px;
+  transition: background-color 0.3s ease;
+}
+
+.edit-button:hover {
+  background-color: #0056b3; 
+}
diff --git a/public/images/logo.jpeg b/public/images/logo.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..b530f66a0702a9a6558805567edcb737f15f8dfe
GIT binary patch
literal 4363
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
V%8Ah_B7Q{tYk>ZLh>(k!{{Y3u#%urp

literal 0
HcmV?d00001

diff --git a/public/images/placeholder.png b/public/images/placeholder.png
new file mode 100644
index 0000000000000000000000000000000000000000..1fc2246b30169e279f74d7006f946878a68afbff
GIT binary patch
literal 2181
zcma)-`#TegAIG=G*$l%{2hB;x&_!}s<+3rOnoB}rF0sBPL`<AqGR&o1zDa85xW~x-
zGWVJ>lbWMgTCSOEja)*SOB?(8{s-rIUeD)wKkw)B`MiI8r#RSOkcX;40RVu!HQvez
z004sabQk3RGwPkI=boYLVCQ^JB9VyNF|^`3Q5{++6t1qW3IqbNSiHHpotsy=wY637
ztm@r6o~QsVVqrwj(4sa&Q9WAp0x4=mi(1eHv_=s_UsQz_^HL-or+4_Jd;hbGUPxGa
zH&g)g^Yfw-w7AP&Jp6cPG<SFTz4(o{goCvQ03<t`65*_5``hkx!|r_d?%LS<`q+;R
zk(}BTdKpbZ*IQ%QiQkgE<pFL006W`YccEuzs#er_LDamzvpPdmqFqr^vC|s5Lc1i+
zLjD|V<dsBqJb%h5eekI)kpIkowZf5C9y!t!@}?$js@ZSu#ntIjRL6tkcl70o{WT_N
zs6cH9JzOjP-2O~gwWf-KdohV(E;%*r;TAI>IAOj7008S+TUj_q<SpmPdXKp%cec}J
z0z+jeQeE&ruo-34)N~q|?lR06GHV&CCrei9L-)hs@ZbJPM1B*;w*041doGr1yg5PS
zkKq)hEdCY9fu*GyYWXXVq<o>5kBJO?i2Sh4G{B4v>O>%x>QYeAEBtazPnZ#2(xg|Q
z&0#-T7OqOE7lOj#VDEt@Sn#|?5v<o1kxbhfQE%Gr$AM=mq7S&^3=k-(pAGfRo$RVP
z=a|p1N_ZdBYYH0~YW0Ojhi6V>e@{HLV{-QVm*wQ*#G{W!Ej$X{^b8r#G%cdf_L3qi
z?=M4ANQFx7QwG_N+_U(#n5X}cq;2|f+Bi5OOd4nS-vR1Oy~goj&5dy-t%WMiVquS^
zX%D^Lg=-&0D^EU{I%29?DLrd#^VxSg^@t1%QWOb!@)kGw<cjgSK(O)Z(;|=8%4#pG
zl;f6;G#cC7-`fJhZp9D43Kx~mr_VNgcNE~MMvIDzS)S0;qD_Lja|G^@(V719OzHH5
z4{^Ui6y8~$FCbkgO53|bb&UbDyKM~>Z~t}dnnJP`MFrQ@C$|><KGCV?6O;fg(Ku=F
zbTE;eVcqjM!_ZQ!-o$332=lQS`*hbYS8L~CLm{npsjP%QE+t=Qx<Nm?LFr&UaNy93
zW<>Jk-zcCy%-EA4KQoQSXeZ)8N#N$Ux;pdm@o_U#<L#ZR!5)sxfGVW1AHKG}--E9o
zz*W}sx;n|cgz+tLa?38NJRZBT)}+%fRJ;eKJKQzV*S2ardB+TTG>zXiU=T_0V5{-G
zEtk~8#$nY#c(N^!;oCb*p;W_ycTn9E7K3iGyr8VsUsHm>+tM&OdEc@EJ=J^QKz9-~
zK6_u%Xm$uLs2+rU&TV;p!+5?;9dY2DGEt$+IPONqCC`_8nGDlmVDX`@xr|66LBrK1
z9^tn>v#R5oWwIKea&V!{-vWIGeB&J0O0YteP!h&xTq|{K8W0Xq;jZCH4y-oKKQ9r1
z2t{FWCK4><ayXm^;pv}Cy{CFyA4&O|6KI`(?PUm<*hdNq3S5?*Wo>MGoF-=y9rApi
zQ5HVA9TZA-kj&1A$BmbMtgmfvzfRIQ&KWm~y%mNhVvcOUQUz)$yW2Y)-_kgHmtTaz
z<{h!>dUxm~ce>ViTBtfIt`EFq>EGa8C}ilaqPL~DwAVAGz|4~aFTDvva2*M5&BzaB
zIvC=u$wWfX13#(uhKw!MbaL^~ZB(y0D3+~AMNTF+Sd0NJJFeux-1BL$B3p4-O8<I1
z_UE!o7%Zm+#8!ETDUF*Rvm1rQH-qk*^d;Q9a$R!;{5jDp)h>ao%Gef8ObX_5rowA1
zY}t4z5}h@9+&?}zXcUiQ9efB1U~YGaBHnT-#agvlzi3!Uf%$82px`vbT?YyVop9lk
z$4@CBmOEE&7Mm{&Ud97i@F`V84y~T}j7*H-pEmy*<Eq}Ispc@4yN^ja=D!o7BmiG4
zy#N^#l%=$sp6ZgliEXRys^)(rJDqh_i=aee>xN3@>4O#6DpJG?-5}5SoB1B_5wN(3
z87pczD_dm`^+H}FR7C!LzNY1yp9-AyRWR}+AIN;~K%MH$0?cVgRauq(ddH1lLa7-Q
zEruQtx7rZ*dFi?V<-$xQQsgz;!+9G%iqc8cyHJX>%Ezz(bj0mfxhZ2#pc|DMq=RvB
zgMW7=6cMcnzTIZxMkD<N0^)Hel&Hi!OkDBIQBG`{{yOb*BsVwIRK10F8I%-=1$L57
zOzkANOxj6bD?XH*laUm8iaV1pbGYMf2kW4b3_&eWy5qrz$0Jt90-H3SB9BI#5&1U0
zM0}FJxZ7(wdEKW1j+TW4i#eNjI!{zWx_tak*7sjy`HA&YF;hv->@5;BPFJQ`pMe^l
zXroA6Bg2cS4tlxaACLa|rCoD3Fs8-E#f5mA^5Ndsi*J-O+W9q=%_s`K2;gb%0~l0t
z0aVN0s$K7X3OZwUb?)~RCyr_D`b6|qX={}>hWl#Nh}@IKg*ws$O+~r^k~-SXw$NQ<
z_j6~MrexcM(-}x>QfI)9)9_|=y@;&xwH+i1slp7Ur~;*sYe7hmZx(&F%<>{nxEtYF
z?QDB$EWf{SX!&k#-_3yCZZDXLb**YJ`AiOftdOTit)$uvlsZ*7S7{|@CK;CxGIV?C
zE03zTTe(t5npu9jBgSZf$n#CN##rTKu4N%LgD!>;P`DHL3pPK}-hB5m?m1=Z@#Qs;
zrNuOvu{#RJNWTBXK-@hkb<-4?=-q@bvy6>^2qMia7ExQoJcM!FO!#3hm+S(J*MR&>
c;Hj~|hZVfa^6A;Kz4`}OpR>2B#S!EG2P~y0zW@LL

literal 0
HcmV?d00001

diff --git a/public/js/login.js b/public/js/login.js
index 9c06506..b672c61 100644
--- a/public/js/login.js
+++ b/public/js/login.js
@@ -1,81 +1,66 @@
-const login = async function (e) {
+function isValidEmail(email) {
+    // Basic email validation using a regular expression
+    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+    return emailRegex.test(email);
+}
+
+function login(e) {
     e.preventDefault();
+    let xhr = new XMLHttpRequest();
+    let data = new URLSearchParams();
+    data.append("email", document.getElementById("email").value);
+    data.append("password", document.getElementById("password").value);
+
+    const emailError = document.getElementById("emailError");
+    const passwordError = document.getElementById("passwordError");
 
-    try {
-        const email = document.getElementById("email").value;
-        const password = document.getElementById("password").value;
-        const response = await fetch("/login", {
-            method: "POST",
-            headers: {
-                "Accept": "application/x-www-form-urlencoded",
-                "Content-Type": "application/x-www-form-urlencoded",
-            },
-            credentials: "include",
-            body: new URLSearchParams({ email, password }),
-        });
+    let isError = false;
 
-        if (response.status === 200) {
-            const result = await response.json();
+    if (!isValidEmail(document.getElementById("email").value)) {
 
-            if (result.success === true) {
-                alert("Login success");
-                window.location.href = "/"; // Redirect to the home page
+        emailError.textContent = "Invalid email address";
+        emailInput.focus();
+        isError = true;
+    } else {
+        emailError.textContent = "";
+    }
+
+    if (document.getElementById("password").value === "") {
+        passwordError.textContent = "Password cannot be empty"
+        passwordError.focus();
+        isError = true;
+    } else {
+        passwordError.textContent = "";
+    }
+
+    if (isError) {
+        return;
+    }
+
+    xhr.onreadystatechange = function () {
+        if (xhr.readyState === 4) {
+            if (xhr.status === 200) {
+                let result = JSON.parse(xhr.responseText);
+                console.log(result);
+                if (result['success'] === true) {
+                    console.log("Success");
+                    window.location.href = '/';
+                } else {
+                    alert("Login failed! Are you sure your credentials are correct?")
+                }
             } else {
-                alert("Login failed");
+                alert("Login failed! Are you sure your credentials are correct?")
             }
-        } else {
-            console.log("Request failed");
         }
-    } catch (error) {
-        console.log(error);
-    }
-};
+    };
 
+    xhr.onerror = function () {
+        console.log("Network error occurred");
+    };
 
-// function login(e){
-//     e.preventDefault()
-//     let xhr = new XMLHttpRequest();
-//     let data={
-//         "email": document.getElementById("email").value,
-//         "password": document.getElementById("password").value,
-//     }
-//     console.log(data.email);
-//
-//     xhr.onreadystatechange=function (){
-//         console.log(xhr.toString())
-//         console.log(this.readyState,this.status)
-//         if (this.readyState==4 && this.status==200){
-//             let result=JSON.parse(this.responseText);
-//             console.log(result.text)
-//             if (result['status']==true){
-//                 console.log("success");
-//                 return;
-//             } else {
-//                 console.log("fail");
-//                 return;
-//                 // window.location.href='/';
-//             }
-//         } else {
-//             console.log("sss");
-//         }
-//     }
-//     // xhr.onload=function (){
-//     //     // let res=xhr.responseText
-//     //     // console.log(res);
-//     //
-//     //     if (xhr.status==200){
-//     //         let res=xhr.responseText
-//     //         console.log(res);
-//     //     } else {
-//     //         console.error(xhr.status)
-//     //     }
-//     // }
-//
-//     xhr.open("POST","http://localhost:8000/login/cont",true);
-//     xhr.setRequestHeader("Accept","application/json");
-//     xhr.setRequestHeader("Content-Type","application/json");
-//     xhr.withCredentials=true;
-//     xhr.send(JSON.stringify(data));
-//     console.log(xhr.toString());
-//
-// }
\ No newline at end of file
+    xhr.open("POST", "/login", true);
+    xhr.setRequestHeader("Accept", "application/json");
+    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+    xhr.withCredentials = true;
+    xhr.send(data.toString());
+}
diff --git a/public/js/sighting.js b/public/js/sighting.js
index 6a1a930..421efe3 100644
--- a/public/js/sighting.js
+++ b/public/js/sighting.js
@@ -22,11 +22,13 @@ function closeEditSightingModal() {
 document.addEventListener("DOMContentLoaded", function () {
 
     const addSightingForm = document.getElementById("add-sighting-form");
-    console.log("aaa", addSightingForm);
-
     addSightingForm.addEventListener("submit", function (e) {
         e.preventDefault();
         const formData = new FormData(addSightingForm);
+        let conf = confirm("Are you sure you want to add this sighting?");
+        if (!conf) {
+            return;
+        }
         fetch("/sighting", {
             method: "POST",
             body: formData,
@@ -76,12 +78,11 @@ document.addEventListener("DOMContentLoaded", function () {
     })
     const editSightingForm = document.getElementById("edit-sighting-form");
 
-    console.log("bbb", editSightingForm);
 
     editSightingForm.addEventListener("submit", function (event) {
+
         event.preventDefault();
         const sightingId = document.getElementById("edit-sighting-id").value;
-        console.log(sightingId)
         const formData = new FormData();
         formData.append("cat_id", document.getElementById("edit-cat-name-select").value);
         formData.append("sighting_location", document.getElementById("edit-sighting-location").value);
@@ -90,6 +91,10 @@ document.addEventListener("DOMContentLoaded", function () {
         formData.append("sighting_description", document.getElementById("edit-sighting-description").value);
         formData.append("image_url", document.getElementById("edit-image_url").files[0]);
 
+        let conf = confirm("Are you sure you want to edit this sighting?");
+        if (!conf) {
+            return;
+        }
         fetch(`/sighting/${sightingId}`, {
             method: "POST",
             body: formData,
@@ -120,12 +125,12 @@ document.addEventListener("DOMContentLoaded", function () {
             const pageNo = searchForm.querySelector("[name='pageNo']").value;
             const pageSize = searchForm.querySelector("[name='pageSize']").value;
 
-            const checkboxes = searchForm.querySelector("[name='order[]']");
+            const checkboxes = searchForm.querySelectorAll("[name='order[]']");
+            console.log(checkboxes);
             const selectedOptions = Array.from(checkboxes)
                 .filter(checkbox => checkbox.checked)
                 .map(checkbox => checkbox.value);
             const order = selectedOptions.join(",");
-
             const queryString = `/sighting?search=${search}&isDesc=${isDesc}&order=${order}&pageNo=${pageNo}&pageSize=${pageSize}`;
             window.location.href = queryString;
 
@@ -158,7 +163,7 @@ function editSighting(sightingId) {
 }
 
 function populateSightingForm(sightingCard, sightingId) {
-    const catId = sightingCard.querySelector(".sighting-cat").textContent.trim();
+    const catId = sightingCard.querySelector(".sighting-cat-id").textContent.trim();
     const sightingLocation = sightingCard.querySelector(".sighting-location").textContent.trim();
     const sightingDate = sightingCard.querySelector(".sighting-date").textContent.trim();
     const sightingTime = sightingCard.querySelector(".sighting-time").textContent.trim();
diff --git a/public/view/cats.php b/public/view/cats.php
index c52f794..fc7b3ab 100644
--- a/public/view/cats.php
+++ b/public/view/cats.php
@@ -62,43 +62,58 @@
                 value="<?= isset($_GET['pageSize']) ? intval($_GET['pageSize']) : 10 ?>">
         </form>
     </div>
-
     <div class="cat-cards-container">
         <?php foreach ($responseCats as $cat): ?>
             <div class="cat-card" id="cat-card-<?= $cat['cat_id'] ?>">
                 <?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
-                    <!-- Edit and delete buttons for admin users -->
                     <a class="delete-button" href="/cat/<?= htmlspecialchars($cat['cat_id']) ?>">X</a>
                 <?php endif; ?>
-                <!-- <a class="delete-button" href="/cat/<?= htmlspecialchars($cat['cat_id']) ?>">X</a> -->
-                <h2 class="cat-title">
-                    <?= htmlspecialchars($cat['name']) ?>
-                </h2>
-                <strong>Gender:</strong>
-                <p class="cat-gender">
-                    <?= htmlspecialchars($cat['gender']) ?>
-                </p>
-                <strong>Color:</strong>
-                <p class="cat-color">
-                    <?= htmlspecialchars($cat['color']) ?>
-                </p>
-                <strong>Description:</strong>
-                <p class="cat-description">
-                    <?= htmlspecialchars($cat['description']) ?>
-                </p>
-                <strong>Location:</strong>
-                <p class="cat-location">
-                    <?= htmlspecialchars($cat['location']) ?>
-                </p>
-                <strong>Spayed:</strong>
-                <p class="cat-spayed">
-                    <?= htmlspecialchars($cat['spayed']) ?>
-                </p>
-                <strong>Added:</strong>
-                <p class="cat-added">
-                    <?= htmlspecialchars($cat['cat_added']) ?>
-                </p>
-                <img class="cat-image" src="public/<?= htmlspecialchars($cat['image_path']) ?>" alt="cat image">
+                <div class="cat-image-container">
+                    <img class="cat-image" onerror="this.src='public/images/placeholder.png'"
+                        src="public/<?= htmlspecialchars($cat['image_path']) ?>" alt="cat image">
+                </div>
+                <div class="cat-details">
+                    <div class="cat-info">
+                        <h2 class="cat-title">
+                            <?= htmlspecialchars($cat['name']) ?>
+                        </h2>
+                        <p class="cat-description">
+                            <?= htmlspecialchars($cat['description']) ?>
+                        </p>
+                    </div>
+                    <div class="cat-metadata">
+                        <div class="cat-metadata-item">
+                            <strong>Gender:</strong>
+                            <span class="cat-gender">
+                                <?= htmlspecialchars($cat['gender']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Color:</strong>
+                            <span class="cat-color">
+                                <?= htmlspecialchars($cat['color']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Location:</strong>
+                            <span class="cat-location">
+                                <?= htmlspecialchars($cat['location']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Spayed:</strong>
+                            <span class="cat-spayed">
+                                <?= htmlspecialchars($cat['spayed']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Added:</strong>
+                            <span class="cat-added">
+                                <?= htmlspecialchars($cat['cat_added']) ?>
+                            </span>
+                        </div>
+                    </div>
+                </div>
                 <audio class="cat-audio" controls>
                     <source src="public/<?= htmlspecialchars($cat['sound_path']) ?>" type="audio/mpeg">
                     <source src="public/<?= htmlspecialchars($cat['sound_path']) ?>" type="audio/ogg">
@@ -109,11 +124,12 @@
                 <?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
                     <!-- Edit and delete buttons for admin users -->
                     <button class="edit-button" onclick="editCat(<?= $cat['cat_id'] ?>)">Edit</button>
-
                 <?php endif; ?>
             </div>
         <?php endforeach; ?>
+
     </div>
+
     <?php require_once(PROJECT_ROOT_PATH . '/public/components/Pagination.php'); ?>
     <?php if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin']): ?>
         <div>
@@ -243,6 +259,7 @@
             <button id="add-cat-button" class="add-button" onclick="openAddCatModal()">+</button>
         </div>
     <?php endif; ?>
+    <?php require_once(PROJECT_ROOT_PATH . '/public/components/Footer.php'); ?>
     <script src="public/js/cats.js"></script>
 </body>
 
diff --git a/public/view/home.php b/public/view/home.php
index 214a530..5a079e9 100644
--- a/public/view/home.php
+++ b/public/view/home.php
@@ -5,133 +5,44 @@
   <meta charset="UTF-8">
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  <link rel="stylesheet" href="public/css/styles.css">
-  <style>
-    /* Add your CSS styles here */
-    body {
-      font-family: Arial, sans-serif;
-      background-color: #f5f5f5;
-      margin: 0;
-      padding: 0;
-    }
-
-    header {
-      background-color: #333;
-      color: #fff;
-      padding: 20px 0;
-      text-align: center;
-    }
-
-    h1 {
-      font-size: 36px;
-      margin: 0;
-    }
-
-    .container {
-      max-width: 1200px;
-      margin: 0 auto;
-      padding: 20px;
-    }
-
-    .intro {
-      text-align: center;
-      margin-bottom: 40px;
-    }
-
-    .cta-button {
-      display: inline-block;
-      padding: 15px 30px;
-      background-color: #007BFF;
-      color: #fff;
-      text-decoration: none;
-      border-radius: 5px;
-      font-weight: bold;
-    }
-
-    .cta-button:hover {
-      background-color: #0056b3;
-    }
-
-    .features {
-      display: flex;
-      flex-wrap: wrap;
-      justify-content: center;
-      gap: 20px;
-    }
-
-    .feature {
-      flex: 1;
-      background-color: #fff;
-      box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
-      border-radius: 5px;
-      text-align: center;
-      padding: 20px;
-      transition: transform 0.2s ease-in-out;
-    }
-
-    .feature h2 {
-      font-size: 24px;
-      margin-bottom: 10px;
-    }
-
-    .feature p {
-      font-size: 16px;
-      color: #555;
-    }
-
-    .feature:hover {
-      transform: translateY(-5px);
-    }
-
-    footer {
-      background-color: #333;
-      color: #fff;
-      text-align: center;
-      padding: 20px 0;
-    }
-  </style>
-  <title>Wild Cats Guide</title>
+  <link rel="stylesheet" type="text/css" href="public/css/styles.css">
+</head>
+<title>Kuchenk Guide</title>
 </head>
 
 <body>
   <?php require_once(PROJECT_ROOT_PATH . '/public/components/Navbar.php'); ?>
 
   <header>
-    <h1>Welcome to the Wild Cats Guide</h1>
-    <p>Explore the fascinating world of wild cats at your university</p>
-    <a href="#features" class="cta-button">Learn More</a>
+    <h1>Welcome to Kuchenk ITB Guide</h1>
+    <p>Explore the fascinating world of wild cats at Institut Teknologi Bandung!</p>
   </header>
 
   <div class="container">
     <div class="intro">
-      <h2>Discover Wild Cats on Campus</h2>
-      <p>Get to know the wild cats that roam your university campus. Explore their preferred locations, view sightings,
-        and share your own.</p>
+      <h2>Discover Kuchenk Gemuk on Campus</h2>
+      <p>Mari berkenalan dengan kuchenk kuchenk gemuk yang menghuni ITB! Lihatlah informasi tenatang mereka, tempat
+        mereka biasa nongkrong, dan share foto kalian dengan mereka jika bertemu!</p>
     </div>
 
     <section id="features" class="features">
       <div class="feature">
-        <h2>Wild Cat List</h2>
-        <p>View a list of wild cats and their preferred locations on campus.</p>
+        <a href="/cat">
+          <h2>Direktori Kuchenk</h2>
+          <p>Ayo kenalan dengan kuchenk gemoy ITB dan lokasi tempat mereka biasa nongkrong!</p>
+        </a>
       </div>
 
       <div class="feature">
-        <h2>Sightings</h2>
-        <p>Share your wild cat sightings with photos and descriptions.</p>
+        <a href="/sighting">
+          <h2>Sightings</h2>
+          <p>Mari lihat foto orang-orang yang ketemu kuchenk ITB!</p>
+        </a>
       </div>
 
-      <div class="feature">
-        <h2>Add a Sighting</h2>
-        <p>Contribute to our guide by adding your own wild cat sightings.</p>
-      </div>
     </section>
   </div>
-
-  <footer>
-    <p>&copy;
-      <?= date('Y') ?> Wild Cats Guide
-    </p>
-  </footer>
+  <?php require_once(PROJECT_ROOT_PATH . '/public/components/Footer.php'); ?>
 </body>
 
 </html>
\ No newline at end of file
diff --git a/public/view/login.php b/public/view/login.php
index 1df55c0..3386ee5 100644
--- a/public/view/login.php
+++ b/public/view/login.php
@@ -1,22 +1,30 @@
 <!DOCTYPE html>
 <html lang="en">
-    <head>
-        <meta charset="UTF-8" />
-        <title>Title</title>
-        <script src="./public/js/login.js"></script>
-        <link rel="stylesheet" href="public/css/styles.css">
-    </head>
-    <body>
-       <?php require_once(PROJECT_ROOT_PATH.'/public/components/Navbar.php'); ?>
-        <h1 id="loginTitle">Login</h1>
-        <form id="inputForm">
-            <label for="email" id="emailLabel">email: </label>
-            <input type="text" id="email" required /> <br /><br />
-            <label for="password" id="passwordLabel">password: </label>
-            <input type="password" id="password" required /> <br /><br />
-            <button type="submit" id="loginButton" onclick="login(event)">
-                Login
-            </button>
+
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Login</title>
+    <script src="public/js/login.js"></script>
+    <link rel="stylesheet" type="text/css" href="public/css/login.css">
+</head>
+
+<body>
+    <div class="login-container">
+        <div class="login-logo">
+            <img src="public/images/logo.jpeg" alt="Your Logo">
+        </div>
+        <h1 class="login-title">Welcome Back</h1>
+        <form class="login-form" id="inputForm">
+            <label for="email" class="login-label">Email:</label>
+            <input type="text" id="email" class="login-input" required>
+            <span id="emailError" class="error-message"></span><br><br>
+            <label for="password" class="login-label">Password:</label>
+            <input type="password" id="password" class="login-input" required><br><br>
+            <span id="passwordError" class="error-message"></span><br><br>
+            <button type="submit" class="login-button" onclick="login(event)">Login</button>
         </form>
-    </body>
-</html>
+    </div>
+</body>
+
+</html>
\ No newline at end of file
diff --git a/public/view/sighting.php b/public/view/sighting.php
index b24a572..1a0517d 100644
--- a/public/view/sighting.php
+++ b/public/view/sighting.php
@@ -31,56 +31,62 @@
             </div>
             <input type="hidden" name="pageNo" value="<?= isset($_GET['pageNo']) ? intval($_GET['pageNo']) : 1 ?>">
             <input type="hidden" name="pageSize"
-                   value="<?= isset($_GET['pageSize']) ? intval($_GET['pageSize']) : 10 ?>">
+                value="<?= isset($_GET['pageSize']) ? intval($_GET['pageSize']) : 10 ?>">
         </form>
     </div>
-    <div class="sighting-cards-container">
-        <?php foreach ($responseSightings as $sighting):?>
-            <div class="sighting-card" id="sighting-card-<?=$sighting['sighting_id']?>">
-                <?php if (isset($_SESSION['user_id']) &&$_SESSION['user_id']==$sighting['user_id']){
-                    echo ("<a class=\"delete-button\" href='sighting/" . $sighting['sighting_id'] . "'>X<a>");
-                }?>
-<!--                --><?php //if ($_SESSION['user_id']===$sighting['user_id']): ?>
-<!--                    <a class="delete-button" href="/sighting/--><?php //= htmlspecialchars($sighting['sighting_id'])?><!--">X</a>-->
-<!--                --><?php //endif;?>
-                <strong>Kucing:</strong>
-                <p class="sighting-cat">
-                    <?=htmlspecialchars($sighting['name'])?>
-                </p>
-                <strong>Sighted by:</strong>
-                <p class="sighting-username">
-                    <?=htmlspecialchars($sighting['username'])?>
-                </p>
-                <strong>Location:</strong>
-                <p class="sighting-location">
-                    <?=htmlspecialchars($sighting['sighting_location'])?>
-                </p>
-                <strong>Date:</strong>
-                <p class="sighting-date">
-                    <?=htmlspecialchars($sighting['date'])?>
-                </p>
-                <strong>Time:</strong>
-                <p class="sighting-time">
-                    <?=htmlspecialchars($sighting['time'])?>
-                </p>
-                <br>
-                <p class="sighting-description">
-                    <?=htmlspecialchars($sighting['sighting_description'])?>
-                </p>
-                <img class="cat-image" src="public/<?= htmlspecialchars($sighting['image_url'])?>" alt="cat_image">
-                <?php if (isset($_SESSION['user_id'])&&$_SESSION['user_id']===$sighting['user_id']): ?>
-                    <a class="edit-button" onclick="editSighting(<?= $sighting['sighting_id']?>)">Edit</a>
-                <?php endif;?>
+    <div class="cat-cards-container">
+        <?php foreach ($responseSightings as $sighting): ?>
+            <div class="cat-card" id="sighting-card-<?= $sighting['sighting_id'] ?>">
+                <?php if (isset($_SESSION['user_id']) && $_SESSION['user_id'] == $sighting['user_id']) {
+                    echo ("<a class=\"delete-button\" href='sighting/" . $sighting['sighting_id'] . "'>X</a>");
+                } ?>
+                <div class="cat-image-container">
+                    <img class="cat-image" onerror="this.src='public/images/placeholder.png'"
+                        src="public/<?= htmlspecialchars($sighting['image_url']) ?>" alt="sighting image">
+                </div>
+                <div class="cat-details">
+                    <div class="cat-info">
+                        <h2 class="cat-title">
+                            <?= htmlspecialchars($sighting['name']) ?>
+                        </h2>
+                        <p class="sighting-description">
+                            <?= htmlspecialchars($sighting['sighting_description']) ?>
+                        </p>
+                    </div>
+                    <div class="cat-metadata">
+                        <div class="cat-metadata-item">
+                            <strong>Sighted by:</strong>
+                            <span class="sighting-username">
+                                <?= htmlspecialchars($sighting['username']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Location:</strong>
+                            <span class="sighting-location">
+                                <?= htmlspecialchars($sighting['sighting_location']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Date:</strong>
+                            <span class="sighting-date">
+                                <?= htmlspecialchars($sighting['date']) ?>
+                            </span>
+                        </div>
+                        <div class="cat-metadata-item">
+                            <strong>Time:</strong>
+                            <span class="sighting-time">
+                                <?= htmlspecialchars($sighting['time']) ?>
+                            </span>
+                        </div>
+                    </div>
+                </div>
+                <?php if (isset($_SESSION['user_id']) && $_SESSION['user_id'] === $sighting['user_id']): ?>
+                    <button class="edit-button" onclick="editSighting(<?= $sighting['sighting_id'] ?>)">Edit</button>
+                <?php endif; ?>
             </div>
-    <!--        <p>-->
-    <!--            --><?php //= htmlspecialchars($sighting['nama'])?>
-    <!--        </p>-->
-    <!--        <img src="public/--><?php //=htmlspecialchars($sighting['image_url'])?><!--">-->
-        <?php endforeach;?>
+        <?php endforeach; ?>
     </div>
-<!--    foreach ($responseCats as $cat){-->
-<!--       echo ('<option value="' . $cat['cat_id'] . '">' . $cat['name'] . '</option>');-->
-<!--    }?>-->
+
     <?php require_once(PROJECT_ROOT_PATH . '/public/components/Pagination.php'); ?>
     <?php if (isset($_SESSION['user_id'])): ?>
         <div>
@@ -93,9 +99,9 @@
                         <div class="form-group">
                             <label for="edit-cat-name-select">Cat name:</label>
                             <select id="edit-cat-name-select" name="cat_id" class="form-control">
-                                <?php foreach ($responseCats as $cat){
+                                <?php foreach ($responseCats as $cat) {
                                     echo ('<option value="' . $cat['cat_id'] . '">' . $cat['name'] . '</option>');
-                                }?>
+                                } ?>
                             </select>
                         </div>
                         <div class="form-group">
@@ -112,12 +118,13 @@
                         </div>
                         <div class="form-group">
                             <label for="edit-sighting-description">Description:</label>
-                            <textarea id="edit-sighting-description" name="sighting_description" class="form-control"></textarea>
+                            <textarea id="edit-sighting-description" name="sighting_description"
+                                class="form-control"></textarea>
                         </div>
                         <div class="form-group">
                             <label for="edit-image_url">Image File (JPG, JPEG, PNG):</label>
                             <input type="file" id="edit-image_url" name="image_url" class="file-input"
-                                   accept=".jpg, .jpeg, .png">
+                                accept=".jpg, .jpeg, .png">
                         </div>
                         <button type="submit" class="submit-button">Edit Sighting</button>
                     </form>
@@ -125,8 +132,9 @@
             </div>
         </div>
         <div>
-<!--            --><?php //echo ("<p>aaaA</p>")?>
-            <div id="add-sighting-modal" class="modal" >
+            <!--            -->
+            <?php //echo ("<p>aaaA</p>")?>
+            <div id="add-sighting-modal" class="modal">
                 <div class="modal-content">
                     <span class="close" onclick="closeAddSightingModal()">&times;</span>
                     <h2>Add New Sighting</h2>
@@ -135,9 +143,9 @@
                         <div class="form-group">
                             <label for="cat-name">Cat name:</label>
                             <select id="cat-name-select" name="cat_id" class="form-control">
-                                <?php foreach ($responseCats as $cat){
+                                <?php foreach ($responseCats as $cat) {
                                     echo ('<option value="' . $cat['cat_id'] . '">' . $cat['name'] . '</option>');
-                                }?>
+                                } ?>
                             </select>
                         </div>
                         <div class="form-group">
@@ -167,7 +175,9 @@
             </div>
             <button id="add-sighting-button" class="add-button" onclick="openAddSightingModal()">+</button>
         </div>
-    <?php endif;?>
+    <?php endif; ?>
+    <?php require_once(PROJECT_ROOT_PATH . '/public/components/Footer.php'); ?>
     <script src="public/js/sighting.js"></script>
 </body>
+
 </html>
\ No newline at end of file
diff --git a/public/view/users.php b/public/view/users.php
index a5e99dc..05fb10a 100644
--- a/public/view/users.php
+++ b/public/view/users.php
@@ -11,8 +11,8 @@
     <?php require_once(PROJECT_ROOT_PATH . '/public/components/Navbar.php'); ?>
     <div class="user-cards-container">
         <?php foreach ($responseUsers as $user): ?>
-            <div class="user-card" id="user-card-<?= $user['user_id'] ?>">
-                <a class="delete-button" href="/user/<?= htmlspecialchars($user['user_id']) ?>">Delete</a>
+            <div class="cat-card" id="user-card-<?= $user['user_id'] ?>">
+                <a class="delete-button" href="/user/<?= htmlspecialchars($user['user_id']) ?>">X</a>
                 <h2 class="user-title">
                     <?= htmlspecialchars($user['nama']) ?>
                 </h2>
@@ -68,6 +68,7 @@
             </div>
         </div>
     </div>
+    <?php require_once(PROJECT_ROOT_PATH . '/public/components/footer.php'); ?>
     <script src="public/js/users.js"></script>
 </body>
 
diff --git a/src/bases/BaseRepository.php b/src/bases/BaseRepository.php
index d5b44aa..18ce80e 100644
--- a/src/bases/BaseRepository.php
+++ b/src/bases/BaseRepository.php
@@ -86,8 +86,8 @@ abstract class BaseRepository
             $offset = ($page - 1) * $perPage;
             $query .= " LIMIT $perPage OFFSET $offset";
         }
-
-        echo $query;
+        // UNCOMMENT THIS FOR DEBUG
+        // echo $query;
         $stmt = $this->pdo->prepare($query);
         $stmt->execute();
 
diff --git a/src/repositories/SightingRepository.php b/src/repositories/SightingRepository.php
index e74a6e5..e3510e4 100644
--- a/src/repositories/SightingRepository.php
+++ b/src/repositories/SightingRepository.php
@@ -21,31 +21,41 @@ class SightingRepository extends BaseRepository
         return self::$instance;
     }
 
-    public function createSighting($sightingData){
-//        foreach ($sightingData as $key => $value){
+    public function createSighting($sightingData)
+    {
+        //        foreach ($sightingData as $key => $value){
 //            echo ($key.":" .$value."<br>");
 //        }
-        return $this->insert($sightingData,array(
-            'cat_id' => PDO::PARAM_INT,
-            'user_id' => PDO::PARAM_INT,
-            'sighting_location' => PDO::PARAM_STR,
-            'date' => PDO::PARAM_STR,
-            'time' => PDO::PARAM_STR,
-            'sighting_description' => PDO::PARAM_STR,
-            'image_url' => PDO::PARAM_STR
-        ));
+        return $this->insert(
+            $sightingData,
+            array(
+                'cat_id' => PDO::PARAM_INT,
+                'user_id' => PDO::PARAM_INT,
+                'sighting_location' => PDO::PARAM_STR,
+                'date' => PDO::PARAM_STR,
+                'time' => PDO::PARAM_STR,
+                'sighting_description' => PDO::PARAM_STR,
+                'image_url' => PDO::PARAM_STR
+            )
+        );
     }
 
-    public function updateSighting($sightingId, $sightingData){
-        return $this->update("sighting_id",$sightingId,$sightingData, array(
-            'cat_id' => PDO::PARAM_INT,
-            'user_id' => PDO::PARAM_INT,
-            'sighting_location' => PDO::PARAM_STR,
-            'date' => PDO::PARAM_STR,
-            'time' => PDO::PARAM_STR,
-            'sighting_description' => PDO::PARAM_STR,
-            'image_url' => PDO::PARAM_STR
-        ));
+    public function updateSighting($sightingId, $sightingData)
+    {
+        return $this->update(
+            "sighting_id",
+            $sightingId,
+            $sightingData,
+            array(
+                'cat_id' => PDO::PARAM_INT,
+                'user_id' => PDO::PARAM_INT,
+                'sighting_location' => PDO::PARAM_STR,
+                'date' => PDO::PARAM_STR,
+                'time' => PDO::PARAM_STR,
+                'sighting_description' => PDO::PARAM_STR,
+                'image_url' => PDO::PARAM_STR
+            )
+        );
     }
 
     public function deleteSighting($sighting)
@@ -53,47 +63,38 @@ class SightingRepository extends BaseRepository
         return $this->delete("sighting_id", $sighting);
     }
 
-//    public function join(){
+    //    public function join(){
 //        $sql = "SELECT * FROM sightings s join (cats c, users u) on (c.cat_id=s.cat_id and u.user_id=s.user_id)";
 //        $stmt = $this->pdo->prepare($sql);
 //        $stmt->execute();
 //        return $stmt->fetchAll(PDO::FETCH_ASSOC);
 //    }
-    public function join($columns = "*",$where=[],$orderBy=[],$page=1,$perPage=10,$isDesc=false){
+    public function join($columns = "*", $where = [], $orderBy = [], $page = 1, $perPage = 10, $isDesc = false)
+    {
         $query = "SELECT $columns FROM sightings s join (cats c, users u) on (c.cat_id=s.cat_id and u.user_id=s.user_id)";
-//        echo "aaaa";
-//        echo "<br>";
-//        echo $query;
-//        $query = "select * from cats c join sightings s on c.cat_id=s.cat_id join users u on s.user_id=u.user_id";
-        if (!empty($where)){
-            $query .= " WHERE ".implode(" AND ",$where);
-//            echo "<br>";
-//            echo $query;
+
+        if (!empty($where)) {
+            $query .= " WHERE " . implode(" AND ", $where);
         }
-//        echo ("<br>");
-//        echo $query;
-//        echo ("<br>");
-        if (!empty($orderBy)){
-            $orderByWithDesc = array_map(function ($column) use ($isDesc){
-                return $column .($isDesc && $isDesc!="false"?" DESC": "");
-            },$orderBy);
-            $query .= " ORDER BY ".implode(", ", $orderByWithDesc);
+        if (!empty($orderBy)) {
+            $orderByWithDesc = array_map(function ($column) use ($isDesc) {
+                return $column . ($isDesc && $isDesc != "false" ? " DESC" : "");
+            }, $orderBy);
+            $query .= " ORDER BY " . implode(", ", $orderByWithDesc);
         }
 
         if (!empty($perPage)) {
             $offset = ($page - 1) * $perPage;
             $query .= " LIMIT $perPage OFFSET $offset";
         }
-        echo $query;
-        echo ("<br>");
 
         $stmt = $this->pdo->prepare($query);
         $stmt->execute();
         $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
 
         $countQuery = "SELECT COUNT(*) as total FROM sightings s join (cats c, users u) on (c.cat_id=s.cat_id and u.user_id=s.user_id)";
-        if (!empty($where)){
-            $countQuery .= " WHERE ".implode(" AND ", $where);
+        if (!empty($where)) {
+            $countQuery .= " WHERE " . implode(" AND ", $where);
         }
         $stmtCount = $this->pdo->prepare($countQuery);
         $stmtCount->execute();
@@ -106,7 +107,8 @@ class SightingRepository extends BaseRepository
 
     }
 
-    public function getSightingById($sightingId){
-        return $this->selectOne("*",["sighting_id = $sightingId"]);
+    public function getSightingById($sightingId)
+    {
+        return $this->selectOne("*", ["sighting_id = $sightingId"]);
     }
 }
\ No newline at end of file
-- 
GitLab