feat: add admin dashboard, profile management, and redesign auth ui

This commit is contained in:
sayasilvi 2025-12-10 01:38:47 +07:00
parent 046365a1d6
commit 0ff4a9c42e
18 changed files with 735 additions and 197 deletions

View File

@ -3,13 +3,36 @@
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Petani; // Wajib import Model Petani
use App\Models\Petani;
use App\Models\Produk;
use App\Models\Transaksi;
class AdminController extends Controller
{
public function dashboard()
{
return view('admin.dashboard');
$totalPetani = Petani::where('status_akun', 'aktif')->count();
$petaniPending = Petani::where('status_akun', 'menunggu')->count();
$totalProduk = Produk::count();
$totalTransaksi = Transaksi::count();
$transaksiTerbaru = Transaksi::with(['pembeli', 'details'])->latest()->take(5)->get();
return view('admin.dashboard', compact(
'totalPetani',
'petaniPending',
'totalProduk',
'totalTransaksi',
'transaksiTerbaru'
));
}
public function monitoring()
{
$produks = Produk::with('petani')->latest()->paginate(10);
$transaksis = Transaksi::with(['pembeli'])->latest()->paginate(10);
return view('admin.monitoring', compact('produks', 'transaksis'));
}
public function verifikasiIndex()

View File

@ -21,6 +21,9 @@ public function loginProcess(Request $request)
$request->validate([
'username' => 'required',
'password' => 'required',
], [
'username.required' => 'Username wajib diisi',
'password.required' => 'Password wajib diisi',
]);
$credentials = $request->only('username', 'password');
@ -31,34 +34,33 @@ public function loginProcess(Request $request)
return redirect()->intended('admin/dashboard');
}
// Cek Login PEMBELI
if (Auth::guard('pembeli')->attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/'); // Ke Halaman Utama (Landing)
}
// Cek Login PETANI
$petani = Petani::where('username', $request->username)->first();
// Jika username ada & password cocok
if ($petani && Hash::check($request->password, $petani->password)) {
// Cek Status Akun
// Validasi Status Akun Petani
if ($petani->status_akun == 'menunggu') {
return back()->withErrors(['username' => 'Akun Anda masih MENUNGGU persetujuan Admin.']);
return back()->withErrors(['login_error' => 'Akun Anda masih dalam proses verifikasi Admin.']);
}
if ($petani->status_akun == 'ditolak') {
return back()->withErrors(['username' => 'Maaf, pendaftaran Anda DITOLAK oleh Admin.']);
return back()->withErrors(['login_error' => 'Pendaftaran Anda ditolak. Silakan hubungi Admin.']);
}
// Jika status Aktif, baru izinkan login
Auth::guard('petani')->login($petani);
$request->session()->regenerate();
return redirect()->intended('petani/dashboard');
}
// Cek Login PEMBELI
if (Auth::guard('pembeli')->attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('/'); // Ke Landing Page
}
return back()->withErrors([
'username' => 'Username atau password salah.',
]);
'login_error' => 'Username atau password salah, atau akun tidak ditemukan.',
])->withInput($request->only('username'));
}
public function showRegisterForm()
@ -68,13 +70,12 @@ public function showRegisterForm()
public function registerProcess(Request $request)
{
// Validasi
$request->validate([
'role' => 'required|in:petani,pembeli',
'nama_lengkap' => 'required',
'username' => 'required|unique:petanis,username|unique:pembelis,username',
'username' => 'required|unique:petanis,username|unique:pembelis,username|alpha_dash',
'password' => 'required|min:6',
'no_hp' => 'required',
'no_hp' => 'required|numeric',
'alamat' => 'required',
]);
@ -85,11 +86,11 @@ public function registerProcess(Request $request)
'password' => Hash::make($request->password),
'no_hp' => $request->no_hp,
'alamat' => $request->alamat,
'nama_usaha' => $request->nama_usaha,
'nama_usaha' => $request->nama_usaha ?? 'Toko Tani ' . $request->nama_lengkap,
'status_akun' => 'menunggu'
]);
return redirect('/login')->with('success', 'Pendaftaran Berhasil! Tunggu verifikasi Admin untuk Login.');
return redirect('/login')->with('success', 'Registrasi Petani Berhasil! Mohon tunggu verifikasi Admin.');
} else {
Pembeli::create([
@ -100,15 +101,16 @@ public function registerProcess(Request $request)
'alamat' => $request->alamat,
]);
return redirect('/login')->with('success', 'Pendaftaran Berhasil! Silakan Login.');
return redirect('/login')->with('success', 'Registrasi Berhasil! Silakan Login.');
}
}
public function logout(Request $request)
{
// Logout semua guard untuk keamanan
if (Auth::guard('admin')->check()) Auth::guard('admin')->logout();
elseif (Auth::guard('petani')->check()) Auth::guard('petani')->logout();
elseif (Auth::guard('pembeli')->check()) Auth::guard('pembeli')->logout();
if (Auth::guard('petani')->check()) Auth::guard('petani')->logout();
if (Auth::guard('pembeli')->check()) Auth::guard('pembeli')->logout();
$request->session()->invalidate();
$request->session()->regenerateToken();

View File

@ -0,0 +1,89 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;
class ProfileController extends Controller
{
// --- FITUR PETANI ---
public function editPetani()
{
$user = Auth::guard('petani')->user();
return view('petani.profile', compact('user'));
}
public function updatePetani(Request $request)
{
$user = Auth::guard('petani')->user();
$request->validate([
'nama_lengkap' => 'required|string|max:255',
'email' => 'required|email|unique:petanis,email,' . $user->id,
'password' => 'nullable|min:6|confirmed',
'foto' => 'nullable|image|max:2048'
]);
$user->nama_lengkap = $request->nama_lengkap;
$user->email = $request->email;
if ($request->filled('password')) {
$user->password = Hash::make($request->password);
}
if ($request->hasFile('foto')) {
if ($user->foto && Storage::exists('public/' . $user->foto)) {
Storage::delete('public/' . $user->foto);
}
$path = $request->file('foto')->store('avatars', 'public');
$user->foto = $path;
}
$user->save();
return back()->with('success', 'Profil berhasil diperbarui!');
}
// --- FITUR PEMBELI ---
public function editPembeli()
{
$user = Auth::guard('pembeli')->user();
return view('landing.profile', compact('user'));
}
public function updatePembeli(Request $request)
{
$user = Auth::guard('pembeli')->user();
$request->validate([
'nama_lengkap' => 'required|string|max:255',
'email' => 'required|email|unique:pembelis,email,' . $user->id,
'no_hp' => 'required|string',
'alamat' => 'required|string',
'password' => 'nullable|min:6|confirmed',
'foto' => 'nullable|image|max:2048'
]);
$user->nama_lengkap = $request->nama_lengkap;
$user->email = $request->email;
$user->no_hp = $request->no_hp;
$user->alamat = $request->alamat;
if ($request->filled('password')) {
$user->password = Hash::make($request->password);
}
if ($request->hasFile('foto')) {
if ($user->foto && Storage::exists('public/' . $user->foto)) {
Storage::delete('public/' . $user->foto);
}
$path = $request->file('foto')->store('avatars', 'public');
$user->foto = $path;
}
$user->save();
return back()->with('success', 'Profil berhasil diperbarui!');
}
}

View File

@ -14,6 +14,7 @@ class Pembeli extends Authenticatable
protected $fillable = [
'nama_lengkap',
'username',
'email',
'password',
'no_hp',
'alamat'

View File

@ -14,6 +14,7 @@ class Petani extends Authenticatable
protected $fillable = [
'nama_lengkap',
'username',
'email',
'password',
'no_hp',
'alamat',

View File

@ -10,22 +10,21 @@
* Run the migrations.
*/
public function up(): void
{
Schema::create('petanis', function (Blueprint $table) {
$table->id();
$table->string('nama_lengkap');
$table->string('username')->unique();
$table->string('password');
$table->string('no_hp', 15);
$table->text('alamat');
$table->string('nama_usaha')->nullable();
// Status Verifikasi
$table->enum('status_akun', ['menunggu', 'aktif', 'ditolak'])->default('menunggu');
$table->timestamps();
});
}
{
Schema::create('petanis', function (Blueprint $table) {
$table->id();
$table->string('nama_lengkap');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->string('foto')->nullable();
$table->string('no_hp', 15);
$table->text('alamat');
$table->string('nama_usaha')->nullable();
$table->enum('status_akun', ['menunggu', 'aktif', 'ditolak'])->default('menunggu');
$table->timestamps();
});
}
/**
* Reverse the migrations.

View File

@ -10,17 +10,19 @@
* Run the migrations.
*/
public function up(): void
{
Schema::create('pembelis', function (Blueprint $table) {
$table->id();
$table->string('nama_lengkap');
$table->string('username')->unique();
$table->string('password');
$table->string('no_hp', 15);
$table->text('alamat');
$table->timestamps();
});
}
{
Schema::create('pembelis', function (Blueprint $table) {
$table->id();
$table->string('nama_lengkap');
$table->string('username')->unique();
$table->string('email')->unique();
$table->string('password');
$table->string('foto')->nullable();
$table->string('no_hp', 15);
$table->text('alamat');
$table->timestamps();
});
}
/**
* Reverse the migrations.

View File

@ -17,6 +17,7 @@ public function run(): void
[
'nama_lengkap' => 'Andi Pembeli',
'username' => 'andi_beli',
'email' => 'andiwibu@gmail.com',
'password' => Hash::make('password123'),
'no_hp' => '081298765432',
'alamat' => 'Jl. Merdeka No. 45, Kota Sejahtera',
@ -26,6 +27,7 @@ public function run(): void
[
'nama_lengkap' => 'Rina Suka Sayur',
'username' => 'rina_sayur',
'email' => 'rinauhuy@gmail.com',
'password' => Hash::make('password123'),
'no_hp' => '085612345678',
'alamat' => 'Perumahan Griya Asri Blok B2, Desa Sukamaju',

View File

@ -17,6 +17,7 @@ public function run(): void
DB::table('petanis')->insert([
'nama_lengkap' => 'Budi Santoso',
'username' => 'budi_tani',
'email' => 'budisantoso@gmail.com',
'password' => Hash::make('password123'),
'no_hp' => '081234567890',
'alamat' => 'Jl. Raya Desa Sukamaju No. 12',
@ -30,6 +31,7 @@ public function run(): void
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',
@ -43,6 +45,7 @@ public function run(): void
DB::table('petanis')->insert([
'nama_lengkap' => 'Joko Widodo',
'username' => 'joko_tani',
'email' => 'wiwokdetok@gmail.com',
'password' => Hash::make('password123'),
'no_hp' => '089876543210',
'alamat' => 'Jl. Buntu No. 99',

View File

@ -1,23 +1,126 @@
@extends('layouts.admin')
@section('title', 'Dashboard Admin')
@section('page-title', 'Dashboard Admin Desa')
@section('page-title', 'Overview Sistem')
@section('content')
<div class="card">
<div class="card-header">
<h4>Selamat Datang, {{ Auth::guard('admin')->user()->nama }}!</h4>
</div>
<div class="card-body">
<p>Anda login sebagai Administrator Desa.</p>
<div class="alert alert-light-primary color-primary">
<i class="bi bi-info-circle"></i> Silakan cek menu <strong>Verifikasi Petani</strong> untuk melihat pendaftaran baru.
<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>
</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>
</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>
</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">
<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">
<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>
<a href="{{ route('admin.verifikasi.index') }}" class="btn btn-primary mt-3">
<i class="bi bi-person-check-fill"></i> Buka Halaman Verifikasi
</a>
{{-- 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>
</div>
</section>
@endsection

View File

@ -0,0 +1,78 @@
@extends('layouts.admin')
@section('title', 'Monitoring Sistem')
@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>
{{ $transaksis->links() }}
</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>
</div>
</div>
</div>
@endsection

View File

@ -1,61 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - TaniDesa</title>
<link rel="stylesheet" href="{{ asset('template/admin/compiled/css/app.css') }}">
<link rel="stylesheet" href="{{ asset('template/admin/compiled/css/auth.css') }}">
<title>Masuk - TaniDesa</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>
body {
background-color: #f4f6f9;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.card-auth {
width: 100%;
max-width: 400px;
border: none;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0,0,0,0.05);
}
.form-control:focus {
border-color: #81c408; /* Warna Hijau Frontend */
box-shadow: 0 0 0 0.25rem rgba(129, 196, 8, 0.25);
}
.btn-tani {
background-color: #81c408;
border-color: #81c408;
color: white;
font-weight: 600;
}
.btn-tani:hover {
background-color: #6da705;
color: white;
}
.text-tani {
color: #81c408;
}
</style>
</head>
<body>
<div id="auth">
<div class="row h-100">
<div class="col-lg-5 col-12">
<div id="auth-left">
<div class="auth-logo">
<a href="{{ url('/') }}"><h3 class="fw-bold">TaniDesa</h3></a>
</div>
<h3 class="fw-bold text-center">Log in</h3>
{{-- Pesan Sukses Register --}}
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
{{-- Pesan Error Login --}}
@if ($errors->any())
<div class="alert alert-danger">
<ul class="mb-0">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('login.proses') }}" method="POST">
@csrf
<div class="form-group position-relative has-icon-left mb-4">
<input type="text" name="username" class="form-control " placeholder="Username">
<div class="form-control-icon"><i class="bi bi-person"></i></div>
</div>
<div class="form-group position-relative has-icon-left mb-4">
<input type="password" name="password" class="form-control " placeholder="Password">
<div class="form-control-icon"><i class="bi bi-shield-lock"></i></div>
</div>
<button class="btn btn-primary btn-block btn-md shadow-md mt-5">Masuk</button>
</form>
<div class="text-center mt-5 text-md fs-6">
<p class="text-gray-600">Belum punya akun? <a href="{{ route('register') }}" class="font-bold">Daftar</a>.</p>
</div>
</div>
<div class="card card-auth bg-white p-4">
<div class="card-body">
<div class="text-center mb-4">
<a href="{{ url('/') }}" class="text-decoration-none">
<h1 class="text-tani display-6 fw-bold">TaniDesa</h1>
</a>
<p class="text-muted">Masuk untuk melanjutkan</p>
</div>
<div class="col-lg-7 d-none d-lg-block">
<div id="auth-right">
{{-- Pesan Sukses --}}
@if (session('success'))
<div class="alert alert-success py-2" role="alert">
<small>{{ session('success') }}</small>
</div>
@endif
{{-- Pesan Error --}}
@if ($errors->any())
<div class="alert alert-danger py-2">
<ul class="mb-0 ps-3 small">
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<form action="{{ route('login.proses') }}" method="POST">
@csrf
<div class="mb-3">
<label class="form-label text-muted small">Username</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="fas fa-user text-muted"></i></span>
<input type="text" name="username" class="form-control border-start-0 ps-0" placeholder="Masukkan username" required>
</div>
</div>
<div class="mb-4">
<label class="form-label text-muted small">Password</label>
<div class="input-group">
<span class="input-group-text bg-light border-end-0"><i class="fas fa-lock text-muted"></i></span>
<input type="password" name="password" class="form-control border-start-0 ps-0" placeholder="Masukkan password" required>
</div>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-tani rounded-pill py-2">MASUK</button>
</div>
</form>
<div class="text-center mt-4">
<small class="text-muted">Belum punya akun? <a href="{{ route('register') }}" class="text-tani fw-bold text-decoration-none">Daftar</a></small>
</div>
</div>
</div>
</body>
</html>

