add template dll.
This commit is contained in:
parent
44dfdec0b0
commit
8a7d2eab98
@ -11,14 +11,14 @@ class FiturController extends Controller
|
|||||||
// Tampilkan semua fitur (halaman admin)
|
// Tampilkan semua fitur (halaman admin)
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$fiturs = Fitur::all();
|
$fitur = Fitur::all();
|
||||||
return view('fiturs.index', compact('fiturs'));
|
return view('admin.fitur.index', compact('fitur'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form tambah fitur
|
// Form tambah fitur
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('fiturs.create');
|
return view('admin.fitur.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simpan fitur baru
|
// Simpan fitur baru
|
||||||
@ -30,16 +30,9 @@ class FiturController extends Controller
|
|||||||
|
|
||||||
Fitur::create($data);
|
Fitur::create($data);
|
||||||
|
|
||||||
return redirect()->route('fiturs.index')->with('success', 'Fitur berhasil ditambahkan!');
|
return redirect()->route('admin.fitur.index')->with('success', 'Fitur berhasil ditambahkan!');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Form edit fitur
|
|
||||||
public function edit(Fitur $fitur)
|
|
||||||
{
|
|
||||||
return view('fiturs.edit', compact('fitur'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update fitur
|
|
||||||
public function update(Request $request, Fitur $fitur)
|
public function update(Request $request, Fitur $fitur)
|
||||||
{
|
{
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
@ -48,14 +41,16 @@ class FiturController extends Controller
|
|||||||
|
|
||||||
$fitur->update($data);
|
$fitur->update($data);
|
||||||
|
|
||||||
return redirect()->route('fiturs.index')->with('success', 'Fitur berhasil diperbarui!');
|
return redirect()->route('admin.fitur.index')->with('success', 'Fitur berhasil diperbarui!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Hapus fitur
|
// Hapus fitur
|
||||||
public function destroy(Fitur $fitur)
|
public function destroy(Fitur $fitur)
|
||||||
{
|
{
|
||||||
$fitur->delete();
|
$fitur->delete();
|
||||||
|
|
||||||
return redirect()->route('fiturs.index')->with('success', 'Fitur berhasil dihapus!');
|
return redirect()->route('admin.fitur.index')->with('success', 'Fitur berhasil dihapus!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,13 +10,13 @@ class KategoriController extends Controller
|
|||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$kategoris = Kategori::all();
|
$kategori = Kategori::all();
|
||||||
return view('kategoris.index', compact('kategoris'));
|
return view('admin.kategori.index', compact('kategori'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
return view('kategoris.create');
|
return view('admin.kategori.create');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
@ -24,16 +24,20 @@ class KategoriController extends Controller
|
|||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'nama' => 'required|string|max:255',
|
'nama' => 'required|string|max:255',
|
||||||
'deskripsi' => 'nullable|string',
|
'deskripsi' => 'nullable|string',
|
||||||
'foto' => 'nullable|string',
|
'foto' => 'nullable|image|mimes:jpg,jpeg,png,gif|max:5120',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
$data['foto'] = $request->file('foto')->store('kategori', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
Kategori::create($data);
|
Kategori::create($data);
|
||||||
return redirect()->route('kategoris.index')->with('success', 'Kategori berhasil ditambahkan!');
|
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil ditambahkan!');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Kategori $kategori)
|
public function edit(Kategori $kategori)
|
||||||
{
|
{
|
||||||
return view('kategoris.edit', compact('kategori'));
|
return view('admin.kategori.edit', compact('kategori'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Request $request, Kategori $kategori)
|
public function update(Request $request, Kategori $kategori)
|
||||||
@ -41,16 +45,20 @@ class KategoriController extends Controller
|
|||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'nama' => 'required|string|max:255',
|
'nama' => 'required|string|max:255',
|
||||||
'deskripsi' => 'nullable|string',
|
'deskripsi' => 'nullable|string',
|
||||||
'foto' => 'nullable|string',
|
'foto' => 'nullable|image|mimes:jpg,jpeg,png,gif|max:5120',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
$data['foto'] = $request->file('foto')->store('kategori', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
$kategori->update($data);
|
$kategori->update($data);
|
||||||
return redirect()->route('kategoris.index')->with('success', 'Kategori berhasil diperbarui!');
|
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil diperbarui!');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Kategori $kategori)
|
public function destroy(Kategori $kategori)
|
||||||
{
|
{
|
||||||
$kategori->delete();
|
$kategori->delete();
|
||||||
return redirect()->route('kategoris.index')->with('success', 'Kategori berhasil dihapus!');
|
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil dihapus!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,20 +10,20 @@ class PelangganController extends Controller
|
|||||||
// Tampilkan semua pelanggan (admin)
|
// Tampilkan semua pelanggan (admin)
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$pelanggans = Pelanggan::with('details')->get();
|
$pelanggans = Pelanggan::all();
|
||||||
return view('pelanggans.index', compact('pelanggans'));
|
return view('admin.pelanggan.index', compact('pelanggans'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detail pelanggan
|
// Detail pelanggan
|
||||||
public function show(Pelanggan $pelanggan)
|
public function show(Pelanggan $pelanggan)
|
||||||
{
|
{
|
||||||
return view('pelanggans.show', compact('pelanggan'));
|
return view('admin.pelanggan.show', compact('pelanggan'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hapus pelanggan
|
// Hapus pelanggan
|
||||||
public function destroy(Pelanggan $pelanggan)
|
public function destroy(Pelanggan $pelanggan)
|
||||||
{
|
{
|
||||||
$pelanggan->delete();
|
$pelanggan->delete();
|
||||||
return redirect()->route('pelanggans.index')->with('success', 'Pelanggan berhasil dihapus!');
|
return redirect()->route('admin.pelanggan.index')->with('success', 'Pelanggan berhasil dihapus!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,20 +6,17 @@ use App\Models\Template;
|
|||||||
use App\Models\Kategori;
|
use App\Models\Kategori;
|
||||||
use App\Models\Fitur;
|
use App\Models\Fitur;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
|
||||||
class TemplateController extends Controller
|
class TemplateController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$templates = Template::with(['kategori','fitur'])->get();
|
$templates = Template::with(['kategori','fitur'])->get();
|
||||||
return view('templates.index', compact('templates'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$kategoris = Kategori::all();
|
$kategoris = Kategori::all();
|
||||||
$fiturs = Fitur::all();
|
$fiturs = Fitur::all();
|
||||||
return view('templates.create', compact('kategoris', 'fiturs'));
|
|
||||||
|
return view('admin.templates.index', compact('templates', 'kategoris', 'fiturs'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
@ -28,36 +25,56 @@ class TemplateController extends Controller
|
|||||||
'nama_template' => 'required|string|max:255',
|
'nama_template' => 'required|string|max:255',
|
||||||
'kategori_id' => 'required|exists:kategoris,id',
|
'kategori_id' => 'required|exists:kategoris,id',
|
||||||
'fitur_id' => 'required|exists:fiturs,id',
|
'fitur_id' => 'required|exists:fiturs,id',
|
||||||
'foto' => 'nullable|string',
|
'foto' => 'nullable|image|mimes:jpg,jpeg,png,gif|max:5120',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
$data['foto'] = $request->file('foto')->store('templates', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
Template::create($data);
|
Template::create($data);
|
||||||
return redirect()->route('templates.index')->with('success', 'Template berhasil ditambahkan!');
|
return redirect()->route('templates.index')->with('success', 'Template berhasil ditambahkan!');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Template $template)
|
|
||||||
{
|
|
||||||
$kategoris = Kategori::all();
|
|
||||||
$fiturs = Fitur::all();
|
|
||||||
return view('templates.edit', compact('template','kategoris','fiturs'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(Request $request, Template $template)
|
public function update(Request $request, Template $template)
|
||||||
{
|
{
|
||||||
$data = $request->validate([
|
$data = $request->validate([
|
||||||
'nama_template' => 'required|string|max:255',
|
'nama_template' => 'required|string|max:255',
|
||||||
'kategori_id' => 'required|exists:kategoris,id',
|
'kategori_id' => 'required|exists:kategoris,id',
|
||||||
'fitur_id' => 'required|exists:fiturs,id',
|
'fitur_id' => 'required|exists:fiturs,id',
|
||||||
'foto' => 'nullable|string',
|
'foto' => 'nullable|image|mimes:jpg,jpeg,png,gif|max:5120',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($request->hasFile('foto')) {
|
||||||
|
if ($template->foto && Storage::disk('public')->exists($template->foto)) {
|
||||||
|
Storage::disk('public')->delete($template->foto);
|
||||||
|
}
|
||||||
|
$data['foto'] = $request->file('foto')->store('templates', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
$template->update($data);
|
$template->update($data);
|
||||||
return redirect()->route('templates.index')->with('success', 'Template berhasil diperbarui!');
|
return redirect()->route('templates.index')->with('success', 'Template berhasil diperbarui!');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Template $template)
|
public function destroy(Template $template)
|
||||||
{
|
{
|
||||||
|
if ($template->foto && Storage::disk('public')->exists($template->foto)) {
|
||||||
|
Storage::disk('public')->delete($template->foto);
|
||||||
|
}
|
||||||
|
|
||||||
$template->delete();
|
$template->delete();
|
||||||
return redirect()->route('templates.index')->with('success', 'Template berhasil dihapus!');
|
return redirect()->route('templates.index')->with('success', 'Template berhasil dihapus!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function byKategori($id)
|
||||||
|
{
|
||||||
|
$kategori = Kategori::findOrFail($id);
|
||||||
|
$templates = Template::with(['kategori','fitur'])
|
||||||
|
->where('kategori_id', $id)
|
||||||
|
->get();
|
||||||
|
$kategoris = Kategori::all();
|
||||||
|
$fiturs = Fitur::all();
|
||||||
|
|
||||||
|
return view('admin.templates.index', compact('templates', 'kategoris', 'fiturs', 'kategori'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<?
|
<?php
|
||||||
|
|
||||||
// database/migrations/2025_09_08_000001_create_kategoris_table.php
|
// database/migrations/2025_09_08_000001_create_kategoris_table.php
|
||||||
use Illuminate\Database\Migrations\Migration;
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h3 class="text-xl font-bold">Manajemen Fitur</h3>
|
<h3 class="text-xl font-bold">Manajemen Fitur</h3>
|
||||||
<button class="bg-blue-600 text-white px-3 py-1 rounded" data-bs-toggle="modal" data-bs-target="#modalTambah">
|
<button id="openTambahModal" class="bg-blue-600 text-white px-3 py-1 rounded flex items-center">
|
||||||
<i class="bi bi-plus-lg mr-1"></i> Tambah Fitur
|
<i class="bi bi-plus-lg mr-1"></i> Tambah Fitur
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Tabel Fitur -->
|
<!-- Tabel Fitur -->
|
||||||
<div class="bg-white rounded-lg shadow-sm">
|
<div class="bg-white rounded-lg shadow-sm">
|
||||||
<div class="p-4">
|
<div class="p-4 overflow-x-auto">
|
||||||
<table class="w-full table-fixed border border-gray-300 text-left">
|
<table class="w-full table-fixed border border-gray-300 text-left">
|
||||||
<thead class="bg-gray-100">
|
<thead class="bg-gray-100">
|
||||||
<tr>
|
<tr>
|
||||||
@ -24,19 +24,19 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse ($fiturs as $key => $fitur)
|
@forelse ($fitur as $key => $item)
|
||||||
<tr class="hover:bg-gray-50">
|
<tr class="hover:bg-gray-50">
|
||||||
<td class="p-2 border border-gray-300">{{ $key + 1 }}</td>
|
<td class="p-2 border border-gray-300">{{ $key + 1 }}</td>
|
||||||
<td class="p-2 border border-gray-300 truncate whitespace-nowrap">{{ $fitur->nama_fitur }}</td>
|
<td class="p-2 border border-gray-300 truncate whitespace-nowrap">{{ $item->deskripsi }}
|
||||||
|
</td>
|
||||||
<td class="p-2 border border-gray-300 text-center">
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
<div class="flex justify-center space-x-2">
|
<div class="flex justify-center space-x-2">
|
||||||
<button class="text-blue-600 flex items-center pr-4" data-bs-toggle="modal" data-bs-target="#modalEdit{{ $fitur->id }}">
|
<button class="text-blue-600 flex items-center pr-4 openEditModalBtn"
|
||||||
|
data-id="{{ $item->id }}">
|
||||||
<i class="bi bi-pencil mr-1"></i> Ubah
|
<i class="bi bi-pencil mr-1"></i> Ubah
|
||||||
</button>
|
</button>
|
||||||
<form action="{{ route('admin.fitur.destroy', $fitur->id) }}"
|
<form action="{{ route('admin.fitur.destroy', $item->id) }}" method="POST"
|
||||||
method="POST"
|
class="inline" onsubmit="return confirm('Yakin mau hapus fitur ini?')">
|
||||||
class="inline"
|
|
||||||
onsubmit="return confirm('Yakin mau hapus fitur ini?')">
|
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<button class="text-red-600 flex items-center">
|
<button class="text-red-600 flex items-center">
|
||||||
@ -53,28 +53,28 @@
|
|||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal Tambah -->
|
<!-- Modal Tambah -->
|
||||||
<div class="modal fade" id="modalTambah" tabindex="-1">
|
<div id="modalTambah" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
<div class="modal-dialog">
|
<div class="absolute inset-0 bg-black opacity-50" id="closeTambahModal"></div>
|
||||||
<form action="{{ route('admin.fitur.store') }}" method="POST" class="modal-content">
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<form action="{{ route('admin.fitur.store') }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
<div class="modal-header">
|
<div class="p-4 border-b">
|
||||||
<h5 class="modal-title text-lg font-medium">Tambah Fitur</h5>
|
<h5 class="text-lg font-medium">Tambah Fitur</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="p-4 space-y-4">
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Nama Fitur</label>
|
<label class="block text-sm font-medium">Nama Fitur</label>
|
||||||
<input type="text" name="nama_fitur" class="w-full p-2 border rounded" required>
|
<input type="text" name="deskripsi" class="w-full p-2 border rounded" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
<button class="bg-gray-300 text-black px-3 py-1 rounded" data-bs-dismiss="modal">Batal</button>
|
<button type="button" id="closeTambahBtn"
|
||||||
|
class="bg-gray-300 text-black px-3 py-1 rounded">Batal</button>
|
||||||
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan</button>
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -82,28 +82,83 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Modal Edit -->
|
<!-- Modal Edit -->
|
||||||
@foreach ($fiturs as $fitur)
|
@foreach ($fitur as $item)
|
||||||
<div class="modal fade" id="modalEdit{{ $fitur->id }}" tabindex="-1">
|
<div id="modalEdit{{ $item->id }}" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
<div class="modal-dialog">
|
<div class="absolute inset-0 bg-black opacity-50 closeEditOverlay" data-id="{{ $item->id }}"></div>
|
||||||
<form action="{{ route('admin.fitur.update', $fitur->id) }}" method="POST" class="modal-content">
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<form action="{{ route('admin.fitur.update', $item->id) }}" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
<div class="modal-header">
|
<div class="p-4 border-b">
|
||||||
<h5 class="modal-title text-lg font-medium">Edit Fitur</h5>
|
<h5 class="text-lg font-medium">Edit Fitur</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="p-4 space-y-4">
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Nama Fitur</label>
|
<label class="block text-sm font-medium">Nama Fitur</label>
|
||||||
<input type="text" name="nama_fitur" value="{{ $fitur->nama_fitur }}" class="w-full p-2 border rounded" required>
|
<input type="text" name="deskripsi" value="{{ $item->deskripsi }}"
|
||||||
|
class="w-full p-2 border rounded" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
<button class="bg-gray-300 text-black px-3 py-1 rounded" data-bs-dismiss="modal">Batal</button>
|
<button type="button" class="bg-gray-300 text-black px-3 py-1 rounded closeEditBtn"
|
||||||
|
data-id="{{ $item->id }}">Batal</button>
|
||||||
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan Perubahan</button>
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan Perubahan</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Modal Tambah
|
||||||
|
const openTambahModal = document.getElementById('openTambahModal');
|
||||||
|
const modalTambah = document.getElementById('modalTambah');
|
||||||
|
const closeTambahBtn = document.getElementById('closeTambahBtn');
|
||||||
|
const closeTambahOverlay = document.getElementById('closeTambahModal');
|
||||||
|
|
||||||
|
openTambahModal.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.remove('hidden');
|
||||||
|
modalTambah.classList.add('flex');
|
||||||
|
});
|
||||||
|
closeTambahBtn.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
closeTambahOverlay.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modal Edit
|
||||||
|
const openEditBtns = document.querySelectorAll('.openEditModalBtn');
|
||||||
|
const closeEditBtns = document.querySelectorAll('.closeEditBtn');
|
||||||
|
const closeEditOverlays = document.querySelectorAll('.closeEditOverlay');
|
||||||
|
|
||||||
|
openEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
modal.classList.add('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditOverlays.forEach(overlay => {
|
||||||
|
overlay.addEventListener('click', () => {
|
||||||
|
const id = overlay.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
@ -7,7 +7,7 @@
|
|||||||
<!-- Header -->
|
<!-- Header -->
|
||||||
<div class="flex justify-between items-center mb-4">
|
<div class="flex justify-between items-center mb-4">
|
||||||
<h3 class="text-xl font-bold">Manajemen Kategori</h3>
|
<h3 class="text-xl font-bold">Manajemen Kategori</h3>
|
||||||
<button class="bg-blue-600 text-white px-3 py-2.5 rounded" data-bs-toggle="modal" data-bs-target="#modalTambah">
|
<button id="openTambahModal" class="bg-blue-600 text-white px-3 py-2.5 rounded flex items-center">
|
||||||
<i class="bi bi-plus-lg mr-1"></i> Nambah Kategori
|
<i class="bi bi-plus-lg mr-1"></i> Nambah Kategori
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<!-- Tabel Kategori -->
|
<!-- Tabel Kategori -->
|
||||||
<div class="bg-white rounded-lg shadow-sm">
|
<div class="bg-white rounded-lg shadow-sm">
|
||||||
<div class="p-4">
|
<div class="p-4 overflow-x-auto">
|
||||||
<table class="w-full table-fixed text-left border border-gray-300 border-collapse">
|
<table class="w-full table-fixed text-left border border-gray-300 border-collapse">
|
||||||
<thead class="bg-gray-100">
|
<thead class="bg-gray-100">
|
||||||
<tr>
|
<tr>
|
||||||
@ -57,25 +57,19 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td class="p-2 border border-gray-300 text-center truncate">{{ $key + 1 }}</td>
|
<td class="p-2 border border-gray-300 text-center truncate">{{ $key + 1 }}</td>
|
||||||
<td class="p-2 border border-gray-300 truncate">{{ $item->nama }}</td>
|
<td class="p-2 border border-gray-300 truncate">{{ $item->nama }}</td>
|
||||||
<td class="p-2 border border-gray-300 truncate">
|
<td class="p-2 border border-gray-300 truncate">{{ $item->deskripsi ?? '-' }}</td>
|
||||||
{{ $item->deskripsi ?? '-' }}
|
|
||||||
</td>
|
|
||||||
<td class="p-2 border border-gray-300 text-center">
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
<div
|
<div
|
||||||
class="w-12 h-12 overflow-hidden rounded bg-gray-100 flex items-center justify-center mx-auto">
|
class="w-12 h-12 overflow-hidden rounded bg-gray-100 flex items-center justify-center mx-auto">
|
||||||
@if ($item->foto)
|
<img src="{{ $item->foto ? asset('storage/' . $item->foto) : asset('default-image.png') }}"
|
||||||
<img src="{{ asset('storage/' . $item->foto) }}" alt="foto"
|
alt="foto" class="max-w-full max-h-full object-contain">
|
||||||
class="max-w-full max-h-full object-contain">
|
|
||||||
@else
|
|
||||||
<img src="{{ asset('default-image.png') }}" alt="default"
|
|
||||||
class="max-w-full max-h-full object-contain">
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-2 border border-gray-300 text-center">
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
<div class="flex justify-center space-x-2">
|
<div class="flex justify-center space-x-2">
|
||||||
<button class="text-blue-600 hover:underline flex items-center pr-4"
|
<button
|
||||||
data-bs-toggle="modal" data-bs-target="#modalEdit{{ $item->id }}">
|
class="text-blue-600 hover:underline flex items-center pr-4 openEditModalBtn"
|
||||||
|
data-id="{{ $item->id }}">
|
||||||
<i class="bi bi-pencil mr-1"></i> Ubah
|
<i class="bi bi-pencil mr-1"></i> Ubah
|
||||||
</button>
|
</button>
|
||||||
<form action="{{ route('admin.kategori.destroy', $item->id) }}" method="POST"
|
<form action="{{ route('admin.kategori.destroy', $item->id) }}" method="POST"
|
||||||
@ -97,37 +91,37 @@
|
|||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="modal fade" id="modalTambah" tabindex="-1">
|
<!-- Modal Tambah -->
|
||||||
<div class="modal-dialog">
|
<div id="modalTambah" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
<form action="{{ route('admin.kategori.store') }}" method="POST" enctype="multipart/form-data"
|
<div class="absolute inset-0 bg-black opacity-50" id="closeTambahModal"></div>
|
||||||
class="modal-content">
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<form action="{{ route('admin.kategori.store') }}" method="POST" enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
<div class="modal-header">
|
<div class="p-4 border-b">
|
||||||
<h5 class="modal-title text-lg font-medium">Tambah Kategori</h5>
|
<h5 class="text-lg font-medium">Tambah Kategori</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="p-4 space-y-4">
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Nama</label>
|
<label class="block text-sm font-medium">Nama</label>
|
||||||
<input type="text" name="nama" class="w-full p-2 border rounded" required>
|
<input type="text" name="nama" class="w-full p-2 border rounded" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Deskripsi</label>
|
<label class="block text-sm font-medium">Deskripsi</label>
|
||||||
<textarea name="deskripsi" class="w-full p-2 border rounded" rows="3"></textarea>
|
<textarea name="deskripsi" class="w-full p-2 border rounded" rows="3"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Foto</label>
|
<label class="block text-sm font-medium">Foto</label>
|
||||||
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
||||||
<small class="text-gray-500">Format yang didukung: JPG, PNG, GIF. Maksimal 5MB.</small>
|
<small class="text-gray-500">Format yang didukung: JPG, PNG, GIF. Maksimal 5MB.</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
<button class="bg-gray-300 text-black px-3 py-1 rounded" data-bs-dismiss="modal">Batal</button>
|
<button type="button" id="closeTambahBtn"
|
||||||
|
class="bg-gray-300 text-black px-3 py-1 rounded">Batal</button>
|
||||||
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan</button>
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -136,27 +130,27 @@
|
|||||||
|
|
||||||
<!-- Modal Edit -->
|
<!-- Modal Edit -->
|
||||||
@foreach ($kategori as $item)
|
@foreach ($kategori as $item)
|
||||||
<div class="modal fade" id="modalEdit{{ $item->id }}" tabindex="-1">
|
<div id="modalEdit{{ $item->id }}" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
<div class="modal-dialog">
|
<div class="absolute inset-0 bg-black opacity-50 closeEditOverlay" data-id="{{ $item->id }}"></div>
|
||||||
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
<form action="{{ route('admin.kategori.update', $item->id) }}" method="POST"
|
<form action="{{ route('admin.kategori.update', $item->id) }}" method="POST"
|
||||||
enctype="multipart/form-data" class="modal-content">
|
enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
@method('PUT')
|
@method('PUT')
|
||||||
<div class="modal-header">
|
<div class="p-4 border-b">
|
||||||
<h5 class="modal-title text-lg font-medium">Edit Kategori</h5>
|
<h5 class="text-lg font-medium">Edit Kategori</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="p-4 space-y-4">
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Nama</label>
|
<label class="block text-sm font-medium">Nama</label>
|
||||||
<input type="text" name="nama" value="{{ $item->nama }}"
|
<input type="text" name="nama" value="{{ $item->nama }}"
|
||||||
class="w-full p-2 border rounded" required>
|
class="w-full p-2 border rounded" required>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Deskripsi</label>
|
<label class="block text-sm font-medium">Deskripsi</label>
|
||||||
<textarea name="deskripsi" class="w-full p-2 border rounded" rows="3">{{ $item->deskripsi }}</textarea>
|
<textarea name="deskripsi" class="w-full p-2 border rounded" rows="3">{{ $item->deskripsi }}</textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
<div>
|
||||||
<label class="block text-sm font-medium">Foto</label>
|
<label class="block text-sm font-medium">Foto</label>
|
||||||
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
||||||
<small class="text-gray-500">Format yang didukung: JPG, PNG, GIF. Maksimal 5MB.</small>
|
<small class="text-gray-500">Format yang didukung: JPG, PNG, GIF. Maksimal 5MB.</small>
|
||||||
@ -172,13 +166,66 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
<button class="bg-gray-300 text-black px-3 py-1 rounded"
|
<button type="button" class="bg-gray-300 text-black px-3 py-1 rounded closeEditBtn"
|
||||||
data-bs-dismiss="modal">Batal</button>
|
data-id="{{ $item->id }}">Batal</button>
|
||||||
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan Perubahan</button>
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan Perubahan</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Modal Tambah
|
||||||
|
const openTambahModal = document.getElementById('openTambahModal');
|
||||||
|
const modalTambah = document.getElementById('modalTambah');
|
||||||
|
const closeTambahBtn = document.getElementById('closeTambahBtn');
|
||||||
|
const closeTambahOverlay = document.getElementById('closeTambahModal');
|
||||||
|
|
||||||
|
openTambahModal.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.remove('hidden');
|
||||||
|
modalTambah.classList.add('flex');
|
||||||
|
});
|
||||||
|
closeTambahBtn.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
closeTambahOverlay.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modal Edit
|
||||||
|
const openEditBtns = document.querySelectorAll('.openEditModalBtn');
|
||||||
|
const closeEditBtns = document.querySelectorAll('.closeEditBtn');
|
||||||
|
const closeEditOverlays = document.querySelectorAll('.closeEditOverlay');
|
||||||
|
|
||||||
|
openEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
modal.classList.add('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditOverlays.forEach(overlay => {
|
||||||
|
overlay.addEventListener('click', () => {
|
||||||
|
const id = overlay.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
133
backend/resources/views/admin/pelanggan/index.blade.php
Normal file
133
backend/resources/views/admin/pelanggan/index.blade.php
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Manajemen Pelanggan')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto py-4">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<h3 class="text-xl font-bold">Manajemen Pelanggan</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Flash Message -->
|
||||||
|
@if (session('success'))
|
||||||
|
<div id="toast-success" class="mb-4 p-3 rounded bg-green-100 text-green-800 border border-green-300 shadow">
|
||||||
|
{{ session('success') }}
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(() => document.getElementById('toast-success')?.remove(), 3000);
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Tabel Pelanggan -->
|
||||||
|
<div class="bg-white rounded-lg shadow-sm">
|
||||||
|
<div class="p-4 overflow-x-auto">
|
||||||
|
<table class="w-full table-fixed text-left border border-gray-300 border-collapse">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="p-2 border border-gray-300 w-[50px] text-center">No</th>
|
||||||
|
<th class="p-2 border border-gray-300">Nama</th>
|
||||||
|
<th class="p-2 border border-gray-300">Email</th>
|
||||||
|
<th class="p-2 border border-gray-300">No. Telepon</th>
|
||||||
|
<th class="p-2 border border-gray-300 text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($pelanggans as $key => $pelanggan)
|
||||||
|
<tr>
|
||||||
|
<td class="p-2 border border-gray-300 text-center">{{ $key + 1 }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $pelanggan->nama_pemesan }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $pelanggan->email }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $pelanggan->no_tlpn ?? '-' }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
|
<div class="flex justify-center space-x-2">
|
||||||
|
<a href="{{ route('admin.pelanggan.show', $pelanggan->id) }}"
|
||||||
|
class="text-blue-600 hover:underline flex items-center">
|
||||||
|
<i class="bi bi-eye mr-1"></i> Detail
|
||||||
|
</a>
|
||||||
|
<button class="text-red-600 hover:underline flex items-center openDeleteModalBtn"
|
||||||
|
data-id="{{ $pelanggan->id }}">
|
||||||
|
<i class="bi bi-trash mr-1"></i> Hapus
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="p-2 text-center text-gray-500 border border-gray-300">Belum ada
|
||||||
|
pelanggan</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Hapus Pelanggan -->
|
||||||
|
@foreach ($pelanggans as $pelanggan)
|
||||||
|
<div id="modalDelete{{ $pelanggan->id }}" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
|
<div class="absolute inset-0 bg-black opacity-50 closeDeleteOverlay" data-id="{{ $pelanggan->id }}"></div>
|
||||||
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<div class="p-4 border-b">
|
||||||
|
<h5 class="text-lg font-medium">Hapus Pelanggan</h5>
|
||||||
|
</div>
|
||||||
|
<div class="p-4">
|
||||||
|
<p>Apakah Anda yakin ingin menghapus pelanggan <strong>{{ $pelanggan->nama }}</strong>?</p>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
|
<button type="button" class="bg-gray-300 text-black px-3 py-1 rounded closeDeleteBtn"
|
||||||
|
data-id="{{ $pelanggan->id }}">Batal</button>
|
||||||
|
<form action="{{ route('admin.pelanggan.destroy', $pelanggan->id) }}" method="POST" class="inline">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button class="bg-red-600 text-white px-3 py-1 rounded">Hapus</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const openDeleteBtns = document.querySelectorAll('.openDeleteModalBtn');
|
||||||
|
const closeDeleteBtns = document.querySelectorAll('.closeDeleteBtn');
|
||||||
|
const closeDeleteOverlays = document.querySelectorAll('.closeDeleteOverlay');
|
||||||
|
|
||||||
|
openDeleteBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalDelete' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
modal.classList.add('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeDeleteBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalDelete' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeDeleteOverlays.forEach(overlay => {
|
||||||
|
overlay.addEventListener('click', () => {
|
||||||
|
const id = overlay.dataset.id;
|
||||||
|
const modal = document.getElementById('modalDelete' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
@ -66,24 +66,24 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Konfirmasi Hapus Tailwind -->
|
||||||
<!-- Modal Konfirmasi Hapus -->
|
<div id="modalDelete" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
<div class="modal fade" id="confirmDeleteModal" tabindex="-1">
|
<div class="absolute inset-0 bg-black opacity-50" id="modalDeleteOverlay"></div>
|
||||||
<div class="modal-dialog">
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
<form id="deleteForm" method="POST" class="modal-content">
|
<form id="deleteForm" method="POST">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<div class="modal-header">
|
<div class="p-4 border-b">
|
||||||
<h5 class="modal-title text-lg font-medium">Hapus Ulasan</h5>
|
<h5 class="text-lg font-medium">Hapus Ulasan</h5>
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="p-4">
|
||||||
Apakah Anda yakin ingin menghapus ulasan dari <strong id="deleteName">—</strong>?
|
Apakah Anda yakin ingin menghapus ulasan dari <strong id="deleteName">—</strong>?
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
<button type="button" class="bg-gray-300 text-black px-3 py-1 rounded"
|
<button type="button" id="closeDeleteModal"
|
||||||
data-bs-dismiss="modal">Batal</button>
|
class="bg-gray-300 text-black px-3 py-1 rounded">Batal</button>
|
||||||
<button type="submit" class="bg-red-600 text-white px-3 py-1 rounded">Ya, Hapus</button>
|
<button type="submit" class="bg-red-600 text-white px-3 py-1 rounded">Ya, Hapus</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@ -92,7 +92,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const modalEl = document.getElementById('confirmDeleteModal');
|
const modal = document.getElementById('modalDelete');
|
||||||
|
const overlay = document.getElementById('modalDeleteOverlay');
|
||||||
|
const closeBtn = document.getElementById('closeDeleteModal');
|
||||||
const deleteForm = document.getElementById('deleteForm');
|
const deleteForm = document.getElementById('deleteForm');
|
||||||
const deleteName = document.getElementById('deleteName');
|
const deleteName = document.getElementById('deleteName');
|
||||||
|
|
||||||
@ -100,9 +102,18 @@
|
|||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
deleteForm.action = btn.dataset.action;
|
deleteForm.action = btn.dataset.action;
|
||||||
deleteName.textContent = btn.dataset.name || 'pengguna ini';
|
deleteName.textContent = btn.dataset.name || 'pengguna ini';
|
||||||
new bootstrap.Modal(modalEl).show();
|
modal.classList.remove('hidden');
|
||||||
|
modal.classList.add('flex');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
}
|
||||||
|
|
||||||
|
closeBtn.addEventListener('click', closeModal);
|
||||||
|
overlay.addEventListener('click', closeModal);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
277
backend/resources/views/admin/templates/index.blade.php
Normal file
277
backend/resources/views/admin/templates/index.blade.php
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('title', 'Manajemen Template')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mx-auto py-4">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="flex justify-between items-center mb-4">
|
||||||
|
<h3 class="text-xl font-bold">
|
||||||
|
@isset($kategori)
|
||||||
|
Template Kategori: {{ $kategori->nama }}
|
||||||
|
@else
|
||||||
|
Semua Template
|
||||||
|
@endisset
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
@if (!isset($kategori))
|
||||||
|
<button id="openTambahModal" class="bg-blue-600 text-white px-3 py-2.5 rounded flex items-center">
|
||||||
|
<i class="bi bi-plus-lg mr-1"></i> Tambah Template
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Flash Message -->
|
||||||
|
@if (session('success'))
|
||||||
|
<div id="toast-success" class="mb-4 p-3 rounded bg-green-100 text-green-800 border border-green-300 shadow">
|
||||||
|
{{ session('success') }}
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(() => document.getElementById('toast-success')?.remove(), 3000);
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($errors->any())
|
||||||
|
<div id="toast-error" class="mb-4 p-3 rounded bg-red-100 text-red-800 border border-red-300 shadow">
|
||||||
|
<ul class="list-disc ml-5">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
setTimeout(() => document.getElementById('toast-error')?.remove(), 5000);
|
||||||
|
</script>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Tabel Template -->
|
||||||
|
<div class="bg-white rounded-lg shadow-sm">
|
||||||
|
<div class="p-4 overflow-x-auto">
|
||||||
|
<table class="w-full table-fixed text-left border border-gray-300 border-collapse">
|
||||||
|
<thead class="bg-gray-100">
|
||||||
|
<tr>
|
||||||
|
<th class="p-2 border border-gray-300 w-[50px] text-center">No</th>
|
||||||
|
<th class="p-2 border border-gray-300 w-[200px]">Nama Template</th>
|
||||||
|
<th class="p-2 border border-gray-300 w-[150px]">Kategori</th>
|
||||||
|
<th class="p-2 border border-gray-300 w-[150px]">Fitur</th>
|
||||||
|
<th class="p-2 border border-gray-300 w-[90px] text-center">Foto</th>
|
||||||
|
<th class="p-2 border border-gray-300 w-[130px] text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse($templates as $key => $template)
|
||||||
|
<tr>
|
||||||
|
<td class="p-2 border border-gray-300 text-center">{{ $key + 1 }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $template->nama_template }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $template->kategori->nama ?? '-' }}</td>
|
||||||
|
<td class="p-2 border border-gray-300 truncate">{{ $template->fitur->deskripsi ?? '-' }}
|
||||||
|
</td>
|
||||||
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
|
<div
|
||||||
|
class="w-12 h-12 overflow-hidden rounded bg-gray-100 flex items-center justify-center mx-auto">
|
||||||
|
<img src="{{ $template->foto ? asset('storage/' . $template->foto) : asset('default-image.png') }}"
|
||||||
|
alt="foto" class="max-w-full max-h-full object-contain">
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="p-2 border border-gray-300 text-center">
|
||||||
|
<div class="flex justify-center space-x-2">
|
||||||
|
<button class="text-blue-600 hover:underline flex items-center openEditModalBtn"
|
||||||
|
data-id="{{ $template->id }}">
|
||||||
|
<i class="bi bi-pencil mr-1"></i> Edit
|
||||||
|
</button>
|
||||||
|
<form action="{{ route('templates.destroy', $template->id) }}" method="POST"
|
||||||
|
class="inline" onsubmit="return confirm('Hapus template ini?')">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button class="text-red-600 hover:underline flex items-center">
|
||||||
|
<i class="bi bi-trash mr-1"></i> Hapus
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="p-2 text-center text-gray-500 border border-gray-300">Belum ada
|
||||||
|
template</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Modal Tambah Template -->
|
||||||
|
@if (!isset($kategori))
|
||||||
|
<div id="modalTambah" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
|
<div class="absolute inset-0 bg-black opacity-50" id="closeTambahModal"></div>
|
||||||
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<form action="{{ route('templates.store') }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
<div class="p-4 border-b">
|
||||||
|
<h5 class="text-lg font-medium">Tambah Template</h5>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Nama Template</label>
|
||||||
|
<input type="text" name="nama_template" class="w-full p-2 border rounded" required>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Kategori</label>
|
||||||
|
<select name="kategori_id" class="w-full p-2 border rounded" required>
|
||||||
|
@foreach ($kategoris as $kategori)
|
||||||
|
<option value="{{ $kategori->id }}">{{ $kategori->nama }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Fitur</label>
|
||||||
|
<select name="fitur_id" class="w-full p-2 border rounded" required>
|
||||||
|
@foreach ($fiturs as $fitur)
|
||||||
|
<option value="{{ $fitur->id }}">{{ $fitur->deskripsi }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Foto (opsional)</label>
|
||||||
|
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
||||||
|
<small class="text-gray-500">Format yang didukung: JPG, PNG, GIF. Maksimal 5MB.</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
|
<button type="button" id="closeTambahBtn"
|
||||||
|
class="bg-gray-300 text-black px-3 py-1 rounded">Batal</button>
|
||||||
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Modal Edit Template -->
|
||||||
|
@foreach ($templates as $template)
|
||||||
|
<div id="modalEdit{{ $template->id }}" class="fixed inset-0 hidden items-center justify-center z-50">
|
||||||
|
<div class="absolute inset-0 bg-black opacity-50 closeEditOverlay" data-id="{{ $template->id }}"></div>
|
||||||
|
<div class="bg-white rounded-lg shadow-lg w-full max-w-md z-50 overflow-hidden">
|
||||||
|
<form action="{{ route('templates.update', $template->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf @method('PUT')
|
||||||
|
<div class="p-4 border-b">
|
||||||
|
<h5 class="text-lg font-medium">Edit Template</h5>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 space-y-4">
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Nama Template</label>
|
||||||
|
<input type="text" name="nama_template" value="{{ $template->nama_template }}"
|
||||||
|
class="w-full p-2 border rounded" required>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Kategori</label>
|
||||||
|
<select name="kategori_id" class="w-full p-2 border rounded" required>
|
||||||
|
@foreach ($kategoris as $kategori)
|
||||||
|
<option value="{{ $kategori->id }}" @selected($kategori->id == $template->kategori_id)>{{ $kategori->nama }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Fitur</label>
|
||||||
|
<select name="fitur_id" class="w-full p-2 border rounded" required>
|
||||||
|
@foreach ($fiturs as $fitur)
|
||||||
|
<option value="{{ $fitur->id }}" @selected($fitur->id == $template->fitur_id)>
|
||||||
|
{{ $fitur->deskripsi }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="block text-sm font-medium">Foto (opsional)</label>
|
||||||
|
@if ($template->foto)
|
||||||
|
<div class="mb-2">
|
||||||
|
<small class="text-gray-500">Foto saat ini:</small>
|
||||||
|
<div
|
||||||
|
class="w-20 h-20 mt-1 overflow-hidden rounded bg-gray-100 flex items-center justify-center border">
|
||||||
|
<img src="{{ asset('storage/' . $template->foto) }}" alt="foto"
|
||||||
|
class="max-w-full max-h-full object-contain">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
<input type="file" name="foto" class="w-full p-2 border rounded" accept="image/*">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="p-4 border-t flex justify-end space-x-2">
|
||||||
|
<button type="button" class="bg-gray-300 text-black px-3 py-1 rounded closeEditBtn"
|
||||||
|
data-id="{{ $template->id }}">Batal</button>
|
||||||
|
<button class="bg-blue-600 text-white px-3 py-1 rounded">Simpan Perubahan</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// Modal Tambah
|
||||||
|
const openTambahModal = document.getElementById('openTambahModal');
|
||||||
|
const modalTambah = document.getElementById('modalTambah');
|
||||||
|
const closeTambahBtn = document.getElementById('closeTambahBtn');
|
||||||
|
const closeTambahOverlay = document.getElementById('closeTambahModal');
|
||||||
|
|
||||||
|
if (openTambahModal) {
|
||||||
|
openTambahModal.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.remove('hidden');
|
||||||
|
modalTambah.classList.add('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (closeTambahBtn) {
|
||||||
|
closeTambahBtn.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (closeTambahOverlay) {
|
||||||
|
closeTambahOverlay.addEventListener('click', () => {
|
||||||
|
modalTambah.classList.add('hidden');
|
||||||
|
modalTambah.classList.remove('flex');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modal Edit
|
||||||
|
const openEditBtns = document.querySelectorAll('.openEditModalBtn');
|
||||||
|
const closeEditBtns = document.querySelectorAll('.closeEditBtn');
|
||||||
|
const closeEditOverlays = document.querySelectorAll('.closeEditOverlay');
|
||||||
|
|
||||||
|
openEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.remove('hidden');
|
||||||
|
modal.classList.add('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditBtns.forEach(btn => {
|
||||||
|
btn.addEventListener('click', () => {
|
||||||
|
const id = btn.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
closeEditOverlays.forEach(overlay => {
|
||||||
|
overlay.addEventListener('click', () => {
|
||||||
|
const id = overlay.dataset.id;
|
||||||
|
const modal = document.getElementById('modalEdit' + id);
|
||||||
|
if (modal) {
|
||||||
|
modal.classList.add('hidden');
|
||||||
|
modal.classList.remove('flex');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
@ -5,16 +5,15 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>@yield('title', 'Admin Panel')</title>
|
<title>@yield('title', 'Admin Panel')</title>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f1f5f9;
|
background-color: #f1f5f9;
|
||||||
font-family: 'Poppins', sans-serif;
|
font-family: 'Poppins', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SIDEBAR */
|
/* Sidebar */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 250px;
|
width: 250px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@ -29,156 +28,99 @@
|
|||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar .logo {
|
|
||||||
text-align: center;
|
|
||||||
padding: 20px 0;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .logo img {
|
|
||||||
width: 130px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar .menu-title {
|
|
||||||
font-size: 11px;
|
|
||||||
font-weight: 600;
|
|
||||||
padding: 15px 20px 5px;
|
|
||||||
color: #6c757d;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: .5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul {
|
|
||||||
list-style: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul li a {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 12px 20px;
|
|
||||||
color: #495057;
|
|
||||||
text-decoration: none;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
border-left: 3px solid transparent;
|
|
||||||
transition: all 0.25s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul li a:hover {
|
|
||||||
background-color: #f1f5ff;
|
|
||||||
color: #0d6efd;
|
|
||||||
border-left: 3px solid #0d6efd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul li a.active {
|
|
||||||
background-color: #eef4ff;
|
|
||||||
color: #0d6efd;
|
|
||||||
border-left: 3px solid #0d6efd;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar ul li a i {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Submenu */
|
|
||||||
.submenu {
|
.submenu {
|
||||||
padding-left: 55px;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.submenu a {
|
.submenu.show {
|
||||||
font-size: 13px;
|
display: block;
|
||||||
padding: 8px 20px;
|
|
||||||
color: #6c757d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submenu a:hover {
|
|
||||||
color: #0d6efd;
|
|
||||||
background: transparent;
|
|
||||||
border-left: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* MAIN CONTENT */
|
|
||||||
.main-content {
|
|
||||||
margin-left: 250px;
|
|
||||||
padding: 25px;
|
|
||||||
min-height: 100vh;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body class="flex">
|
||||||
|
|
||||||
<!-- Sidebar -->
|
<!-- Sidebar -->
|
||||||
<div id="sidebar" class="sidebar bg-white d-flex flex-column">
|
<div class="sidebar flex flex-col">
|
||||||
|
|
||||||
<!-- LOGO -->
|
<!-- LOGO -->
|
||||||
<div class="sidebar-header text-center py-4 px-10">
|
<div class="text-center py-4 border-b">
|
||||||
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="img-fluid mb-2" style="max-height: 80px;">
|
<img src="{{ asset('images/logo.png') }}" alt="Logo" class="mx-auto mb-2" style="max-height: 80px;">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- MENU -->
|
<!-- MENU -->
|
||||||
<div class="sidebar-menu flex-grow-1">
|
<div class="flex-1 overflow-y-auto">
|
||||||
<p class="menu-title text-muted px-3 mb-2">Menu Utama</p>
|
<p class="text-gray-500 uppercase text-xs font-semibold px-3 mt-4 mb-2">Menu Utama</p>
|
||||||
<ul class="list-unstyled px-2">
|
<ul class="px-2 space-y-1">
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('admin.dashboard') }}"
|
<a href="{{ route('admin.dashboard') }}"
|
||||||
class="d-flex align-items-center py-2 px-3 {{ request()->is('admin/dashboard') ? 'active' : '' }}">
|
class="flex items-center py-2 px-3 rounded hover:bg-blue-50 {{ request()->is('admin/dashboard') ? 'bg-blue-100 text-blue-600' : 'text-gray-700' }}">
|
||||||
<i class="bi bi-house-door me-2"></i> Dasbor
|
<i class="bi bi-house-door me-2"></i> Dasbor
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('admin.kategori.index') }}"
|
<a href="{{ route('admin.kategori.index') }}"
|
||||||
class="d-flex align-items-center py-2 px-3 {{ request()->is('admin/kategori*') ? 'active' : '' }}">
|
class="flex items-center py-2 px-3 rounded hover:bg-blue-50 {{ request()->is('admin/kategori*') ? 'bg-blue-100 text-blue-600' : 'text-gray-700' }}">
|
||||||
<i class="bi bi-diagram-3 me-2"></i> Kategori
|
<i class="bi bi-diagram-3 me-2"></i> Kategori
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('admin.fitur.index') }}"
|
<a href="{{ route('admin.fitur.index') }}"
|
||||||
class="d-flex align-items-center py-2 px-3 {{ request()->is('admin/fitur*') ? 'active' : '' }}">
|
class="flex items-center py-2 px-3 rounded hover:bg-blue-50 {{ request()->is('admin/fitur*') ? 'bg-blue-100 text-blue-600' : 'text-gray-700' }}">
|
||||||
<i class="bi bi-grid me-2"></i> Fitur
|
<i class="bi bi-grid me-2"></i> Fitur
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- Dropdown Templat -->
|
<!-- Dropdown Templat -->
|
||||||
<li>
|
<li>
|
||||||
<a href="#templatSubmenu" data-bs-toggle="collapse" aria-expanded="false"
|
@php
|
||||||
class="d-flex align-items-center py-2 px-3">
|
$isTemplatePage = request()->is('templates*'); // cek apakah sedang di halaman template
|
||||||
<i class="bi bi-card-list me-2"></i> Templat
|
@endphp
|
||||||
<i class="bi bi-chevron-down ms-auto"></i>
|
<button
|
||||||
|
class="w-full flex items-center justify-between py-2 px-3 text-gray-700 rounded hover:bg-blue-50 {{ $isTemplatePage ? 'bg-blue-100 text-blue-600' : '' }}"
|
||||||
|
id="templatBtn">
|
||||||
|
<span><i class="bi bi-card-list me-2"></i> Templat</span>
|
||||||
|
<i class="bi bi-chevron-down transition-transform {{ $isTemplatePage ? 'rotate-180' : '' }}"
|
||||||
|
id="templatIcon"></i>
|
||||||
|
</button>
|
||||||
|
<ul class="submenu pl-6 space-y-1 {{ $isTemplatePage ? 'show' : '' }}" id="templatSubmenu">
|
||||||
|
<li>
|
||||||
|
<a href="{{ route('templates.index') }}"
|
||||||
|
class="block py-2 px-2 rounded {{ request()->is('templates') ? 'bg-blue-100 text-blue-600' : 'text-gray-500 hover:text-blue-600 hover:bg-blue-50' }}">
|
||||||
|
Semua Template
|
||||||
</a>
|
</a>
|
||||||
<ul id="templatSubmenu" class="submenu collapse list-unstyled ms-4">
|
</li>
|
||||||
<li><a href="javascript:void(0)" class="d-block py-2">Pernikahan</a></li>
|
@foreach (\App\Models\Kategori::all() as $kategori)
|
||||||
<li><a href="javascript:void(0)" class="d-block py-2">Ulang Tahun</a></li>
|
<li>
|
||||||
<li><a href="javascript:void(0)" class="d-block py-2">Khitan</a></li>
|
<a href="{{ route('templates.byKategori', $kategori->id) }}"
|
||||||
|
class="block py-2 px-2 rounded {{ request()->is('templates/kategori/' . $kategori->id) ? 'bg-blue-100 text-blue-600' : 'text-gray-500 hover:text-blue-600 hover:bg-blue-50' }}">
|
||||||
|
{{ $kategori->nama }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="javascript:void(0)" class="d-flex align-items-center py-2 px-3">
|
<a href="{{ route('admin.pelanggan.index') }}"
|
||||||
|
class="flex items-center py-2 px-3 rounded hover:bg-blue-50 text-gray-700">
|
||||||
<i class="bi bi-people me-2"></i> Pelanggan
|
<i class="bi bi-people me-2"></i> Pelanggan
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('admin.reviews.index') }}"
|
<a href="{{ route('admin.reviews.index') }}"
|
||||||
class="d-flex align-items-center py-2 px-3 {{ request()->is('admin/ulasan') ? 'active' : '' }}">
|
class="flex items-center py-2 px-3 rounded hover:bg-blue-50 {{ request()->is('admin/ulasan') ? 'bg-blue-100 text-blue-600' : 'text-gray-700' }}">
|
||||||
<i class="bi bi-chat-dots me-2"></i> Ulasan
|
<i class="bi bi-chat-dots me-2"></i> Ulasan
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- MENU AKUN -->
|
<p class="text-gray-500 uppercase text-xs font-semibold px-3 mt-4 mb-2">Akun</p>
|
||||||
<p class="menu-title text-muted px-3 mt-4 mb-2">Akun</p>
|
<ul class="px-2 space-y-1">
|
||||||
<ul class="list-unstyled px-2">
|
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ route('admin.logout') }}"
|
<a href="{{ route('admin.logout') }}"
|
||||||
onclick="event.preventDefault(); document.getElementById('logout-form').submit();"
|
onclick="event.preventDefault(); document.getElementById('logout-form').submit();"
|
||||||
class="d-flex align-items-center py-2 px-3 text-danger fw-bold">
|
class="flex items-center py-2 px-3 text-red-600 font-semibold hover:bg-red-50 rounded">
|
||||||
<i class="bi bi-box-arrow-right me-2 text-danger"></i> Keluar
|
<i class="bi bi-box-arrow-right me-2"></i> Keluar
|
||||||
</a>
|
</a>
|
||||||
<form id="logout-form" action="{{ route('admin.logout') }}" method="POST" class="d-none">
|
<form id="logout-form" action="{{ route('admin.logout') }}" method="POST" class="hidden">
|
||||||
@csrf
|
@csrf
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
@ -187,11 +129,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- MAIN CONTENT -->
|
<!-- MAIN CONTENT -->
|
||||||
<div class="main-content">
|
<div class="flex-1 ml-[250px] p-6">
|
||||||
@yield('content')
|
@yield('content')
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
<script>
|
||||||
|
// Dropdown Templat
|
||||||
|
const templatBtn = document.getElementById('templatBtn');
|
||||||
|
const templatSubmenu = document.getElementById('templatSubmenu');
|
||||||
|
const templatIcon = document.getElementById('templatIcon');
|
||||||
|
|
||||||
|
templatBtn.addEventListener('click', () => {
|
||||||
|
templatSubmenu.classList.toggle('show');
|
||||||
|
templatIcon.classList.toggle('rotate-180');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Http\Controllers\Api\ReviewController;
|
use App\Http\Controllers\Api\ReviewController;
|
||||||
use App\Http\Controllers\Api\TemplateController;
|
|
||||||
use App\Http\Controllers\Api\KategoriApiController;
|
use App\Http\Controllers\Api\KategoriApiController;
|
||||||
use App\Http\Controllers\Api\PernikahanApiController;
|
use App\Http\Controllers\Api\PernikahanApiController;
|
||||||
use App\Http\Controllers\Api\UlangTahunApiController;
|
use App\Http\Controllers\Api\UlangTahunApiController;
|
||||||
use App\Http\Controllers\Api\KhitanApiController;
|
use App\Http\Controllers\Api\KhitanApiController;
|
||||||
|
use App\Http\Controllers\Api\TemplateApiController;
|
||||||
|
|
||||||
// Form API (user)
|
// Form API (user)
|
||||||
Route::post('form/pernikahan', [PernikahanApiController::class, 'store']);
|
Route::post('form/pernikahan', [PernikahanApiController::class, 'store']);
|
||||||
|
@ -27,18 +27,34 @@ Route::prefix('admin')->name('admin.')->group(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Kategori
|
//Kategori
|
||||||
Route::resource('kategoris', KategoriController::class)->middleware('auth');
|
Route::prefix('admin')->name('admin.')->group(function () {
|
||||||
|
Route::resource('kategori', KategoriController::class);
|
||||||
|
});
|
||||||
|
|
||||||
// Route Admin Fitur
|
// Route Admin Fitur
|
||||||
Route::resource('fiturs', FiturController::class)->middleware('auth');
|
Route::prefix('admin')->name('admin.')->group(function () {
|
||||||
|
Route::resource('fitur', FiturController::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// Template
|
||||||
|
Route::prefix('admin')->group(function () {
|
||||||
|
Route::get('templates', [TemplateController::class, 'index'])->name('templates.index');
|
||||||
|
Route::post('templates', [TemplateController::class, 'store'])->name('templates.store');
|
||||||
|
Route::put('templates/{template}', [TemplateController::class, 'update'])->name('templates.update');
|
||||||
|
Route::delete('templates/{template}', [TemplateController::class, 'destroy'])->name('templates.destroy');
|
||||||
|
Route::get('templates/kategori/{id}', [TemplateController::class, 'byKategori'])->name('templates.byKategori');
|
||||||
|
});
|
||||||
|
|
||||||
// Route Admin Template
|
|
||||||
Route::resource('templates', TemplateController::class)->middleware('auth');
|
|
||||||
|
|
||||||
// Route Admin Pelanggan
|
// Route Admin Pelanggan
|
||||||
Route::resource('pelanggans', PelangganController::class)->only(['index', 'show', 'destroy'])->middleware('auth');
|
Route::prefix('admin')->name('admin.')->group(function () {
|
||||||
|
Route::resource('pelanggan', PelangganController::class)->only([
|
||||||
|
'index',
|
||||||
|
'show',
|
||||||
|
'destroy'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -65,5 +81,3 @@ Route::prefix('admin')->name('admin.')->middleware('auth:admin')->group(function
|
|||||||
return redirect()->route('admin.reviews.index')->with('success', 'Ulasan berhasil dihapus');
|
return redirect()->route('admin.reviews.index')->with('success', 'Ulasan berhasil dihapus');
|
||||||
})->name('reviews.destroy');
|
})->name('reviews.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user