383 lines
11 KiB
PHP
383 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use App\Models\User;
|
|
use App\Models\Pricelist;
|
|
use App\Models\Booking;
|
|
use App\Models\Photo;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Facades\Session;
|
|
|
|
|
|
class AdminController extends Controller
|
|
{
|
|
|
|
public function __construct()
|
|
{
|
|
$this->middleware('auth'); // Memastikan hanya pengguna yang login bisa mengakses controller
|
|
}
|
|
|
|
// Tampilkan dashboard admin
|
|
public function dashboard()
|
|
{
|
|
$totalBookings = Booking::count();
|
|
$totalCustomers = User::where('role', 'customer')->count();
|
|
$totalEmployees = User::where('role', 'user')->count();
|
|
$pendingBookings = Booking::where('status', 'pending')->count();
|
|
$approvedBookings = Booking::where('status', 'approved')->count();
|
|
$declinedBookings = Booking::where('status', 'declined')->count();
|
|
|
|
return view('dashboard.admin', compact(
|
|
'totalBookings', 'totalCustomers', 'totalEmployees',
|
|
'pendingBookings', 'approvedBookings', 'declinedBookings'
|
|
));
|
|
}
|
|
|
|
|
|
// 📌 1. Tampilkan Daftar Booking
|
|
public function showBookings()
|
|
{
|
|
$bookings = Booking::with('customer')->latest()->get();
|
|
|
|
return view('admin.bookings', compact('bookings'));
|
|
}
|
|
|
|
// 📌 2. Terima Booking
|
|
|
|
public function acceptBooking(Request $request, $id)
|
|
{
|
|
$request->validate([
|
|
'dp' => 'required|integer|min:0',
|
|
]);
|
|
|
|
$booking = Booking::findOrFail($id);
|
|
$booking->status = 'approved';
|
|
$booking->dp = $request->dp; // Simpan DP yang dimasukkan admin
|
|
$booking->keterangan = null; // Clear keterangan
|
|
$booking->save();
|
|
|
|
return back()->with('success', 'Booking berhasil disetujui dengan DP.');
|
|
}
|
|
|
|
// Method untuk menolak booking
|
|
public function declineBooking(Request $request, $id)
|
|
{
|
|
$request->validate([
|
|
'keterangan' => 'required|string',
|
|
]);
|
|
|
|
$booking = Booking::findOrFail($id);
|
|
$booking->status = 'declined';
|
|
$booking->keterangan = $request->keterangan; // Simpan alasan penolakan
|
|
$booking->dp = null; // Clear DP
|
|
$booking->save();
|
|
|
|
return back()->with('success', 'Booking berhasil ditolak dengan alasan.');
|
|
}
|
|
|
|
|
|
|
|
|
|
// 📌 4. Tampilkan Daftar Pengguna
|
|
public function showUsers(Request $request)
|
|
{
|
|
$query = User::query();
|
|
|
|
if ($request->has('search')) {
|
|
$search = $request->input('search');
|
|
$query->where('name', 'like', "%{$search}%")
|
|
->orWhere('email', 'like', "%{$search}%");
|
|
}
|
|
|
|
$users = $query->get(); // atau ->paginate(10) jika pakai pagination
|
|
|
|
return view('admin.users', compact('users'));
|
|
}
|
|
|
|
|
|
// 📌 5. Hapus Pengguna
|
|
public function deleteUser($id)
|
|
{
|
|
$user = User::findOrFail($id);
|
|
$user->delete();
|
|
|
|
return redirect()->route('admin.users')->with('success', 'Pengguna berhasil dihapus.');
|
|
}
|
|
|
|
public function editUser($id)
|
|
{
|
|
$user = User::find($id);
|
|
if (!$user) {
|
|
return response()->json(['error' => 'User not found'], 404);
|
|
}
|
|
return response()->json($user);
|
|
}
|
|
|
|
public function updateUser(Request $request, $id)
|
|
{
|
|
$user = User::findOrFail($id);
|
|
|
|
$data = $request->except(['_token', '_method']);
|
|
|
|
// Jika password diisi, hash password baru
|
|
if (!empty($request->password)) {
|
|
$data['password'] = Hash::make($request->password);
|
|
} else {
|
|
unset($data['password']); // Jangan update password jika tidak diubah
|
|
}
|
|
|
|
$user->update($data);
|
|
|
|
return redirect()->route('admin.users')->with('success', 'User berhasil diperbarui.');
|
|
}
|
|
|
|
public function storeUser(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'name' => 'required|string|max:255',
|
|
'email' => 'required|email|unique:users,email',
|
|
'phone' => 'required|string|max:15',
|
|
'address' => 'required|string|max:255',
|
|
'password' => 'required|min:6',
|
|
'role' => 'required|in:user,customer',
|
|
], [
|
|
'password.min' => 'Password minimal harus 6 karakter.',
|
|
'email.unique' => 'Email sudah digunakan.',
|
|
]);
|
|
|
|
User::create([
|
|
'name' => $validated['name'],
|
|
'email' => $validated['email'],
|
|
'phone' => $validated['phone'],
|
|
'address' => $validated['address'],
|
|
'password' => bcrypt($validated['password']),
|
|
'role' => $validated['role'],
|
|
]);
|
|
|
|
Session::flash('success', 'Karyawan berhasil ditambahkan.');
|
|
return redirect()->route('admin.users');
|
|
}
|
|
|
|
|
|
public function hapustoken($id)
|
|
{
|
|
// Cari foto berdasarkan ID
|
|
$photo = Photo::findOrFail($id);
|
|
|
|
// Ambil token dari foto tersebut
|
|
$token = $photo->token;
|
|
|
|
// Ambil semua foto yang punya token tersebut
|
|
$photos = Photo::where('token', $token)->get();
|
|
|
|
if ($photos->isEmpty()) {
|
|
return redirect()->back()->with('error', 'Tidak ditemukan foto dengan token tersebut.');
|
|
}
|
|
|
|
// Hapus semua foto
|
|
foreach ($photos as $photo) {
|
|
$photo->forceDelete();
|
|
}
|
|
|
|
return redirect()->back()->with('success', 'Token dan semua foto berhasil dihapus.');
|
|
}
|
|
|
|
|
|
public function resetToken($id)
|
|
{
|
|
$photo = Photo::findOrFail($id);
|
|
|
|
// Ambil semua foto yang punya token sama
|
|
$photos = Photo::where('token', $photo->token)->get();
|
|
|
|
// Generate token baru
|
|
$newToken = Str::random(10);
|
|
|
|
// Update semua yang punya token sama
|
|
foreach ($photos as $p) {
|
|
$p->update(['token' => $newToken]);
|
|
}
|
|
|
|
return redirect()->back()->with('success', 'Token berhasil digenerate ulang.');
|
|
}
|
|
|
|
// 📌 6. Tampilkan Halaman Upload Foto
|
|
public function uploadPage()
|
|
{
|
|
$customers = User::where('role', 'customer')->get();
|
|
$photos = Photo::with('customer')->get();
|
|
|
|
return view('admin.upload', compact('customers', 'photos'));
|
|
}
|
|
|
|
// 📌 7. Simpan Foto ke Storage dan Database
|
|
public function storeUpload(Request $request)
|
|
{
|
|
$request->validate([
|
|
'customer_id' => 'required|exists:users,id',
|
|
'foto' => 'required|image|mimes:jpeg,png,jpg|max:2048',
|
|
]);
|
|
|
|
// Simpan ke Storage
|
|
$file = $request->file('foto');
|
|
$path = $file->store('photos', 'public');
|
|
|
|
// Buat Token Unik
|
|
$token = Str::random(10);
|
|
|
|
// Simpan ke Database
|
|
Photo::create([
|
|
'customer_id' => $request->customer_id,
|
|
'file_path' => $path,
|
|
'token' => $token,
|
|
]);
|
|
|
|
return redirect()->route('admin.upload')->with('success', 'Foto berhasil diunggah.');
|
|
}
|
|
|
|
|
|
|
|
public function showReports()
|
|
{
|
|
$totalBookings = Booking::count();
|
|
$pendingBookings = Booking::where('status', 'pending')->count();
|
|
$approvedBookings = Booking::where('status', 'accepted')->count();
|
|
$declinedBookings = Booking::where('status', 'declined')->count();
|
|
$totalCustomers = User::where('role', 'customer')->count();
|
|
$totalEmployees = User::where('role', 'user')->count();
|
|
$totalUsers = User::count();
|
|
$totalRevenue = Booking::sum('payment_method');
|
|
$bookings = Booking::with('customer')->get();
|
|
|
|
return view('admin.reports', compact(
|
|
'totalBookings',
|
|
'pendingBookings',
|
|
'approvedBookings',
|
|
'declinedBookings',
|
|
'totalCustomers',
|
|
'totalEmployees',
|
|
'totalUsers',
|
|
'totalRevenue',
|
|
'bookings',
|
|
));
|
|
}
|
|
|
|
public function showPricelist()
|
|
{
|
|
$pricelists = Pricelist::all();
|
|
return view('admin.reports', compact('pricelists'));
|
|
}
|
|
|
|
public function destroyPricelist($id)
|
|
{
|
|
$item = Pricelist::findOrFail($id);
|
|
|
|
// Hapus file gambar jika perlu
|
|
if ($item->gambar && \Storage::exists('public/' . $item->gambar)) {
|
|
\Storage::delete('public/' . $item->gambar);
|
|
}
|
|
|
|
$item->delete();
|
|
|
|
return redirect()->route('admin.reports')->with('success', 'Produk berhasil dihapus!');
|
|
}
|
|
|
|
|
|
public function update(Request $request, $id)
|
|
{
|
|
$pricelist = Pricelist::findOrFail($id);
|
|
|
|
$data = $request->only(['kategori', 'judul', 'deskripsi', 'harga']);
|
|
|
|
// Simpan paket sebagai JSON agar tetap array
|
|
if ($request->has('paket')) {
|
|
$data['paket'] = json_encode(array_values($request->input('paket')));
|
|
}
|
|
|
|
// Cek apakah gambar baru diupload
|
|
if ($request->hasFile('gambar')) {
|
|
// Buat folder kalau belum ada
|
|
$destination = public_path('images/pricelists');
|
|
if (!file_exists($destination)) {
|
|
mkdir($destination, 0755, true);
|
|
}
|
|
|
|
$file = $request->file('gambar');
|
|
$filename = time() . '_' . $file->getClientOriginalName();
|
|
|
|
// Simpan file ke folder public/images/pricelists
|
|
$file->move($destination, $filename);
|
|
$data['gambar'] = 'images/pricelists/' . $filename;
|
|
}
|
|
|
|
$pricelist->update($data);
|
|
|
|
return redirect()->route('admin.reports')->with('success', 'Produk berhasil diperbarui!');
|
|
}
|
|
|
|
|
|
|
|
public function storePricelist(Request $request)
|
|
{
|
|
$validated = $request->validate([
|
|
'kategori' => 'required|string|max:255',
|
|
'judul' => 'required|string|max:255',
|
|
'deskripsi' => 'required|string',
|
|
'harga' => 'required|numeric',
|
|
'gambar' => 'required|image|mimes:jpg,jpeg,png|max:512',
|
|
'paket' => 'nullable|array',
|
|
'paket.*.label' => 'nullable|string',
|
|
'paket.*.value' => 'nullable|string',
|
|
'paket.*.harga' => 'nullable|numeric',
|
|
]);
|
|
|
|
$data = $validated;
|
|
|
|
if ($request->hasFile('gambar')) {
|
|
$destination = public_path('images/pricelists');
|
|
|
|
// Buat folder kalau belum ada
|
|
if (!file_exists($destination)) {
|
|
mkdir($destination, 0755, true);
|
|
}
|
|
|
|
$file = $request->file('gambar');
|
|
$filename = time() . '_' . $file->getClientOriginalName();
|
|
|
|
// Simpan ke public_html
|
|
$file->move($destination, $filename);
|
|
|
|
// Simpan path-nya ke database (relatif dari domain)
|
|
$data['gambar'] = 'images/pricelist/' . $filename;
|
|
}
|
|
|
|
// Filter paket kosong
|
|
$filteredPaket = array_filter($request->input('paket', []), function($paket) {
|
|
return !empty($paket['label']) && !empty($paket['value']) && !empty($paket['harga']);
|
|
});
|
|
|
|
$data['paket'] = $filteredPaket;
|
|
|
|
Pricelist::create($data);
|
|
|
|
return redirect()->back()->with('success', 'Produk berhasil ditambahkan!');
|
|
}
|
|
|
|
public function destroy($id)
|
|
{
|
|
$booking = Booking::findOrFail($id);
|
|
$booking->delete();
|
|
|
|
return redirect()->back()->with('success', 'Booking berhasil dihapus.');
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|