View File

@ -1,72 +1,117 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Daftar - TaniDesa</title>
<link rel="stylesheet" href="{{ asset('template/admin/compiled/css/app.css') }}">
<link rel="stylesheet" href="{{ asset('template/admin/compiled/css/auth.css') }}">
<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>
body {
background-color: #f4f6f9;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px 0;
}
.card-auth {
width: 100%;
max-width: 500px; /* Sedikit lebih lebar */
border: none;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0,0,0,0.05);
}
.form-control:focus, .form-select:focus {
border-color: #81c408;
box-shadow: 0 0 0 0.25rem rgba(129, 196, 8, 0.25);
}
.btn-tani {
background-color: #81c408;
border-color: #81c408;
color: white;
font-weight: 600;
}
.btn-tani:hover {
background-color: #6da705;
color: white;
}
.text-tani {
color: #81c408;
}
.bg-tani-light {
background-color: #eef8d8;
color: #4c7a04;
}
</style>
</head>
<body>
<div id="auth">
<div class="row h-100">
<div class="col-lg-6 col-12 mx-auto">
<div id="auth-left">
<h1 class="auth-title">Daftar.</h1>
<p class="auth-subtitle mb-4">Bergabunglah dengan komunitas TaniDesa.</p>
<form action="{{ route('register.proses') }}" method="POST">
@csrf
<div class="form-group mb-3">
<label class="fw-bold">Saya ingin mendaftar sebagai:</label>
<select name="role" id="role" class="form-select" onchange="toggleForm()">
<option value="pembeli">Pembeli (Ingin Belanja)</option>
<option value="petani">Petani (Ingin Jualan)</option>
</select>
</div>
<div class="card card-auth bg-white p-4">
<div class="card-body">
<div class="text-center mb-4">
<a href="{{ url('/') }}" class="text-decoration-none">
<h2 class="text-tani fw-bold">Daftar Akun</h2>
</a>
<p class="text-muted small">Bergabunglah dengan TaniDesa</p>
</div>
<div class="form-group position-relative has-icon-left mb-3">
<input type="text" name="nama_lengkap" class="form-control" placeholder="Nama Lengkap" required>
<div class="form-control-icon"><i class="bi bi-person"></i></div>
</div>
<form action="{{ route('register.proses') }}" method="POST">
@csrf
{{-- Pilihan Role --}}
<div class="mb-3">
<label class="form-label small fw-bold text-muted">Daftar Sebagai</label>
<select name="role" id="role" class="form-select text-center fw-bold" onchange="toggleForm()" style="cursor: pointer;">
<option value="pembeli">👤 Pembeli (Ingin Belanja)</option>
<option value="petani">🌾 Petani (Ingin Jualan)</option>
</select>
</div>
<div class="form-group position-relative has-icon-left mb-3">
<input type="text" name="username" class="form-control" placeholder="Username" required>
<div class="form-control-icon"><i class="bi bi-person-badge"></i></div>
</div>
<div class="form-group position-relative has-icon-left mb-3">
<input type="password" name="password" class="form-control" placeholder="Password" required>
<div class="form-control-icon"><i class="bi bi-shield-lock"></i></div>
</div>
<div class="form-group position-relative has-icon-left mb-3">
<input type="number" name="no_hp" class="form-control" placeholder="No HP / WA" required>
<div class="form-control-icon"><i class="bi bi-telephone"></i></div>
</div>
<div class="form-group position-relative has-icon-left mb-3">
<textarea name="alamat" class="form-control" placeholder="Alamat Lengkap" required></textarea>
<div class="form-control-icon"><i class="bi bi-geo-alt"></i></div>
</div>
{{-- Input Khusus Petani (Hidden Awal) --}}
<div id="form-petani" style="display: none;">
<div class="form-group position-relative has-icon-left mb-3">
<input type="text" name="nama_usaha" class="form-control" placeholder="Nama Usaha / Toko Tani">
<div class="form-control-icon"><i class="bi bi-shop"></i></div>
</div>
<div class="alert alert-warning py-2"><small>Akun Petani butuh verifikasi Admin.</small></div>
</div>
<button class="btn btn-primary btn-block btn-lg shadow-lg mt-3">Daftar Sekarang</button>
</form>
<div class="text-center mt-4">
<p class="text-gray-600">Sudah punya akun? <a href="{{ route('login') }}" class="font-bold">Login</a>.</p>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label small text-muted">Nama Lengkap</label>
<input type="text" name="nama_lengkap" class="form-control" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label small text-muted">Username</label>
<input type="text" name="username" class="form-control" required>
</div>
</div>
<div class="mb-3">
<label class="form-label small text-muted">Password</label>
<input type="password" name="password" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label small text-muted">Nomor HP / WA</label>
<input type="number" name="no_hp" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label small text-muted">Alamat Lengkap</label>
<textarea name="alamat" class="form-control" rows="2" required></textarea>
</div>
{{-- Input Khusus Petani --}}
<div id="form-petani" style="display: none;" class="bg-tani-light p-3 rounded mb-3 border border-success">
<label class="form-label small fw-bold"><i class="fas fa-store me-1"></i> Nama Toko / Usaha Tani</label>
<input type="text" name="nama_usaha" class="form-control" placeholder="Contoh: Sayur Segar Pak Budi">
<small class="d-block mt-2" style="font-size: 11px;">*Akun petani memerlukan verifikasi Admin sebelum bisa login.</small>
</div>
<div class="d-grid gap-2 mt-4">
<button type="submit" class="btn btn-tani rounded-pill py-2">DAFTAR SEKARANG</button>
</div>
</form>
<div class="text-center mt-4">
<small class="text-muted">Sudah punya akun? <a href="{{ route('login') }}" class="text-tani fw-bold text-decoration-none">Login</a></small>
</div>
</div>
</div>

