This commit is contained in:
alfinfadli16 2025-06-13 02:23:46 +07:00
parent 3c9f5774a5
commit eb637d4fed
9 changed files with 572 additions and 252 deletions

View File

@ -0,0 +1,29 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Sewa;
use Carbon\Carbon;
class ReportController extends Controller
{
public function transactions(Request $request)
{
// Ambil data transaksi (sewa yang sudah selesai atau dikonfirmasi)
$query = Sewa::with('user', 'paket')
->whereIn('status', ['confirmed', 'completed']); // Asumsi 'confirmed' dan 'completed' adalah status yang relevan untuk laporan transaksi
// Filter berdasarkan tanggal jika ada
if ($request->has('start_date') && $request->has('end_date')) {
$startDate = Carbon::parse($request->input('start_date'))->startOfDay();
$endDate = Carbon::parse($request->input('end_date'))->endOfDay();
$query->whereBetween('created_at', [$startDate, $endDate]);
}
$transactions = $query->latest()->paginate(10); // Paginate hasilnya
return view('admin.reports.transactions', compact('transactions', 'request'));
}
}

View File

@ -10,6 +10,12 @@
class PenggunaController extends Controller
{
public function __construct()
{
// Middleware untuk method yang membutuhkan akses admin
$this->middleware('admin')->only(['create', 'store', 'edit', 'update', 'destroy']);
}
/**
* Menampilkan halaman daftar pengguna
*
@ -18,7 +24,9 @@ class PenggunaController extends Controller
public function index()
{
$pengguna = User::where('tipe_pengguna', 'admin')->get();
return view('pengguna', compact('pengguna'));
$users = User::where('tipe_pengguna', 'user')->get();
$activeTab = 'admin'; // Menandai tab admin sebagai aktif
return view('pengguna', compact('pengguna', 'users', 'activeTab'));
}
/**
@ -48,29 +56,24 @@ public function store(Request $request)
'email' => 'required|string|email|max:255|unique:users',
'no_telp' => 'required|string|max:20',
'alamat' => 'required|string',
'password' => 'required|string|min:8',
'tipe_pengguna' => 'required|in:admin,user'
'password' => 'required|string|min:8'
]);
$validated['password'] = Hash::make($validated['password']);
$validated['tipe_pengguna'] = 'admin';
$user = User::create($validated);
User::create($validated);
DB::commit();
return redirect()->route('pengguna')->with('success', 'Admin berhasil ditambahkan');
return redirect()->route('pengguna')
->with('success', 'Admin berhasil ditambahkan');
} catch (\Exception $e) {
DB::rollback();
Log::error('Error saat menambah admin: ' . $e->getMessage());
return redirect()->back()
->withInput()
->withErrors(['error' => 'Terjadi kesalahan saat menyimpan data. Silakan coba lagi.']);
return redirect()->back()->with('error', 'Terjadi kesalahan saat menambah admin')->withInput();
}
}
/**
* Menghapus pengguna
*
@ -81,16 +84,23 @@ public function destroy($id)
{
try {
$user = User::findOrFail($id);
$user->delete();
return redirect()->route('pengguna')
->with('success', 'Admin berhasil dihapus');
// Pastikan tidak menghapus diri sendiri
if ($user->id === auth()->id()) {
return redirect()->back()->with('error', 'Anda tidak dapat menghapus akun Anda sendiri');
}
// Pastikan yang dihapus adalah admin
if ($user->tipe_pengguna !== 'admin') {
return redirect()->back()->with('error', 'Anda hanya dapat menghapus akun admin melalui menu ini');
}
$user->delete();
return redirect()->route('pengguna')->with('success', 'Admin berhasil dihapus');
} catch (\Exception $e) {
Log::error('Error saat menghapus admin: ' . $e->getMessage());
return redirect()->back()
->withErrors(['error' => 'Terjadi kesalahan saat menghapus data.']);
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus admin');
}
}
}

View File

@ -115,28 +115,29 @@ public function adminIndex()
/**
* Mengubah status pemesanan (khusus admin)
*/
public function updateStatus(Request $request, $id)
{
// Hanya admin yang bisa akses
if (!Auth::user()->tipe_pengguna == 'admin') {
return redirect()->route('dashboard');
}
$request->validate([
'status' => 'required|in:pending,confirmed,ongoing,completed,dibatalkan',
]);
$sewa = Sewa::findOrFail($id);
$sewa->status = $request->status;
$sewa->save();
return redirect()->route('admin.riwayat')
->with('success', 'Status pesanan berhasil diperbarui.');
{
if (Auth::user()->tipe_pengguna !== 'admin') {
return redirect()->route('dashboard')->with('error', 'Akses ditolak.');
}
/**
* Menghapus riwayat pemesanan
*/
$sewa = Sewa::findOrFail($id);
if ($sewa->status !== 'confirmed') {
return back()->with('error', 'Status hanya bisa diubah jika saat ini adalah confirmed.');
}
if ($request->status !== 'completed') {
return back()->with('error', 'Status hanya bisa diubah menjadi completed.');
}
$sewa->status = 'completed';
$sewa->save();
return back()->with('success', 'Status berhasil diperbarui menjadi completed.');
}
public function hapus($id)
{
$sewa = Sewa::findOrFail($id);

View File

@ -0,0 +1,85 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class UserController extends Controller
{
public function __construct()
{
// Middleware hanya untuk admin yang mengakses destroy
$this->middleware('admin')->only(['destroy']);
}
/**
* Menampilkan halaman daftar pengguna dan admin
*/
public function index()
{
$pengguna = User::where('tipe_pengguna', 'admin')->get(); // Ambil admin
$users = User::where('tipe_pengguna', 'user')->get(); // Ambil user biasa
$activeTab = 'user';
return view('pengguna', compact('pengguna', 'users', 'activeTab'));
}
/**
* Menghapus pengguna (user biasa saja)
*/
public function destroy($id)
{
try {
$user = User::findOrFail($id);
if ($user->tipe_pengguna !== 'user') {
return redirect()->back()->with('error', 'Anda hanya dapat menghapus akun user biasa melalui menu ini');
}
$user->delete();
return redirect()->route('users')->with('success', 'Pengguna berhasil dihapus');
} catch (\Exception $e) {
Log::error('Error saat menghapus pengguna: ' . $e->getMessage());
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus pengguna');
}
}
/**
* Menampilkan form tambah pengguna (opsional)
*/
public function create()
{
return view('tambah-pengguna');
}
/**
* Menyimpan pengguna baru (admin)
*/
public function store(Request $request)
{
$request->validate([
'nama' => 'required|string|max:255',
'username' => 'required|string|max:255|unique:users',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|string|min:6|confirmed',
'alamat' => 'nullable|string',
'no_telp' => 'nullable|string|max:20',
]);
User::create([
'nama' => $request->nama,
'username' => $request->username,
'email' => $request->email,
'role' => 'customer', // atau 'admin' jika pakai role
'password' => bcrypt($request->password),
'alamat' => $request->alamat,
'no_telp' => $request->no_telp,
'tipe_pengguna' => 'admin',
]);
return redirect()->route('users')->with('success', 'Admin berhasil ditambahkan');
}
}

View File

@ -0,0 +1,97 @@
@extends('layouts.app')
@section('title', 'Laporan Transaksi - Admin INUFA')
@section('header', 'Laporan Transaksi')
@section('content')
<div class="bg-white rounded-lg shadow-lg p-6">
<h2 class="text-2xl font-bold text-gray-800 mb-6">Filter Laporan</h2>
<form action="{{ route('admin.reports.transactions') }}" method="GET" class="mb-6 flex flex-wrap gap-4 items-end">
<div class="flex flex-col">
<label for="start_date" class="text-sm font-medium text-gray-700 mb-1">Tanggal Mulai:</label>
<input type="date" id="start_date" name="start_date" class="form-input rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" value="{{ request('start_date') }}">
</div>
<div class="flex flex-col">
<label for="end_date" class="text-sm font-medium text-gray-700 mb-1">Tanggal Akhir:</label>
<input type="date" id="end_date" name="end_date" class="form-input rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" value="{{ request('end_date') }}">
</div>
<button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">Filter</button>
@if(request()->has('start_date') || request()->has('end_date'))
<a href="{{ route('admin.reports.transactions') }}" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2">Reset</a>
@endif
</form>
@if($transactions->count() > 0)
<div class="overflow-x-auto">
<table class="min-w-full bg-white border border-gray-200 rounded-lg">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">No</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">ID Sewa</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Tanggal Sewa</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Pelanggan</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Paket</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Total Harga</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Nominal Pembayaran</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Sisa Pembayaran</th>
<th class="py-3 px-4 text-left text-sm font-semibold text-gray-600 border-b">Status</th>
<th class="py-3 px-4 text-center text-sm font-semibold text-gray-600 border-b">Aksi</th>
</tr>
</thead>
<tbody>
@foreach($transactions as $index => $sewa)
<tr class="border-b hover:bg-gray-50">
<td class="py-3 px-4 text-sm text-gray-800">{{ $transactions->firstItem() + $index }}</td>
<td class="py-3 px-4 text-sm text-gray-800">#{{ $sewa->id }}</td>
<td class="py-3 px-4 text-sm text-gray-800">{{ \Carbon\Carbon::parse($sewa->created_at)->format('d M Y H:i') }}</td>
<td class="py-3 px-4 text-sm text-gray-800">{{ $sewa->user->nama }}</td>
<td class="py-3 px-4 text-sm text-gray-800">{{ $sewa->paket->nama_paket }}</td>
<td class="py-3 px-4 text-sm text-gray-800">Rp {{ number_format($sewa->total_harga, 0, ',', '.') }}</td>
<td class="py-3 px-4 text-sm text-gray-800">Rp {{ number_format($sewa->nominal_pembayaran, 0, ',', '.') }}</td>
<td class="py-3 px-4 text-sm text-gray-800">
@php
$sisaPembayaran = $sewa->total_harga - ($sewa->nominal_pembayaran ?? 0);
@endphp
@if($sisaPembayaran > 0)
<span class="text-red-600 font-medium">
Rp {{ number_format($sisaPembayaran, 0, ',', '.') }}
</span>
@else
<span class="text-green-600 font-medium">Lunas</span>
@endif
</td>
<td class="py-3 px-4 text-sm text-gray-800">
<span class="px-2 py-1 text-xs font-semibold rounded-full
@if($sewa->status === 'completed') bg-green-100 text-green-800
@elseif($sewa->status === 'confirmed') bg-blue-100 text-blue-800
@else bg-gray-100 text-gray-800 @endif">
{{ ucfirst($sewa->status) }}
</span>
</td>
<td class="py-3 px-4 text-center text-sm">
@if($sewa->status !== 'completed' && $sewa->status !== 'dibatalkan')
<a href="{{ route('admin.riwayat.show-update-payment', $sewa->id) }}" class="bg-indigo-500 hover:bg-indigo-600 text-white px-3 py-1 rounded-md">
Update Pembayaran
</a>
@else
<span class="text-gray-500">Tidak Ada Aksi</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mt-4">
{{ $transactions->links() }} <!-- Menampilkan paginasi -->
</div>
@else
<div class="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700 p-4" role="alert">
<p class="font-bold">Informasi</p>
<p>Tidak ada data transaksi yang ditemukan.</p>
</div>
@endif
</div>
@endsection

View File

@ -1,83 +1,112 @@
@extends('layouts.app')
@section('title', 'Manajemen Riwayat - INUFA')
@section('title', 'Riwayat Sewa - Admin INUFA')
@section('header', 'Manajemen Riwayat Pemesanan')
@section('header', 'Manajemen Riwayat Sewa')
@section('content')
<div class="bg-white rounded-lg shadow-lg p-6">
<div class="mb-6">
<h2 class="text-xl font-bold mb-2">Daftar Semua Pemesanan</h2>
<p class="text-gray-600">Menampilkan semua pesanan dari seluruh pengguna.</p>
</div>
<!-- Filter dan Pencarian -->
<div class="mb-6 flex flex-col md:flex-row space-y-4 md:space-y-0 md:space-x-4">
<div class="w-full md:w-1/3">
<label for="status-filter" class="block text-sm font-medium text-gray-700 mb-1">Filter Status</label>
<select id="status-filter" class="w-full border-gray-300 rounded-md shadow-sm p-2 focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
<option value="">Semua Status</option>
<option value="pending">Pending</option>
<option value="confirmed">Confirmed</option>
<option value="ongoing">Ongoing</option>
<option value="completed">Completed</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="w-full md:w-2/3">
<label for="search" class="block text-sm font-medium text-gray-700 mb-1">Cari Pemesanan</label>
<input type="text" id="search" placeholder="Cari berdasarkan ID, nama pengguna, atau lokasi..." class="w-full border-gray-300 rounded-md shadow-sm p-2 focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
</div>
</div>
<!-- Tabel Riwayat -->
@if(count($sewas) > 0)
<div class="overflow-x-auto">
<table class="min-w-full bg-white">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left">ID</th>
<th class="py-3 px-4 text-left">Pengguna</th>
<th class="py-3 px-4 text-left">No</th>
<th class="py-3 px-4 text-left">Tanggal</th>
<th class="py-3 px-4 text-left">Customer</th>
<th class="py-3 px-4 text-left">Paket</th>
<th class="py-3 px-4 text-left">Tanggal Mulai</th>
<th class="py-3 px-4 text-left">Tanggal Selesai</th>
<th class="py-3 px-4 text-left">Total Harga</th>
<th class="py-3 px-4 text-left">Nominal Pembayaran</th>
<th class="py-3 px-4 text-left">Sisa Pembayaran</th>
<th class="py-3 px-4 text-left">Status</th>
<th class="py-3 px-4 text-left">Aksi</th>
<th class="py-3 px-4 text-center">Aksi</th>
</tr>
</thead>
<tbody id="orders-table-body">
@foreach($sewas as $sewa)
<tr class="border-b hover:bg-gray-50 order-row" data-status="{{ $sewa->status }}">
<td class="py-3 px-4 font-medium">#{{ $sewa->id }}</td>
<td class="py-3 px-4">{{ $sewa->user->name }}</td>
<td class="py-3 px-4">{{ $sewa->paket->nama }}</td>
<td class="py-3 px-4">{{ date('d/m/Y', strtotime($sewa->tanggal_mulai)) }}</td>
<td class="py-3 px-4">{{ date('d/m/Y', strtotime($sewa->tanggal_selesai)) }}</td>
<tbody>
@foreach($sewas as $index => $sewa)
@php
$user = optional($sewa->user);
$paket = optional($sewa->paket);
$sisaPembayaran = $sewa->total_harga - ($sewa->nominal_pembayaran ?? 0);
@endphp
<tr class="border-b hover:bg-gray-50">
<td class="py-3 px-4">{{ $index + 1 }}</td>
<td class="py-3 px-4">{{ $sewa->created_at->format('d/m/Y') }}</td>
<td class="py-3 px-4">
<div class="text-sm">
<p class="font-medium text-gray-900">{{ $user->name ?? '-' }}</p>
<p class="text-gray-500">{{ $user->email ?? '-' }}</p>
</div>
</td>
<td class="py-3 px-4">{{ $paket->nama_paket ?? '-' }}</td>
<td class="py-3 px-4">Rp {{ number_format($sewa->total_harga, 0, ',', '.') }}</td>
<td class="py-3 px-4">
<span class="px-2 py-1 rounded-full text-xs font-semibold
{{ $sewa->status == 'pending' ? 'bg-yellow-100 text-yellow-800' :
($sewa->status == 'confirmed' ? 'bg-blue-100 text-blue-800' :
($sewa->status == 'ongoing' ? 'bg-purple-100 text-purple-800' :
($sewa->status == 'completed' ? 'bg-green-100 text-green-800' :
'bg-red-100 text-red-800'))) }}">
Rp {{ number_format($sewa->nominal_pembayaran ?? 0, 0, ',', '.') }}
</td>
<td class="py-3 px-4">
@if($sisaPembayaran > 0)
<span class="text-red-600 font-medium">
Rp {{ number_format($sisaPembayaran, 0, ',', '.') }}
</span>
@else
<span class="text-green-600 font-medium">Lunas</span>
@endif
</td>
<td class="py-3 px-4">
<span class="px-2 py-1 rounded-full text-xs font-semibold
@if($sewa->status == 'pending') bg-yellow-100 text-yellow-800
@elseif($sewa->status == 'confirmed') bg-blue-100 text-blue-800
@elseif($sewa->status == 'ongoing') bg-indigo-100 text-indigo-800
@elseif($sewa->status == 'completed') bg-green-100 text-green-800
@elseif($sewa->status == 'dibatalkan') bg-red-100 text-red-800
@endif">
{{ ucfirst($sewa->status) }}
</span>
</td>
<td class="py-3 px-4">
<div class="flex space-x-2">
<a href="#" onclick="openStatusModal({{ $sewa->id }}, '{{ $sewa->status }}')" class="bg-blue-500 text-white py-1 px-2 rounded hover:bg-blue-600 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
<path d="M13.586 3.586a2 2 0 112.828 2.828l-.793.793-2.828-2.828.793-.793zM11.379 5.793L3 14.172V17h2.828l8.38-8.379-2.83-2.828z" />
</svg>
<div class="flex flex-col sm:flex-row justify-center sm:space-x-2 space-y-2 sm:space-y-0">
<!-- Tombol Detail -->
<a href="{{ route('admin.riwayat.show', $sewa->id) }}"
class="bg-blue-600 text-white px-3 py-1 rounded hover:bg-blue-700 text-sm">
Detail
</a>
<a href="{{ route('riwayat.show', $sewa->id) }}" class="bg-green-500 text-white py-1 px-2 rounded hover:bg-green-600 transition-colors">
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
<path d="M10 12a2 2 0 100-4 2 2 0 000 4z" />
<path fill-rule="evenodd" d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z" clip-rule="evenodd" />
</svg>
<!-- Tombol Chat -->
<a href="{{ route('chat.show', $sewa->user_id) }}"
class="bg-green-500 text-white px-3 py-1 rounded hover:bg-green-600 text-sm">
Chat
</a>
@if($sewa->status === 'confirmed')
<!-- Tombol Tandai Selesai -->
<form action="{{ route('admin.riwayat.status', $sewa->id) }}" method="POST" class="inline">
@csrf
@method('PUT')
<input type="hidden" name="status" value="completed">
<button type="submit"
onclick="return confirm('Ubah status menjadi Completed?')"
class="bg-purple-600 text-white px-3 py-1 rounded hover:bg-purple-700 text-sm">
Tandai Selesai
</button>
</form>
@endif
@if(!in_array($sewa->status, ['completed', 'dibatalkan']))
<!-- Form Update Status -->
<form action="{{ route('admin.riwayat.status', $sewa->id) }}" method="POST">
@csrf
@method('PUT')
<select name="status"
onchange="this.form.submit()"
class="rounded-md border-gray-300 text-sm shadow-sm focus:border-blue-300 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
<option value="pending" {{ $sewa->status == 'pending' ? 'selected' : '' }}>Pending</option>
<option value="confirmed" {{ $sewa->status == 'confirmed' ? 'selected' : '' }}>Confirmed</option>
<option value="ongoing" {{ $sewa->status == 'ongoing' ? 'selected' : '' }}>Ongoing</option>
<option value="completed" {{ $sewa->status == 'completed' ? 'selected' : '' }}>Completed</option>
<option value="dibatalkan" {{ $sewa->status == 'dibatalkan' ? 'selected' : '' }}>Dibatalkan</option>
</select>
</form>
@endif
</div>
</td>
</tr>
@ -87,99 +116,8 @@
</div>
@else
<div class="text-center py-8">
<p class="text-gray-500">Belum ada data pemesanan.</p>
<p class="text-gray-500">Belum ada riwayat pemesanan</p>
</div>
@endif
</div>
<!-- Modal Update Status -->
<div id="status-modal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center">
<div class="bg-white rounded-lg p-6 max-w-md w-full">
<h3 class="text-xl font-bold mb-4">Update Status Pemesanan</h3>
<form id="status-form" action="" method="POST">
@csrf
@method('PUT')
<div class="mb-4">
<label for="status" class="block text-gray-700 font-medium mb-2">Status Baru</label>
<select id="status" name="status" class="w-full border-gray-300 rounded-md shadow-sm p-2 focus:border-blue-500 focus:ring focus:ring-blue-200 focus:ring-opacity-50">
<option value="pending">Pending</option>
<option value="confirmed">Confirmed</option>
<option value="ongoing">Ongoing</option>
<option value="completed">Completed</option>
<option value="cancelled">Cancelled</option>
</select>
</div>
<div class="flex justify-end space-x-2">
<button type="button" onclick="closeStatusModal()" class="bg-gray-300 text-gray-800 py-2 px-4 rounded hover:bg-gray-400 transition-colors">
Batal
</button>
<button type="submit" class="bg-blue-800 text-white py-2 px-4 rounded hover:bg-blue-900 transition-colors">
Simpan
</button>
</div>
</form>
</div>
</div>
@endsection
@section('scripts')
<script>
// Filter berdasarkan status
document.getElementById('status-filter').addEventListener('change', function() {
const status = this.value;
const rows = document.querySelectorAll('.order-row');
rows.forEach(row => {
if (status === '' || row.dataset.status === status) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
// Pencarian
document.getElementById('search').addEventListener('keyup', function() {
const searchTerm = this.value.toLowerCase();
const rows = document.querySelectorAll('.order-row');
rows.forEach(row => {
const rowText = row.textContent.toLowerCase();
if (rowText.includes(searchTerm)) {
row.style.display = '';
} else {
row.style.display = 'none';
}
});
});
// Modal status
function openStatusModal(id, currentStatus) {
const modal = document.getElementById('status-modal');
const form = document.getElementById('status-form');
const statusSelect = document.getElementById('status');
// Set action URL
form.action = `/admin/riwayat/${id}/status`;
// Set current status
statusSelect.value = currentStatus;
// Show modal
modal.classList.remove('hidden');
}
function closeStatusModal() {
const modal = document.getElementById('status-modal');
modal.classList.add('hidden');
}
// Close modal jika klik di luar modal
window.onclick = function(event) {
const modal = document.getElementById('status-modal');
if (event.target === modal) {
closeStatusModal();
}
};
</script>
@endsection

View File

@ -13,21 +13,28 @@
@if(auth()->user()->tipe_pengguna === 'admin')
<a href="{{ route('pengguna') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('pengguna*') ? 'bg-blue-800 text-white' : '' }}">
Admin
pengguna
</a>
<a href="{{ route('input-stock') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('input-stock*') ? 'bg-blue-800 text-white' : '' }}">
Input Stock
</a>
@endif
<a href="{{ route('paket') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('paket*') ? 'bg-blue-800 text-white' : '' }}">
Paket
</a>
@if(auth()->user()->tipe_pengguna === 'user')
<a href="{{ route('sewa.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('sewa.*') ? 'bg-blue-800 text-white' : '' }}">
Sewa
</a>
@endif
@if(auth()->user()->tipe_pengguna === 'admin')
<a href="/admin/verifikasi" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->is('admin/verifikasi*') ? 'bg-blue-800 text-white' : '' }}">
Verifikasi
</a>
<a href="{{ route('admin.reports.transactions') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('admin.reports.transactions') ? 'bg-blue-800 text-white' : '' }}">
Laporan Transaksi
</a>
@endif
<a href="{{ route('paket') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('paket*') ? 'bg-blue-800 text-white' : '' }}">
Paket
</a>
<a href="{{ route('sewa.index') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('sewa.*') ? 'bg-blue-800 text-white' : '' }}">
Sewa
</a>
<a href="{{ route('riwayat') }}" class="block py-3 px-4 text-gray-800 font-semibold mb-1 hover:bg-gray-100 {{ request()->routeIs('riwayat') ? 'bg-blue-800 text-white' : '' }}">
Riwayat
</a>

View File

@ -1,61 +1,189 @@
@extends('layouts.app')
@section('title', 'Data Admin - INUFA')
@section('title', 'Data Pengguna - INUFA')
@section('header')
<div class="flex space-x-8">
<a href="{{ route('pengguna') }}" class="font-semibold border-b-2 border-white pb-1">Data Admin</a>
<!-- <a href="{{ route('admin') }}" class="font-semibold">Data User</a> -->
<div class="relative inline-block text-left mb-2 bg-white p-2 rounded-lg shadow">
<button type="button" class="inline-flex items-center rounded-md px-2 py-1 bg-transparent text-base font-semibold text-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-blue-400" id="data-pengguna-dropdown-button" aria-expanded="true" aria-haspopup="true">
Data Pengguna
<svg class="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
<div class="origin-top-left absolute left-0 mt-2 w-48 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none hidden" role="menu" aria-orientation="vertical" aria-labelledby="data-pengguna-dropdown-button" tabindex="-1" id="data-pengguna-dropdown-menu">
<div class="py-1" role="none">
<a href="{{ route('pengguna') }}" class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 {{ $activeTab === 'admin' ? 'bg-gray-100' : '' }}" role="menuitem" tabindex="-1" id="menu-item-admin">Admin</a>
<a href="{{ route('users') }}" class="text-gray-700 block px-4 py-2 text-sm hover:bg-gray-100 {{ $activeTab === 'user' ? 'bg-gray-100' : '' }}" role="menuitem" tabindex="-1" id="menu-item-user">User</a>
</div>
</div>
</div>
@endsection
@section('content')
<!-- Add Button -->
<div class="mb-6">
<a href="{{ route('pengguna.create') }}" class="inline-block bg-white text-gray-800 px-4 py-2 rounded font-semibold">
Tambah Admin
</a>
<!-- Add Button - Only visible for admin -->
<div id="adminContent" class="{{ $activeTab === 'admin' ? '' : 'hidden' }}">
@if(auth()->user()->tipe_pengguna === 'admin')
<div class="mb-6">
<a href="{{ route('pengguna.create') }}" class="inline-block bg-white text-gray-800 px-4 py-2 rounded font-semibold">
Tambah Admin
</a>
</div>
@endif
<!-- Table Admin -->
<div class="bg-white rounded shadow overflow-x-auto">
<table class="w-full table-fixed">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left w-12 border-r">No</th>
<th class="py-3 px-4 text-left w-36 border-r">Nama</th>
<th class="py-3 px-4 text-left w-36 border-r">Username</th>
<th class="py-3 px-4 text-left w-48 border-r">Email</th>
<th class="py-3 px-4 text-left w-36 border-r">No.Telp</th>
<th class="py-3 px-4 text-left border-r">Alamat</th>
@if(auth()->user()->tipe_pengguna === 'admin')
<th class="py-3 px-4 text-center w-24">Aksi</th>
@endif
</tr>
</thead>
<tbody>
@forelse($pengguna as $index => $user)
<tr class="border-t">
<td class="py-3 px-4 border-r">{{ $index + 1 }}</td>
<td class="py-3 px-4 border-r">{{ $user->nama }}</td>
<td class="py-3 px-4 border-r">{{ $user->username }}</td>
<td class="py-3 px-4 border-r">{{ $user->email }}</td>
<td class="py-3 px-4 border-r">{{ $user->no_telp }}</td>
<td class="py-3 px-4 border-r">{{ $user->alamat }}</td>
@if(auth()->user()->tipe_pengguna === 'admin')
<td class="py-3 px-4 text-center">
<form action="{{ route('pengguna.destroy', $user->id) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit" class="bg-red-500 text-white px-4 py-1 rounded-sm font-medium text-sm">
Hapus
</button>
</form>
</td>
@endif
</tr>
@empty
<tr class="border-t">
<td colspan="{{ auth()->user()->tipe_pengguna === 'admin' ? 7 : 6 }}" class="py-3 px-4 text-center">Tidak ada data admin</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
<!-- Table -->
<div class="bg-white rounded shadow overflow-x-auto">
<table class="w-full table-fixed">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left w-12 border-r">No</th>
<th class="py-3 px-4 text-left w-36 border-r">Nama</th>
<th class="py-3 px-4 text-left w-36 border-r">Username</th>
<th class="py-3 px-4 text-left w-48 border-r">Email</th>
<th class="py-3 px-4 text-left w-36 border-r">No.Telp</th>
<th class="py-3 px-4 text-left border-r">Alamat</th>
<th class="py-3 px-4 text-center w-24">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($pengguna as $index => $user)
<tr class="border-t">
<td class="py-3 px-4 border-r">{{ $user->id }}</td>
<td class="py-3 px-4 border-r">{{ $user->nama }}</td>
<td class="py-3 px-4 border-r">{{ $user->username }}</td>
<td class="py-3 px-4 border-r">{{ $user->email }}</td>
<td class="py-3 px-4 border-r">{{ $user->no_telp }}</td>
<td class="py-3 px-4 border-r">{{ $user->alamat }}</td>
<td class="py-3 px-4 text-center">
<form action="{{ route('pengguna.destroy', $user->id) }}" method="POST">
@csrf
@method('DELETE')
<button type="submit" class="bg-red-500 text-white px-4 py-1 rounded-sm font-medium text-sm">
Hapus
</button>
</form>
</td>
</tr>
@empty
<tr class="border-t">
<td colspan="7" class="py-3 px-4 text-center">Tidak ada data admin</td>
</tr>
@endforelse
</tbody>
</table>
<!-- Table User Content -->
<div id="userContent" class="{{ $activeTab === 'user' ? '' : 'hidden' }}">
<div class="bg-white rounded shadow overflow-x-auto">
<table class="w-full table-fixed">
<thead>
<tr class="bg-gray-100">
<th class="py-3 px-4 text-left w-12 border-r">No</th>
<th class="py-3 px-4 text-left w-36 border-r">Nama</th>
<th class="py-3 px-4 text-left w-36 border-r">Username</th>
<th class="py-3 px-4 text-left w-48 border-r">Email</th>
<th class="py-3 px-4 text-left w-36 border-r">No.Telp</th>
<th class="py-3 px-4 text-left border-r">Alamat</th>
@if(auth()->user()->tipe_pengguna === 'admin')
<th class="py-3 px-4 text-center w-24">Aksi</th>
@endif
</tr>
</thead>
<tbody>
@forelse($users as $index => $user)
<tr class="border-t">
<td class="py-3 px-4 border-r">{{ $index + 1 }}</td>
<td class="py-3 px-4 border-r">{{ $user->nama }}</td>
<td class="py-3 px-4 border-r">{{ $user->username }}</td>
<td class="py-3 px-4 border-r">{{ $user->email }}</td>
<td class="py-3 px-4 border-r">{{ $user->no_telp }}</td>
<td class="py-3 px-4 border-r">{{ $user->alamat }}</td>
@if(auth()->user()->tipe_pengguna === 'admin')
<td class="py-3 px-4 text-center">
<form action="{{ route('users.destroy', $user->id) }}" method="POST" class="inline">
@csrf
@method('DELETE')
<button type="submit" class="bg-red-500 text-white px-4 py-1 rounded-sm font-medium text-sm">
Hapus
</button>
</form>
</td>
@endif
</tr>
@empty
<tr class="border-t">
<td colspan="{{ auth()->user()->tipe_pengguna === 'admin' ? 7 : 6 }}" class="py-3 px-4 text-center">Tidak ada data pengguna</td>
</tr>
@endforelse
</tbody>
</table>
</div>
</div>
@endsection
@endsection
@push('scripts')
<script>
function showTab(tab) {
// Update tab styling
if (tab === 'admin') {
document.getElementById('adminContent').style.display = 'block';
document.getElementById('userContent').style.display = 'none';
} else {
document.getElementById('adminContent').style.display = 'none';
document.getElementById('userContent').style.display = 'block';
}
}
document.addEventListener('DOMContentLoaded', function() {
const dropdownButton = document.getElementById('data-pengguna-dropdown-button');
const dropdownMenu = document.getElementById('data-pengguna-dropdown-menu');
if (dropdownButton && dropdownMenu) {
dropdownButton.addEventListener('click', function() {
dropdownMenu.classList.toggle('hidden');
});
document.addEventListener('click', function(event) {
if (!dropdownButton.contains(event.target) && !dropdownMenu.contains(event.target)) {
dropdownMenu.classList.add('hidden');
}
});
// Set initial tab visibility based on $activeTab, this replaces the previous showTab logic
const initialActiveTab = '{{ $activeTab }}';
if (initialActiveTab === 'user') {
document.getElementById('adminContent').classList.add('hidden');
document.getElementById('userContent').classList.remove('hidden');
} else {
document.getElementById('adminContent').classList.remove('hidden');
document.getElementById('userContent').classList.add('hidden');
}
// Handle click on dropdown menu items to switch tabs and hide menu
document.getElementById('menu-item-admin').addEventListener('click', function(event) {
event.preventDefault();
window.location.href = this.href; // Redirect to the admin route
dropdownMenu.classList.add('hidden');
});
document.getElementById('menu-item-user').addEventListener('click', function(event) {
event.preventDefault();
window.location.href = this.href; // Redirect to the user route
dropdownMenu.classList.add('hidden');
});
}
});
// The showTab function is no longer needed in its original form if we rely on full page reload for tab switching.
// However, if there was client-side only tab switching logic that needed to be preserved, it would be different.
// For now, I'm assuming full page reload based on the hrefs.
</script>
@endpush

View File

@ -16,6 +16,7 @@
use App\Http\Controllers\OngkirKotaController;
use App\Http\Controllers\ContactInfoController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\UserController;
/*
|--------------------------------------------------------------------------
@ -29,11 +30,14 @@
*/
// Route untuk halaman welcome
Route::get('/', function () {
$pakets = \App\Models\Paket::where('status', 'aktif')->get();
return view('welcome', compact('pakets'));
});
// Route untuk sewa yang bisa diakses tanpa login
Route::get('/sewa', [SewaController::class, 'index'])->name('sewa.index');
@ -48,6 +52,20 @@
// Route untuk logout
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
// Route untuk pembatalan pesanan
Route::middleware(['auth'])->group(function () {
Route::get('/riwayat/cancel/{id}', [RiwayatController::class, 'showCancelForm'])->name('riwayat.cancel-form');
Route::put('/riwayat/cancel/{id}/process', [RiwayatController::class, 'processCancel'])->name('riwayat.process-cancel');
// Chat Routes
Route::get('/chat', [ChatController::class, 'index'])->name('chat.index');
Route::get('/chat/{user_id}', [ChatController::class, 'show'])->name('chat.show');
Route::post('/chat/{user_id}', [ChatController::class, 'store'])->name('chat.store');
Route::get('/chat/{user_id}/messages', [ChatController::class, 'getMessages'])->name('chat.messages');
Route::get('/chat/unread-count', [ChatController::class, 'getUnreadCount'])->name('chat.unreadCount');
Route::post('/chat/{user_id}/mark-as-read', [ChatController::class, 'markAsRead'])->name('chat.markAsRead');
});
// Route yang membutuhkan autentikasi
Route::middleware(['auth'])->group(function () {
// Dashboard
@ -119,30 +137,33 @@
Route::get('/riwayat', [SewaController::class, 'riwayat'])->name('riwayat');
});
// Riwayat
// Riwayat untuk customer
Route::get('/riwayat', [RiwayatController::class, 'index'])->name('riwayat');
Route::get('/riwayat/{id}', [RiwayatController::class, 'show'])->name('riwayat.show');
Route::put('/riwayat/{id}/batal', [RiwayatController::class, 'cancel'])->name('riwayat.batal');
Route::delete('/riwayat/{id}/hapus', [RiwayatController::class, 'hapus'])->name('riwayat.hapus');
// Admin Riwayat
Route::prefix('admin')->name('admin.')->group(function () {
// Admin Routes
Route::middleware(['admin'])->prefix('admin')->name('admin.')->group(function () {
// Riwayat Routes untuk admin
Route::get('/riwayat', [RiwayatController::class, 'adminIndex'])->name('riwayat');
Route::get('/riwayat/{id}', [RiwayatController::class, 'show'])->name('riwayat.show');
Route::put('/riwayat/{id}/status', [RiwayatController::class, 'updateStatus'])->name('riwayat.status');
Route::get('/riwayat/{id}/update-payment', [RiwayatController::class, 'showUpdatePaymentForm'])->name('riwayat.show-update-payment');
Route::put('/riwayat/{id}/update-payment', [RiwayatController::class, 'updatePayment'])->name('riwayat.update-payment');
// Verifikasi Pembayaran
Route::get('/verifikasi', [App\Http\Controllers\Admin\VerifikasiController::class, 'index'])->name('verifikasi.index');
Route::post('/verifikasi/{id}/approve', [App\Http\Controllers\Admin\VerifikasiController::class, 'approve'])->name('verifikasi.approve');
Route::post('/verifikasi/{id}/reject', [App\Http\Controllers\Admin\VerifikasiController::class, 'reject'])->name('verifikasi.reject');
// Laporan Transaksi
Route::get('/reports/transactions', [App\Http\Controllers\Admin\ReportController::class, 'transactions'])->name('reports.transactions');
});
// Chat Routes
Route::get('/chat/unread-count', [ChatController::class, 'getUnreadCount'])->name('chat.unreadCount');
Route::get('/chat', [ChatController::class, 'index'])->name('chat.index');
Route::get('/chat/latest-messages/{user_id}', [ChatController::class, 'getLatestMessages'])->name('chat.latestMessages');
Route::get('/chat/{user_id}/messages', [ChatController::class, 'getNewMessages'])->name('chat.messages');
Route::get('/chat/{user_id}', [ChatController::class, 'show'])->name('chat.show');
Route::post('/chat/{user_id}', [ChatController::class, 'store'])->name('chat.store');
Route::post('/chat/{user_id}/mark-as-read', [ChatController::class, 'markAsRead'])->name('chat.markAsRead');
});
// Reroute dari dashboard/users ke pengguna
@ -189,3 +210,7 @@
});
Route::get('/paket/{id}/detail', [PaketController::class, 'detail'])->name('paket.detail');
// Route untuk data pengguna biasa
Route::get('/users', [UserController::class, 'index'])->name('users');
Route::delete('/users/{id}', [UserController::class, 'destroy'])->name('users.destroy');