diff --git a/src/Controllers/DormController.php b/src/Controllers/DormController.php new file mode 100644 index 0000000000000000000000000000000000000000..24123c6e17b2cb42acc6524e3b4a66f7b7faa705 --- /dev/null +++ b/src/Controllers/DormController.php @@ -0,0 +1,59 @@ +<?php + +namespace app\Controllers; + +use app\Core\Request; +use app\Core\Response; +use app\Forms\Field; +use app\Forms\Number; +use app\Forms\Required; +use app\Forms\Validation; +use app\Models\Dorm; +use app\Models\Media; +use app\Models\Owners; + +class DormController extends Controller +{ + public function create() + { + $form = new Validation([ + [new Field("dorm_name", "Nama Kos"), [new Required()]], + [new Field("address", "Alamat"), [new Required()]], + [new Field("price", "Harga"), [new Required(), new Number()]], + [new Field("description", "Deskripsi"), [new Required()]], + [new Field("city", "Kota"), [new Required()]], + [new Field("owner_id", "Pemilik"), [new Required(), new Number()]] + ]); + + if (Request::getMethod() === "POST") { + if ($form->validate(Request::getBody())) { + $form->data["name"] = $form->data["dorm_name"]; + unset($form->data["dorm_name"]); + $dorm = Dorm::toModel($form->data); + $dorm->save(); + Response::redirect("/dorms/{$dorm->dorm_id}/media"); + return; + } + var_dump($form->getFields()["errors"]); + exit(); + } + $owners = Owners::all("name DESC"); + $this->render("dorm/create", [ + "owners" => $owners, + ...$form->getFields() + ]); + } + + + public function media($params) + { + $dormId = $params["dormId"]; + $dorm = Dorm::findById($dormId); + $medias = Media::findByDormId($dormId); + + $this->render("dorm/media", [ + "dorm" => $dorm, + "medias" => $medias + ]); + } +} diff --git a/src/Core/Application.php b/src/Core/Application.php index abe39482a2c514cc1bd9b17e65cd7c520e33ad84..e10d34fb7047ca830c526dcce0fd15172da8b5cd 100644 --- a/src/Core/Application.php +++ b/src/Core/Application.php @@ -4,6 +4,7 @@ namespace app\Core; use app\Controllers\OwnerController; use app\Controllers\AuthController; +use app\Controllers\DormController; use app\Middlewares\AdminOnly; use app\Middlewares\AuthRequired; use app\Models\BaseModel; @@ -39,5 +40,8 @@ class Application $this->router->delete("/owners", [AdminOnly::class], OwnerController::class, 'delete'); $this->router->get('/users/{user_id}/{dorm_id}', [], AuthController::class, 'test'); $this->router->get("/me", [AuthRequired::class], AuthController::class, 'me'); + + $this->router->methods(["GET", "POST"], "/dorms/create", [AdminOnly::class], DormController::class, 'create'); + $this->router->get("/dorms/{dormId}/media", [AdminOnly::class], DormController::class, 'media'); } } diff --git a/src/Models/Dorm.php b/src/Models/Dorm.php new file mode 100644 index 0000000000000000000000000000000000000000..3157abf1aa9222d3c1e90e7da8f82ac47e5e9a81 --- /dev/null +++ b/src/Models/Dorm.php @@ -0,0 +1,17 @@ +<?php + +namespace app\Models; + + +class Dorm extends BaseModel +{ + public int $dorm_id; + public string $name; + public string $address; + public string $city; + public int $price; + public string $description; + public int $owner_id; + protected static string $table = "dorms"; + protected static string $primaryKey = "dorm_id"; +} diff --git a/src/Models/Media.php b/src/Models/Media.php new file mode 100644 index 0000000000000000000000000000000000000000..c2722e9e159d6de26155731c586d5fff706423be --- /dev/null +++ b/src/Models/Media.php @@ -0,0 +1,21 @@ +<?php + +namespace app\Models; + + +class Media extends BaseModel +{ + public int $media_id; + public int $dorm_id; + public string $type; + public string $alt_text; + public string $endpoint; + protected static string $table = "medias"; + protected static string $primaryKey = "media_id"; + + + public static function findByDormId(int $dormId) + { + return self::where(["dorm_id" => $dormId]); + } +} diff --git a/src/Views/dorm/create.php b/src/Views/dorm/create.php new file mode 100644 index 0000000000000000000000000000000000000000..24d1db41cb65b47f64dce39e4c8a858685821fb2 --- /dev/null +++ b/src/Views/dorm/create.php @@ -0,0 +1,66 @@ +@extends('layouts/base') +@@head +<link rel="stylesheet" href="/static/styles/create-dorm.css"> +@@endhead +<div> + <h1>Tambahkan Kos</h1> + <form method="POST" novalidate class="create-form"> + <div class="input-group"> + <label for="owner_id" class="required">Pemilik</label> + <select name="owner_id"> + <?php + foreach ($owners as $owner) { + echo '<option value="' . $owner->owner_id . '">' . $owner->name . '</option>'; + } + ?> + </select> + </div> + <div class="input-group"> + <label for="dorm_name" class="required">Nama Kos</label> + <input name="dorm_name" autofocus placeholder="Nama Kos" value="<?= $fields["dorm_name"] ?? '' ?>" /> + <?php + if (isset($errors) && array_key_exists('dorm_name', $errors)) { + echo '<div class="error">' . $errors["dorm_name"] . '</div>'; + } + ?> + </div> + <div class="input-group"> + <label for="address" class="required">Alamat</label> + <input name="address" placeholder="Alamat" value="<?= $fields["address"] ?? '' ?>" /> + <?php + if (isset($errors) && array_key_exists('address', $errors)) { + echo '<div class="error">' . $errors["address"] . '</div>'; + } + ?> + </div> + <div class="input-group"> + <label for="city" class="required">Kota</label> + <input name="city" placeholder="Kota" value="<?= $fields["city"] ?? '' ?>" /> + <?php + if (isset($errors) && array_key_exists('city', $errors)) { + echo '<div class="error">' . $errors["city"] . '</div>'; + } + ?> + </div> + <div class="input-group"> + <label for="price" class="required">Harga</label> + <input name="price" type="number" min="0" placeholder="Harga" value="<?= $fields["price"] ?? '' ?>" /> + <?php + if (isset($errors) && array_key_exists('price', $errors)) { + echo '<div class="error">' . $errors["price"] . '</div>'; + } + ?> + </div> + <div class="input-group"> + <label for="description" class="required">Deskripsi</label> + <textarea name="description" placeholder="Deskripsi" value="<?= $fields["description"] ?? '' ?>"></textarea> + <?php + if (isset($errors) && array_key_exists('description', $errors)) { + echo '<div class="error">' . $errors["description"] . '</div>'; + } + ?> + </div> + <button class="btn btn-primary">Tambah Kos</button> + + </form> +</div> \ No newline at end of file diff --git a/src/Views/dorm/media.php b/src/Views/dorm/media.php new file mode 100644 index 0000000000000000000000000000000000000000..a57efda74ab6a2a9f01ee159cc8c0b7f3675f729 --- /dev/null +++ b/src/Views/dorm/media.php @@ -0,0 +1 @@ +@extends('layouts/base') \ No newline at end of file diff --git a/src/Views/index.php b/src/Views/index.php index 49e155b462a13f9345b62790b492eb667aa0af7b..4cf6a4336eb30b64950777f780252099c702176e 100644 --- a/src/Views/index.php +++ b/src/Views/index.php @@ -1,8 +1,14 @@ @extends('layouts/base') -<h1>Home</h1> -<? if ($user) : ?> - <p>Welcome <?= $user->name ?></p> - <a href="/logout">Logout</a> -<? else : ?> - <a href="/login">Login</a> -<? endif; ?> \ No newline at end of file +@@head +<link rel="stylesheet" href="/static/styles/home.css"> +@@endhead +<section class="hero"> + <h1 class="hero-title">Mau cari kos?</h1> + <p class="hero-desc">Dapatkan infonya dan langsung sewa di MyKos. + </p> + <? if ($user->is_admin ?? false) : ?> + <div class="cta-admin"> + <a href="/dorms/create" class="btn btn-primary">Tambah Kos</a> + </div> + <? endif; ?> +</section> \ No newline at end of file diff --git a/src/Views/login.php b/src/Views/login.php index 3a2bc7d910238938ab0a36b3e0c1406d91c31e49..9b2390ee7e2e8847fd057acea1aa813dad96e77d 100644 --- a/src/Views/login.php +++ b/src/Views/login.php @@ -1,23 +1,22 @@ @extends('layouts/auth') <h1 class="auth-title">Login</h1> <div class="input-group"> - <label for="email">Email</label> - <input name="email" type="email" autofocus placeholder="Email" - value="<?= isset($fields["email"]) ? $fields["email"] : '' ?>" /> + <label for="email" class="required">Email</label> + <input name="email" type="email" autofocus placeholder="Email" value="<?= isset($fields["email"]) ? $fields["email"] : '' ?>" /> <?php - if (isset($errors) && array_key_exists('email', $errors)) { - echo '<div class="error">' . $errors["email"] . '</div>'; - } - ?> + if (isset($errors) && array_key_exists('email', $errors)) { + echo '<div class="error">' . $errors["email"] . '</div>'; + } + ?> </div> <div class="input-group"> - <label for="password">Password</label> + <label for="password" class="required">Password</label> <input name="password" type="password" placeholder="Password" /> <?php - if (isset($errors) && array_key_exists('password', $errors)) { - echo '<div class="error">' . $errors["password"] . '</div>'; - } - ?> + if (isset($errors) && array_key_exists('password', $errors)) { + echo '<div class="error">' . $errors["password"] . '</div>'; + } + ?> </div> <button class="btn btn-primary">Login</button> <p class="auth-switch">Belum punya akun MyKos? <a href="/register">Daftar Sekarang</a></p> \ No newline at end of file diff --git a/src/Views/owner/index.php b/src/Views/owner/index.php index 473c346225be532f61197eaec0c70c83bc12ea9d..6c8a03660420a9a6f19fcf96745535187a783d52 100644 --- a/src/Views/owner/index.php +++ b/src/Views/owner/index.php @@ -5,8 +5,7 @@ <div class="owner-container"> <div class="add-wrapper"> <button class="btn btn-primary add-owner dialog-btn" data-dialog="add-owner-dialog"> - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" - width="16" height="16" aria-hidden="true"> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" width="16" height="16" aria-hidden="true"> <path stroke-linecap="round" stroke-linejoin="round" d="M12 4.5v15m7.5-7.5h-15" /> </svg> Tambah Penyewa @@ -26,33 +25,36 @@ <tbody> <?php foreach ($owners as $owner) : ?> - <tr> - <td><?= $owner->owner_id ?></td> - <td><?= $owner->name ?></td> - <td><?= $owner->phone_number ?></td> - <td class="action"> - <button type="button" class="btn btn-outlined dialog-btn edit-owner" - data-dialog="add-owner-dialog">Ubah</button> - <form method="POST"> - <button type="button" class="btn btn-danger dialog-btn" - data-dialog="delete-<?= $owner->owner_id ?>">Hapus</button> - <input type="hidden" name="owner_id" value="<?= $owner->owner_id ?>" /> - <input type="hidden" name="_method" value="DELETE" /> - <div class="dialog-wrapper delete-<?= $owner->owner_id ?>"> - <div class="dialog-content"> - <h4 class="confirm-title"> - Apakah anda yakin ingin menghapus penyewa <?= $owner->name ?>? - </h4> - <div class="confirm-action"> - <button type="button" class="btn btn-outlined dialog-btn" - data-dialog="delete-<?= $owner->owner_id ?>">Batal</button> - <button type="submit" class="btn btn-danger">Hapus</button> + <tr> + <td><?= $owner->owner_id ?></td> + <td><?= $owner->name ?></td> + <td><?= $owner->phone_number ?></td> + <td class="action"> + <button type="button" class="btn btn-outlined dialog-btn edit-owner action-btn" 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" style="transform: translateX(2px);"> + <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> + </button> + <form method="POST"> + <button type="button" class="btn btn-danger dialog-btn action-btn" data-dialog="delete-<?= $owner->owner_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="owner_id" value="<?= $owner->owner_id ?>" /> + <input type="hidden" name="_method" value="DELETE" /> + <div class="dialog-wrapper delete-<?= $owner->owner_id ?>"> + <div class="dialog-content"> + <h4 class="confirm-title"> + Apakah anda yakin ingin menghapus penyewa <?= $owner->name ?>? + </h4> + <div class="confirm-action"> + <button type="button" class="btn btn-outlined dialog-btn" data-dialog="delete-<?= $owner->owner_id ?>">Batal</button> + <button type="submit" class="btn btn-danger">Hapus</button> + </div> </div> </div> - </div> - </form> - </td> - </tr> + </form> + </td> + </tr> <?php endforeach; ?> </tbody> </table> @@ -89,7 +91,7 @@ use app\Core\Request; <?= isset($editId) ? "Ubah" : "Tambah" ?> </button> <? if (isset($editId)) : ?> - <input type="hidden" name="owner_id" value="<?= $editId ?>" /> + <input type="hidden" name="owner_id" value="<?= $editId ?>" /> <? endif; ?> </form> </div> diff --git a/src/Views/register.php b/src/Views/register.php index d8be0e22847b0a225f9dc015af04938256b76def..3bc3a707f288828c446e95448b82028dca7f5a7f 100644 --- a/src/Views/register.php +++ b/src/Views/register.php @@ -1,7 +1,7 @@ @extends('layouts/auth') <h1 class="auth-title">Register</h1> <div class="input-group"> - <label for="name">Nama</label> + <label for="name" class="required">Nama</label> <input name="name" autofocus placeholder="Nama" value="<?= $fields["name"] ?>" /> <?php if (array_key_exists('name', $errors)) { @@ -10,7 +10,7 @@ ?> </div> <div class="input-group"> - <label for="email">Email</label> + <label for="email" class="required">Email</label> <input name="email" type="email" autofocus placeholder="Email" value="<?= $fields["email"] ?>" /> <?php if (array_key_exists('email', $errors)) { @@ -28,7 +28,7 @@ ?> </div> <div class="input-group"> - <label for="password">Password</label> + <label for="password" class="required">Password</label> <input name="password" type="password" placeholder="Password" /> <?php if (array_key_exists('password', $errors)) { @@ -37,7 +37,7 @@ ?> </div> <div class="input-group"> - <label for="password2">Konfirmasi Password</label> + <label for="password2" class="required">Konfirmasi Password</label> <input name="password2" type="password" placeholder="Konfirmasi Password" /> <?php if (array_key_exists('password2', $errors)) { diff --git a/src/public/static/styles/create-dorm.css b/src/public/static/styles/create-dorm.css new file mode 100644 index 0000000000000000000000000000000000000000..f6175bb7d32ff7559f647884e56a0d4c3e6e614d --- /dev/null +++ b/src/public/static/styles/create-dorm.css @@ -0,0 +1,16 @@ +.create-form { + display: flex; + flex-direction: column; + + gap: 1rem; + max-width: 32rem; +} + +h1 { + margin-top: 3rem; + margin-bottom: 2rem; +} + +.create-form button { + margin-bottom: 3rem; +} diff --git a/src/public/static/styles/home.css b/src/public/static/styles/home.css new file mode 100644 index 0000000000000000000000000000000000000000..6d0bf26b1d81e48af1e592d7469b84691b664e1c --- /dev/null +++ b/src/public/static/styles/home.css @@ -0,0 +1,23 @@ +.hero { + margin: 3rem 0; +} + +.hero-title { + font-weight: 900; +} + +.hero-desc { + font-size: var(--text-lg); + line-height: 200%; +} + +.cta-admin { + display: flex; + margin-top: 2rem; +} + +.cta-admin a { + max-width: 100%; + min-width: 10rem; + text-align: center; +} diff --git a/src/public/static/styles/main.css b/src/public/static/styles/main.css index 42adb03a14354ce8078142d1c83e8c085a69aa04..935db4b874a04a8f7ab1b73f059037cad446dd4a 100644 --- a/src/public/static/styles/main.css +++ b/src/public/static/styles/main.css @@ -162,6 +162,12 @@ a::visited { color: var(--color-danger-hover); } +.input-group label.required::after { + content: "*"; + color: var(--color-danger); + margin-left: 0.25rem; +} + .input-group label { display: block; margin-bottom: 0.5rem; @@ -169,7 +175,9 @@ a::visited { font-weight: 700; } -.input-group input { +.input-group input, +textarea, +select { display: block; width: 100%; padding: 0.75rem 1rem; @@ -178,7 +186,9 @@ a::visited { font-size: var(--text-sm); } -.input-group input:focus { +.input-group input:focus, +textarea:focus, +select:focus { outline: none; border-color: var(--color-primary); } diff --git a/src/public/static/styles/owner.css b/src/public/static/styles/owner.css index 02ce01d6cf1b2916a742fd8634c2a4cda5cad669..6f11aeaa850b659dd295c9b92effc7dd4d8b9d41 100644 --- a/src/public/static/styles/owner.css +++ b/src/public/static/styles/owner.css @@ -35,9 +35,15 @@ td.action { display: flex; justify-content: center; + align-items: center; gap: 0.5rem; } -td.action button { - padding: 0.5rem; +td.action .action-btn { + width: 2rem; + height: 2rem; + padding: 0; + display: flex; + justify-content: center; + align-items: center; font-weight: 500; }