Redesigned the Admin Chat UI according to branding, updated the specific grain seeder, and fixed bugs in category routing and product image previews
This commit is contained in:
parent
bd3c6193c0
commit
ea955f9e46
|
|
@ -0,0 +1,70 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Kategori;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class KategoriController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$kategoris = Kategori::withCount('produks')->latest()->get();
|
||||
return view('admin.kategori.index', compact('kategoris'));
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
return view('admin.kategori.create');
|
||||
}
|
||||
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'nama_kategori' => 'required|string|max:255|unique:kategoris,nama_kategori',
|
||||
'ikon' => 'nullable|string|max:50',
|
||||
]);
|
||||
|
||||
Kategori::create([
|
||||
'nama_kategori' => $request->nama_kategori,
|
||||
'slug' => Str::slug($request->nama_kategori),
|
||||
'ikon' => $request->ikon,
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil ditambahkan.');
|
||||
}
|
||||
|
||||
public function edit($id)
|
||||
{
|
||||
$kategori = Kategori::findOrFail($id);
|
||||
return view('admin.kategori.edit', compact('kategori'));
|
||||
}
|
||||
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$kategori = Kategori::findOrFail($id);
|
||||
|
||||
$request->validate([
|
||||
'nama_kategori' => 'required|string|max:255|unique:kategoris,nama_kategori,'.$id,
|
||||
'ikon' => 'nullable|string|max:50',
|
||||
]);
|
||||
|
||||
$kategori->update([
|
||||
'nama_kategori' => $request->nama_kategori,
|
||||
'slug' => Str::slug($request->nama_kategori),
|
||||
'ikon' => $request->ikon,
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil diperbarui.');
|
||||
}
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
$kategori = Kategori::findOrFail($id);
|
||||
$kategori->delete();
|
||||
|
||||
return redirect()->route('admin.kategori.index')->with('success', 'Kategori berhasil dihapus.');
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,10 @@ public function dashboard()
|
|||
$totalProduk = Produk::count();
|
||||
$totalTransaksi = Transaksi::count();
|
||||
|
||||
$transaksiTerbaru = Transaksi::with(['pembeli', 'details'])->latest()->take(5)->get();
|
||||
$transaksiTerbaru = Transaksi::with(['pembeli', 'petani'])
|
||||
->latest()
|
||||
->take(5)
|
||||
->get();
|
||||
|
||||
return view('admin.dashboard', compact(
|
||||
'totalPetani',
|
||||
|
|
@ -30,15 +33,28 @@ public function dashboard()
|
|||
public function monitoring()
|
||||
{
|
||||
$produks = Produk::with('petani')->latest()->paginate(10);
|
||||
$transaksis = Transaksi::with(['pembeli'])->latest()->paginate(10);
|
||||
$transaksis = Transaksi::with(['pembeli', 'petani'])
|
||||
->latest()
|
||||
->paginate(10);
|
||||
|
||||
return view('admin.monitoring', compact('produks', 'transaksis'));
|
||||
}
|
||||
|
||||
// --- FITUR BARU: DETAIL TRANSAKSI ---
|
||||
public function transaksiDetail($id)
|
||||
{
|
||||
$transaksi = Transaksi::with(['pembeli', 'petani', 'detailTransaksis.produk'])
|
||||
->findOrFail($id);
|
||||
|
||||
return view('admin.transaksi_detail', compact('transaksi'));
|
||||
}
|
||||
|
||||
// --- VERIFIKASI PETANI ---
|
||||
|
||||
public function verifikasiIndex()
|
||||
{
|
||||
// Ambil data petani yang statusnya 'menunggu'
|
||||
$petanis = Petani::orderBy('created_at', 'desc')->get();
|
||||
$petanis = Petani::orderBy('created_at', 'desc')->get();
|
||||
|
||||
return view('admin.verifikasi.index', compact('petanis'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,12 @@ public function index(Request $request)
|
|||
return view('landing.partials.product_list', compact('produks'))->render();
|
||||
}
|
||||
|
||||
$produkTerlaris = Produk::with('petani')
|
||||
->inRandomOrder()
|
||||
$produkTerlaris = Produk::withSum(['detailTransaksis as total_terjual' => function ($query) {
|
||||
$query->whereHas('transaksi', function ($q) {
|
||||
$q->where('status', '!=', 'batal');
|
||||
});
|
||||
}], 'jumlah')
|
||||
->orderByDesc('total_terjual')
|
||||
->take(4)
|
||||
->get();
|
||||
|
||||
|
|
@ -29,25 +33,53 @@ public function index(Request $request)
|
|||
|
||||
public function shop(Request $request)
|
||||
{
|
||||
$query = Produk::with('petani');
|
||||
$query = Produk::where('stok', '>', 0);
|
||||
|
||||
if ($request->has('search') && $request->search != '') {
|
||||
$query->where('nama_produk', 'like', '%' . $request->search . '%');
|
||||
// Filter Kategori Berdasarkan Slug
|
||||
if ($request->has('kategori') && $request->kategori != '') {
|
||||
$slug = $request->kategori;
|
||||
|
||||
$query->whereHas('kategori', function ($q) use ($slug) {
|
||||
$q->where('slug', $slug);
|
||||
});
|
||||
}
|
||||
|
||||
$produks = $query->paginate(12);
|
||||
// Sorting (Urutkan)
|
||||
if ($request->has('sort')) {
|
||||
switch ($request->sort) {
|
||||
case 'termurah':
|
||||
$query->orderBy('harga', 'asc');
|
||||
break;
|
||||
case 'termahal':
|
||||
$query->orderBy('harga', 'desc');
|
||||
break;
|
||||
case 'terbaru':
|
||||
$query->latest();
|
||||
break;
|
||||
default:
|
||||
$query->latest();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$query->latest();
|
||||
}
|
||||
|
||||
$produks = $query->paginate(9);
|
||||
|
||||
return view('landing.shop', compact('produks'));
|
||||
}
|
||||
|
||||
public function detail($id)
|
||||
{
|
||||
$produk = Produk::with('petani')->findOrFail($id);
|
||||
$related_products = Produk::where('petani_id', $produk->petani_id)
|
||||
->where('id', '!=', $id)
|
||||
$produk = Produk::with(['kategori', 'petani', 'images'])->findOrFail($id);
|
||||
|
||||
$produk_terkait = Produk::where('kategori_id', $produk->kategori_id)
|
||||
->where('id', '!=', $produk->id)
|
||||
->where('stok', '>', 0)
|
||||
->inRandomOrder()
|
||||
->take(4)
|
||||
->get();
|
||||
|
||||
return view('landing.detail', compact('produk', 'related_products'));
|
||||
return view('landing.detail', compact('produk', 'produk_terkait'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,27 +20,36 @@ private function getChatList($user)
|
|||
})->orderBy('created_at', 'desc')->get();
|
||||
|
||||
$conversations = $allMessages->groupBy(function ($pesan) use ($user) {
|
||||
return $pesan->pengirim_id == $user->id
|
||||
? $pesan->penerima_type . '_' . $pesan->penerima_id
|
||||
: $pesan->pengirim_type . '_' . $pesan->pengirim_id;
|
||||
if ($pesan->pengirim_id == $user->id && $pesan->pengirim_type == get_class($user)) {
|
||||
return $pesan->penerima_type . '_' . $pesan->penerima_id;
|
||||
} else {
|
||||
return $pesan->pengirim_type . '_' . $pesan->pengirim_id;
|
||||
}
|
||||
});
|
||||
|
||||
return $conversations->map(function ($msgs) use ($user) {
|
||||
$lastMsg = $msgs->first();
|
||||
if ($lastMsg->pengirim_id == $user->id) {
|
||||
|
||||
if ($lastMsg->pengirim_id == $user->id && $lastMsg->pengirim_type == get_class($user)) {
|
||||
$lawan = $lastMsg->penerima;
|
||||
} else {
|
||||
$lawan = $lastMsg->pengirim;
|
||||
}
|
||||
|
||||
// Fallback
|
||||
$lawanObj = $lawan ?? new \stdClass;
|
||||
|
||||
return [
|
||||
'lawan_id' => $lawan->id ?? 0,
|
||||
'lawan_type' => get_class($lawan ?? new \stdClass),
|
||||
'lawan_type' => get_class($lawanObj),
|
||||
'nama' => $lawan->nama_lengkap ?? 'User Terhapus',
|
||||
'foto' => $lawan->foto ?? null, // Pastikan ada accessor url foto
|
||||
'foto' => $lawan->foto ?? null,
|
||||
'last_message' => $lastMsg->isi_pesan,
|
||||
'time' => $lastMsg->created_at->diffForHumans(),
|
||||
'unread' => $msgs->where('penerima_id', $user->id)->where('sudah_dibaca', false)->count()
|
||||
'unread' => $msgs->where('penerima_id', $user->id)
|
||||
->where('penerima_type', get_class($user))
|
||||
->where('sudah_dibaca', false)
|
||||
->count()
|
||||
];
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,42 +5,52 @@
|
|||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Produk;
|
||||
use App\Models\ProdukImage;
|
||||
use App\Models\Kategori; // PENTING: Import Model Kategori
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ProdukController extends Controller
|
||||
{
|
||||
// Tampilkan Daftar Produk Petani
|
||||
public function index()
|
||||
{
|
||||
$produks = Produk::where('petani_id', Auth::guard('petani')->id())->latest()->get();
|
||||
$produks = Produk::with('kategori')
|
||||
->where('petani_id', Auth::guard('petani')->id())
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
return view('petani.produk.index', compact('produks'));
|
||||
}
|
||||
|
||||
// Form Tambah Produk
|
||||
public function create()
|
||||
{
|
||||
return view('petani.produk.create');
|
||||
$kategoris = Kategori::all();
|
||||
|
||||
return view('petani.produk.create', compact('kategoris'));
|
||||
}
|
||||
|
||||
// Simpan Produk Baru
|
||||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'nama_produk' => 'required|string|max:255',
|
||||
'harga' => 'required|numeric|min:0',
|
||||
'stok' => 'required|integer|min:0',
|
||||
'deskripsi' => 'required|string',
|
||||
'foto_produk' => 'required|image|mimes:jpeg,png,jpg|max:2048',
|
||||
'nama_produk' => 'required|string|max:255',
|
||||
'kategori_id' => 'required|exists:kategoris,id',
|
||||
'harga' => 'required|numeric|min:0',
|
||||
'stok' => 'required|integer|min:0',
|
||||
'deskripsi' => 'required|string',
|
||||
'foto_produk' => 'required|image|mimes:jpeg,png,jpg|max:2048',
|
||||
'foto_tambahan.*' => 'nullable|image|mimes:jpeg,png,jpg|max:2048'
|
||||
]);
|
||||
|
||||
// Simpan Foto Utama
|
||||
$fotoPath = null;
|
||||
if ($request->hasFile('foto_produk')) {
|
||||
$fotoPath = $request->file('foto_produk')->store('produk', 'public');
|
||||
}
|
||||
|
||||
Produk::create([
|
||||
// Simpan Data Produk
|
||||
$produk = Produk::create([
|
||||
'petani_id' => Auth::guard('petani')->id(),
|
||||
'kategori_id' => $request->kategori_id,
|
||||
'nama_produk' => $request->nama_produk,
|
||||
'harga' => $request->harga,
|
||||
'stok' => $request->stok,
|
||||
|
|
@ -48,29 +58,50 @@ public function store(Request $request)
|
|||
'foto_produk' => $fotoPath,
|
||||
]);
|
||||
|
||||
// Simpan Foto Tambahan
|
||||
if ($request->hasFile('foto_tambahan')) {
|
||||
foreach ($request->file('foto_tambahan') as $file) {
|
||||
$path = $file->store('produk/gallery', 'public');
|
||||
ProdukImage::create([
|
||||
'produk_id' => $produk->id,
|
||||
'foto' => $path
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('petani.produk.index')->with('success', 'Produk berhasil ditambahkan.');
|
||||
}
|
||||
|
||||
// Form Edit Produk
|
||||
public function edit($id)
|
||||
{
|
||||
$produk = Produk::where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail();
|
||||
return view('petani.produk.edit', compact('produk'));
|
||||
$produk = Produk::with('images')->where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail();
|
||||
$kategoris = Kategori::all();
|
||||
|
||||
return view('petani.produk.edit', compact('produk', 'kategoris'));
|
||||
}
|
||||
|
||||
// Update Produk
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$produk = Produk::where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail();
|
||||
$produk = Produk::with('images')->where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail();
|
||||
|
||||
// Hitung slot gambar tersisa
|
||||
$jumlahGambarLama = $produk->images->count();
|
||||
$sisaSlot = max(3 - $jumlahGambarLama, 0);
|
||||
|
||||
$request->validate([
|
||||
'nama_produk' => 'required|string|max:255',
|
||||
'harga' => 'required|numeric|min:0',
|
||||
'stok' => 'required|integer|min:0',
|
||||
'deskripsi' => 'required|string',
|
||||
'foto_produk' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||
'nama_produk' => 'required|string|max:255',
|
||||
'kategori_id' => 'required|exists:kategoris,id',
|
||||
'harga' => 'required|numeric|min:0',
|
||||
'stok' => 'required|integer|min:0',
|
||||
'deskripsi' => 'required|string',
|
||||
'foto_produk' => 'nullable|image|mimes:jpeg,png,jpg|max:2048',
|
||||
'foto_tambahan' => 'array|max:' . $sisaSlot,
|
||||
'foto_tambahan.*' => 'image|mimes:jpeg,png,jpg|max:2048'
|
||||
], [
|
||||
'foto_tambahan.max' => "Anda hanya bisa menambah $sisaSlot foto lagi."
|
||||
]);
|
||||
|
||||
// Update Foto Utama
|
||||
if ($request->hasFile('foto_produk')) {
|
||||
if ($produk->foto_produk && Storage::disk('public')->exists($produk->foto_produk)) {
|
||||
Storage::disk('public')->delete($produk->foto_produk);
|
||||
|
|
@ -78,21 +109,32 @@ public function update(Request $request, $id)
|
|||
$produk->foto_produk = $request->file('foto_produk')->store('produk', 'public');
|
||||
}
|
||||
|
||||
// Update Data
|
||||
$produk->update([
|
||||
'nama_produk' => $request->nama_produk,
|
||||
'kategori_id' => $request->kategori_id,
|
||||
'harga' => $request->harga,
|
||||
'stok' => $request->stok,
|
||||
'deskripsi' => $request->deskripsi,
|
||||
'foto_produk' => $produk->foto_produk
|
||||
]);
|
||||
|
||||
if ($request->hasFile('foto_produk')) {
|
||||
$produk->save();
|
||||
// Tambah Foto Galeri
|
||||
if ($request->hasFile('foto_tambahan')) {
|
||||
foreach ($request->file('foto_tambahan') as $file) {
|
||||
if ($produk->images()->count() >= 3) break;
|
||||
|
||||
$path = $file->store('produk/gallery', 'public');
|
||||
ProdukImage::create([
|
||||
'produk_id' => $produk->id,
|
||||
'foto' => $path
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('petani.produk.index')->with('success', 'Produk berhasil diperbarui.');
|
||||
}
|
||||
|
||||
// Hapus Produk
|
||||
public function destroy($id)
|
||||
{
|
||||
$produk = Produk::where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail();
|
||||
|
|
@ -101,8 +143,32 @@ public function destroy($id)
|
|||
Storage::disk('public')->delete($produk->foto_produk);
|
||||
}
|
||||
|
||||
foreach($produk->images as $img) {
|
||||
if (Storage::disk('public')->exists($img->foto)) {
|
||||
Storage::disk('public')->delete($img->foto);
|
||||
}
|
||||
}
|
||||
|
||||
$produk->images()->delete();
|
||||
$produk->delete();
|
||||
|
||||
return redirect()->route('petani.produk.index')->with('success', 'Produk berhasil dihapus.');
|
||||
}
|
||||
|
||||
public function deleteImage($id)
|
||||
{
|
||||
$image = ProdukImage::findOrFail($id);
|
||||
|
||||
if ($image->produk->petani_id != Auth::guard('petani')->id()) {
|
||||
abort(403);
|
||||
}
|
||||
|
||||
if (Storage::disk('public')->exists($image->foto)) {
|
||||
Storage::disk('public')->delete($image->foto);
|
||||
}
|
||||
|
||||
$image->delete();
|
||||
|
||||
return back()->with('success', 'Foto berhasil dihapus.');
|
||||
}
|
||||
}
|
||||
|
|
@ -72,16 +72,17 @@ public function prosesCheckout(Request $request)
|
|||
DB::transaction(function () use ($request, $pembeli_id) {
|
||||
|
||||
if ($request->has('produk_id')) {
|
||||
// LOGIKA BELI LANGSUNG (Single Item)
|
||||
// --- LOGIKA BELI LANGSUNG (Single Item) ---
|
||||
$produk = Produk::findOrFail($request->produk_id);
|
||||
$total_harga = $produk->harga * $request->jumlah;
|
||||
|
||||
$transaksi = Transaksi::create([
|
||||
'pembeli_id' => $pembeli_id,
|
||||
'petani_id' => $produk->petani_id,
|
||||
'tanggal_transaksi' => now(),
|
||||
'alamat_pengiriman' => $request->alamat_pengiriman,
|
||||
'total_harga' => $total_harga,
|
||||
'status' => 'menunggu_konfirmasi',
|
||||
'status' => 'menunggu konfirmasi',
|
||||
'kode_invoice' => 'INV/' . date('Ymd') . '/' . rand(1000, 9999),
|
||||
]);
|
||||
|
||||
|
|
@ -94,7 +95,9 @@ public function prosesCheckout(Request $request)
|
|||
]);
|
||||
|
||||
$produk->decrement('stok', $request->jumlah);
|
||||
|
||||
} else {
|
||||
// --- LOGIKA KERANJANG (Cart) ---
|
||||
$cart = session()->get('cart');
|
||||
|
||||
// Kelompokkan produk berdasarkan Petani ID
|
||||
|
|
@ -113,13 +116,14 @@ public function prosesCheckout(Request $request)
|
|||
$subtotal_transaksi = 0;
|
||||
$kode_invoice = 'INV/' . date('Ymd') . '/' . rand(1000, 9999);
|
||||
|
||||
// Membuat Header Transaksi
|
||||
// Membuat Header Transaksi per Petani
|
||||
$transaksi = Transaksi::create([
|
||||
'pembeli_id' => $pembeli_id,
|
||||
'petani_id' => $petani_id,
|
||||
'tanggal_transaksi' => now(),
|
||||
'alamat_pengiriman' => $request->alamat_pengiriman,
|
||||
'total_harga' => 0,
|
||||
'status' => 'menunggu_konfirmasi',
|
||||
'status' => 'menunggu konfirmasi',
|
||||
'kode_invoice' => $kode_invoice,
|
||||
]);
|
||||
|
||||
|
|
@ -154,7 +158,7 @@ public function prosesCheckout(Request $request)
|
|||
// Riwayat Pesanan
|
||||
public function pesananSaya()
|
||||
{
|
||||
$transaksis = Transaksi::with(['details.produk.petani'])
|
||||
$transaksis = Transaksi::with(['detailTransaksis.produk.petani'])
|
||||
->where('pembeli_id', Auth::guard('pembeli')->id())
|
||||
->latest()
|
||||
->get();
|
||||
|
|
@ -186,10 +190,10 @@ public function pesananMasuk()
|
|||
{
|
||||
$petaniId = Auth::guard('petani')->id();
|
||||
|
||||
$pesanans = Transaksi::whereHas('details.produk', function ($q) use ($petaniId) {
|
||||
$pesanans = Transaksi::whereHas('detailTransaksis.produk', function ($q) use ($petaniId) {
|
||||
$q->where('petani_id', $petaniId);
|
||||
})
|
||||
->with(['pembeli', 'details.produk'])
|
||||
->with(['pembeli', 'detailTransaksis.produk'])
|
||||
->latest()
|
||||
->get();
|
||||
|
||||
|
|
@ -223,10 +227,10 @@ public function pesananDetail($id)
|
|||
$petaniId = Auth::guard('petani')->id();
|
||||
|
||||
// Ambil transaksi berdasarkan ID
|
||||
$pesanan = Transaksi::whereHas('details.produk', function ($q) use ($petaniId) {
|
||||
$pesanan = Transaksi::whereHas('detailTransaksis.produk', function ($q) use ($petaniId) {
|
||||
$q->where('petani_id', $petaniId);
|
||||
})
|
||||
->with(['pembeli', 'details.produk'])
|
||||
->with(['pembeli', 'detailTransaksis.produk'])
|
||||
->findOrFail($id);
|
||||
|
||||
return view('petani.pesanan.detail', compact('pesanan'));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Kategori extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['nama_kategori', 'slug', 'ikon'];
|
||||
|
||||
public function produks()
|
||||
{
|
||||
return $this->hasMany(Produk::class, 'kategori_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ class Produk extends Model
|
|||
protected $fillable = [
|
||||
'petani_id',
|
||||
'nama_produk',
|
||||
'kategori',
|
||||
'harga',
|
||||
'stok',
|
||||
'deskripsi',
|
||||
|
|
@ -25,9 +24,19 @@ public function petani()
|
|||
{
|
||||
return $this->belongsTo(Petani::class, 'petani_id');
|
||||
}
|
||||
|
||||
|
||||
public function detailTransaksis()
|
||||
{
|
||||
return $this->hasMany(DetailTransaksi::class, 'produk_id');
|
||||
}
|
||||
}
|
||||
|
||||
public function images()
|
||||
{
|
||||
return $this->hasMany(ProdukImage::class, 'produk_id');
|
||||
}
|
||||
|
||||
public function kategori()
|
||||
{
|
||||
return $this->belongsTo(Kategori::class, 'kategori_id');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ProdukImage extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
'produk_id',
|
||||
'foto'
|
||||
];
|
||||
|
||||
public function produk()
|
||||
{
|
||||
return $this->belongsTo(Produk::class, 'produk_id');
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ class Transaksi extends Model
|
|||
|
||||
protected $fillable = [
|
||||
'pembeli_id',
|
||||
'petani_id',
|
||||
'tanggal_transaksi',
|
||||
'alamat_pengiriman',
|
||||
'total_harga',
|
||||
|
|
@ -25,7 +26,12 @@ public function pembeli()
|
|||
return $this->belongsTo(Pembeli::class, 'pembeli_id');
|
||||
}
|
||||
|
||||
public function details()
|
||||
public function petani()
|
||||
{
|
||||
return $this->belongsTo(Petani::class, 'petani_id');
|
||||
}
|
||||
|
||||
public function detailTransaksis()
|
||||
{
|
||||
return $this->hasMany(DetailTransaksi::class, 'transaksi_id');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('kategoris', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('nama_kategori');
|
||||
$table->string('slug')->unique();
|
||||
$table->string('ikon')->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('kategoris');
|
||||
}
|
||||
};
|
||||
|
|
@ -14,8 +14,8 @@ public function up(): void
|
|||
Schema::create('produks', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('petani_id')->constrained('petanis')->onDelete('cascade');
|
||||
$table->foreignId('kategori_id')->nullable()->constrained('kategoris')->onDelete('set null');
|
||||
$table->string('nama_produk');
|
||||
$table->string('kategori')->default('Lainnya');
|
||||
$table->decimal('harga', 12, 0);
|
||||
$table->integer('stok');
|
||||
$table->text('deskripsi');
|
||||
|
|
@ -31,4 +31,4 @@ public function down(): void
|
|||
{
|
||||
Schema::dropIfExists('produks');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -10,20 +10,21 @@
|
|||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('transaksis', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('pembeli_id')->constrained('pembelis')->onDelete('cascade');
|
||||
$table->dateTime('tanggal_transaksi');
|
||||
$table->text('alamat_pengiriman');
|
||||
$table->decimal('total_harga', 15, 0);
|
||||
$table->enum('status', ['menunggu_konfirmasi', 'diproses', 'dikirim', 'selesai', 'batal'])
|
||||
->default('menunggu_konfirmasi');
|
||||
|
||||
$table->string('kode_invoice')->unique()->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
{
|
||||
Schema::create('transaksis', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('pembeli_id')->constrained('pembelis')->onDelete('cascade');
|
||||
$table->foreignId('petani_id')->constrained('petanis')->onDelete('cascade');
|
||||
$table->dateTime('tanggal_transaksi');
|
||||
$table->text('alamat_pengiriman');
|
||||
$table->decimal('total_harga', 15, 0);
|
||||
$table->enum('status', ['menunggu konfirmasi', 'diproses', 'dikirim', 'selesai', 'batal'])
|
||||
->default('menunggu konfirmasi');
|
||||
|
||||
$table->string('kode_invoice')->unique()->nullable();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('produk_images', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('produk_id')->constrained('produks')->onDelete('cascade');
|
||||
$table->string('foto');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('produk_images');
|
||||
}
|
||||
};
|
||||
|
|
@ -13,6 +13,19 @@ class PetaniSeeder extends Seeder
|
|||
*/
|
||||
public function run(): void
|
||||
{
|
||||
// Petani SUDAH AKTIF -> Bisa login & jualan
|
||||
DB::table('petanis')->insert([
|
||||
'nama_lengkap' => 'Siti Aminah',
|
||||
'username' => 'siti_sayur',
|
||||
'email' => 'siti@gmail.com',
|
||||
'password' => Hash::make('password123'),
|
||||
'no_hp' => '085678901234',
|
||||
'alamat' => 'Dusun Krajan RT 02 RW 01',
|
||||
'nama_usaha' => 'Sayur Segar Bu Siti',
|
||||
'status_akun' => 'aktif',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
// Petani BARU DAFTAR menunggu verifikasi
|
||||
DB::table('petanis')->insert([
|
||||
'nama_lengkap' => 'Budi Santoso',
|
||||
|
|
@ -27,19 +40,6 @@ public function run(): void
|
|||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
// Petani SUDAH AKTIF -> Bisa login & jualan
|
||||
DB::table('petanis')->insert([
|
||||
'nama_lengkap' => 'Siti Aminah',
|
||||
'username' => 'siti_sayur',
|
||||
'email' => 'siti@gmail.com',
|
||||
'password' => Hash::make('password123'),
|
||||
'no_hp' => '085678901234',
|
||||
'alamat' => 'Dusun Krajan RT 02 RW 01',
|
||||
'nama_usaha' => 'Sayur Segar Bu Siti',
|
||||
'status_akun' => 'aktif',
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
// Petani DITOLAK
|
||||
DB::table('petanis')->insert([
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Produk;
|
||||
use App\Models\ProdukImage;
|
||||
use App\Models\Kategori;
|
||||
use App\Models\Petani;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ProdukSeeder extends Seeder
|
||||
{
|
||||
|
|
@ -12,49 +16,105 @@ class ProdukSeeder extends Seeder
|
|||
*/
|
||||
public function run(): void
|
||||
{
|
||||
$data = [
|
||||
[
|
||||
'petani_id' => 2,
|
||||
'nama_produk' => 'Cabai Merah Keriting Segar',
|
||||
'harga' => 45000,
|
||||
'stok' => 50,
|
||||
'deskripsi' => 'Cabai merah keriting hasil panen pagi ini. Pedas mantap, cocok untuk sambal. Bebas pestisida kimia.',
|
||||
'foto_produk' => null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'petani_id' => 2,
|
||||
'nama_produk' => 'Tomat Buah Organik',
|
||||
'harga' => 12000,
|
||||
'stok' => 100,
|
||||
'deskripsi' => 'Tomat buah ukuran besar, merah merona. Sangat segar untuk jus atau lalapan.',
|
||||
'foto_produk' => null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'petani_id' => 2,
|
||||
'nama_produk' => 'Sawi Hijau (Caisim)',
|
||||
'harga' => 5000,
|
||||
'stok' => 25,
|
||||
'deskripsi' => 'Sawi hijau segar, satu ikat besar kira-kira 500gram. Renyah dan tidak pahit.',
|
||||
'foto_produk' => null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
],
|
||||
[
|
||||
'petani_id' => 2,
|
||||
'nama_produk' => 'Wortel Brastagi Super',
|
||||
'harga' => 15000,
|
||||
'stok' => 40,
|
||||
'deskripsi' => 'Wortel impor lokal kualitas super. Manis, renyah, dan warna oranye pekat.',
|
||||
'foto_produk' => null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]
|
||||
$petani = Petani::inRandomOrder()->first();
|
||||
|
||||
if (!$petani) {
|
||||
$this->command->error('Tabel petani kosong. Jalankan PetaniSeeder terlebih dahulu!');
|
||||
return;
|
||||
}
|
||||
|
||||
// KATEGORI
|
||||
$kategoriGabah = [
|
||||
['nama' => 'Gabah Kering Panen (GKP)', 'slug' => 'gkp', 'ikon' => 'fas fa-seedling'],
|
||||
['nama' => 'Gabah Kering Giling (GKG)', 'slug' => 'gkg', 'ikon' => 'fas fa-sun'],
|
||||
['nama' => 'Benih Padi Unggul', 'slug' => 'benih-padi', 'ikon' => 'fas fa-leaf'],
|
||||
['nama' => 'Padi Ketan', 'slug' => 'padi-ketan', 'ikon' => 'fas fa-box'],
|
||||
['nama' => 'Padi Organik', 'slug' => 'padi-organik', 'ikon' => 'fas fa-heart'],
|
||||
];
|
||||
|
||||
DB::table('produks')->insert($data);
|
||||
foreach ($kategoriGabah as $k) {
|
||||
Kategori::firstOrCreate(
|
||||
['slug' => $k['slug']],
|
||||
[
|
||||
'nama_kategori' => $k['nama'],
|
||||
'ikon' => $k['ikon']
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
// DAFTAR PRODUK
|
||||
$daftarProduk = [
|
||||
[
|
||||
'nama' => 'Gabah Ciherang (GKP) Baru Panen',
|
||||
'harga' => 5200,
|
||||
'stok' => 2000,
|
||||
'deskripsi' => 'Gabah varietas Ciherang kondisi Kering Panen (GKP). Baru dipotong pagi ini. Bulir kuning bersih, hampa rendah. Lokasi sawah pinggir jalan raya, akses truk mudah.',
|
||||
'kategori_slug' => 'gkp',
|
||||
'gallery' => 2
|
||||
],
|
||||
[
|
||||
'nama' => 'Gabah IR-64 Siap Giling (GKG)',
|
||||
'harga' => 7500,
|
||||
'stok' => 500,
|
||||
'deskripsi' => 'Gabah IR-64 kondisi Kering Giling (GKG). Kadar air sudah dibawah 14%, siap masuk huller/penggilingan. Dijamin rendemen beras tinggi.',
|
||||
'kategori_slug' => 'gkg',
|
||||
'gallery' => 3
|
||||
],
|
||||
[
|
||||
'nama' => 'Benih Padi Inpari 32 Bersertifikat',
|
||||
'harga' => 15000,
|
||||
'stok' => 50,
|
||||
'deskripsi' => 'Benih padi varietas Inpari 32 label ungu. Tahan wereng dan penyakit hawar daun. Potensi hasil panen hingga 8 ton/hektar.',
|
||||
'kategori_slug' => 'benih-padi',
|
||||
'gallery' => 1
|
||||
],
|
||||
[
|
||||
'nama' => 'Gabah Padi Ketan Putih Super',
|
||||
'harga' => 8000,
|
||||
'stok' => 300,
|
||||
'deskripsi' => 'Padi ketan putih murni, tidak tercampur padi biasa. Cocok untuk industri tape atau olahan ketan. Kualitas super.',
|
||||
'kategori_slug' => 'padi-ketan',
|
||||
'gallery' => 2
|
||||
],
|
||||
[
|
||||
'nama' => 'Gabah Mentik Wangi Organik',
|
||||
'harga' => 9000,
|
||||
'stok' => 100,
|
||||
'deskripsi' => 'Gabah Mentik Wangi (Pandan Wangi Jawa) ditanam full organik tanpa pestisida kimia. Aroma sangat wangi, beras pulen.',
|
||||
'kategori_slug' => 'padi-organik',
|
||||
'gallery' => 2
|
||||
],
|
||||
[
|
||||
'nama' => 'Gabah Kering Giling (GKG) Situbagendit',
|
||||
'harga' => 7200,
|
||||
'stok' => 1500,
|
||||
'deskripsi' => 'Gabah Situbagendit kering jemur 3 hari. Cocok untuk stok gudang penggilingan. Lokasi Nganjuk.',
|
||||
'kategori_slug' => 'gkg',
|
||||
'gallery' => 1
|
||||
],
|
||||
];
|
||||
|
||||
// INSERT DATA
|
||||
foreach ($daftarProduk as $item) {
|
||||
$kategori = Kategori::where('slug', $item['kategori_slug'])->first();
|
||||
|
||||
// Create Produk
|
||||
$produk = Produk::create([
|
||||
'petani_id' => $petani->id,
|
||||
'kategori_id' => $kategori->id,
|
||||
'nama_produk' => $item['nama'],
|
||||
'harga' => $item['harga'],
|
||||
'stok' => $item['stok'],
|
||||
'deskripsi' => $item['deskripsi'],
|
||||
'foto_produk' => null,
|
||||
]);
|
||||
|
||||
for ($i = 0; $i < $item['gallery']; $i++) {
|
||||
ProdukImage::create([
|
||||
'produk_id' => $produk->id,
|
||||
'foto' => 'dummy/gabah/sample_' . $i . '.jpg',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
|
|
@ -4,123 +4,158 @@
|
|||
@section('page-title', 'Overview Sistem')
|
||||
|
||||
@section('content')
|
||||
<section class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
{{-- Statistik Petani Aktif --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon purple"><i class="bi bi-people-fill"></i></div>
|
||||
<section class="row">
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
{{-- Statistik Petani Aktif --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon purple"><i class="bi bi-people-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Petani Aktif</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalPetani }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Petani Aktif</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalPetani }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Statistik Menunggu Verifikasi --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon red"><i class="bi bi-person-plus-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Verifikasi Pending</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $petaniPending }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Statistik Total Produk --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon green"><i class="bi bi-basket-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Produk</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalProduk }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Statistik Total Transaksi --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon blue"><i class="bi bi-receipt"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Transaksi</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalTransaksi }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Statistik Menunggu Verifikasi --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon red"><i class="bi bi-person-plus-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Verifikasi Pending</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $petaniPending }}</h6>
|
||||
</div>
|
||||
{{-- Tabel Ringkasan Transaksi --}}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Transaksi Terbaru di Platform</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Petani / Usaha</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Tanggal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($transaksiTerbaru as $trx)
|
||||
<tr>
|
||||
<td class="fw-bold text-primary">#{{ $trx->kode_invoice }}</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-bold text-dark">
|
||||
{{ $trx->petani->nama_lengkap ?? 'Petani Tidak Ditemukan' }}
|
||||
</span>
|
||||
<small class="text-muted" style="font-size: 0.85em;">
|
||||
<i class="bi bi-shop me-1"></i>
|
||||
{{ $trx->petani->nama_usaha ?? '-' }}
|
||||
</small>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{{-- Statistik Total Produk --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon green"><i class="bi bi-basket-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Produk</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalProduk }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<td>{{ $trx->pembeli->nama_lengkap ?? 'Guest' }}</td>
|
||||
|
||||
{{-- Statistik Total Transaksi --}}
|
||||
<div class="col-6 col-lg-3 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon blue"><i class="bi bi-receipt"></i></div>
|
||||
<td class="fw-bold">Rp {{ number_format($trx->total_harga, 0, ',', '.') }}</td>
|
||||
|
||||
<td>
|
||||
@php
|
||||
$badgeClass = match ($trx->status) {
|
||||
'selesai' => 'bg-success',
|
||||
'batal' => 'bg-danger',
|
||||
'dikirim' => 'bg-primary',
|
||||
'diproses' => 'bg-info',
|
||||
'menunggu konfirmasi' => 'bg-warning text-dark',
|
||||
default => 'bg-secondary',
|
||||
};
|
||||
@endphp
|
||||
<span class="badge {{ $badgeClass }} rounded-pill px-3">
|
||||
{{ ucwords($trx->status) }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="text-muted small">{{ $trx->created_at->format('d M Y') }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-4 text-muted">
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<i class="bi bi-inbox fs-1 mb-2"></i>
|
||||
Belum ada transaksi baru.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Transaksi</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalTransaksi }}</h6>
|
||||
<div class="text-center mt-3">
|
||||
<a href="{{ route('admin.monitoring') }}" class="btn btn-sm btn-primary">
|
||||
Lihat Semua Data
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Tabel Ringkasan Transaksi Terbaru --}}
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Transaksi Terbaru di Platform</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Tanggal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($transaksiTerbaru as $trx)
|
||||
<tr>
|
||||
<td>#{{ $trx->kode_invoice }}</td>
|
||||
<td>{{ $trx->pembeli->nama_lengkap }}</td>
|
||||
<td>Rp {{ number_format($trx->total_harga, 0, ',', '.') }}</td>
|
||||
<td>
|
||||
<span class="badge bg-{{ $trx->status == 'selesai' ? 'success' : ($trx->status == 'batal' ? 'danger' : 'warning') }}">
|
||||
{{ ucfirst($trx->status) }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ $trx->created_at->diffForHumans() }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr><td colspan="5" class="text-center">Belum ada transaksi.</td></tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<a href="{{ route('admin.monitoring') }}" class="btn btn-sm btn-primary">Lihat Semua Data</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Tambah Kategori')
|
||||
@section('page-title', 'Tambah Kategori Baru')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<form action="{{ route('admin.kategori.store') }}" method="POST">
|
||||
@csrf
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Nama Kategori <span class="text-danger">*</span></label>
|
||||
<input type="text" name="nama_kategori"
|
||||
class="form-control @error('nama_kategori') is-invalid @enderror"
|
||||
placeholder="Contoh: Beras, Sayuran, Buah" value="{{ old('nama_kategori') }}" required>
|
||||
@error('nama_kategori')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">Kode Ikon (FontAwesome/Bootstrap)</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-emoji-smile"></i></span>
|
||||
<input type="text" name="ikon" class="form-control" placeholder="Contoh: fas fa-carrot"
|
||||
value="{{ old('ikon') }}">
|
||||
</div>
|
||||
<div class="form-text small">Opsional. Gunakan class dari FontAwesome atau Bootstrap Icons.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end gap-2">
|
||||
<a href="{{ route('admin.kategori.index') }}" class="btn btn-light border px-4">Batal</a>
|
||||
<button type="submit" class="btn btn-primary px-4">Simpan Kategori</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Edit Kategori')
|
||||
@section('page-title', 'Edit Kategori')
|
||||
|
||||
@section('content')
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body p-4">
|
||||
<form action="{{ route('admin.kategori.update', $kategori->id) }}" method="POST">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold">Nama Kategori <span class="text-danger">*</span></label>
|
||||
<input type="text" name="nama_kategori"
|
||||
class="form-control @error('nama_kategori') is-invalid @enderror"
|
||||
value="{{ old('nama_kategori', $kategori->nama_kategori) }}" required>
|
||||
@error('nama_kategori')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">Kode Ikon</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text">
|
||||
<i class="{{ $kategori->ikon ?? 'bi bi-emoji-smile' }}"></i>
|
||||
</span>
|
||||
<input type="text" name="ikon" class="form-control" placeholder="Contoh: fas fa-carrot"
|
||||
value="{{ old('ikon', $kategori->ikon) }}">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-end gap-2">
|
||||
<a href="{{ route('admin.kategori.index') }}" class="btn btn-light border px-4">Batal</a>
|
||||
<button type="submit" class="btn btn-success px-4">Update Kategori</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Master Kategori')
|
||||
@section('page-title', 'Kelola Kategori Produk')
|
||||
|
||||
@section('content')
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0 fw-bold">Daftar Kategori</h5>
|
||||
<a href="{{ route('admin.kategori.create') }}" class="btn btn-primary btn-sm rounded-pill px-4">
|
||||
<i class="bi bi-plus-lg me-1"></i> Tambah Baru
|
||||
</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
||||
{{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th width="5%">No</th>
|
||||
<th>Ikon</th>
|
||||
<th>Nama Kategori</th>
|
||||
<th>Slug</th>
|
||||
<th>Jumlah Produk</th>
|
||||
<th width="15%" class="text-center">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($kategoris as $index => $kat)
|
||||
<tr>
|
||||
<td>{{ $loop->iteration }}</td>
|
||||
<td>
|
||||
@if($kat->ikon)
|
||||
<i class="{{ $kat->ikon }} fs-5 text-secondary"></i>
|
||||
@else
|
||||
<span class="text-muted">-</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="fw-bold">{{ $kat->nama_kategori }}</td>
|
||||
<td><code class="text-primary">{{ $kat->slug }}</code></td>
|
||||
<td>
|
||||
<span class="badge bg-info bg-opacity-10 text-info rounded-pill px-3">
|
||||
{{ $kat->produks_count }} Produk
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a href="{{ route('admin.kategori.edit', $kat->id) }}" class="btn btn-sm btn-warning me-1">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</a>
|
||||
<form action="{{ route('admin.kategori.destroy', $kat->id) }}" method="POST"
|
||||
class="d-inline"
|
||||
onsubmit="return confirm('Yakin hapus kategori ini? Produk terkait akan kehilangan kategorinya.')">
|
||||
@csrf @method('DELETE')
|
||||
<button type="submit" class="btn btn-sm btn-danger">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="6" class="text-center py-5 text-muted">Belum ada kategori data.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -4,75 +4,122 @@
|
|||
@section('page-title', 'Monitoring Data')
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
{{-- TABEL SEMUA TRANSAKSI --}}
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Semua Transaksi</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Waktu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($transaksis as $t)
|
||||
<tr>
|
||||
<td>{{ $t->kode_invoice }}</td>
|
||||
<td>{{ $t->pembeli->nama_lengkap }}</td>
|
||||
<td>Rp {{ number_format($t->total_harga, 0, ',', '.') }}</td>
|
||||
<td>{{ strtoupper($t->status) }}</td>
|
||||
<td>{{ $t->created_at->format('d M Y H:i') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="row">
|
||||
{{-- TABEL SEMUA TRANSAKSI --}}
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Semua Transaksi</h4>
|
||||
</div>
|
||||
{{ $transaksis->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Petani / Usaha</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Tanggal</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($transaksis as $trx)
|
||||
<tr>
|
||||
<td class="fw-bold text-primary">#{{ $trx->kode_invoice }}</td>
|
||||
<td>
|
||||
<div class="d-flex flex-column">
|
||||
<span class="fw-bold text-dark">
|
||||
{{ $trx->petani->nama_lengkap ?? 'Petani Tidak Ditemukan' }}
|
||||
</span>
|
||||
<small class="text-muted" style="font-size: 0.85em;">
|
||||
<i class="bi bi-shop me-1"></i>
|
||||
{{ $trx->petani->nama_usaha ?? '-' }}
|
||||
</small>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{{-- TABEL SEMUA PRODUK --}}
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Semua Produk Terdaftar</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nama Produk</th>
|
||||
<th>Pemilik (Petani)</th>
|
||||
<th>Harga</th>
|
||||
<th>Stok</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($produks as $p)
|
||||
<tr>
|
||||
<td>{{ $p->nama_produk }}</td>
|
||||
<td>{{ $p->petani->nama_lengkap }}</td>
|
||||
<td>Rp {{ number_format($p->harga, 0, ',', '.') }}</td>
|
||||
<td>{{ $p->stok }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<td>{{ $trx->pembeli->nama_lengkap ?? 'Guest' }}</td>
|
||||
|
||||
<td class="fw-bold">Rp {{ number_format($trx->total_harga, 0, ',', '.') }}</td>
|
||||
|
||||
<td>
|
||||
@php
|
||||
$badgeClass = match ($trx->status) {
|
||||
'selesai' => 'bg-success',
|
||||
'batal' => 'bg-danger',
|
||||
'dikirim' => 'bg-primary',
|
||||
'diproses' => 'bg-info',
|
||||
'menunggu konfirmasi' => 'bg-warning text-dark',
|
||||
default => 'bg-secondary',
|
||||
};
|
||||
@endphp
|
||||
<span class="badge {{ $badgeClass }} rounded-pill px-3">
|
||||
{{ ucwords($trx->status) }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
<td class="text-muted small">{{ $trx->created_at->format('d M Y') }}</td>
|
||||
|
||||
<td>
|
||||
<a href="{{ route('admin.transaksi.detail', $trx->id) }}"
|
||||
class="btn btn-sm btn-info text-white" data-bs-toggle="tooltip"
|
||||
title="Lihat Detail">
|
||||
<i class="bi bi-eye"></i> Detail
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="text-center py-4 text-muted">
|
||||
<div class="d-flex flex-column align-items-center">
|
||||
<i class="bi bi-inbox fs-1 mb-2"></i>
|
||||
Belum ada transaksi baru.
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- TABEL SEMUA PRODUK --}}
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Semua Produk Terdaftar</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nama Produk</th>
|
||||
<th>Pemilik (Petani)</th>
|
||||
<th>Harga</th>
|
||||
<th>Stok</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($produks as $p)
|
||||
<tr>
|
||||
<td>{{ $p->nama_produk }}</td>
|
||||
<td>{{ $p->petani->nama_lengkap }}</td>
|
||||
<td>Rp {{ number_format($p->harga, 0, ',', '.') }}</td>
|
||||
<td>{{ $p->stok }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{ $produks->links() }}
|
||||
</div>
|
||||
{{ $produks->links() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Detail Transaksi')
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<div>
|
||||
<h3 class="mb-0">Detail Transaksi</h3>
|
||||
<span class="text-muted">Invoice: #{{ $transaksi->kode_invoice }}</span>
|
||||
</div>
|
||||
<a href="{{ route('admin.monitoring') }}" class="btn btn-secondary">
|
||||
<i class="bi bi-arrow-left"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card mb-4 border-0 shadow-sm" style="border-radius: 12px; overflow: hidden;">
|
||||
|
||||
{{-- Header Card yang Bersih --}}
|
||||
<div class="card-header bg-white py-3 border-bottom">
|
||||
<h5 class="mb-0 fw-bold text-dark" style="font-size: 1.1rem;">
|
||||
<i class="bi bi-cart3 me-2 text-primary"></i>Daftar Produk
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table align-middle mb-0">
|
||||
<thead style="background-color: #f8f9fa;">
|
||||
<tr>
|
||||
<th scope="col" class="ps-4 py-3 text-secondary small text-uppercase fw-bold"
|
||||
style="width: 45%;">Produk</th>
|
||||
<th scope="col" class="text-end py-3 text-secondary small text-uppercase fw-bold">
|
||||
Harga</th>
|
||||
<th scope="col"
|
||||
class="text-center py-3 text-secondary small text-uppercase fw-bold">Qty</th>
|
||||
<th scope="col"
|
||||
class="text-end pe-4 py-3 text-secondary small text-uppercase fw-bold">Subtotal
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($transaksi->detailTransaksis as $detail)
|
||||
<tr>
|
||||
<td class="ps-4 py-3">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<img src="{{ $detail->produk->foto_produk ? asset('storage/' . $detail->produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=200&auto=format&fit=crop' }}"
|
||||
alt="{{ $detail->produk->nama_produk }}" class="rounded-3 shadow-sm"
|
||||
style="width: 55px; height: 55px; object-fit: cover;">
|
||||
</div>
|
||||
|
||||
{{-- Detail Nama & Badge --}}
|
||||
<div>
|
||||
<div class="fw-bold text-dark mb-1">{{ $detail->produk->nama_produk }}
|
||||
</div>
|
||||
|
||||
{{-- Badge Kategori --}}
|
||||
@php
|
||||
$kategori = $detail->produk->kategori->nama_kategori ?? 'Umum';
|
||||
$badgeColor = match ($kategori) {
|
||||
default => 'bg-primary bg-opacity-10 text-primary'
|
||||
};
|
||||
@endphp
|
||||
<span
|
||||
class="badge {{ $badgeColor }} border border-opacity-10 rounded-pill px-2">
|
||||
{{ $kategori }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
{{-- Harga Satuan --}}
|
||||
<td class="text-end text-muted">
|
||||
<small>Rp {{ number_format($detail->harga_satuan, 0, ',', '.') }}</small>
|
||||
</td>
|
||||
|
||||
{{-- Qty --}}
|
||||
<td class="text-center">
|
||||
<span class="badge bg-light text-dark border px-2 py-1 rounded-pill">
|
||||
x{{ $detail->jumlah }}
|
||||
</span>
|
||||
</td>
|
||||
|
||||
{{-- Subtotal --}}
|
||||
<td class="text-end fw-bold pe-4 text-dark">
|
||||
Rp {{ number_format($detail->subtotal, 0, ',', '.') }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
|
||||
{{-- Footer Total --}}
|
||||
<tfoot class="bg-white">
|
||||
<tr>
|
||||
<td colspan="4" class="p-0">
|
||||
<div class="d-flex justify-content-end align-items-center p-4"
|
||||
style="background: linear-gradient(to right, #fff, #f8f9fa);">
|
||||
<div class="text-end">
|
||||
<span class="text-muted d-block small mb-1">Total Transaksi</span>
|
||||
<h4 class="fw-bolder text-primary mb-0">
|
||||
Rp {{ number_format($transaksi->total_harga, 0, ',', '.') }}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Info Pihak Terkait --}}
|
||||
<div class="col-md-4">
|
||||
{{-- Info Status --}}
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title text-muted">Status Pesanan</h6>
|
||||
@php
|
||||
$badgeClass = match ($transaksi->status) {
|
||||
'selesai' => 'bg-success',
|
||||
'batal' => 'bg-danger',
|
||||
'dikirim' => 'bg-primary',
|
||||
'diproses' => 'bg-info',
|
||||
'menunggu konfirmasi' => 'bg-warning text-dark',
|
||||
default => 'bg-secondary',
|
||||
};
|
||||
@endphp
|
||||
<span class="badge {{ $badgeClass }} fs-6 w-100 py-2">
|
||||
{{ ucwords($transaksi->status) }}
|
||||
</span>
|
||||
<small class="text-muted d-block mt-2 text-center">
|
||||
Tanggal: {{ $transaksi->created_at->format('d M Y H:i') }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Info Pembeli --}}
|
||||
<div class="card mb-3">
|
||||
<div class="card-header bg-white">
|
||||
<i class="bi bi-person-circle me-1"></i> Data Pembeli
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold">{{ $transaksi->pembeli->nama_lengkap ?? 'Guest' }}</h6>
|
||||
<p class="mb-1 small text-muted"><i class="bi bi-telephone"></i>
|
||||
{{ $transaksi->pembeli->no_hp ?? '-' }}</p>
|
||||
<hr>
|
||||
<small class="text-muted">Alamat Pengiriman:</small>
|
||||
<p class="mb-0 small">{{ $transaksi->alamat_pengiriman }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Info Petani --}}
|
||||
<div class="card">
|
||||
<div class="card-header bg-white">
|
||||
<i class="bi bi-shop me-1"></i> Data Penjual (Petani)
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6 class="fw-bold">{{ $transaksi->petani->nama_lengkap ?? 'Tidak Diketahui' }}</h6>
|
||||
<p class="mb-0 small text-muted">{{ $transaksi->petani->nama_usaha ?? '-' }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Masuk - TaniDesa</title>
|
||||
<title>Masuk - GriyaPadi.id</title>
|
||||
<link href="{{ asset('template/frontend/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" />
|
||||
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
<div class="card-body">
|
||||
<div class="text-center mb-4">
|
||||
<a href="{{ url('/') }}" class="text-decoration-none">
|
||||
<h2 class="fw-bold text-tani"><i class="fas fa-leaf me-2"></i>TaniDesa</h2>
|
||||
<h2 class="fw-bold text-tani"><i class="fas fa-leaf me-2"></i>GriyaPadi.id</h2>
|
||||
</a>
|
||||
<p class="text-muted small">Masuk untuk melanjutkan</p>
|
||||
</div>
|
||||
|
|
@ -58,7 +58,7 @@
|
|||
</div>
|
||||
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-tani rounded-pill py-2">MASUK</button>
|
||||
<button type="submit" class="btn btn-tani rounded-pill py-2">Login</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Daftar - TaniDesa</title>
|
||||
<title>Daftar - GriyaPadi.id</title>
|
||||
<link href="{{ asset('template/frontend/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" />
|
||||
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
<div class="card-body">
|
||||
<div class="text-center mb-4">
|
||||
<h2 class="fw-bold text-tani">Daftar Akun</h2>
|
||||
<p class="text-muted small">Gabung komunitas TaniDesa</p>
|
||||
<p class="text-muted small">Gabung komunitas GriyaPadi.id</p>
|
||||
</div>
|
||||
|
||||
<form action="{{ route('register.proses') }}" method="POST">
|
||||
|
|
@ -150,7 +150,7 @@
|
|||
</div>
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
<button type="submit" class="btn btn-tani rounded-pill py-2">DAFTAR SEKARANG</button>
|
||||
<button type="submit" class="btn btn-tani rounded-pill py-2">Register</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<html lang="id">
|
||||
|
||||
<head>
|
||||
<title>Reset Password - TaniDesa</title>
|
||||
<title>Reset Password - GriyaPadi.id</title>
|
||||
<link href="{{ asset('template/frontend/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" />
|
||||
<style>
|
||||
|
|
|
|||
|
|
@ -47,25 +47,32 @@ class="rounded-3 me-3"
|
|||
</div>
|
||||
</td>
|
||||
<td class="text-muted">Rp
|
||||
{{ number_format($details['price'], 0, ',', '.') }}</td>
|
||||
<td>
|
||||
<div class="input-group quantity" style="width: 100px;">
|
||||
<button class="btn btn-sm btn-light border btn-minus-custom">
|
||||
<i class="fa fa-minus x-small"></i>
|
||||
{{ number_format($details['price'], 0, ',', '.') }}
|
||||
</td>
|
||||
<td class="align-middle text-center">
|
||||
<div class="input-group input-group-sm flex-nowrap mx-auto shadow-sm"
|
||||
style="width: 120px;">
|
||||
|
||||
{{-- Tombol Minus --}}
|
||||
<button class="btn btn-light border btn-minus-custom" type="button">
|
||||
<i class="fas fa-minus text-secondary" style="font-size: 0.8rem;"></i>
|
||||
</button>
|
||||
|
||||
{{-- Input Jumlah --}}
|
||||
<input type="text"
|
||||
class="form-control form-control-sm text-center border-0 qty-input bg-white"
|
||||
value="{{ $details['quantity'] }}" readonly>
|
||||
<button class="btn btn-sm btn-light border btn-plus-custom">
|
||||
<i class="fa fa-plus x-small"></i>
|
||||
class="form-control text-center border-top border-bottom border-light bg-white qty-input px-0"
|
||||
value="{{ $details['quantity'] }}" readonly style="min-width: 40px;">
|
||||
|
||||
{{-- Tombol Plus --}}
|
||||
<button class="btn btn-light border btn-plus-custom" type="button">
|
||||
<i class="fas fa-plus text-secondary" style="font-size: 0.8rem;"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="fw-bold text-dark">Rp {{ number_format($total, 0, ',', '.') }}
|
||||
</td>
|
||||
<td class="pe-4 text-end">
|
||||
<form action="{{ route('cart.remove') }}" method="POST"
|
||||
class="d-inline">
|
||||
<form action="{{ route('cart.remove') }}" method="POST" class="d-inline">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<input type="hidden" name="id" value="{{ $id }}">
|
||||
|
|
@ -97,12 +104,10 @@ class="d-inline">
|
|||
<span class="fw-bold fs-5 text-primary">Rp
|
||||
{{ number_format($total_belanja, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
<a href="{{ route('checkout') }}"
|
||||
class="btn btn-primary w-100 rounded-pill py-3 fw-bold shadow-sm">
|
||||
<a href="{{ route('checkout') }}" class="btn btn-primary w-100 rounded-pill py-3 fw-bold shadow-sm">
|
||||
Checkout Sekarang
|
||||
</a>
|
||||
<a href="{{ route('shop') }}"
|
||||
class="btn btn-link text-muted w-100 mt-2 text-decoration-none small">
|
||||
<a href="{{ route('shop') }}" class="btn btn-link text-muted w-100 mt-2 text-decoration-none small">
|
||||
Lanjut Belanja
|
||||
</a>
|
||||
</div>
|
||||
|
|
@ -126,10 +131,10 @@ class="btn btn-link text-muted w-100 mt-2 text-decoration-none small">
|
|||
|
||||
@section('js')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function () {
|
||||
$(".quantity button").off("click");
|
||||
|
||||
$(".btn-plus-custom").click(function(e) {
|
||||
$(".btn-plus-custom").click(function (e) {
|
||||
e.preventDefault();
|
||||
var ele = $(this);
|
||||
var input = ele.closest("tr").find(".qty-input");
|
||||
|
|
@ -139,7 +144,7 @@ class="btn btn-link text-muted w-100 mt-2 text-decoration-none small">
|
|||
updateCart(ele.closest("tr").attr("data-id"), newVal);
|
||||
});
|
||||
|
||||
$(".btn-minus-custom").click(function(e) {
|
||||
$(".btn-minus-custom").click(function (e) {
|
||||
e.preventDefault();
|
||||
var ele = $(this);
|
||||
var input = ele.closest("tr").find(".qty-input");
|
||||
|
|
@ -160,11 +165,11 @@ function updateCart(id, qty) {
|
|||
id: id,
|
||||
quantity: qty
|
||||
},
|
||||
success: function(response) {
|
||||
success: function (response) {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
@ -4,136 +4,216 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<div class="container-fluid bg-light py-3 mb-4">
|
||||
{{-- BREADCRUMB --}}
|
||||
<div class="container-fluid py-3 mb-3">
|
||||
<div class="container">
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb m-0">
|
||||
<li class="breadcrumb-item"><a href="{{ url('/') }}" class="text-muted text-decoration-none">Home</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('shop') }}"
|
||||
class="text-muted text-decoration-none">Belanja</a></li>
|
||||
<li class="breadcrumb-item active text-primary fw-bold" aria-current="page">{{ $produk->nama_produk }}
|
||||
</li>
|
||||
<ol class="breadcrumb mb-0">
|
||||
<li class="breadcrumb-item"><a href="{{ url('/') }}" class="text-decoration-none">Home</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('shop') }}" class="text-decoration-none">Belanja</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">{{ Str::limit($produk->nama_produk, 40) }}</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container pb-5">
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-6">
|
||||
<div class="rounded-4 overflow-hidden shadow-sm border position-relative bg-white">
|
||||
<img src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : asset('template/frontend/img/fruite-item-5.jpg') }}"
|
||||
class="img-fluid w-100" style="object-fit: cover; max-height: 500px;"
|
||||
alt="{{ $produk->nama_produk }}">
|
||||
<div class="row g-4 g-lg-5">
|
||||
|
||||
<div class="position-absolute top-0 start-0 m-3">
|
||||
@if ($produk->stok > 0)
|
||||
<span class="badge bg-primary shadow-sm px-3 py-2 rounded-pill">Stok Tersedia</span>
|
||||
@else
|
||||
<span class="badge bg-danger shadow-sm px-3 py-2 rounded-pill">Stok Habis</span>
|
||||
{{-- GALERI PRODUK --}}
|
||||
<div class="col-lg-5">
|
||||
<div class="sticky-top" style="top: 120px; z-index: 1;">
|
||||
|
||||
{{-- GAMBAR UTAMA (BESAR) --}}
|
||||
<div class="card border-0 rounded-4 shadow-sm overflow-hidden mb-3">
|
||||
<div class="ratio ratio-4x3 bg-light">
|
||||
<img id="main-image"
|
||||
src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : asset('template/frontend/img/no-image.jpg') }}"
|
||||
class="object-fit-cover cursor-pointer" alt="{{ $produk->nama_produk }}"
|
||||
onerror="this.src='{{ asset('template/frontend/img/no-image.jpg') }}';">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- THUMBNAIL (GAMBAR KECIL) --}}
|
||||
<div class="d-flex gap-2 overflow-auto pb-2" style="scrollbar-width: thin;">
|
||||
|
||||
@if($produk->foto_produk)
|
||||
<div class="flex-shrink-0" style="width: 80px; height: 80px;">
|
||||
<img src="{{ asset('storage/' . $produk->foto_produk) }}"
|
||||
class="img-thumbnail w-100 h-100 object-fit-cover rounded-3 border-primary thumbnail-active"
|
||||
onclick="changeImage(this)" style="cursor: pointer; border-width: 2px;">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($produk->images && $produk->images->count() > 0)
|
||||
@foreach($produk->images as $img)
|
||||
<div class="flex-shrink-0" style="width: 80px; height: 80px;">
|
||||
<img src="{{ asset('storage/' . $img->foto) }}"
|
||||
class="img-thumbnail w-100 h-100 object-fit-cover rounded-3 border-0 opacity-75"
|
||||
onclick="changeImage(this)" style="cursor: pointer; transition: all 0.2s;">
|
||||
</div>
|
||||
@endforeach
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-6">
|
||||
<div class="h-100 d-flex flex-column justify-content-center">
|
||||
|
||||
<div class="mb-2">
|
||||
{{-- INFO & AKSI --}}
|
||||
<div class="col-lg-7">
|
||||
<div class="ps-lg-4">
|
||||
|
||||
{{-- Kategori Badge --}}
|
||||
<div class="mb-3">
|
||||
<span
|
||||
class="badge bg-light text-dark border border-secondary text-uppercase px-3 py-2 rounded-pill fw-bold">
|
||||
{{ $produk->kategori ?? 'Hasil Tani' }}
|
||||
class="badge bg-primary bg-opacity-10 px-3 py-2 rounded-pill fw-bold border border-primary border-opacity-10">
|
||||
<i class="fas fa-tag me-1"></i> {{ $produk->kategori->nama_kategori ?? 'Sayur & Buah' }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<h1 class="fw-bold display-6 text-dark mb-2">{{ $produk->nama_produk }}</h1>
|
||||
{{-- Nama Produk --}}
|
||||
<h1 class="display-6 fw-bold text-dark mb-2">{{ $produk->nama_produk }}</h1>
|
||||
|
||||
<div class="mb-4">
|
||||
<h2 class="fw-bold text-primary display-5 mb-0">
|
||||
{{-- Harga --}}
|
||||
<div class="d-flex align-items-baseline gap-2 mb-4 pb-4 border-bottom">
|
||||
<h3 class="text-primary fw-bold mb-0">
|
||||
Rp {{ number_format($produk->harga, 0, ',', '.') }}
|
||||
<span class="fs-6 text-muted fw-normal">/ kg</span>
|
||||
</h2>
|
||||
</h3>
|
||||
<span class="text-muted fs-5">/ kg</span>
|
||||
</div>
|
||||
|
||||
<p class="text-secondary mb-4" style="line-height: 1.8; font-size: 1.05rem;">
|
||||
{{ $produk->deskripsi }}
|
||||
</p>
|
||||
{{-- Deskripsi --}}
|
||||
<div class="mb-4">
|
||||
<h6 class="fw-bold text-dark">Deskripsi Produk</h6>
|
||||
<p class="text-black-50 small mb-0" style="line-height: 1.8;">
|
||||
{{ $produk->deskripsi }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center bg-white border rounded-4 p-3 mb-4 shadow-sm">
|
||||
<div class="bg-light rounded-circle p-2 me-3 d-flex align-items-center justify-content-center text-primary"
|
||||
style="width: 50px; height: 50px;">
|
||||
<i class="fas fa-user-tie fs-4"></i>
|
||||
{{-- Info Penjual --}}
|
||||
<div class="d-flex align-items-center bg-light border rounded-3 p-3 mb-4">
|
||||
<div class="bg-white rounded-circle p-2 me-3 shadow-sm text-primary d-flex align-items-center justify-content-center"
|
||||
style="width: 45px; height: 45px;">
|
||||
<i class="fas fa-store fs-5"></i>
|
||||
</div>
|
||||
<div class="flex-grow-1">
|
||||
<p class="mb-0 text-muted small">Dijual oleh:</p>
|
||||
<h6 class="mb-0 fw-bold text-dark">{{ $produk->petani->nama_lengkap ?? 'Petani Mitra' }}</h6>
|
||||
<p class="text-muted small mb-0 fw-bold text-uppercase" style="font-size: 0.7rem;">Dijual Oleh
|
||||
</p>
|
||||
<h6 class="fw-bold text-dark mb-0">{{ $produk->petani->nama_lengkap ?? 'Petani Mitra' }}</h6>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm rounded-pill px-3"
|
||||
<button type="button" class="btn btn-outline-success btn-sm rounded-pill px-3 fw-bold"
|
||||
data-bs-toggle="modal" data-bs-target="#chatModal">
|
||||
<i class="fas fa-comment-dots me-1"></i> Chat
|
||||
<i class="fab fa-whatsapp me-1"></i> Chat
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{-- FORM PEMBELIAN --}}
|
||||
<form action="{{ route('cart.add') }}" method="POST">
|
||||
@csrf
|
||||
<input type="hidden" name="id" value="{{ $produk->id }}">
|
||||
|
||||
<div class="d-flex align-items-center mb-4 flex-wrap gap-3">
|
||||
<div class="input-group shadow-sm" style="width: 140px;">
|
||||
<button type="button" class="btn btn-light border" onclick="updateQty(-1)">
|
||||
<i class="fa fa-minus small"></i>
|
||||
</button>
|
||||
<input type="number" name="qty" id="input-qty"
|
||||
class="form-control text-center bg-white border-top border-bottom border-0"
|
||||
value="1" min="1" max="{{ $produk->stok }}" readonly>
|
||||
<button type="button" class="btn btn-light border" onclick="updateQty(1)">
|
||||
<i class="fa fa-plus small"></i>
|
||||
</button>
|
||||
<div class="mb-4">
|
||||
{{-- Input Jumlah --}}
|
||||
<div class="mb-3">
|
||||
<label class="form-label small fw-bold text-muted text-uppercase mb-2">Atur Jumlah</label>
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="input-group" style="max-width: 180px;">
|
||||
<button type="button" class="btn btn-outline-primary" onclick="updateQty(-1)">
|
||||
<i class="fas fa-minus"></i>
|
||||
</button>
|
||||
<input type="text" class="form-control text-center fw-bold bg-white"
|
||||
id="display-qty" value="1" readonly>
|
||||
<input type="hidden" name="qty" id="real-input-qty" value="1" min="1"
|
||||
max="{{ $produk->stok }}">
|
||||
<button type="button" class="btn btn-outline-primary" onclick="updateQty(1)">
|
||||
<i class="fas fa-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="ms-3 small text-muted">
|
||||
Stok: <span class="fw-bold text-dark">{{ $produk->stok }} Kg</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Tombol Aksi --}}
|
||||
<div class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary rounded-pill py-2 shadow-sm fw-bold fs-6"
|
||||
style="height: 50px;">
|
||||
<i class="fas fa-cart-plus me-2"></i> Masukkan Keranjang
|
||||
</button>
|
||||
<a href="javascript:void(0);" onclick="beliLangsung()"
|
||||
class="btn btn-outline-dark rounded-pill py-2 border-2 fw-bold fs-6"
|
||||
style="height: 50px; line-height: 32px;">
|
||||
Beli Sekarang
|
||||
</a>
|
||||
</div>
|
||||
<span class="text-muted small">
|
||||
Sisa Stok: <strong class="text-dark">{{ $produk->stok }} Kg</strong>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="d-grid gap-2 d-sm-flex">
|
||||
<button type="submit" class="btn btn-primary btn-lg rounded-pill px-5 shadow-sm flex-grow-1">
|
||||
<i class="fa fa-shopping-basket me-2"></i> + Keranjang
|
||||
</button>
|
||||
|
||||
<a href="javascript:void(0);" onclick="beliLangsung()"
|
||||
class="btn btn-outline-secondary btn-lg rounded-pill px-4 flex-grow-1">
|
||||
Beli Langsung
|
||||
</a>
|
||||
{{-- Footer Info --}}
|
||||
<div class="d-flex gap-4 pt-3 border-top">
|
||||
<div class="d-flex align-items-center text-muted small">
|
||||
<i class="fas fa-truck me-2 text-primary"></i> Pengiriman Cepat
|
||||
</div>
|
||||
<div class="d-flex align-items-center text-muted small">
|
||||
<i class="fas fa-shield-alt me-2 text-primary"></i> Produk Segar
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (isset($produk_terkait) && count($produk_terkait) > 0)
|
||||
<div class="mt-5 pt-5 border-top">
|
||||
|
||||
{{-- BAGIAN PRODUK TERKAIT --}}
|
||||
@if (isset($produk_terkait) && $produk_terkait->count() > 0)
|
||||
<div class="mt-5 pt-4 border-top">
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<h3 class="fw-bold m-0 text-dark">Produk Sejenis</h3>
|
||||
<a href="{{ route('shop') }}" class="text-primary text-decoration-none fw-bold small">
|
||||
Lihat Semua <i class="fas fa-arrow-right ms-1"></i>
|
||||
<h4 class="fw-bold m-0 text-dark">Produk Sejenis</h4>
|
||||
<a href="{{ route('shop') }}" class="btn btn-sm btn-outline-primary rounded-pill px-3">
|
||||
Lihat Lainnya <i class="fas fa-arrow-right ms-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
@foreach ($produk_terkait as $related)
|
||||
@foreach ($produk_terkait as $produk)
|
||||
<div class="col-6 col-md-3">
|
||||
<a href="{{ route('produk.detail', $related->id) }}" class="text-decoration-none">
|
||||
<div class="card h-100 border-0 shadow-sm overflow-hidden rounded-4">
|
||||
<div class="position-relative">
|
||||
<img src="{{ $related->foto_produk ? asset('storage/' . $related->foto_produk) : asset('template/frontend/img/fruite-item-5.jpg') }}"
|
||||
class="card-img-top" style="height: 200px; object-fit: cover;"
|
||||
alt="{{ $related->nama_produk }}">
|
||||
<a href="{{ route('produk.detail', $produk->id) }}" class="text-decoration-none">
|
||||
<div class="card border-0 shadow-sm h-100 product-card">
|
||||
<!-- Stock Badge -->
|
||||
<div class="position-absolute top-0 end-0 m-2 z-1">
|
||||
<span class="badge bg-warning text-dark">
|
||||
Stok: {{ $produk->stok }} Kg
|
||||
</span>
|
||||
</div>
|
||||
<div class="card-body p-3">
|
||||
<h6 class="fw-bold text-dark mb-1 text-truncate">{{ $related->nama_produk }}</h6>
|
||||
<p class="text-primary fw-bold mb-0">Rp
|
||||
{{ number_format($related->harga, 0, ',', '.') }}</p>
|
||||
|
||||
<!-- Image -->
|
||||
<div class="overflow-hidden" style="height: 200px;">
|
||||
<img src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=800&auto=format&fit=crop' }}"
|
||||
class="card-img-top w-100 h-100" alt="{{ $produk->nama_produk }}"
|
||||
style="object-fit: cover;">
|
||||
</div>
|
||||
|
||||
<div class="card-body d-flex justify-content-between flex-column p-3">
|
||||
<div>
|
||||
<span class="badge bg-success mb-2">{{ $produk->kategori ?? 'Umum' }}</span>
|
||||
<h6 class="fw-bold mb-2">{{ $produk->nama_produk }}</h6>
|
||||
<p class="text-muted small mb-3">{{ Str::limit($produk->deskripsi, 60) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center pt-2 border-top">
|
||||
<div>
|
||||
<small class="text-muted">Harga/Kg</small>
|
||||
<h6 class="fw-bold text-success mb-0">
|
||||
Rp {{ number_format($produk->harga, 0, ',', '.') }}
|
||||
</h6>
|
||||
</div>
|
||||
<a href="{{ route('produk.detail', $produk->id) }}"
|
||||
class="btn btn-success btn-sm rounded-pill">
|
||||
<i class="fa fa-eye"></i> Detail
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
@ -144,12 +224,16 @@ class="card-img-top" style="height: 200px; object-fit: cover;"
|
|||
@endif
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="chatModal" tabindex="-1">
|
||||
{{-- MODAL CHAT --}}
|
||||
<div class="modal fade" id="chatModal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0 shadow-lg rounded-4">
|
||||
<div class="modal-header bg-primary text-white border-0 rounded-top-4">
|
||||
<h5 class="modal-title fw-bold">Hubungi Petani</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
<div class="modal-content border-0 shadow-lg rounded-3">
|
||||
<div class="modal-header bg-primary text-white border-0">
|
||||
<h5 class="modal-title fw-semibold text-white">
|
||||
<i class="fab fa-whatsapp me-2"></i>Hubungi Penjual
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
<form action="{{ route('pesan.kirim') }}" method="POST">
|
||||
@csrf
|
||||
|
|
@ -158,41 +242,75 @@ class="card-img-top" style="height: 200px; object-fit: cover;"
|
|||
<input type="hidden" name="penerima_type" value="App\Models\Petani">
|
||||
|
||||
<div class="mb-3">
|
||||
<label class="form-label fw-bold small text-muted text-uppercase">Pesan Anda</label>
|
||||
<textarea name="isi_pesan" class="form-control bg-light border-0 rounded-3 p-3" rows="4" required
|
||||
placeholder="Halo, saya tertarik dengan produk ini..."></textarea>
|
||||
<label class="form-label fw-bold">Kepada:</label>
|
||||
<input type="text" class="form-control"
|
||||
value="{{ $produk->petani->nama_lengkap ?? 'Petani Mitra' }}" readonly>
|
||||
</div>
|
||||
|
||||
<div class="mb-0">
|
||||
<label class="form-label fw-bold">Pesan Anda:</label>
|
||||
<textarea name="isi_pesan" class="form-control" rows="4" required
|
||||
placeholder="Contoh: Halo, apakah stok untuk produk {{ $produk->nama_produk }} masih tersedia?"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer border-0 px-4 pb-4 pt-0">
|
||||
<button type="button" class="btn btn-light rounded-pill px-4"
|
||||
data-bs-dismiss="modal">Batal</button>
|
||||
<button type="submit" class="btn btn-primary rounded-pill px-4 shadow-sm">
|
||||
<i class="fas fa-paper-plane me-2"></i> Kirim Pesan
|
||||
<button type="button" class="btn btn-light rounded-pill px-4" data-bs-dismiss="modal">Batal</button>
|
||||
<button type="submit" class="btn btn-primary rounded-pill px-4">
|
||||
<i class="fab fa-whatsapp me-2"></i>Kirim Pesan
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('js')
|
||||
<script>
|
||||
// Fungsi untuk update input number
|
||||
const hargaSatuan = {{ $produk->harga }};
|
||||
|
||||
function updateQty(change) {
|
||||
let input = document.getElementById('input-qty');
|
||||
let newVal = parseInt(input.value) + change;
|
||||
let display = document.getElementById('display-qty');
|
||||
let input = document.getElementById('real-input-qty');
|
||||
let subtotalEl = document.getElementById('subtotal');
|
||||
|
||||
let currentVal = parseInt(input.value);
|
||||
let newVal = currentVal + change;
|
||||
let max = parseInt(input.getAttribute('max'));
|
||||
|
||||
if (newVal >= 1 && newVal <= max) {
|
||||
input.value = newVal;
|
||||
display.value = newVal;
|
||||
|
||||
// Update subtotal
|
||||
let subtotal = newVal * hargaSatuan;
|
||||
subtotalEl.textContent = 'Rp ' + subtotal.toLocaleString('id-ID');
|
||||
}
|
||||
}
|
||||
|
||||
// Redirect dengan membawa QTY
|
||||
function beliLangsung() {
|
||||
let qty = document.getElementById('input-qty').value;
|
||||
let qty = document.getElementById('real-input-qty').value;
|
||||
let produkId = "{{ $produk->id }}";
|
||||
window.location.href = "{{ route('checkout') }}?produk_id=" + produkId + "&qty=" + qty;
|
||||
}
|
||||
|
||||
// FUNGSI GANTI GAMBAR GALERI
|
||||
function changeImage(element) {
|
||||
document.getElementById('main-image').src = element.src;
|
||||
|
||||
let thumbnails = document.querySelectorAll('.img-thumbnail');
|
||||
thumbnails.forEach(img => {
|
||||
img.classList.remove('border-primary', 'thumbnail-active');
|
||||
img.classList.add('border-0', 'opacity-75');
|
||||
img.style.borderWidth = '1px';
|
||||
});
|
||||
|
||||
// Highlight thumbnail yang sedang aktif
|
||||
element.classList.remove('border-0', 'opacity-75');
|
||||
element.classList.add('border-primary', 'thumbnail-active');
|
||||
element.style.borderWidth = '2px';
|
||||
element.style.opacity = '1';
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
@section('content')
|
||||
|
||||
<div class="container-fluid py-5 mb-5 hero-header bg-light">
|
||||
<div class="container py-5">
|
||||
<div class="row align-items-center g-5">
|
||||
<div class="container-fluid mb-5 bg-white">
|
||||
<div class="container">
|
||||
<div class="row align-items-center g-5 py-5">
|
||||
<div class="col-lg-6 order-2 order-lg-1">
|
||||
<div class="d-inline-block border border-secondary text-secondary rounded-pill px-3 py-2 mb-3 fw-bold">
|
||||
🌾 Mitra Petani Padi Indonesia
|
||||
</div>
|
||||
<h1 class="display-4 fw-bold text-dark mb-4">
|
||||
Jual Beli Gabah & <br>
|
||||
Jual Gabah & <br>
|
||||
<span class="text-primary">Beras Berkualitas.</span>
|
||||
</h1>
|
||||
<p class="lead text-muted mb-5">
|
||||
|
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
<div class="col-lg-6 order-1 order-lg-2 text-center">
|
||||
<div class="position-relative d-inline-block">
|
||||
<img src="https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=1000&auto=format&fit=crop"
|
||||
<img src="{{ asset('images/banner.jpg') }}"
|
||||
class="img-fluid rounded-circle shadow-lg w-100" style="max-height: 450px; object-fit: cover;"
|
||||
alt="Padi Premium">
|
||||
<div class="position-absolute bg-white p-3 rounded-3 shadow d-none d-md-block"
|
||||
|
|
|
|||
|
|
@ -2,33 +2,166 @@
|
|||
@section('title', 'Chat dengan ' . $lawan->nama_lengkap)
|
||||
|
||||
@section('content')
|
||||
<div class="container py-5">
|
||||
<div class="row g-0 chat-container">
|
||||
<style>
|
||||
.chat-layout {
|
||||
height: 80vh;
|
||||
background-color: #fff;
|
||||
border: 1px solid #e9ecef;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<div class="col-md-4 chat-sidebar d-none d-md-block">
|
||||
<div class="p-3 bg-white sticky-top border-bottom">
|
||||
<input type="text" class="form-control rounded-pill" placeholder="Cari pesan...">
|
||||
/* --- Sidebar Kiri (List User) --- */
|
||||
.chat-sidebar {
|
||||
background-color: #fff;
|
||||
border-right: 1px solid #f0f0f0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-item {
|
||||
transition: all 0.2s;
|
||||
border-bottom: 1px solid #f8f9fa;
|
||||
}
|
||||
|
||||
.chat-item:hover,
|
||||
.chat-item.active {
|
||||
background-color: #f9fdf0;
|
||||
border-left: 4px solid #81c408;
|
||||
}
|
||||
|
||||
/* --- Area Chat Kanan --- */
|
||||
.chat-main {
|
||||
background-color: #ffffff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
padding: 15px 20px;
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 25px;
|
||||
background-color: #fafafa;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
/* --- Bubble Chat Style --- */
|
||||
.chat-bubble {
|
||||
max-width: 75%;
|
||||
padding: 12px 18px;
|
||||
position: relative;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.5;
|
||||
border-radius: 18px;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* Pesan SAYA */
|
||||
.bubble-me {
|
||||
background-color: #81c408;
|
||||
color: #ffffff;
|
||||
align-self: flex-end;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
/* Pesan LAWAN */
|
||||
.bubble-other {
|
||||
background-color: #f1f3f5;
|
||||
color: #333333;
|
||||
align-self: flex-start;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
|
||||
.chat-time {
|
||||
font-size: 0.7rem;
|
||||
margin-top: 4px;
|
||||
display: block;
|
||||
text-align: right;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.chat-footer {
|
||||
padding: 15px 20px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.btn-send {
|
||||
background-color: #81c408;
|
||||
color: white;
|
||||
border: none;
|
||||
transition: 0.3s;
|
||||
}
|
||||
|
||||
.btn-send:hover {
|
||||
background-color: #6da705;
|
||||
color: white;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #ddd;
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container py-5">
|
||||
<div class="row g-0 chat-layout shadow-sm">
|
||||
|
||||
{{-- SIDEBAR KIRI --}}
|
||||
<div class="col-md-4 chat-sidebar d-none d-md-flex">
|
||||
{{-- Header Sidebar --}}
|
||||
<div class="p-3 border-bottom">
|
||||
<h6 class="fw-bold text-dark mb-3">Pesan Masuk</h6>
|
||||
<input type="text" class="form-control bg-light border-0 rounded-pill" placeholder="Cari percakapan...">
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
{{-- List Chat --}}
|
||||
<div class="flex-grow-1 overflow-auto">
|
||||
@foreach ($chatList as $chat)
|
||||
<a href="{{ route('pembeli.pesan.show', $chat['lawan_id']) }}"
|
||||
class="list-group-item list-group-item-action chat-list-item py-3 {{ $chat['lawan_id'] == $lawan->id ? 'active' : '' }}">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ asset('template/frontend/img/avatar.jpg') }}" class="rounded-circle"
|
||||
width="50" height="50" style="object-fit: cover;">
|
||||
<div class="ms-3 flex-grow-1 overflow-hidden">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<h6
|
||||
class="mb-0 fw-bold {{ $chat['lawan_id'] == $lawan->id ? 'text-dark' : 'text-dark' }}">
|
||||
{{ $chat['nama'] }}</h6>
|
||||
<small
|
||||
class="{{ $chat['lawan_id'] == $lawan->id ? 'text-muted' : 'text-muted' }}">{{ $chat['time'] }}</small>
|
||||
</div>
|
||||
<p
|
||||
class="mb-0 small text-truncate {{ $chat['lawan_id'] == $lawan->id ? 'text-dark' : 'text-muted' }}">
|
||||
{{ Str::limit($chat['last_message'], 30) }}
|
||||
class="d-flex align-items-center p-3 text-decoration-none text-dark chat-item {{ $chat['lawan_id'] == $lawan->id ? 'active' : '' }}">
|
||||
|
||||
{{-- Avatar --}}
|
||||
<div class="position-relative">
|
||||
<img src="{{ asset('template/frontend/img/avatar.jpg') }}" class="rounded-circle" width="45"
|
||||
height="45" style="object-fit: cover;">
|
||||
@if($chat['unread'] > 0)
|
||||
<span
|
||||
class="position-absolute top-0 start-100 translate-middle p-1 bg-danger border border-light rounded-circle"></span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="ms-3 flex-grow-1 overflow-hidden">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold small">{{ $chat['nama'] }}</span>
|
||||
<span class="text-muted" style="font-size: 0.7rem;">{{ $chat['time'] }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center mt-1">
|
||||
<p class="mb-0 text-muted small text-truncate" style="max-width: 85%;">
|
||||
{{ Str::limit($chat['last_message'], 25) }}
|
||||
</p>
|
||||
@if($chat['unread'] > 0)
|
||||
<span class="badge bg-danger rounded-pill"
|
||||
style="font-size: 0.6rem;">{{ $chat['unread'] }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
|
|
@ -36,70 +169,80 @@ class="mb-0 small text-truncate {{ $chat['lawan_id'] == $lawan->id ? 'text-dark'
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 chat-content">
|
||||
{{-- AREA CHAT KANAN --}}
|
||||
<div class="col-md-8 chat-main">
|
||||
|
||||
{{-- Chat Header --}}
|
||||
<div class="chat-header d-flex align-items-center bg-white shadow-sm">
|
||||
<a href="{{ route('pembeli.pesan.index') }}" class="d-md-none me-3 text-dark">
|
||||
<i class="fas fa-arrow-left"></i>
|
||||
</a>
|
||||
{{-- Header Chat --}}
|
||||
<div class="chat-header d-flex align-items-center justify-content-between">
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="{{ route('pembeli.pesan.index') }}" class="d-md-none me-3 text-dark"><i
|
||||
class="fas fa-arrow-left"></i></a>
|
||||
|
||||
<div class="bg-success text-white rounded-circle d-flex align-items-center justify-content-center fw-bold me-3"
|
||||
style="width: 45px; height: 45px;">
|
||||
{{ substr($lawan->nama_lengkap, 0, 1) }}
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="mb-0 fw-bold text-dark">{{ $lawan->nama_lengkap }}</h6>
|
||||
<small class="text-success"><i class="fas fa-store me-1"></i>{{ $lawan->nama_usaha }}</small>
|
||||
{{-- Inisial Nama Lawan --}}
|
||||
<div class="rounded-circle d-flex align-items-center justify-content-center fw-bold text-white me-3"
|
||||
style="width: 40px; height: 40px; background-color: #81c408; font-size: 1.1rem;">
|
||||
{{ substr($lawan->nama_lengkap, 0, 1) }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6 class="mb-0 fw-bold" style="color: #333;">{{ $lawan->nama_lengkap }}</h6>
|
||||
<small class="text-muted" style="font-size: 0.8rem;">
|
||||
<i class="fas fa-store me-1 text-success"></i> {{ $lawan->nama_usaha ?? 'Online' }}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Chat Box --}}
|
||||
<div class="chat-box" id="chatBox">
|
||||
{{-- Isi Pesan (Chat Box) --}}
|
||||
<div class="chat-content" id="chatBox">
|
||||
@php
|
||||
$currentUser = Auth::guard('petani')->check() ? Auth::guard('petani')->user() : Auth::guard('pembeli')->user();
|
||||
$currentUserType = get_class($currentUser);
|
||||
@endphp
|
||||
|
||||
@forelse ($chats as $chat)
|
||||
@php
|
||||
$isMe =
|
||||
$chat->pengirim_id == Auth::guard('pembeli')->id() &&
|
||||
$chat->pengirim_type == 'App\Models\Pembeli';
|
||||
$isMe = ($chat->pengirim_id == $currentUser->id) && ($chat->pengirim_type == $currentUserType);
|
||||
@endphp
|
||||
|
||||
<div class="d-flex {{ $isMe ? 'justify-content-end' : 'justify-content-start' }} mb-3">
|
||||
<div class="message-bubble shadow-sm {{ $isMe ? 'message-me' : 'message-other' }}">
|
||||
<div>{{ $chat->isi_pesan }}</div>
|
||||
<div class="text-end mt-1" style="font-size: 0.65rem; opacity: 0.8;">
|
||||
{{ $chat->created_at->format('H:i') }}
|
||||
@if ($isMe)
|
||||
<i class="fas fa-check-double ms-1"></i>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
{{-- BUBBLE CHAT --}}
|
||||
<div class="chat-bubble {{ $isMe ? 'bubble-me' : 'bubble-other' }}">
|
||||
{{ $chat->isi_pesan }}
|
||||
<span class="chat-time">
|
||||
{{ $chat->created_at->format('H:i') }}
|
||||
@if ($isMe)
|
||||
<i class="fas fa-check ms-1" style="font-size: 0.6rem;"></i>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@empty
|
||||
<div class="text-center py-5 mt-5">
|
||||
<p class="text-muted bg-white d-inline-block px-3 py-1 rounded-pill border">Mulai percakapan
|
||||
dengan {{ $lawan->nama_lengkap }}</p>
|
||||
<div class="text-center mt-5 opacity-50">
|
||||
<i class="far fa-comments fa-3x mb-3 text-secondary"></i>
|
||||
<p class="small text-muted">Belum ada percakapan.<br>Sapa
|
||||
<strong>{{ $lawan->nama_lengkap }}</strong> sekarang!</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
|
||||
{{-- Footer Chat --}}
|
||||
{{-- Input Footer --}}
|
||||
<div class="chat-footer">
|
||||
<form action="{{ route('pesan.kirim') }}" method="POST" class="d-flex gap-2">
|
||||
<form action="{{ route('pesan.kirim') }}" method="POST" class="d-flex gap-2 align-items-center">
|
||||
@csrf
|
||||
<input type="hidden" name="penerima_id" value="{{ $lawan->id }}">
|
||||
<input type="hidden" name="penerima_type" value="{{ get_class($lawan) }}">
|
||||
|
||||
<input type="text" name="isi_pesan" class="form-control rounded-pill border-success"
|
||||
placeholder="Ketik pesan..." required autocomplete="off">
|
||||
<input type="text" name="isi_pesan" class="form-control bg-light border-0 rounded-pill px-4 py-2"
|
||||
placeholder="Tulis pesan Anda..." required autocomplete="off">
|
||||
|
||||
<button type="submit"
|
||||
class="btn btn-success rounded-circle d-flex align-items-center justify-content-center"
|
||||
class="btn btn-send rounded-circle d-flex align-items-center justify-content-center shadow-sm"
|
||||
style="width: 45px; height: 45px;">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -107,15 +250,13 @@ class="btn btn-success rounded-circle d-flex align-items-center justify-content-
|
|||
|
||||
@section('js')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$(document).ready(function () {
|
||||
// Auto scroll ke bawah
|
||||
const chatBox = document.getElementById("chatBox");
|
||||
if (chatBox) {
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
}
|
||||
|
||||
// Fokus ke input
|
||||
$('input[name="isi_pesan"]').focus();
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
@ -4,95 +4,109 @@
|
|||
|
||||
@section('content')
|
||||
<div class="container py-5 mt-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h2 class="fw-bold text-dark">Riwayat Pesanan</h2>
|
||||
<a href="{{ route('shop') }}" class="btn btn-outline-primary btn-sm rounded-pill">
|
||||
<i class="fas fa-plus me-1"></i> Pesan Lagi
|
||||
{{-- Header Section --}}
|
||||
<div class="d-flex justify-content-between align-items-center mb-5">
|
||||
<div>
|
||||
<h2 class="fw-bold text-dark mb-0">Riwayat Pesanan</h2>
|
||||
<p class="text-muted small mb-0">Pantau status belanjaan Anda di sini</p>
|
||||
</div>
|
||||
<a href="{{ route('shop') }}" class="btn btn-primary rounded-pill px-4 shadow-sm">
|
||||
<i class="fas fa-shopping-bag me-2"></i>Belanja Lagi
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success alert-dismissible fade show shadow-sm border-0" role="alert">
|
||||
<i class="fa fa-check-circle me-2"></i> {{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($transaksis->isEmpty())
|
||||
<div class="text-center py-5 bg-light rounded-3">
|
||||
<i class="fas fa-receipt fa-4x text-muted mb-3 opacity-25"></i>
|
||||
<h5 class="text-muted">Belum ada riwayat pesanan.</h5>
|
||||
<a href="{{ route('shop') }}" class="btn btn-primary rounded-pill mt-3 px-4">Mulai Belanja</a>
|
||||
{{-- Empty State --}}
|
||||
<div class="text-center py-5">
|
||||
<div class="bg-light rounded-circle d-inline-flex align-items-center justify-content-center mb-4"
|
||||
style="width: 100px; height: 100px;">
|
||||
<i class="fas fa-receipt fa-3x text-secondary opacity-50"></i>
|
||||
</div>
|
||||
<h5 class="fw-bold text-dark">Belum ada pesanan</h5>
|
||||
<p class="text-muted mb-4">Yuk, mulai isi keranjang belanja Anda dengan produk segar!</p>
|
||||
<a href="{{ route('shop') }}" class="btn btn-outline-primary rounded-pill px-4">Mulai Belanja</a>
|
||||
</div>
|
||||
@else
|
||||
<div class="row">
|
||||
{{-- List Transaksi --}}
|
||||
<div class="row g-4">
|
||||
@foreach ($transaksis as $trx)
|
||||
<div class="col-12 mb-3">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm rounded-4 overflow-hidden">
|
||||
{{-- Invoice & Status --}}
|
||||
<div
|
||||
class="card-header bg-white border-bottom border-light p-4 d-flex flex-wrap justify-content-between align-items-center">
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="bg-light p-2 rounded text-center" style="width: 50px;">
|
||||
<i class="fas fa-file-invoice text-primary fs-4"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="fw-bold mb-0 text-dark">#{{ $trx->kode_invoice }}</h6>
|
||||
<small
|
||||
class="text-muted">{{ \Carbon\Carbon::parse($trx->tanggal_transaksi)->format('d M Y • H:i') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$statusClass = match ($trx->status) {
|
||||
'menunggu_konfirmasi', 'menunggu konfirmasi' => 'bg-warning text-dark bg-opacity-25 border border-warning',
|
||||
'diproses' => 'bg-info text-dark bg-opacity-25 border border-info',
|
||||
'dikirim' => 'bg-primary bg-opacity-10 border border-primary',
|
||||
'selesai' => 'bg-success bg-opacity-10 border border-success',
|
||||
'batal' => 'bg-danger bg-opacity-10 border border-danger',
|
||||
default => 'bg-secondary text-secondary bg-opacity-10'
|
||||
};
|
||||
@endphp
|
||||
<span class="badge {{ $statusClass }} px-3 py-2 rounded-pill mt-2 mt-sm-0">
|
||||
{{ ucwords(str_replace('_', ' ', $trx->status)) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="card-body p-4">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-md-8">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="bg-light p-2 rounded me-3 text-center" style="width: 50px;">
|
||||
<i class="fas fa-file-invoice text-primary fs-4"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="mb-0 fw-bold">Order #{{ $trx->kode_invoice }}</h6>
|
||||
<small
|
||||
class="text-muted">{{ \Carbon\Carbon::parse($trx->tanggal_transaksi)->format('d F Y') }}</small>
|
||||
</div>
|
||||
<div class="ms-3">
|
||||
@if ($trx->status == 'menunggu_konfirmasi')
|
||||
<span
|
||||
class="badge bg-warning text-dark bg-opacity-25 border border-warning">Menunggu</span>
|
||||
@elseif($trx->status == 'diproses')
|
||||
<span
|
||||
class="badge bg-info text-dark bg-opacity-25 border border-info">Diproses</span>
|
||||
@elseif($trx->status == 'dikirim')
|
||||
<span
|
||||
class="badge bg-primary text-primary bg-opacity-10 border border-primary">Dikirim</span>
|
||||
@elseif($trx->status == 'selesai')
|
||||
<span
|
||||
class="badge bg-success text-success bg-opacity-10 border border-success">Selesai</span>
|
||||
@else
|
||||
<span
|
||||
class="badge bg-danger text-danger bg-opacity-10 border border-danger">Batal</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@php $firstItem = $trx->details->first(); @endphp
|
||||
<div class="d-flex align-items-center bg-light rounded p-2 mt-2">
|
||||
<img src="{{ $firstItem->produk->foto_produk ? asset('storage/' . $firstItem->produk->foto_produk) : asset('template/frontend/img/fruite-item-5.jpg') }}"
|
||||
width="40" height="40" class="rounded object-fit-cover me-3">
|
||||
<div class="text-truncate">
|
||||
<span class="fw-bold text-dark">{{ $firstItem->produk->nama_produk }}</span>
|
||||
@if ($trx->details->count() > 1)
|
||||
<span class="text-muted small ms-1">+ {{ $trx->details->count() - 1 }}
|
||||
produk lainnya</span>
|
||||
@else
|
||||
<span class="text-muted small ms-1">({{ $firstItem->jumlah }} kg)</span>
|
||||
@endif
|
||||
{{-- Preview Produk --}}
|
||||
<div class="col-md-7 mb-3 mb-md-0">
|
||||
@php $firstItem = $trx->detailTransaksis->first(); @endphp
|
||||
@if($firstItem)
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ $firstItem->produk->foto_produk ? asset('storage/' . $firstItem->produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=200&auto=format&fit=crop' }}"
|
||||
class="rounded-3 object-fit-cover me-3 shadow-sm" width="60" height="60"
|
||||
alt="Produk">
|
||||
|
||||
<div>
|
||||
<h6 class="fw-bold text-dark mb-1">{{ $firstItem->produk->nama_produk }}</h6>
|
||||
<p class="text-muted small mb-0">
|
||||
{{ $firstItem->jumlah }} kg x Rp
|
||||
{{ number_format($firstItem->harga_satuan, 0, ',', '.') }}
|
||||
@if ($trx->detailTransaksis->count() > 1)
|
||||
<span class="text-primary fw-bold ms-1">+
|
||||
{{ $trx->detailTransaksis->count() - 1 }} produk lainnya</span>
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 text-md-end mt-3 mt-md-0">
|
||||
<p class="text-muted mb-1 small">Total Belanja</p>
|
||||
<h5 class="fw-bold text-primary mb-3">Rp
|
||||
{{ number_format($trx->total_harga, 0, ',', '.') }}</h5>
|
||||
{{-- Total & Button --}}
|
||||
<div class="col-md-5 text-md-end border-start-md ps-md-4">
|
||||
<small class="text-muted d-block mb-1">Total Tagihan</small>
|
||||
<h5 class="fw-bold text-dark mb-3">Rp {{ number_format($trx->total_harga, 0, ',', '.') }}
|
||||
</h5>
|
||||
|
||||
<div class="d-flex justify-content-md-end gap-2">
|
||||
<button class="btn btn-outline-secondary btn-sm rounded-pill px-3"
|
||||
data-bs-toggle="modal" data-bs-target="#detailModal{{ $trx->id }}">
|
||||
Detail
|
||||
<button class="btn btn-light btn-sm rounded-pill px-3 border" data-bs-toggle="modal"
|
||||
data-bs-target="#detailModal{{ $trx->id }}">
|
||||
Lihat Detail
|
||||
</button>
|
||||
|
||||
@if ($trx->status == 'dikirim')
|
||||
<form action="{{ route('pesanan.selesai', $trx->id) }}" method="POST"
|
||||
onsubmit="return confirm('Konfirmasi terima barang?')">
|
||||
onsubmit="return confirm('Apakah Anda yakin barang sudah diterima dengan baik?')">
|
||||
@csrf
|
||||
<button type="submit" class="btn btn-success btn-sm rounded-pill px-3">
|
||||
Diterima
|
||||
<button type="submit" class="btn btn-success btn-sm rounded-pill px-3 shadow-sm">
|
||||
<i class="fas fa-check me-1"></i> Pesanan Diterima
|
||||
</button>
|
||||
</form>
|
||||
@endif
|
||||
|
|
@ -105,41 +119,143 @@ class="badge bg-danger text-danger bg-opacity-10 border border-danger">Batal</sp
|
|||
|
||||
{{-- MODAL DETAIL --}}
|
||||
<div class="modal fade" id="detailModal{{ $trx->id }}" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content border-0">
|
||||
<div class="modal-header bg-light">
|
||||
<h5 class="modal-title fw-bold">Detail #{{ $trx->kode_invoice }}</h5>
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content border-0 rounded-4 shadow-lg overflow-hidden">
|
||||
|
||||
{{-- Header: Putih Bersih --}}
|
||||
<div class="modal-header border-bottom-0 pt-4 px-4 pb-0">
|
||||
<div>
|
||||
<h5 class="modal-title fw-bold text-dark" style="font-size: 1.25rem;">Detail Pesanan</h5>
|
||||
<p class="text-muted small mb-0">Invoice: <span
|
||||
class="font-monospace">#{{ $trx->kode_invoice }}</span></p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<label class="fw-bold small text-muted">Alamat Pengiriman</label>
|
||||
<p class="mb-0 bg-light p-2 rounded">{{ $trx->alamat_pengiriman }}</p>
|
||||
|
||||
<div class="modal-body p-4">
|
||||
|
||||
{{-- 1. STATUS BANNER (Meniru Style Referensi) --}}
|
||||
@php
|
||||
$statusConfig = match ($trx->status) {
|
||||
'menunggu_konfirmasi', 'menunggu konfirmasi' => ['bg' => '#fff3cd', 'text' => '#856404', 'icon' => 'fa-clock', 'title' => 'Menunggu Konfirmasi', 'desc' => 'Menunggu penjual menerima pesanan Anda.'],
|
||||
'diproses' => ['bg' => '#cff4fc', 'text' => '#055160', 'icon' => 'fa-box-open', 'title' => 'Sedang Diproses', 'desc' => 'Penjual sedang mengemas barang Anda.'],
|
||||
'dikirim' => ['bg' => '#cfe2ff', 'text' => '#084298', 'icon' => 'fa-truck', 'title' => 'Dalam Pengiriman', 'desc' => 'Kurir sedang menuju ke lokasi Anda.'],
|
||||
'selesai' => ['bg' => '#d1e7dd', 'text' => '#0f5132', 'icon' => 'fa-check-circle', 'title' => 'Transaksi Selesai', 'desc' => 'Terima kasih telah berbelanja produk lokal!'],
|
||||
'batal' => ['bg' => '#f8d7da', 'text' => '#842029', 'icon' => 'fa-times-circle', 'title' => 'Dibatalkan', 'desc' => 'Transaksi ini telah dibatalkan.'],
|
||||
default => ['bg' => '#e2e3e5', 'text' => '#41464b', 'icon' => 'fa-question-circle', 'title' => 'Status Tidak Dikenal', 'desc' => '']
|
||||
};
|
||||
@endphp
|
||||
|
||||
<div class="d-flex align-items-center p-3 rounded-3 mb-4"
|
||||
style="background-color: {{ $statusConfig['bg'] }}; color: {{ $statusConfig['text'] }};">
|
||||
<i class="fas {{ $statusConfig['icon'] }} fs-3 me-3"></i>
|
||||
<div>
|
||||
<h6 class="fw-bold mb-0">{{ $statusConfig['title'] }}</h6>
|
||||
<small style="opacity: 0.9;">{{ $statusConfig['desc'] }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<h6 class="fw-bold mt-4 mb-3">Daftar Item</h6>
|
||||
<ul class="list-group list-group-flush">
|
||||
@foreach ($trx->details as $d)
|
||||
<li
|
||||
class="list-group-item d-flex justify-content-between align-items-center px-0">
|
||||
|
||||
<div class="row g-4 mb-4">
|
||||
{{-- 2. INFO PENJUAL (Kiri) --}}
|
||||
<div class="col-md-6">
|
||||
<label class="small text-secondary fw-bold text-uppercase mb-2"
|
||||
style="font-size: 0.75rem; letter-spacing: 0.5px;">Dijual Oleh</label>
|
||||
<div class="bg-light p-3 rounded-3 d-flex align-items-center justify-content-between">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ $d->produk->foto_produk ? asset('storage/' . $d->produk->foto_produk) : asset('template/frontend/img/fruite-item-5.jpg') }}"
|
||||
width="40" height="40" class="rounded me-2 object-fit-cover">
|
||||
<div class="bg-white rounded-circle shadow-sm d-flex align-items-center justify-content-center me-3"
|
||||
style="width: 45px; height: 45px;">
|
||||
<i class="fas fa-store text-primary"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="fw-bold">{{ $d->produk->nama_produk }}</div>
|
||||
<small class="text-muted">{{ $d->jumlah }} kg x
|
||||
<h6 class="fw-bold text-dark mb-0" style="font-size: 0.95rem;">
|
||||
{{ $trx->petani->nama_lengkap ?? 'Petani' }}</h6>
|
||||
<small class="text-muted"
|
||||
style="font-size: 0.85rem;">{{ $trx->petani->nama_usaha ?? 'Tani Desa Seller' }}</small>
|
||||
</div>
|
||||
</div>
|
||||
@if($trx->petani)
|
||||
<a href="https://wa.me/{{ $trx->petani->no_hp }}" target="_blank"
|
||||
class="btn btn-success btn-sm rounded-circle d-flex align-items-center justify-content-center"
|
||||
style="width: 35px; height: 35px;" data-bs-toggle="tooltip"
|
||||
title="Chat WhatsApp">
|
||||
<i class="fab fa-whatsapp"></i>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 3. INFO PENGIRIMAN (Kanan) --}}
|
||||
<div class="col-md-6">
|
||||
<label class="small text-secondary fw-bold text-uppercase mb-2"
|
||||
style="font-size: 0.75rem; letter-spacing: 0.5px;">Info Pengiriman</label>
|
||||
<div class="bg-light p-3 rounded-3 h-100">
|
||||
<div class="d-flex mb-2">
|
||||
<i class="fas fa-map-marker-alt text-danger mt-1 me-2"></i>
|
||||
<div>
|
||||
<h6 class="fw-bold text-dark mb-0" style="font-size: 0.95rem;">Alamat Tujuan
|
||||
</h6>
|
||||
<small class="text-muted d-block text-truncate"
|
||||
style="max-width: 200px;">{{ $trx->alamat_pengiriman }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ms-4 ps-1 border-top pt-2 mt-2">
|
||||
<small class="text-muted">Metode Bayar: <span class="fw-bold text-dark">Cash on
|
||||
Delivery (COD)</span></small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 4. RINCIAN BARANG (Style Card List) --}}
|
||||
<label class="small text-secondary fw-bold text-uppercase mb-2"
|
||||
style="font-size: 0.75rem; letter-spacing: 0.5px;">Rincian Barang</label>
|
||||
<div class="border rounded-3 overflow-hidden mb-4">
|
||||
@foreach ($trx->detailTransaksis as $d)
|
||||
<div class="d-flex align-items-center justify-content-between p-3 bg-white border-bottom">
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ $d->produk->foto_produk ? asset('storage/' . $d->produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=200&auto=format&fit=crop' }}"
|
||||
class="rounded-3 object-fit-cover me-3"
|
||||
style="width: 60px; height: 60px; background-color: #f8f9fa;">
|
||||
<div>
|
||||
<h6 class="mb-1 fw-bold text-dark">{{ $d->produk->nama_produk }}</h6>
|
||||
<small class="text-muted d-block">{{ $d->jumlah }} kg x Rp
|
||||
{{ number_format($d->harga_satuan, 0, ',', '.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="fw-bold text-dark">{{ number_format($d->subtotal, 0, ',', '.') }}</span>
|
||||
</li>
|
||||
<div class="fw-bold text-dark">
|
||||
Rp {{ number_format($d->subtotal, 0, ',', '.') }}
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{-- 5. TOTAL BLOCK (Hijau Solid seperti referensi) --}}
|
||||
@php
|
||||
// Menggunakan warna background sesuai status agar konsisten, atau default hijau fresh
|
||||
$footerBg = ($trx->status == 'batal') ? '#dc3545' : (($trx->status == 'menunggu_konfirmasi') ? '#ffc107' : '#82c91e');
|
||||
$footerText = ($trx->status == 'menunggu_konfirmasi') ? '#000' : '#fff';
|
||||
@endphp
|
||||
<div class="p-3 rounded-3" style="background-color: {{ $footerBg }}; color: {{ $footerText }};">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<span style="opacity: 0.9;">Subtotal Produk</span>
|
||||
<span class="fw-bold">Rp {{ number_format($trx->total_harga, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span style="opacity: 0.9;">Biaya Pengiriman (COD)</span>
|
||||
<span class="fw-bold">Gratis</span>
|
||||
</div>
|
||||
<hr class="my-2" style="opacity: 0.3;">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<span class="fw-bold fs-5">Total Pembayaran</span>
|
||||
<span class="fw-bold fs-5">Rp {{ number_format($trx->total_harga, 0, ',', '.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer justify-content-between bg-light">
|
||||
<span class="text-muted small">Total Tagihan</span>
|
||||
<span class="fw-bold fs-5 text-primary">Rp
|
||||
{{ number_format($trx->total_harga, 0, ',', '.') }}</span>
|
||||
|
||||
<div class="modal-footer border-top-0 pt-0 pb-4 px-4">
|
||||
<button type="button" class="btn btn-light border rounded-pill px-4 w-100"
|
||||
data-bs-dismiss="modal">Tutup</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -149,3 +265,13 @@ class="fw-bold text-dark">{{ number_format($d->subtotal, 0, ',', '.') }}</span>
|
|||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('style')
|
||||
<style>
|
||||
@media (min-width: 768px) {
|
||||
.border-start-md {
|
||||
border-left: 1px solid #dee2e6 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
|
@ -3,118 +3,175 @@
|
|||
@section('title', 'Belanja Padi & Beras')
|
||||
|
||||
@section('content')
|
||||
<!-- Page Header -->
|
||||
<div class="container-fluid py-5 bg-light">
|
||||
<div class="container-fluid py-5 bg-light border-bottom mb-5">
|
||||
<div class="container text-center">
|
||||
<h1 class="display-5 fw-bold text-dark">Belanja Produk Kami</h1>
|
||||
<h1 class="display-5 fw-bold text-dark mb-3">Belanja Produk Kami</h1>
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb justify-content-center mb-0">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
||||
<li class="breadcrumb-item active">Shop</li>
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}" class="text-decoration-none">Home</a></li>
|
||||
<li class="breadcrumb-item active text-muted">Shop</li>
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Shop Section -->
|
||||
<div class="container py-5">
|
||||
<div class="container pb-5">
|
||||
<div class="row g-4">
|
||||
<!-- Sidebar -->
|
||||
|
||||
<div class="col-lg-3">
|
||||
<!-- Search -->
|
||||
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body">
|
||||
<h5 class="fw-bold mb-3">Cari Produk</h5>
|
||||
<div class="card-body p-4">
|
||||
<h6 class="fw-bold mb-3 text-uppercase small text-muted">Cari Produk</h6>
|
||||
<form action="{{ route('shop') }}" method="GET">
|
||||
@if(request('kategori')) <input type="hidden" name="kategori" value="{{ request('kategori') }}">
|
||||
@endif
|
||||
@if(request('sort')) <input type="hidden" name="sort" value="{{ request('sort') }}"> @endif
|
||||
|
||||
<div class="input-group">
|
||||
<input type="search" name="search" class="form-control" placeholder="Cari..."
|
||||
value="{{ request('search') }}">
|
||||
<button class="btn btn-success" type="submit">
|
||||
<i class="fa fa-search"></i>
|
||||
<input type="search" name="search" class="form-control bg-light border-0"
|
||||
placeholder="Nama produk..." value="{{ request('search') }}">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Info -->
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<h5 class="fw-bold mb-3">Informasi</h5>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-check-circle text-success me-2"></i>
|
||||
<small>Total {{ $produks->total() }} Produk</small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<i class="fas fa-leaf text-success me-2"></i>
|
||||
<small>100% Organik</small>
|
||||
</div>
|
||||
<div class="d-flex align-items-center">
|
||||
<i class="fas fa-truck text-success me-2"></i>
|
||||
<small>Gratis Ongkir Min. 50 Kg</small>
|
||||
<div class="card border-0 shadow-sm mb-4">
|
||||
<div class="card-body p-4">
|
||||
<h6 class="fw-bold mb-3 text-uppercase small text-muted">Kategori</h6>
|
||||
<div class="d-flex flex-column gap-2">
|
||||
|
||||
@php
|
||||
$kategoriList = \App\Models\Kategori::all();
|
||||
$currentKat = request('kategori');
|
||||
@endphp
|
||||
|
||||
<a href="{{ route('shop', array_merge(request()->query(), ['kategori' => null])) }}"
|
||||
class="d-flex justify-content-between align-items-center text-decoration-none {{ !$currentKat ? 'fw-bold text-primary' : 'text-secondary' }}">
|
||||
<span>Semua Kategori</span>
|
||||
</a>
|
||||
|
||||
{{-- Looping Data Database --}}
|
||||
@foreach($kategoriList as $kat)
|
||||
<a href="{{ route('shop', array_merge(request()->query(), ['kategori' => $kat->slug])) }}"
|
||||
class="d-flex justify-content-between align-items-center text-decoration-none {{ $currentKat == $kat->slug ? 'fw-bold text-primary' : 'text-secondary' }}">
|
||||
|
||||
<span>{{ $kat->nama_kategori }}</span>
|
||||
|
||||
@if($currentKat == $kat->slug)
|
||||
<i class="fas fa-check small"></i>
|
||||
@endif
|
||||
</a>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card border-0 shadow-sm bg-primary text-white">
|
||||
<div class="card-body p-4">
|
||||
<h5 class="fw-bold mb-2"><i class="fas fa-leaf me-2"></i>Produk Segar</h5>
|
||||
<p class="small mb-0 opacity-75">Semua produk kami diambil langsung dari petani lokal terpercaya.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Product Grid -->
|
||||
<div class="col-lg-9">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-4 bg-white p-3 rounded shadow-sm border">
|
||||
<div class="d-none d-md-block text-muted small">
|
||||
Menampilkan <span
|
||||
class="fw-bold text-dark">{{ $produks->firstItem() ?? 0 }}-{{ $produks->lastItem() ?? 0 }}</span>
|
||||
dari <span class="fw-bold text-dark">{{ $produks->total() }}</span> produk
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center">
|
||||
<label class="small text-muted me-2 text-nowrap">Urutkan:</label>
|
||||
<form id="sortForm" action="{{ route('shop') }}" method="GET">
|
||||
{{-- Pertahankan query lain saat sorting --}}
|
||||
@foreach(request()->except('sort') as $key => $value)
|
||||
<input type="hidden" name="{{ $key }}" value="{{ $value }}">
|
||||
@endforeach
|
||||
|
||||
<select name="sort" class="form-select form-select-sm border-0 bg-light fw-bold text-dark"
|
||||
onchange="document.getElementById('sortForm').submit()"
|
||||
style="width: 160px; cursor: pointer;">
|
||||
<option value="terbaru" {{ request('sort') == 'terbaru' ? 'selected' : '' }}>Paling Baru
|
||||
</option>
|
||||
<option value="termurah" {{ request('sort') == 'termurah' ? 'selected' : '' }}>Harga Terendah
|
||||
</option>
|
||||
<option value="termahal" {{ request('sort') == 'termahal' ? 'selected' : '' }}>Harga Tertinggi
|
||||
</option>
|
||||
<option value="terlaris" {{ request('sort') == 'terlaris' ? 'selected' : '' }}>Paling Laris
|
||||
</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-4">
|
||||
@forelse($produks as $produk)
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card border-0 shadow-sm h-100 product-card">
|
||||
<!-- Stock Badge -->
|
||||
<div class="position-absolute top-0 end-0 m-2 z-1">
|
||||
<span class="badge bg-warning text-dark">
|
||||
Stok: {{ $produk->stok }} Kg
|
||||
</span>
|
||||
</div>
|
||||
<a href="{{ route('produk.detail', $produk->id) }}" class="text-decoration-none">
|
||||
<div class="card border-0 shadow-sm h-100 product-card">
|
||||
<!-- Stock Badge -->
|
||||
<div class="position-absolute top-0 end-0 m-2 z-1">
|
||||
<span class="badge bg-warning text-dark">
|
||||
Stok: {{ $produk->stok }} Kg
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Image -->
|
||||
<div class="overflow-hidden" style="height: 200px;">
|
||||
<img src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=800&auto=format&fit=crop' }}"
|
||||
class="card-img-top w-100 h-100" alt="{{ $produk->nama_produk }}"
|
||||
style="object-fit: cover;">
|
||||
</div>
|
||||
<!-- Image -->
|
||||
<div class="overflow-hidden" style="height: 200px;">
|
||||
<img src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=800&auto=format&fit=crop' }}"
|
||||
class="card-img-top w-100 h-100" alt="{{ $produk->nama_produk }}"
|
||||
style="object-fit: cover;">
|
||||
</div>
|
||||
|
||||
<div class="card-body p-3">
|
||||
<span class="badge bg-success mb-2">{{ $produk->kategori ?? 'Umum' }}</span>
|
||||
<h6 class="fw-bold mb-2">{{ $produk->nama_produk }}</h6>
|
||||
<p class="text-muted small mb-3">{{ Str::limit($produk->deskripsi, 60) }}</p>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center pt-2 border-top">
|
||||
<div class="card-body d-flex justify-content-between flex-column p-3">
|
||||
<div>
|
||||
<small class="text-muted">Harga/Kg</small>
|
||||
<h6 class="fw-bold text-success mb-0">
|
||||
Rp {{ number_format($produk->harga, 0, ',', '.') }}
|
||||
</h6>
|
||||
<span class="badge bg-success mb-2">{{ $produk->kategori->nama_kategori ?? 'Umum' }}</span>
|
||||
<h6 class="fw-bold mb-2">{{ $produk->nama_produk }}</h6>
|
||||
<p class="text-muted small mb-3">{{ Str::limit($produk->deskripsi, 60) }}</p>
|
||||
</div>
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center pt-2 border-top">
|
||||
<div>
|
||||
<small class="text-muted">Harga/Kg</small>
|
||||
<h6 class="fw-bold text-success mb-0">
|
||||
Rp {{ number_format($produk->harga, 0, ',', '.') }}
|
||||
</h6>
|
||||
</div>
|
||||
<a href="{{ route('produk.detail', $produk->id) }}"
|
||||
class="btn btn-success btn-sm rounded-pill">
|
||||
<i class="fa fa-eye"></i> Detail
|
||||
</a>
|
||||
</div>
|
||||
<a href="{{ route('produk.detail', $produk->id) }}"
|
||||
class="btn btn-success btn-sm rounded-pill">
|
||||
<i class="fa fa-eye"></i> Detail
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
@empty
|
||||
<div class="col-12">
|
||||
<div class="text-center py-5">
|
||||
<i class="fas fa-search fa-4x text-muted mb-3"></i>
|
||||
<h4 class="text-muted">Produk Tidak Ditemukan</h4>
|
||||
<p class="text-muted">Coba kata kunci lain atau hapus filter pencarian.</p>
|
||||
<a href="{{ route('shop') }}" class="btn btn-outline-success rounded-pill mt-2">
|
||||
<i class="fas fa-sync-alt me-2"></i> Reset Pencarian
|
||||
<div class="text-center py-5 bg-white rounded-3 shadow-sm border border-dashed">
|
||||
<i class="fas fa-search fa-3x text-muted opacity-50 mb-3"></i>
|
||||
<h5 class="fw-bold text-dark">Produk Tidak Ditemukan</h5>
|
||||
<p class="text-muted mb-4">Coba ubah kata kunci pencarian atau reset filter Anda.</p>
|
||||
<a href="{{ route('shop') }}" class="btn btn-outline-primary rounded-pill px-4">
|
||||
<i class="fas fa-sync-alt me-2"></i> Reset Filter
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
<!-- Pagination -->
|
||||
@if ($produks->hasPages())
|
||||
<div class="d-flex justify-content-center mt-5">
|
||||
{{ $produks->links() }}
|
||||
{{ $produks->withQueryString()->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
|
@ -122,13 +179,23 @@ class="btn btn-success btn-sm rounded-pill">
|
|||
</div>
|
||||
|
||||
<style>
|
||||
/* Hover Effect */
|
||||
.product-card {
|
||||
transition: transform 0.3s, box-shadow 0.3s;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.product-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15) !important;
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
/* Zoom Image on Hover */
|
||||
.product-card:hover img {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.transition-transform {
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
</style>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
@ -4,20 +4,85 @@
|
|||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>@yield('title') - TaniDesa</title>
|
||||
<title>@yield('title') - GriyaPadi.id</title>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="shortcut icon" href="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/compiled/svg/favicon.svg"
|
||||
type="image/x-icon">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/compiled/css/app.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/compiled/css/app-dark.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/compiled/css/iconly.css">
|
||||
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
|
||||
@yield('css')
|
||||
|
||||
<style>
|
||||
/* --- CUSTOM GREEN THEME --- */
|
||||
:root {
|
||||
--primary-green: #81c408;
|
||||
--primary-hover: #6da705;
|
||||
}
|
||||
|
||||
.logo a {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 1.7rem;
|
||||
}
|
||||
|
||||
.bg-primary-green {
|
||||
background-color: var(--primary-green) !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.text-primary-green {
|
||||
background-color: var(--primary-green) !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.sidebar-wrapper .sidebar-menu .sidebar-item.active .sidebar-link {
|
||||
background-color: var(--primary-green) !important;
|
||||
box-shadow: 0 5px 10px rgba(129, 196, 8, 0.3);
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--primary-green);
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--primary-hover);
|
||||
}
|
||||
|
||||
.stats-icon {
|
||||
display: flex !important;
|
||||
justify-content: center !important;
|
||||
align-items: center !important;
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.stats-icon i {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
/* Loader/Spinner Color if exists */
|
||||
.spinner-border.text-primary {
|
||||
color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
/* Pagination active color */
|
||||
.page-item.active .page-link {
|
||||
background-color: var(--primary-green) !important;
|
||||
border-color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
.chat-card {
|
||||
height: 80vh;
|
||||
overflow: hidden;
|
||||
|
|
@ -48,7 +113,7 @@
|
|||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
/* Item List di Sidebar */
|
||||
/* Item List */
|
||||
.chat-item {
|
||||
transition: all 0.3s;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
|
|
@ -59,15 +124,58 @@
|
|||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
/* Active Chat Item */
|
||||
.chat-item.active {
|
||||
background-color: #2d46a18f;
|
||||
color: white !important;
|
||||
background-color: rgba(129, 196, 8, 0.2);
|
||||
border-left: 4px solid var(--primary-green);
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.chat-item.active p,
|
||||
.chat-item.active small,
|
||||
.chat-item.active h6 {
|
||||
color: white !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-green) !important;
|
||||
border-color: var(--primary-green) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus,
|
||||
.btn-primary:active {
|
||||
background-color: var(--primary-hover) !important;
|
||||
border-color: var(--primary-hover) !important;
|
||||
box-shadow: 0 0 0 0.25rem rgba(129, 196, 8, 0.5) !important;
|
||||
}
|
||||
|
||||
/* Tombol Outline */
|
||||
.btn-outline-primary {
|
||||
color: var(--primary-green) !important;
|
||||
border-color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
.btn-outline-primary:hover {
|
||||
background-color: var(--primary-green) !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Pagination */
|
||||
.page-item.active .page-link {
|
||||
background-color: var(--primary-green) !important;
|
||||
border-color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
.page-link {
|
||||
color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
/* Form Check / Radio Button / Switch saat aktif */
|
||||
.form-check-input:checked {
|
||||
background-color: var(--primary-green) !important;
|
||||
border-color: var(--primary-green) !important;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
|
|
@ -93,10 +201,10 @@
|
|||
<div class="sidebar-wrapper active">
|
||||
<div class="sidebar-header position-relative">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="logo">
|
||||
<a href="#">TaniDesa</a>
|
||||
<div class="logo me-md-2">
|
||||
<a href="#" style="color: #81c408;">GriyaPadi.id</a>
|
||||
</div>
|
||||
<div class="theme-toggle d-flex gap-2 align-items-center mt-2">
|
||||
<div class="theme-toggle d-flex gap-1 align-items-center mt-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true" role="img" class="iconify iconify--system-uicons" width="20"
|
||||
height="20" preserveAspectRatio="xMidYMid meet" viewBox="0 0 21 21">
|
||||
|
|
@ -118,16 +226,15 @@
|
|||
<label class="form-check-label"></label>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true" role="img" class="iconify iconify--mdi" width="20"
|
||||
height="20" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24">
|
||||
aria-hidden="true" role="img" class="iconify iconify--mdi" width="20" height="20"
|
||||
preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24">
|
||||
<path fill="currentColor"
|
||||
d="m17.75 4.09l-2.53 1.94l.91 3.06l-2.63-1.81l-2.63 1.81l.91-3.06l-2.53-1.94L12.44 4l1.06-3l1.06 3l3.19.09m3.5 6.91l-1.64 1.25l.59 1.98l-1.7-1.17l-1.7 1.17l.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95l2.06.05m-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85c-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14c.4-.4.82-.76 1.27-1.08c.75-.53 1.93.36 1.85 1.19c-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82c-2.81 3.14-2.7 7.96.31 10.98c3.02 3.01 7.84 3.12 10.98.31Z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-toggler x">
|
||||
<a href="#" class="sidebar-hide d-xl-none d-block"><i
|
||||
class="bi bi-x bi-middle"></i></a>
|
||||
<a href="#" class="sidebar-hide d-xl-none d-block"><i class="bi bi-x bi-middle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -138,21 +245,35 @@ class="bi bi-x bi-middle"></i></a>
|
|||
|
||||
{{-- Menu Dashboard Admin --}}
|
||||
@if (Auth::guard('admin')->check())
|
||||
|
||||
{{-- DASHBOARD --}}
|
||||
<li class="sidebar-item {{ request()->is('admin/dashboard') ? 'active' : '' }}">
|
||||
<a href="{{ route('admin.dashboard') }}" class='sidebar-link'>
|
||||
<i class="bi bi-grid-fill"></i> <span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{-- MASTER KATEGORI --}}
|
||||
<li class="sidebar-item {{ request()->is('admin/kategori*') ? 'active' : '' }}">
|
||||
<a href="{{ route('admin.kategori.index') }}" class='sidebar-link'>
|
||||
<i class="bi bi-tags-fill"></i> <span>Master Kategori</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{-- VERIFIKASI PETANI --}}
|
||||
<li class="sidebar-item {{ request()->is('admin/verifikasi*') ? 'active' : '' }}">
|
||||
<a href="{{ route('admin.verifikasi.index') }}" class='sidebar-link'>
|
||||
<i class="bi bi-person-badge-fill"></i> <span>Verifikasi Petani</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
{{-- MONITORING --}}
|
||||
<li class="sidebar-item {{ request()->is('admin/monitoring*') ? 'active' : '' }}">
|
||||
<a href="{{ route('admin.monitoring') }}" class='sidebar-link'>
|
||||
<i class="bi bi-eye-fill"></i> <span>Monitoring</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@endif
|
||||
|
||||
{{-- Menu Dashboard Petani --}}
|
||||
|
|
@ -214,7 +335,7 @@ class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
|
|||
</header>
|
||||
|
||||
<div class="page-heading">
|
||||
<h3>@yield('page-title')</h3>
|
||||
<div>@yield('page-title')</div>
|
||||
</div>
|
||||
|
||||
<div class="page-content">
|
||||
|
|
@ -224,7 +345,7 @@ class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
|
|||
<footer>
|
||||
<div class="footer clearfix mb-0 text-muted">
|
||||
<div class="float-start">
|
||||
<p>2025 © TaniDesa</p>
|
||||
<p>2025 © GriyaPadi.id</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
@ -234,10 +355,10 @@ class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
|
|||
<script src="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/static/js/components/dark.js"></script>
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/extensions/perfect-scrollbar/perfect-scrollbar.min.js">
|
||||
</script>
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/compiled/js/app.js"></script>
|
||||
|
||||
@yield('js')
|
||||
</body>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -3,13 +3,12 @@
|
|||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>@yield('title') - TaniDesa</title>
|
||||
<title>@yield('title') - GriyaPadi.id</title>
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;600&family=Raleway:wght@600;800&display=swap"
|
||||
rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css" />
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.4.1/font/bootstrap-icons.css" rel="stylesheet">
|
||||
|
|
@ -26,16 +25,33 @@
|
|||
:root {
|
||||
--primary-color: #81c408;
|
||||
--primary-hover: #6da705;
|
||||
--secondary-color: #ffc107;
|
||||
--light-bg: #f8f9fa;
|
||||
--secondary-color: #ffc107f6;
|
||||
--light-bg: #f5f7f9;
|
||||
--dark-text: #2c3e50;
|
||||
--muted-text: #6c757d;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-family: 'Inter', sans-serif;
|
||||
background-color: var(--light-bg);
|
||||
color: var(--dark-text);
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-weight: 700;
|
||||
color: var(--dark-text);
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
/* Utility Colors */
|
||||
.text-primary {
|
||||
color: var(--primary-color) !important;
|
||||
}
|
||||
|
|
@ -48,6 +64,14 @@
|
|||
border-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
/* BUTTON */
|
||||
.btn {
|
||||
font-weight: 500;
|
||||
border-radius: 6px;
|
||||
padding: 0.5rem 1.25rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--primary-color);
|
||||
|
|
@ -57,6 +81,7 @@
|
|||
.btn-primary:hover {
|
||||
background-color: var(--primary-hover);
|
||||
border-color: var(--primary-hover);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.btn-outline-primary {
|
||||
|
|
@ -69,10 +94,15 @@
|
|||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background-color: var(--secondary-color);
|
||||
border-color: var(--secondary-color);
|
||||
color: #333;
|
||||
/* NAVBAR */
|
||||
.navbar {
|
||||
box-shadow: 0 2px 15px rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.navbar-light .navbar-nav .nav-link {
|
||||
font-weight: 500;
|
||||
color: var(--dark-text);
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.navbar-light .navbar-nav .nav-link.active,
|
||||
|
|
@ -80,115 +110,66 @@
|
|||
color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
.rounded-pill {
|
||||
border-radius: 50rem !important;
|
||||
/* FORM INPUTS */
|
||||
.form-control {
|
||||
border-radius: 6px;
|
||||
border: 1px solid #dee2e6;
|
||||
padding: 0.6rem 1rem;
|
||||
}
|
||||
|
||||
.rounded-4 {
|
||||
border-radius: 1rem !important;
|
||||
.form-control:focus {
|
||||
box-shadow: 0 0 0 3px rgba(129, 196, 8, 0.15);
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
/* CARDS */
|
||||
.card {
|
||||
border: none;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.02);
|
||||
transition: 0.3s;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.footer-accent {
|
||||
border-bottom: 1px solid rgba(129, 196, 8, 0.5);
|
||||
}
|
||||
|
||||
/* Chat Section */
|
||||
/* CHAT SECTION */
|
||||
.chat-container {
|
||||
height: 80vh;
|
||||
background: #fff;
|
||||
border-radius: 15px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e9ecef;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.chat-sidebar {
|
||||
background-color: #f8f9fa;
|
||||
border-right: 1px solid #e9ecef;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chat-list-item {
|
||||
transition: all 0.2s;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.chat-list-item:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.chat-list-item.active {
|
||||
background-color: #e3f2fd;
|
||||
border-left: 4px solid #81c408;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
background: #fff;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
background-color: #fcfcfc;
|
||||
background-image: radial-gradient(#81c408 0.5px, transparent 0.5px);
|
||||
background-size: 20px 20px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* Bubble Chat */
|
||||
.message-bubble {
|
||||
max-width: 70%;
|
||||
padding: 10px 15px;
|
||||
border-radius: 15px;
|
||||
margin-bottom: 10px;
|
||||
position: relative;
|
||||
font-size: 0.95rem;
|
||||
max-width: 75%;
|
||||
padding: 10px 16px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.message-me {
|
||||
background-color: #81c408;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
border-bottom-right-radius: 2px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.message-other {
|
||||
background-color: #e9ecef;
|
||||
color: #333;
|
||||
background-color: #f1f3f5;
|
||||
color: var(--dark-text);
|
||||
border-bottom-left-radius: 2px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.chat-footer {
|
||||
padding: 15px;
|
||||
background: #fff;
|
||||
border-top: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
/* SCROLLBAR */
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
|
@ -201,6 +182,15 @@
|
|||
background: #ccc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #bbb;
|
||||
}
|
||||
|
||||
/* Footer Accent */
|
||||
.footer-accent {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
|
@ -208,25 +198,21 @@
|
|||
|
||||
<div id="spinner"
|
||||
class="show w-100 vh-100 bg-white position-fixed translate-middle top-50 start-50 d-flex align-items-center justify-content-center">
|
||||
<div class="spinner-grow text-primary" role="status"></div>
|
||||
<div class="spinner-border text-primary" role="status" style="width: 3rem; height: 3rem;"></div>
|
||||
</div>
|
||||
<div class="container-fluid fixed-top">
|
||||
<div class="container-fluid bg-primary d-none d-lg-block">
|
||||
|
||||
<div class="container-fluid fixed-top px-0">
|
||||
<div class="container-fluid bg-primary d-none d-lg-block py-3">
|
||||
<div class="container">
|
||||
<div class="topbar">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="top-info ps-2">
|
||||
<small class="me-3"><i class="fas fa-map-marker-alt me-2 text-secondary"></i> <a
|
||||
href="#" class="text-white">Desa Sukamaju, Indonesia</a></small>
|
||||
<small class="me-3"><i class="fas fa-envelope me-2 text-secondary"></i><a href="#"
|
||||
class="text-white">info@tanidesa.com</a></small>
|
||||
</div>
|
||||
<div class="top-link pe-2">
|
||||
<a href="#" class="text-white"><small class="text-white mx-2">Kebijakan
|
||||
Privasi</small>/</a>
|
||||
<a href="#" class="text-white"><small class="text-white mx-2">Syarat &
|
||||
Ketentuan</small></a>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between text-white" style="font-size: 0.85rem;">
|
||||
<div>
|
||||
<span class="me-3"><i class="fas fa-map-marker-alt me-2"></i> Desa Sukamaju, Indonesia</span>
|
||||
<span class="me-3"><i class="fas fa-envelope me-2"></i> info@tanidesa.com</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="#" class="text-white text-decoration-none me-2">Bantuan</a>
|
||||
<span class="text-white-50">|</span>
|
||||
<a href="#" class="text-white text-decoration-none ms-2">Ikuti Kami</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -234,67 +220,76 @@ class="text-white">info@tanidesa.com</a></small>
|
|||
|
||||
<div class="container-fluid bg-white shadow-sm">
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-light navbar-expand-xl">
|
||||
<a href="{{ url('/') }}" class="navbar-brand">
|
||||
<h1 class="text-primary display-6">TaniDesa</h1>
|
||||
<nav class="navbar navbar-light navbar-expand-xl py-3">
|
||||
<a href="{{ url('/') }}" class="navbar-brand d-flex align-items-center">
|
||||
<h1 class="text-primary m-0 fw-bold" style="font-size: 1.8rem; letter-spacing: -1px;">GriyaPadi.id
|
||||
</h1>
|
||||
</a>
|
||||
<button class="navbar-toggler py-2 px-3" type="button" data-bs-toggle="collapse"
|
||||
|
||||
<button class="navbar-toggler border-0" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarCollapse">
|
||||
<span class="fa fa-bars text-primary"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse bg-white" id="navbarCollapse">
|
||||
|
||||
<div class="collapse navbar-collapse" id="navbarCollapse">
|
||||
<div class="navbar-nav mx-auto">
|
||||
<a href="{{ url('/') }}"
|
||||
class="nav-item nav-link {{ request()->is('/') ? 'active' : '' }}">Home</a>
|
||||
class="nav-item nav-link mx-2 {{ request()->is('/') ? 'active' : '' }}">Home</a>
|
||||
<a href="{{ route('shop') }}"
|
||||
class="nav-item nav-link {{ request()->is('shop*') ? 'active' : '' }}">Belanja</a>
|
||||
<a href="#" class="nav-item nav-link">Kontak</a>
|
||||
class="nav-item nav-link mx-2 {{ request()->is('shop*') ? 'active' : '' }}">Belanja</a>
|
||||
</div>
|
||||
|
||||
<div class="d-flex m-3 me-0 align-items-center">
|
||||
<form action="{{ route('shop') }}" method="GET" class="d-flex me-4">
|
||||
<div class="d-flex align-items-center mt-3 mt-xl-0">
|
||||
<form action="{{ route('shop') }}" method="GET" class="me-3 d-none d-md-flex">
|
||||
<div class="input-group">
|
||||
<input type="search" name="search" class="form-control border border-secondary"
|
||||
placeholder="Cari..." value="{{ request('search') }}"
|
||||
style="border-radius: 20px 0 0 20px;">
|
||||
<button class="btn btn-outline-secondary border border-secondary" type="submit"
|
||||
style="border-radius: 0 20px 20px 0;">
|
||||
<i class="fas fa-search text-primary"></i>
|
||||
<input type="search" name="search" class="form-control border-end-0"
|
||||
placeholder="Cari produk..." value="{{ request('search') }}"
|
||||
style="border-radius: 6px 0 0 6px;">
|
||||
<button class="btn btn-outline-secondary border-start-0" type="submit"
|
||||
style="border-radius: 0 6px 6px 0; border-color: #dee2e6;">
|
||||
<i class="fas fa-search text-muted"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<a href="{{ route('cart') }}" class="position-relative me-4 my-auto">
|
||||
<i class="fa fa-shopping-bag fa-2x text-dark"></i>
|
||||
<span
|
||||
class="position-absolute bg-secondary rounded-circle d-flex align-items-center justify-content-center text-dark px-1"
|
||||
style="top: -5px; left: 15px; height: 20px; min-width: 20px;">
|
||||
<a href="{{ route('cart') }}" class="position-relative me-3 text-dark">
|
||||
<i class="bi bi-bag fs-4"></i> <span
|
||||
class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger"
|
||||
style="font-size: 0.6rem;">
|
||||
{{ count((array) session('cart')) }}
|
||||
</span>
|
||||
</a>
|
||||
|
||||
@if (Auth::guard('pembeli')->check())
|
||||
<div class="nav-item dropdown">
|
||||
<a href="#" class="nav-link dropdown-toggle my-auto text-dark fw-bold"
|
||||
<div class="nav-item dropdown ms-2">
|
||||
<a href="#"
|
||||
class="nav-link dropdown-toggle text-dark fw-bold d-flex align-items-center"
|
||||
data-bs-toggle="dropdown">
|
||||
<i class="fas fa-user fa-2x me-1"></i>
|
||||
<div class="bg-light rounded-circle d-flex align-items-center justify-content-center me-2"
|
||||
style="width: 35px; height: 35px;">
|
||||
<i class="fas fa-user text-primary"></i>
|
||||
</div>
|
||||
<span
|
||||
class="d-none d-xl-inline">{{ Auth::guard('pembeli')->user()->nama_lengkap }}</span>
|
||||
class="d-none d-xl-inline small">{{ Auth::guard('pembeli')->user()->nama_lengkap }}</span>
|
||||
</a>
|
||||
<div class="dropdown-menu m-0 bg-secondary rounded-0">
|
||||
<a href="{{ route('pembeli.profile') }}" class="dropdown-item">Profil Saya</a>
|
||||
<a href="{{ route('pembeli.pesan.index') }}" class="dropdown-item">Pesan
|
||||
Saya</a>
|
||||
<a href="{{ route('pesanan.saya') }}" class="dropdown-item">Pesanan Saya</a>
|
||||
<div class="dropdown-menu dropdown-menu-end border-0 shadow-sm m-0 rounded-3">
|
||||
<a href="{{ route('pembeli.profile') }}" class="dropdown-item py-2"><i
|
||||
class="bi bi-person me-2"></i> Profil</a>
|
||||
<a href="{{ route('pembeli.pesan.index') }}" class="dropdown-item py-2"><i
|
||||
class="bi bi-chat-dots me-2"></i> Pesan</a>
|
||||
<a href="{{ route('pesanan.saya') }}" class="dropdown-item py-2"><i
|
||||
class="bi bi-bag-check me-2"></i> Riwayat Pesanan</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<form action="{{ route('logout') }}" method="POST">
|
||||
@csrf
|
||||
<button type="submit" class="dropdown-item">Logout</button>
|
||||
<button type="submit" class="dropdown-item py-2 text-danger"><i
|
||||
class="bi bi-box-arrow-right me-2"></i> Logout</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
<a href="{{ route('login') }}" class="my-auto btn btn-primary rounded-pill px-4">
|
||||
<i class="fas fa-user me-2"></i> Login
|
||||
<a href="{{ route('login') }}" class="btn btn-primary px-4 ms-2">
|
||||
Login
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
|
|
@ -303,100 +298,79 @@ class="d-none d-xl-inline">{{ Auth::guard('pembeli')->user()->nama_lengkap }}</s
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 150px;">
|
||||
|
||||
<div style="margin-top: 170px;">
|
||||
@if (session('success'))
|
||||
<div class="container mt-3">
|
||||
<div class="alert alert-success alert-dismissible fade show shadow-sm" role="alert">
|
||||
<i class="fa fa-check-circle me-2"></i> {{ session('success') }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
<div class="container mt-4">
|
||||
<div class="alert alert-success border-0 shadow-sm rounded-3 d-flex align-items-center"
|
||||
role="alert">
|
||||
<i class="bi bi-check-circle-fill fs-4 me-3"></i>
|
||||
<div>{{ session('success') }}</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert"
|
||||
aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@yield('content')
|
||||
</div>
|
||||
<div class="container-fluid bg-dark text-white-50 footer">
|
||||
|
||||
<div class="container-fluid bg-dark text-white-50 footer mt-5 pt-5">
|
||||
<div class="container py-5">
|
||||
<div class="pb-4 mb-4 footer-accent">
|
||||
<div class="row g-4">
|
||||
<div class="col-lg-3">
|
||||
<a href="#">
|
||||
<h1 class="text-primary mb-0">TaniDesa</h1>
|
||||
<p class="text-secondary mb-0">Platform Pangan Langsung Petani</p>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="position-relative mx-auto">
|
||||
<input class="form-control border-0 w-100 py-3 px-4 rounded-pill" type="text"
|
||||
placeholder="Email Anda">
|
||||
<button type="submit"
|
||||
class="btn btn-primary border-0 border-secondary py-3 px-4 position-absolute rounded-pill text-white"
|
||||
style="top: 0; right: 0;">Langganan</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3">
|
||||
<div class="d-flex justify-content-end pt-3">
|
||||
<a class="btn btn-outline-secondary me-2 btn-md-square rounded-circle" href=""><i
|
||||
class="fab fa-twitter"></i></a>
|
||||
<a class="btn btn-outline-secondary me-2 btn-md-square rounded-circle" href=""><i
|
||||
class="fab fa-facebook-f"></i></a>
|
||||
<a class="btn btn-outline-secondary me-2 btn-md-square rounded-circle" href=""><i
|
||||
class="fab fa-youtube"></i></a>
|
||||
<a class="btn btn-outline-secondary btn-md-square rounded-circle" href=""><i
|
||||
class="fab fa-linkedin-in"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="footer-item">
|
||||
<h4 class="text-light mb-3">Tentang Kami</h4>
|
||||
<p class="mb-4">TaniDesa memotong rantai pasok yang panjang, memberikan harga terbaik untuk
|
||||
petani dan kesegaran maksimal untuk pembeli.</p>
|
||||
<h3 class="text-white mb-4">GriyaPadi.id</h3>
|
||||
<p class="mb-4 small">Menghubungkan petani lokal langsung dengan pembeli untuk harga yang adil dan
|
||||
produk berkualitas tinggi.</p>
|
||||
<div class="d-flex pt-2">
|
||||
<a class="btn btn-outline-light btn-sm rounded-circle me-2" href=""><i
|
||||
class="fab fa-twitter"></i></a>
|
||||
<a class="btn btn-outline-light btn-sm rounded-circle me-2" href=""><i
|
||||
class="fab fa-facebook-f"></i></a>
|
||||
<a class="btn btn-outline-light btn-sm rounded-circle" href=""><i
|
||||
class="fab fa-youtube"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="d-flex flex-column text-start footer-item">
|
||||
<h4 class="text-light mb-3">Menu Cepat</h4>
|
||||
<a class="btn-link" href="{{ route('shop') }}">Belanja Sekarang</a>
|
||||
<a class="btn-link" href="#">Hubungi Kami</a>
|
||||
<a class="btn-link" href="#">Syarat & Ketentuan</a>
|
||||
<h5 class="text-white mb-4">Tautan Cepat</h5>
|
||||
<div class="d-flex flex-column justify-content-start">
|
||||
<a class="text-white-50 mb-2 text-decoration-none" href="{{ route('shop') }}"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Belanja</a>
|
||||
<a class="text-white-50 mb-2 text-decoration-none" href="#"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Tentang Kami</a>
|
||||
<a class="text-white-50 text-decoration-none" href="#"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Hubungi Kami</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="d-flex flex-column text-start footer-item">
|
||||
<h4 class="text-light mb-3">Akun</h4>
|
||||
<a class="btn-link" href="{{ route('pembeli.profile') }}">Profil Saya</a>
|
||||
<a class="btn-link" href="{{ route('cart') }}">Keranjang Belanja</a>
|
||||
<a class="btn-link" href="{{ route('pesanan.saya') }}">Riwayat Pesanan</a>
|
||||
<h5 class="text-white mb-4">Akun Saya</h5>
|
||||
<div class="d-flex flex-column justify-content-start">
|
||||
<a class="text-white-50 mb-2 text-decoration-none" href="{{ route('pembeli.profile') }}"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Profil</a>
|
||||
<a class="text-white-50 mb-2 text-decoration-none" href="{{ route('cart') }}"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Keranjang</a>
|
||||
<a class="text-white-50 text-decoration-none" href="{{ route('pesanan.saya') }}"><i
|
||||
class="bi bi-chevron-right me-2 small"></i>Riwayat Pesanan</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6">
|
||||
<div class="footer-item">
|
||||
<h4 class="text-light mb-3">Kontak</h4>
|
||||
<p>Alamat: Desa Sukamaju, Nganjuk</p>
|
||||
<p>Email: info@tanidesa.com</p>
|
||||
<p>WA: +62 812 3456 7890</p>
|
||||
</div>
|
||||
<h5 class="text-white mb-4">Hubungi Kami</h5>
|
||||
<p class="small mb-2"><i class="fa fa-map-marker-alt me-3"></i>Desa Sukamaju, Nganjuk</p>
|
||||
<p class="small mb-2"><i class="fa fa-envelope me-3"></i>info@tanidesa.com</p>
|
||||
<p class="small mb-0"><i class="fa fa-phone-alt me-3"></i>+62 812 3456 7890</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid copyright bg-dark py-4" style="border-top: 1px solid rgba(255,255,255,0.1);">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-6 text-center text-md-start mb-3 mb-md-0">
|
||||
<span class="text-light"><a href="#"><i
|
||||
class="fas fa-copyright text-light me-2"></i>TaniDesa</a>, All right
|
||||
reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid copyright bg-dark py-4 border-top border-secondary">
|
||||
<div class="container text-center">
|
||||
<span class="text-white-50 small">© <a href="#" class="text-white">GriyaPadi.id</a>, All Right
|
||||
Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" class="btn btn-primary border-3 border-primary rounded-circle back-to-top"><i
|
||||
class="fa fa-arrow-up"></i></a>
|
||||
<a href="#" class="btn btn-primary btn-lg-square rounded-circle back-to-top shadow"><i
|
||||
class="bi bi-arrow-up"></i></a>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
|
|
|
|||
|
|
@ -4,78 +4,79 @@
|
|||
@section('page-title', 'Overview Toko')
|
||||
|
||||
@section('content')
|
||||
<section class="row">
|
||||
<div class="col-12 col-lg-12">
|
||||
<div class="row">
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon purple">
|
||||
<i class="bi bi-basket-fill"></i>
|
||||
<section class="row">
|
||||
<div class="col-12 col-lg-12">
|
||||
<div class="row">
|
||||
{{-- Card 1: Produk Saya --}}
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon purple"><i class="bi bi-people-fill"></i></div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Produk Saya</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalProduk }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Produk Saya</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $totalProduk }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Card 2: Pesanan Baru --}}
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon blue">
|
||||
<i class="bi bi-receipt"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Pesanan Baru</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $pesananBaru }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Card 3: Total Pendapatan --}}
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4 d-flex justify-content-center align-items-center">
|
||||
<div class="stats-icon green">
|
||||
<i class="bi bi-cash"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Pendapatan</h6>
|
||||
<h6 class="font-extrabold mb-0">Rp {{ number_format($totalPendapatan, 0, ',', '.') }}
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon blue">
|
||||
<i class="bi bi-receipt"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Pesanan Baru</h6>
|
||||
<h6 class="font-extrabold mb-0">{{ $pesananBaru }}</h6>
|
||||
<small class="text-xs text-muted">Perlu diproses</small>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Selamat Datang, {{ Auth::guard('petani')->user()->nama_lengkap }}!</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-lg-4 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body px-3 py-4-5">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="stats-icon green">
|
||||
<i class="bi bi-cash"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<h6 class="text-muted font-semibold">Total Pendapatan</h6>
|
||||
<h6 class="font-extrabold mb-0">Rp {{ number_format($totalPendapatan, 0, ',', '.') }}</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Kelola produk dan pantau pesanan Anda melalui menu di sebelah kiri.</p>
|
||||
<a href="{{ route('petani.produk.create') }}" class="btn btn-primary">Tambah Produk Baru</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Selamat Datang, {{ Auth::guard('petani')->user()->nama_lengkap }}!</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>Kelola produk dan pantau pesanan Anda melalui menu di sebelah kiri.</p>
|
||||
<a href="{{ route('petani.produk.create') }}" class="btn btn-primary">Tambah Produk Baru</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
@endsection
|
||||
|
|
@ -2,13 +2,40 @@
|
|||
@section('title', 'Kotak Masuk')
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
/* Styling Khusus agar sama dengan Show Blade */
|
||||
.chat-card {
|
||||
height: 80vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-sidebar {
|
||||
border-right: 1px solid #dee2e6;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-list-container {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Scrollbar Tipis */
|
||||
::-webkit-scrollbar { width: 6px; }
|
||||
::-webkit-scrollbar-track { background: #f1f1f1; }
|
||||
::-webkit-scrollbar-thumb { background: #ccc; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #aaa; }
|
||||
</style>
|
||||
|
||||
<section class="section">
|
||||
<div class="card chat-card shadow-sm">
|
||||
<div class="row g-0 h-100">
|
||||
|
||||
{{-- DAFTAR CHAT --}}
|
||||
<div class="col-md-4 chat-sidebar">
|
||||
<div class="p-4 border-bottom bg-white sticky-top">
|
||||
<h5 class="mb-3 text-primary"><i class="bi bi-chat-left-text-fill"></i> Percakapan</h5>
|
||||
<h5 class="mb-3 text-success"><i class="bi bi-chat-left-text-fill"></i> Percakapan</h5>
|
||||
<div class="form-group position-relative has-icon-right mb-0">
|
||||
<input type="text" class="form-control" placeholder="Cari pembeli...">
|
||||
<div class="form-control-icon">
|
||||
|
|
@ -17,45 +44,53 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
<div class="list-group list-group-flush chat-list-container">
|
||||
@forelse($chatList as $chat)
|
||||
<a href="{{ route('petani.pesan.show', $chat['lawan_id']) }}" class="list-group-item list-group-item-action chat-item p-3">
|
||||
<div class="d-flex align-items-center">
|
||||
|
||||
<div class="avatar avatar-lg me-3">
|
||||
<img src="{{ asset('assets/compiled/jpg/1.jpg') }}" alt="Avatar"> @if($chat['unread'] > 0)
|
||||
{{-- Avatar Inisial --}}
|
||||
<span class="avatar-content rounded-circle d-flex align-items-center justify-content-center text-white font-bold"
|
||||
style="width: 48px; height: 48px; background-color: #81c408; font-size: 1.2rem;">
|
||||
{{ substr($chat['nama'], 0, 1) }}
|
||||
</span>
|
||||
@if($chat['unread'] > 0)
|
||||
<span class="avatar-status bg-danger"></span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="flex-grow-1 text-truncate">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<h6 class="mb-0 text-dark">{{ $chat['nama'] }}</h6>
|
||||
<small class="text-muted" style="font-size: 11px">{{ $chat['time'] }}</small>
|
||||
<h6 class="mb-0 text-dark fw-bold">{{ $chat['nama'] }}</h6>
|
||||
<small class="text-muted" style="font-size: 0.75rem">{{ $chat['time'] }}</small>
|
||||
</div>
|
||||
<p class="mb-0 small text-muted text-truncate">
|
||||
{{ Str::limit($chat['last_message'], 30) }}
|
||||
{{ Str::limit($chat['last_message'], 35) }}
|
||||
</p>
|
||||
</div>
|
||||
@if($chat['unread'] > 0)
|
||||
<span class="badge bg-danger rounded-pill ms-2">{{ $chat['unread'] }}</span>
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
@empty
|
||||
<div class="text-center p-5">
|
||||
<i class="bi bi-inbox x-3 text-muted"></i>
|
||||
<p class="text-muted mt-2">Belum ada pesan masuk.</p>
|
||||
<div class="text-center p-5 mt-4">
|
||||
<i class="bi bi-chat-square-text text-muted" style="font-size: 3rem; opacity: 0.5;"></i>
|
||||
<p class="text-muted mt-3">Belum ada pesan masuk.</p>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8 d-none d-md-flex align-items-center justify-content-center bg-white flex-column">
|
||||
<div class="text-center opacity-50">
|
||||
<div class="mb-3">
|
||||
<i class="bi bi-chat-square-dots text-primary" style="font-size: 5rem;"></i>
|
||||
<div class="col-md-8 d-none d-md-flex align-items-center justify-content-center bg-light flex-column border-start">
|
||||
<div class="text-center opacity-75">
|
||||
<div class="mb-4">
|
||||
<div class="bg-white p-4 rounded-circle shadow-sm d-inline-block">
|
||||
<i class="bi bi-chat-dots-fill text-success" style="font-size: 4rem;"></i>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="text-primary">Selamat Datang, Pak Tani!</h4>
|
||||
<p class="text-secondary">Pilih percakapan di sebelah kiri untuk melihat detail pesan.</p>
|
||||
<h4 class="text-dark fw-bold">Selamat Datang di Pesan!</h4>
|
||||
<p class="text-secondary mt-2">
|
||||
Pilih salah satu percakapan di sebelah kiri<br>untuk melihat detail pesan dan membalasnya.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,63 @@
|
|||
@section('title', 'Chat: ' . $lawan->nama_lengkap)
|
||||
|
||||
@section('content')
|
||||
<style>
|
||||
.chat-card {
|
||||
height: 80vh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-sidebar {
|
||||
border-right: 1px solid #dee2e6;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.chat-list-container {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.chat-window {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #f2f7ff;
|
||||
}
|
||||
|
||||
.chat-content {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: #ccc;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover {
|
||||
background: #aaa;
|
||||
}
|
||||
</style>
|
||||
|
||||
<section class="section">
|
||||
<div class="card chat-card shadow-sm">
|
||||
<div class="row g-0 h-100">
|
||||
|
||||
<div class="col-md-4 chat-sidebar d-none d-md-block">
|
||||
<div class="p-4 border-bottom bg-white sticky-top">
|
||||
<h5 class="mb-3 text-primary"><i class="bi bi-chat-left-text-fill"></i> Percakapan</h5>
|
||||
{{-- SIDEBAR KIRI (DAFTAR CHAT) --}}
|
||||
<div class="col-md-4 chat-sidebar d-none d-md-flex">
|
||||
<div class="p-4 border-bottom bg-white">
|
||||
<h5 class="mb-3 text-success"><i class="bi bi-chat-left-text-fill"></i> Percakapan</h5>
|
||||
<div class="form-group position-relative has-icon-right mb-0">
|
||||
<input type="text" class="form-control" placeholder="Cari pembeli...">
|
||||
<div class="form-control-icon">
|
||||
|
|
@ -17,14 +67,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="list-group list-group-flush">
|
||||
<div class="list-group list-group-flush chat-list-container">
|
||||
@foreach ($chatList as $chat)
|
||||
<a href="{{ route('petani.pesan.show', $chat['lawan_id']) }}"
|
||||
class="list-group-item list-group-item-action chat-item p-3 {{ $chat['lawan_id'] == $lawan->id ? 'active' : '' }}">
|
||||
<div class="d-flex align-items-center">
|
||||
|
||||
<div class="avatar avatar-lg me-3">
|
||||
<span class="avatar-content bg-primary text-white">
|
||||
{{-- Avatar dengan inisial --}}
|
||||
<span
|
||||
class="avatar-content rounded-circle d-flex align-items-center justify-content-center text-white font-bold"
|
||||
style="width: 48px; height: 48px; background-color: #81c408; font-size: 1.2rem;">
|
||||
{{ substr($chat['nama'], 0, 1) }}
|
||||
</span>
|
||||
@if ($chat['unread'] > 0)
|
||||
|
|
@ -35,15 +88,17 @@ class="list-group-item list-group-item-action chat-item p-3 {{ $chat['lawan_id']
|
|||
<div class="flex-grow-1 text-truncate">
|
||||
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||
<h6
|
||||
class="mb-0 {{ $chat['lawan_id'] == $lawan->id ? 'text-white' : 'text-dark' }}">
|
||||
class="mb-0 fw-bold {{ $chat['lawan_id'] == $lawan->id ? 'text-white' : 'text-dark' }}">
|
||||
{{ $chat['nama'] }}
|
||||
</h6>
|
||||
<small
|
||||
class="{{ $chat['lawan_id'] == $lawan->id ? 'text-white' : 'text-muted' }}"
|
||||
style="font-size: 11px">{{ $chat['time'] }}</small>
|
||||
class="{{ $chat['lawan_id'] == $lawan->id ? 'text-white-50' : 'text-muted' }}"
|
||||
style="font-size: 0.75rem">
|
||||
{{ $chat['time'] }}
|
||||
</small>
|
||||
</div>
|
||||
<p
|
||||
class="mb-0 small text-truncate {{ $chat['lawan_id'] == $lawan->id ? 'text-white' : 'text-muted' }}">
|
||||
class="mb-0 small text-truncate {{ $chat['lawan_id'] == $lawan->id ? 'text-white-50' : 'text-muted' }}">
|
||||
{{ Str::limit($chat['last_message'], 30) }}
|
||||
</p>
|
||||
</div>
|
||||
|
|
@ -53,42 +108,45 @@ class="mb-0 small text-truncate {{ $chat['lawan_id'] == $lawan->id ? 'text-white
|
|||
</div>
|
||||
</div>
|
||||
|
||||
{{-- AREA CHAT KANAN --}}
|
||||
<div class="col-md-8 chat-window">
|
||||
|
||||
<div class="p-3 border-bottom bg-white d-flex align-items-center shadow-sm z-index-1">
|
||||
{{-- Header Chat --}}
|
||||
<div class="p-3 border-bottom bg-white d-flex align-items-center shadow-sm" style="z-index: 10;">
|
||||
<a href="{{ route('petani.pesan.index') }}"
|
||||
class="btn btn-sm btn-light me-3 d-md-none rounded-circle">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
</a>
|
||||
|
||||
<div class="avatar avatar-md me-3">
|
||||
<div class="avatar-content bg-primary text-white font-bold">
|
||||
<span
|
||||
class="avatar-content rounded-circle d-flex align-items-center justify-content-center text-white font-bold"
|
||||
style="width: 40px; height: 40px; background-color: #81c408;">
|
||||
{{ substr($lawan->nama_lengkap, 0, 1) }}
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="mb-0 text-dark">{{ $lawan->nama_lengkap }}</h6>
|
||||
<h6 class="mb-0 text-dark fw-bold">{{ $lawan->nama_lengkap }}</h6>
|
||||
<small class="text-muted">{{ $lawan->role ?? 'Pembeli' }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- Isi Chat --}}
|
||||
<div class="chat-content" id="chatContainer">
|
||||
@forelse($chats as $chat)
|
||||
@php
|
||||
$isMe =
|
||||
$chat->pengirim_id == Auth::guard('petani')->id() &&
|
||||
$chat->pengirim_type == 'App\Models\Petani';
|
||||
$isMe = ($chat->pengirim_id == Auth::guard('petani')->id() &&
|
||||
$chat->pengirim_type == 'App\Models\Petani');
|
||||
@endphp
|
||||
|
||||
<div class="d-flex w-100 mb-3 {{ $isMe ? 'justify-content-end' : 'justify-content-start' }}">
|
||||
<div style="max-width: 70%;">
|
||||
<div class="p-3 shadow-sm position-relative"
|
||||
style="border-radius: 15px;
|
||||
border-{{ $isMe ? 'bottom-right' : 'bottom-left' }}-radius: 0;
|
||||
background-color: {{ $isMe ? '#435ebe' : '#ffffff' }};
|
||||
color: {{ $isMe ? '#ffffff' : '#212529' }};">
|
||||
<div style="max-width: 75%;">
|
||||
<div class="p-3 shadow-sm position-relative" style="border-radius: 15px;
|
||||
border-{{ $isMe ? 'bottom-right' : 'bottom-left' }}-radius: 0;
|
||||
background-color: {{ $isMe ? '#81c408' : '#ffffff' }};
|
||||
color: {{ $isMe ? '#ffffff' : '#212529' }};">
|
||||
|
||||
<p class="mb-1" style="font-size: 0.95rem; line-height: 1.5;">
|
||||
<p class="mb-1" style="font-size: 0.95rem; line-height: 1.5; word-wrap: break-word;">
|
||||
{{ $chat->isi_pesan }}
|
||||
</p>
|
||||
|
||||
|
|
@ -105,23 +163,24 @@ class="btn btn-sm btn-light me-3 d-md-none rounded-circle">
|
|||
</div>
|
||||
</div>
|
||||
@empty
|
||||
<div class="text-center my-5">
|
||||
<span class="badge bg-light-secondary text-secondary p-3 rounded-pill">
|
||||
Belum ada percakapan. Sapa pembeli Anda! 👋
|
||||
<div class="text-center my-auto">
|
||||
<span class="badge bg-light text-secondary p-3 rounded-pill shadow-sm">
|
||||
👋 Belum ada percakapan. Mulai sapa pembeli Anda!
|
||||
</span>
|
||||
</div>
|
||||
@endforelse
|
||||
</div>
|
||||
|
||||
{{-- Footer Input Pesan --}}
|
||||
<div class="p-3 bg-white border-top">
|
||||
<form action="{{ route('pesan.kirim') }}" method="POST" class="d-flex gap-2 align-items-center">
|
||||
@csrf
|
||||
<input type="hidden" name="penerima_id" value="{{ $lawan->id }}">
|
||||
|
||||
<input type="hidden" name="penerima_type" value="App\Models\Pembeli">
|
||||
<div class="input-group">
|
||||
<input type="text" name="isi_pesan" class="form-control" placeholder="Ketik pesan..."
|
||||
required autocomplete="off">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<button type="submit" class="btn btn-primary-green">
|
||||
<i class="bi bi-send-fill"></i> Kirim
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -134,11 +193,11 @@ class="btn btn-sm btn-light me-3 d-md-none rounded-circle">
|
|||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var chatBox = document.getElementById("chatContainer");
|
||||
if (chatBox) {
|
||||
chatBox.scrollTop = chatBox.scrollHeight;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
@endsection
|
||||
|
|
@ -1,174 +1,175 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Detail Pesanan')
|
||||
@section('page-title', 'Detail Pesanan #' . $pesanan->kode_invoice)
|
||||
@section('page-title')
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<div>
|
||||
<h4 class="mb-0">Detail Pesanan</h4>
|
||||
<p class="text-muted font-bold mb-0">Invoice: #{{ $pesanan->kode_invoice }}</p>
|
||||
</div>
|
||||
<a href="{{ route('petani.pesanan.index') }}" class="btn btn-light">
|
||||
<i class="bi bi-arrow-left"></i> Kembali
|
||||
</a>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Informasi Pesanan</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<th width="30%">Nomor Invoice</th>
|
||||
<td>: <span class="text-primary font-bold">#{{ $pesanan->kode_invoice }}</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Tanggal Pesanan</th>
|
||||
<td>: {{ \Carbon\Carbon::parse($pesanan->tanggal_transaksi)->format('d F Y H:i') }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<td>:
|
||||
@if($pesanan->status == 'menunggu_konfirmasi')
|
||||
<span class="badge bg-warning">Perlu Konfirmasi</span>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<span class="badge bg-info">Diproses</span>
|
||||
@elseif($pesanan->status == 'dikirim')
|
||||
<span class="badge bg-primary">Dikirim</span>
|
||||
@elseif($pesanan->status == 'selesai')
|
||||
<span class="badge bg-success">Selesai</span>
|
||||
@else
|
||||
<span class="badge bg-danger">Batal</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<h5>Daftar Produk</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Produk</th>
|
||||
<th class="text-center">Jumlah</th>
|
||||
<th class="text-end">Harga Satuan</th>
|
||||
<th class="text-end">Subtotal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($pesanan->details as $detail)
|
||||
@if($detail->produk->petani_id == Auth::guard('petani')->id())
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ $detail->produk->foto_produk ? asset('storage/'.$detail->produk->foto_produk) : asset('template/frontend/img/fruite-item-5.jpg') }}"
|
||||
alt="{{ $detail->produk->nama_produk }}"
|
||||
class="rounded me-2"
|
||||
style="width: 50px; height: 50px; object-fit: cover;">
|
||||
<div>
|
||||
<h6 class="mb-0">{{ $detail->produk->nama_produk }}</h6>
|
||||
<div class="row">
|
||||
{{-- KOLOM KIRI: Daftar Produk --}}
|
||||
<div class="col-lg-8">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Daftar Produk yang Dipesan</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Produk</th>
|
||||
<th class="text-center">Qty</th>
|
||||
<th class="text-end">Harga</th>
|
||||
<th class="text-end">Subtotal</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($pesanan->detailTransaksis as $detail)
|
||||
@if($detail->produk->petani_id == Auth::guard('petani')->id())
|
||||
<tr>
|
||||
<td>
|
||||
<div class="d-flex align-items-center">
|
||||
<img src="{{ $detail->produk->foto_produk ? asset('storage/' . $detail->produk->foto_produk) : 'https://images.unsplash.com/photo-1586201375761-83865001e31c?q=80&w=200&auto=format&fit=crop' }}"
|
||||
class="rounded me-3" width="50" height="50" style="object-fit: cover;">
|
||||
<div>
|
||||
<h6 class="mb-1">{{ $detail->produk->nama_produk }}</h6>
|
||||
<span
|
||||
class="badge bg-primary-green">{{ $detail->produk->kategori->nama_kategori ?? 'Umum' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">{{ $detail->jumlah }}</td>
|
||||
<td class="text-end">Rp {{ number_format($detail->harga_satuan, 0, ',', '.') }}</td>
|
||||
<td class="text-end fw-bold">Rp {{ number_format($detail->subtotal, 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="text-end fw-bold">Total Pendapatan:</td>
|
||||
<td class="text-end fw-bold text-success">
|
||||
@php
|
||||
$totalPetani = $pesanan->details->filter(function($detail) {
|
||||
return $detail->produk->petani_id == Auth::guard('petani')->id();
|
||||
})->sum('subtotal');
|
||||
@endphp
|
||||
Rp {{ number_format($totalPetani, 0, ',', '.') }}
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span class="badge bg-primary-green">{{ $detail->jumlah }}</span>
|
||||
</td>
|
||||
<td class="text-end">Rp {{ number_format($detail->harga_satuan, 0, ',', '.') }}</td>
|
||||
<td class="text-end fw-bold">Rp {{ number_format($detail->subtotal, 0, ',', '.') }}</td>
|
||||
</tr>
|
||||
@endif
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 pt-3 border-top">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-0">Total</h5>
|
||||
@php
|
||||
$totalPetani = $pesanan->detailTransaksis->filter(function ($detail) {
|
||||
return $detail->produk->petani_id == Auth::guard('petani')->id();
|
||||
})->sum('subtotal');
|
||||
@endphp
|
||||
<h4 class="mb-0 text-primary fw-bold">Rp {{ number_format($totalPetani, 0, ',', '.') }}</h4>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Informasi Pembeli</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="avatar avatar-lg me-3">
|
||||
<img src="{{ asset('template/admin/static/images/faces/2.jpg') }}" alt="Pembeli">
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="mb-0">{{ $pesanan->pembeli->nama_lengkap }}</h5>
|
||||
<small class="text-muted">{{ $pesanan->pembeli->username }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><strong><i class="bi bi-telephone me-2"></i> No. HP / WA:</strong><br>
|
||||
<a href="https://wa.me/{{ $pesanan->pembeli->no_hp }}" target="_blank" class="text-success">{{ $pesanan->pembeli->no_hp }}</a></p>
|
||||
|
||||
<p><strong><i class="bi bi-geo-alt me-2"></i> Alamat Pengiriman:</strong><br>
|
||||
{{ $pesanan->alamat_pengiriman }}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Panel Aksi & Info --}}
|
||||
<div class="col-lg-4">
|
||||
@if($pesanan->status == 'menunggu_konfirmasi' || $pesanan->status == 'menunggu konfirmasi')
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<div class="alert alert-warning mb-3">
|
||||
<h6 class="alert-heading mb-2">Perlu Konfirmasi</h6>
|
||||
<p class="mb-0 small">Pastikan stok tersedia sebelum menerima pesanan ini.</p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Aksi Pesanan</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if($pesanan->status == 'menunggu_konfirmasi')
|
||||
<p class="text-muted mb-3">Pesanan baru masuk. Silakan terima jika stok tersedia atau tolak jika tidak bisa dipenuhi.</p>
|
||||
<div class="d-grid gap-2">
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST">
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST" class="mb-2">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="diproses">
|
||||
<button class="btn btn-success w-100" onclick="return confirm('Terima pesanan ini?')">
|
||||
<i class="bi bi-check-circle me-2"></i> Terima Pesanan
|
||||
<button class="btn btn-primary w-100" onclick="return confirm('Stok aman? Terima pesanan ini?')">
|
||||
<i class="bi bi-check-circle"></i> Terima Pesanan
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="batal">
|
||||
<button class="btn btn-danger w-100" onclick="return confirm('Tolak pesanan ini?')">
|
||||
<i class="bi bi-x-circle me-2"></i> Tolak Pesanan
|
||||
<button class="btn btn-danger w-100" onclick="return confirm('Yakin ingin menolak?')">
|
||||
<i class="bi bi-x-circle"></i> Tolak
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<p class="text-muted mb-3">Pesanan sedang diproses. Jika barang sudah dikirim atau siap diambil, update statusnya.</p>
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="dikirim">
|
||||
<button class="btn btn-primary w-100">
|
||||
<i class="bi bi-truck me-2"></i> Kirim Barang
|
||||
</button>
|
||||
</form>
|
||||
@elseif($pesanan->status == 'dikirim')
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-info-circle me-2"></i> Barang sedang dalam pengiriman. Menunggu konfirmasi selesai dari pembeli atau sistem.
|
||||
</div>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<div class="card mb-3">
|
||||
<div class="card-body text-center">
|
||||
<div class="alert alert-info">
|
||||
<i class="bi bi-box-seam fs-2 d-block mb-2"></i>
|
||||
<h6 class="alert-heading">Sedang Diproses</h6>
|
||||
<p class="mb-0 small">Klik tombol di bawah jika barang sudah diserahkan ke kurir.</p>
|
||||
</div>
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="dikirim">
|
||||
<button class="btn btn-info w-100">
|
||||
<i class="bi bi-truck"></i> Update Jadi Dikirim
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
@elseif($pesanan->status == 'selesai')
|
||||
<div class="alert alert-success">
|
||||
<i class="bi bi-check-circle-fill me-2"></i> Pesanan Selesai.
|
||||
</div>
|
||||
@elseif($pesanan->status == 'batal')
|
||||
<div class="alert alert-danger">
|
||||
<i class="bi bi-x-circle-fill me-2"></i> Pesanan Dibatalkan.
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-3 text-center">
|
||||
<a href="{{ route('petani.pesanan.index') }}" class="btn btn-link text-secondary">Kembali ke Daftar</a>
|
||||
{{-- STATUS BADGE --}}
|
||||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title mb-3">Status Pesanan</h6>
|
||||
@php
|
||||
$statusBadge = match ($pesanan->status) {
|
||||
'menunggu_konfirmasi', 'menunggu konfirmasi' => 'bg-warning',
|
||||
'diproses' => 'bg-info',
|
||||
'dikirim' => 'bg-primary',
|
||||
'selesai' => 'bg-success',
|
||||
'batal' => 'bg-danger',
|
||||
default => 'bg-secondary'
|
||||
};
|
||||
@endphp
|
||||
<span class="badge {{ $statusBadge }} fs-6">
|
||||
{{ str_replace('_', ' ', ucwords($pesanan->status)) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- INFO PEMBELI --}}
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h5 class="card-title mb-0">Data Pembeli</h5>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center mb-3">
|
||||
<div class="d-flex justify-content-center align-items-center me-2">
|
||||
<div class="stats-icon blue"><i class="bi bi-people-fill"></i></div>
|
||||
</div>
|
||||
<div>
|
||||
<h6 class="mb-0">{{ $pesanan->pembeli->nama_lengkap }}</h6>
|
||||
<small class="text-muted">{{ $pesanan->pembeli->username }}</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<small class="text-muted d-block mb-1">Kontak</small>
|
||||
<a href="https://wa.me/{{ $pesanan->pembeli->no_hp }}" target="_blank"
|
||||
class="text-success text-decoration-none">
|
||||
<i class="bi bi-whatsapp"></i> {{ $pesanan->pembeli->no_hp }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<small class="text-muted d-block mb-1">Alamat Pengiriman</small>
|
||||
<p class="mb-0">{{ $pesanan->alamat_pengiriman }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -4,93 +4,81 @@
|
|||
@section('page-title', 'Daftar Pesanan Masuk')
|
||||
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Kelola Pesanan</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
@endif
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4>Kelola Pesanan</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if(session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
@endif
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="table1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Barang</th>
|
||||
<th>Alamat</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($pesanans as $pesanan)
|
||||
<tr>
|
||||
<td class="text-primary font-bold">#{{ $pesanan->kode_invoice }}</td>
|
||||
<td>
|
||||
{{ $pesanan->pembeli->nama_lengkap }}<br>
|
||||
<small class="text-muted">{{ $pesanan->pembeli->no_hp }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-unstyled mb-0">
|
||||
@foreach($pesanan->details as $detail)
|
||||
<li>- {{ $detail->produk->nama_produk }} ({{ $detail->jumlah }})</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</td>
|
||||
<td><small>{{ Str::limit($pesanan->alamat_pengiriman, 30) }}</small></td>
|
||||
<td class="font-bold">Rp {{ number_format($pesanan->total_harga, 0, ',', '.') }}</td>
|
||||
<td>
|
||||
@if($pesanan->status == 'menunggu_konfirmasi')
|
||||
<span class="badge bg-warning">Perlu Konfirmasi</span>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<span class="badge bg-info">Diproses</span>
|
||||
@elseif($pesanan->status == 'dikirim')
|
||||
<span class="badge bg-primary">Dikirim</span>
|
||||
@elseif($pesanan->status == 'selesai')
|
||||
<span class="badge bg-success">Selesai</span>
|
||||
@else
|
||||
<span class="badge bg-danger">Batal</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('petani.pesanan.detail', $pesanan->id) }}" class="btn btn-sm btn-info text-white" title="Lihat Detail">
|
||||
<i class="bi bi-eye"></i> Detail
|
||||
</a>
|
||||
{{-- Tombol Aksi Status --}}
|
||||
@if($pesanan->status == 'menunggu_konfirmasi')
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="diproses">
|
||||
<button class="btn btn-sm btn-success" title="Terima Pesanan"><i class="bi bi-check-lg"></i></button>
|
||||
</form>
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST" class="d-inline">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="batal">
|
||||
<button class="btn btn-sm btn-danger" title="Tolak Pesanan" onclick="return confirm('Tolak pesanan ini?')"><i class="bi bi-x-lg"></i></button>
|
||||
</form>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<form action="{{ route('petani.pesanan.update', $pesanan->id) }}" method="POST">
|
||||
@csrf @method('PATCH')
|
||||
<input type="hidden" name="status" value="dikirim">
|
||||
<button class="btn btn-sm btn-primary" title="Kirim Barang"><i class="bi bi-truck"></i> Kirim</button>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">Belum ada pesanan masuk.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover" id="table1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Invoice</th>
|
||||
<th>Pembeli</th>
|
||||
<th>Barang</th>
|
||||
<th>Alamat</th>
|
||||
<th>Total</th>
|
||||
<th>Status</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($pesanans as $pesanan)
|
||||
<tr>
|
||||
<td class="text-primary font-bold">#{{ $pesanan->kode_invoice }}</td>
|
||||
<td>
|
||||
{{ $pesanan->pembeli->nama_lengkap }}<br>
|
||||
<small class="text-muted">{{ $pesanan->pembeli->no_hp }}</small>
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-unstyled mb-0">
|
||||
@foreach($pesanan->detailTransaksis as $detail)
|
||||
<li>- {{ $detail->produk->nama_produk }} ({{ $detail->jumlah }})</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</td>
|
||||
<td><small>{{ Str::limit($pesanan->alamat_pengiriman, 30) }}</small></td>
|
||||
<td class="font-bold">Rp {{ number_format($pesanan->total_harga, 0, ',', '.') }}</td>
|
||||
<td>
|
||||
@if($pesanan->status == 'menunggu konfirmasi')
|
||||
<span class="badge bg-warning">Perlu Konfirmasi</span>
|
||||
@elseif($pesanan->status == 'diproses')
|
||||
<span class="badge bg-info">Diproses</span>
|
||||
@elseif($pesanan->status == 'dikirim')
|
||||
<span class="badge bg-primary">Dikirim</span>
|
||||
@elseif($pesanan->status == 'selesai')
|
||||
<span class="badge bg-success">Selesai</span>
|
||||
@else
|
||||
<span class="badge bg-danger">Batal</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ route('petani.pesanan.detail', $pesanan->id) }}"
|
||||
class="btn btn-sm btn-outline-primary rounded-pill px-3">
|
||||
Lihat Detail <i class="bi bi-arrow-right ms-1"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="text-center">Belum ada pesanan masuk.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('js')
|
||||
<script>
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl)
|
||||
})
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -4,56 +4,232 @@
|
|||
@section('page-title', 'Tambah Produk Baru')
|
||||
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('petani.produk.store') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('petani.produk.store') }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Nama Produk</label>
|
||||
<input type="text" name="nama_produk" class="form-control" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Kategori Padi/Beras</label>
|
||||
<select name="kategori" class="form-select" required>
|
||||
<option value="Pandan Wangi">Pandan Wangi</option>
|
||||
<option value="IR 64">IR 64 (Setra Ramos)</option>
|
||||
<option value="Ketan">Ketan (Putih/Hitam)</option>
|
||||
<option value="Merah">Beras Merah</option>
|
||||
<option value="Hitam">Beras Hitam</option>
|
||||
<option value="Lainnya">Lainnya</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{-- DATA PRODUK --}}
|
||||
<div class="col-lg-8">
|
||||
<h5 class="mb-4">Informasi Produk</h5>
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Nama Produk</label>
|
||||
<input type="text" name="nama_produk" class="form-control"
|
||||
placeholder="Contoh: Beras Pandan Wangi Super" required>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group mb-3">
|
||||
<label>Harga (Rp)</label>
|
||||
<input type="number" name="harga" class="form-control" required>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="fw-bold">Kategori</label>
|
||||
<select name="kategori_id" class="form-select" required>
|
||||
<option value="" disabled selected>Pilih Kategori</option>
|
||||
@foreach($kategoris as $kat)
|
||||
<option value="{{ $kat->id }}" {{ old('kategori_id') == $kat->id ? 'selected' : '' }}>
|
||||
{{ $kat->nama_kategori }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="fw-bold">Stok (Kg)</label>
|
||||
<input type="number" name="stok" class="form-control" placeholder="0" required
|
||||
min="0">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Harga (Rp)</label>
|
||||
<input type="number" name="harga" class="form-control" placeholder="0" required min="0">
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Deskripsi</label>
|
||||
<textarea name="deskripsi" class="form-control" rows="4"
|
||||
placeholder="Jelaskan kualitas produk Anda..." required></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- UPLOAD GAMBAR --}}
|
||||
<div class="col-lg-4">
|
||||
<h5 class="mb-4">Media Produk</h5>
|
||||
|
||||
{{-- FOTO UTAMA --}}
|
||||
<div class="card bg-light border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<label class="fw-bold mb-2">Foto Utama</label>
|
||||
|
||||
{{-- AREA PREVIEW --}}
|
||||
<div class="mb-2 bg-white border rounded d-flex align-items-center justify-content-center position-relative overflow-hidden"
|
||||
style="height: 150px;">
|
||||
|
||||
{{-- Ikon Upload --}}
|
||||
<div id="placeholder-utama" class="text-center text-muted">
|
||||
<i class="bi bi-cloud-arrow-up fs-1"></i>
|
||||
<div class="small mt-1">Klik untuk upload</div>
|
||||
</div>
|
||||
|
||||
{{-- Tampilan Gambar --}}
|
||||
<img id="preview-utama" src="#"
|
||||
class="img-fluid w-100 h-100 object-fit-contain d-none">
|
||||
</div>
|
||||
|
||||
<input type="file" name="foto_produk" class="form-control form-control-sm"
|
||||
accept="image/*" required onchange="previewMainImage(this)">
|
||||
<small class="text-muted">Wajib. Tampil di halaman depan.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- GALERI TAMBAHAN --}}
|
||||
<div class="card bg-light border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<label class="fw-bold m-0">Galeri Tambahan</label>
|
||||
<span class="badge bg-primary rounded-pill" id="count-badge">0/3</span>
|
||||
</div>
|
||||
|
||||
{{-- Container Preview Grid --}}
|
||||
<div id="gallery-preview-container" class="row g-2 mb-3">
|
||||
{{-- Gambar preview --}}
|
||||
</div>
|
||||
|
||||
{{-- Input File Visual --}}
|
||||
<div class="mb-2">
|
||||
<input type="file" id="input-gallery-visual"
|
||||
class="form-control form-control-sm" accept="image/*" multiple>
|
||||
</div>
|
||||
|
||||
{{-- Input File Hidden --}}
|
||||
<input type="file" name="foto_tambahan[]" id="real-input-gallery" class="d-none"
|
||||
multiple>
|
||||
|
||||
<small class="text-muted d-block" style="font-size: 0.8rem;">
|
||||
<i class="bi bi-info-circle me-1"></i>Maksimal 3 foto. Bisa dihapus sebelum
|
||||
upload.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group mb-3">
|
||||
<label>Stok</label>
|
||||
<input type="number" name="stok" class="form-control" required>
|
||||
|
||||
<div class="border-top pt-3 mt-4 text-end">
|
||||
<a href="{{ route('petani.produk.index') }}" class="btn btn-secondary me-2">Batal</a>
|
||||
<button type="submit" class="btn btn-primary px-4">Simpan Produk</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Deskripsi</label>
|
||||
<textarea name="deskripsi" class="form-control" rows="4" required></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Foto Produk</label>
|
||||
<input type="file" name="foto_produk" class="form-control" accept="image/*" required>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-primary">Simpan Produk</button>
|
||||
<a href="{{ route('petani.produk.index') }}" class="btn btn-secondary">Batal</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
<script>
|
||||
// ----------------------------------------------------
|
||||
// PREVIEW FOTO UTAMA
|
||||
// ----------------------------------------------------
|
||||
function previewMainImage(input) {
|
||||
const preview = document.getElementById('preview-utama');
|
||||
const placeholder = document.getElementById('placeholder-utama');
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function (e) {
|
||||
preview.src = e.target.result;
|
||||
|
||||
// Tampilkan Gambar, Sembunyikan Ikon
|
||||
preview.classList.remove('d-none');
|
||||
placeholder.classList.add('d-none');
|
||||
}
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
} else {
|
||||
preview.src = '#';
|
||||
preview.classList.add('d-none');
|
||||
placeholder.classList.remove('d-none');
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// LOGIC GALERI TAMBAHAN (KERANJANG UPLOAD)
|
||||
// ----------------------------------------------------
|
||||
const inputVisual = document.getElementById('input-gallery-visual');
|
||||
const inputReal = document.getElementById('real-input-gallery');
|
||||
const container = document.getElementById('gallery-preview-container');
|
||||
const countBadge = document.getElementById('count-badge');
|
||||
|
||||
// "Keranjang" virtual untuk menampung file
|
||||
let dt = new DataTransfer();
|
||||
|
||||
inputVisual.addEventListener('change', function () {
|
||||
const newFiles = this.files;
|
||||
|
||||
// Cek Limit Total
|
||||
if (dt.items.length + newFiles.length > 3) {
|
||||
alert('Maksimal hanya boleh 3 gambar tambahan!');
|
||||
this.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop file baru
|
||||
for (let i = 0; i < newFiles.length; i++) {
|
||||
const file = newFiles[i];
|
||||
|
||||
dt.items.add(file);
|
||||
|
||||
// Buat HTML Preview
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
const col = document.createElement('div');
|
||||
col.className = 'col-4 position-relative new-image-preview';
|
||||
|
||||
col.innerHTML = `
|
||||
<img src="${e.target.result}" class="rounded w-100 border bg-white" style="height: 70px; object-fit: cover;">
|
||||
<span class="position-absolute top-0 end-0 badge bg-secondary text-white rounded-circle m-1 shadow-sm remove-btn"
|
||||
style="cursor: pointer;">×</span>
|
||||
`;
|
||||
|
||||
// Event Listener Tombol Hapus (X)
|
||||
col.querySelector('.remove-btn').addEventListener('click', function () {
|
||||
|
||||
// Hapus file dari keranjang berdasarkan nama & size
|
||||
for (let j = 0; j < dt.items.length; j++) {
|
||||
if (dt.files[j].name === file.name && dt.files[j].size === file.size) {
|
||||
dt.items.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
inputReal.files = dt.files;
|
||||
col.remove();
|
||||
updateBadge();
|
||||
});
|
||||
|
||||
container.appendChild(col);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
inputReal.files = dt.files;
|
||||
this.value = '';
|
||||
updateBadge();
|
||||
});
|
||||
|
||||
function updateBadge() {
|
||||
let total = dt.items.length;
|
||||
countBadge.innerText = total + '/3';
|
||||
|
||||
// Visual Feedback jika penuh
|
||||
if (total >= 3) {
|
||||
inputVisual.disabled = true;
|
||||
inputVisual.setAttribute('title', 'Slot penuh (Maks 3)');
|
||||
countBadge.className = 'badge bg-danger rounded-pill';
|
||||
} else {
|
||||
inputVisual.disabled = false;
|
||||
inputVisual.removeAttribute('title');
|
||||
countBadge.className = 'badge bg-primary rounded-pill';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -4,61 +4,263 @@
|
|||
@section('page-title', 'Edit Produk')
|
||||
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form action="{{ route('petani.produk.update', $produk->id) }}" method="POST" enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
{{-- Form Utama --}}
|
||||
<form action="{{ route('petani.produk.update', $produk->id) }}" method="POST"
|
||||
enctype="multipart/form-data">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Nama Produk</label>
|
||||
<input type="text" name="nama_produk" class="form-control" value="{{ $produk->nama_produk }}" required>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{-- DATA PRODUK --}}
|
||||
<div class="col-lg-8">
|
||||
<h5 class="mb-4">Informasi Produk</h5>
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Nama Produk</label>
|
||||
<input type="text" name="nama_produk" class="form-control"
|
||||
value="{{ $produk->nama_produk }}" required>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="form-label">Kategori Padi/Beras</label>
|
||||
<select name="kategori" class="form-select" required>
|
||||
<option value="Pandan Wangi">Pandan Wangi</option>
|
||||
<option value="IR 64">IR 64 (Setra Ramos)</option>
|
||||
<option value="Ketan">Ketan (Putih/Hitam)</option>
|
||||
<option value="Merah">Beras Merah</option>
|
||||
<option value="Hitam">Beras Hitam</option>
|
||||
<option value="Lainnya">Lainnya</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="fw-bold">Kategori</label>
|
||||
<select name="kategori_id" class="form-select" required>
|
||||
<option value="" disabled>Pilih Kategori</option>
|
||||
@foreach($kategoris as $kat)
|
||||
<option value="{{ $kat->id }}" {{ (old('kategori_id', $produk->kategori_id) == $kat->id) ? 'selected' : '' }}>
|
||||
{{ $kat->nama_kategori }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group mb-3">
|
||||
<label>Harga (Rp)</label>
|
||||
<input type="number" name="harga" class="form-control" value="{{ $produk->harga }}" required>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label class="fw-bold">Stok</label>
|
||||
<input type="number" name="stok" class="form-control" value="{{ $produk->stok }}"
|
||||
required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Harga (Rp)</label>
|
||||
<input type="number" name="harga" class="form-control" value="{{ $produk->harga }}"
|
||||
required>
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label class="fw-bold">Deskripsi</label>
|
||||
<textarea name="deskripsi" class="form-control" rows="4"
|
||||
required>{{ $produk->deskripsi }}</textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- KELOLA GAMBAR --}}
|
||||
<div class="col-lg-4">
|
||||
<h5 class="mb-4">Kelola Gambar</h5>
|
||||
|
||||
{{-- FOTO UTAMA --}}
|
||||
<div class="card bg-light border-0 mb-4">
|
||||
<div class="card-body">
|
||||
<label class="fw-bold mb-2">Foto Utama</label>
|
||||
|
||||
{{-- AREA PREVIEW --}}
|
||||
<div class="mb-2 bg-white border rounded d-flex align-items-center justify-content-center position-relative overflow-hidden"
|
||||
style="height: 150px;">
|
||||
|
||||
<div id="placeholder-utama"
|
||||
class="text-center text-muted {{ $produk->foto_produk ? 'd-none' : '' }}">
|
||||
<i class="bi bi-cloud-arrow-up fs-1"></i>
|
||||
<div class="small mt-1">Upload foto baru</div>
|
||||
</div>
|
||||
|
||||
<img id="preview-utama"
|
||||
src="{{ $produk->foto_produk ? asset('storage/' . $produk->foto_produk) : '#' }}"
|
||||
class="img-fluid w-100 h-100 object-fit-contain {{ $produk->foto_produk ? '' : 'd-none' }}">
|
||||
</div>
|
||||
|
||||
{{-- Input File --}}
|
||||
<input type="file" name="foto_produk" class="form-control form-control-sm"
|
||||
accept="image/*" onchange="previewMainImage(this)">
|
||||
<small class="text-muted">Biarkan kosong jika tidak ingin mengganti foto.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- GALERI TAMBAHAN --}}
|
||||
<div class="card bg-light border-0">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||
<label class="fw-bold m-0">Galeri Tambahan</label>
|
||||
<span class="badge bg-primary rounded-pill" id="count-badge">0/3</span>
|
||||
</div>
|
||||
|
||||
{{-- CONTAINER PREVIEW --}}
|
||||
<div id="gallery-preview-container" class="row g-2 mb-3">
|
||||
|
||||
{{-- Gambar Lama dari Database --}}
|
||||
@foreach($produk->images as $img)
|
||||
<div class="col-4 position-relative existing-image-wrapper"
|
||||
id="existing-img-{{ $img->id }}">
|
||||
<img src="{{ asset('storage/' . $img->foto) }}"
|
||||
class="rounded w-100 border bg-white"
|
||||
style="height: 70px; object-fit: cover;">
|
||||
|
||||
{{-- Tombol Hapus Gambar Lama --}}
|
||||
<a href="javascript:void(0)"
|
||||
class="position-absolute top-0 end-0 badge bg-danger text-white rounded-circle text-decoration-none m-1 shadow-sm"
|
||||
onclick="if(confirm('Hapus foto ini?')) deleteExistingImage({{ $img->id }});"
|
||||
style="cursor: pointer;">×</a>
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
{{-- INPUT FILE --}}
|
||||
<div class="mb-3">
|
||||
<input type="file" id="input-gallery-visual"
|
||||
class="form-control form-control-sm" accept="image/*" multiple>
|
||||
</div>
|
||||
|
||||
{{-- INPUT FILE HIDDEN --}}
|
||||
<input type="file" name="foto_tambahan[]" id="real-input-gallery" class="d-none"
|
||||
multiple>
|
||||
|
||||
<small class="text-muted d-block" style="font-size: 0.8rem;">
|
||||
<i class="bi bi-info-circle me-1"></i>Maksimal 3 foto tambahan total.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group mb-3">
|
||||
<label>Stok</label>
|
||||
<input type="number" name="stok" class="form-control" value="{{ $produk->stok }}" required>
|
||||
|
||||
<div class="border-top pt-3 mt-4 text-end">
|
||||
<a href="{{ route('petani.produk.index') }}" class="btn btn-secondary me-2">Batal</a>
|
||||
<button type="submit" class="btn btn-success px-4">Update Produk</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Deskripsi</label>
|
||||
<textarea name="deskripsi" class="form-control" rows="4" required>{{ $produk->deskripsi }}</textarea>
|
||||
{{-- FORM TERSEMBUNYI UNTUK HAPUS GAMBAR LAMA --}}
|
||||
@foreach($produk->images as $img)
|
||||
<form id="form-del-img-{{ $img->id }}" action="{{ route('petani.produk.image.delete', $img->id) }}"
|
||||
method="POST" style="display: none;">
|
||||
@csrf @method('DELETE')
|
||||
</form>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="form-group mb-3">
|
||||
<label>Foto Produk (Biarkan kosong jika tidak ingin mengganti)</label>
|
||||
<input type="file" name="foto_produk" class="form-control" accept="image/*">
|
||||
@if ($produk->foto_produk)
|
||||
<small class="text-muted">Foto saat ini:</small><br>
|
||||
<img src="{{ asset('storage/' . $produk->foto_produk) }}" width="100" class="mt-2 rounded">
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-success">Update Produk</button>
|
||||
<a href="{{ route('petani.produk.index') }}" class="btn btn-secondary">Batal</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
<script>
|
||||
// ----------------------------------------------------
|
||||
// PREVIEW FOTO UTAMA
|
||||
// ----------------------------------------------------
|
||||
function previewMainImage(input) {
|
||||
const preview = document.getElementById('preview-utama');
|
||||
const placeholder = document.getElementById('placeholder-utama');
|
||||
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
preview.src = e.target.result;
|
||||
preview.classList.remove('d-none');
|
||||
placeholder.classList.add('d-none');
|
||||
}
|
||||
|
||||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// LOGIC HAPUS GAMBAR LAMA (DATABASE)
|
||||
// ----------------------------------------------------
|
||||
function deleteExistingImage(id) {
|
||||
document.getElementById('form-del-img-' + id).submit();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// LOGIC PREVIEW + ACCUMULATE
|
||||
// ----------------------------------------------------
|
||||
const inputVisual = document.getElementById('input-gallery-visual');
|
||||
const inputReal = document.getElementById('real-input-gallery');
|
||||
const container = document.getElementById('gallery-preview-container');
|
||||
const countBadge = document.getElementById('count-badge');
|
||||
|
||||
let dt = new DataTransfer();
|
||||
let existingCount = document.querySelectorAll('.existing-image-wrapper').length;
|
||||
updateBadge();
|
||||
|
||||
inputVisual.addEventListener('change', function () {
|
||||
const newFiles = this.files;
|
||||
|
||||
if (existingCount + dt.items.length + newFiles.length > 3) {
|
||||
alert('Maksimal total hanya boleh 3 gambar tambahan!');
|
||||
this.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop file yang baru dipilih
|
||||
for (let i = 0; i < newFiles.length; i++) {
|
||||
const file = newFiles[i];
|
||||
|
||||
// Tambahkan ke keranjang DataTransfer
|
||||
dt.items.add(file);
|
||||
|
||||
// Buat Preview Element
|
||||
const reader = new FileReader();
|
||||
reader.onload = function (e) {
|
||||
const col = document.createElement('div');
|
||||
col.className = 'col-4 position-relative new-image-preview';
|
||||
|
||||
// HTML Preview
|
||||
col.innerHTML = `
|
||||
<img src="${e.target.result}" class="rounded w-100 border bg-white" style="height: 70px; object-fit: cover;">
|
||||
<span class="position-absolute top-0 end-0 badge bg-secondary text-white rounded-circle m-1 shadow-sm remove-btn"
|
||||
style="cursor: pointer;">×</span>
|
||||
`;
|
||||
|
||||
// Event Hapus Preview
|
||||
col.querySelector('.remove-btn').addEventListener('click', function () {
|
||||
for (let j = 0; j < dt.items.length; j++) {
|
||||
if (dt.files[j].name === file.name && dt.files[j].size === file.size) {
|
||||
dt.items.remove(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Sinkronisasi ke Input Real
|
||||
inputReal.files = dt.files;
|
||||
col.remove();
|
||||
updateBadge();
|
||||
});
|
||||
|
||||
container.appendChild(col);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
|
||||
inputReal.files = dt.files;
|
||||
this.value = '';
|
||||
updateBadge();
|
||||
});
|
||||
|
||||
function updateBadge() {
|
||||
let total = existingCount + dt.items.length;
|
||||
countBadge.innerText = total + '/3';
|
||||
|
||||
if (total >= 3) {
|
||||
inputVisual.disabled = true;
|
||||
countBadge.classList.remove('bg-primary');
|
||||
countBadge.classList.add('bg-danger');
|
||||
inputVisual.setAttribute('title', 'Kapasitas penuh');
|
||||
} else {
|
||||
inputVisual.disabled = false;
|
||||
countBadge.classList.remove('bg-danger');
|
||||
countBadge.classList.add('bg-primary');
|
||||
inputVisual.removeAttribute('title');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Admin\KategoriController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use App\Http\Controllers\AuthController;
|
||||
use App\Http\Controllers\AdminController;
|
||||
|
|
@ -44,7 +45,7 @@
|
|||
|
||||
Route::get('/forgot-password', [ForgotPasswordController::class, 'showLinkRequestForm'])->name('password.request');
|
||||
Route::post('/forgot-password', [ForgotPasswordController::class, 'sendResetLinkEmail'])->name('password.email');
|
||||
|
||||
|
||||
Route::get('/reset-password/{token}', [ForgotPasswordController::class, 'showResetForm'])->name('password.reset');
|
||||
Route::post('/reset-password', [ForgotPasswordController::class, 'reset'])->name('password.update');
|
||||
});
|
||||
|
|
@ -78,8 +79,6 @@
|
|||
Route::put('/profile', [ProfileController::class, 'updatePembeli'])->name('pembeli.profile.update');
|
||||
});
|
||||
|
||||
|
||||
// --- ADMIN AREA ---
|
||||
Route::middleware(['auth:admin'])->group(function () {
|
||||
Route::get('/admin/dashboard', [AdminController::class, 'dashboard'])->name('admin.dashboard');
|
||||
Route::get('/admin/monitoring', [AdminController::class, 'monitoring'])->name('admin.monitoring');
|
||||
|
|
@ -91,6 +90,12 @@
|
|||
Route::post('/{id}/approve', 'verifikasiApprove');
|
||||
Route::post('/{id}/reject', 'verifikasiReject');
|
||||
});
|
||||
|
||||
// CRUD Kategori
|
||||
Route::resource('admin/kategori', KategoriController::class)->names('admin.kategori');
|
||||
|
||||
Route::get('/admin/transaksi/{id}', [AdminController::class, 'transaksiDetail'])
|
||||
->name('admin.transaksi.detail');
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -101,6 +106,7 @@
|
|||
|
||||
// CRUD Produk Petani
|
||||
Route::resource('petani/produk', ProdukController::class)->names('petani.produk');
|
||||
Route::delete('/petani/produk/image/{id}', [App\Http\Controllers\Petani\ProdukController::class, 'deleteImage'])->name('petani.produk.image.delete');
|
||||
|
||||
// Manajemen Pesanan Masuk (Petani)
|
||||
Route::get('/petani/pesanan', [TransaksiController::class, 'pesananMasuk'])->name('petani.pesanan.index');
|
||||
|
|
|
|||
Loading…
Reference in New Issue