selesai semua

This commit is contained in:
Putrid1ana 2025-06-17 20:24:37 +07:00
parent af29398f05
commit 954d2ceaa4
34 changed files with 787 additions and 321 deletions

View File

@ -164,4 +164,16 @@ public function logout(Request $request)
$request->session()->regenerateToken();
return redirect('/home');
}
protected function authenticated(Request $request, $user)
{
if (!$user->rental_approved) {
// Kalau belum approve rental → ke approve_rental
return redirect()->route('users.showApprovalForm')->with('info', 'Silakan setujui syarat & ketentuan rental terlebih dahulu.');
}
// Kalau sudah approve → ke peta
return redirect()->route('users.peta');
}
}

View File

@ -5,6 +5,7 @@
use Illuminate\Http\Request;
use App\Models\Booking;
use App\Models\User;
use Illuminate\Support\Facades\Log;
use App\Models\Room;
use App\Models\PerpanjanganBooking;
@ -46,7 +47,7 @@ public function store(Request $request)
$request->validate([
'id_user' => 'required|exists:users,id_user',
'id_kamar' => 'required|exists:rooms,id_kamar',
'status_booking' => 'required|in:Pending,Dikonfirmasi,Dibatalkan',
'status_booking' => 'required|in:Pending,Dikonfirmasi,Dibatalkan,Selesai',
'tanggal_booking' => 'required|date',
'tanggal_checkin' => 'required|date|after_or_equal:tanggal_booking',
'tanggal_checkout' => 'required|date|after:tanggal_checkin',
@ -84,7 +85,7 @@ public function update(Request $request, $id_booking)
$request->validate([
'id_user' => 'required|exists:users,id_user',
'id_kamar' => 'required|exists:rooms,id_kamar',
'status_booking' => 'required|in:Pending,Dikonfirmasi,Dibatalkan',
'status_booking' => 'required|in:Pending,Dikonfirmasi,Dibatalkan,Selesai',
'tanggal_booking' => 'required|date',
'tanggal_checkin' => 'required|date|after_or_equal:tanggal_booking',
'tanggal_checkout' => 'required|date|after:tanggal_checkin',
@ -164,24 +165,29 @@ public function confirm($id_booking)
return redirect()->route('admin.booking')->with('success', 'Pemesanan berhasil dikonfirmasi.');
}
public function cancel($id_booking)
{
$booking = Booking::findOrFail($id_booking);
public function cancel($id_booking)
{
Log::info('Cancel function called for booking ID: ' . $id_booking);
// Pastikan status booking sudah dikonfirmasi sebelum bisa dibatalkan
if ($booking->status_booking == 'Dikonfirmasi') {
$booking->status_booking = 'Dibatalkan';
$booking->save();
$booking = Booking::findOrFail($id_booking);
// Perbarui status kamar menjadi 'tersedia' jika diperlukan
$room = $booking->room;
$room->status = 'tersedia';
$room->save();
// Ubah status booking menjadi Dibatalkan jika statusnya belum Selesai
if (in_array($booking->status_booking, ['Pending', 'Dikonfirmasi'])) {
$booking->update([
'status_booking' => 'Dibatalkan'
]);
// Update kamar jadi tersedia jika sebelumnya status booking dikonfirmasi
if ($booking->room && $booking->status_booking === 'Dikonfirmasi') {
$booking->room->update([
'status' => 'tersedia'
]);
}
return redirect()->route('admin.booking')->with('success', 'Booking berhasil dibatalkan.');
}
return redirect()->route('admin.booking')->with('success', 'Booking berhasil dibatalkan.');
}
public function approvePerpanjangan($id)
{
// Ambil data perpanjangan

View File

@ -32,16 +32,18 @@ public function index()
}
}
// Ambil booking pending untuk ditampilkan di tabel
$pendingBookings = Booking::where('status_booking', 'pending')->with('user', 'room')->get();
// Ambil booking pending + relasi transaction, user, room
$pendingBookings = Booking::with(['transaction', 'user', 'room'])
->where('status_booking', 'pending')
->get();
return view('admin.dashboard', compact(
'totalUsers',
'totalRooms',
'totalBookings',
'pendingBookings',
'confirmedBookings',
'daysLeftPerBooking'
return view('admin.dashboard', compact(
'totalUsers',
'totalRooms',
'totalBookings',
'pendingBookings',
'confirmedBookings',
'daysLeftPerBooking'
));
}

View File

@ -21,7 +21,7 @@ public function index(Request $request)
$query->where('status_transaksi', 'like', '%' . $request->search . '%');
}
$transaksi = $query->orderBy('tanggal_pembayaran', 'desc')->paginate(10);
$transaksi = $query->orderBy('tanggal_pembayaran', 'desc')->paginate(10);
return view('admin.transaksi', compact('transaksi'));
}

View File

@ -5,6 +5,7 @@
use App\Models\Booking;
use App\Models\Transaksi;
use App\Models\User;
use App\Models\Room;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
@ -64,4 +65,84 @@ public function showDetailPesanan($id_booking)
return view('users.detail-pesanan', compact('booking', 'pembayaran'));
}
// Menampilkan halaman form persetujuan dengan pengecekan
public function showApprovalForm()
{
$user = auth()->user();
if ($user->rental_approved) {
return redirect()->route('users.peta')->with('info', 'Anda sudah menyetujui persyaratan penyewaan.');
}
return view('users.approve_rental');
}
// Memproses form persetujuan dengan pengecekan
public function approveRental(Request $request)
{
/** @var \App\Models\User $user */
$user = Auth::user();
if ($user->rental_approved) {
return redirect()->route('users.peta')->with('info', 'Anda sudah menyetujui persyaratan penyewaan.');
}
$request->validate([
'id_card' => 'required|mimes:jpg,jpeg,png,pdf|max:2048',
'agree' => 'required',
]);
// Simpan file Kartu Identitas ke public/assets/users
if ($request->hasFile('id_card')) {
$file = $request->file('id_card');
$filename = time() . '_' . $file->getClientOriginalName();
// Pindahkan ke public/assets/users
$file->move(public_path('assets/users'), $filename);
// Simpan hanya nama file
$user->id_card_path = $filename;
}
// Update status persetujuan
$user->rental_approved = 1;
$user->save();
return redirect()->route('users.peta')->with('success', 'Persetujuan berhasil disimpan. Anda sekarang bisa melakukan penyewaan.');
}
public function showMap()
{
$user = auth()->user();
if (!$user->rental_approved) {
return redirect()->route('user.showApprovalForm')->with('warning', 'Silakan menyetujui persyaratan terlebih dahulu.');
}
// Ambil semua kamar
$rooms = Room::whereIn('status', ['tersedia', 'terisi', 'maintenance'])->get();
// Ambil booking user (jika ada)
$booking = Booking::where('id_user', $user->id_user)
->whereIn('status_booking', ['pending', 'dikonfirmasi'])
->orderBy('tanggal_booking', 'desc')
->first();
return view('users.peta', compact('rooms', 'booking'));
}
public function showDashboard()
{
$user = auth()->user();
if (!$user->rental_approved) {
return redirect()->route('user.showApprovalForm')->with('warning', 'Silakan menyetujui persyaratan terlebih dahulu.');
}
// Jika sudah approve, arahkan ke peta
return redirect()->route('users.peta');
}
}

View File

@ -39,4 +39,10 @@ public function room()
{
return $this->belongsTo(Room::class, 'id_kamar', 'id_kamar');
}
public function transaction()
{
return $this->hasOne(Transaksi::class, 'id_booking', 'id_booking');
}
}

