Takut hilang

This commit is contained in:
HANIF FEBRIANSYAH 2025-04-03 07:28:44 +07:00
parent a1ef885081
commit e718c10a60
39 changed files with 1869 additions and 860 deletions

View File

@ -2,10 +2,12 @@
namespace App\Http\Controllers;
use App\Models\DataKategori;
use Nette\Utils\Strings;
use App\Models\DataKategori;
use Illuminate\Http\Request;
use PhpParser\Node\Stmt\TryCatch;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;
use Illuminate\Auth\Events\Validated;
use Illuminate\Http\RedirectResponse;
use PhpParser\Node\Expr\Cast\String_;
@ -20,7 +22,9 @@ class AdminDataKursusController extends Controller
public function dataKursus()
{
// Mengambil semua data kursus dari model DataKursus
$courses = DataKursus::with('kategoris')->paginate(10);
$courses = DataKursus::with('kategoris')
->where('user_id', auth()->id()) // Filter berdasarkan user yang login
->paginate(10);
// Mengambil gambar untuk setiap course, jika ada
foreach ($courses as $course) {
@ -53,7 +57,6 @@ public function store(Request $request)
'lokasi' => 'required',
'latitude' => 'required', // Ubah menjadi wajib diisi
'longitude' => 'required', // Ubah menjadi wajib diisi
'popular' => 'required',
'img_konten.*' => 'nullable|image', // Gambar konten tetap opsional
], [
'nama_kursus.required' => 'Nama kursus wajib diisi.',
@ -69,7 +72,6 @@ public function store(Request $request)
'lokasi.required' => 'Lokasi wajib diisi.',
'latitude.required' => 'Latitude wajib diisi.', // Pesan error custom
'longitude.required' => 'Longitude wajib diisi.', // Pesan error custom
'popular.required' => 'Status popular wajib diisi.',
'img_konten.*.nullable' => 'Gambar konten bersifat opsional.',
'img_konten.*.file' => 'File yang di-upload harus berupa gambar.',
]);
@ -91,6 +93,7 @@ public function store(Request $request)
}
}
// Simpan data ke dalam database
// Simpan data ke dalam database
$result = DataKursus::create([
'nama_kursus' => $request->nama_kursus,
@ -99,12 +102,12 @@ public function store(Request $request)
'deskripsi' => $request->deskripsi,
'paket' => $request->paket,
'metode' => $request->metode,
'fasilitas' => $request->fasilitas,
'fasilitas' => json_encode(json_decode($request->fasilitas, true)), // Pastikan data tersimpan sebagai JSON valid
'lokasi' => $request->lokasi,
'latitude' => $request->latitude, // Menyimpan nilai latitude bebas
'longitude' => $request->longitude, // Menyimpan nilai longitude bebas
'popular' => $request->popular, // Menyimpan nilai longitude bebas
'latitude' => $request->latitude,
'longitude' => $request->longitude,
'img_konten' => json_encode($imgKontenPaths),
'user_id' => Auth::id(),
]);
// Redirect setelah berhasil
@ -118,17 +121,23 @@ public function store(Request $request)
public function edit($id)
{
// Ambil record DataKursus berdasarkan ID-nya
// Ambil data kategori
$kategori = DataKategori::all();
// Ambil data kursus berdasarkan ID
$dataKursus = DataKursus::findOrFail($id);
// Decode field JSON untuk nama gambar jika ada
// Decode JSON fasilitas agar bisa ditampilkan dalam bentuk array
$fasilitas = json_decode($dataKursus->fasilitas, true) ?? [];
// Decode JSON untuk daftar gambar konten (jika ada)
$imageName = $dataKursus->img_konten ? json_decode($dataKursus->img_konten, true) : [];
// Kirim data ke view
return view('admin.ubahDataKursusAdmin', compact('dataKursus', 'imageName', 'kategori'));
return view('admin.ubahDataKursusAdmin', compact('dataKursus', 'imageName', 'kategori', 'fasilitas'));
}
public function update(Request $request, $id)
{
// Validasi request
@ -140,10 +149,10 @@ public function update(Request $request, $id)
'img_konten.*' => 'nullable|image',
'latitude' => 'required|numeric',
'longitude' => 'required|numeric',
'popular' => 'required|string',
'paket' => 'required|string',
'metode' => 'required|string',
'fasilitas' => 'required|string',
'fasilitas' => 'required|array', // Mengizinkan array
'fasilitas.*' => 'required|string', // Setiap elemen harus string
'lokasi' => 'required|string',
], [
'nama_kursus.required' => 'Nama kursus wajib diisi.',
@ -155,29 +164,32 @@ public function update(Request $request, $id)
'latitude.numeric' => 'Latitude harus berupa angka.',
'longitude.required' => 'Longitude wajib diisi.',
'longitude.numeric' => 'Longitude harus berupa angka.',
'popular.required' => 'Status popular wajib diisi.',
'paket.required' => 'Paket wajib diisi.',
'metode.required' => 'Metode wajib diisi.',
'fasilitas.required' => 'Fasilitas wajib diisi.',
'fasilitas.array' => 'Fasilitas harus dalam format array.',
'lokasi.required' => 'Lokasi wajib diisi.',
]);
try {
// Gunakan transaksi database untuk memastikan data aman
DB::beginTransaction();
// Ambil record DataKursus berdasarkan ID-nya
$dataKursus = DataKursus::findOrFail($id);
// Update fields
$dataKursus->nama_kursus = $request->input('nama_kursus');
$dataKursus->kategori_id = $request->input('kategori_id');
$dataKursus->deskripsi = $request->input('deskripsi');
$dataKursus->latitude = $request->input('latitude');
$dataKursus->longitude = $request->input('longitude');
$dataKursus->popular = $request->input('popular');
$dataKursus->paket = $request->input('paket');
$dataKursus->metode = $request->input('metode');
$dataKursus->fasilitas = $request->input('fasilitas');
$dataKursus->lokasi = $request->input('lokasi');
$dataKursus->update([
'nama_kursus' => $request->input('nama_kursus'),
'kategori_id' => $request->input('kategori_id'),
'deskripsi' => $request->input('deskripsi'),
'latitude' => $request->input('latitude'),
'longitude' => $request->input('longitude'),
'paket' => $request->input('paket'),
'metode' => $request->input('metode'),
'fasilitas' => json_encode($request->input('fasilitas')), // Simpan sebagai JSON
'lokasi' => $request->input('lokasi'),
]);
// Update gambar utama jika ada file baru
if ($request->hasFile('img')) {
@ -193,7 +205,7 @@ public function update(Request $request, $id)
// Update multiple file upload jika ada file baru
if ($request->hasFile('img_konten')) {
if ($dataKursus->img_konten) {
$oldImages = json_decode($dataKursus->img_konten, true);
$oldImages = json_decode($dataKursus->img_konten, true) ?? [];
foreach ($oldImages as $oldImage) {
Storage::delete('public/' . $oldImage);
}
@ -201,8 +213,8 @@ public function update(Request $request, $id)
$menuImages = [];
foreach ($request->file('img_konten') as $file) {
$imgKontenPaths = $file->store('logo', 'public');
$menuImages[] = $imgKontenPaths;
$imgKontenPath = $file->store('logo', 'public');
$menuImages[] = $imgKontenPath;
}
$dataKursus->img_konten = json_encode($menuImages);
}
@ -210,10 +222,14 @@ public function update(Request $request, $id)
// Simpan perubahan
$dataKursus->save();
// Commit transaksi
DB::commit();
// Redirect dengan pesan sukses
return redirect()->route('admin.dataKursus')->with('success', 'Data berhasil diperbarui.');
} catch (\Exception $e) {
// Tangani error dan kirimkan pesan error
// Rollback jika terjadi error
DB::rollBack();
return redirect()->back()->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
}
}
@ -223,8 +239,13 @@ public function update(Request $request, $id)
public function destroy($id)
{
$dataKursus = DataKursus::findOrFail($id);
$dataKursus->delete();
return redirect()->route('admin.dataKursus')->with('success', 'Data berhasil dihapus.');
try {
$dataKursus = DataKursus::findOrFail($id);
$dataKursus->delete();
return redirect()->route('admin.dataKursus')->with('success', 'Data berhasil dihapus.');
} catch (\Exception $e) {
return redirect()->route('admin.dataKursus')->with('error', 'Gagal Menghapus Kursus, Periksa ');
}
}
}

View File

@ -0,0 +1,130 @@
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
class AdminUserController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$role = $request->get('role'); // Ambil filter role
$search = $request->get('search'); // Ambil input search
$user = User::when($role, function ($query, $role) {
return $query->where('role', $role); // Filter berdasarkan role jika ada
})
->when($search, function ($query, $search) {
return $query->where(function ($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhere('username', 'like', "%{$search}"); // Cari berdasarkan nama atau email
});
})
->whereIn('role', ['user', 'pengunjung']) // Pastikan hanya user & pengunjung
->paginate(10);
return view('admin.user.index', compact('user'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
// Validasi data yang masuk
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:6',
'verif_password' => 'required|same:password',
]);
// Simpan user baru ke database
User::create([
'name' => $validatedData['name'],
'email' => $validatedData['email'],
'password' => Hash::make($validatedData['password']), // Hash password untuk keamanan
'role' => 'user', // Default role untuk user baru
]);
return redirect()->route('user.index')->with('success', 'User berhasil ditambahkan!');
} catch (\Exception $e) {
// Simpan error ke log untuk debugging
return redirect()->route('user.index')->with('error', 'Error: ' . $e->getMessage());
}
}
/**
* Display the specified resource.
*/
public function show(string $id) {}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$request->validate([
'name' => 'required',
'email' => 'email|required'
]);
try {
$user = User::findOrFail($id);
$user->name = $request->input('name');
$user->email = $request->input('email');
$user->save();
return redirect()->route('user.index')->with('success', 'User berhasil diperbarui.');
} catch (\Exception $e) {
return redirect()->route('user.index')->with('error', 'Error:' . $e->getMessage());
}
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
try {
// Cari user berdasarkan ID
$user = User::findOrFail($id);
// Hapus user dari database
$user->delete();
// Redirect dengan pesan sukses
return redirect()->route('user.index')->with('success', 'User berhasil dihapus.');
} catch (\Exception $e) {
return redirect()->route('user.index')->with('error', 'Terjadi kesalahan: ' . $e->getMessage());
}
}
}

View File

@ -104,11 +104,16 @@ public function update(Request $request, string $id)
*/
public function destroy(string $id)
{
// Temukan kategori berdasarkan ID
$kategori = DataKategori::findOrFail($id);
try {
// Temukan kategori berdasarkan ID
$kategori = DataKategori::findOrFail($id);
// Hapus kategori
$kategori->delete();
return redirect()->route('kategori.index')->with('success', 'Kategori berhasil dihapus.');
// Hapus kategori
$kategori->delete();
return redirect()->route('kategori.index')->with('success', 'Kategori berhasil dihapus.');
} catch (\Exception $e) {
return redirect()->route('kategori.index')->with('error', 'Gagal menghapus kategori. untuk menghapus kategori tidak boleh ada kursus yang tersambung dengan kategori ');
}
}
}

View File

@ -4,6 +4,7 @@
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class LoginController extends Controller
{
@ -14,43 +15,65 @@ public function index()
public function authenticate(Request $request)
{
// Validasi input
// Validasi input (login bisa berupa email atau username, dan password)
$credentials = $request->validate([
'email' => ['required', 'email'],
'login' => ['required'], // Input login (email atau username)
'password' => ['required'],
]);
// Ambil nilai "remember" dari request (default false jika tidak dicentang)
$remember = $request->has('remember');
// Coba autentikasi dengan kredensial dan parameter "remember"
if (Auth::attempt($credentials, $remember)) {
// Logout pengguna lama untuk mencegah konflik sesi
Auth::logout();
// Cek apakah input login berupa email atau username
$user = null;
if (filter_var($credentials['login'], FILTER_VALIDATE_EMAIL)) {
// Jika input adalah email, cari berdasarkan email
$user = \App\Models\User::where('email', $credentials['login'])->first();
} else {
// Jika input adalah username, cari berdasarkan username
$user = \App\Models\User::where('username', $credentials['login'])->first();
}
// Cek apakah pengguna ditemukan
if ($user && Hash::check($credentials['password'], $user->password)) {
// Jika password cocok, login
Auth::login($user, $remember);
$request->session()->regenerate();
// Periksa role dan arahkan sesuai dengan role
// Ambil role user yang sedang login
$role = Auth::user()->role;
// Simpan status login sesuai dengan role
if ($role === 'admin') {
session(['is_pengunjung_logged_in' => true]); // Menyimpan status pengunjung dalam sesi
session(['is_admin_logged_in' => true]); // Status admin
return redirect()->route('admin.home');
}
// Jika pengunjung, simpan sesi dan arahkan ke halaman depan
if ($role === 'user') {
session(['is_user_logged_in' => true]); // Status user
return redirect()->route('user.home'); // Redirect ke halaman user
}
if ($role === 'pengunjung') {
session(['is_pengunjung_logged_in' => true]); // Menyimpan status pengunjung dalam sesi
return redirect()->route('user.home');
session(['is_pengunjung_logged_in' => true]); // Status pengunjung
return redirect()->route('pengunjung.home'); // Redirect ke halaman pengunjung
}
}
// Jika gagal login, kembali dengan error
return back()->withErrors([
'email' => 'Email atau password salah.',
'login' => 'Email/Username atau password salah.',
]);
}
public function logout(Request $request)
{
Auth::logout();

View File

@ -31,7 +31,7 @@ public function home()
$peta = DataKursus::with('kategoris')->get();
// Kembalikan view dengan data yang sudah diproses
return view('user.home', compact('landingpage','peta'));
return view('user.home', compact('landingpage', 'peta'));
}

View File

@ -20,7 +20,7 @@ public function handle($request, Closure $next, $role)
return $next($request);
}
// Redirect jika tidak memiliki akses
return redirect()->route('gagal.home')->with('error', 'You do not have access to this page.');
// Redirect kembali ke halaman sebelumnya dengan pesan error
return back()->with('error', 'You do not have access to this page.');
}
}

View File

@ -26,7 +26,9 @@ class DataKursus extends Model
'latitude',
'longitude', // Pastikan nama kolom sesuai dengan migrasi
'popular', // Pastikan nama kolom sesuai dengan migrasi
'img_konten'
'img_konten',
'user_id'
];
public $timestamps = true;
@ -35,7 +37,7 @@ public function kategoris(): BelongsTo
{
return $this->belongsTo(DataKategori::class, 'kategori_id', 'id'); // Menentukan foreign key dan local key
}
public function kunjungan(): HasMany
{
return $this->hasMany(Kunjungan::class, 'kursus_id', 'id'); // Menentukan foreign key dan local key
@ -45,4 +47,8 @@ public function ulasan(): HasMany
{
return $this->hasMany(DataUlasan::class, 'kursus_id', 'id'); // Menentukan foreign key dan local key
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id', 'id'); // Menentukan foreign key dan local key
}
}

View File

@ -4,10 +4,11 @@
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
@ -24,6 +25,7 @@ class User extends Authenticatable implements MustVerifyEmail
protected $fillable = [
'name',
'email',
'username',
'password',
'role'
];
@ -31,6 +33,10 @@ public function ulasans(): HasMany
{
return $this->hasMany(DataUlasan::class, 'user_id', 'id'); // Menentukan foreign key dan local key
}
public function users(): HasMany
{
return $this->hasMany(User::class, 'user_id', 'id'); // Menentukan foreign key dan local key
}
/**
* The attributes that should be hidden for serialization.

View File

@ -2,6 +2,8 @@
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
@ -17,8 +19,8 @@ public function register(): void
/**
* Bootstrap any application services.
*/
public function boot(): void
public function boot()
{
//
App::setLocale(Session::get('locale', 'id')); // Default ke Bahasa Indonesia
}
}

View File

