diff --git a/Dockerfile.build b/Dockerfile.build
new file mode 100644
index 0000000000000000000000000000000000000000..cf3d5c1b5458556d110d756ab3ba6c2e3a5a65d2
--- /dev/null
+++ b/Dockerfile.build
@@ -0,0 +1,5 @@
+FROM php:8.2-apache
+RUN apt-get update && apt-get install -y libpq-dev && docker-php-ext-install pdo pdo_pgsql
+RUN a2enmod rewrite
+COPY ./src /var/www/html
+COPY ./src/php.ini /usr/local/etc/php/php.ini
\ No newline at end of file
diff --git a/build-image.sh b/build-image.sh
new file mode 100644
index 0000000000000000000000000000000000000000..6e26f4c1619983fa152e10b59ee18c958ee9b93a
--- /dev/null
+++ b/build-image.sh
@@ -0,0 +1 @@
+docker build -t tubes2-php -f "Dockerfile.build" .
\ No newline at end of file
diff --git a/scripts/build-image.sh b/scripts/build-image.sh
deleted file mode 100644
index ce096bac1ad2e7c6eec731197a2b126c245fa237..0000000000000000000000000000000000000000
--- a/scripts/build-image.sh
+++ /dev/null
@@ -1 +0,0 @@
-docker build -t tubes-1:latest .
\ No newline at end of file
diff --git a/seed.py b/seed.py
new file mode 100644
index 0000000000000000000000000000000000000000..d7d35c7d6845ce348468a4dea1bf874fb451bcf2
--- /dev/null
+++ b/seed.py
@@ -0,0 +1,56 @@
+import psycopg2
+from faker import Faker
+from random import randint
+
+conn = psycopg2.connect(
+    host="localhost",
+    database="mykos",
+    user="postgres",
+    password="postgres",
+    port=5433)
+
+cur = conn.cursor()
+fake = Faker("id_ID")
+
+owners = []
+for i in range(10):
+    owners.append(f"('{fake.name()}', '08{fake.msisdn()}')")
+owners_str = ", ".join(owners)
+
+cur.execute("INSERT INTO owners(name, phone_number) VALUES " + owners_str)
+
+dorms = []
+for i in range(10000):
+    owner_id = randint(1, 10)
+    name = fake.text(max_nb_chars=50)
+    address = fake.address()
+    city = fake.city()
+    price = randint(10, 250) * 10000
+    description = fake.paragraph(nb_sentences=2)
+    dorms.append(
+        f"({owner_id}, '{name}', '{address}', '{city}', {price}, '{description}')")
+dorms_str = ", ".join(dorms)
+cur.execute(
+    "INSERT INTO dorms(owner_id, name, address, city, price, description) VALUES " + dorms_str)
+
+medias = []
+for i in range(1, 10001):
+    for j in range(randint(1, 3)):
+        img_id = randint(1, 8)
+        endpoint = "/media/images/kos" + str(img_id) + ".jpeg"
+        alt_text = fake.text(max_nb_chars=25)
+        medias.append(f"({i}, 'photo', '{endpoint}', '{alt_text}')")
+
+    if randint(0, 1):
+        medias.append(
+            f"({i}, 'video', '/media/videos/video.mp4', 'preview kos')")
+
+medias_str = ", ".join(medias)
+cur.execute(
+    "INSERT INTO medias(dorm_id, type, endpoint, alt_text) VALUES " + medias_str)
+
+
+conn.commit()
+print("Success")
+cur.close()
+conn.close()
diff --git a/src/Controllers/DormController.php b/src/Controllers/DormController.php
index 10e8b9400aadfafaf4ae4c11dd384e5eecb47698..e17316cd7dd595b446c0066df1902b3cb9732985 100644
--- a/src/Controllers/DormController.php
+++ b/src/Controllers/DormController.php
@@ -17,11 +17,11 @@ use app\Utils\Toast;
 
 class DormController extends Controller
 {
-
-  public function list()
+  public function getList()
   {
     $page = Request::getPage();
     $cities = Dorm::getCities();
+    $ids = Request::getQuery()["ids"] ?? null;
     $sort = Request::getQuery()["sort"] ?? "dorm_id DESC";
     $city = Request::getQuery()["city"] ?? "";
     $price = Request::getQuery()["price"] ?? "";
@@ -39,9 +39,27 @@ class DormController extends Controller
     if (!in_array($price, $priceValues)) {
       $price = "";
     }
-    $data = Dorm::getAllFiltered($page, $sort, Request::getQuery()["q"] ?? "", $city, $price);
+    if ($ids !== null) {
+      $ids = explode(",", $ids);
+      $data = Dorm::getInIds($ids, $page, $sort, $city, $price);
+      $data["page"] = $page;
+      $data["cities"] = $cities;
+      return $data;
+    } else {
+      $data = Dorm::getAllFiltered($page, $sort, Request::getQuery()["q"] ?? "", $city, $price);
+    }
     $data["page"] = $page;
     $data["cities"] = $cities;
+    return $data;
+  }
+
+  public function list()
+  {
+    $data = $this->getList();
+    if (Request::isJSON()) {
+      Response::json($data);
+      return;
+    }
     if (isset(Request::getQuery()["list-only"])) {
       $this->render("dorm/list", $data);
       return;
@@ -62,12 +80,19 @@ class DormController extends Controller
       return;
     }
 
-    $this->render("dorm/view", [
+    $data = [
       "dorm" => $dorm,
       "medias" => $medias,
       "owner" => $owner,
-      "reviews" => $reviews
-    ]);
+    ];
+
+    if (Request::isJSON()) {
+      Response::json($data);
+      return;
+    }
+    $data["reviews"] = $reviews;
+
+    $this->render("dorm/view", $data);
   }
 
 
diff --git a/src/Controllers/UserController.php b/src/Controllers/UserController.php
index 5bffa27fcb4a0dcf72c383575c835d3495012082..874961404521f5ab3cbd9c21407225a6f69c2e49 100644
--- a/src/Controllers/UserController.php
+++ b/src/Controllers/UserController.php
@@ -23,29 +23,29 @@ class UserController extends Controller
     Response::$title = "Akun | MyKos";
   }
 
