diff --git a/.gitignore b/.gitignore index b71b1ea..d71020c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ Homestead.json Homestead.yaml Thumbs.db +/storage/framework/views/*.php +/storage/framework/cache/data/* +/storage/framework/sessions/* \ No newline at end of file diff --git a/README.md b/README.md index 6dc6eec..77cd149 100644 --- a/README.md +++ b/README.md @@ -141,14 +141,21 @@ ### Step 6: Database Migration php artisan migrate --seed ``` -### Step 7: Konfigurasi Storage Link +### Step 7: Import Data Wilayah Indonesia (Wajib) +Jalankan perintah ini untuk mengisi data wilayah resmi Indonesia ke dalam database. + +```bash +php artisan laravolt:indonesia:seed +``` + +### Step 8: Konfigurasi Storage Link Jalankan perintah untuk konfigurasi storage link untuk menyimpan gambar ```bash php artisan storage:link ``` -### Step 8: Start Application +### Step 9: Start Application **Terminal (Laravel Server):** ```bash php artisan serve diff --git a/app/Http/Controllers/CartController.php b/app/Http/Controllers/CartController.php index 1322def..f4074dc 100644 --- a/app/Http/Controllers/CartController.php +++ b/app/Http/Controllers/CartController.php @@ -12,15 +12,16 @@ class CartController extends Controller // Menampilkan Halaman Keranjang public function index() { - // Cek Login Pembeli if (!Auth::guard('pembeli')->check()) { return redirect()->route('login')->with('error', 'Silakan login terlebih dahulu untuk melihat keranjang.'); } $pembeli_id = Auth::guard('pembeli')->id(); - // Ambil data keranjang dari Database - $cart = Cart::with('produk')->where('pembeli_id', $pembeli_id)->get(); + $cart = Cart::with('produk') + ->where('pembeli_id', $pembeli_id) + ->latest() + ->get(); return view('landing.cart', compact('cart')); } @@ -54,8 +55,8 @@ public function addToCart(Request $request) } else { Cart::create([ 'pembeli_id' => $pembeli_id, - 'produk_id' => $produk_id, - 'quantity' => $quantity + 'produk_id' => $produk_id, + 'quantity' => $quantity ]); } diff --git a/app/Http/Controllers/LandingController.php b/app/Http/Controllers/LandingController.php index 25c94df..c3e260f 100644 --- a/app/Http/Controllers/LandingController.php +++ b/app/Http/Controllers/LandingController.php @@ -25,11 +25,13 @@ public function index(Request $request) return view('landing.partials.product_list', compact('produks'))->render(); } - $produkTerlaris = Produk::withSum(['detailTransaksis as total_terjual' => function ($query) { - $query->whereHas('transaksi', function ($q) { - $q->where('status', '!=', 'batal'); - }); - }], 'jumlah') + $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(); @@ -41,6 +43,21 @@ public function shop(Request $request) { $query = Produk::where('stok', '>', 0); + // --- FILTER LOKASI --- + if ($request->filled('provinsi')) { + $query->where('provinsi_code', $request->provinsi); + } + if ($request->filled('kota')) { + $query->where('kota_code', $request->kota); + } + if ($request->filled('kecamatan')) { + $query->where('kecamatan_code', $request->kecamatan); + } + if ($request->filled('desa')) { + $query->where('desa_code', $request->desa); + } + + // Filter Search if ($request->has('search') && $request->search != '') { $query->where('nama_produk', 'like', '%' . $request->search . '%'); } @@ -91,4 +108,4 @@ public function detail($id) return view('landing.detail', compact('produk', 'produk_terkait')); } -} +} \ No newline at end of file diff --git a/app/Http/Controllers/Petani/ProdukController.php b/app/Http/Controllers/Petani/ProdukController.php index a753ec9..b3dc943 100644 --- a/app/Http/Controllers/Petani/ProdukController.php +++ b/app/Http/Controllers/Petani/ProdukController.php @@ -6,38 +6,47 @@ use Illuminate\Http\Request; use App\Models\Produk; use App\Models\ProdukImage; -use App\Models\Kategori; // PENTING: Import Model Kategori +use App\Models\Kategori; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Storage; +use Laravolt\Indonesia\Models\City; +use Laravolt\Indonesia\Models\District; +use Laravolt\Indonesia\Models\Province; +use Laravolt\Indonesia\Models\Village; class ProdukController extends Controller { public function index() { $produks = Produk::with('kategori') - ->where('petani_id', Auth::guard('petani')->id()) - ->latest() - ->get(); - + ->where('petani_id', Auth::guard('petani')->id()) + ->latest() + ->get(); + return view('petani.produk.index', compact('produks')); } public function create() { $kategoris = Kategori::all(); - - return view('petani.produk.create', compact('kategoris')); + $provinsis = Province::all(); + + return view('petani.produk.create', compact('kategoris', 'provinsis')); } public function store(Request $request) { $request->validate([ - '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', + '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', + 'provinsi_code' => 'required', + 'kota_code' => 'required', + 'kecamatan_code' => 'required', + 'desa_code' => 'required', + 'foto_produk' => 'required|image|mimes:jpeg,png,jpg|max:2048', 'foto_tambahan.*' => 'nullable|image|mimes:jpeg,png,jpg|max:2048' ]); @@ -49,12 +58,16 @@ public function store(Request $request) // Simpan Data Produk $produk = Produk::create([ - 'petani_id' => Auth::guard('petani')->id(), - 'kategori_id' => $request->kategori_id, + 'petani_id' => Auth::guard('petani')->id(), + 'kategori_id' => $request->kategori_id, 'nama_produk' => $request->nama_produk, - 'harga' => $request->harga, - 'stok' => $request->stok, - 'deskripsi' => $request->deskripsi, + 'harga' => $request->harga, + 'provinsi_code' => $request->provinsi_code, + 'kota_code' => $request->kota_code, + 'kecamatan_code' => $request->kecamatan_code, + 'desa_code' => $request->desa_code, + 'stok' => $request->stok, + 'deskripsi' => $request->deskripsi, 'foto_produk' => $fotoPath, ]); @@ -64,7 +77,7 @@ public function store(Request $request) $path = $file->store('produk/gallery', 'public'); ProdukImage::create([ 'produk_id' => $produk->id, - 'foto' => $path + 'foto' => $path ]); } } @@ -77,7 +90,12 @@ public function edit($id) $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')); + $provinsis = Province::all(); + $kotas = City::where('province_code', $produk->provinsi_code)->get(); + $kecamatans = District::where('city_code', $produk->kota_code)->get(); + $desas = Village::where('district_code', $produk->kecamatan_code)->get(); + + return view('petani.produk.edit', compact('produk', 'kategoris', 'provinsis', 'kotas', 'kecamatans', 'desas')); } public function update(Request $request, $id) @@ -89,13 +107,17 @@ public function update(Request $request, $id) $sisaSlot = max(3 - $jumlahGambarLama, 0); $request->validate([ - '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, + 'nama_produk' => 'required|string|max:255', + 'kategori_id' => 'required|exists:kategoris,id', + 'harga' => 'required|numeric|min:0', + 'provinsi_code' => 'required', + 'kota_code' => 'required', + 'kecamatan_code' => 'required', + 'desa_code' => 'required', + '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." @@ -112,22 +134,27 @@ public function update(Request $request, $id) // 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 + 'kategori_id' => $request->kategori_id, + 'harga' => $request->harga, + 'provinsi_code' => $request->provinsi_code, + 'kota_code' => $request->kota_code, + 'kecamatan_code' => $request->kecamatan_code, + 'desa_code' => $request->desa_code, + 'stok' => $request->stok, + 'deskripsi' => $request->deskripsi, + 'foto_produk' => $produk->foto_produk ]); - + // Tambah Foto Galeri if ($request->hasFile('foto_tambahan')) { foreach ($request->file('foto_tambahan') as $file) { - if ($produk->images()->count() >= 3) break; - + if ($produk->images()->count() >= 3) + break; + $path = $file->store('produk/gallery', 'public'); ProdukImage::create([ 'produk_id' => $produk->id, - 'foto' => $path + 'foto' => $path ]); } } @@ -138,18 +165,18 @@ public function update(Request $request, $id) public function destroy($id) { $produk = Produk::where('id', $id)->where('petani_id', Auth::guard('petani')->id())->firstOrFail(); - + if ($produk->foto_produk && Storage::disk('public')->exists($produk->foto_produk)) { Storage::disk('public')->delete($produk->foto_produk); } - foreach($produk->images as $img) { + foreach ($produk->images as $img) { if (Storage::disk('public')->exists($img->foto)) { Storage::disk('public')->delete($img->foto); } } - - $produk->images()->delete(); + + $produk->images()->delete(); $produk->delete(); return redirect()->route('petani.produk.index')->with('success', 'Produk berhasil dihapus.'); @@ -158,7 +185,7 @@ public function destroy($id) public function deleteImage($id) { $image = ProdukImage::findOrFail($id); - + if ($image->produk->petani_id != Auth::guard('petani')->id()) { abort(403); } diff --git a/app/Http/Controllers/TransaksiController.php b/app/Http/Controllers/TransaksiController.php index af96605..e8de055 100644 --- a/app/Http/Controllers/TransaksiController.php +++ b/app/Http/Controllers/TransaksiController.php @@ -6,6 +6,7 @@ use App\Models\Produk; use App\Models\Transaksi; use App\Models\DetailTransaksi; +use App\Models\Cart; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; @@ -13,10 +14,16 @@ class TransaksiController extends Controller { // --- FITUR PEMBELI --- - // Tampilkan Halaman Checkout + /** + * Tampilkan Halaman Checkout + * Mendukung Beli Langsung dan Checkout dari Keranjang (Database) + */ public function checkoutPage(Request $request) { - // Beli Langsung (Buy Now) + // Mendefinisikan ID Pembeli agar tidak error 'Undefined Variable' + $pembeli_id = Auth::guard('pembeli')->id(); + + // 1. LOGIKA BELI LANGSUNG (Buy Now) if ($request->has('produk_id')) { $produk = Produk::with('petani')->findOrFail($request->produk_id); $items = collect([ @@ -34,32 +41,48 @@ public function checkoutPage(Request $request) return view('landing.checkout', compact('items', 'total_belanja')); } - // Checkout dari Keranjang - $cart = session()->get('cart'); - if ($cart && count($cart) > 0) { - $items = collect(); - foreach ($cart as $id => $details) { - $produk = Produk::find($id); - if ($produk) { - $items->push((object) [ - 'id' => $id, - 'produk' => $produk, - 'nama_produk' => $details['name'], - 'harga' => $details['price'], - 'jumlah' => $details['quantity'], - 'subtotal' => $details['price'] * $details['quantity'], - 'foto' => $details['photo'] - ]); - } - } - $total_belanja = $items->sum('subtotal'); - return view('landing.checkout', compact('items', 'total_belanja')); + // 2. LOGIKA CHECKOUT DARI KERANJANG (Database) + $cartIds = $request->query('cart_ids'); + + if (!$cartIds) { + return redirect()->route('cart')->with('error', 'Pilih minimal satu produk di keranjang untuk dicheckout.'); } - return redirect()->route('shop')->with('error', 'Keranjang Anda kosong, silakan belanja dulu.'); + $selectedIds = explode(',', $cartIds); + + // Ambil data dari Tabel Cart yang ID-nya dicentang oleh user + $cartItems = Cart::with('produk.petani') + ->where('pembeli_id', $pembeli_id) + ->whereIn('id', $selectedIds) + ->get(); + + if ($cartItems->isEmpty()) { + return redirect()->route('cart')->with('error', 'Barang di keranjang tidak ditemukan atau sudah dihapus.'); + } + + // Transformasi data agar sesuai dengan format yang dibaca di View Checkout + $items = $cartItems->map(function ($item) { + return (object) [ + 'cart_id' => $item->id, + 'id' => $item->produk->id, + 'produk' => $item->produk, + 'nama_produk' => $item->produk->nama_produk, + 'harga' => $item->produk->harga, + 'jumlah' => $item->quantity, + 'subtotal' => $item->produk->harga * $item->quantity, + 'foto' => $item->produk->foto_produk + ]; + }); + + $total_belanja = $items->sum('subtotal'); + + return view('landing.checkout', compact('items', 'total_belanja')); } - // fungsi prosesCheckout + /** + * Proses Pembuatan Transaksi + * Mengelompokkan pesanan berdasarkan Petani dan membersihkan keranjang + */ public function prosesCheckout(Request $request) { $request->validate([ @@ -70,9 +93,9 @@ public function prosesCheckout(Request $request) $pembeli_id = Auth::guard('pembeli')->id(); DB::transaction(function () use ($request, $pembeli_id) { - + if ($request->has('produk_id')) { - // --- LOGIKA BELI LANGSUNG (Single Item) --- + // --- LOGIKA BELI LANGSUNG --- $produk = Produk::findOrFail($request->produk_id); $total_harga = $produk->harga * $request->jumlah; @@ -97,65 +120,64 @@ public function prosesCheckout(Request $request) $produk->decrement('stok', $request->jumlah); } else { - // --- LOGIKA KERANJANG (Cart) --- - $cart = session()->get('cart'); - - // Kelompokkan produk berdasarkan Petani ID - $cartItems = []; - foreach ($cart as $id => $details) { - $produk = Produk::find($id); - if ($produk) { - $cartItems[$produk->petani_id][] = [ - 'produk' => $produk, - 'qty' => $details['quantity'] - ]; - } + // --- LOGIKA KERANJANG (DATABASE) --- + if (!$request->cart_ids) { + throw new \Exception("ID keranjang tidak ditemukan."); } - foreach ($cartItems as $petani_id => $items) { - $subtotal_transaksi = 0; - $kode_invoice = 'INV/' . date('Ymd') . '/' . rand(1000, 9999); + $cartIds = explode(',', $request->cart_ids); + + $cartItems = Cart::with('produk') + ->whereIn('id', $cartIds) + ->where('pembeli_id', $pembeli_id) + ->get(); - // Membuat Header Transaksi per Petani + // Kelompokkan produk berdasarkan Petani ID agar Invoice terpisah per toko + $groupedByPetani = []; + foreach ($cartItems as $item) { + $groupedByPetani[$item->produk->petani_id][] = $item; + } + + foreach ($groupedByPetani as $petani_id => $items) { $transaksi = Transaksi::create([ 'pembeli_id' => $pembeli_id, 'petani_id' => $petani_id, 'tanggal_transaksi' => now(), 'alamat_pengiriman' => $request->alamat_pengiriman, - 'total_harga' => 0, + 'total_harga' => 0, // Diupdate setelah menghitung subtotal 'status' => 'menunggu konfirmasi', - 'kode_invoice' => $kode_invoice, + 'kode_invoice' => 'INV/' . date('Ymd') . '/' . rand(1000, 9999), ]); + $subtotal_transaksi = 0; foreach ($items as $item) { - $produk = $item['produk']; - $qty = $item['qty']; - $total_per_item = $produk->harga * $qty; + $total_per_item = $item->produk->harga * $item->quantity; $subtotal_transaksi += $total_per_item; DetailTransaksi::create([ 'transaksi_id' => $transaksi->id, - 'produk_id' => $produk->id, - 'jumlah' => $qty, - 'harga_satuan' => $produk->harga, + 'produk_id' => $item->produk->id, + 'jumlah' => $item->quantity, + 'harga_satuan' => $item->produk->harga, 'subtotal' => $total_per_item, ]); - $produk->decrement('stok', $qty); + $item->produk->decrement('stok', $item->quantity); } - // Update total harga transaksi + // Update total harga transaksi per petani $transaksi->update(['total_harga' => $subtotal_transaksi]); } - session()->forget('cart'); + // OTOMATIS BERSIHKAN ITEM KERANJANG YANG SUDAH DIBELI + Cart::whereIn('id', $cartIds)->delete(); } }); - return redirect()->route('pesanan.saya')->with('success', 'Pesanan berhasil dibuat! Menunggu konfirmasi petani.'); + return redirect()->route('pesanan.saya')->with('success', 'Pesanan berhasil dibuat! Silakan pantau status pesanan Anda.'); } - // Riwayat Pesanan + // Riwayat Pesanan Pembeli public function pesananSaya() { $transaksis = Transaksi::with(['detailTransaksis.produk.petani']) @@ -172,11 +194,10 @@ public function konfirmasiSelesai($id) $transaksi = Transaksi::where('pembeli_id', Auth::guard('pembeli')->id()) ->findOrFail($id); - // Hanya bisa selesai jika status sebelumnya 'dikirim' if ($transaksi->status == 'dikirim') { $transaksi->status = 'selesai'; $transaksi->save(); - return back()->with('success', 'Terima kasih! Pesanan telah diselesaikan.'); + return back()->with('success', 'Terima kasih! Pesanan telah selesai.'); } return back()->with('error', 'Pesanan belum dikirim atau sudah selesai.'); @@ -185,7 +206,7 @@ public function konfirmasiSelesai($id) // --- FITUR PETANI --- - // Daftar Pesanan Masuk + // Daftar Pesanan Masuk untuk Dashboard Petani public function pesananMasuk() { $petaniId = Auth::guard('petani')->id(); @@ -200,7 +221,7 @@ public function pesananMasuk() return view('petani.pesanan.index', compact('pesanans')); } - // Update Status (Terima/Tolak/Kirim) + // Update Status Pesanan oleh Petani public function updateStatus(Request $request, $id) { $transaksi = Transaksi::findOrFail($id); @@ -212,8 +233,9 @@ public function updateStatus(Request $request, $id) $transaksi->status = $request->status; $transaksi->save(); + // Jika dibatalkan, kembalikan stok produk if ($request->status == 'batal') { - foreach ($transaksi->details as $detail) { + foreach ($transaksi->detailTransaksis as $detail) { $detail->produk->increment('stok', $detail->jumlah); } } @@ -221,12 +243,11 @@ public function updateStatus(Request $request, $id) return back()->with('success', 'Status pesanan berhasil diperbarui.'); } - // Detail Pesanan (Petani) + // Detail Pesanan untuk Sisi Petani public function pesananDetail($id) { $petaniId = Auth::guard('petani')->id(); - // Ambil transaksi berdasarkan ID $pesanan = Transaksi::whereHas('detailTransaksis.produk', function ($q) use ($petaniId) { $q->where('petani_id', $petaniId); }) @@ -235,4 +256,4 @@ public function pesananDetail($id) return view('petani.pesanan.detail', compact('pesanan')); } -} +} \ No newline at end of file diff --git a/app/Http/Controllers/WilayahController.php b/app/Http/Controllers/WilayahController.php new file mode 100644 index 0000000..bdbfe7a --- /dev/null +++ b/app/Http/Controllers/WilayahController.php @@ -0,0 +1,29 @@ +code)->get(); + return response()->json($kota); + } + + public function getKecamatan(Request $request) + { + $kecamatan = District::where('city_code', $request->code)->get(); + return response()->json($kecamatan); + } + + public function getDesa(Request $request) + { + $desa = Village::where('district_code', $request->code)->get(); + return response()->json($desa); + } +} \ No newline at end of file diff --git a/app/Models/Produk.php b/app/Models/Produk.php index e5ac3a5..70b9638 100644 --- a/app/Models/Produk.php +++ b/app/Models/Produk.php @@ -17,7 +17,11 @@ class Produk extends Model 'harga', 'stok', 'deskripsi', - 'foto_produk' + 'foto_produk', + 'provinsi_code', + 'kota_code', + 'kecamatan_code', + 'desa_code', ]; public function petani() diff --git a/composer.json b/composer.json index 44c6054..17f22e1 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,8 @@ "require": { "php": "^8.2", "laravel/framework": "^12.0", - "laravel/tinker": "^2.10.1" + "laravel/tinker": "^2.10.1", + "laravolt/indonesia": "^0.39.0" }, "require-dev": { "fakerphp/faker": "^1.23", diff --git a/composer.lock b/composer.lock index 6efa171..f6c5f78 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c514d8f7b9fc5970bdd94287905ef584", + "content-hash": "766a52f13bbfa552b799835b6f5f3e18", "packages": [ { "name": "brick/math", @@ -1457,6 +1457,88 @@ }, "time": "2025-01-27T14:24:01+00:00" }, + { + "name": "laravolt/indonesia", + "version": "v0.39", + "source": { + "type": "git", + "url": "https://github.com/laravolt/indonesia.git", + "reference": "351e1c0e69b9415b0a56e03677fcfe0bbeca513a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravolt/indonesia/zipball/351e1c0e69b9415b0a56e03677fcfe0bbeca513a", + "reference": "351e1c0e69b9415b0a56e03677fcfe0bbeca513a", + "shasum": "" + }, + "require": { + "illuminate/support": "^8.0|^9.0|^10.0|^11.0|^12.0", + "php": "^7.3|^8.0" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^7.0|^8.0|^9.0|^10.0", + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^9.0|^10.5|^11.5.3" + }, + "suggest": { + "laravolt/suitable": "Required if you want to access editor panel", + "spatie/geocoder": "Synchronize latitude longitude data directly using Google's Geocoding Service" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Indonesia": "Laravolt\\Indonesia\\Facade" + }, + "providers": [ + "Laravolt\\Indonesia\\ServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Laravolt\\Indonesia\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bayu Hendra Winata", + "email": "bayu.hendra@javan.co.id" + }, + { + "name": "Akbar Adhatama", + "email": "am.adhatama@gmail.com" + }, + { + "name": "Deri Ramdani", + "email": "deri.ramdani1@gmail.com" + } + ], + "description": "Package Laravel yang berisi data Provinsi, Kabupaten/Kota, Kecamatan, dan Keluarahan/Desa di seluruh Indonesia.", + "keywords": [ + "desa", + "indonesia", + "kabupaten", + "kecamatan", + "kelurahan", + "kota", + "laravel", + "laravolt", + "provinsi" + ], + "support": { + "issues": "https://github.com/laravolt/indonesia/issues", + "source": "https://github.com/laravolt/indonesia/tree/v0.39" + }, + "time": "2026-01-03T13:26:02+00:00" + }, { "name": "league/commonmark", "version": "2.7.1", diff --git a/config/laravolt/indonesia.php b/config/laravolt/indonesia.php new file mode 100644 index 0000000..24cd1dd --- /dev/null +++ b/config/laravolt/indonesia.php @@ -0,0 +1,24 @@ + 'indonesia_', + 'route' => [ + 'enabled' => false, + 'middleware' => ['web', 'auth'], + 'prefix' => 'indonesia', + ], + 'view' => [ + 'layout' => 'ui::layouts.app', + ], + 'menu' => [ + 'enabled' => false, + ], + 'cache' => [ + 'ttl' => env('INDONESIA_CACHE_TTL', 3600), + 'prefix' => env('INDONESIA_CACHE_PREFIX', 'indonesia_service'), + 'store' => env('INDONESIA_CACHE_STORE', 'redis'), + ], + 'database' => [ + 'connection' => env('INDONESIA_DB_CONNECTION', null), + ], +]; diff --git a/database/migrations/2016_08_03_072729_create_provinces_table.php b/database/migrations/2016_08_03_072729_create_provinces_table.php new file mode 100644 index 0000000..d416d57 --- /dev/null +++ b/database/migrations/2016_08_03_072729_create_provinces_table.php @@ -0,0 +1,42 @@ +connection())->create(config('laravolt.indonesia.table_prefix').'provinces', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->char('code', 2)->unique(); + $table->string('name', 255); + $table->text('meta')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop(config('laravolt.indonesia.table_prefix').'provinces'); + } +} diff --git a/database/migrations/2016_08_03_072750_create_cities_table.php b/database/migrations/2016_08_03_072750_create_cities_table.php new file mode 100644 index 0000000..78c29e3 --- /dev/null +++ b/database/migrations/2016_08_03_072750_create_cities_table.php @@ -0,0 +1,48 @@ +connection())->create(config('laravolt.indonesia.table_prefix').'cities', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->char('code', 4)->unique(); + $table->char('province_code', 2); + $table->string('name', 255); + $table->text('meta')->nullable(); + $table->timestamps(); + + $table->foreign('province_code') + ->references('code') + ->on(config('laravolt.indonesia.table_prefix').'provinces') + ->onUpdate('cascade')->onDelete('restrict'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop(config('laravolt.indonesia.table_prefix').'cities'); + } +} diff --git a/database/migrations/2016_08_03_072804_create_districts_table.php b/database/migrations/2016_08_03_072804_create_districts_table.php new file mode 100644 index 0000000..451478f --- /dev/null +++ b/database/migrations/2016_08_03_072804_create_districts_table.php @@ -0,0 +1,48 @@ +connection())->create(config('laravolt.indonesia.table_prefix').'districts', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->char('code', 7)->unique(); + $table->char('city_code', 4); + $table->string('name', 255); + $table->text('meta')->nullable(); + $table->timestamps(); + + $table->foreign('city_code') + ->references('code') + ->on(config('laravolt.indonesia.table_prefix').'cities') + ->onUpdate('cascade')->onDelete('restrict'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop(config('laravolt.indonesia.table_prefix').'districts'); + } +} diff --git a/database/migrations/2016_08_03_072819_create_villages_table.php b/database/migrations/2016_08_03_072819_create_villages_table.php new file mode 100644 index 0000000..14eea55 --- /dev/null +++ b/database/migrations/2016_08_03_072819_create_villages_table.php @@ -0,0 +1,48 @@ +connection())->create(config('laravolt.indonesia.table_prefix').'villages', function (Blueprint $table) { + $table->bigIncrements('id'); + $table->char('code', 10)->unique(); + $table->char('district_code', 7); + $table->string('name', 255); + $table->text('meta')->nullable(); + $table->timestamps(); + + $table->foreign('district_code') + ->references('code') + ->on(config('laravolt.indonesia.table_prefix').'districts') + ->onUpdate('cascade')->onDelete('restrict'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop(config('laravolt.indonesia.table_prefix').'villages'); + } +} diff --git a/database/migrations/2026_03_01_125919_add_lokasi_to_produks_table.php b/database/migrations/2026_03_01_125919_add_lokasi_to_produks_table.php new file mode 100644 index 0000000..1ad90c0 --- /dev/null +++ b/database/migrations/2026_03_01_125919_add_lokasi_to_produks_table.php @@ -0,0 +1,29 @@ +dropColumn('lokasi'); + } + + $table->char('provinsi_code', 2)->nullable()->after('deskripsi'); + $table->char('kota_code', 4)->nullable()->after('provinsi_code'); + $table->char('kecamatan_code', 7)->nullable()->after('kota_code'); + $table->char('desa_code', 10)->nullable()->after('kecamatan_code'); + }); + } + + public function down(): void + { + Schema::table('produks', function (Blueprint $table) { + $table->dropColumn(['provinsi_code', 'kota_code', 'kecamatan_code', 'desa_code']); + $table->string('lokasi')->nullable(); + }); + } +}; \ No newline at end of file diff --git a/database/seeders/TransaksiSeeder.php b/database/seeders/TransaksiSeeder.php index 9ee9983..c8ab4fb 100644 --- a/database/seeders/TransaksiSeeder.php +++ b/database/seeders/TransaksiSeeder.php @@ -69,7 +69,7 @@ public function run(): void 'kode_invoice' => 'INV-' . $tahunIni . '03-003', 'pembeli_id' => 1, 'petani_id' => 1, - 'tanggal_transaksi' => Carbon::create($tahunIni, 3, 5, 9, 15, 0), + 'tanggal_transaksi' => Carbon::create($tahunIni, 1, 5, 9, 15, 0), 'alamat_pengiriman' => 'Perumahan Indah Blok C2, Surabaya', 'total_harga' => 150000, 'status' => 'selesai', diff --git a/public/template/frontend/img/testimonial-1.jpg b/public/template/frontend/img/.jpg similarity index 100% rename from public/template/frontend/img/testimonial-1.jpg rename to public/template/frontend/img/.jpg diff --git a/public/template/frontend/img/best-product-4.jpg b/public/template/frontend/img/no-image.jpg similarity index 100% rename from public/template/frontend/img/best-product-4.jpg rename to public/template/frontend/img/no-image.jpg diff --git a/resources/views/landing/checkout.blade.php b/resources/views/landing/checkout.blade.php index 20ff068..82a3266 100644 --- a/resources/views/landing/checkout.blade.php +++ b/resources/views/landing/checkout.blade.php @@ -79,6 +79,7 @@ Kembali + diff --git a/resources/views/landing/home.blade.php b/resources/views/landing/home.blade.php index 9af55ef..cdbb7e7 100644 --- a/resources/views/landing/home.blade.php +++ b/resources/views/landing/home.blade.php @@ -4,45 +4,39 @@ @section('content') -
- Platform langsung yang menghubungkan petani padi lokal dengan pembeli. - Dapatkan harga gabah terbaik dan gabah berkualitas. -
-
- + Platform langsung yang menghubungkan petani padi lokal dengan pembeli. + Dapatkan harga gabah terbaik dan gabah berkualitas. +
+ + Belanja + +
+ Armada pickup siap kirim langsung ke lokasi Anda.
+Armada pickup siap kirim langsung ke lokasi Anda.
Harga tangan pertama langsung tanpa tengkulak.
+Harga tangan pertama langsung tanpa tengkulak.
Jaminan padi berkualitas, bulir utuh, bersih, dan bebas campuran.
+Jaminan padi berkualitas, bulir utuh, bersih, dan bebas campuran.
Pembayaran fleksibel, bisa transfer atau COD.
+Pembayaran fleksibel, bisa transfer atau COD.
Pilihan favorit pelanggan kami minggu ini.
-Pilihan favorit pelanggan kami minggu ini.
+
-
+ - {{ Str::limit($item->deskripsi, 50) }} +
+ {{ Str::limit($item->deskripsi, 50) }} +
+ +Belum ada data penjualan.
-Belum ada data penjualan.
+Petani Mitra
+Transaksi
+Rating Rata-rata
+Garansi Kualitas
+Petani Mitra
-Transaksi
-Rating Rata-rata
-Garansi Kualitas
-Pilih varietas gabah yang Anda butuhkan hari ini.
+Pilih varietas gabah yang Anda butuhkan hari ini.
-- Kami melayani kerjasama untuk penggilingan padi, restoran, dan toko - kelontong dengan harga grosir spesial. -
- - Hubungi Kami - -+ Kami melayani kerjasama untuk penggilingan padi, restoran, dan toko + kelontong dengan harga grosir spesial. +
+ + Hubungi Kami + +