user()->venue; if (!$venue) { return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.'); } // Check for auto reopen if ($venue->checkAutoReopen()) { session()->flash('success', 'Venue telah dibuka kembali secara otomatis!'); } return view('admin.venues.index', compact('venue')); } /** * Show the form for editing venue */ public function edit() { $venue = auth()->user()->venue()->with('images', 'operatingHours')->first(); // Tambahkan 'operatingHours' if (!$venue) { return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.'); } return view('admin.venues.edit', compact('venue')); } /** * Update venue information */ public function update(Request $request) { $venue = auth()->user()->venue; if (!$venue) { return redirect()->route('admin.dashboard')->with('error', 'Anda belum memiliki venue yang ditugaskan.'); } // 1. Pra-proses data jam operasional sebelum validasi $input = $request->all(); if (isset($input['hours'])) { foreach ($input['hours'] as $day => &$data) { // Gunakan '&' untuk modifikasi langsung // Jika 'is_closed' dicentang, atau jika input waktu kosong, paksa menjadi null if (isset($data['is_closed']) && $data['is_closed'] == 'on') { $data['open_time'] = null; $data['close_time'] = null; } } } // 2. Buat aturan validasi yang lebih pintar $validator = Validator::make($input, [ 'name' => 'required|string|max:255', 'address' => 'required|string|max:500', 'latitude' => 'nullable|string|max:255', 'longitude' => 'nullable|string|max:255', // ... (validasi lain tetap sama) ... 'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048', 'gallery_images.*' => 'image|mimes:jpeg,png,jpg,gif|max:2048', 'hours' => 'required|array|size:7', // Aturan baru: open_time wajib diisi KECUALI jika is_closed dicentang 'hours.*.open_time' => 'required_unless:hours.*.is_closed,on|nullable|date_format:H:i', 'hours.*.close_time' => 'required_unless:hours.*.is_closed,on|nullable|date_format:H:i', 'link_instagram' => 'nullable|url', 'link_tiktok' => 'nullable|url', 'link_facebook' => 'nullable|url', 'link_x' => 'nullable|url', ]); if ($validator->fails()) { return redirect()->back()->withErrors($validator)->withInput(); } try { // (Sisa dari kode ini tidak perlu diubah) $imagePath = $venue->image; if ($request->hasFile('image')) { /* ... logika upload ... */ } if ($request->hasFile('gallery_images')) { /* ... logika upload galeri ... */ } $venue->update([ 'name' => $request->name, 'address' => $request->address, 'latitude' => $request->latitude, 'longitude' => $request->longitude, 'phone' => $request->phone, 'link_instagram' => $request->link_instagram, 'link_tiktok' => $request->link_tiktok, 'link_facebook' => $request->link_facebook, 'link_x' => $request->link_x, 'description' => $request->description, 'image' => $imagePath, ]); foreach ($request->hours as $dayNumber => $hoursData) { $isClosed = isset($hoursData['is_closed']); $venue->operatingHours()->updateOrCreate( ['day_of_week' => $dayNumber], [ 'open_time' => $isClosed ? null : $hoursData['open_time'], 'close_time' => $isClosed ? null : $hoursData['close_time'], 'is_closed' => $isClosed, ] ); } return redirect()->route('admin.venue.index') ->with('success', 'Informasi venue berhasil diperbarui!'); } catch (\Exception $e) { return redirect()->back() ->with('error', 'Terjadi kesalahan: ' . $e->getMessage()) ->withInput(); } } public function destroyImage(VenueImage $image) { // Otorisasi: Pastikan admin yang sedang login adalah pemilik venue dari gambar ini // Kita bandingkan venue_id milik admin dengan venue_id milik gambar. if ($image->venue_id !== auth()->user()->venue_id) { return response()->json(['success' => false, 'message' => 'Akses tidak diizinkan.'], 403); } try { // Hapus file dari storage if (Storage::disk('public')->exists($image->path)) { Storage::disk('public')->delete($image->path); } // Hapus record dari database $image->delete(); return response()->json(['success' => true, 'message' => 'Gambar berhasil dihapus.']); } catch (\Exception $e) { // Catat error untuk debugging jika perlu // Log::error('Failed to delete gallery image: ' . $e->getMessage()); // Kirim respons error yang jelas return response()->json(['success' => false, 'message' => 'Gagal menghapus gambar di server.'], 500); } } /** * Toggle venue status (open/close) */ public function toggleStatus(Request $request) { $venue = auth()->user()->venue; if (!$venue) { return response()->json(['error' => 'Venue tidak ditemukan'], 404); } try { if ($venue->status === 'open') { // Closing venue - validate required fields $validator = Validator::make($request->all(), [ 'close_reason' => 'required|string|max:500', 'reopen_date' => 'required|date|after:today', ], [ 'close_reason.required' => 'Alasan penutupan harus diisi.', 'reopen_date.required' => 'Tanggal buka kembali harus diisi.', 'reopen_date.date' => 'Format tanggal tidak valid.', 'reopen_date.after' => 'Tanggal buka kembali harus setelah hari ini.', ]); if ($validator->fails()) { return response()->json([ 'error' => 'Validasi gagal', 'errors' => $validator->errors() ], 422); } $venue->closeVenue($request->close_reason, $request->reopen_date); $message = 'Venue berhasil ditutup!'; } else { // Opening venue $venue->openVenue(); $message = 'Venue berhasil dibuka!'; } return response()->json([ 'success' => true, 'message' => $message, 'status' => $venue->status, 'venue' => [ 'status' => $venue->status, 'close_reason' => $venue->close_reason, 'reopen_date' => $venue->reopen_date ? $venue->reopen_date->format('d M Y') : null, 'open_time' => $venue->open_time ? Carbon::parse($venue->open_time)->format('H:i') : null, 'close_time' => $venue->close_time ? Carbon::parse($venue->close_time)->format('H:i') : null, ] ]); } catch (\Exception $e) { return response()->json([ 'error' => 'Terjadi kesalahan: ' . $e->getMessage() ], 500); } } }