-//   public function me()
-//   {
-//     $form = new Validation([
-//       [new Field('email', "Email"), [new Required(), new Email()]],
-//       [new Field('name', "Nama"), [new Required()]],
-//       [new Field('phone_number', "Nomor Telepon"), [new Required(), new Phone()]],
-//     //   [new Field('password'), [new Required()]]
-//     ]);
-//     if (Request::getMethod() === "POST") {
-//       if ($form->validate(Request::getBody())) {
-//         $user = User::toModel($form->data);
-//         $user->save();
-//         Toast::success("Penyewa berhasil ditambahkan", true);
-//         Response::redirect("/owners");
-//         return;
-//       }
-//     }
-//     $user = Request::getUser();
-//     $this->render("user/index", [
-//       "user" => $user,
-//       ...$form->getFields(),
-//     ]);
-//   }
+  //   public function me()
+  //   {
+  //     $form = new Validation([
+  //       [new Field('email', "Email"), [new Required(), new Email()]],
+  //       [new Field('name', "Nama"), [new Required()]],
+  //       [new Field('phone_number', "Nomor Telepon"), [new Required(), new Phone()]],
+  //     //   [new Field('password'), [new Required()]]
+  //     ]);
+  //     if (Request::getMethod() === "POST") {
+  //       if ($form->validate(Request::getBody())) {
+  //         $user = User::toModel($form->data);
+  //         $user->save();
+  //         Toast::success("Penyewa berhasil ditambahkan", true);
+  //         Response::redirect("/owners");
+  //         return;
+  //       }
+  //     }
+  //     $user = Request::getUser();
+  //     $this->render("user/index", [
+  //       "user" => $user,
+  //       ...$form->getFields(),
+  //     ]);
+  //   }
 
   public function edit()
   {
@@ -65,7 +65,7 @@ class UserController extends Controller
       $user = User::findById($userId);
       $this->setUserFormData($formProfile, $user);
     }