@ -9,7 +9,8 @@
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.0",
"laravel/sanctum": "^3.2",
"laravel/tinker": "^2.8"
"laravel/tinker": "^2.8",
"laravolt/indonesia": "^0.36.0"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",

84
composer.lock generated
View File

@ -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": "85309d4524da1baae35ac151622b248f",
"content-hash": "08dbb25675a803a24f2b8a6421dd5c41",
"packages": [
{
"name": "brick/math",
@ -1512,6 +1512,88 @@
},
"time": "2024-09-23T13:32:56+00:00"
},
{
"name": "laravolt/indonesia",
"version": "v0.36",
"source": {
"type": "git",
"url": "https://github.com/laravolt/indonesia.git",
"reference": "f1499a4cecf83b6f09a40a61aff084f7445bee4c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravolt/indonesia/zipball/f1499a4cecf83b6f09a40a61aff084f7445bee4c",
"reference": "f1499a4cecf83b6f09a40a61aff084f7445bee4c",
"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.36"
},
"time": "2025-02-28T12:19:57+00:00"
},
{
"name": "league/commonmark",
"version": "2.6.1",

View File

@ -82,7 +82,7 @@
|
*/
'locale' => 'en',
'locale' => 'id',
/*
|--------------------------------------------------------------------------

View File

@ -15,15 +15,12 @@ public function definition()
return [
'kategori_id' => DataKategori::factory(), // Relasi dengan kategori
'nama_kursus' => $this->faker->sentence(3), // Nama kursus random
'img' => $this->faker->imageUrl(640, 480, 'education', true, 'kursus'), // Gambar kursus random
'deskripsi' => $this->faker->paragraph(), // Deskripsi kursus random
'paket' => $this->faker->word(), // Paket kursus random
'metode' => $this->faker->randomElement(['Online', 'Offline', 'Hybrid']), // Metode random
'fasilitas' => $this->faker->sentence(), // Fasilitas random
'lokasi' => $this->faker->address(), // Lokasi random
'latitude' => $this->faker->latitude(-90, 90), // Latitude random
'longitude' => $this->faker->longitude(-180, 180), // Longitude random
'popular' => $this->faker->boolean(), // True/false untuk popular
];
}
}

View File

@ -16,8 +16,9 @@ public function up(): void
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->string('username')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->enum('role', ['admin', 'pengunjung'])->default('pengunjung')->index(); // Tambahkan index
$table->enum('role', ['admin', 'user', 'pengunjung'])->default('pengunjung')->index(); // Tambahkan index
$table->string('password');
$table->rememberToken();
$table->timestamps();

View File

@ -18,18 +18,22 @@ public function up()
$table->longText('deskripsi');
$table->longText('paket');
$table->longText('metode');
$table->text('fasilitas');
$table->longText('lokasi');
$table->string('latitude');
$table->string('longitude');
$table->string('popular');
$table->json('fasilitas')->nullable();
$table->string('latitude')->nullable();
$table->string('longitude')->nullable();
$table->json('img_konten')->nullable();
$table->timestamps();
$table->foreignId('user_id')
->nullable() // Membuat kolom ini bisa NULL
->constrained('users') // Nama tabel yang dijadikan referensi
->onDelete('restrict') // Aturan saat data dihapus
->onUpdate('cascade'); // Aturan saat data diupdate
$table->foreignId('kategori_id')
->nullable() // Membuat kolom ini bisa NULL
->constrained('kategori') // Nama tabel yang dijadikan referensi
->onDelete('set null') // Aturan saat data dihapus
->onDelete('restrict') // Aturan saat data dihapus
->onUpdate('cascade'); // Aturan saat data diupdate
});
}

View File

@ -17,17 +17,18 @@ public function up()
$table->text('comment')->nullable();
$table->timestamps();
// Foreign key constraint
// Foreign key constraint untuk kursus_id
$table->foreignId('kursus_id')
->nullable() // Membuat kolom ini bisa NULL
->constrained('kategori') // Nama tabel yang dijadikan referensi
->onDelete('set null') // Aturan saat data dihapus
->constrained('data_kursus') // Mengarah ke tabel kursus, bukan kategori
->onDelete('cascade') // Aturan saat data dihapus, akan menghapus ulasan terkait
->onUpdate('cascade'); // Aturan saat data diupdate
// Foreign key constraint untuk user_id
$table->foreignId('user_id')
->nullable() // Membuat kolom ini bisa NULL
->constrained('users') // Nama tabel yang dijadikan referensi
->onDelete('set null') // Aturan saat data dihapus
->onDelete('cascade') // Aturan saat data dihapus, akan menghapus ulasan terkait
->onUpdate('cascade'); // Aturan saat data diupdate
});
}

View File

@ -18,9 +18,31 @@ public function run(): void
User::create([
'name' => 'Salma Admin',
'email' => 'salma@gmail.com',
'username' => 'salma',
'password' => bcrypt('salma281103'), // Ganti dengan password pilihan Anda
'role' => 'admin',
]);
User::create([
'name' => 'Admin',
'email' => 'admin@gmail.com',
'username' => 'admin',
'password' => bcrypt('admin123'), // Ganti dengan password pilihan Anda
'role' => 'admin',
]);
User::create([
'name' => 'User',
'email' => 'user@gmail.com',
'username' => 'user',
'password' => bcrypt('user123'), // Ganti dengan password pilihan Anda
'role' => 'user',
]);
User::create([
'name' => 'pengunjung',
'username' => 'pengunjung',
'email' => 'pengunjung@gmail.com',
'password' => bcrypt('pengunjung123'), // Ganti dengan password pilihan Anda
'role' => 'pengunjung',
]);
DataKategori::insert([
['nama_kategori' => 'Speaking'],
['nama_kategori' => 'Reading'],
@ -28,31 +50,25 @@ public function run(): void
['nama_kategori' => 'Good Evening'],
]);
// User::create([
// 'name' => 'user',
// 'email' => 'user@gmail.com',
// 'password' => bcrypt('user123'), // Ganti dengan password pilihan Anda
// 'role' => 'pengunjung',
// ]);
// // Buat 3 kategori, setiap kategori memiliki banyak kursus
// // Buat 3 kategori
// $kategoris = DataKategori::factory(3)->create();
$kategoris = DataKategori::factory(3)->create();
// // Buat kursus hingga total 20 data
// $totalKursus = 20;
// $kategoris->each(function ($kategori) use ($totalKursus, $kategoris) {
// $jumlahKursusPerKategori = floor($totalKursus / $kategoris->count());
// DataKursus::factory($jumlahKursusPerKategori)->create([
// 'kategori_id' => $kategori->id,
// ]);
// });
// Buat kursus hingga total 20 data
$totalKursus = 20;
$kategoris->each(function ($kategori) use ($totalKursus, $kategoris) {
$jumlahKursusPerKategori = floor($totalKursus / $kategoris->count());
DataKursus::factory($jumlahKursusPerKategori)->create([
'kategori_id' => $kategori->id,
]);
});
// // Jika ada sisa karena pembagian tidak rata, tambahkan ke kategori pertama
// $sisa = $totalKursus % $kategoris->count();
// if ($sisa > 0) {
// DataKursus::factory($sisa)->create([
// 'kategori_id' => $kategoris->first()->id,
// ]);
// }
// Jika ada sisa karena pembagian tidak rata, tambahkan ke kategori pertama
$sisa = $totalKursus % $kategoris->count();
if ($sisa > 0) {
DataKursus::factory($sisa)->create([
'kategori_id' => $kategoris->first()->id,
]);
}
}
}

View File

View File

@ -0,0 +1,277 @@
<x-adminlayout>
<div class="px-10">
<div class="py-10 md:px-0 px-4">
<div class="flex justify-end items-center pb-4 ">
<button data-modal-target="default-modal-tambah-users" data-modal-toggle="default-modal-tambah-users"
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-md shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular"
href="{{ route('kategori.create') }}">Tambah Data</button>
</div>
<div class="flex justify-end items-center pb-4 w-full">
<form class="max-w-lg w-full" method="GET" action="{{ route('user.index') }}">
<div class="flex">
<select name="role" id="role"
class="shrink-0 z-10 inline-flex items-center py-2.5 px-4 text-sm font-medium text-gray-900 bg-gray-100 border border-gray-300 rounded-s-lg hover:bg-gray-200 focus:ring-4 focus:outline-none focus:ring-gray-100">
<option value="" selected>All Roles</option>
<option value="user" {{ request('role') == 'user' ? 'selected' : '' }}>User</option>
<option value="pengunjung" {{ request('role') == 'pengunjung' ? 'selected' : '' }}>
Pengunjung</option>
</select>
<div class="relative w-full">
<input type="search" name="search" value="{{ request('search') }}"
class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-e-lg border-s-gray-50 border-s-2 border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
placeholder="Search users..." />
<button type="submit"
class="absolute top-0 end-0 p-2.5 text-sm font-medium h-full text-white bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-e-lg border border-green-700 hover:bg-green-800 focus:ring-4 focus:outline-none focus:ring-blue-300">
<svg class="w-4 h-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
</svg>
<span class="sr-only">Search</span>
</button>
</div>
</div>
</form>
</div>
{{ $user->links() }}
<div class="relative overflow-x-auto sm:rounded-lg">
<table class="w-full text-sm text-gray-700 shadow-md border border-gray-300 rounded-lg overflow-hidden">
<thead class="text-xs uppercase bg-gray-100 border-b border-gray-300">
<tr>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">No</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Nama</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Email</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Role</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Terdaftar</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Diperbarui</th>
<th scope="col" class="py-3 px-4 text-end">Aksi</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-300">
@foreach ($user as $no => $index)
<tr class="odd:bg-white even:bg-gray-50 hover:bg-gray-200 transition">
<th scope="row"
class="py-4 px-4 font-medium text-gray-900 text-end border-r border-gray-300">
{{ ($user->currentPage() - 1) * $user->perPage() + $no + 1 }}
</th>
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $index->name }}
</td>
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $index->email }}
</td>
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $index->role }}
</td>
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $index->created_at }}
</td>
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $index->updated_at }}
</td>
<td class="py-4 px-4 text-end">
<div class="flex justify-end space-x-2">
<!-- Tombol Edit -->
<button data-modal-target="modal-edit-users-{{ $index->id }}"
data-modal-toggle="modal-edit-users-{{ $index->id }}"
class="font-extrabold text-xs shadow-md hover:bg-green-700 text-white py-2 px-2 bg-green-600 rounded-lg transition">
<i class="fas fa-edit text-xs"></i>
</button>
<!-- Tombol Hapus -->
<button data-modal-target="modal-delete-user-{{ $index->id }}"
data-modal-toggle="modal-delete-user-{{ $index->id }}"
class="font-extrabold text-xs shadow-md hover:bg-red-700 text-white py-2 px-2 bg-red-600 rounded-lg transition">
<i class="fas fa-trash text-xs"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="py-4">
{{ $user->links() }}
</div>
</div>
</div>
<!-- Modal Tambah Kategoris -->
<div id="default-modal-tambah-users" data-modal-backdrop="static" tabindex="-1" aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<div class="relative bg-white rounded-lg shadow ">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t ">
<h3 class="text-xl font-semibold text-gray-900 ">
Tambah User
</h3>
<button type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center "
data-modal-hide="default-modal-tambah-users">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<form action="{{ route('user.store') }}" method="POST">
@csrf
<div class="p-4 items-center">
<label for="name" class="block text-gray-700 font-bold mb-1">Nama</label>
<input type="text" id="name" name="name"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Nama" required autocomplete="off">
</div>
<div class="p-4 items-center">
<label for="email" class="block text-gray-700 font-bold mb-1">Email</label>
<input type="email" id="email" name="email"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Email" required autocomplete="off">
</div>
<div class="p-4 items-center">
<label for="password" class="block text-gray-700 font-bold mb-1">Password</label>
<input type="password" id="password" name="password"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Password" required autocomplete="off">
</div>
<div class="p-4 items-center">
<label for="verif_password" class="block text-gray-700 font-bold mb-1">Verifikasi
Password</label>
<input type="password" id="verif_password" name="verif_password"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Ulang Password" required autocomplete="off">
</div>
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b ">
<button type="submit"
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-md shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular">
Tambah
</button>
<button type="button" onclick="history.back();"
class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700">
Batal
</button>
</div>
</form>
</div>
</div>
</div>
<!-- Modal EDIT Kategori -->
@foreach ($user as $index)
<div id="modal-edit-users-{{ $index->id }}" data-modal-backdrop="static" tabindex="-1"
aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<div class="relative bg-white rounded-lg shadow ">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t ">
<h3 class="text-xl font-semibold text-gray-900 ">
Edit User
</h3>
<button type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center "
data-modal-hide="modal-edit-users-{{ $index->id }}">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<form id="edit-user-form" method="POST" action="{{ route('user.update', $index->id) }}">
@csrf <!-- Token CSRF -->
@method('PUT') <!-- Menggunakan metode PUT -->
<input hidden value="{{ $index->id }}" type="text" id="edit-idkategori"
name="id" required>
<div class="px-4 pb-4 items-center">
<label for="Name" class="block mt-4 text-gray-700 font-bold mb-1">Nama</label>
<input type="text" id="edit-nama" name="name" value="{{ $index->name }}"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan user" required required required autocomplete="off">
</div>
<div class="px-4 pb-4 items-center">
<label for="email" class="block mt-4 text-gray-700 font-bold mb-1">Email</label>
<input type="text" id="edit-nama" name="email" value="{{ $index->email }}"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan user" required required required autocomplete="off">
</div>
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b ">
<button type="submit"
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-md shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular">
Update
</button>
<button data-modal-hiden="modal-edit-users-{{ $index->id }}" type="button"
class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 ">
Batal
</button>
</div>
</form>
</div>
</div>
</div>
@endforeach
{{-- Modal DELETE Kategori --}}
@foreach ($user as $index)
<div id="modal-delete-user-{{ $index->id }}" data-modal-backdrop="static" tabindex="-1"
class="hidden fixed inset-0 z-50 items-center justify-center bg-black bg-opacity-50">
<div class="relative p-4 w-full max-w-md max-h-full">
<div class="relative bg-white rounded-lg shadow ">
<button type="button" data-modal-hide="modal-delete-user-{{ $index->id }}"
class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 inline-flex justify-center items-center "
id="close-modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
<span class="sr-only">Close modal</span>
</button>
<div class="p-4 md:p-5 text-center">
<svg class="mx-auto mb-4 text-gray-400 w-12 h-12 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<h3 class="mb-5 text-lg font-normal text-gray-500 ">Anda yakin ingin
menghapus?</h3>
<div class="flex justify-center">
<form id="delete-user" method="POST" action="{{ route('user.destroy', $index->id) }}">
@csrf <!-- Token CSRF -->
@method('DELETE') <!-- Menggunakan metode DELETE -->
<button type="submit"
class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center">
Ya, Saya Yakin
</button>
</form>
<button type="button"
id="cancel-logout"data-modal-hide="modal-delete-user-{{ $index->id }}"
class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 ">
Tidak, Batal
</button>
</div>
</div>
</div>
</div>
</div>
@endforeach
</x-adminlayout>

View File

@ -1,64 +1,58 @@
<x-adminlayout>
<div class="container">
<div class="px-10">
<div class="py-10 md:px-0 px-4">
<div class="flex justify-end items-center pb-4 ">
<button data-modal-target="default-modal-tambah-kategori"
data-modal-toggle="default-modal-tambah-kategori"
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-xl shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular"
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-md shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular"
href="{{ route('kategori.create') }}">Tambah Data</button>
</div>
{{ $kategori->links() }}
<div class="relative overflow-x-auto sm:rounded-lg poppins-regular">
<table class="w-full text-sm text-end rtl:text-right shadow-gray-600 text-gray-500">
<thead class="text-8x1 text-gray-700 uppercase shadow-gray-600 bg-gray-50 pb-4">
<table class="w-full text-sm text-gray-700 shadow-md border border-gray-300 rounded-lg overflow-hidden">
<thead class="text-xs uppercase bg-gray-100 border-b border-gray-300">
<tr>
<th scope="col" class=" py-3 text-end">No</th>
<!-- Menambahkan text-end untuk penataan -->
<th scope="col" class=" py-3 text-end">Nama Kategori</th>
<!-- Menambahkan text-end untuk penataan -->
<th scope="col" class=" py-3 text-end">Aksi</th>
<!-- Menambahkan text-end untuk penataan -->
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">No</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Nama Kategori</th>
<th scope="col" class="py-3 px-4 text-end">Aksi</th>
</tr>
</thead>
<tbody class="shadow-gray-600">
<tbody class="divide-y divide-gray-300">
@foreach ($kategori as $index => $kategoris)
<tr class="odd:bg-white even:bg-gray-50 shadow-gray-600 ">
<th scope="row" class=" py-4 font-medium text-gray-900 text-end">
<!-- Menambahkan text-end untuk penataan -->
<p class="m-auto space-x-2 flex justify-end">
{{ ($kategori->currentPage() - 1) * $kategori->perPage() + $index + 1 }}
</p>
<tr class="odd:bg-white even:bg-gray-50 hover:bg-gray-200 transition">
<th scope="row"
class="py-4 px-4 font-medium text-gray-900 text-end border-r border-gray-300">
{{ ($kategori->currentPage() - 1) * $kategori->perPage() + $index + 1 }}
</th>
<td class=" py-4 text-end">
<td class="py-4 px-4 text-end border-r border-gray-300">
{{ $kategoris->nama_kategori }}
</td>
<td class=" py-4 text-end">
<!-- Menambahkan text-end untuk penataan -->
<div class="flex justify-end space-x-4"> <!-- Menyusun ikon sejajar -->
<td class="py-4 px-4 text-end">
<div class="flex justify-end space-x-2">
<!-- Tombol Edit -->
<button data-modal-target="default-modal-edit-kategori{{ $kategoris->id }}"
data-modal-toggle="default-modal-edit-kategori{{ $kategoris->id }}"
class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white py-2 px-2 bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-lg h-fit">
<i class="fas fa-edit text-xs"></i> <!-- Icon Edit -->
class="font-extrabold text-xs shadow-md hover:bg-green-700 text-white py-2 px-2 bg-green-600 rounded-lg transition">
<i class="fas fa-edit text-xs"></i>
</button>
<!-- Tombol Hapus -->
<button data-modal-target="default-modal-delete-kategori{{ $kategoris->id }}"
data-modal-toggle="default-modal-delete-kategori{{ $kategoris->id }}"
class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white py-2 px-2 bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-lg h-fit">
<i class="fas fa-trash text-xs"></i> <!-- Icon Hapus -->
class="font-extrabold text-xs shadow-md hover:bg-red-700 text-white py-2 px-2 bg-red-600 rounded-lg transition">
<i class="fas fa-trash text-xs"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="py-4">
@ -72,13 +66,13 @@ class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-
<div id="default-modal-tambah-kategori" tabindex="-1" aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
<h3 class="text-xl poppins-regular text-green-800 dark:text-white">
<div class="relative bg-white rounded-lg shadow ">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t ">
<h3 class="text-xl poppins-regular text-green-800 ">
Tambahkan Kategori
</h3>
<button type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center "
data-modal-hide="default-modal-tambah-kategori">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
@ -97,13 +91,13 @@ class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-
placeholder="Masukkan Kategori" required required autocomplete="off">
</div>
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b ">
<button type="submit"
class="text-white bg-gradient-to-tr from-[#60BC9D] to-[#12372A] hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg text-sm poppins-regular px-5 py-2.5 text-end dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
class="text-white bg-gradient-to-tr from-[#60BC9D] to-[#12372A] hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg text-sm poppins-regular px-5 py-2.5 text-end ">
Tambah
</button>
<button data-modal-hide="default-modal-tambah-kategori" type="button"
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-green-800 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-green-800 focus:z-10 focus:ring-4 focus:ring-gray-100 ">
Batal
</button>
</div>
@ -116,13 +110,13 @@ class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none
<div id="default-modal-edit-kategori{{ $kategoris->id }}" tabindex="-1" aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600">
<h3 class="text-xl poppins-regular text-gray-900 dark:text-white">
<div class="relative bg-white rounded-lg shadow ">
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t ">
<h3 class="text-xl poppins-regular text-gray-900 ">
Edit Kategori
</h3>
<button type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center "
data-modal-hide="default-modal-edit-kategori{{ $kategoris->id }}">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
@ -136,8 +130,8 @@ class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounde
action="{{ route('kategori.update', $kategoris->id) }}">
@csrf <!-- Token CSRF -->
@method('PUT') <!-- Menggunakan metode PUT -->
<input hidden value="{{ $kategoris->id }}" type="text" id="edit-idkategori"
name="id" required>
<input hidden value="{{ $kategoris->id }}" type="text" id="edit-idkategori" name="id"
required>
<div class="px-4 pb-4 items-center">
<label for="detail_kategori"
@ -147,14 +141,13 @@ class="block mt-4 text-gray-700 poppins-regular mb-1">Kategori</label>
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Kategori" required required required autocomplete="off">
</div>
<div
class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600">
<div class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b ">
<button type="submit"
class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 poppins-regular rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
class="bg-gradient-to-tr from-[#60BC9D] to-[#12372A] py-2 px-4 rounded-md shadow-md shadow-gray-600 hover:bg-[#3F6A6B] text-white text-5x1 poppins-regular">
Update
</button>
<button data-modal-hiden="default-modal-edit-kategori{{ $kategoris->id }}" type="button"
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-100 ">
Batal
</button>
</div>
@ -169,9 +162,9 @@ class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none
<div id="default-modal-delete-kategori{{ $kategoris->id }}" tabindex="-1"
class="hidden fixed inset-0 z-50 items-center justify-center bg-black bg-opacity-50">
<div class="relative p-4 w-full max-w-md max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="relative bg-white rounded-lg shadow ">
<button type="button" data-modal-hide="default-modal-delete-kategori{{ $kategoris->id }}"
class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 inline-flex justify-center items-center "
id="close-modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
@ -181,12 +174,12 @@ class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hov
<span class="sr-only">Close modal</span>
</button>
<div class="p-4 md:p-5 text-center">
<svg class="mx-auto mb-4 text-gray-400 w-12 h-12 dark:text-gray-200" aria-hidden="true"
<svg class="mx-auto mb-4 text-gray-400 w-12 h-12 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<h3 class="mb-5 text-lg poppins-regular text-gray-500 dark:text-gray-400">Anda yakin ingin
<h3 class="mb-5 text-lg poppins-regular text-gray-500 ">Anda yakin ingin
menghapus?</h3>
<div class="flex justify-center">
<form id="edit-kategori-form" method="POST"
@ -194,14 +187,14 @@ class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hov
@csrf <!-- Token CSRF -->
@method('DELETE') <!-- Menggunakan metode DELETE -->
<button type="submit"
class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:focus:ring-red-800 font-medium rounded-lg text-sm poppins-regular inline-flex items-center px-5 py-2.5 text-center">
class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 font-medium rounded-lg text-sm poppins-regular inline-flex items-center px-5 py-2.5 text-center">
Ya, Saya Yakin
</button>
</form>
<button type="button"
id="cancel-logout"data-modal-hide="default-modal-delete-kategori{{ $kategoris->id }}"
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-red-700 focus:z-10 focus:ring-4 focus:ring-gray-100 ">
Tidak, Batal
</button>
</div>

View File

@ -1,6 +1,6 @@
<x-adminlayout>
<div class="container">
<div class="lg:px-10">
<div class="py-10 px-4 md:px-0">
@ -11,94 +11,104 @@
{{ $courses->links() }}
<div class="relative overflow-x-auto sm:rounded-lg">
<table class="w-full text-sm text-right rtl:text-right shadow-gray-600 text-gray-500">
<thead class="text-6x1 poppins-regular text-gray-700 uppercase shadow-gray-600 bg-gray-50">
<table class="w-full text-sm text-gray-700 shadow-md border border-gray-300 rounded-lg overflow-hidden">
<thead class="text-xs uppercase bg-gray-100 border-b border-gray-300">
<tr>
<th scope="col" class=" py-3 px-4 text-end">No</th>
<th scope="col" class=" py-3 px-4 text-end">Nama Kursus</th>
<th scope="col" class=" py-3 px-4 text-end">Kategori</th>
<th scope="col" class=" py-3 px-4 text-end">Paket</th>
<th scope="col" class=" py-3 px-4 text-end">Metode</th>
<th scope="col" class=" py-3 px-4 text-end">Fasilitas</th>
<th scope="col" class=" py-3 px-4 text-end">Lokasi</th>
<th scope="col" class=" py-3 px-4 text-end">Aksi</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">No</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Nama Kursus</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Kategori</th>
{{-- <th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Paket</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Metode</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Lokasi</th> --}}
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Fasilitas</th>
<th scope="col" class="py-3 px-4 text-end border-r border-gray-300">Latitude-Longitude
</th>
<th scope="col" class="py-3 px-4 text-end">Aksi</th>
</tr>
</thead>
<tbody class="shadow-gray-600">
<tbody class="divide-y divide-gray-300">
@foreach ($courses as $index => $course)
<tr class="odd:bg-white even:bg-gray-50 shadow-gray-600 ">
<th scope="row" class="px-4 py-4 text-end poppins-regular text-gray-900 whitespace-nowrap">
<tr
class="odd:bg-white even:bg-gray-50 hover:bg-gray-200 transition border-b border-gray-300">
<th scope="row"
class="px-4 py-4 text-end poppins-regular text-gray-900 whitespace-nowrap border-r border-gray-300">
{{ ($courses->currentPage() - 1) * $courses->perPage() + $loop->iteration }}
</th>
<td class=" py-4 text-end px-4">
<div class="flex justify-end flex-row gap-3 items-center w-full h-full">
<td class="py-4 text-end px-4 border-r border-gray-300">
<div class="flex justify-end flex-row gap-3 items-center">
<div class="form-control flex-1">
<span class="text-sm uppercase font-semibold">
{{ $course->nama_kursus }}
</span>
<span class="text-xs text-gray-400 line-clamp-2">
{{ Str::limit($course->deskripsi, 200, '...') }}
@php
$words = explode(' ', Str::limit($course->deskripsi, 200, '...'));
$firstPart = implode(' ', array_slice($words, 0, 15)); // Ambil 15 kata pertama
$secondPart = implode(' ', array_slice($words, 15)); // Sisanya
@endphp
<span
class="text-xs text-gray-400 break-words whitespace-normal leading-tight max-w-xs sm:max-w-sm md:max-w-md">
<br> {{ $firstPart }} <br> {{ $secondPart }}
</span>
</div>
<div class="w-8 h-8 rounded-md overflow-hidden">
<div
class="sm:w-14 lg:w-24 2xl:w-32 sm:h-14 lg:h-24 2xl:h-32 rounded-md overflow-hidden border border-gray-300">
<img src="{{ asset('storage/' . $course->img) }}"
class="aspect-square shadow-md shadow-gray-500 object-cover" alt="">
class="aspect-square shadow-md shadow-gray-500 object-cover"
alt="">
</div>
</div>
</td>
<td class=" py-4 text-end px-4">
<td class="py-4 text-end px-4 border-r border-gray-300">
<div class="flex flex-col justify-center text-end poppins-regular">
<span class="mb-2">
{{ $course->kategoris ? $course->kategoris->nama_kategori : 'Kategori tidak tersedia' }}
</span>
<span>{{ $course->popular }}</span>
</div>
</td>
<td class=" py-4 text-end items-center px-4">
<div> {!! Str::limit($course->paket, 50, '...') !!}</div>
{{-- <td class="py-4 text-end px-4 border-r border-gray-300">{!! Str::limit($course->paket, 50, '...') !!}</td>
<td class="py-4 text-end px-4 border-r border-gray-300">{!! Str::limit($course->metode, 50, '...') !!}</td>
<td class="py-4 text-end px-4 border-r border-gray-300">{!! Str::limit($course->lokasi, 50, '...') !!}</td> --}}
<td class="py-4 text-end px-4 border-r border-gray-300 uppercase">
@php
$fasilitasArray = json_decode($course->fasilitas, true);
$fasilitasText = $fasilitasArray ? implode(', ', $fasilitasArray) : '-';
@endphp
{!! Str::limit($fasilitasText, 50, '...') !!}
</td>
<td class=" py-4 text-end items-center px-4">
<div> {!! Str::limit($course->metode, 50, '...') !!}</div>
</td>
<td class=" py-4 text-end items-center px-4">
<div> {!! Str::limit($course->fasilitas, 50, '...') !!}</div>
</td>
<td class=" py-4 text-end items-center px-4">
<div> {!! Str::limit($course->lokasi, 50, '...') !!}</div>
</td>
<td class=" py-4 text-end items-center px-4">
<td class="py-4 text-end px-4 border-r border-gray-300">
{{ $course->latitude }},{{ $course->longitude }}</td>
<td class="py-4 text-end px-4">
<div class="flex justify-end items-center space-x-1 md:space-x-2">
<!-- Detail Button with Icon -->
<div>
<button data-modal-target="modal-detail{{ $course->id }}"
data-modal-toggle="modal-detail{{ $course->id }}"
class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-green-800 text-white py-2 px-2 bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-lg h-fit">
<i class="fas fa-info-circle text-xs"></i> <!-- Icon Detail -->
</button>
</div>
<button data-modal-target="modal-detail{{ $course->id }}"
data-modal-toggle="modal-detail{{ $course->id }}"
class="font-extrabold text-xs shadow-md hover:bg-blue-600 text-white py-2 px-2 bg-blue-500 rounded-lg transition">
<i class="fas fa-info-circle text-xs"></i>
</button>
<!-- Edit Button with Icon -->
<div>
<a href="/admin/{{ $course->id }}/edit-kursus"
class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-green-800 text-white py-2 px-2 bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-lg h-fit">
<i class="fas fa-edit text-xs"></i> <!-- Icon Edit -->
</a>
</div>
<a href="/admin/{{ $course->id }}/edit-kursus"
class="font-extrabold text-xs shadow-md hover:bg-yellow-600 text-white py-2 px-2 bg-yellow-500 rounded-lg transition">
<i class="fas fa-edit text-xs"></i>
</a>
<!-- Delete Button with Icon -->
<div>
<button data-modal-target="popup-modal-{{ $course->id }}"
data-modal-toggle="popup-modal-{{ $course->id }}"
class="font-extrabold text-xs shadow-md shadow-gray-600 hover:bg-green-800 text-white py-2 px-2 bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-lg h-fit">
<i class="fas fa-trash-alt text-xs"></i> <!-- Icon Delete -->
</button>
</div>
<button data-modal-target="popup-modal-{{ $course->id }}"
data-modal-toggle="popup-modal-{{ $course->id }}"
class="font-extrabold text-xs shadow-md hover:bg-red-600 text-white py-2 px-2 bg-red-500 rounded-lg transition">
<i class="fas fa-trash-alt text-xs"></i>
</button>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@foreach ($courses as $course)
<!-- Modal Konfirmasi -->
<div id="popup-modal-{{ $course->id }}" tabindex="-1"
@ -170,7 +180,7 @@ class="py-2.5 px-5 ms-3 text-sm poppins-regular text-gray-900 focus:outline-none
</div>
<!-- Main modal -->
@foreach ($courses as $course)

View File

@ -1,5 +1,5 @@
<x-adminlayout>
<div class="container">
<div class="">
<div class="py-10 px-4">
<div class="pb-4 flex">
<a class="px-4 flex text-white text-lg justify-center shadow-md shadow-gray-600 items-center py-2 rounded-xl bg-[#4F7F81]"
@ -50,11 +50,11 @@ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:
</div>
<!-- Input File Single -->
<div>
<label for="deskripsi" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">
<label for="deskripsi" class="block mb-2 text-sm font-medium text-gray-900 ">
Deskripsi
</label>
<textarea id="deskripsi" name="deskripsi" rows="4"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:placeholder-gray-400"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 "
placeholder="KAMPUNG INGGRIS LC LANGUAGE CENTER Adalah . . . ." required>{{ old('deskripsi') }}</textarea>
</div>
<div class="flex justify-between w-full gap-4">
@ -102,13 +102,7 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
</div>
<!-- Fasilitas -->
<div>
<label for="fasilitas" class="block mb-2 text-sm font-medium text-gray-900">Fasilitas</label>
<input id="fasilitas" name="fasilitas" type="hidden" value="{{ old('fasilitas') }}" />
<trix-editor input="fasilitas"
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
placeholder="Write your thoughts here..."></trix-editor>
</div>
<!-- Lokasi -->
<div>
@ -118,6 +112,93 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
placeholder="Write your thoughts here..."></trix-editor>
</div>
<div>
<label for="fasilitas" class="block mb-2 text-sm font-medium text-gray-900">Fasilitas</label>
<input id="fasilitas" name="fasilitas" type="hidden" value="{{ old('fasilitas') }}" />
<!-- Tombol tambah fasilitas -->
<div id="facility-inputs" class=" grid grid-cols-4 gap-4">
<!-- Input fasilitas akan ditambahkan di sini -->
</div>
<button id="add-facility-btn" type="button"
class="mt-3 px-4 py-2 text-xs bg-blue-500 text-white rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Tambah Fasilitas
</button>
</div>
<!-- Script untuk menambah input fasilitas -->
<script>
let facilityIndex = 0; // Untuk memastikan setiap input memiliki ID unik
// Fungsi untuk menambahkan input fasilitas
function addFacilityInput() {
// Buat div baru untuk input fasilitas
const facilityDiv = document.createElement('div');
facilityDiv.classList.add('facility-input', 'bg-gray-100', 'rounded-lg');
// Buat label untuk input fasilitas
const label = document.createElement('label');
label.setAttribute('for', 'fasilitas_' + facilityIndex);
label.classList.add('block', 'text-sm', 'font-medium', 'text-gray-700');
// Buat input untuk fasilitas
const input = document.createElement('input');
input.id = 'fasilitas_' + facilityIndex;
input.name = 'fasilitas_' + facilityIndex;
input.type = 'text';
input.classList.add('block', 'w-full', 'px-3', 'py-2', 'border', 'border-gray-300', 'rounded-md',
'shadow-sm');
input.placeholder = 'Masukkan fasilitas';
// Buat tombol hapus untuk input fasilitas ini
const deleteButton = document.createElement('button');
deleteButton.type = 'button';
deleteButton.classList.add('ml-2', 'text-red-500', 'hover:text-red-700');
deleteButton.textContent = 'Hapus';
deleteButton.addEventListener('click', function() {
facilityDiv.remove();
updateFasilitasInput();
});
// Menambahkan elemen-elemen ke dalam div fasilitas
facilityDiv.appendChild(label);
facilityDiv.appendChild(input);
facilityDiv.appendChild(deleteButton);
// Menambahkan div fasilitas ke dalam kontainer
document.getElementById('facility-inputs').appendChild(facilityDiv);
// Update indeks fasilitas untuk input selanjutnya
facilityIndex++;
// Update input tersembunyi dengan nilai terbaru JSON
updateFasilitasInput();
}
// Tambahkan fasilitas pertama kali saat halaman dimuat
addFacilityInput();
// Event listener untuk tombol tambah fasilitas
document.getElementById('add-facility-btn').addEventListener('click', function() {
addFacilityInput();
});
// Fungsi untuk memperbarui nilai JSON di input tersembunyi
function updateFasilitasInput() {
const fasilitasArray = [];
const facilityInputs = document.querySelectorAll('.facility-input input');
// Ambil nilai dari semua input fasilitas
facilityInputs.forEach(input => {
if (input.value.trim() !== '') {
fasilitasArray.push(input.value.trim());
}
});
// Setel nilai JSON di input tersembunyi
document.getElementById('fasilitas').value = JSON.stringify(fasilitasArray);
}
</script>
<div>
<label for="latitude" class="block mb-2 text-sm font-medium text-gray-900">Uplaud
Gambar</label>
@ -125,18 +206,18 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
<div class="grid grid-cols-1 gap-4">
<div>
<label for="file_input"
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-gray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 ">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
<svg class="w-8 h-8 mb-4 text-gray-500 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2" />
</svg>
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span
class="font-semibold">Click to upload Single</p>
<p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF
<p class="mb-2 text-sm text-gray-500 "><span class="font-semibold">Click
to upload Single</p>
<p class="text-xs text-gray-500 ">SVG, PNG, JPG or GIF
</p>
<input id="file_input" type="file" name="img" class="hidden"
onchange="previewImage(event)" />
@ -157,18 +238,18 @@ class="aspect-video h-40 object-contain" />
<div class="grid grid-cols-1 gap-4">
<div>
<label for="multiple_files"
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-gray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 ">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
<svg class="w-8 h-8 mb-4 text-gray-500 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2" />
</svg>
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span
class="font-semibold">Click to upload Multi</p>
<p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF
<p class="mb-2 text-sm text-gray-500 "><span class="font-semibold">Click
to upload Multi</p>
<p class="text-xs text-gray-500 ">SVG, PNG, JPG or GIF
</p>
<input id="multiple_files" type="file" name="img_konten[]" multiple
onchange="previewMultipleImages(event)" class="hidden" />

View File

@ -1,5 +1,5 @@
<x-adminlayout>
<div class="container">
<div class="">
<div class="py-10 px-4">
<div class="pb-4 flex">
<a class="px-4 flex text-white text-lg justify-center items-center py-2 rounded-xl bg-[#4F7F81]"
@ -28,11 +28,10 @@ class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:
placeholder="Kampung Inggris LC - Language Center" required />
</div>
<div class="hidden">
<label for="countries"
class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Pilih
<label for="countries" class="block mb-2 text-sm font-medium text-gray-900 ">Pilih
Popular</label>
<select id="countries" name="popular"
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 ">
<option selected>{{ $dataKursus->popular }}</option>
@if ($dataKursus->popular === 'popular')
<option value="Tidak">Tidak</option>
@ -112,15 +111,7 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
placeholder="Write your thoughts here..."></trix-editor>
</div>
<!-- Fasilitas -->
<div>
<label for="fasilitas" class="block mb-2 text-sm font-medium text-gray-900">Fasilitas</label>
<input id="fasilitas" name="fasilitas" type="hidden"
value="{{ old('fasilitas', $dataKursus->fasilitas) }}" />
<trix-editor input="fasilitas"
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
placeholder="Write your thoughts here..."></trix-editor>
</div>
<!-- Lokasi -->
<div>
@ -131,6 +122,87 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500"
placeholder="Write your thoughts here..."></trix-editor>
</div>
<!-- Fasilitas -->
<div>
<label for="fasilitas" class="block mb-2 text-sm font-medium text-gray-900">Fasilitas</label>
<input id="fasilitas" name="fasilitas" type="hidden" value='{!! json_encode($fasilitas ?? []) !!}' />
<!-- Inputan dinamis untuk fasilitas -->
<div id="facility-inputs" class="grid grid-cols-4 gap-4">
@foreach ($fasilitas as $index => $item)
<div class="facility-input bg-gray-100 p-2 rounded-lg flex gap-2 items-center">
<input type="text" name="fasilitas[]" value="{{ $item }}"
class="block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm" />
<button type="button"
class="remove-facility text-red-500 hover:text-red-700">Hapus</button>
</div>
@endforeach
</div>
<!-- Tombol tambah fasilitas -->
<button id="add-facility-btn" type="button"
class="mt-3 px-4 py-2 text-xs bg-blue-500 text-white rounded-lg hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500">
Tambah Fasilitas
</button>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const facilityContainer = document.getElementById('facility-inputs');
const hiddenFasilitasInput = document.getElementById('fasilitas');
function updateFasilitas() {
let fasilitasArray = [];
facilityContainer.querySelectorAll("input[name='fasilitas[]']").forEach(input => {
if (input.value.trim() !== '') {
fasilitasArray.push(input.value.trim());
}
});
hiddenFasilitasInput.value = JSON.stringify(fasilitasArray);
}
// Event listener untuk tombol tambah fasilitas
document.getElementById('add-facility-btn').addEventListener('click', function() {
const div = document.createElement('div');
div.classList.add('facility-input', 'bg-gray-100', 'p-2', 'rounded-lg', 'flex', 'gap-2',
'items-center');
const input = document.createElement('input');
input.type = 'text';
input.name = 'fasilitas[]';
input.classList.add('block', 'w-full', 'px-3', 'py-2', 'border', 'border-gray-300',
'rounded-md', 'shadow-sm');
input.placeholder = 'Masukkan fasilitas';
const deleteButton = document.createElement('button');
deleteButton.type = 'button';
deleteButton.textContent = 'Hapus';
deleteButton.classList.add('text-red-500', 'hover:text-red-700');
deleteButton.addEventListener('click', function() {
div.remove();
updateFasilitas();
});
div.appendChild(input);
div.appendChild(deleteButton);
facilityContainer.appendChild(div);
});
// Event listener untuk tombol hapus
facilityContainer.addEventListener('click', function(event) {
if (event.target.classList.contains('remove-facility')) {
event.target.parentElement.remove();
updateFasilitas();
}
});
// Perbarui input fasilitas setiap kali terjadi perubahan
facilityContainer.addEventListener('input', updateFasilitas);
});
</script>
<div>
<label for="latitude" class="block mb-2 text-sm font-medium text-gray-900">Upload
Gambar</label>
@ -138,19 +210,19 @@ class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border bor
<div class="grid grid-cols-1 gap-4">
<div>
<label for="file_input"
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-gray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 ">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
<svg class="w-8 h-8 mb-4 text-gray-500 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2" />
</svg>
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span
class="font-semibold">Click to
<p class="mb-2 text-sm text-gray-500 "><span class="font-semibold">Click
to
upload Single</p>
<p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF
<p class="text-xs text-gray-500 ">SVG, PNG, JPG or GIF
</p>
<input id="file_input" type="file" name="img" class="hidden"
onchange="previewImage(event)" />
@ -180,19 +252,19 @@ class="block w-full text-white bg-[#4F7F81] hover:bg-[#3F6A6B] focus:ring-4 focu
<div class="grid grid-cols-1 gap-4">
<div>
<label for="multiple_files"
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 dark:hover:bg-gray-800 dark:bg-gray-700 hover:bg-gray-100 dark:border-gray-600 dark:hover:border-gray-500 dark:hover:bg-gray-600">
class="flex flex-col items-center justify-center w-full h-64 border-2 border-gray-300 border-dashed rounded-lg cursor-pointer bg-gray-50 ">
<div class="flex flex-col items-center justify-center pt-5 pb-6">
<svg class="w-8 h-8 mb-4 text-gray-500 dark:text-gray-400"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
<svg class="w-8 h-8 mb-4 text-gray-500 " aria-hidden="true"
xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round"
stroke-linejoin="round" stroke-width="2"
d="M13 13h3a3 3 0 0 0 0-6h-.025A5.56 5.56 0 0 0 16 6.5 5.5 5.5 0 0 0 5.207 5.021C5.137 5.017 5.071 5 5 5a4 4 0 0 0 0 8h2.167M10 15V6m0 0L8 8m2-2 2 2" />
</svg>
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span
class="font-semibold">Click to
<p class="mb-2 text-sm text-gray-500 "><span class="font-semibold">Click
to
upload Multi</p>
<p class="text-xs text-gray-500 dark:text-gray-400">SVG, PNG, JPG or GIF
<p class="text-xs text-gray-500 ">SVG, PNG, JPG or GIF
</p>
<input id="multiple_files" type="file" name="img_konten[]" multiple
onchange="previewMultipleImages(event)" class="hidden" />
@ -245,8 +317,7 @@ class="object-contain max-h-48 mx-auto" alt="Gambar">
<!-- Multiple Files Modal -->
<div id="multiple-files-modal" tabindex="-1" aria-hidden="true"
class="hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full px-4">
<div
class="relative overflow-x-auto p-4 w-full max-w-2xl max-h-full rounded-lg">
<div class="relative overflow-x-auto p-4 w-full max-w-2xl max-h-full rounded-lg">
<div class="flex items-center justify-center">
<!-- Flex container to arrange images horizontally -->
@if (!empty($dataKursus->img_konten))

View File

@ -2,40 +2,24 @@
<html lang="en">
<head>
@include('components.navbarAdmin')
{{-- @vite(['resources/css/app.css', 'resources/js/app.js']) --}}
{{-- <script src="../path/to/flowbite/dist/flowbite.min.js"></script> --}}
{{-- <script src="https://cdn.jsdelivr.net/npm/flowbite@3.0.0/dist/flowbite.min.js"></script> --}}
@include('partials.head')
@vite(['resources/css/app.css', 'resources/js/app.js'])
@vite(['resources/css/app.css', 'resources/js/app.js', 'public/css/font.css'])
@include('partials.font')
@include('partials.notification')
</head>
<body>
@if (session('success'))
<div id="notification"
class="fixed top-4 left-1/2 transform -translate-x-1/2 bg-green-50 text-green-800 border border-green-300 rounded-lg p-4 z-20">
<div class="flex items-center">
<svg class="flex-shrink-0 w-4 h-4 me-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z" />
</svg>
<span class="font-medium">{{ session('success') }}</span>
</div>
@include('components.navbarAdmin')
<div class="p-4 sm:ml-64">
<div class="p-4 border-2 border-gray-200 border-dashed rounded-lg dark:border-gray-700 mt-14">
{{ $slot }}
</div>
@endif
<script>
document.addEventListener('DOMContentLoaded', function() {
const notification = document.getElementById('notification');
if (notification) {
setTimeout(() => {
notification.classList.add('hidden');
}, 5000); // 5000 milliseconds = 5 seconds
}
});
</script>
<script src="../path/to/flowbite/dist/flowbite.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.0.0/dist/flowbite.min.js"></script>
{{ $slot }}
</div>
</body>

View File

@ -1,5 +1,5 @@
<footer class="bg-green-900">
<div class="mx-auto container w-full py-6 lg:py-8">
<div class="mx-auto container w-full px-4 py-6 lg:py-8">
<div class="space-y-10 md:flex md:justify-between">
<div>
<a href="#" class="flex items-start justify-start ml-[-10px]">
@ -15,7 +15,7 @@ class="self-center pt-6 text-4xl text-white barlow-condensed-semibold whitespace
</div>
<div class="grid grid-cols-2 gap-8 sm:gap-6 sm:grid-cols-3">
<div>
<h2 class="mb-6 text-sm poppin-semibold text-white uppercase">Resources
<h2 class="mb-6 text-sm poppins-semibold text-white uppercase">Resources
</h2>
<ul class="text-white poppins-regular space-y-4">
<li class="">
@ -34,8 +34,7 @@ class="self-center pt-6 text-4xl text-white barlow-condensed-semibold whitespace
</h2>
<ul class="text-white poppins-regular space-y-4">
<li class="">
<a href="#"
class="hover:underline ">Github</a>
<a href="#" class="hover:underline ">Github</a>
</li>
<li>
<a href="#" class="hover:underline">Discord</a>

View File

@ -1,10 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="scroll-smooth">
<head>
@vite(['resources/css/app.css', 'resources/js/app.js', 'public/css/font.css'])
@include('components.navbar')
@include('partials.font')
@include('partials.head')
</head>

View File

@ -1,61 +1,101 @@
<div class=" flex justify-center relative">
<nav
class="z-50 container bg-white text-white rounded-full fixed top-4 p-2 flex items-center justify-between shadow-lg w-full w-full mx-auto">
<!-- Logo dan Nama Aplikasi -->
<a href="{{ route('user.home') }}" class="flex items-center">
<img src="{{ asset('img/logo3.png') }}" class="h-10 w-10" alt="Logo LearnMap" />
<span class="ml-2 text-2xl barlow-condensed-semibold text-green-800">LearnMap</span>
</a>
<div class="flex justify-center ">
<nav class="container px-4 top-4 fixed z-[999] ">
<div class="flex justify-between py-2 items-center shadow-lg bg-white px-4 rounded-full text-white">
<a href="#" class="flex items-center">
<svg class="h-7 w-7 text-green-700" viewBox="0 0 24 24" fill="currentColor"
xmlns="http://www.w3.org/2000/svg">
<path
d="M12 2C8 2 5 5 5 9c0 5 7 11 7 11s7-6 7-11c0-4-3-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5S10.62 6.5 12 6.5s2.5 1.12 2.5 2.5S13.38 11.5 12 11.5z" />
</svg>
<span class="text-2xl font-semibold text-green-800">LearnMap</span>
</a>
<div class="hidden md:flex" id="navbar-menu">
<ul class="flex space-x-8 text-lg poppins-regular">
<li>
<a href="{{ route('user.home') }}"
class="text-black hover:text-green-600 {{ Request::routeIs('user.home') ? 'text-green-700 ' : '' }}">
Beranda
</a>
</li>
<li>
<a href="{{ route('user.kursus') }}"
class="text-black hover:text-green-600 {{ Request::routeIs('user.kursus') ? 'text-green-700 ' : '' }}">
Kursus
</a>
</li>
<li>
<a href="{{ route('user.peta') }}"
class="text-black hover:text-green-600 {{ Request::routeIs('user.peta') ? 'text-green-700 ' : '' }}">
Peta
</a>
</li>
</ul>
<!-- Menu Navigasi -->
<ul class="flex space-x-8 text-lg poppins-regular">
<li><a href="{{ route('user.home') }}" class="text-black hover:text-green-600">Beranda</a></li>
<li><a href="{{ route('user.kursus') }}" class="text-black hover:text-green-600">Kursus</a></li>
<li><a href="{{ route('user.peta') }}" class="text-black hover:text-green-600">Peta</a></li>
</ul>
<!-- Tombol Login atau Dropdown User -->
@if (Auth::check())
<div class="relative">
<button type="button" class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300"
id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown">
<span class="sr-only">Open user menu</span>
<img class="w-8 h-8 rounded-full"
src="{{ Auth::user()->avatar ?: 'https://www.gravatar.com/avatar/' . md5(strtolower(trim(Auth::user()->email))) }}?d=identicon"
alt="user photo">
</div>
<div class="flex items-center">
<!-- Hamburger Button (hanya tampil di mobile) -->
<button data-collapse-toggle="navbar-menu" type="button"
class="md:hidden inline-flex items-center p-2 w-10 h-10 justify-center text-gray-500 rounded-lg hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200"
aria-controls="navbar-menu" aria-expanded="false">
<span class="sr-only">Open main menu</span>
<svg class="w-6 h-6" aria-hidden="true" fill="none" viewBox="0 0 17 14"
xmlns="http://www.w3.org/2000/svg">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M1 1h15M1 7h15M1 13h15"></path>
</svg>
</button>
<!-- Dropdown Menu -->
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow"
id="user-dropdown">
<div class="px-4 py-3">
<span class="block text-sm text-gray-900">{{ Auth::user()->name }}</span>
<span class="block text-sm text-gray-500 truncate">{{ Auth::user()->email }}</span>
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
@if (Auth::user() && Auth::user()->role === 'admin')
<li>
<a href="{{ route('admin.home') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a>
</li>
@endif
<li>
<a href="{{ route('password.edit') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Setting</a>
</li>
<li>
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit"
class="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 text-left">Sign
out</button>
</form>
</li>
</ul>
<!-- Login / Dropdown User -->
<div class="ml-4">
@if (Auth::check())
<div class="relative" data-dropdown>
<button type="button"
class="flex items-center text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300"
id="user-menu-button" aria-expanded="false" data-dropdown-toggle="user-dropdown">
<span class="sr-only">Open user menu</span>
<img class="w-8 h-8 rounded-full"
src="{{ Auth::user()->avatar ?: 'https://www.gravatar.com/avatar/' . md5(strtolower(trim(Auth::user()->email))) }}?d=identicon"
alt="user photo">
</button>
<!-- Dropdown Menu -->
<div id="user-dropdown"
class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-lg shadow"
data-popper-placement="bottom">
<div class="px-4 py-3">
<span class="block text-sm text-gray-900">{{ Auth::user()->name }}</span>
<span class="block text-sm text-gray-500 truncate">{{ Auth::user()->email }}</span>
<span
class="block text-sm text-gray-500 truncate">{{ Auth::user()->username }}</span>
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
@if (in_array(Auth::user()->role, ['admin', 'user']))
<li>
<a href="{{ route('admin.home') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a>
</li>
@endif
<li>
<a href="{{ route('password.edit') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Setting</a>
</li>
<li>
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit"
class="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 text-left">Sign
out</button>
</form>
</li>
</ul>
</div>
</div>
@else
<a href="{{ route('login') }}"
class="bg-green-900 text-white px-5 py-2 text-xs lg:text-sm rounded-full hover:bg-green-700">Login</a>
@endif
</div>
</div>
@else
<a href="{{ route('login') }}"
class="bg-green-900 text-white px-4 py-2 rounded-full hover:bg-green-700">Login</a>
@endif
</div>
</nav>
</div>
</div>

View File

@ -1,30 +1,21 @@
<div class="flex justify-center relative">
<nav class="z-50 container bg-white text-white rounded-full fixed top-4 p-2 flex items-center justify-between shadow-lg w-full max-w-4xl mx-auto">
{{-- <div class=" flex justify-center relative">
<nav
class="z-50 container bg-white text-white rounded-full fixed top-4 p-2 flex items-center justify-between shadow-lg w-full mx-auto">
<!-- Logo dan Nama Aplikasi -->
<a href="{{ route('user.home') }}" class="flex items-center">
<img src="{{ asset('img/Rectangle 65.png') }}" class="h-10 w-10" alt="Logo LearnMap" />
<span class="ml-2 text-2xl font-semibold text-black">LearnMap</span>
<img src="{{ asset('img/logo3.png') }}" class="h-10 w-10" alt="Logo LearnMap" />
<span class="ml-2 text-2xl barlow-condensed-semibold text-green-800">LearnMap</span>
</a>
<!-- Menu Navigasi -->
<ul class="flex space-x-8 text-lg poppins-regular">
<li>
<a href="{{ route('admin.home') }}" class="text-black hover:text-green-600 ">
Dashboard
</a>
</li>
<li>
<a href="{{ route('kategori.index') }}" class="text-black hover:text-green-600">
Kategori
</a>
</li>
<li>
<a href="{{ route('admin.dataKursus') }}" class="text-black hover:text-green-600">
Data Kursus
</a>
</li>
</ul>
@if (Auth::user() && in_array(Auth::user()->role, ['admin', 'user']))
<ul class="flex space-x-8 text-lg poppins-regular">
<li><a href="{{ route('admin.home') }}" class="text-black hover:text-green-600">Beranda</a></li>
<li><a href="{{ route('kategori.index') }}" class="text-black hover:text-green-600">Kategori</a></li>
<li><a href="{{ route('user.index') }}" class="text-black hover:text-green-600">User</a></li>
</ul>
@else
@endif
<!-- Tombol Login atau Dropdown User -->
@if (Auth::check())
<div class="relative">
@ -43,10 +34,12 @@
<span class="block text-sm text-gray-500 truncate">{{ Auth::user()->email }}</span>
</div>
<ul class="py-2" aria-labelledby="user-menu-button">
<li>
<a href="{{ route('admin.home') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a>
</li>
@if (Auth::user() && in_array(Auth::user()->role, ['admin', 'user']))
<li>
<a href="{{ route('admin.home') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Dashboard</a>
</li>
@endif
<li>
<a href="{{ route('password.edit') }}"
class="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100">Setting</a>
@ -67,65 +60,152 @@ class="block w-full px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 text-left"
class="bg-green-900 text-white px-4 py-2 rounded-full hover:bg-green-700">Login</a>
@endif
</nav>
</div>
</div> --}}
<!-- Modal Konfirmasi -->
<div id="popup-modal" tabindex="-1"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-md max-h-full">
<div class="relative bg-white rounded-lg shadow">
<button type="button"
class="absolute top-3 end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center"
data-modal-hide="popup-modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
<span class="sr-only">Close modal</span>
</button>
<div class="p-4 md:p-5 text-center">
<svg class="mx-auto mb-4 text-[#3F6A6B] w-12 h-12" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
<h3 class="mb-5 text-lg font-normal text-black">
Apakah Anda yakin ingin keluar?
</h3>
<div class="flex justify-center">
<form id="logout-form" method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit"
class="text-white bg-[#4F7F81] hover:bg-[#3F6A6B] focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm inline-flex items-center px-5 py-2.5 text-center">
Ya, Keluar
<nav class="fixed top-0 z-50 w-full bg-white border-b border-gray-200 dark:bg-gray-800 dark:border-gray-700">
<div class="px-3 py-3 lg:px-5 lg:pl-3">
<div class="flex items-center justify-between">
<div class="flex items-center justify-start rtl:justify-end">
<button data-drawer-target="logo-sidebar" data-drawer-toggle="logo-sidebar" aria-controls="logo-sidebar"
type="button"
class="inline-flex items-center p-2 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
<span class="sr-only">Open sidebar</span>
<svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg">
<path clip-rule="evenodd" fill-rule="evenodd"
d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z">
</path>
</svg>
</button>
<a href="{{ route('user.home') }}" class="flex items-center">
<svg class="h-7 w-7 text-green-700" viewBox="0 0 24 24" fill="currentColor"
xmlns="http://www.w3.org/2000/svg">
<path
d="M12 2C8 2 5 5 5 9c0 5 7 11 7 11s7-6 7-11c0-4-3-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5S10.62 6.5 12 6.5s2.5 1.12 2.5 2.5S13.38 11.5 12 11.5z" />
</svg>
<span class="text-2xl font-semibold text-green-800">LearnMap</span>
</a>
</div>
<div class="flex items-center">
<div class="flex items-center ms-3">
<div>
<button type="button"
class="flex text-sm bg-gray-800 rounded-full focus:ring-4 focus:ring-gray-300 dark:focus:ring-gray-600"
aria-expanded="false" data-dropdown-toggle="dropdown-user">
<span class="sr-only">Open user menu</span>
<img class="w-8 h-8 rounded-full"
src="https://flowbite.com/docs/images/people/profile-picture-5.jpg" alt="user photo">
</button>
</form>
<button type="button"
class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-[#3F6A6B] focus:z-10 focus:ring-4 focus:ring-gray-100"
data-modal-hide="popup-modal">
Tidak, Batal
</button>
</div>
<div class="z-50 hidden my-4 text-base list-none bg-white divide-y divide-gray-100 rounded-sm shadow-sm dark:bg-gray-700 dark:divide-gray-600"
id="dropdown-user">
<div class="px-4 py-3" role="none">
<p class="text-sm text-green-900 dark:text-white" role="none">
{{ Auth::user()->email }}
</p>
<p class="text-sm font-medium text-green-900 truncate dark:text-gray-300" role="none">
{{ Auth::user()->name }}
</p>
</div>
<ul class="py-1" role="none">
<li>
<a href="{{ route('admin.home') }}"
class="block px-4 py-2 text-sm text-green-700 hover:bg-gray-100 "
role="menuitem">Dashboard</a>
</li>
<li>
<a href="{{ route('password.edit') }}"
class="block px-4 py-2 text-sm text-green-700 hover:bg-gray-100 "
role="menuitem">Settings</a>
</li>
<li>
<form action="{{ route('logout') }}" method="POST"
class="block px-4 py-2 text-sm text-green-700 hover:bg-gray-100 ">
@csrf
<button type="submit" class="w-full text-left">Sign out</button>
</form>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</nav>
<script>
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('[data-modal-toggle]').forEach(button => {
button.addEventListener('click', () => {
const targetId = button.getAttribute('data-modal-target');
document.getElementById(targetId).classList.remove('hidden');
});
});
<aside id="logo-sidebar"
class="fixed top-0 left-0 z-40 w-64 h-screen pt-20 transition-transform -translate-x-full bg-white border-r border-gray-200 sm:translate-x-0"
aria-label="Sidebar">
<div class="h-full px-3 pb-4 overflow-y-auto bg-white">
<ul class="space-y-2 font-medium">
<li>
@if (Auth::user() && in_array(Auth::user()->role, ['admin', 'user']))
<a href="{{ route('admin.home') }}"
class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-green-100 group {{ request()->routeIs('admin.home') ? 'bg-green-200 text-green-700' : 'hover:bg-green-100 hover:text-green-600' }}">
<svg class="w-5 h-5 transition duration-75 group-hover:text-green-700 {{ request()->routeIs('admin.home') ? 'text-green-700' : 'text-gray-500' }}"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 22 21">
<path
d="M16.975 11H10V4.025a1 1 0 0 0-1.066-.998 8.5 8.5 0 1 0 9.039 9.039.999.999 0 0 0-1-1.066h.002Z" />
<path
d="M12.5 0c-.157 0-.311.01-.565.027A1 1 0 0 0 11 1.02V10h8.975a1 1 0 0 0 1-.935c.013-.188.028-.374.028-.565A8.51 8.51 0 0 0 12.5 0Z" />
</svg>
<span class="ms-3">Dashboard</span>
</a>
@else
@endif
</li>
document.querySelectorAll('[data-modal-hide]').forEach(button => {
button.addEventListener('click', () => {
const targetId = button.getAttribute('data-modal-hide');
document.getElementById(targetId).classList.add('hidden');
});
});
});
</script>
@if (Auth::user() && in_array(Auth::user()->role, ['user']))
<li>
<a href="{{ route('admin.dataKursus') }}"
class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-green-100 group
{{ request()->routeIs(['admin.create', 'admin.dataKursus', 'admin.edit']) ? 'bg-green-200 text-green-700' : 'hover:bg-green-100 hover:text-green-600' }}">
<svg class="w-5 h-5 transition duration-75 group-hover:text-green-700
{{ request()->routeIs(['admin.create', 'admin.dataKursus', 'admin.edit']) ? 'text-green-700' : 'text-gray-500' }}"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 18 20">
<path
d="M17 5.923A1 1 0 0 0 16 5h-3V4a4 4 0 1 0-8 0v1H2a1 1 0 0 0-1 .923L.086 17.846A2 2 0 0 0 2.08 20h13.84a2 2 0 0 0 1.994-2.153L17 5.923ZM7 9a1 1 0 0 1-2 0V7h2v2Zm0-5a2 2 0 1 1 4 0v1H7V4Zm6 5a1 1 0 1 1-2 0V7h2v2Z" />
</svg>
<span class="ms-3">Kursus</span>
</a>
</li>
@else
<li>
<a href="{{ route('kategori.index') }}"
class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-green-100 group {{ request()->routeIs('kategori.index') ? 'bg-green-200 text-green-700' : 'hover:bg-green-100 hover:text-green-600' }}">
<svg class="w-5 h-5 transition duration-75 group-hover:text-green-700 {{ request()->routeIs('kategori.index') ? 'text-green-700' : 'text-gray-500' }}"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 18 18">
<path
d="M6.143 0H1.857A1.857 1.857 0 0 0 0 1.857v4.286C0 7.169.831 8 1.857 8h4.286A1.857 1.857 0 0 0 8 6.143V1.857A1.857 1.857 0 0 0 6.143 0Zm10 0h-4.286A1.857 1.857 0 0 0 10 1.857v4.286C10 7.169 10.831 8 11.857 8h4.286A1.857 1.857 0 0 0 18 6.143V1.857A1.857 1.857 0 0 0 16.143 0Zm-10 10H1.857A1.857 1.857 0 0 0 0 11.857v4.286C0 17.169.831 18 1.857 18h4.286A1.857 1.857 0 0 0 8 16.143v-4.286A1.857 1.857 0 0 0 6.143 10Zm10 0h-4.286A1.857 1.857 0 0 0 10 11.857v4.286c0 1.026.831 1.857 1.857 1.857h4.286A1.857 1.857 0 0 0 18 16.143v-4.286A1.857 1.857 0 0 0 16.143 10Z" />
</svg>
<span class="ms-3">Kategori</span>
</a>
</li>
<li>
<a href="{{ route('user.index') }}"
class="flex items-center p-2 text-gray-900 rounded-lg hover:bg-green-100 group {{ request()->routeIs('user.index') ? 'bg-green-200 text-green-700' : 'hover:bg-green-100 hover:text-green-600' }}">
<svg class="w-5 h-5 transition duration-75 group-hover:text-green-700 {{ request()->routeIs('user.index') ? 'text-green-700' : 'text-gray-500' }}"
aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor"
viewBox="0 0 20 18">
<path
d="M14 2a3.963 3.963 0 0 0-1.4.267 6.439 6.439 0 0 1-1.331 6.638A4 4 0 1 0 14 2Zm1 9h-1.264A6.957 6.957 0 0 1 15 15v2a2.97 2.97 0 0 1-.184 1H19a1 1 0 0 0 1-1v-1a5.006 5.006 0 0 0-5-5ZM6.5 9a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM8 10H5a5.006 5.006 0 0 0-5 5v2a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-2a5.006 5.006 0 0 0-5-5Z" />
</svg>
<span class="ms-3">Users</span>
</a>
</li>
@endif
</ul>
</div>
</aside>

View File

@ -1,27 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1.0" name="viewport"/>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1.0" name="viewport" />
<title>Login</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet"/>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet" />
<style>
body {
font-family: 'Inter', sans-serif;
}
</style>
</head>
<body class="bg-gray-100">
@if (session('success'))
<div class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-3 rounded-md shadow-lg z-50">
<div
class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-green-500 text-white px-6 py-3 rounded-md shadow-lg z-50">
{{ session('success') }}
</div>
@endif
@if (session('error'))
<div
class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-6 py-3 rounded-md shadow-lg z-50">
{{ session('error') }}
</div>
@endif
@if ($errors->any())
<div class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-6 py-3 rounded-md shadow-lg z-50">
<div
class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-6 py-3 rounded-md shadow-lg z-50">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@ -45,16 +54,22 @@
<form method="POST">
@csrf
<div class="mb-4">
<label class="block text-sm poppins-regular mb-1" for="email">Email*</label>
<input class="w-full border border-gray-300 rounded-lg py-2 px-3" id="email" name="email" placeholder="Enter your email" type="email" required/>
<label class="block text-sm poppins-regular mb-1" for="login">Email/Username*</label>
<input class="w-full border border-gray-300 rounded-lg py-2 px-3" id="login" name="login"
placeholder="Enter your email or username" type="text" required />
</div>
<div class="mb-4">
<label class="block text-sm poppins-regular mb-1" for="password">Password*</label>
<input class="w-full border border-gray-300 rounded-lg py-2 px-3" id="password" name="password" placeholder="Enter your password" type="password" required/>
<a href="{{ route('password.forget') }}" class="text-sm text-green-800 poppins-regular mt-2 inline-block">Forgot password?</a>
<input class="w-full border border-gray-300 rounded-lg py-2 px-3" id="password" name="password"
placeholder="Enter your password" type="password" required />
<a href="{{ route('password.forget') }}"
class="text-sm text-green-800 poppins-regular mt-2 inline-block">Forgot password?</a>
</div>
<button class="w-full bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white rounded-lg py-2 poppins-regular" type="submit">Log In</button>
<button
class="w-full bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white rounded-lg py-2 poppins-regular"
type="submit">Log In</button>
</form>
<p class="mt-4 poppins-regula text-sm text-gray-500">
Don't have an account?
<a href="{{ route('register.index') }}" class="text-black poppins-regular">Register here</a>
@ -62,13 +77,18 @@
</div>
</div>
<!-- Right Side -->
<div class="hidden lg:flex lg:w-1/2 flex items-center justify-center bg-cover bg-center relative" style="background-image: url('{{ asset('img/bg-login.jpg') }}'); background-size: object-contain;">
<div class="hidden lg:flex lg:w-1/2 flex items-center justify-center bg-cover bg-center relative"
style="background-image: url('{{ asset('img/bg-login.jpg') }}'); background-size: object-contain;">
<div class="absolute inset-0 opacity-25"></div>
<div class="relative z-10 p-8">
<h2 class="text-5xl barlow-condensed-semibold text-green-800 mb-4">MARI TEMUKAN KURSUS IMPIANMU BERSAMA LEARN MAP.</h2>
<p class="text-black poppins-regular ">Jelajahi kursus berkualitas bersama Learn Map, sekarang juga. Temukan berbagai pilihan kursus yang dirancang untuk meningkatkan keterampilan dan pengetahuanmu.</p>
<h2 class="text-5xl barlow-condensed-semibold text-green-800 mb-4">MARI TEMUKAN KURSUS IMPIANMU BERSAMA
LEARN MAP.</h2>
<p class="text-black poppins-regular ">Jelajahi kursus berkualitas bersama Learn Map, sekarang juga.
Temukan berbagai pilihan kursus yang dirancang untuk meningkatkan keterampilan dan pengetahuanmu.
</p>
</div>
</div>
</div>
</body>
</html>
</html>

View File

@ -0,0 +1,45 @@
<div class="container">
<div class="grid grid-cols-2">
<div>
<div class="text-black poppins-medium font-semibold pb-2 text-2xl pt-4 poppins-semibold">
<p>Deskripsi</p>
</div>
<div>
<p class="poppins-regular text-black text-lg pb-2" id="deskripsi-text">
{{ Str::limit($data->deskripsi, 500, '...') }}
</p>
@if (strlen($data->deskripsi) > 500)
<button id="toggle-deskripsi" class="text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
</div>
<div>
</div>
</div>
{{-- Bagian Fasilitas --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Fasilitas
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="fasilitas-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->fasilitas, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->fasilitas)) > 250)
<button id="toggle-fasilitas" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
</div>

View File

@ -2,7 +2,7 @@
<!-- CSS Aplikasi -->
@vite(['resources/css/app.css', 'resources/js/app.js','public/css/font.css'])
@vite(['resources/css/app.css', 'resources/js/app.js', 'public/css/font.css'])
<link href="{{ mix('css/app.css') }}" rel="stylesheet">
<!-- Viewport untuk Responsif -->
@ -31,7 +31,7 @@
<!-- link font -->
<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=Bebas+Neue&display=swap" rel="stylesheet">\
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&display=swap" rel="stylesheet">
</style>
</style>

View File

@ -0,0 +1,36 @@
@if (session('success'))
<div id="notification"
class="fixed top-10 left-1/2 transform -translate-x-1/2 bg-green-50 text-green-800 border border-green-300 rounded-lg p-4 z-[99]">
<div class="flex items-center">
<svg class="flex-shrink-0 w-4 h-4 me-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z" />
</svg>
<span class="font-medium">{{ session('success') }}</span>
</div>
</div>
@endif
@if (session('error'))
<div id="notification"
class="fixed top-10 left-1/2 transform -translate-x-1/2 bg-red-50 text-red-800 border border-red-300 rounded-lg p-4 z-[99]">
<div class="flex items-center">
<svg class="flex-shrink-0 w-4 h-4 me-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z" />
</svg>
<span class="font-medium">{{ session('error') }}</span>
</div>
</div>
@endif
<script>
document.addEventListener('DOMContentLoaded', function() {
const notification = document.getElementById('notification');
if (notification) {
setTimeout(() => {
notification.classList.add('hidden');
}, 5000); // 5000 milliseconds = 5 seconds
}
});
</script>

View File

@ -12,16 +12,16 @@ class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-
</div>
@enderror
<div class="flex justify-center items-center pb-16 p-4">
<div class="h-auto w-full relative">
<img src="{{ asset('storage/' . $data->img) }}" alt="" class="aspect-[4/2] w-full object-cover rounded-2xl">
<div class="flex justify-center items-center p-4">
<div class="h-auto w-full relative ">
<img src="{{ asset('storage/' . $data->img) }}" alt=""
class="aspect-[4/2] w-full object-cover rounded-2xl">
<figcaption class="container w-full">
<div class="absolute container bottom-8 left-1/2 transform -translate-x-1/2 space-y-10 text-center">
<div class="absolute container bottom-12 left-1/2 transform -translate-x-1/2 space-y-10 text-center">
<p class="poppins-bold text-start text-6xl xl:text-8xl text-white pr-16 w-1/2">
{{ $data->nama_kursus }}
</p>
<div class="flex justify-start space-x-4">
<a href="/kursus/{{ $data->id }}/rute" target="_blank"
class="poppins-medium py-3 px-8 bg-[#4F7F81] text-white rounded-xl text-sm shadow-xl">Rute
@ -32,313 +32,21 @@ class="poppins-medium py-3 px-8 bg-[#4F7F81] text-white rounded-xl text-sm shado
Detail</button>
</div>
<div class="flex justify-between w-full text-white">
<button class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Deskripsi</button>
<button class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Paket</button>
<button class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Metode</button>
<button class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Fasilitas</button>
<button class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Lokasi</button>
<button
class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Deskripsi</button>
<button
class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Paket</button>
<button
class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Metode</button>
<button
class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Fasilitas</button>
<button
class="px-20 py-3 poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] rounded-3xl">Lokasi</button>
</div>
</div>
</figcaption>
</div>
</div>
</div>
<div class="container">
<p class="poppins-medium font-semibold text-sm xl:text-xl text-black pb-4">
({{ optional($data->kategoris)->nama_kategori ?? 'Kategori tidak tersedia' }}
)</p>
<!-- Main modal -->
<div id="default-modal-detail-gambar" tabindex="-1" aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl xl:max-w-3xl 2xl:max-w-4xl max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="p-4 md:p-5 space-y-4">
<div class="relative overflow-hidden rounded-lg gap-4 space-y-4 ">
@if (!empty($imageNames) && count($imageNames) > 0)
@foreach ($imageNames as $index => $img_konten)
<div class="border border-slate-300 rounded-md p-4">
<img src="{{ asset('storage/' . $img_konten) }}" class="w-full h-auto object-contain"
alt="Image {{ $index + 1 }}">
</div>
@endforeach
@else
<div class="block duration-1000 ease-in-out" data-carousel-item>
<img src="https://via.placeholder.com/600x400" class="w-full h-auto object-contain"
alt="No image available">
</div>
@endif
</div>
</div>
</div>
</div>
</div>
<div class="text-black poppins-medium font-semibold pb-2 text-2xl pt-4 poppins-semibold">
<p>Deskripsi</p>
</div>
<div>
<p class="poppins-regular text-black text-lg pb-2" id="deskripsi-text">
{{ Str::limit($data->deskripsi, 500, '...') }}
</p>
@if (strlen($data->deskripsi) > 500)
<button id="toggle-deskripsi" class="text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
<div class="grid grid-cols-1 gap-4 py-10">
{{-- Bagian Paket --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Paket
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="paket-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->paket, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->paket)) > 200)
<button id="toggle-paket" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
{{-- Bagian Metode Pembelajaran --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold text-2xl text-black underline">
Metode Pembelajaran
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="metode-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->metode, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->metode)) > 250)
<button id="toggle-metode" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
{{-- Bagian Fasilitas --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Fasilitas
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="fasilitas-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->fasilitas, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->fasilitas)) > 250)
<button id="toggle-fasilitas" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
{{-- Bagian Lokasi --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Lokasi
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="lokasi-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->lokasi, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->lokasi)) > 250)
<button id="toggle-lokasi" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Fungsi reusable untuk mengatur toggle teks
function toggleText(elementId, buttonId, fullText) {
const textElement = document.getElementById(elementId);
const toggleButton = document.getElementById(buttonId);
if (toggleButton) {
const shortText = textElement.innerHTML; // Teks pendek yang sudah dirender
toggleButton.addEventListener('click', function () {
if (textElement.innerHTML === shortText) {
// Tampilkan teks penuh
textElement.innerHTML = fullText;
toggleButton.innerText = 'Tampilkan Lebih Sedikit';
} else {
// Kembalikan ke teks pendek
textElement.innerHTML = shortText;
toggleButton.innerText = 'Lihat Selengkapnya';
}
});
}
}
// Terapkan fungsi ke setiap bagian
toggleText('paket-text', 'toggle-paket', @json($data->paket));
toggleText('metode-text', 'toggle-metode', @json($data->metode));
toggleText('fasilitas-text', 'toggle-fasilitas', @json($data->fasilitas));
toggleText('lokasi-text', 'toggle-lokasi', @json($data->lokasi));
toggleText('deskripsi-text', 'toggle-deskripsi', @json($data->deskripsi));
});
</script>
<div class="grid grid-cols-6 gap-4 py-20 ">
<!-- Left Column: Comment Form -->
<!-- Right Column: Ratings and Reviews -->
<div class="col-span-4 ">
<!-- Ratings Section -->
<div class="bg-gray-50">
<div class=" flex justify-between items-center">
<div class="flex w-full items-center">
<div class="flex items-center">
@for ($i = 1; $i <= 5; $i++)
<svg class="w-5 h-5 {{ $i <= round($averageRating) ? 'text-yellow-400' : 'text-gray-300' }}"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
@endfor
<span class="text-sm pl-4">Rata-rata: {{ round($averageRating, 1) }} / 5</span>
</div>
<div class=" md:ml-4">
<p class="poppins-medium poppins-regular text-sm xl:text-xl text-black">
(Total: {{ $totalRatings }} ulasan)
</p>
</div>
</div>
<div class="w-full">
{{ $ulasan->links() }}
</div>
</div>
<!-- Reviews Section -->
</div>
<div class="grid md:grid-cols-3 gap-4 items-center justify-end rtl">
@foreach ($ulasan as $review)
<div class="mb-6 mt-4 p-4 bg-white rounded-lg shadow-xl">
<!-- Reviewer Info -->
<div class="flex items-center mb-3">
<img src="/img/profil.png" alt="User Avatar" class="w-10 h-10 rounded-full mr-4">
<div>
<h4 class="font-bold text-gray-800">{{ $review->user->name ?? 'Anonim' }}</h4>
<p class="text-sm text-gray-500">
{{ $review->created_at->diffForHumans() }}
</p>
</div>
</div>
<!-- Reviewer Rating -->
<div class="flex items-center mb-2">
@for ($i = 1; $i <= 5; $i++)
<svg class="w-5 h-5 {{ $i <= $review->rating ? 'text-yellow-400' : 'text-gray-300' }}"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
@endfor
</div>
<!-- Review Comment -->
<p class="text-gray-700">{{ $review->comment }}</p>
</div>
@endforeach
</div>
<!-- Pagination Links -->
</div>
<div class="col-span-2">
@auth
<form action="{{ route('storeUlasan') }}" method="POST">
@csrf
<div class="max-w-xl mb-4 border border-gray-200 rounded-lg bg-gray-50">
<!-- Comment Input -->
<div class="hidden">
<input name="user_id" value="{{ Auth::user()->id }}" type="text">
<input name="kursus_id" value="{{ $data->id }}" type="text">
</div>
<div class="px-4 py-2 bg-white rounded-t-lg">
<label for="comment" class="sr-only">Your comment</label>
<textarea id="comment" name="comment" rows="4"
class="w-full px-0 text-sm text-gray-900 bg-white border-0 focus:ring-0 placeholder-gray-400"
placeholder="Write a comment..." required></textarea>
</div>
<!-- Rating Stars and Submit Button -->
<div class="flex items-center justify-between px-3 py-2 border-t border-gray-200">
<!-- Rating Stars -->
<div class="flex items-center space-x-2" id="rating-stars">
@for ($i = 1; $i <= 5; $i++)
<label class="cursor-pointer">
<input type="radio" name="rating" value="{{ $i }}" class="hidden" />
<svg class="w-6 h-6 text-gray-300 hover:text-yellow-400 transition-colors duration-200"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
</label>
@endfor
</div>
<script>
// JavaScript for managing star ratings
const starsContainer = document.getElementById('rating-stars');
const stars = starsContainer.querySelectorAll('svg');
const inputs = starsContainer.querySelectorAll('input[type="radio"]');
stars.forEach((star, index) => {
star.addEventListener('click', () => {
// Set all previous stars to active
stars.forEach((s, i) => {
if (i <= index) {
s.classList.add('text-yellow-400');
s.classList.remove('text-gray-300');
} else {
s.classList.add('text-gray-300');
s.classList.remove('text-yellow-400');
}
});
// Set the corresponding radio input
inputs[index].checked = true;
});
});
</script>
<!-- Submit Button -->
<button type="submit"
class="inline-flex items-center py-2.5 px-4 text-xs font-medium text-center text-white bg-blue-700 rounded-lg focus:ring-4 focus:ring-blue-200 hover:bg-blue-800">
Post Comment
</button>
</div>
</div>
</form>
@endauth
@guest
<p class="text-sm poppins-regular text-gray-500">
Anda harus <a href="{{ route('login') }}" class="text-green-800 poppins-semibold hover:underline">login</a> untuk
memberikan ulasan.
</p>
@endguest
<!-- Community Guidelines -->
<p class="ms-auto text-xs poppins-regular text-gray-500">
Remember, contributions to this topic should follow our
<a href="#" class="text-green-800 poppins-semibold hover:underline">Community Guidelines</a>.
</p>
</div>
</div>
</div>
</x-layout>
@include('partials.detail.deskripsi')
</x-layout>

View File

@ -4,129 +4,176 @@
<!-- Hero Section -->
<div class="relative">
<!-- Gambar -->
<img alt="LearnMap Hero Image" class="w-full object-cover" src="{{ asset('img/bg-home.jpg') }}" />
<img alt="LearnMap Hero Image"
class="h-[420px] sm:h-[450px] md:h-[480px] lg:h-[545px] xl:h-[645px] 2xl:h-[945px] brightness-100 w-full object-cover "
src="{{ asset('img/bg-home.jpg') }}">
<!-- Overlay Teks -->
<div class="absolute inset-0 flex items-center justify-center pl-8">
<div
class="absolute inset-0 flex items-center justify-center mb-14 sm:mb-14 md:mb-20 lg:mb-32 xl:mb-44 2xl:mb-72">
<div class="text-white">
<div>
<h1 class="text-9xl font-bold mb-4 text-center barlow-condensed-semibold">
<h1
class=" text-green-600 text-5xl sm:text-5xl md:text-6xl lg:text-7xl xl:text-8xl 2xl:text-9xl
font-bold text-center barlow-condensed-semibold drop-shadow-lg">
PARE EDUCATION <br> ENGLISH LANGUAGE
</h1>
<!-- <p class="text-lg mb-6">
<p
class="px-4 container text-xs sm:text-sm md:text-md lg:text-base xl:text-xl 2xl:text-2xl text-center text-green-700 font-weight-bold poppins-bold mb-2 xl:mb-6 barlow-condensed-semibold drop-shadow-lg">
Belajar bahasa Inggris dengan metode menarik dan akses mudah di LearnMap.
</p> -->
</p>
</div>
<div class="flex justify-center">
<a class=" text-white px-6 py-3 rounded-md bg-gradient-to-tr from-[#60BC9D] to-[#12372A]" href="{{route('user.kursus')}}">
<a class="text-white text-xs sm:text-xs md:text-base xl:text-2xl uppercase barlow-condensed-semibold px-4 py-1 xl:px-8 xl:py-2 rounded-md xl:rounded-xl bg-gradient-to-tr from-[#60BC9D] to-[#12372A]"
href="{{ route('user.kursus') }}">
Jelajahi
</a>
</div>
</div>
</div>
</div>
<!-- About Section -->
<!-- Popular Courses Section -->
<div class="container mx-auto px-4 py-12">
<div class=" py-12">
<div class="container px-4 space-y-8 lg:space-y-12 2xl:space-y-20 py-10 xl:py-16">
{{-- Tentang Kami --}}
<div class="">
<div class="flex ">
<div class="space-y-4">
<h2 class="text-5xl barlow-condensed-semibold text-green-800 font-bold ">
<div class="">
<h2
class="text-2xl lg:text-3xl 2xl:text-5xl barlow-condensed-semibold text-green-800 font-bold mb-1">
TENTANG KAMI
</h2>
<h2 class="text-start poppins-regular mb-12 text-xl text-gray-600">
<h2
class="text-start poppins-regular text-xs lg:text-base 2xl:text-xl text-gray-600 mb-2 lg:mb-6">
LearnMap adalah sebuah aplikasi website Sistem Informasi Geografis (SIG) yang dirancang khusus
untuk memudahkan Anda menemukan tempat bimbingan belajar bahasa Inggris terbaik di Kecamatan Pare,
Kabupaten Kediri. Kami menyediakan berbagai pilihan kursus berkualitas tinggi dengan tutor berpengalaman,
metode pembelajaran yang interaktif dan menarik, serta akses yang mudah dan cepat melalui platform digital
kami. Dengan LearnMap, Anda dapat menjelajahi informasi lengkap tentang lokasi, program, dan fasilitas
bimbingan belajar, sehingga membantu Anda meningkatkan keterampilan bahasa Inggris secara efektif dan
LearnMap adalah sebuah aplikasi website Sistem Informasi Geografis (SIG) yang dirancang
khusus
untuk memudahkan Anda menemukan tempat bimbingan belajar bahasa Inggris terbaik di Kecamatan
Pare,
Kabupaten Kediri. Kami menyediakan berbagai pilihan kursus berkualitas tinggi dengan tutor
berpengalaman,
metode pembelajaran yang interaktif dan menarik, serta akses yang mudah dan cepat melalui
platform digital
kami. Dengan LearnMap, Anda dapat menjelajahi informasi lengkap tentang lokasi, program, dan
fasilitas
bimbingan belajar, sehingga membantu Anda meningkatkan keterampilan bahasa Inggris secara
efektif dan
mewujudkan mimpi Anda untuk menguasai bahasa internasional ini dengan lebih percaya diri.
</h2>
<div class="flex ">
<div class="flex">
<a class="poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white px-6 py-3 rounded-md"
<a class="text-xs lg:text-sm 2xl:text-lg poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white px-4 py-2 2xl:px-6 2xl:py-3 rounded-md"
href="">
Pelajari Lebih Lanjut
</a>
</div>
</div>
<img alt="About LearnMap" class="w-auto h-128 object-contain "
src="{{ asset('img/tentang kami2.jpg') }}" />
{{-- <img alt="About LearnMap" class="w-auto h-128 object-contain "
src="{{ asset('img/img/tentang kami.jpg') }}" /> --}}
</div>
</div>
<!-- PETA -->
<div id="" class="container px-4 mt-10 relative z-[1] ">
<div class="mb-4 flex justify-between">
<div id="" class=" relative z-[1] ">
<div class=" flex justify-between">
<!-- Section Title -->
<div>
<p class="text-5xl font-bold text-start mb-4 barlow-condensed-semibold text-green-800">PERSEBARAN KURSUS</p>
<h5 class="text-start poppins-regular mb-12 text-xl text-gray-600">Berikut adalah persebaran seluruh wisata saat ini
<div class="w-full ">
<p
class="text-2xl lg:text-3xl 2xl:text-5xl font-bold text-start barlow-condensed-semibold text-green-800">
PERSEBARAN KURSUS</p>
<h5 class="text-start poppins-regular mb-4 text-xs lg:text-base 2xl:text-xl text-gray-600">
Berikut adalah persebaran
seluruh wisata saat ini
</h5>
<div class="p-20 " id="map"></div>
<div class="aspect-[5/2]" id="map"></div>
</div>
</div>
<style>
#map {
width: 100%;
height: 400px;
/* Bisa disesuaikan */
border-radius: 10px;
}
</style>
<!-- LEAFLET JS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Pastikan elemen "map" ada di dalam HTML
var map = L.map('map').setView([51.505, -0.09], 13);
document.addEventListener('DOMContentLoaded', function() {
// Pastikan elemen "map" ada dalam dokumen sebelum inisialisasi
var mapElement = document.getElementById('map');
if (!mapElement) {
console.warn("Element dengan ID 'map' tidak ditemukan.");
return;
}
// Inisialisasi Leaflet map
var map = L.map('map').setView([-7.7560717, 112.1823541], 15);
// Tambahkan tile layer dari OpenStreetMap
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Tambahkan marker
L.marker([51.5, -0.09]).addTo(map)
.bindPopup('<b>Ini Popup</b><br>Anda bisa menyesuaikan teks di sini.')
.openPopup();
// Tambahkan marker dari database jika ada data
@if ($peta->isNotEmpty())
@foreach ($peta as $latlong)
L.marker([{{ $latlong->latitude }}, {{ $latlong->longitude }}]).addTo(map)
.bindPopup(`
<b>{{ addslashes($latlong->nama_kursus) }}</b> <br>
<img class="w-32 h-20 object-cover" src="{{ asset('storage/' . $latlong->img) }}" alt="{{ addslashes($latlong->nama_kursus) }}" /> <br>
<a href="{{ url('/kursus/' . $latlong->id . '/detail') }}" class="text-blue-500 underline">Selengkapnya</a>
`);
@endforeach
@else
// Jika tidak ada data, tambahkan titik default di pusat kota Pare
L.marker([-7.7560717, 112.1823541]).addTo(map)
.bindPopup('<b>Default Marker: Pusat Kota Pare</b>');
@endif
// Perbaiki ukuran map jika terjadi masalah dengan tampilan
setTimeout(() => {
map.invalidateSize();
}, 500);
});
</script>
<h2 class="text-5xl font-bold text-start mb-4 barlow-condensed-semibold text-green-800">
</div>
{{-- Kursus Populer --}}
<div>
<h2
class="text-2xl lg:text-3xl 2xl:text-5xl font-bold text-start barlow-condensed-semibold text-green-800">
KURSUS POPULER
</h2>
<p class="text-start poppins-regular mb-12 text-xl text-gray-600">
<p class="text-start poppins-regular mb-4 text-xs lg:text-base 2xl:text-xl text-gray-600">
Pilih kursus yang sesuai dengan kebutuhan Anda
</p>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
@if ($landingpage->isNotEmpty())
@foreach ($landingpage as $landingpage)
<div
class="bg-white rounded-lg shadow-md overflow-hidden transition ease-in-out delay-0 hover:-translate-y-1 hover:scale-100 duration-300">
class="bg-white rounded-lg shadow-md overflow-hidden transition ease-in-out delay-0 hover:-translate-y-1 hover:scale-100 duration-300 h-full flex flex-col">
<a href="#">
<img class="w-full h-48 object-cover" src="{{ asset('storage/' . $landingpage->img) }}"
<img class="w-full h-48 object-cover"
src="{{ asset('storage/' . $landingpage->img) }}"
alt="{{ $landingpage->nama_kursus }}" />
</a>
<div class="p-4">
<h3 class="text-xl font-semibold poppins-bold uppercase text-green-800">
<div class="p-4 flex flex-col flex-grow ">
<h3
class="text-base lg:text-lg 2xl:text-xl font-semibold poppins-bold uppercase text-green-800">
{{ $landingpage->nama_kursus }}
</h3>
<p class="mt-2 text-gray-700 poppins-regular text-gray-600">
<p
class="pb-8 text-xs lg:text-sm 2xl:text-base text-gray-700 poppins-regular flex-grow">
{{ Str::words($landingpage->deskripsi, 20, '...') }}
</p>
<a class="poppins-regular mt-4 inline-block bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white px-4 py-2 rounded-md"
<a class="poppins-regular mt-auto inline-block bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white py-2 lg:py-3 rounded-md text-center text-sm lg:text-base"
href="/kursus/{{ $landingpage->id }}/detail">
Lihat Detail
</a>
@ -135,13 +182,13 @@ class="bg-white rounded-lg shadow-md overflow-hidden transition ease-in-out dela
@endforeach
@else
<div
class="poppins-regular text-graycol-span-3 py-10 bg-[#EBFEA1] poppins-extrabold flex items-center justify-center p-2">
class="col-span-3 py-10 bg-[#EBFEA1] poppins-extrabold flex items-center justify-center p-2">
<p>Tidak Tersedia Kursus</p>
</div>
@endif
</div>
</div>
</div>
</x-layout>
</x-layout>

