add desain & fix bug
This commit is contained in:
parent
54c237d211
commit
f39f510bda
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Review;
|
||||
|
||||
class ReviewApiController extends Controller
|
||||
{
|
||||
// Ambil semua ulasan (JSON)
|
||||
public function index()
|
||||
{
|
||||
$reviews = Review::latest()->get();
|
||||
|
||||
return response()->json($reviews, 200);
|
||||
}
|
||||
|
||||
// Simpan ulasan baru
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'rating' => 'required|integer|min:1|max:5',
|
||||
'message' => 'required|string',
|
||||
'name' => 'required|string|max:100',
|
||||
'city' => 'required|string|max:100',
|
||||
]);
|
||||
|
||||
$review = Review::create($validated);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Ulasan berhasil disimpan',
|
||||
'data' => $review,
|
||||
], 201);
|
||||
}
|
||||
|
||||
// Tampilkan ulasan tertentu
|
||||
public function show($id)
|
||||
{
|
||||
$review = Review::findOrFail($id);
|
||||
return response()->json($review, 200);
|
||||
}
|
||||
|
||||
// Hapus ulasan
|
||||
public function destroy($id)
|
||||
{
|
||||
$review = Review::findOrFail($id);
|
||||
$review->delete();
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Ulasan berhasil dihapus',
|
||||
], 200);
|
||||
}
|
||||
}
|
||||
@ -3,35 +3,58 @@
|
||||
@section('title', 'Tambah Kategori')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-3">Tambah Kategori</h2>
|
||||
<div class="container mx-auto py-8">
|
||||
<div class="max-w-2xl mx-auto bg-white shadow-md rounded-xl p-8 border border-blue-100">
|
||||
<h2 class="text-2xl font-semibold text-black mb-6">Tambah Kategori</h2>
|
||||
|
||||
<form action="{{ route('admin.kategori.store') }}" method="POST" enctype="multipart/form-data">
|
||||
<form action="{{ route('admin.kategori.store') }}" method="POST" enctype="multipart/form-data" class="space-y-5">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nama" class="form-label">Nama Kategori</label>
|
||||
<input type="text" class="form-control @error('nama') is-invalid @enderror"
|
||||
id="nama" name="nama" value="{{ old('nama') }}" required>
|
||||
@error('nama') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<!-- Nama Kategori -->
|
||||
<div>
|
||||
<label for="nama" class="block text-sm font-medium text-gray-700 mb-2">Nama Kategori</label>
|
||||
<input type="text" id="nama" name="nama"
|
||||
value="{{ old('nama') }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('nama') border-red-500 @enderror"
|
||||
placeholder="Masukkan nama kategori" required>
|
||||
@error('nama')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="deskripsi" class="form-label">Deskripsi</label>
|
||||
<textarea class="form-control @error('deskripsi') is-invalid @enderror"
|
||||
id="deskripsi" name="deskripsi">{{ old('deskripsi') }}</textarea>
|
||||
@error('deskripsi') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<!-- Deskripsi -->
|
||||
<div>
|
||||
<label for="deskripsi" class="block text-sm font-medium text-gray-700 mb-2">Deskripsi</label>
|
||||
<textarea id="deskripsi" name="deskripsi" rows="4"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('deskripsi') border-red-500 @enderror"
|
||||
placeholder="Tuliskan deskripsi kategori">{{ old('deskripsi') }}</textarea>
|
||||
@error('deskripsi')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="foto" class="form-label">Foto</label>
|
||||
<input type="file" class="form-control @error('foto') is-invalid @enderror"
|
||||
id="foto" name="foto">
|
||||
@error('foto') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<!-- Foto -->
|
||||
<div>
|
||||
<label for="foto" class="block text-sm font-medium text-gray-700 mb-2">Foto</label>
|
||||
<input type="file" id="foto" name="foto"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 cursor-pointer focus:ring-2 focus:ring-blue-400 @error('foto') border-red-500 @enderror">
|
||||
@error('foto')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success">Simpan</button>
|
||||
<a href="{{ route('admin.kategori.index') }}" class="btn btn-secondary">Kembali</a>
|
||||
<!-- Tombol -->
|
||||
<div class="flex justify-end gap-3 pt-4">
|
||||
<a href="{{ route('admin.kategori.index') }}"
|
||||
class="bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-5 py-2 rounded-lg transition duration-200">
|
||||
Kembali
|
||||
</a>
|
||||
<button type="submit"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-medium px-6 py-2 rounded-lg shadow transition duration-200">
|
||||
Simpan
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@ -3,41 +3,64 @@
|
||||
@section('title', 'Edit Kategori')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-3">Edit Kategori</h2>
|
||||
<div class="container mx-auto py-8">
|
||||
<div class="max-w-2xl mx-auto bg-white shadow-md rounded-xl p-8 border border-blue-100">
|
||||
<h2 class="text-2xl font-semibold text-black mb-6">Edit Kategori</h2>
|
||||
|
||||
<form action="{{ route('admin.kategori.update', $kategori->id) }}" method="POST" enctype="multipart/form-data">
|
||||
<form action="{{ route('admin.kategori.update', $kategori->id) }}" method="POST" enctype="multipart/form-data" class="space-y-5">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="nama" class="form-label">Nama Kategori</label>
|
||||
<input type="text" class="form-control @error('nama') is-invalid @enderror"
|
||||
id="nama" name="nama" value="{{ old('nama', $kategori->nama) }}" required>
|
||||
@error('nama') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<!-- Nama Kategori -->
|
||||
<div>
|
||||
<label for="nama" class="block text-sm font-medium text-gray-700 mb-2">Nama Kategori</label>
|
||||
<input type="text" id="nama" name="nama"
|
||||
value="{{ old('nama', $kategori->nama) }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('nama') border-red-500 @enderror"
|
||||
placeholder="Masukkan nama kategori" required>
|
||||
@error('nama')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="deskripsi" class="form-label">Deskripsi</label>
|
||||
<textarea class="form-control @error('deskripsi') is-invalid @enderror"
|
||||
id="deskripsi" name="deskripsi">{{ old('deskripsi', $kategori->deskripsi) }}</textarea>
|
||||
@error('deskripsi') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<!-- Deskripsi -->
|
||||
<div>
|
||||
<label for="deskripsi" class="block text-sm font-medium text-gray-700 mb-2">Deskripsi</label>
|
||||
<textarea id="deskripsi" name="deskripsi" rows="4"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('deskripsi') border-red-500 @enderror"
|
||||
placeholder="Tuliskan deskripsi kategori">{{ old('deskripsi', $kategori->deskripsi) }}</textarea>
|
||||
@error('deskripsi')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label for="foto" class="form-label">Foto</label>
|
||||
<!-- Foto -->
|
||||
<div>
|
||||
<label for="foto" class="block text-sm font-medium text-gray-700 mb-2">Foto</label>
|
||||
@if($kategori->foto)
|
||||
<div class="mb-2">
|
||||
<img src="{{ asset('storage/'.$kategori->foto) }}" width="100" class="img-thumbnail">
|
||||
<div class="mb-3">
|
||||
<img src="{{ asset('storage/'.$kategori->foto) }}" alt="Foto Kategori" class="w-32 h-32 object-cover rounded-lg border border-gray-200">
|
||||
</div>
|
||||
@endif
|
||||
<input type="file" class="form-control @error('foto') is-invalid @enderror"
|
||||
id="foto" name="foto">
|
||||
@error('foto') <div class="invalid-feedback">{{ $message }}</div> @enderror
|
||||
<input type="file" id="foto" name="foto"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 cursor-pointer focus:ring-2 focus:ring-blue-400 @error('foto') border-red-500 @enderror">
|
||||
@error('foto')
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Update</button>
|
||||
<a href="{{ route('admin.kategori.index') }}" class="btn btn-secondary">Kembali</a>
|
||||
<!-- Tombol -->
|
||||
<div class="flex justify-end gap-3 pt-4">
|
||||
<a href="{{ route('admin.kategori.index') }}"
|
||||
class="bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-5 py-2 rounded-lg transition duration-200">
|
||||
Kembali
|
||||
</a>
|
||||
<button type="submit"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-medium px-6 py-2 rounded-lg shadow transition duration-200">
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@ -3,30 +3,46 @@
|
||||
@section('title', 'Buat Pesanan')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<h2 class="mb-3">Buat Pesanan</h2>
|
||||
<div class="container mx-auto py-8">
|
||||
<div class="max-w-2xl mx-auto bg-white shadow-md rounded-xl p-8 border border-blue-100">
|
||||
<h2 class="text-2xl font-semibold text-black mb-6">Buat Pesanan</h2>
|
||||
|
||||
<form action="{{ route('pelanggans.store') }}" method="POST">
|
||||
<form action="{{ route('pelanggans.store') }}" method="POST" class="space-y-5">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Nama Pemesan</label>
|
||||
<input type="text" name="nama_pemesan" class="form-control" value="{{ old('nama_pemesan') }}" required>
|
||||
<!-- Nama Pemesan -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">Nama Pemesan</label>
|
||||
<input type="text" name="nama_pemesan"
|
||||
value="{{ old('nama_pemesan') }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Email</label>
|
||||
<input type="email" name="email" class="form-control" value="{{ old('email') }}" required>
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">Email</label>
|
||||
<input type="email" name="email"
|
||||
value="{{ old('email') }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>No. Telepon</label>
|
||||
<input type="text" name="no_tlpn" class="form-control" value="{{ old('no_tlpn') }}" required>
|
||||
<!-- No. Telepon -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">No. Telepon</label>
|
||||
<input type="text" name="no_tlpn"
|
||||
value="{{ old('no_tlpn') }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<label>Template</label>
|
||||
<select name="template_id" id="template_id" class="form-select" required>
|
||||
<!-- Template -->
|
||||
<div>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">Template</label>
|
||||
<select name="template_id" id="template_id"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 focus:ring-2 focus:ring-blue-400 focus:outline-none"
|
||||
required>
|
||||
<option value="">-- Pilih Template --</option>
|
||||
@foreach($templates as $template)
|
||||
<option value="{{ $template->id }}" data-form='@json($template->form)'>
|
||||
@ -36,11 +52,18 @@
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- tempat field dinamis -->
|
||||
<!-- Tempat field dinamis -->
|
||||
<div id="dynamic-form"></div>
|
||||
|
||||
<button type="submit" class="btn btn-success">Kirim Pesanan</button>
|
||||
<!-- Tombol -->
|
||||
<div class="flex justify-end pt-4">
|
||||
<button type="submit"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-medium px-6 py-2 rounded-lg shadow transition duration-200">
|
||||
Kirim Pesanan
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -58,11 +81,11 @@ document.getElementById('template_id').addEventListener('change', function () {
|
||||
let input = '';
|
||||
|
||||
if (field.type === 'text') {
|
||||
input = `<input type="text" name="form[${key}]" class="form-control" ${field.required ? 'required' : ''}>`;
|
||||
input = `<input type="text" name="form[${key}]" class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none" ${field.required ? 'required' : ''}>`;
|
||||
} else if (field.type === 'textarea') {
|
||||
input = `<textarea name="form[${key}]" class="form-control" ${field.required ? 'required' : ''}></textarea>`;
|
||||
input = `<textarea name="form[${key}]" class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none" ${field.required ? 'required' : ''}></textarea>`;
|
||||
} else if (field.type === 'select') {
|
||||
input = `<select name="form[${key}]" class="form-select">`;
|
||||
input = `<select name="form[${key}]" class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 focus:ring-2 focus:ring-blue-400 focus:outline-none">`;
|
||||
field.options.forEach(opt => {
|
||||
input += `<option value="${opt}">${opt}</option>`;
|
||||
});
|
||||
@ -70,7 +93,7 @@ document.getElementById('template_id').addEventListener('change', function () {
|
||||
}
|
||||
container.innerHTML += `
|
||||
<div class="mb-3">
|
||||
<label>${label}</label>
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">${label}</label>
|
||||
${input}
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -3,16 +3,19 @@
|
||||
@section('title', 'Edit Template')
|
||||
|
||||
@section('content')
|
||||
<div class="container mt-4">
|
||||
<h2>Edit Template</h2>
|
||||
<div class="container mx-auto py-8">
|
||||
<div class="max-w-2xl mx-auto bg-white shadow-md rounded-xl p-8 border border-blue-100">
|
||||
<h2 class="text-2xl font-semibold text-black mb-6">Edit Template</h2>
|
||||
|
||||
{{-- Alert sukses / error --}}
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
<div class="bg-green-100 text-green-700 px-4 py-2 rounded-lg mb-4 border border-green-200">
|
||||
{{ session('success') }}
|
||||
</div>
|
||||
@endif
|
||||
@if($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
<div class="bg-red-100 text-red-700 px-4 py-2 rounded-lg mb-4 border border-red-200">
|
||||
<ul class="list-disc pl-5 mb-0">
|
||||
@foreach($errors->all() as $err)
|
||||
<li>{{ $err }}</li>
|
||||
@endforeach
|
||||
@ -20,69 +23,81 @@
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form action="{{ route('admin.template.update', $template->id) }}"
|
||||
method="POST" enctype="multipart/form-data">
|
||||
<form action="{{ route('admin.template.update', $template->id) }}" method="POST" enctype="multipart/form-data" class="space-y-5">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
{{-- Nama Template --}}
|
||||
<div class="mb-3">
|
||||
<label for="nama_template" class="form-label">Nama Template</label>
|
||||
<input type="text" name="nama_template" id="nama_template"
|
||||
class="form-control @error('nama_template') is-invalid @enderror"
|
||||
value="{{ old('nama_template', $template->nama_template) }}" required>
|
||||
<div>
|
||||
<label for="nama_template" class="block text-sm font-medium text-gray-700 mb-2">Nama Template</label>
|
||||
<input type="text" id="nama_template" name="nama_template"
|
||||
value="{{ old('nama_template', $template->nama_template) }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('nama_template') border-red-500 @enderror"
|
||||
required>
|
||||
@error('nama_template')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Harga --}}
|
||||
<div class="mb-3">
|
||||
<label for="harga" class="form-label">Harga</label>
|
||||
<input type="number" name="harga" id="harga"
|
||||
class="form-control @error('harga') is-invalid @enderror"
|
||||
value="{{ old('harga', $template->harga) }}" required>
|
||||
<div>
|
||||
<label for="harga" class="block text-sm font-medium text-gray-700 mb-2">Harga</label>
|
||||
<input type="number" id="harga" name="harga"
|
||||
value="{{ old('harga', $template->harga) }}"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('harga') border-red-500 @enderror"
|
||||
required>
|
||||
@error('harga')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Paket --}}
|
||||
<div class="mb-3">
|
||||
<label for="paket" class="form-label">Paket</label>
|
||||
<select name="paket" id="paket" class="form-select @error('paket') is-invalid @enderror" required>
|
||||
<div>
|
||||
<label for="paket" class="block text-sm font-medium text-gray-700 mb-2">Paket</label>
|
||||
<select id="paket" name="paket"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 focus:ring-2 focus:ring-blue-400 focus:outline-none @error('paket') border-red-500 @enderror"
|
||||
required>
|
||||
<option value="starter" {{ old('paket', $template->paket) == 'starter' ? 'selected' : '' }}>Starter</option>
|
||||
<option value="basic" {{ old('paket', $template->paket) == 'basic' ? 'selected' : '' }}>Basic</option>
|
||||
<option value="premium" {{ old('paket', $template->paket) == 'premium' ? 'selected' : '' }}>Premium</option>
|
||||
</select>
|
||||
@error('paket')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Foto / Gambar --}}
|
||||
<div>
|
||||
<label for="foto" class="block text-sm font-medium text-gray-700 mb-2">Gambar Template</label>
|
||||
<div class="mb-3">
|
||||
<label for="foto" class="form-label">Gambar Template</label>
|
||||
<div class="mb-2">
|
||||
@if($template->foto)
|
||||
<img src="{{ asset('storage/' . $template->foto) }}"
|
||||
alt="{{ $template->nama_template }}"
|
||||
class="rounded border" style="max-height: 120px">
|
||||
class="w-32 h-32 object-cover rounded-lg border border-gray-200">
|
||||
@else
|
||||
<p class="text-muted">Belum ada gambar</p>
|
||||
<p class="text-gray-500 text-sm">Belum ada gambar</p>
|
||||
@endif
|
||||
</div>
|
||||
<input type="file" name="foto" id="foto"
|
||||
class="form-control @error('foto') is-invalid @enderror">
|
||||
<small class="text-muted">Kosongkan jika tidak ingin mengganti gambar.</small>
|
||||
<input type="file" id="foto" name="foto"
|
||||
class="w-full border border-gray-300 rounded-lg px-4 py-2 bg-gray-50 cursor-pointer focus:ring-2 focus:ring-blue-400 @error('foto') border-red-500 @enderror">
|
||||
<p class="text-gray-500 text-sm mt-1">Kosongkan jika tidak ingin mengganti gambar.</p>
|
||||
@error('foto')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
<p class="text-red-500 text-sm mt-1">{{ $message }}</p>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
{{-- Tombol --}}
|
||||
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
|
||||
<a href="{{ route('admin.template.index') }}" class="btn btn-secondary">Batal</a>
|
||||
<div class="flex justify-end gap-3 pt-4">
|
||||
<a href="{{ route('admin.template.index') }}"
|
||||
class="bg-gray-100 hover:bg-gray-200 text-gray-700 font-medium px-5 py-2 rounded-lg transition duration-200">
|
||||
Batal
|
||||
</a>
|
||||
<button type="submit"
|
||||
class="bg-blue-600 hover:bg-blue-700 text-white font-medium px-6 py-2 rounded-lg shadow transition duration-200">
|
||||
Simpan Perubahan
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@ -12,3 +12,9 @@ Route::get('/templates', [TemplateApiController::class, 'index']);
|
||||
Route::get('/templates/{template}', [TemplateApiController::class, 'show']);
|
||||
|
||||
|
||||
use App\Http\Controllers\Api\ReviewApiController;
|
||||
|
||||
Route::get('/reviews', [ReviewApiController::class, 'index']);
|
||||
Route::post('/reviews', [ReviewApiController::class, 'store']);
|
||||
Route::get('/reviews/{id}', [ReviewApiController::class, 'show']);
|
||||
Route::delete('/reviews/{id}', [ReviewApiController::class, 'destroy']);
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
|
||||
// id template yang mau ditampilkan
|
||||
// ID template yang mau ditampilkan
|
||||
const selectedIds = [1, 2, 3, 5, 6, 8]
|
||||
|
||||
// state dropdown
|
||||
// state dropdown (buat fitur paket aja sekarang)
|
||||
const openDropdownId = ref(null)
|
||||
const toggleDropdown = (templateId) => {
|
||||
openDropdownId.value = openDropdownId.value === templateId ? null : templateId
|
||||
}
|
||||
|
||||
// fetch API dari Laravel
|
||||
// ambil data dari API Laravel
|
||||
const { data: templatesData, error } = await useFetch('http://localhost:8000/api/templates')
|
||||
|
||||
// filter hanya id tertentu
|
||||
@ -36,45 +36,54 @@ const templates = computed(() =>
|
||||
:key="t.id"
|
||||
class="bg-white border rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300"
|
||||
>
|
||||
<!-- Image -->
|
||||
<!-- Gambar -->
|
||||
<img
|
||||
:src="`http://localhost:8000${t.foto}`"
|
||||
:src="t.foto"
|
||||
:alt="t.nama_template"
|
||||
class="w-full h-48 object-cover"
|
||||
/>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="p-5 text-center">
|
||||
<h4 class="text-xl font-bold text-gray-800 mb-2">{{ t.nama }}</h4>
|
||||
<p class="text-green-600 font-semibold text-xl mb-4">
|
||||
<h4 class="text-xl font-bold text-gray-800 mb-2">{{ t.nama_template }}</h4>
|
||||
<p class="text-green-600 font-semibold text-xl mb-1">
|
||||
Rp {{ Number(t.harga).toLocaleString('id-ID') }}
|
||||
</p>
|
||||
<p class="text-gray-500 text-sm mb-4">
|
||||
Paket: {{ t.paket || 'Tidak ada paket' }}
|
||||
</p>
|
||||
|
||||
<!-- Dropdown fitur -->
|
||||
<div v-if="t.fiturs && t.fiturs.length > 0" class="relative mb-4">
|
||||
<!-- Dropdown untuk lihat info tambahan -->
|
||||
<div class="relative mb-4">
|
||||
<button
|
||||
@click="toggleDropdown(t.id)"
|
||||
class="w-full bg-white border border-gray-300 rounded-md shadow-sm px-4 py-2 inline-flex justify-between items-center"
|
||||
>
|
||||
<span class="mx-auto text-gray-700 font-semibold">FITUR YANG TERSEDIA</span>
|
||||
<span class="mx-auto text-gray-700 font-semibold">DETAIL TEMPLATE</span>
|
||||
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor">
|
||||
<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 v-if="openDropdownId === t.id">
|
||||
<ul class="mt-4 space-y-2 text-gray-600 text-left">
|
||||
<li v-for="f in t.fiturs" :key="f.id" class="flex items-center">
|
||||
<svg class="h-4 w-4 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<ul class="mt-4 space-y-2 text-gray-600 text-left px-2">
|
||||
<li class="flex items-center">
|
||||
<svg class="h-4 w-4 text-blue-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
{{ f.deskripsi }}
|
||||
Kategori: {{ t.kategori || 'Tanpa kategori' }}
|
||||
</li>
|
||||
<li class="flex items-center">
|
||||
<svg class="h-4 w-4 text-blue-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
|
||||
</svg>
|
||||
Paket: {{ t.paket || '-' }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<!-- Tombol -->
|
||||
<div class="flex items-center gap-3 mt-6">
|
||||
<button
|
||||
class="w-full bg-white border border-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg hover:bg-gray-100 transition-colors"
|
||||
@ -82,7 +91,7 @@ const templates = computed(() =>
|
||||
Preview
|
||||
</button>
|
||||
<NuxtLink
|
||||
:to="`/form/${t.kategori.nama.toLowerCase().replace(/ /g, '-')}` + `?template_id=${t.id}`"
|
||||
:to="`/form/${t.kategori ? t.kategori.toLowerCase().replace(/ /g, '-') : 'lainnya'}` + `?template_id=${t.id}`"
|
||||
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center"
|
||||
>
|
||||
Order
|
||||
@ -92,7 +101,7 @@ const templates = computed(() =>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Jika error -->
|
||||
<!-- Jika error atau kosong -->
|
||||
<div v-else class="text-gray-500">Tidak ada template yang bisa ditampilkan</div>
|
||||
|
||||
<!-- See more -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user