-    
+
     $user = Request::getUser();
     $this->render("user/edit", [
       "user" => $user,
@@ -82,41 +82,41 @@ class UserController extends Controller
     $this->setUserFormData($formProfile, $user);
 
     if (Request::getMethod() === "POST") {
-        $valid = $formPassword->validate(Request::getBody());
-        $data = $formPassword->data;
-        if (!password_verify($data['password'], $user->password)) {
-            $formPassword->addError('password', 'Password salah');
-            $valid = false;
-        } 
-        if ($data["password1"] !== $data["password2"]) {
-            $formPassword->addError('password2', 'Password tidak sama');
-            $valid = false;
-        }
-        if (!$valid) {
-            $this->setUserFormData($formProfile, $user);
-            
-            $formPassword->data["password"] = $data["password"];
-            $formPassword->data["password1"] = $data["password1"];
-            $formPassword->data["password2"] = $data["password2"];
-
-          $this->render('user/edit', [ 
+      $valid = $formPassword->validate(Request::getBody());
+      $data = $formPassword->data;
+      if (!password_verify($data['password'], $user->password)) {
+        $formPassword->addError('password', 'Password salah');
+        $valid = false;
+      }
+      if ($data["password1"] !== $data["password2"]) {
+        $formPassword->addError('password2', 'Password tidak sama');
+        $valid = false;
+      }
+      if (!$valid) {
+        $this->setUserFormData($formProfile, $user);
+
+        $formPassword->data["password"] = $data["password"];
+        $formPassword->data["password1"] = $data["password1"];
+        $formPassword->data["password2"] = $data["password2"];
+
+        $this->render('user/edit', [
           "user" => $user,
           "fields" => $formProfile->data + $formPassword->data,
           "errors" => $formProfile->errors + $formPassword->errors
-          ]);
+        ]);
         return;
-        }
+      }
 
-        $userId = Request::getUser()->user_id;
-        $user = User::findById($userId);
-        $user->user_id = $userId;
-        $user->password = password_hash($data["password1"], PASSWORD_DEFAULT);
+      $userId = Request::getUser()->user_id;
+      $user = User::findById($userId);
+      $user->user_id = $userId;
+      $user->password = password_hash($data["password1"], PASSWORD_DEFAULT);
 
-        $user->save();
-        Toast::success("Password berhasil diubah", true);
-        Response::redirect("/account/edit");
-        return;
-    } 
+      $user->save();
+      Toast::success("Password berhasil diubah", true);
+      Response::redirect("/account/edit");
+      return;
+    }
   }
 
 
@@ -127,12 +127,12 @@ class UserController extends Controller
     $form->data["phone_number"] = $user->phone_number;
   }
 
-//   private function setPasswordFormData(Validation $form, User $user)
-//   {
-//     $form->data["password"] = $user->name;
-//     $form->data["password1"] = $user->email;
-//     $form->data["password2"] = $user->phone_number;
-//   }
+  //   private function setPasswordFormData(Validation $form, User $user)
+  //   {
+  //     $form->data["password"] = $user->name;
+  //     $form->data["password1"] = $user->email;
+  //     $form->data["password2"] = $user->phone_number;
+  //   }
 
 
   private function getProfileForm()
@@ -147,9 +147,9 @@ class UserController extends Controller
   private function getPasswordForm()
   {
     return new Validation([
-        [new Field('password', "Password Lama"), [new Required()]],
-        [new Field('password1', "Passwor Baru"), [new Required(), new Minimum(4)]],
-        [new Field('password2', "Konfirmasi Password"), [new Required()]]
+      [new Field('password', "Password Lama"), [new Required()]],
+      [new Field('password1', "Passwor Baru"), [new Required(), new Minimum(4)]],
+      [new Field('password2', "Konfirmasi Password"), [new Required()]]
     ]);
   }
 }