View File

@ -0,0 +1,82 @@
@extends('layouts.frontend')
@section('title', 'Profil Saya')
@section('content')
<div class="container py-5 mt-5">
<div class="row justify-content-center">
<div class="col-lg-8">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white py-3">
<h4 class="mb-0 fw-bold">Edit Profil</h4>
</div>
<div class="card-body p-4">
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<form action="{{ route('pembeli.profile.update') }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-4 text-center mb-4">
<img src="{{ $user->foto ? asset('storage/' . $user->foto) : asset('template/frontend/img/avatar.jpg') }}"
class="rounded-circle img-thumbnail mb-3"
style="width: 150px; height: 150px; object-fit: cover;">
<div>
<label class="btn btn-sm btn-outline-secondary">
<i class="fas fa-camera me-1"></i> Ubah Foto
<input type="file" name="foto" hidden accept="image/*">
</label>
</div>
</div>
<div class="col-md-8">
<div class="mb-3">
<label class="form-label fw-bold">Nama Lengkap</label>
<input type="text" name="nama_lengkap" class="form-control"
value="{{ $user->nama_lengkap }}" required>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Email</label>
<input type="email" name="email" class="form-control"
value="{{ $user->email }}" required>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Nomor HP</label>
<input type="text" name="no_hp" class="form-control"
value="{{ $user->no_hp }}" required>
</div>
<div class="mb-3">
<label class="form-label fw-bold">Alamat Pengiriman Default</label>
<textarea name="alamat" class="form-control" rows="3" required>{{ $user->alamat }}</textarea>
</div>
<hr>
<p class="text-muted small">Isi kolom di bawah HANYA jika ingin mengganti password.</p>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Password Baru</label>
<input type="password" name="password" class="form-control">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Ulangi Password</label>
<input type="password" name="password_confirmation" class="form-control">
</div>
</div>
<div class="d-grid mt-3">
<button type="submit" class="btn btn-primary rounded-pill py-2">Simpan
Perubahan</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
@endsection