View File

@ -1,11 +1,5 @@
<x-layout>
<div class="py-10 bg-white container">
<!-- <div class="bg-[#EBFEA1] poppins-extrabold m-auto flex items-center justify-center p-2">
<p>Halaman ini berisi tentang kursus di Pare! </p>
</div> -->
</div>
<div class="container pb-20">
<div class="container pb-20 pt-20 px-4">
<div class="flex justify-end space-x-2 py-4">
<form method="GET" action="{{ route('user.kursus') }}" class="flex space-x-2">
<!-- Dropdown Kategori -->
@ -32,9 +26,9 @@ class="absolute top-0 end-0 px-4 h-full text-sm font-medium text-white bg-gradie
</form>
</div>
{{ $data_kursus->links() }}
{{-- {{ $data_kursus->links() }} --}}
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 justify-center py-4 items-center gap-4 !important">
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 justify-center pb-4 items-center gap-4 !important">
@foreach ($data_kursus as $kursus)
<div class="kursus-item max-w-xl h-ful mx-auto shadow-2xl rounded-lg">
<div>
@ -45,11 +39,11 @@ class="absolute top-0 end-0 px-4 h-full text-sm font-medium text-white bg-gradie
<div class="p-5 h-44">
<div>
<h5
class="barlow-condensed-semibold text-green-800 nama-kursus mb-2 text-2xl poppins-regular font-extrabold tracking-tight text-gray-900">
class="barlow-condensed-semibold text-green-800 nama-kursus mb-2 text-2xl poppins-regular font-extrabold tracking-tight ">
{{ $kursus->nama_kursus }}
</h5>
<h5
class="poppins-regular text-black nama-kursus mb-2 text-sm poppins-regular font-extrabold tracking-tight text-gray-900">
class="poppins-regular text-black nama-kursus mb-2 text-sm poppins-regular font-extrabold tracking-tight ">
{{ optional($kursus->kategoris)->nama_kategori ?? 'Kategori tidak tersedia' }}
</h5>
</div>