diff --git a/src/Controllers/WishlistController.php b/src/Controllers/WishlistController.php
index b057f9b3e8ac161e6c18a73338bcadee4ae0493a..1006580e73410c27ae0cc36fb7231fd5bd87cc17 100644
--- a/src/Controllers/WishlistController.php
+++ b/src/Controllers/WishlistController.php
@@ -70,7 +70,7 @@ class WishlistController extends Controller
     $dormId = $params["dormId"];
 
     if (Request::getMethod() === "GET") {
-      if (empty(Wishlists::where(["dorm_id"=>$dormId, "user_id"=>$userId]))) {
+      if (empty(Wishlists::where(["dorm_id" => $dormId, "user_id" => $userId]))) {
         $wishlist = Wishlists::toModel(["dorm_id" => $dormId, "user_id" => $userId]);
         $wishlist->save();
       }
diff --git a/src/Core/Application.php b/src/Core/Application.php
index 463ff2d6ef9f1cc11ebb9851ba956601158d426d..a4a65861847e3e9682e48074537a540b9db087d3 100644
--- a/src/Core/Application.php
+++ b/src/Core/Application.php
@@ -36,6 +36,7 @@ class Application
   {
     $this->router = new Router();
     $this->router->get('/', [], DormController::class, 'list');
+    $this->router->get('/dorms', [], DormController::class, 'list');
     $this->router->methods(["GET", "POST"], '/login', [],  AuthController::class, 'login');
     $this->router->methods(["GET", "POST"], '/register', [],  AuthController::class, 'register');
     $this->router->get('/logout', [],  AuthController::class, 'logout');
@@ -47,7 +48,7 @@ class Application
     $this->router->get("/me", [AuthRequired::class], AuthController::class, 'me');
 
     $this->router->methods(["GET", "POST"], "/dorms/create", [AdminOnly::class], DormController::class, 'create');
-    $this->router->methods(["GET", "POST"], "/dorms/{dormId}", [AuthRequired::class], DormController::class, 'view');
+    $this->router->methods(["GET", "POST"], "/dorms/{dormId}", [], DormController::class, 'view');
     $this->router->delete("/dorms/{dormId}", [AuthRequired::class], DormController::class, 'delete');
     $this->router->methods(["GET", "POST"], "/dorms/{dormId}/media", [AdminOnly::class], DormController::class, 'media');
     $this->router->delete("/dorms/{dormId}/media", [AdminOnly::class], DormController::class, 'deleteMedia');
diff --git a/src/Core/Request.php b/src/Core/Request.php
index 51c314ba5ae02e310355b3ed971009272c7ffbdf..b2f2bdfb35e1cd717766406e596be083afba4efc 100644
--- a/src/Core/Request.php
+++ b/src/Core/Request.php
@@ -74,4 +74,9 @@ class Request
   {
     return $_GET;
   }
+
+  public static function isJSON()
+  {
+    return isset($_SERVER["ACCEPT"]) && $_SERVER["ACCEPT"] === "application/json";
+  }
 }
diff --git a/src/Core/Response.php b/src/Core/Response.php
index 59445f395f2383fbc123e0a0dd845d64186243c0..325933c4dfcff7cdb5061cd1c0fe967474bdaf4f 100644
--- a/src/Core/Response.php
+++ b/src/Core/Response.php
@@ -16,4 +16,10 @@ class Response
     header("Location: $url");
     self::statusCode($permanent ? 301 : 302);
   }
+
+  public static function json($data)
+  {
+    header('Content-Type: application/json');
+    echo json_encode($data);
+  }
 }