View File

@ -22,17 +22,20 @@ class User extends Authenticatable
'email',
'password',
'role',
'reset_password', // Tambahkan kolom ini agar bisa diisi secara massal
'reset_password',
'id_card_path', // Tambahkan agar bisa diisi
'rental_approved', // Tambahkan agar bisa diisi
];
protected $hidden = [
'password',
'remember_token',
'reset_password', // Sembunyikan agar tidak terlihat ketika objek dikonversi ke JSON
'reset_password',
];
protected $casts = [
'email_verified_at' => 'datetime',
'rental_approved' => 'boolean', // Otomatis cast ke true/false
];
// Method untuk memeriksa peran pengguna
@ -42,7 +45,7 @@ public function hasRole($role)
}
public function bookings()
{
return $this->hasMany(Booking::class, 'id_user', 'id_user');
}
{
return $this->hasMany(Booking::class, 'id_user', 'id_user');
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

View File

@ -11,8 +11,8 @@
</a>
<form method="GET" action="{{ route('admin.booking') }}" class="d-flex">
<input type="text" name="search" class="form-control form-control-sm me-2"
placeholder="Cari booking..." value="{{ request()->search }}" style="max-width: 200px;">
<input type="text" name="search" class="form-control form-control-sm me-2" placeholder="Cari booking..."
value="{{ request()->search }}" style="max-width: 200px;">
<button type="submit" class="btn btn-outline-secondary btn-sm">Cari</button>
</form>
</div>
@ -42,16 +42,19 @@
<td>{{ \Carbon\Carbon::parse($booking->tanggal_checkout)->format('d-m-Y') }}</td>
<td>{{ ucfirst($booking->status_booking) }}</td>
<td>
<a href="{{ route('admin.editbooking', ['id_booking' => $booking->id_booking]) }}" class="text-warning">
<a href="{{ route('admin.editbooking', ['id_booking' => $booking->id_booking]) }}"
class="text-warning">
<i class="bi bi-pencil-square"></i>
</a>
<a href="{{ route('admin.deletebooking', ['id_booking' => $booking->id_booking]) }}" class="text-danger"
<a href="{{ route('admin.deletebooking', ['id_booking' => $booking->id_booking]) }}"
class="text-danger"
onclick="return confirm('Apakah Anda yakin ingin menghapus booking ini?');">
<i class="bi bi-trash-fill"></i>
</a>
@if ($booking->status_booking === 'Dikonfirmasi')
<a href="{{ route('admin.bookingselesai', $booking->id_booking) }}" class="btn btn-success btn-sm mt-1">
<a href="{{ route('admin.bookingselesai', $booking->id_booking) }}"
class="btn btn-success btn-sm mt-1">
Tandai Selesai
</a>
@endif
@ -59,9 +62,12 @@
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-3">
{{ $bookings->withQueryString()->links() }}
</div>
</div>
</div>
@endsection
@endsection

View File

@ -19,37 +19,57 @@
</form>
</div>
<!-- Tabel Data Customer -->
<div class="table-responsive">
<table class="table table-bordered text-center">
<thead class="table-primary">
<tr>
<th>No</th>
<th>Nama</th>
<th>Email</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($users as $index => $user)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
<a href="{{ route('admin.editcustomer', ['id_user' => $user->id_user]) }}" class="text-primary">
<i class="bi bi-pencil-square"></i>
</a>
<a href="{{ route('admin.deletecustomer', ['id_user' => $user->id_user]) }}" class="text-danger"
onclick="return confirm('Apakah Anda yakin ingin menghapus user ini?');">
<i class="bi bi-trash-fill"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<!-- Tabel Data Customer -->
<div class="table-responsive">
<table class="table table-bordered text-center">
<thead class="table-primary">
<tr>
<th>No</th>
<th>Nama</th>
<th>Email</th>
<th>Rental Approved</th>
<th>Card</th>
<th>Tanggal Daftar</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($users as $index => $user)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $user->name }}</td>
<td>{{ $user->email }}</td>
<td>
@if($user->rental_approved)
<span class="badge bg-success">Disetujui</span>
@else
<span class="badge bg-warning text-dark">Belum Disetujui</span>
@endif
</td>
<td>
@if($user->id_card_path)
<a href="{{ asset($user->id_card_path) }}" target="_blank" class="btn btn-sm btn-info text-white">
Lihat
</a>
@else
<span class="text-muted">Belum Upload</span>
@endif
</td>
<td>{{ $user->created_at ? $user->created_at->format('d-m-Y') : '-' }}</td>
<td>
<a href="{{ route('admin.editcustomer', ['id_user' => $user->id_user]) }}" class="text-primary me-2">
<i class="bi bi-pencil-square"></i>
</a>
<a href="{{ route('admin.deletecustomer', ['id_user' => $user->id_user]) }}" class="text-danger"
onclick="return confirm('Apakah Anda yakin ingin menghapus user ini?');">
<i class="bi bi-trash-fill"></i>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>

View File

@ -86,6 +86,8 @@
<th>Nama Customer</th>
<th>Kamar</th>
<th>Tanggal Pemesanan</th>
<th>Bukti Pembayaran</th>
<th>Foto Identitas</th>
<th>Status</th>
<th>Aksi</th>
</tr>
@ -101,24 +103,51 @@
-
{{ \Carbon\Carbon::parse($booking->tanggal_checkout)->format('d M Y') }}
</td>
<td>
@if($booking->transaction && $booking->transaction->bukti_pembayaran)
<a href="{{ asset($booking->transaction->bukti_pembayaran) }}" target="_blank">
<img src="{{ asset($booking->transaction->bukti_pembayaran) }}" alt="Bukti Pembayaran" class="img-thumbnail-hover"
style="max-width: 80px; max-height: 80px; object-fit: cover; border-radius: 5px; border: 1px solid #ccc;">
</a>
@else
<span class="text-muted">Belum Upload</span>
@endif
</td>
<td>
@if($booking->user && $booking->user->id_card_path)
<a href="{{ asset('assets/users/' . $booking->user->id_card_path) }}"
target="_blank">
<img src="{{ asset('assets/users/' . $booking->user->id_card_path) }}"
alt="ID Card" class="img-thumbnail-hover"
style="max-width: 80px; max-height: 80px; object-fit: cover; border-radius: 5px; border: 1px solid #ccc;">
</a>
@else
<span class="text-muted">Belum Upload</span>
@endif
</td>
<td>
<span class="badge bg-warning text-dark">Belum Dikonfirmasi</span>
</td>
<td class="flex gap-2 justify-start">
<!-- Tombol Konfirmasi -->
<form action="{{ route('admin.bookingconfirm', $booking->id_booking) }}" method="POST" class="flex items-center">
<form action="{{ route('admin.bookingconfirm', $booking->id_booking) }}"
method="POST" class="flex items-center mb-1">
@csrf
@method('PUT')
<button type="submit" class="btn btn-sm btn-success flex items-center gap-1">
<button type="submit"
class="btn btn-sm btn-success flex items-center gap-1">
<i class="bi bi-check-circle-fill"></i> Konfirmasi
</button>
</form>
<!-- Tombol Batalkan -->
<form action="{{ route('admin.bookingcancel', $booking->id_booking) }}" method="POST" class="flex items-center" onsubmit="return confirm('Apakah Anda yakin ingin membatalkan booking ini?')">
<form action="{{ route('admin.bookingcancel', $booking->id_booking) }}"
method="POST" class="flex items-center"
onsubmit="return confirm('Apakah Anda yakin ingin membatalkan booking ini?')">
@csrf
@method('PUT')
<button type="submit" class="btn btn-sm btn-danger flex items-center gap-1">
<button type="submit"
class="btn btn-sm btn-danger flex items-center gap-1">
<i class="bi bi-x-circle-fill"></i> Batalkan
</button>
</form>
@ -167,4 +196,4 @@
</div>
</div>
</div>
@endsection
@endsection

