This commit is contained in:
Salma Banafsha S. F. 2025-04-06 11:53:19 +07:00
parent f38438a1e1
commit 7c904f3bdf
7 changed files with 99 additions and 64 deletions

View File

@ -56,6 +56,7 @@ public function store(Request $request)
$validatedData = $request->validate([ $validatedData = $request->validate([
'name' => 'required|string|max:255', 'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email', 'email' => 'required|email|unique:users,email',
'username' => 'required',
'password' => 'required|min:6', 'password' => 'required|min:6',
'verif_password' => 'required|same:password', 'verif_password' => 'required|same:password',
]); ]);
@ -64,6 +65,7 @@ public function store(Request $request)
User::create([ User::create([
'name' => $validatedData['name'], 'name' => $validatedData['name'],
'email' => $validatedData['email'], 'email' => $validatedData['email'],
'username' => $validatedData['username'],
'password' => Hash::make($validatedData['password']), // Hash password untuk keamanan 'password' => Hash::make($validatedData['password']), // Hash password untuk keamanan
'role' => 'user', // Default role untuk user baru 'role' => 'user', // Default role untuk user baru
]); ]);

View File

@ -15,13 +15,13 @@ class DatabaseSeeder extends Seeder
*/ */
public function run(): void public function run(): void
{ {
User::create([ // User::create([
'name' => 'Salma Admin', // 'name' => 'Salma Admin',
'email' => 'salma@gmail.com', // 'email' => 'salma@gmail.com',
'username' => 'salma', // 'username' => 'salma',
'password' => bcrypt('salma281103'), // Ganti dengan password pilihan Anda // 'password' => bcrypt('salma281103'), // Ganti dengan password pilihan Anda
'role' => 'admin', // 'role' => 'admin',
]); // ]);
User::create([ User::create([
'name' => 'Admin', 'name' => 'Admin',
'email' => 'admin@gmail.com', 'email' => 'admin@gmail.com',
@ -43,12 +43,12 @@ public function run(): void
'password' => bcrypt('pengunjung123'), // Ganti dengan password pilihan Anda 'password' => bcrypt('pengunjung123'), // Ganti dengan password pilihan Anda
'role' => 'pengunjung', 'role' => 'pengunjung',
]); ]);
DataKategori::insert([ // DataKategori::insert([
['nama_kategori' => 'Speaking'], // ['nama_kategori' => 'Speaking'],
['nama_kategori' => 'Reading'], // ['nama_kategori' => 'Reading'],
['nama_kategori' => 'Good Looking'], // ['nama_kategori' => 'Good Looking'],
['nama_kategori' => 'Good Evening'], // ['nama_kategori' => 'Good Evening'],
]); // ]);
// // // Buat 3 kategori, setiap kategori memiliki banyak kursus // // // Buat 3 kategori, setiap kategori memiliki banyak kursus
// // // Buat 3 kategori // // // Buat 3 kategori

View File

@ -24,8 +24,8 @@ class="block p-2.5 w-full z-20 text-sm text-gray-900 bg-gray-50 rounded-e-lg bor
placeholder="Search users..." /> placeholder="Search users..." />
<button type="submit" <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"> 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" <svg class="w-4 h-4" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
fill="none" viewBox="0 0 20 20"> viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <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" /> stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
</svg> </svg>
@ -141,6 +141,12 @@ class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300" class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Email" required autocomplete="off"> placeholder="Masukkan Email" required autocomplete="off">
</div> </div>
<div class="p-4 items-center">
<label for="Username" class="block text-gray-700 font-bold mb-1">Username</label>
<input type="Username" id="Username" name="username"
class="w-full px-3 border rounded-lg focus:outline-none focus:ring focus:border-blue-300"
placeholder="Masukkan Username" required autocomplete="off">
</div>
<div class="p-4 items-center"> <div class="p-4 items-center">
<label for="password" class="block text-gray-700 font-bold mb-1">Password</label> <label for="password" class="block text-gray-700 font-bold mb-1">Password</label>
@ -174,8 +180,7 @@ class="py-2.5 px-5 ms-3 text-sm font-medium text-gray-900 focus:outline-none bg-
</div> </div>
<!-- Modal EDIT Kategori --> <!-- Modal EDIT Kategori -->
@foreach ($user as $index) @foreach ($user as $index)
<div id="modal-edit-users-{{ $index->id }}" data-modal-backdrop="static" tabindex="-1" <div id="modal-edit-users-{{ $index->id }}" data-modal-backdrop="static" tabindex="-1" aria-hidden="true"
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"> 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 p-4 w-full max-w-2xl max-h-full">
<div class="relative bg-white rounded-lg shadow "> <div class="relative bg-white rounded-lg shadow ">
@ -186,10 +191,10 @@ class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50
<button type="button" <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 " 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 }}"> data-modal-hide="modal-edit-users-{{ $index->id }}">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
fill="none" viewBox="0 0 14 14"> viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" /> d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg> </svg>
<span class="sr-only">Close modal</span> <span class="sr-only">Close modal</span>
</button> </button>
@ -197,8 +202,7 @@ class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounde
<form id="edit-user-form" method="POST" action="{{ route('user.update', $index->id) }}"> <form id="edit-user-form" method="POST" action="{{ route('user.update', $index->id) }}">
@csrf <!-- Token CSRF --> @csrf <!-- Token CSRF -->
@method('PUT') <!-- Menggunakan metode PUT --> @method('PUT') <!-- Menggunakan metode PUT -->
<input hidden value="{{ $index->id }}" type="text" id="edit-idkategori" <input hidden value="{{ $index->id }}" type="text" id="edit-idkategori" name="id" required>
name="id" required>
<div class="px-4 pb-4 items-center"> <div class="px-4 pb-4 items-center">
<label for="Name" class="block mt-4 text-gray-700 font-bold mb-1">Nama</label> <label for="Name" class="block mt-4 text-gray-700 font-bold mb-1">Nama</label>
@ -240,16 +244,16 @@ class="absolute top-3 right-3 text-gray-400 bg-transparent hover:bg-gray-200 hov
id="close-modal"> id="close-modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" <svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 14 14"> viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" /> d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg> </svg>
<span class="sr-only">Close modal</span> <span class="sr-only">Close modal</span>
</button> </button>
<div class="p-4 md:p-5 text-center"> <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" <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"> xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
stroke-width="2" d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" /> d="M10 11V6m0 8h.01M19 10a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg> </svg>
<h3 class="mb-5 text-lg font-normal text-gray-500 ">Anda yakin ingin <h3 class="mb-5 text-lg font-normal text-gray-500 ">Anda yakin ingin
menghapus?</h3> menghapus?</h3>
@ -263,8 +267,7 @@ class="text-white bg-red-600 hover:bg-red-800 focus:ring-4 focus:outline-none fo
</button> </button>
</form> </form>
<button type="button" <button type="button" id="cancel-logout" data-modal-hide="modal-delete-user-{{ $index->id }}"
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 "> 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 Tidak, Batal
</button> </button>

View File

@ -65,9 +65,8 @@ class="fixed top-5 left-1/2 transform -translate-x-1/2 bg-red-500 text-white px-
<a href="{{ route('password.forget') }}" <a href="{{ route('password.forget') }}"
class="text-sm text-green-800 poppins-regular mt-2 inline-block">Forgot password?</a> class="text-sm text-green-800 poppins-regular mt-2 inline-block">Forgot password?</a>
</div> </div>
<button <button class="w-full bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white rounded-lg py-2 poppins-regular
class="w-full bg-gradient-to-tr from-[#60BC9D] to-[#12372A] text-white rounded-lg py-2 poppins-regular" transition delay-100 duration-300 ease-in-out hover:-translate-y-1 hover:scale-110 hover:bg-green-800" type="submit">Log In</button>
type="submit">Log In</button>
</form> </form>
<p class="mt-4 poppins-regula text-sm text-gray-500"> <p class="mt-4 poppins-regula text-sm text-gray-500">

View File

@ -58,41 +58,71 @@ class="w-full h-80 object-cover rounded-lg cursor-pointer" onclick="openModal()"
{{-- Tombol +n jika lebih dari 3 gambar --}} {{-- Tombol +n jika lebih dari 3 gambar --}}
@if (count($imageNames) > 3) @if (count($imageNames) > 3)
<div class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 text-white text-lg font-bold rounded-lg cursor-pointer" <button data-modal-toggle="imageModal"
onclick="openModal()"> class="absolute inset-0 flex items-center justify-center bg-black bg-opacity-50 text-white text-lg font-bold rounded-lg cursor-pointer">
+{{ count($imageNames) - 3 }} +{{ count($imageNames) - 3 }}
</div> </button>
@endif @endif
@endif @endif
</div> </div>
</div> </div>
@endif @endif
{{-- Modal untuk menampilkan semua gambar --}} {{-- Modal untuk menampilkan semua gambar --}}
<div id="imageModal" <div id="imageModal" tabindex="-1" aria-hidden="true"
class="fixed inset-0 hidden bg-black bg-opacity-80 flex items-center justify-center z-50"> class="fixed inset-0 hidden z-[999] overflow-y-auto overflow-x-hidden bg-black bg-opacity-80 flex items-center justify-center">
<div class="bg-white p-5 rounded-lg shadow-lg max-w-3xl w-full relative"> <div class="relative p-4 w-full max-w-6xl max-h-full">
<button onclick="closeModal()" <!-- Modal content -->
class="absolute top-2 right-2 text-white bg-red-500 p-2 rounded-full"></button> <div class="relative bg-white rounded-lg shadow">
<div class="grid grid-cols-2 gap-2 max-h-[80vh] overflow-y-auto p-2">
@foreach ($imageNames as $image) <!-- Close button di pojok kanan atas -->
<img src="{{ asset('storage/' . $image) }}" alt="Gambar Detail" <button type="button"
class="w-full h-40 object-cover rounded-lg"> class="absolute top-2 right-2 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 z-50"
@endforeach onclick="toggleModal('imageModal')">
<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 1l6 6m0 0l6 6M7 7l6-6M7 7L1 13" />
</svg>
<span class="sr-only">Tutup modal</span>
</button>
<div class="grid grid-cols-1 gap-4 p-6 overflow-y-auto max-h-[80vh]">
@foreach ($imageNames as $image)
<img src="{{ asset('storage/' . $image) }}" alt="Gambar Detail"
class="w-full h-auto object-contain rounded-lg shadow-md">
@endforeach
</div>
</div> </div>
</div> </div>
</div> </div>
{{-- JavaScript untuk Modal --}}
<script> <script>
function openModal() { // Toggle modal visibility
document.getElementById('imageModal').classList.remove('hidden'); function toggleModal(id) {
const modal = document.getElementById(id);
modal.classList.toggle('hidden');
} }
function closeModal() { // Klik di luar modal content = close
document.getElementById('imageModal').classList.add('hidden'); window.addEventListener('click', function (event) {
} const modal = document.getElementById('imageModal');
if (!modal.classList.contains('hidden') && event.target === modal) {
modal.classList.add('hidden');
}
});
// Untuk tombol dengan data-modal-toggle
document.querySelectorAll('[data-modal-toggle]').forEach(button => {
button.addEventListener('click', () => {
const targetId = button.getAttribute('data-modal-toggle');
toggleModal(targetId);
});
});
</script> </script>
@else @else
<p class="text-gray-500 italic text-center">Tidak ada gambar yang tersedia.</p> <p class="text-gray-500 italic text-center">Tidak ada gambar yang tersedia.</p>
@endif @endif
@ -262,8 +292,8 @@ class="inline-flex items-center py-2.5 px-4 text-xs font-medium text-center text
@guest @guest
<p class="text-sm poppins-regular text-gray-500"> <p class="text-sm poppins-regular text-gray-500">
Anda harus <a href="{{ route('login') }}" Anda harus <a href="{{ route('login') }}" class="text-green-800 poppins-semibold hover:underline">login</a>
class="text-green-800 poppins-semibold hover:underline">login</a> untuk untuk
memberikan ulasan. memberikan ulasan.
</p> </p>
@endguest @endguest

View File

@ -58,6 +58,7 @@
// Route untuk ADMIN (Hanya Admin) // Route untuk ADMIN (Hanya Admin)
Route::prefix('admin')->middleware(['auth', 'role:admin'])->group(function () { Route::prefix('admin')->middleware(['auth', 'role:admin'])->group(function () {
Route::resource('/kategori', KategoriController::class); Route::resource('/kategori', KategoriController::class);
Route::resource('/user', AdminUserController::class);
}); });
// Route untuk USER (Hanya User) // Route untuk USER (Hanya User)

View File

@ -7,13 +7,13 @@ export default defineConfig({
refresh: true, refresh: true,
}), }),
], ],
// RUN DI MOBILE // // RUN DI MOBILE
server: { // server: {
host: '0.0.0.0', // Akses dari HP bisa // host: '0.0.0.0', // Akses dari HP bisa
port: 5173, // Default Vite port // port: 5173, // Default Vite port
strictPort: true, // strictPort: true,
hmr: { // hmr: {
host: '192.168.1.4' // IP MENYESUAIKAN laptop kamu // host: '192.168.1.4' // IP MENYESUAIKAN laptop kamu
} // }
}, // },
}); });