diff --git a/src/Models/Dorm.php b/src/Models/Dorm.php
index 509ebfcfb7483f57f09dfbe8db78262add352d99..d459c5657713f5bf9c8d40b8b1bf9679e3f8c2a0 100644
--- a/src/Models/Dorm.php
+++ b/src/Models/Dorm.php
@@ -19,7 +19,7 @@ class Dorm extends BaseModel
 
   public static function getAllFiltered($page = 1, $orderBy = "dorm_id DESC", $search = "", $city = "", $price = "")
   {
-    $limit = 4;
+    $limit = 12;
     $offset = ($page - 1) * $limit;
     $cityQuery = $city ? "AND city = '$city'" : "";
     $priceQuery = $price ? "AND $price" : "";
diff --git a/src/Models/schema.sql b/src/Models/schema.sql
index 508f5c00cb5d5924e075d5c8ded87211f67b2683..578b27f0c30f9fc33ef71360dbb491bbbd9f5cf7 100644
--- a/src/Models/schema.sql
+++ b/src/Models/schema.sql
@@ -1,4 +1,4 @@
-CREATE TABLE users (
+CREATE TABLE IF NOT EXISTS users (
     user_id     SERIAL NOT NULL,
     email       TEXT NOT NULL UNIQUE,
     name        TEXT NOT NULL,
@@ -9,7 +9,7 @@ CREATE TABLE users (
     PRIMARY KEY (user_id)
 );
 
-CREATE TABLE owners (
+CREATE TABLE IF NOT EXISTS owners (
     owner_id     SERIAL NOT NULL,
     name        TEXT NOT NULL,
     phone_number TEXT,
@@ -17,7 +17,7 @@ CREATE TABLE owners (
     PRIMARY KEY (owner_id)
 );
 
-CREATE TABLE dorms (
+CREATE TABLE IF NOT EXISTS dorms (
     dorm_id      SERIAL NOT NULL,
     owner_id    INT NOT NULL,
     name        TEXT NOT NULL,
@@ -30,9 +30,15 @@ CREATE TABLE dorms (
     FOREIGN KEY (owner_id) REFERENCES owners(owner_id)
 );
 
-CREATE TYPE media_type AS ENUM ('photo', 'video');
+--create types
+DO $$
+BEGIN
+    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'media_type') THEN
+       CREATE TYPE media_type AS ENUM ('photo', 'video');
+    END IF;
+END$$;
 
-CREATE TABLE medias (
+CREATE TABLE IF NOT EXISTS medias (
     media_id    SERIAL NOT NULL,
     dorm_id      INT NOT NULL,
     type        MEDIA_TYPE NOT NULL,
@@ -43,7 +49,7 @@ CREATE TABLE medias (
     FOREIGN KEY (dorm_id) REFERENCES dorms(dorm_id) ON DELETE CASCADE
 );
 
-CREATE TABLE reviews (
+CREATE TABLE IF NOT EXISTS reviews (
     review_id   SERIAL NOT NULL,
     dorm_id      INT NOT NULL,
     user_id     INT NOT NULL, 
@@ -55,7 +61,7 @@ CREATE TABLE reviews (
     FOREIGN KEY (user_id) REFERENCES users(user_id)
 );
 
-CREATE TABLE wishlists (
+CREATE TABLE IF NOT EXISTS wishlists (
     user_id     INT NOT NULL,
     dorm_id      INT NOT NULL,
     created_at   TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
diff --git a/src/Views/dorm/list.php b/src/Views/dorm/list.php
index 17cfccba2567ce1d70bdd87ee0e9f6058837e8fa..1ef48c12844a32f380d1d55d3b3b9826b29ca8fd 100644
--- a/src/Views/dorm/list.php
+++ b/src/Views/dorm/list.php
@@ -21,18 +21,26 @@
   <? endforeach; ?>
 </ul>
 <div class="pagination">
+  <button data-page="1" class="pagination_item" <? if ($page===1) echo "disabled" ?>><span
+      aria-hidden="true">&laquo;</span>
+    <span class="sr-only">First</span>
+  </button>
   <button data-page="<?= $page - 1 ?>" class="pagination_item" <? if ($page===1) echo "disabled" ?>>
-    <span aria-hidden="true">&laquo;</span>
+    <span aria-hidden="true">&lt;</span>
     <span class="sr-only">Previous</span>
   </button>
-
-  <? for ($i = 1; $i <= $totalPage; $i++) : ?>
+  <? for ($i = $page - 2; $i <= $page + 2; $i++) : ?>
+  <? if ($i < 1 || $i > $totalPage) continue; ?>
   <button data-page="<?= $i ?>" class="pagination_item <?= $i == $page ? 'active' : '' ?>"><?= $i ?></button>
   <? endfor; ?>
 
   <button data-page="<?= $page + 1 ?>" class="pagination_item" <? if ($page==$totalPage) echo "disabled" ?>>
-    <span aria-hidden="true">&raquo;</span>
+    <span aria-hidden="true">&gt;</span>
     <span class="sr-only">Next</span>
   </button>
+  <button data-page="<?= $totalPage ?>" class="pagination_item" <? if ($page==$totalPage) echo "disabled" ?>>
+    <span aria-hidden="true">&raquo;</span>
+    <span class="sr-only">Last</span>
+  </button>
 
 </div>
\ No newline at end of file
diff --git a/src/Views/dorm/view.php b/src/Views/dorm/view.php
index 6d12e5dfe972a38518a00d63b8fd75fd43741897..d975d9742999c1efcb3af28c468422f967ae6030 100644
--- a/src/Views/dorm/view.php
+++ b/src/Views/dorm/view.php
@@ -2,9 +2,9 @@
 @@head
 <link rel="stylesheet" href="/static/styles/dorm-view.css?v=<?php
 
-use app\Models\User;
+                                                            use app\Models\User;
 
- echo time(); ?>">
+                                                            echo time(); ?>">
 @@endhead
 <div class="container">
   <? if (count($medias) > 0) : ?>
@@ -43,20 +43,20 @@ use app\Models\User;
     <div class="info-booking">
 
       <p class="price">Rp<?= number_format($dorm->price, 0, ',', '.') ?>
-            <span> / bulan</span>
+        <span> / bulan</span>
       </p>
 
       <p class="info-owner">Info Pemilik</p>
       <p><span class="person-icon">&#128100;</span>: <?= $owner->name ?></p>
       <p><span class="phone-icon">&nbsp;&#9742;</span>&nbsp;: <?= $owner->phone_number ?></p>
-      <? if (!$user->is_admin ?? false) : ?>
+      <? if ($user && !$user->is_admin ?? false) : ?>
         <!-- <form id="wishlist-button" action="/WishlistController/add" method="POST">
           <input type="hidden" name="dorm_id" id="likedInput" value="<?= $dormId ?>">    
         </form>
         <button id="wishlist-button" lass="btn btn-primary btn-edit-kos">Tambahkan kos ke wishlist</button> -->
-      <div class="wishlist">
-        <a href="/dorms/<?= $dorm->dorm_id ?>/add-to-wishlist" id="wishlist-button" class="btn btn-primary btn-edit-kos">Tambahkan kos ke wishlist</a>
-        <!-- <script>
+        <div class="wishlist">
+          <a href="/dorms/<?= $dorm->dorm_id ?>/add-to-wishlist" id="wishlist-button" class="btn btn-primary btn-edit-kos">Tambahkan kos ke wishlist</a>
+          <!-- <script>
           $(document).ready(function () {
               // Attach a click event listener to the like link
               $("#wishlist-button").click(function (event) {
@@ -68,24 +68,21 @@ use app\Models\User;
               });
           });
         </script> -->
-      </div>
+        </div>
       <? endif; ?>
-      
+
     </div>
   </div>
 
   <? if ($user->is_admin ?? false) : ?>
-  <div class="edit-admin">
-    <a href="/dorms/<?= $dorm->dorm_id ?>/edit" class="btn btn-primary btn-edit-kos">Edit Kos</a>
-  </div>
-  <form method="POST">
-      <button type="button" class="btn btn-danger dialog-btn action-btn delete-dorm"
-      data-dialog="delete-<?= $dorm->dorm_id ?>"><svg xmlns="http://www.w3.org/2000/svg" fill="none"
-      viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="14" height="14">
-      <path stroke-linecap="round" stroke-linejoin="round"
-      d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
-      </svg>
-      Delete kos
+    <div class="edit-admin">
+      <a href="/dorms/<?= $dorm->dorm_id ?>/edit" class="btn btn-primary btn-edit-kos">Edit Kos</a>
+    </div>
+    <form method="POST">
+      <button type="button" class="btn btn-danger dialog-btn action-btn delete-dorm" data-dialog="delete-<?= $dorm->dorm_id ?>"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="14" height="14">
+          <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
+        </svg>
+        Delete kos
       </button>
       <input type="hidden" name="dorm_id" value="<?= $dorm->dorm_id ?>" />
       <input type="hidden" name="_method" value="DELETE" />
@@ -93,29 +90,27 @@ use app\Models\User;
         <div class="dialog-content">
           <h4 class="confirm-title">Apakah Anda yakin ingin menghapus kos?</h4>
           <div class="confirm-action">
-            <button type="button" class="btn btn-outlined dialog-btn"
-            data-dialog="delete-<?= $dorm->dorm_id ?>">Batal</button>
+            <button type="button" class="btn btn-outlined dialog-btn" data-dialog="delete-<?= $dorm->dorm_id ?>">Batal</button>
             <button type="submit" class="btn btn-danger">Hapus</button>
           </div>
         </div>
       </div>
     </form>
   <? endif; ?>
-  
+
   <div class="reviews">
     <h1> Review Kos Ini</h1>
-    <? if (!$user->is_admin ?? false) : ?>
+    <? if ($user && !$user->is_admin ?? false) : ?>
       <div class="add-review">
         <a href="/dorms/<?= $dorm->dorm_id ?>/add-review" class="btn btn-primary btn-add-review">
-          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor"
-          width="12" height="12" aria-hidden="true">
-          <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
+          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" width="12" height="12" aria-hidden="true">
+            <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
           </svg>
-        Tambahkan Review
+          Tambahkan Review
         </a>
       </div>
     <? endif; ?>
-      
+
     <ul class="review-list">
       <? foreach ($reviews as $review) : ?>
         <? $reviewer = User::findById($review->user_id); ?>
@@ -125,8 +120,8 @@ use app\Models\User;
             <p class="review-item-rate">
               <?
               $rating = $review->rate;
-              $stars = str_repeat("★", $rating); 
-              $emptyStars = str_repeat("☆", 5 - $rating); 
+              $stars = str_repeat("★", $rating);
+              $emptyStars = str_repeat("☆", 5 - $rating);
               echo $stars . $emptyStars;
               ?>
             </p>
@@ -135,20 +130,15 @@ use app\Models\User;
           <div class="review-actions">
             <? if (($user->is_admin ?? false) || ($user->user_id == $reviewer->user_id  ?? false)) : ?>
               <? if ($user->user_id == $reviewer->user_id ??  false) : ?>
-                <a href="/reviews/<?= $review->review_id ?>" class="btn btn-outlined edit-review" data-dialog="add-owner-dialog"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
-                  stroke-width="2" stroke="currentColor" width="20" height="20">
-                  <path stroke-linecap="round" stroke-linejoin="round"
-                  d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
+                <a href="/reviews/<?= $review->review_id ?>" class="btn btn-outlined edit-review" data-dialog="add-owner-dialog"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
+                    <path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
                   </svg>
                 </a>
               <? endif ?>
               <form method="POST" action="/dorms/<?= $dorm->dorm_id ?>/delete-review">
-                <button type="button" class="btn btn-danger dialog-btn action-btn"
-                data-dialog="delete-<?= $review->review_id ?>"><svg xmlns="http://www.w3.org/2000/svg" fill="none"
-                viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
-                <path stroke-linecap="round" stroke-linejoin="round"
-                d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
-                </svg>
+                <button type="button" class="btn btn-danger dialog-btn action-btn" data-dialog="delete-<?= $review->review_id ?>"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" width="20" height="20">
+                    <path stroke-linecap="round" stroke-linejoin="round" d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0" />
+                  </svg>
                 </button>
                 <input type="hidden" name="review_id" value="<?= $review->review_id ?>" />
                 <input type="hidden" name="_method" value="DELETE" />
@@ -156,8 +146,7 @@ use app\Models\User;
                   <div class="dialog-content">
                     <h4 class="confirm-title">Apakah anda yakin ingin menghapus review?</h4>
                     <div class="confirm-action">
-                      <button type="button" class="btn btn-outlined dialog-btn"
-                      data-dialog="delete-<?= $review->review_id ?>">Batal</button>
+                      <button type="button" class="btn btn-outlined dialog-btn" data-dialog="delete-<?= $review->review_id ?>">Batal</button>
                       <button type="submit" class="btn btn-danger">Hapus</button>
                     </div>
                   </div>
diff --git a/src/migrate.php b/src/migrate.php
new file mode 100644
index 0000000000000000000000000000000000000000..e10d247c439ed606cb43ddf9ef729a0c062a2e4a
--- /dev/null
+++ b/src/migrate.php
@@ -0,0 +1,11 @@
+<?php
+
+$dsn = sprintf("pgsql:host=%s;dbname=%s", getenv("POSTGRES_HOST"), getenv("POSTGRES_DB"));
+$pdo = new PDO($dsn, getenv("POSTGRES_USER"), getenv("POSTGRES_PASSWORD"), [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_PERSISTENT => true]);
+
+try {
+  $sql = file_get_contents(__DIR__ . "/Models/schema.sql");
+  $pdo->exec($sql);
+} catch (PDOException $e) {
+  die($e->getMessage());
+}