View File

@ -38,12 +38,26 @@
</thead>
<tbody>
@foreach($rooms as $room)
<tr>
<tr
@if($room->status == 'terisi')
class="table-danger"
@elseif($room->status == 'maintenance')
class="table-success"
@endif
>
<td>{{ ($rooms->currentPage() - 1) * $rooms->perPage() + $loop->iteration }}</td>
<td>{{ $room->room_number }}</td>
<td>{{ $room->room_type }}</td>
<td>Rp {{ number_format((int) $room->harga, 0, ',', '.') }}</td>
<td>{{ ucfirst($room->status) }}</td>
<td>
@if($room->status == 'terisi')
<span class="badge bg-danger">{{ ucfirst($room->status) }}</span>
@elseif($room->status == 'maintenance')
<span class="badge bg-success">{{ ucfirst($room->status) }}</span>
@else
<span class="badge bg-secondary">{{ ucfirst($room->status) }}</span>
@endif
</td>
<td>{{ $room->lantai }}</td>
<td>{{ $room->fasilitas }}</td>
<td>

View File

@ -48,10 +48,13 @@
</td>
<td>{{ \Carbon\Carbon::parse($item->tanggal_pembayaran)->format('d-m-Y H:i') }}</td>
<td>
<a href="{{ route('admin.edittransaksi', ['id_transaksi' => $item->id_transaksi]) }}" method="POST" enctype="multipart/form-data" class="text-warning">
<a href="{{ route('admin.edittransaksi', ['id_transaksi' => $item->id_transaksi]) }}"
method="POST" enctype="multipart/form-data" class="text-warning">
<i class="bi bi-pencil-square"></i>
</a>
<a href="{{ route('admin.deletetransaksi', ['id_transaksi' => $item->id_transaksi]) }}" class="text-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus transaksi ini?');">
<a href="{{ route('admin.deletetransaksi', ['id_transaksi' => $item->id_transaksi]) }}"
class="text-danger"
onclick="return confirm('Apakah Anda yakin ingin menghapus transaksi ini?');">
<i class="bi bi-trash-fill"></i>
</a>
</td>
@ -60,6 +63,9 @@
</tbody>
</table>
</div>
<div class="mt-3">
{{ $transaksi->withQueryString()->links() }}
</div>
</div>
</div>
@endsection
@endsection

View File