View File

@ -22,7 +22,6 @@
<script src="https://cdn.jsdelivr.net/gh/zuramai/mazer@docs/demo/assets/static/js/initTheme.js"></script>
<div id="app">
<!-- START SIDEBAR -->
<div id="sidebar">
<div class="sidebar-wrapper active">
<div class="sidebar-header position-relative">
@ -30,8 +29,6 @@
<div class="logo">
<a href="#">TaniDesa</a>
</div>
<!-- Toggle Dark Mode -->
<div class="theme-toggle d-flex gap-2 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"
@ -61,7 +58,6 @@
</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>
@ -69,7 +65,6 @@ class="bi bi-x bi-middle"></i></a>
</div>
</div>
<!-- MENU SIDEBAR -->
<div class="sidebar-menu">
<ul class="menu">
<li class="sidebar-title">Menu Utama</li>
@ -78,14 +73,17 @@ class="bi bi-x bi-middle"></i></a>
@if (Auth::guard('admin')->check())
<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>
<i class="bi bi-grid-fill"></i> <span>Dashboard</span>
</a>
</li>
<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>
<i class="bi bi-person-badge-fill"></i> <span>Verifikasi Petani</span>
</a>
</li>
<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
@ -94,44 +92,45 @@ class="bi bi-x bi-middle"></i></a>
@if (Auth::guard('petani')->check())
<li class="sidebar-item {{ request()->is('petani/dashboard') ? 'active' : '' }}">
<a href="{{ route('petani.dashboard') }}" class='sidebar-link'>
<i class="bi bi-grid-fill"></i>
<span>Dashboard</span>
<i class="bi bi-grid-fill"></i> <span>Dashboard</span>
</a>
</li>
<li class="sidebar-item {{ request()->is('petani/produk*') ? 'active' : '' }}">
<a href="{{ route('petani.produk.index') }}" class='sidebar-link'>
<i class="bi bi-basket-fill"></i>
<span>Kelola Produk</span>
<i class="bi bi-basket-fill"></i> <span>Kelola Produk</span>
</a>
</li>
{{-- Manajemen Pesanan Masuk --}}
<li class="sidebar-item {{ request()->is('petani/pesanan*') ? 'active' : '' }}">
<a href="{{ route('petani.pesanan.index') }}" class='sidebar-link'>
<i class="bi bi-receipt"></i>
<span>Pesanan Masuk</span>
<i class="bi bi-receipt"></i> <span>Pesanan Masuk</span>
</a>
</li>
{{-- Manajemen Kotak Masuk(Pesan) --}}
<li class="sidebar-item {{ request()->is('petani/pesan*') ? 'active' : '' }}">
<li
class="sidebar-item {{ request()->is('petani/pesan') || request()->is('petani/pesan/*') ? 'active' : '' }}">
<a href="{{ route('petani.pesan.index') }}" class='sidebar-link'>
<i class="bi bi-chat-dots-fill"></i>
<span>Kotak Masuk</span>
<i class="bi bi-chat-dots-fill"></i> <span>Kotak Masuk</span>
</a>
</li>
@endif
<li class="sidebar-title">Akun</li>
{{-- Menu Profil --}}
@if (Auth::guard('petani')->check())
<li class="sidebar-item {{ request()->is('petani/profile*') ? 'active' : '' }}">
<a href="{{ route('petani.profile') }}" class='sidebar-link'>
<i class="bi bi-person-circle"></i> <span>Profil Saya</span>
</a>
</li>
@endif
{{-- Logout --}}
<li class="sidebar-item">
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit"
class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
<i class="bi bi-box-arrow-left"></i>
<span>Logout</span>
<i class="bi bi-box-arrow-left"></i> <span>Logout</span>
</button>
</form>
</li>
@ -140,7 +139,6 @@ class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
</div>
</div>
<!-- MAIN CONTENT -->
<div id="main">
<header class="mb-3">
<a href="#" class="burger-btn d-block d-xl-none">
@ -152,7 +150,6 @@ class='sidebar-link border-0 bg-transparent text-danger w-100 text-start'>
<h3>@yield('page-title')</h3>
</div>
<!-- KONTEN DINAMIS -->
<div class="page-content">
@yield('content')
</div>