View File

@ -4,18 +4,40 @@
max-width: 100%;
}
</style>
<div class="container flex flex-col">
<div class="py-10 bg-white">
<!--
<div class="bg-[#EBFEA1] poppins-extrabold m-auto flex items-center justify-center p-2">
<p>Halaman ini berisi tentang kursus di Pare!</p>
</div> -->
</div>
<div class="pb-10">
<div class="container py-14 px-4">
<div class="py-10 lg:py-16 2xl:py-20">
<!-- Peta Leaflet -->
<div id="map1"
class="w-full h-56 sm:h-64 md:h-96 lg:h-[500px] xl:h-[650px] max-w-4xl rounded-lg shadow-lg"></div>
</div>
<div class="">
<h2 class="text-2xl lg:text-3xl 2xl:text-5xl barlow-condensed-semibold text-green-800 font-bold mb-1">
PETA LEARN-MAP
</h2>
<h2 class="text-start poppins-regular text-xs lg:text-base 2xl:text-xl text-gray-600 mb-2 lg:mb-6">
LearnMap adalah sebuah aplikasi website Sistem Informasi Geografis (SIG) yang dirancang
khusus
untuk memudahkan Anda menemukan tempat bimbingan belajar bahasa Inggris terbaik di Kecamatan
Pare,
Kabupaten Kediri. Kami menyediakan berbagai pilihan kursus berkualitas tinggi dengan tutor
berpengalaman,
metode pembelajaran yang interaktif dan menarik, serta akses yang mudah dan cepat melalui
platform digital
kami. Dengan LearnMap, Anda dapat menjelajahi informasi lengkap tentang lokasi, program, dan
fasilitas
bimbingan belajar, sehingga membantu Anda meningkatkan keterampilan bahasa Inggris secara
efektif dan
mewujudkan mimpi Anda untuk menguasai bahasa internasional ini dengan lebih percaya diri.
</h2>
<div class="flex">
<a class="text-xs lg:text-sm 2xl:text-lg poppins-regular bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white px-4 py-2 2xl:px-6 2xl:py-3 rounded-md"
href="">
Pelajari Lebih Lanjut
</a>
</div>
</div>
</div>
<!-- Leaflet CSS dan JS -->
@ -27,33 +49,35 @@ class="w-full h-56 sm:h-64 md:h-96 lg:h-[500px] xl:h-[650px] max-w-4xl rounded-l
<script>
document.addEventListener('DOMContentLoaded', function() {
// Inisialisasi peta dengan koordinat dan tingkat zoom
const map = L.map('map1').setView([-7.7517397, 112.1780461],
15); // Gunakan 'map1' untuk ID peta yang sesuai
// Pastikan elemen "map1" ada sebelum inisialisasi
var mapElement = document.getElementById('map1');
if (!mapElement) {
console.warn("Elemen dengan ID 'map1' tidak ditemukan.");
return;
}
// Tambahkan lapisan ubin dari OpenStreetMap
// Inisialisasi Leaflet Map
const map = L.map('map1').setView([-7.7560717, 112.1823541], 15);
// Tambahkan tile layer dari OpenStreetMap
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// Menambahkan marker secara dinamis dengan data dari Blade
@foreach ($latilongti as $latilongti)
L.marker([{{ $latilongti->latitude }}, {{ $latilongti->longitude }}])
.addTo(map)
.bindPopup(
'<div class="h-auto w-full">' +
'<img src="{{ asset('storage/' . $latilongti->img) }}" alt="" class="w-full h-20 object-contain">' +
'</div>' +
'<p>' +
'{{ $latilongti->nama_kursus }} <br>' +
'<a href="/kursus/{{ $latilongti->id }}/detail">Selengkapnya</a>'
)
.openPopup();
// Tambahkan marker dari data Blade
@foreach ($latilongti as $data)
L.marker([{{ $data->latitude }}, {{ $data->longitude }}]).addTo(map)
.bindPopup(`
<div class="h-auto w-full">
<img src="{{ asset('storage/' . $data->img) }}" alt="{{ addslashes($data->nama_kursus) }}" class="w-full h-20 object-contain">
</div>
<p>
<b>{{ addslashes($data->nama_kursus) }}</b> <br>
<a href="{{ url('/kursus/' . $data->id . '/detail') }}" class="text-blue-500 underline">Selengkapnya</a>
</p>
`);
@endforeach
});
</script>
</x-layout>

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
{{-- <!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
@ -137,4 +137,290 @@
</div>
</div>
</body>
</html>
</html> --}}
<div class="container">
<p class="poppins-medium font-semibold text-sm xl:text-xl text-black pb-4">
({{ optional($data->kategoris)->nama_kategori ?? 'Kategori tidak tersedia' }}
)</p>
<!-- Main modal -->
<div id="default-modal-detail-gambar" tabindex="-1" aria-hidden="true"
class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl xl:max-w-3xl 2xl:max-w-4xl max-h-full">
<div class="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div class="p-4 md:p-5 space-y-4">
<div class="relative overflow-hidden rounded-lg gap-4 space-y-4 ">
@if (!empty($imageNames) && count($imageNames) > 0)
@foreach ($imageNames as $index => $img_konten)
<div class="border border-slate-300 rounded-md p-4">
<img src="{{ asset('storage/' . $img_konten) }}"
class="w-full h-auto object-contain" alt="Image {{ $index + 1 }}">
</div>
@endforeach
@else
<div class="block duration-1000 ease-in-out" data-carousel-item>
<img src="https://via.placeholder.com/600x400" class="w-full h-auto object-contain"
alt="No image available">
</div>
@endif
</div>
</div>
</div>
</div>
</div>
<div class="text-black poppins-medium font-semibold pb-2 text-2xl pt-4 poppins-semibold">
<p>Deskripsi</p>
</div>
<div>
<p class="poppins-regular text-black text-lg pb-2" id="deskripsi-text">
{{ Str::limit($data->deskripsi, 500, '...') }}
</p>
@if (strlen($data->deskripsi) > 500)
<button id="toggle-deskripsi" class="text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
<div class="grid grid-cols-1 gap-4 py-10">
{{-- Bagian Paket --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Paket
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="paket-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->paket, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->paket)) > 200)
<button id="toggle-paket" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
{{-- Bagian Metode Pembelajaran --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold text-2xl text-black underline">
Metode Pembelajaran
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="metode-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->metode, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->metode)) > 250)
<button id="toggle-metode" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
{{-- Bagian Lokasi --}}
<div class="w-auto xl:max-w-max space-y-4">
<p class="poppins-semibold font-semibold text-2xl text-black underline">
Lokasi
</p>
<p class="pl-4 poppins-regular text-lg text-black" id="lokasi-text">
{!! htmlspecialchars_decode(Str::limit(strip_tags($data->lokasi, '<br><p><strong><em>'), 250, '...')) !!}
</p>
@if (strlen(strip_tags($data->lokasi)) > 250)
<button id="toggle-lokasi" class="pl-4 text-blue-500 hover:underline poppins-medium text-sm mt-2">
Lihat Selengkapnya
</button>
@endif
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
// Fungsi reusable untuk mengatur toggle teks
function toggleText(elementId, buttonId, fullText) {
const textElement = document.getElementById(elementId);
const toggleButton = document.getElementById(buttonId);
if (toggleButton) {
const shortText = textElement.innerHTML; // Teks pendek yang sudah dirender
toggleButton.addEventListener('click', function() {
if (textElement.innerHTML === shortText) {
// Tampilkan teks penuh
textElement.innerHTML = fullText;
toggleButton.innerText = 'Tampilkan Lebih Sedikit';
} else {
// Kembalikan ke teks pendek
textElement.innerHTML = shortText;
toggleButton.innerText = 'Lihat Selengkapnya';
}
});
}
}
// Terapkan fungsi ke setiap bagian
toggleText('paket-text', 'toggle-paket', @json($data->paket));
toggleText('metode-text', 'toggle-metode', @json($data->metode));
toggleText('fasilitas-text', 'toggle-fasilitas', @json($data->fasilitas));
toggleText('lokasi-text', 'toggle-lokasi', @json($data->lokasi));
toggleText('deskripsi-text', 'toggle-deskripsi', @json($data->deskripsi));
});
</script>
<div class="grid grid-cols-6 gap-4 py-20 ">
<!-- Left Column: Comment Form -->
<!-- Right Column: Ratings and Reviews -->
<div class="col-span-4 ">
<!-- Ratings Section -->
<div class="bg-gray-50">
<div class=" flex justify-between items-center">
<div class="flex w-full items-center">
<div class="flex items-center">
@for ($i = 1; $i <= 5; $i++)
<svg class="w-5 h-5 {{ $i <= round($averageRating) ? 'text-yellow-400' : 'text-gray-300' }}"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
@endfor
<span class="text-sm pl-4">Rata-rata: {{ round($averageRating, 1) }} / 5</span>
</div>
<div class=" md:ml-4">
<p class="poppins-medium poppins-regular text-sm xl:text-xl text-black">
(Total: {{ $totalRatings }} ulasan)
</p>
</div>
</div>
<div class="w-full">
{{ $ulasan->links() }}
</div>
</div>
<!-- Reviews Section -->
</div>
<div class="grid md:grid-cols-3 gap-4 items-center justify-end rtl">
@foreach ($ulasan as $review)
<div class="mb-6 mt-4 p-4 bg-white rounded-lg shadow-xl">
<!-- Reviewer Info -->
<div class="flex items-center mb-3">
<img src="/img/profil.png" alt="User Avatar" class="w-10 h-10 rounded-full mr-4">
<div>
<h4 class="font-bold text-gray-800">{{ $review->user->name ?? 'Anonim' }}</h4>
<p class="text-sm text-gray-500">
{{ $review->created_at->diffForHumans() }}
</p>
</div>
</div>
<!-- Reviewer Rating -->
<div class="flex items-center mb-2">
@for ($i = 1; $i <= 5; $i++)
<svg class="w-5 h-5 {{ $i <= $review->rating ? 'text-yellow-400' : 'text-gray-300' }}"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
@endfor
</div>
<!-- Review Comment -->
<p class="text-gray-700">{{ $review->comment }}</p>
</div>
@endforeach
</div>
<!-- Pagination Links -->
</div>
<div class="col-span-2">
@auth
<form action="{{ route('storeUlasan') }}" method="POST">
@csrf
<div class="max-w-xl mb-4 border border-gray-200 rounded-lg bg-gray-50">
<!-- Comment Input -->
<div class="hidden">
<input name="user_id" value="{{ Auth::user()->id }}" type="text">
<input name="kursus_id" value="{{ $data->id }}" type="text">
</div>
<div class="px-4 py-2 bg-white rounded-t-lg">
<label for="comment" class="sr-only">Your comment</label>
<textarea id="comment" name="comment" rows="4"
class="w-full px-0 text-sm text-gray-900 bg-white border-0 focus:ring-0 placeholder-gray-400"
placeholder="Write a comment..." required></textarea>
</div>
<!-- Rating Stars and Submit Button -->
<div class="flex items-center justify-between px-3 py-2 border-t border-gray-200">
<!-- Rating Stars -->
<div class="flex items-center space-x-2" id="rating-stars">
@for ($i = 1; $i <= 5; $i++)
<label class="cursor-pointer">
<input type="radio" name="rating" value="{{ $i }}"
class="hidden" />
<svg class="w-6 h-6 text-gray-300 hover:text-yellow-400 transition-colors duration-200"
xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 20">
<path
d="M20.924 7.625a1.523 1.523 0 0 0-1.238-1.044l-5.051-.734-2.259-4.577a1.534 1.534 0 0 0-2.752 0L7.365 5.847l-5.051.734A1.535 1.535 0 0 0 1.463 9.2l3.656 3.563-.863 5.031a1.532 1.532 0 0 0 2.226 1.616L11 17.033l4.518 2.375a1.534 1.534 0 0 0 2.226-1.617l-.863-5.03L20.537 9.2a1.523 1.523 0 0 0 .387-1.575Z" />
</svg>
</label>
@endfor
</div>
<script>
// JavaScript for managing star ratings
const starsContainer = document.getElementById('rating-stars');
const stars = starsContainer.querySelectorAll('svg');
const inputs = starsContainer.querySelectorAll('input[type="radio"]');
stars.forEach((star, index) => {
star.addEventListener('click', () => {
// Set all previous stars to active
stars.forEach((s, i) => {
if (i <= index) {
s.classList.add('text-yellow-400');
s.classList.remove('text-gray-300');
} else {
s.classList.add('text-gray-300');
s.classList.remove('text-yellow-400');
}
});
// Set the corresponding radio input
inputs[index].checked = true;
});
});
</script>
<!-- Submit Button -->
<button type="submit"
class="inline-flex items-center py-2.5 px-4 text-xs font-medium text-center text-white bg-blue-700 rounded-lg focus:ring-4 focus:ring-blue-200 hover:bg-blue-800">
Post Comment
</button>
</div>
</div>
</form>
@endauth
@guest
<p class="text-sm poppins-regular text-gray-500">
Anda harus <a href="{{ route('login') }}"
class="text-green-800 poppins-semibold hover:underline">login</a> untuk
memberikan ulasan.
</p>
@endguest
<!-- Community Guidelines -->
<p class="ms-auto text-xs poppins-regular text-gray-500">
Remember, contributions to this topic should follow our
<a href="#" class="text-green-800 poppins-semibold hover:underline">Community
Guidelines</a>.
</p>
</div>
</div>
</div>

View File

@ -3,17 +3,19 @@
use App\Models\User;
use App\Models\PendingUser;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Facades\Session;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\KategoriController;
use App\Http\Controllers\RegisterController;
use App\Http\Controllers\AdminUserController;
use App\Http\Controllers\KunjunganController;
use App\Http\Controllers\PengunjungController;
use App\Http\Controllers\ProfileNewController;
use App\Http\Controllers\AdminDashboardController;
use App\Http\Controllers\AdminDataKursusController;
use App\Http\Controllers\Auth\NewPasswordController;
use App\Http\Controllers\Auth\PasswordResetLinkController;
use App\Http\Controllers\KunjunganController;
Route::get('/login', [LoginController::class, 'index'])->name('login'); // Halaman login
Route::post('/login', [LoginController::class, 'authenticate'])->name('login.process'); // Proses login
@ -41,23 +43,36 @@
Route::post('reset-password', [NewPasswordController::class, 'store'])
->name('password.store');
// ADMIN
Route::prefix('admin')->middleware(['auth', 'role:admin'])->group(function () {
Route::get('/dashboard', [AdminDashboardController::class, 'index'])->name('admin.home');
Route::get('/data-kursus', [AdminDataKursusController::class, 'dataKursus'])->name('admin.dataKursus');
Route::middleware(['auth'])->group(function () {
Route::get('/password/edit', [ProfileNewController::class, 'edit'])->name('password.edit');
Route::put('/password/update', [ProfileNewController::class, 'update'])->name('password.update'); // Ubah dari POST ke PUT
});
// ADMIN & USER
Route::prefix('admin')->middleware(['auth'])->group(function () {
Route::get('dashboard', [AdminDashboardController::class, 'index'])->name('admin.home');
Route::resource('/user', AdminUserController::class);
});
// Route untuk ADMIN (Hanya Admin)
Route::prefix('admin')->middleware(['auth', 'role:admin'])->group(function () {
Route::resource('/kategori', KategoriController::class);
});
// Route untuk USER (Hanya User)
Route::prefix('admin')->middleware(['auth', 'role:user'])->group(function () {
Route::get('/create-data', [AdminDataKursusController::class, 'create'])->name('admin.create');
Route::get('/data-kursus', [AdminDataKursusController::class, 'dataKursus'])->name('admin.dataKursus');
Route::get('/{id}/edit-kursus', [AdminDataKursusController::class, 'edit'])->name('admin.edit');
// Fungsi di admin
// Fungsi CRUD kursus untuk user
Route::put('/update/{id}', [AdminDataKursusController::class, 'update'])->name('admin.update');
Route::post('/store', [AdminDataKursusController::class, 'store'])->name('kursus.store');
Route::delete('/delete/{id}', [AdminDataKursusController::class, 'destroy'])->name('delete');
Route::resource('kategori', KategoriController::class);
});
// USER
// PENGUNJUNG
Route::get('/', [PengunjungController::class, 'home'])->name('user.home');
Route::get('/gagal-login', [PengunjungController::class, 'gagal'])->name('gagal.home');
Route::get('/kursus', [PengunjungController::class, 'kursus'])->name('user.kursus');
@ -67,12 +82,15 @@
Route::post('/store-ulasan', [PengunjungController::class, 'storeUlasann'])->name('storeUlasan');
Route::post('/kursus/{id}/detail', [KunjunganController::class, 'visitCourse'])->name('kursus.visit');
Route::get('/set-locale/{lang}', function ($lang) {
Session::put('locale', $lang);
return back();
})->name('set.locale');
Route::middleware(['auth'])->group(function () {
Route::get('/password/edit', [ProfileNewController::class, 'edit'])->name('password.edit');
Route::put('/password/update', [ProfileNewController::class, 'update'])->name('password.update'); // Ubah dari POST ke PUT
});
require __DIR__ . '/auth.php';

View File

@ -22,7 +22,7 @@ export default {
extend: {
// Tambahkan font Bebas Neue di sini
fontFamily: {
'bebas-neue': ['"Bebas Neue"', 'sans-serif'],
"bebas-neue": ['"Bebas Neue"', "sans-serif"],
},
dropShadow: {
"1xl": "0 10px 20px rgba(0, 0, 0, 0.15)", // Light shadow for minimal depth
@ -36,4 +36,4 @@ export default {
},
},
plugins: [require("flowbite/plugin")],
};
};