@ -0,0 +1,144 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Persetujuan Penyewaan | Kos Calista</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<!-- Bootstrap Icons -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css" rel="stylesheet" />
<style>
body {
background: linear-gradient(to right, #a1c4fd, #c2e9fb);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-family: 'Poppins', sans-serif;
}
.card {
max-width: 700px;
width: 100%;
border-radius: 20px;
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.1);
overflow: hidden;
background-color: #fff;
padding: 30px;
}
.card-header {
background: linear-gradient(to right, #4facfe, #00f2fe);
color: #fff;
padding: 20px;
text-align: center;
font-size: 1.5rem;
font-weight: bold;
letter-spacing: 1px;
}
.card-body p {
font-size: 1rem;
color: #333;
}
.card-body ul {
padding-left: 1.2rem;
}
.card-body ul li {
margin-bottom: 0.7rem;
color: #555;
}
.form-label {
font-weight: 600;
color: #444;
}
.btn-gradient {
background: linear-gradient(135deg, #4facfe, #00f2fe);
border: none;
color: #fff;
font-weight: 600;
padding: 12px;
border-radius: 50px;
transition: 0.3s ease;
}
.btn-gradient:hover {
opacity: 0.9;
transform: scale(1.02);
}
.form-check-label {
font-size: 0.95rem;
color: #444;
}
.text-muted {
font-size: 0.85rem;
}
@media (max-width: 576px) {
.card {
padding: 20px;
}
}
</style>
</head>
<body>
<div class="card">
<div class="card-header">
Persetujuan Penyewaan Kamar<br />
<small style="font-size: 0.9rem;">Kos Calista</small>
</div>
<div class="card-body mt-3">
<p>Dengan ini saya, sebagai calon penghuni <strong>Kos Calista</strong>, menyatakan bahwa saya telah membaca, memahami, dan menyetujui syarat dan ketentuan berikut:</p>
<ul>
<li>Saya bersedia memberikan data diri yang valid, termasuk <strong>kartu identitas resmi (KTP)</strong> yang masih berlaku untuk keperluan administrasi dan verifikasi.</li>
<li>Kartu identitas hanya digunakan oleh pengelola Kos Calista untuk keperluan verifikasi dan tidak akan disalahgunakan.</li>
<li>Saya bersedia menjaga ketertiban, keamanan, serta kebersihan lingkungan Kos Calista.</li>
<li>Saya bertanggung jawab atas penggunaan dan perawatan fasilitas kamar kos yang saya tempati.</li>
<li>Jika terjadi kerusakan akibat kelalaian pribadi, saya siap bertanggung jawab untuk memperbaiki atau mengganti sesuai ketentuan yang berlaku.</li>
<li>Saya tidak akan menggunakan kamar kos untuk kegiatan yang melanggar hukum atau norma yang berlaku.</li>
<li>Semua informasi yang saya berikan adalah benar dan dapat dipertanggungjawabkan. Jika terbukti memberikan data palsu, saya siap menerima sanksi dari pengelola Kos Calista.</li>
</ul>
<form method="POST" action="{{ route('user.approveRental') }}" enctype="multipart/form-data" class="mt-4">
@csrf
<!-- Upload Kartu Identitas -->
<div class="mb-3">
<label for="id_card" class="form-label">Upload Foto Kartu Identitas (KTP) *</label>
<input type="file" name="id_card" id="id_card" class="form-control" required>
<small class="text-muted">Format JPG, PNG, atau PDF. Maksimal 2MB.</small>
</div>
<!-- Checkbox persetujuan -->
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" name="agree" id="agree" required>
<label class="form-check-label" for="agree">
Saya menyetujui semua syarat dan ketentuan di atas.
</label>
</div>
<!-- Tombol Submit -->
<div class="d-grid">
<button type="submit" class="btn btn-gradient">
<i class="bi bi-check-circle me-2"></i> Setuju & Lanjutkan
</button>
</div>
</form>
</div>
</div>
<!-- Bootstrap JS (optional) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

View File

@ -11,7 +11,12 @@
<div class="w-full max-w-3xl bg-white rounded-2xl shadow-2xl overflow-hidden border border-blue-100">
<div class="p-8">
<h2 class="text-3xl font-bold text-blue-800 mb-6 border-b-2 border-blue-200 pb-2 flex items-center">
🧾 <span class="ml-2">Detail Pesanan</span>
<!-- Ganti emoji 🧾 dengan SVG icon -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 17v-2a4 4 0 00-4-4H4m0 0V9m0 4h4m5 5h6a2 2 0 002-2V7a2 2 0 00-2-2h-6m-2 0h-.01M9 21h6a2 2 0 002-2v-2H9v4z" />
</svg>
<span class="ml-2">Detail Pesanan</span>
</h2>
@if (session('success'))
@ -28,14 +33,27 @@
<div>
<p class="text-gray-600 font-semibold">📌 Status Pemesanan:</p>
<p class="text-indigo-700 font-bold text-lg">{{ $booking->status_booking }}</p>
@if ($booking->status_booking === 'Dibatalkan')
<p class="mt-3 text-red-600 font-semibold">
⚠️ Pesanan dibatalkan. Untuk pengembalian uang, silakan hubungi nomor berikut: <br>
<a href="https://wa.me/6285940949841" target="_blank" class="text-green-600 underline">
0859-4094-9841
</a>
</p>
@endif
</div>
<div>
<p class="text-gray-600 font-semibold">📅 Tanggal Check-In:</p>
<p class="text-gray-900">{{ $booking->tanggal_checkin }}</p>
<p class="text-gray-900">
{{ \Carbon\Carbon::parse($booking->tanggal_checkin)->format('d-m-Y') }}
</p>
</div>
<div>
<p class="text-gray-600 font-semibold">📅 Tanggal Check-Out:</p>
<p class="text-gray-900">{{ $booking->tanggal_checkout }}</p>
<p class="text-gray-900">
{{ \Carbon\Carbon::parse($booking->tanggal_checkout)->format('d-m-Y') }}
</p>
</div>
</div>
@ -48,9 +66,8 @@
@if ($pembayaran->bukti_pembayaran)
<div class="mt-4">
<p class="font-semibold text-gray-700 mb-2">🖼️ Bukti Pembayaran:</p>
<img src="{{ asset($pembayaran->bukti_pembayaran) }}"
alt="Bukti Pembayaran"
class="w-full max-h-[400px] object-contain rounded-lg border border-gray-300 shadow-md">
<img src="{{ asset($pembayaran->bukti_pembayaran) }}" alt="Bukti Pembayaran"
class="w-full max-h-[400px] object-contain rounded-lg border border-gray-300 shadow-md">
</div>
@endif
</div>
@ -62,9 +79,9 @@ class="w-full max-h-[400px] object-contain rounded-lg border border-gray-300 sha
<div class="text-right">
<a href="{{ route('users.peta') }}"
class="inline-flex items-center bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-600 hover:to-blue-800 text-white px-6 py-2 rounded-full transition-all shadow-md hover:shadow-lg">
Kembali ke Beranda
</a>
class="inline-flex items-center bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-600 hover:to-blue-800 text-white px-6 py-2 rounded-full transition-all shadow-md hover:shadow-lg">
&larr; Kembali ke Beranda
</a>
</div>
</div>
</div>

View File

@ -5,6 +5,8 @@
<meta charset="UTF-8">
<title>Detail Kamar - {{ $room->room_number }}</title>
<script src="https://cdn.tailwindcss.com"></script>
<!-- Masukkan di dalam <head> -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
</head>
<body class="min-h-screen flex flex-col bg-gradient-to-b from-blue-400">
@ -51,42 +53,40 @@ class="{{ $room->status == 'tersedia' ? 'text-green-600' : ($room->status == 'te
@endif
@if (!empty($room->deskripsi))
@php
// Pisahkan berdasarkan dua bagian utama: 'Fasilitas umum :' dan 'Aturan di Kos Calista'
$fasilitas = '';
$aturan = '';
if (preg_match('/Fasilitas umum\s*:\s*(.+?)\s*Aturan di Kos Calista\s*/s', $room->deskripsi, $match)) {
$fasilitas = trim($match[1]);
}
if (preg_match('/Aturan di Kos Calista\s*(.+)/s', $room->deskripsi, $match)) {
$aturan = trim($match[1]);
}
// Ambil item berdasarkan pola angka di depan (1. xxx 2. xxx ...)
preg_match_all('/\d+\.\s*([^0-9]+)/', $fasilitas, $fasilitasList);
preg_match_all('/\d+\.\s*([^0-9]+)/', $aturan, $aturanList);
@endphp
<div class="mb-4">
<h3 class="text-md font-semibold text-gray-800 mb-1">Fasilitas Umum:</h3>
<ul class="list-disc pl-5 text-gray-700 text-sm leading-relaxed">
@foreach ($fasilitasList[1] as $item)
<li>{{ trim($item) }}</li>
@endforeach
</ul>
</div>
<div class="mb-4">
<h3 class="text-md font-semibold text-gray-800 mb-1">Aturan di Kos Calista:</h3>
<ul class="list-decimal pl-5 text-gray-700 text-sm leading-relaxed">
@foreach ($aturanList[1] as $item)
<li>{{ trim($item) }}</li>
@endforeach
</ul>
</div>
@endif
@php
$fasilitas = '';
$aturan = '';
if (preg_match('/Fasilitas umum\s*:\s*(.+?)\s*Aturan di Kos Calista\s*/s', $room->deskripsi, $match)) {
$fasilitas = trim($match[1]);
}
if (preg_match('/Aturan di Kos Calista\s*(.+)/s', $room->deskripsi, $match)) {
$aturan = trim($match[1]);
}
preg_match_all('/\d+\.\s*([^0-9]+)/', $fasilitas, $fasilitasList);
preg_match_all('/\d+\.\s*([^0-9]+)/', $aturan, $aturanList);
@endphp
<div class="mb-4">
<h3 class="text-md font-semibold text-gray-800 mb-1">Fasilitas Umum:</h3>
<ul class="list-disc pl-5 text-gray-700 text-sm leading-relaxed">
@foreach ($fasilitasList[1] as $item)
<li>{{ trim($item) }}</li>
@endforeach
</ul>
</div>
<div class="mb-4">
<h3 class="text-md font-semibold text-gray-800 mb-1">Aturan di Kos Calista:</h3>
<ul class="list-decimal pl-5 text-gray-700 text-sm leading-relaxed">
@foreach ($aturanList[1] as $item)
<li>{{ trim($item) }}</li>
@endforeach
</ul>
</div>
@endif
<div class="mt-6">
<a href="{{ route('users.peta') }}"
@ -100,6 +100,7 @@ class="inline-block bg-gray-300 hover:bg-gray-400 text-gray-800 font-medium px-5
<!-- Bagian Kanan: Form Booking -->
@if ($room->status == 'tersedia')
<!-- FORMULIR BOOKING -->
<div class="w-full md:w-1/3 mt-10 md:mt-0">
<div class="bg-gray-100 p-6 rounded-lg shadow-md">
<h3 class="text-xl font-bold text-gray-800 mb-6">Formulir Booking</h3>
@ -125,51 +126,36 @@ class="w-full bg-gray-100 border border-gray-300 rounded-lg px-4 py-2 cursor-not
<div>
<label for="tanggal_checkin" class="block text-gray-700 font-medium mb-1">Tanggal
Check-in</label>
<input type="date" id="tanggal_checkin" name="tanggal_checkin" required
<input type="text" id="tanggal_checkin" name="tanggal_checkin" required
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400"
placeholder="DD/MM/YYYY">
</div>
<div>
<label for="durasi" class="block text-gray-700 font-medium mb-1">Durasi Sewa (bulan)</label>
<select id="durasi" name="durasi" required
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400">
@for ($i = 1; $i <= 12; $i++)
<option value="{{ $i }}">{{ $i }} Bulan</option>
@endfor
</select>
</div>
<div>
<label for="tanggal_checkout" class="block text-gray-700 font-medium mb-1">Tanggal
Check-out</label>
<input type="date" id="tanggal_checkout" name="tanggal_checkout" required
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400">
<p id="error-message" class="text-red-500 text-sm mt-1 hidden">Tanggal Check-out harus sama
dengan tanggal Check-in!</p>
<input type="text" id="tanggal_checkout" name="tanggal_checkout" readonly required
class="w-full bg-gray-100 border border-gray-300 rounded-lg px-4 py-2 cursor-not-allowed"
placeholder="DD/MM/YYYY">
<p id="formatted_checkout" class="text-sm text-gray-600 mt-1"></p>
</div>
<script>
const checkinInput = document.getElementById('tanggal_checkin');
const checkoutInput = document.getElementById('tanggal_checkout');
const errorMessage = document.getElementById('error-message');
checkoutInput.addEventListener('change', function () {
const checkinDate = new Date(checkinInput.value);
const checkoutDate = new Date(checkoutInput.value);
// Mendapatkan hanya tanggal (day) dari tanggal check-in dan check-out
const checkinDay = checkinDate.getDate();
const checkoutDay = checkoutDate.getDate();
// Validasi apakah tanggal checkout tidak sama dengan tanggal checkin
if (checkoutDay !== checkinDay) {
errorMessage.classList.remove('hidden'); // Menampilkan pesan error
checkoutInput.setCustomValidity("Tanggal Check-out harus sama dengan tanggal Check-in.");
}
else {
errorMessage.classList.add('hidden'); // Menyembunyikan pesan error
checkoutInput.setCustomValidity(""); // Menghapus validasi custom
}
});
</script>
<div class="pt-4">
<button type="submit"
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 rounded-lg transition">
Sewa Sekarang
Booking
</button>
</div>
</form>
</div>
</div>
@ -179,6 +165,71 @@ class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 rounde
</div>
</div>
<!-- Flatpickr JS -->
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script>
const checkinInput = document.getElementById('tanggal_checkin');
const durasiInput = document.getElementById('durasi');
const checkoutInput = document.getElementById('tanggal_checkout');
const formattedCheckout = document.getElementById('formatted_checkout');
flatpickr("#tanggal_checkin", {
altInput: true,
altFormat: "d/m/Y",
dateFormat: "Y-m-d",
defaultDate: new Date(),
onChange: updateCheckoutDate
});
flatpickr("#tanggal_checkout", {
altInput: true,
altFormat: "d/m/Y",
dateFormat: "Y-m-d",
clickOpens: false
});
function updateCheckoutDate() {
const checkinValue = checkinInput.value;
const durasi = parseInt(durasiInput.value);
const parts = checkinValue.split('-'); // karena sudah Y-m-d
if (parts.length === 3) {
const year = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10) - 1;
const day = parseInt(parts[2], 10);
const checkinDate = new Date(year, month, day);
const checkoutDate = new Date(checkinDate);
const checkinDay = checkoutDate.getDate();
checkoutDate.setMonth(checkoutDate.getMonth() + durasi);
if (checkoutDate.getDate() !== checkinDay) {
checkoutDate.setDate(0);
}
const dd = String(checkoutDate.getDate()).padStart(2, '0');
const mm = String(checkoutDate.getMonth() + 1).padStart(2, '0');
const yyyy = checkoutDate.getFullYear();
const formattedForServer = `${yyyy}-${mm}-${dd}`;
const formattedForDisplay = `${dd}/${mm}/${yyyy}`;
checkoutInput._flatpickr.setDate(formattedForServer);
formattedCheckout.textContent = `Tanggal Check-out: ${formattedForDisplay}`;
}
}
// Jalankan update pertama kali saat load halaman
document.addEventListener('DOMContentLoaded', function() {
updateCheckoutDate();
});
// Update saat durasi diubah
durasiInput.addEventListener('change', updateCheckoutDate);
</script>
</body>

View File

@ -109,7 +109,7 @@
<h2 class="section-title">Galeri Kos Calista</h2>
<div class="text-center mb-4">
<a href="/home" class="btn btn-gradient">
<a href="{{ route('users.home') }}" class="btn btn-gradient">
<i class="bi bi-images me-2"></i> Kembali
</a>
</div>

View File

@ -102,7 +102,7 @@
<div class="container">
<div class="header">
<h2 style="color:#3294DDCC; font-size: 28px; font-weight: bold;">Galeri Kos Calista</h2>
<a href="/galeri" class="btn btn-custom1">
<a href="{{ route('users.galeri') }}" class="btn btn-custom1">
Lihat Semua <i class="bi bi-arrow-right"></i>
</a>
</div>
@ -184,7 +184,7 @@
<div class="contact-details">
<p><i class="fas fa-map-marker-alt fa-fw"></i> Jl. Mastrip Blk. H / Blk. I No.14, Krajan Timur,
Sumbersari, Kec. Sumbersari, Kabupaten Jember, Jawa Timur 68121</p>
<p><i class="fas fa-phone fa-fw"></i> 0857-9043-3661</p>
<p><i class="fas fa-phone fa-fw"></i> 0859-4094-9841</p>
<p><i class="fas fa-envelope fa-fw"></i> Kostcalista@gmail.com</p>
</div>

View File

@ -36,13 +36,13 @@
<!-- Tanggal Check-In -->
<div>
<label class="block text-gray-700 font-medium mb-1">Tanggal Check-In</label>
<p class="text-gray-800">{{ $booking->tanggal_checkin }}</p>
<p class="text-gray-800">{{ \Carbon\Carbon::parse($booking->tanggal_checkin)->format('d-m-Y') }}</p>
</div>
<!-- Tanggal Check-Out -->
<div>
<label class="block text-gray-700 font-medium mb-1">Tanggal Check-Out</label>
<p class="text-gray-800">{{ $booking->tanggal_checkout }}</p>
<p class="text-gray-800">{{ \Carbon\Carbon::parse($booking->tanggal_checkout)->format('d-m-Y') }}</p>
</div>
<div class="mt-4">

View File

@ -95,7 +95,7 @@
<body>
<div class="form-container">
<h2>Perpanjang Masa Sewa</h2>
<form action="/perpanjang/{{ $booking->id_booking }}" method="POST" enctype="multipart/form-data">
<form action="{{ route('users.perpanjangan-sewa', $booking->id_booking) }}" method="POST" enctype="multipart/form-data">
@csrf
<div class="form-group">
@ -117,17 +117,23 @@
<div class="form-group">
<label>Tanggal Check-out Lama:</label>
<p>{{ $booking->tanggal_checkout }}</p>
</div>
<div class="form-group">
<label for="tanggal_checkout_baru">Tanggal Check-out Baru</label>
<input type="date" name="tanggal_checkout_baru" class="form-control" required>
<p>{{ \Carbon\Carbon::parse($booking->tanggal_checkout)->format('d-m-Y') }}</p>
</div>
<div class="form-group">
<label for="durasi_bulan">Durasi Perpanjangan (bulan)</label>
<input type="number" name="durasi_bulan" id="durasi_bulan" class="form-control" min="1" required>
<select name="durasi_bulan" id="durasi_bulan" class="form-control" required>
<option value="">-- Pilih Durasi --</option>
@for ($i = 1; $i <= 12; $i++)
<option value="{{ $i }}">{{ $i }} Bulan</option>
@endfor
</select>
</div>
<!-- Tanggal Check-out Baru (otomatis) -->
<div class="form-group">
<label for="tanggal_checkout_baru">Tanggal Check-out Baru</label>
<input type="text" name="tanggal_checkout_baru" id="tanggal_checkout_baru" class="form-control" readonly required>
</div>
<div class="form-group">
@ -175,55 +181,82 @@
<!-- Tombol -->
<div id="button_group" class="button-group hidden">
<a href="/petakos" class="btn btn-secondary w-50">Kembali</a>
<a href="{{ route('users.peta') }}" class="btn btn-secondary">Kembali</a>
<button type="submit" class="btn btn-primary w-50">Kirim Permintaan</button>
</div>
</form>
</div>
<script>
const hargaPerBulan = parseInt(document.getElementById('harga_per_bulan').dataset.harga);
const durasiInput = document.getElementById('durasi_bulan');
const totalBiayaText = document.getElementById('total_biaya');
const inputTotalBiaya = document.getElementById('input_total_biaya');
<!-- SCRIPT -->
<script>
const hargaPerBulan = parseInt(document.getElementById('harga_per_bulan').dataset.harga);
const durasiInput = document.getElementById('durasi_bulan');
const totalBiayaText = document.getElementById('total_biaya');
const inputTotalBiaya = document.getElementById('input_total_biaya');
const tanggalCheckoutBaruInput = document.getElementById('tanggal_checkout_baru');
durasiInput.addEventListener('input', function () {
const bulan = parseInt(this.value);
const total = bulan * hargaPerBulan;
// Ambil tanggal checkout lama dari blade
const tanggalCheckoutLamaStr = '{{ $booking->tanggal_checkout }}';
const tanggalCheckoutLama = new Date(tanggalCheckoutLamaStr);
if (!isNaN(total)) {
totalBiayaText.textContent = 'Rp ' + total.toLocaleString();
inputTotalBiaya.value = total;
}
});
durasiInput.addEventListener('input', function () {
const bulan = parseInt(this.value);
const total = bulan * hargaPerBulan;
const metodeSelect = document.getElementById('metode_pembayaran');
const transferInfo = document.getElementById('transfer_info');
const ewalletInfo = document.getElementById('ewallet_info');
const buktiSection = document.getElementById('bukti_pembayaran_section');
const buttonGroup = document.getElementById('button_group');
// Hitung total biaya
if (!isNaN(total)) {
totalBiayaText.textContent = 'Rp ' + total.toLocaleString();
inputTotalBiaya.value = total;
}
metodeSelect.addEventListener('change', function () {
const selected = this.value;
// Hitung tanggal checkout baru
if (!isNaN(bulan)) {
const newDate = new Date(tanggalCheckoutLama);
newDate.setMonth(newDate.getMonth() + bulan);
// Reset semua dulu
transferInfo.classList.add('hidden');
ewalletInfo.classList.add('hidden');
buktiSection.classList.add('hidden');
buttonGroup.classList.add('hidden');
// Format tanggal ke DD-MM-YYYY
const year = newDate.getFullYear();
const month = String(newDate.getMonth() + 1).padStart(2, '0');
const day = String(newDate.getDate()).padStart(2, '0');
const formattedDate = `${day}-${month}-${year}`;
tanggalCheckoutBaruInput.value = formattedDate;
} else {
tanggalCheckoutBaruInput.value = '';
}
});
// Metode pembayaran handler
const metodeSelect = document.getElementById('metode_pembayaran');
const transferInfo = document.getElementById('transfer_info');
const ewalletInfo = document.getElementById('ewallet_info');
const buktiSection = document.getElementById('bukti_pembayaran_section');
const buttonGroup = document.getElementById('button_group');
metodeSelect.addEventListener('change', function () {
const selected = this.value;
// Reset semua dulu
transferInfo.classList.add('hidden');
ewalletInfo.classList.add('hidden');
buktiSection.classList.add('hidden');
buttonGroup.classList.add('hidden');
// Tampilkan sesuai pilihan
if (selected === 'Transfer') {
transferInfo.classList.remove('hidden');
buktiSection.classList.remove('hidden');
buttonGroup.classList.remove('hidden');
} else if (selected === 'E-Wallet') {
ewalletInfo.classList.remove('hidden');
buktiSection.classList.remove('hidden');
buttonGroup.classList.remove('hidden');
} else if (selected === 'Tunai') {
buttonGroup.classList.remove('hidden');
}
});
</script>
// Tampilkan sesuai pilihan
if (selected === 'Transfer') {
transferInfo.classList.remove('hidden');
buktiSection.classList.remove('hidden');
buttonGroup.classList.remove('hidden');
} else if (selected === 'E-Wallet') {
ewalletInfo.classList.remove('hidden');
buktiSection.classList.remove('hidden');
buttonGroup.classList.remove('hidden');
} else if (selected === 'Tunai') {
buttonGroup.classList.remove('hidden');
}
});
</script>
</body>
</html>
</html>

View File

@ -11,78 +11,84 @@
<body class="bg-gradient-to-br from-blue-400 to-white min-h-screen flex items-center justify-center p-6 font-sans">
<div class="max-w-6xl mx-auto py-6 px-4">
<!-- Header -->
<header class="bg-black text-white px-6 py-4 rounded-lg flex justify-between items-center shadow-md">
<h1 class="text-2xl font-bold">Kos Calista</h1>
<!-- Header -->
<header class="bg-black text-white px-6 py-4 rounded-lg flex justify-between items-center shadow-md">
<h1 class="text-2xl font-bold">Kos Calista</h1>
<div class="flex items-center gap-6">
<div class="flex items-center gap-6">
{{-- Notifikasi sisa masa booking --}}
@isset($daysLeft)
@if ($daysLeft > 0)
<div class="bg-yellow-400 text-black px-4 py-1 rounded text-sm font-medium">
Sisa booking: <strong>{{ $daysLeft }} hari</strong>
</div>
@elseif ($daysLeft === 0)
<div class="bg-red-500 text-white px-4 py-1 rounded text-sm font-medium">
Hari ini <strong>terakhir</strong> masa booking!
</div>
@else
<div class="bg-gray-600 text-white px-4 py-1 rounded text-sm font-medium">
Masa booking sudah <strong>berakhir</strong>
</div>
@endif
@endisset
<i class="fa fa-female text-2xl"></i>
<!-- Dropdown -->
<div class="relative group">
<button class="bg-white text-blue-800 font-semibold px-4 py-2 rounded shadow hover:bg-gray-100 transition">
Menu
</button>
<div class="absolute right-0 mt-2 w-44 bg-white border border-gray-200 rounded shadow-md opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-10">
@isset($booking)
<a href="{{ route('users.detail-pesanan', ['id_booking' => $booking->id_booking]) }}"
class="block px-4 py-2 text-black hover:bg-gray-100">
Detail Pesanan
</a>
<a href="{{ route('users.perpanjangan-sewa', ['id_booking' => $booking->id_booking]) }}"
class="block px-4 py-2 text-black hover:bg-gray-100">
Perpanjang Sewa
</a>
@else
<span class="block px-4 py-2 text-gray-400 cursor-not-allowed">
Detail Pesanan
</span>
{{-- Notifikasi sisa masa booking --}}
@isset($daysLeft)
@if ($daysLeft > 0)
<div class="bg-yellow-400 text-black px-4 py-1 rounded text-sm font-medium">
Sisa booking: <strong>{{ $daysLeft }} hari</strong>
</div>
@elseif ($daysLeft === 0)
<div class="bg-red-500 text-white px-4 py-1 rounded text-sm font-medium">
Hari ini <strong>terakhir</strong> masa booking!
</div>
@else
<div class="bg-gray-600 text-white px-4 py-1 rounded text-sm font-medium">
Masa booking sudah <strong>berakhir</strong>
</div>
@endif
@endisset
<a href="{{ route('users.profile') }}" class="block px-4 py-2 text-black hover:bg-gray-100">
Profile
</a>
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="w-full text-left px-4 py-2 text-black hover:bg-gray-100">
Logout
<i class="fa fa-female text-2xl"></i>
<!-- Dropdown -->
<div class="relative group">
<button
class="bg-white text-blue-800 font-semibold px-4 py-2 rounded shadow hover:bg-gray-100 transition">
Menu
</button>
</form>
<div
class="absolute right-0 mt-2 w-44 bg-white border border-gray-200 rounded shadow-md opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 z-10">
@isset($booking)
<a href="{{ route('users.detail-pesanan', ['id_booking' => $booking->id_booking]) }}"
class="block px-4 py-2 text-black hover:bg-gray-100">
Detail Pesanan
</a>
<a href="{{ route('users.perpanjangan-sewa', ['id_booking' => $booking->id_booking]) }}"
class="block px-4 py-2 text-black hover:bg-gray-100">
Perpanjang Sewa
</a>
@else
<span class="block px-4 py-2 text-gray-400 cursor-not-allowed">
Detail Pesanan
</span>
@endisset
<a href="{{ route('users.profile') }}" class="block px-4 py-2 text-black hover:bg-gray-100">
Profile
</a>
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit" class="w-full text-left px-4 py-2 text-black hover:bg-gray-100">
Logout
</button>
</form>
</div>
</div>
</div>
</div>
</div>
</header>
</header>
<!-- Denah Kos -->
<section class="mt-8 bg-white p-6 rounded-lg shadow-lg">
<h2 class="text-2xl font-semibold text-center text-blue-800 mb-4">📍 Denah Kos</h2>
<h2 class="text-2xl font-semibold text-center text-blue-800 mb-4">?? Denah Kos</h2>
<div class="relative overflow-hidden rounded-lg">
<div id="slider" class="flex transition-transform duration-500 ease-in-out w-full">
<img src="{{ asset('assets/peta/1.png') }}" class="w-full object-contain flex-shrink-0" alt="Denah 1">
<img src="{{ asset('assets/peta/2.png') }}" class="w-full object-contain flex-shrink-0" alt="Denah 2">
<img src="{{ asset('assets/peta/1.png') }}" class="w-full object-contain flex-shrink-0"
alt="Denah 1">
<img src="{{ asset('assets/peta/2.png') }}" class="w-full object-contain flex-shrink-0"
alt="Denah 2">
</div>
</div>
<div class="mt-4 flex justify-center gap-3">
<button onclick="slideTo(0)" class="w-10 h-10 bg-blue-600 hover:bg-blue-700 text-white rounded-full">1</button>
<button onclick="slideTo(1)" class="w-10 h-10 bg-blue-600 hover:bg-blue-700 text-white rounded-full">2</button>
<button onclick="slideTo(0)"
class="w-10 h-10 bg-blue-600 hover:bg-blue-700 text-white rounded-full">1</button>
<button onclick="slideTo(1)"
class="w-10 h-10 bg-blue-600 hover:bg-blue-700 text-white rounded-full">2</button>
</div>
</section>
@ -93,44 +99,64 @@ function slideTo(index) {
}
</script>
<!-- Daftar Kamar -->
<section class="mt-10">
<h2 class="text-2xl font-semibold text-blue-800 mb-4">🛏️ Daftar Kamar</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
@foreach($rooms as $room)
<a href="{{ $room->status === 'tersedia' ? route('users.detail_kamar', $room->id_kamar) : '#' }}"
class="block">
<div class="relative bg-white p-4 rounded-lg shadow-md hover:shadow-lg transition
{{ $room->status !== 'tersedia' ? 'opacity-60 pointer-events-none' : '' }}">
<!-- Daftar Kamar -->
<section class="mt-10">
<h2 class="text-2xl font-semibold text-blue-800 mb-4">??? Daftar Kamar</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">
@foreach($rooms as $room)
@php
$isDisabled = isset($booking); // User sudah booking kamar lain?
$isBookedRoom = isset($booking) && $booking->id_kamar == $room->id_kamar;
@endphp
<!-- Overlay jika terisi atau diperbaiki -->
@if($room->status === 'terisi')
<div class="absolute inset-0 flex items-center justify-center bg-red-200 bg-opacity-70 rounded-lg z-10">
<i class="fas fa-times-circle text-red-600 text-4xl"></i>
</div>
@elseif($room->status === 'diperbaiki')
<div class="absolute top-2 right-2 bg-yellow-500 text-white text-xs px-2 py-1 rounded shadow z-10">
Diperbaiki
</div>
@endif
<a href="{{ (!$isDisabled && $room->status === 'tersedia') ? route('users.detail_kamar', $room->id_kamar) : '#' }}"
class="block">
<img src="{{ asset('assets/admin/' . $room->foto) }}"
class="w-full h-40 object-cover rounded-lg shadow">
<h3 class="font-bold mt-2 text-lg">{{ $room->room_number }} - {{ $room->room_type }}</h3>
<p class="text-gray-700 font-semibold">Rp {{ number_format($room->harga, 2, ',', '.') }}</p>
<p class="text-sm {{
$room->status == 'tersedia' ? 'text-green-600' :
($room->status == 'terisi' ? 'text-red-600' : 'text-yellow-600') }}">
{{ ucfirst($room->status) }}
</p>
<p class="text-xs text-gray-500">Lantai: {{ $room->lantai }}</p>
<p class="text-xs text-gray-500">{{ Str::limit($room->deskripsi, 50) }}</p>
<div class="relative bg-white p-4 rounded-lg shadow-md hover:shadow-lg transition transform hover:scale-105
{{ $room->status !== 'tersedia' || ($isDisabled && !$isBookedRoom) ? 'opacity-60' : '' }}
{{ $isBookedRoom ? 'border-4 border-green-500 animate-pulse' : '' }}">
{{-- Overlay kondisi kamar --}}
@if($room->status === 'terisi')
<div class="absolute inset-0 flex items-center justify-center bg-red-200 bg-opacity-70 rounded-lg z-10">
<i class="fas fa-times-circle text-red-600 text-4xl"></i>
</div>
</a>
@endforeach
</div>
</section>
@elseif($room->status === 'diperbaiki')
<div class="absolute top-2 right-2 bg-yellow-500 text-white text-xs px-2 py-1 rounded shadow z-10">
Diperbaiki
</div>
@elseif($isDisabled && !$isBookedRoom)
<div class="absolute inset-0 flex items-center justify-center bg-gray-200 bg-opacity-70 rounded-lg z-10 text-center p-2 text-sm font-medium text-gray-700">
Anda sudah memesan kamar
</div>
@endif
{{-- Label jika kamar ini milik user --}}
@if($isBookedRoom)
<div class="absolute top-2 left-2 bg-green-600 text-white text-xs px-2 py-1 rounded shadow z-10">
Kamar Anda
</div>
@endif
<img src="{{ asset('assets/admin/' . $room->foto) }}"
class="w-full h-40 object-cover rounded-lg shadow">
<h3 class="font-bold mt-2 text-lg">{{ $room->room_number }} - {{ $room->room_type }}</h3>
<p class="text-gray-700 font-semibold">Rp {{ number_format($room->harga, 2, ',', '.') }}</p>
<p class="text-sm {{
$room->status == 'tersedia' ? 'text-green-600' :
($room->status == 'terisi' ? 'text-red-600' : 'text-yellow-600') }}">
{{ ucfirst($room->status) }}
</p>
<p class="text-xs text-gray-500">Lantai: {{ $room->lantai }}</p>
<p class="text-xs text-gray-500">{{ Str::limit($room->deskripsi, 50) }}</p>
</div>
</a>
@endforeach
</div>
</section>
</div>
</body>
</html>
</html>