View File

@ -97,7 +97,7 @@ class="position-absolute bg-secondary rounded-circle d-flex align-items-center j
class="d-none d-xl-inline ms-1">{{ Auth::guard('pembeli')->user()->nama_lengkap }}</span>
</a>
<div class="dropdown-menu m-0 bg-secondary rounded-0">
<a href="#" class="dropdown-item">Profil Saya</a>
<a href="{{ route('pembeli.profile') }}" class="dropdown-item">Profil Saya</a>
<a href="{{ route('pembeli.pesan.index') }}" class="dropdown-item">Pesan Saya</a>
@ -216,11 +216,6 @@ class="fab fa-linkedin-in"></i></a>
class="fas fa-copyright text-light me-2"></i>TaniDesa</a>, All right
reserved.</span>
</div>
<div class="col-md-6 text-center text-md-end">
<span class="text-light">Designed By <a href="https://htmlcodex.com" class="text-white">HTML
Codex</a> Distributed By <a href="https://themewagon.com"
class="text-white">ThemeWagon</a></span>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,63 @@
@extends('layouts.admin')
@section('title', 'Profil Saya')
@section('page-title', 'Pengaturan Akun')
@section('content')
<div class="card">
<div class="card-body">
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<form action="{{ route('petani.profile.update') }}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="row">
<div class="col-md-4 text-center">
<img src="{{ $user->foto ? asset('storage/' . $user->foto) : asset('template/admin/static/images/faces/2.jpg') }}"
alt="Avatar" class="rounded-circle img-thumbnail mb-3"
style="width: 150px; height: 150px; object-fit: cover;">
<div class="mb-3">
<label class="form-label btn btn-sm btn-outline-primary">
Ganti Foto <input type="file" name="foto" hidden accept="image/*">
</label>
</div>
</div>
<div class="col-md-8">
<div class="mb-3">
<label class="form-label">Nama Lengkap / Nama Toko</label>
<input type="text" name="nama_lengkap" class="form-control" value="{{ $user->nama_lengkap }}"
required>
</div>
<div class="mb-3">
<label class="form-label">Email</label>
<input type="email" name="email" class="form-control" value="{{ $user->email }}" required>
</div>
<hr class="my-4">
<h6 class="text-muted mb-3">Ganti Password (Opsional)</h6>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Password Baru</label>
<input type="password" name="password" class="form-control"
placeholder="Kosongkan jika tidak diganti">
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Konfirmasi Password</label>
<input type="password" name="password_confirmation" class="form-control"
placeholder="Ulangi password baru">
</div>
</div>
<button type="submit" class="btn btn-primary">Simpan Perubahan</button>
</div>
</div>
</form>
</div>
</div>
@endsection

View File

@ -8,6 +8,7 @@
use App\Http\Controllers\PesanController;
use App\Http\Controllers\Petani\DashboardController;
use App\Http\Controllers\Petani\ProdukController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\TransaksiController;
/*
@ -65,12 +66,16 @@
// Route Pesan untuk Pembeli
Route::get('/pesan', [PesanController::class, 'index'])->name('pembeli.pesan.index');
Route::get('/pesan/{id}', [PesanController::class, 'show'])->name('pembeli.pesan.show');
Route::get('/profile', [ProfileController::class, 'editPembeli'])->name('pembeli.profile');
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');
// Petani Verification Logic
Route::controller(AdminController::class)->prefix('admin/verifikasi')->group(function () {
@ -98,4 +103,7 @@
// Route Pesan untuk Petani
Route::get('/petani/pesan', [PesanController::class, 'index'])->name('petani.pesan.index');
Route::get('/petani/pesan/{id}', [PesanController::class, 'show'])->name('petani.pesan.show');
Route::get('/petani/profile', [ProfileController::class, 'editPetani'])->name('petani.profile');
Route::put('/petani/profile', [ProfileController::class, 'updatePetani'])->name('petani.profile.update');
});