View File

@ -115,25 +115,25 @@
</div>
<ul class="nav flex-column">
<li class="nav-item">
<a href="/dashboard-admin" class="nav-link"><i class="bi bi-speedometer2"></i><span>Dashboard</span></a>
<a href="{{ route('admin.dashboard') }}" class="nav-link"><i class="bi bi-speedometer2"></i><span>Dashboard</span></a>
</li>
<li class="nav-item">
<a href="/customer" class="nav-link"><i class="bi bi-people"></i><span>Data Customer</span></a>
<a href="{{ route('admin.customer') }}" class="nav-link"><i class="bi bi-people"></i><span>Data Customer</span></a>
</li>
<li class="nav-item">
<a href="/rooms" class="nav-link"><i class="bi bi-door-closed"></i><span>Data Kamar</span></a>
<a href="{{ route('admin.rooms') }}" class="nav-link"><i class="bi bi-door-closed"></i><span>Data Kamar</span></a>
</li>
<li class="nav-item">
<a href="/booking" class="nav-link"><i class="bi bi-calendar-check"></i><span>Data Booking</span></a>
<a href="{{ route('admin.booking') }}" class="nav-link"><i class="bi bi-calendar-check"></i><span>Data Booking</span></a>
</li>
<li class="nav-item">
<a href="/transaksi" class="nav-link"><i class="bi bi-cash-stack"></i><span>Data Transaksi</span></a>
<a href="{{ route('admin.transaksi') }}" class="nav-link"><i class="bi bi-cash-stack"></i><span>Data Transaksi</span></a>
</li>
<li class="nav-item">
<a href="/expense" class="nav-link"><i class="bi bi-wallet2"></i><span>Pengeluaran</span></a>
<a href="{{ route('admin.expense') }}" class="nav-link"><i class="bi bi-wallet2"></i><span>Pengeluaran</span></a>
</li>
<li class="nav-item">
<a href="/keuangan" class="nav-link"><i class="bi bi-credit-card"></i><span>Laporan Keuangan</span></a>
<a href="{{ route('admin.keuangan') }}" class="nav-link"><i class="bi bi-credit-card"></i><span>Laporan Keuangan</span></a>
</li>
</ul>
</div>

View File

@ -99,10 +99,10 @@
</div>
<ul class="nav flex-column">
<li class="nav-item">
<a href="/dashboard_pemilik" class="nav-link"><i class="bi bi-speedometer2"></i><span>Dashboard</span></a>
<a href="{{ route('dashboard_pemilik') }}" class="nav-link"><i class="bi bi-speedometer2"></i><span>Dashboard</span></a>
</li>
<li class="nav-item">
<a href="/laporan" class="nav-link"><i class="bi bi-people"></i><span>Laporan</span></a>
<a href="{{ route('laporan') }}" class="nav-link"><i class="bi bi-people"></i><span>Laporan</span></a>
</li>
</ul>
</div>

View File

@ -15,7 +15,8 @@
<a href="#layanan" class="text-white me-3 fw-bold text-decoration-none">Layanan</a>
<a href="#galeri" class="text-white me-3 fw-bold text-decoration-none">Galeri</a>
<a href="#contact" class="text-white me-3 fw-bold text-decoration-none">Kontak</a>
<a href="#" class="text-white fw-bold text-decoration-none">Masuk</a>
<a href="{{ route('login') }}" class="btn fw-bold masuk-button">Masuk</a>
</div>
</div>
<p class="mt-5">Create by Diana.</p>

View File

@ -23,15 +23,16 @@
<!-- Tombol Daftar & Masuk -->
<div class="d-lg-none d-flex flex-column align-items-center mt-3">
<a href="/register" class="nav-link text-white">DAFTAR</a>
<a href="/login" class="btn fw-bold masuk-button mt-2">MASUK</a>
<a href="{{ route('register') }}" class="nav-link text-white me-3">DAFTAR</a>
<a href="{{ route('login') }}" class="btn fw-bold masuk-button">MASUK</a>
</div>
</div>
<!-- Tombol Daftar & Masuk di layar besar -->
<div class="d-none d-lg-flex align-items-center tombol-auth">
<a href="/register" class="nav-link text-white me-3">DAFTAR</a>
<a href="/login" class="btn fw-bold masuk-button">MASUK</a>
<a href="{{ route('register') }}" class="nav-link text-white me-3">DAFTAR</a>
<a href="{{ route('login') }}" class="btn fw-bold masuk-button">MASUK</a>
</div>
</div>
</nav>

View File

@ -32,6 +32,10 @@
*/
// Halaman utama
Route::get('/', function () {
return redirect()->route('users.home');
});
Route::get('/home', [HomeController::class, 'index'])->name('users.home');
Route::get('/galeri', function () {
@ -65,9 +69,7 @@
// Route untuk User
// ===============================
Route::middleware(['auth', 'roles:user'])->group(function () {
Route::get('/dashboard-user', fn() => view('users.peta'))->name('users.peta');
// Route::get('/profile', [UserController::class, 'edit'])->name('users.editprofile');
// Route::put('/user/profile', [UserController::class, 'update'])->name('users.updateProfile');
Route::get('/dashboard-user', [UserController::class, 'showDashboard'])->name('users.peta');
Route::get('/petakos', [KamarController::class, 'index'])->name('users.peta');
Route::get('/detail-kamar/{id_kamar}', [RoomController::class, 'show'])->name('users.detail_kamar');
Route::post('/booking-kamar', [BookingController::class, 'storebooking'])->name('users.storebooking');
@ -79,6 +81,12 @@
Route::get('/profile', [UserController::class, 'showProfile'])->name('users.profile');
Route::get('/profile/edit', [UserController::class, 'editProfile'])->name('users.edit-profile');
Route::put('/profile/update', [UserController::class, 'updateProfile'])->name('users.updateProfile');
// Tampilkan form persetujuan
Route::get('/user/approve-rental', [UserController::class, 'showApprovalForm'])->name('user.showApprovalForm');
// Proses submit persetujuan
Route::post('/user/approve-rental', [UserController::class, 'approveRental'])->name('user.approveRental');
Route::get('/peta', [UserController::class, 'showMap'])->name('users.peta');
});
@ -156,6 +164,6 @@
// Route untuk Pemilik
// ===============================
Route::middleware(['auth', 'roles:pemilik'])->group(function () {
Route::get('/dashboard_pemilik', [DashboardPemilikController::class, 'index'])->name('pemilik.dashboard');
Route::get('/dashboard_pemilik', [DashboardPemilikController::class, 'index'])->name('dashboard_pemilik');
Route::get('/laporan', [LaporanController::class, 'index'])->name('pemilik.laporan');
});