diff --git a/app/Http/Controllers/Admin/ProfileController.php b/app/Http/Controllers/Admin/ProfileController.php new file mode 100644 index 0000000..87e7a3a --- /dev/null +++ b/app/Http/Controllers/Admin/ProfileController.php @@ -0,0 +1,57 @@ +user(); + return view('admin.profile.edit', compact('admin')); + } + + public function update(Request $request) + { + $admin = Auth::guard('admin')->user(); + + $request->validate([ + 'username' => 'required|string|max:100|unique:admins,username,' . $admin->id_admin . ',id_admin', + 'password' => 'nullable|min:6|confirmed', + 'password_confirmation' => 'nullable', + 'foto_profil' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:2048', + ], [ + 'username.required' => 'Username wajib diisi.', + 'username.unique' => 'Username sudah digunakan.', + 'password.min' => 'Password minimal 6 karakter.', + 'password.confirmed' => 'Konfirmasi password tidak cocok.', + 'foto_profil.image' => 'File harus berupa gambar.', + 'foto_profil.max' => 'Ukuran foto maksimal 2MB.', + ]); + + $data = ['username' => $request->username]; + + if ($request->filled('password')) { + $data['password'] = Hash::make($request->password); + } + + if ($request->hasFile('foto_profil')) { + if ($admin->foto_profil && Storage::disk('public')->exists($admin->foto_profil)) { + Storage::disk('public')->delete($admin->foto_profil); + } + $path = $request->file('foto_profil')->store('foto_profil/admin', 'public'); + $data['foto_profil'] = $path; + } + + $admin->update($data); + + return redirect()->route('admin.profile.edit') + ->with('success', 'Profil berhasil diperbarui!'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Guru/ProfilController.php b/app/Http/Controllers/Guru/ProfilController.php deleted file mode 100644 index b9ce187..0000000 --- a/app/Http/Controllers/Guru/ProfilController.php +++ /dev/null @@ -1,42 +0,0 @@ -user(); - return view('guru.profil.show', compact('guru')); - } - - public function update(Request $request) - { - $guru = Auth::guard('guru')->user(); - - $validated = $request->validate([ - 'nama' => 'required|string|max:100', - 'password' => 'nullable|string|min:6|confirmed', - ], [ - 'nama.required' => 'Nama wajib diisi', - 'password.min' => 'Password minimal 6 karakter', - 'password.confirmed' => 'Konfirmasi password tidak cocok', - ]); - - $guru->nama = $validated['nama']; - - if ($request->filled('password')) { - $guru->password = Hash::make($validated['password']); - } - - $guru->save(); - - return redirect()->route('guru.profil.show') - ->with('success', 'Profil berhasil diupdate!'); - } -} \ No newline at end of file diff --git a/app/Http/Controllers/Guru/ProfileController.php b/app/Http/Controllers/Guru/ProfileController.php new file mode 100644 index 0000000..31fb263 --- /dev/null +++ b/app/Http/Controllers/Guru/ProfileController.php @@ -0,0 +1,55 @@ +user(); + return view('guru.profile.edit', compact('guru')); + } + + public function update(Request $request) + { + $guru = Auth::guard('guru')->user(); + + $request->validate([ + 'password' => 'nullable|min:6|confirmed', + 'password_confirmation' => 'nullable', + 'foto_profil' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:2048', + ], [ + 'password.min' => 'Password minimal 6 karakter.', + 'password.confirmed' => 'Konfirmasi password tidak cocok.', + 'foto_profil.image' => 'File harus berupa gambar.', + 'foto_profil.max' => 'Ukuran foto maksimal 2MB.', + ]); + + $data = []; + + if ($request->filled('password')) { + $data['password'] = Hash::make($request->password); + } + + if ($request->hasFile('foto_profil')) { + if ($guru->foto_profil && Storage::disk('public')->exists($guru->foto_profil)) { + Storage::disk('public')->delete($guru->foto_profil); + } + $path = $request->file('foto_profil')->store('foto_profil/guru', 'public'); + $data['foto_profil'] = $path; + } + + if (!empty($data)) { + $guru->update($data); + } + + return redirect()->route('guru.profile.edit') + ->with('success', 'Profil berhasil diperbarui!'); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php deleted file mode 100644 index a48eb8d..0000000 --- a/app/Http/Controllers/ProfileController.php +++ /dev/null @@ -1,60 +0,0 @@ - $request->user(), - ]); - } - - /** - * Update the user's profile information. - */ - public function update(ProfileUpdateRequest $request): RedirectResponse - { - $request->user()->fill($request->validated()); - - if ($request->user()->isDirty('email')) { - $request->user()->email_verified_at = null; - } - - $request->user()->save(); - - return Redirect::route('profile.edit')->with('status', 'profile-updated'); - } - - /** - * Delete the user's account. - */ - public function destroy(Request $request): RedirectResponse - { - $request->validateWithBag('userDeletion', [ - 'password' => ['required', 'current_password'], - ]); - - $user = $request->user(); - - Auth::logout(); - - $user->delete(); - - $request->session()->invalidate(); - $request->session()->regenerateToken(); - - return Redirect::to('/'); - } -} diff --git a/app/Http/Controllers/Siswa/ProfileController.php b/app/Http/Controllers/Siswa/ProfileController.php new file mode 100644 index 0000000..39b4699 --- /dev/null +++ b/app/Http/Controllers/Siswa/ProfileController.php @@ -0,0 +1,58 @@ +user(); + return view('siswa.profile.edit', compact('siswa')); + } + + public function update(Request $request) + { + $siswa = Auth::guard('siswa')->user(); + + $request->validate([ + 'password' => 'nullable|min:6|confirmed', + 'password_confirmation' => 'nullable', + 'foto_profil' => 'nullable|image|mimes:jpg,jpeg,png,webp|max:2048', + ], [ + 'password.min' => 'Password minimal 6 karakter.', + 'password.confirmed' => 'Konfirmasi password tidak cocok.', + 'foto_profil.image' => 'File harus berupa gambar.', + 'foto_profil.max' => 'Ukuran foto maksimal 2MB.', + ]); + + $data = []; + + // Update password + if ($request->filled('password')) { + $data['password'] = Hash::make($request->password); + } + + // Update foto profil + if ($request->hasFile('foto_profil')) { + // Hapus foto lama jika ada + if ($siswa->foto_profil && Storage::disk('public')->exists($siswa->foto_profil)) { + Storage::disk('public')->delete($siswa->foto_profil); + } + $path = $request->file('foto_profil')->store('foto_profil/siswa', 'public'); + $data['foto_profil'] = $path; + } + + if (!empty($data)) { + $siswa->update($data); + } + + return redirect()->route('siswa.profile.edit') + ->with('success', 'Profil berhasil diperbarui!'); + } +} \ No newline at end of file diff --git a/app/Models/Admin.php b/app/Models/Admin.php index 2b9d766..862ad7a 100644 --- a/app/Models/Admin.php +++ b/app/Models/Admin.php @@ -19,7 +19,8 @@ class Admin extends Authenticatable protected $fillable = [ 'username', - 'password' + 'password', + 'foto_profil' ]; protected $hidden = [ diff --git a/app/Models/Guru.php b/app/Models/Guru.php index 5b35a97..91af307 100644 --- a/app/Models/Guru.php +++ b/app/Models/Guru.php @@ -17,7 +17,8 @@ class Guru extends Authenticatable protected $fillable = [ 'nip', 'nama', - 'password' + 'password', + 'foto_profil' ]; protected $hidden = [ diff --git a/app/Models/Siswa.php b/app/Models/Siswa.php index 39d03d6..c8ac042 100644 --- a/app/Models/Siswa.php +++ b/app/Models/Siswa.php @@ -21,6 +21,7 @@ class Siswa extends Authenticatable 'tanggal_lahir', 'id_kelas', 'password', + 'foto_profil' ]; protected $hidden = [ diff --git a/database/migrations/2026_03_14_024528_add_pp.php b/database/migrations/2026_03_14_024528_add_pp.php new file mode 100644 index 0000000..3b2e58b --- /dev/null +++ b/database/migrations/2026_03_14_024528_add_pp.php @@ -0,0 +1,42 @@ +string('foto_profil')->nullable()->after('password'); + }); + } + + if (!Schema::hasColumn('gurus', 'foto_profil')) { + Schema::table('gurus', function (Blueprint $table) { + $table->string('foto_profil')->nullable()->after('password'); + }); + } + + if (!Schema::hasColumn('admins', 'foto_profil')) { + Schema::table('admins', function (Blueprint $table) { + $table->string('foto_profil')->nullable()->after('password'); + }); + } + } + + public function down(): void + { + Schema::table('siswas', function (Blueprint $table) { + $table->dropColumn('foto_profil'); + }); + Schema::table('gurus', function (Blueprint $table) { + $table->dropColumn('foto_profil'); + }); + Schema::table('admins', function (Blueprint $table) { + $table->dropColumn('foto_profil'); + }); + } +}; \ No newline at end of file diff --git a/resources/views/admin/layouts/app.blade.php b/resources/views/admin/layouts/app.blade.php index 8e80979..f4f9813 100644 --- a/resources/views/admin/layouts/app.blade.php +++ b/resources/views/admin/layouts/app.blade.php @@ -9,92 +9,42 @@ @stack('styles') -
@@ -104,67 +54,39 @@
+ +@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/guru/layouts/app.blade.php b/resources/views/guru/layouts/app.blade.php index bc880ac..e21e04c 100644 --- a/resources/views/guru/layouts/app.blade.php +++ b/resources/views/guru/layouts/app.blade.php @@ -9,77 +9,39 @@ @stack('styles') -
@@ -88,40 +50,23 @@ Logo
- - - Dashboard + + Dashboard - - - - Daftar Guru + + Daftar Guru - - - - Daftar Kelas + + Daftar Kelas - - - - Daftar Siswa + + Daftar Siswa - - - - Mata Pelajaran + + Mata Pelajaran - - - - Leaderboard + + Leaderboard + +@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/guru/profil/index.blade.php b/resources/views/guru/profile/index.blade.php similarity index 100% rename from resources/views/guru/profil/index.blade.php rename to resources/views/guru/profile/index.blade.php diff --git a/resources/views/siswa/layouts/app.blade.php b/resources/views/siswa/layouts/app.blade.php index 4866b81..8c8e621 100644 --- a/resources/views/siswa/layouts/app.blade.php +++ b/resources/views/siswa/layouts/app.blade.php @@ -35,28 +35,16 @@ position: relative; } - /* Default: collapsed saat pertama load */ .sidebar.collapsed { width: 0; padding: 0; border-right: none; } - .sidebar-logo { - text-align: center; - margin-bottom: 40px; - white-space: nowrap; - } + .sidebar-logo { text-align: center; margin-bottom: 40px; white-space: nowrap; } + .sidebar-logo img { width: 90px; } - .sidebar-logo img { - width: 90px; - } - - .sidebar-menu { - display: flex; - flex-direction: column; - white-space: nowrap; - } + .sidebar-menu { display: flex; flex-direction: column; white-space: nowrap; } .sidebar-link { display: flex; @@ -71,42 +59,19 @@ transition: all 0.2s ease; } - .sidebar-link:hover { - background: #e6f0ff; - color: #1d4ed8; - } + .sidebar-link:hover { background: #e6f0ff; color: #1d4ed8; } + .sidebar-link.active { background: #e6f0ff; color: #1d4ed8; } - .sidebar-link.active { - background: #e6f0ff; - color: #1d4ed8; - } + .sidebar-icon { width: 20px; height: 20px; flex-shrink: 0; } + .sidebar-logout { margin-top: auto; } + .sidebar-logout button { width: 100%; border: none; background: transparent; color: #ef4444; font-weight: 600; padding: 10px; text-align: left; } - .sidebar-icon { - width: 20px; - height: 20px; - flex-shrink: 0; - } - - .sidebar-logout { - margin-top: auto; - } - - .sidebar-logout button { - width: 100%; - border: none; - background: transparent; - color: #ef4444; - font-weight: 600; - padding: 10px; - text-align: left; - } - - /* ===== TOGGLE ARROW BUTTON ===== */ + /* ===== TOGGLE BUTTON ===== */ .sidebar-toggle-btn { position: fixed; top: 50%; transform: translateY(-50%); - left: 260px; /* sama dengan lebar sidebar saat terbuka */ + left: 260px; z-index: 1000; width: 22px; height: 48px; @@ -121,19 +86,11 @@ box-shadow: 2px 0 8px rgba(43, 142, 243, 0.3); } - .sidebar-toggle-btn:hover { - background: #1a7ae0; - } + .sidebar-toggle-btn:hover { background: #1a7ae0; } + .sidebar-toggle-btn.collapsed { left: 0; } - /* Posisi tombol saat sidebar collapsed */ - .sidebar-toggle-btn.collapsed { - left: 0; - } - - /* Arrow icon SVG */ .toggle-arrow { - width: 12px; - height: 12px; + width: 12px; height: 12px; fill: none; stroke: white; stroke-width: 2.5; @@ -142,20 +99,10 @@ transition: transform 0.3s ease; } - /* Saat collapsed, panah mengarah ke kanan (buka) */ - .sidebar-toggle-btn.collapsed .toggle-arrow { - transform: rotate(180deg); - } + .sidebar-toggle-btn.collapsed .toggle-arrow { transform: rotate(180deg); } /* ===== MAIN ===== */ - .main { - flex: 1; - background: #f5f9ff; - display: flex; - flex-direction: column; - transition: all 0.3s ease; - min-width: 0; /* prevent overflow */ - } + .main { flex: 1; background: #f5f9ff; display: flex; flex-direction: column; transition: all 0.3s ease; min-width: 0; } /* TOPBAR */ .topbar { @@ -169,31 +116,40 @@ align-items: center; } - .topbar-left { - font-weight: 600; - font-size: 16px; - display: flex; - align-items: center; - gap: 10px; - } + .topbar-left { font-weight: 600; font-size: 16px; display: flex; align-items: center; gap: 10px; } + .topbar-right { display: flex; align-items: center; gap: 14px; } + .topbar-icon { width: 24px; height: 24px; cursor: pointer; } - .topbar-right { - display: flex; - align-items: center; - gap: 16px; - } - - .topbar-icon { - width: 24px; - height: 24px; + /* Foto profil di topbar */ + .topbar-avatar { + width: 36px; height: 36px; + border-radius: 50%; + object-fit: cover; + border: 2px solid rgba(255,255,255,0.5); cursor: pointer; + transition: border-color 0.2s; + display: block; } - /* CONTENT */ - .content { - padding: 20px 30px; - flex: 1; + .topbar-avatar:hover { border-color: white; } + + .topbar-avatar-icon { + width: 36px; height: 36px; + border-radius: 50%; + background: rgba(255,255,255,0.2); + border: 2px solid rgba(255,255,255,0.4); + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: background 0.2s; + flex-shrink: 0; } + + .topbar-avatar-icon:hover { background: rgba(255,255,255,0.3); } + .topbar-avatar-icon svg { width: 20px; height: 20px; stroke: white; } + + .content { padding: 20px 30px; flex: 1; } @stack('styles') @@ -202,38 +158,32 @@
- - -
-
-
@yield('content')
-
- @stack('scripts') diff --git a/resources/views/siswa/leaderboard/index.blade.php b/resources/views/siswa/leaderboard/index.blade.php index eada5fd..80e330e 100644 --- a/resources/views/siswa/leaderboard/index.blade.php +++ b/resources/views/siswa/leaderboard/index.blade.php @@ -7,137 +7,62 @@ .page-title { font-size: 28px; font-weight: 800; margin-top: -20px; margin-bottom: 6px; } .page-subtitle { font-size: 14px; color: #64748b; margin-bottom: 24px; } -/* Podium top 3 */ -.podium-wrap { - display: flex; - align-items: flex-end; - justify-content: center; - gap: 12px; - margin-bottom: 32px; -} - -.podium-item { - display: flex; - flex-direction: column; - align-items: center; - gap: 8px; -} +.podium-wrap { display: flex; align-items: flex-end; justify-content: center; gap: 12px; margin-bottom: 32px; } +.podium-item { display: flex; flex-direction: column; align-items: center; gap: 8px; } .podium-avatar { - width: 56px; - height: 56px; border-radius: 50%; - display: flex; - align-items: center; - justify-content: center; - font-size: 22px; - font-weight: 800; - color: white; - position: relative; + display: flex; align-items: center; justify-content: center; + font-size: 22px; font-weight: 800; color: white; + position: relative; overflow: hidden; flex-shrink: 0; + width: 56px; height: 56px; } -.podium-crown { - position: absolute; - top: -16px; - font-size: 18px; -} +.podium-avatar img { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; } +.podium-crown { position: absolute; top: -16px; font-size: 18px; z-index: 1; } -.rank-1 .podium-avatar { background: linear-gradient(135deg, #f59e0b, #d97706); width: 68px; height: 68px; font-size: 26px; } -.rank-2 .podium-avatar { background: linear-gradient(135deg, #94a3b8, #64748b); } -.rank-3 .podium-avatar { background: linear-gradient(135deg, #f97316, #ea580c); } +.rank-1 .podium-avatar { background: linear-gradient(135deg,#f59e0b,#d97706); width:68px; height:68px; font-size:26px; } +.rank-2 .podium-avatar { background: linear-gradient(135deg,#94a3b8,#64748b); } +.rank-3 .podium-avatar { background: linear-gradient(135deg,#f97316,#ea580c); } -.podium-name { font-size: 13px; font-weight: 700; color: #1e293b; text-align: center; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } -.podium-exp { font-size: 12px; color: #64748b; } +.podium-name { font-size:13px; font-weight:700; color:#1e293b; text-align:center; max-width:90px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; } +.podium-exp { font-size:12px; color:#64748b; } -.podium-bar { - border-radius: 12px 12px 0 0; - width: 80px; - display: flex; - align-items: center; - justify-content: center; - font-size: 20px; - font-weight: 800; - color: white; -} +.podium-bar { border-radius:12px 12px 0 0; width:80px; display:flex; align-items:center; justify-content:center; font-size:20px; font-weight:800; color:white; } +.rank-1 .podium-bar { height:80px; background:linear-gradient(135deg,#f59e0b,#d97706); } +.rank-2 .podium-bar { height:60px; background:linear-gradient(135deg,#94a3b8,#64748b); } +.rank-3 .podium-bar { height:44px; background:linear-gradient(135deg,#f97316,#ea580c); } -.rank-1 .podium-bar { height: 80px; background: linear-gradient(135deg, #f59e0b, #d97706); } -.rank-2 .podium-bar { height: 60px; background: linear-gradient(135deg, #94a3b8, #64748b); } -.rank-3 .podium-bar { height: 44px; background: linear-gradient(135deg, #f97316, #ea580c); } +.my-rank-banner { background:linear-gradient(135deg,#667eea,#764ba2); border-radius:16px; padding:16px 20px; color:white; display:flex; align-items:center; gap:16px; margin-bottom:20px; } +.my-rank-avatar { width:48px; height:48px; border-radius:50%; object-fit:cover; border:2px solid rgba(255,255,255,0.5); flex-shrink:0; } +.my-rank-avatar-placeholder { width:48px; height:48px; border-radius:50%; background:rgba(255,255,255,0.2); display:flex; align-items:center; justify-content:center; font-size:20px; font-weight:800; flex-shrink:0; } +.my-rank-num { font-size:36px; font-weight:800; line-height:1; } +.my-rank-info { flex:1; } +.my-rank-label { font-size:12px; opacity:0.8; margin-bottom:2px; } +.my-rank-nama { font-size:16px; font-weight:700; } +.my-rank-exp { font-size:13px; opacity:0.9; } -/* My rank banner */ -.my-rank-banner { - background: linear-gradient(135deg, #667eea, #764ba2); - border-radius: 16px; - padding: 16px 20px; - color: white; - display: flex; - align-items: center; - gap: 16px; - margin-bottom: 20px; -} +.custom-card { background:white; border-radius:20px; border:2px solid #e5e5e5; padding:22px; } +.section-title { font-size:15px; font-weight:700; color:#1e293b; margin-bottom:16px; } -.my-rank-num { - font-size: 36px; - font-weight: 800; - line-height: 1; -} +.lb-row { display:flex; align-items:center; gap:12px; padding:10px 14px; border-radius:12px; margin-bottom:8px; transition:background 0.15s; } +.lb-row:hover { background:#f8fafc; } +.lb-row.highlight { background:#f0eeff; border:2px solid #c4b5fd; } -.my-rank-info { flex: 1; } -.my-rank-label { font-size: 12px; opacity: 0.8; margin-bottom: 2px; } -.my-rank-nama { font-size: 16px; font-weight: 700; } -.my-rank-exp { font-size: 13px; opacity: 0.9; } +.lb-rank { width:32px; height:32px; border-radius:50%; background:#e2e8f0; display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:700; color:#64748b; flex-shrink:0; } +.lb-rank.gold { background:#fef3c7; color:#d97706; } +.lb-rank.silver { background:#f1f5f9; color:#64748b; } +.lb-rank.bronze { background:#ffedd5; color:#ea580c; } -/* Tabel */ -.custom-card { background: white; border-radius: 20px; border: 2px solid #e5e5e5; padding: 22px; } -.section-title { font-size: 15px; font-weight: 700; color: #1e293b; margin-bottom: 16px; } +.lb-avatar { width:36px; height:36px; border-radius:50%; object-fit:cover; flex-shrink:0; border:2px solid #e2e8f0; } +.lb-avatar-placeholder { width:36px; height:36px; border-radius:50%; background:#e6f0ff; display:flex; align-items:center; justify-content:center; font-size:14px; font-weight:700; color:#2b8ef3; flex-shrink:0; } -.lb-row { - display: flex; - align-items: center; - gap: 14px; - padding: 12px 14px; - border-radius: 12px; - margin-bottom: 8px; - transition: background 0.15s; -} +.lb-nama { flex:1; font-size:14px; font-weight:600; color:#1e293b; } +.lb-nisn { font-size:12px; color:#94a3b8; } +.lb-exp { font-size:14px; font-weight:700; color:#667eea; } -.lb-row:hover { background: #f8fafc; } -.lb-row.highlight { background: #f0eeff; border: 2px solid #c4b5fd; } - -.lb-rank { - width: 32px; - height: 32px; - border-radius: 50%; - background: #e2e8f0; - display: flex; - align-items: center; - justify-content: center; - font-size: 13px; - font-weight: 700; - color: #64748b; - flex-shrink: 0; -} - -.lb-rank.gold { background: #fef3c7; color: #d97706; } -.lb-rank.silver { background: #f1f5f9; color: #64748b; } -.lb-rank.bronze { background: #ffedd5; color: #ea580c; } - -.lb-nama { flex: 1; font-size: 14px; font-weight: 600; color: #1e293b; } -.lb-nisn { font-size: 12px; color: #94a3b8; } -.lb-exp { font-size: 14px; font-weight: 700; color: #667eea; } - -.semester-badge { - display: inline-block; - background: #f0eeff; - color: #667eea; - font-size: 12px; - font-weight: 700; - padding: 4px 12px; - border-radius: 99px; - margin-bottom: 20px; -} - -.empty-state { text-align: center; padding: 40px 20px; color: #94a3b8; } +.semester-badge { display:inline-block; background:#f0eeff; color:#667eea; font-size:12px; font-weight:700; padding:4px 12px; border-radius:99px; margin-bottom:20px; } +.empty-state { text-align:center; padding:40px 20px; color:#94a3b8; } @endpush @@ -148,9 +73,7 @@

๐Ÿ… Leaderboard

Peringkat siswa berdasarkan total EXP yang dikumpulkan.

- - Semester {{ $semester }} ยท {{ $tahunAjaran }} - +Semester {{ $semester }} ยท {{ $tahunAjaran }} @if($leaderboard->isEmpty())
@@ -160,9 +83,8 @@
@else - {{-- Podium Top 3 --}} @php - $top3 = $leaderboard->take(3); + $top3 = $leaderboard->take(3); $first = $top3->firstWhere('ranking', 1); $second = $top3->firstWhere('ranking', 2); $third = $top3->firstWhere('ranking', 3); @@ -171,31 +93,44 @@ @if($first)
- {{-- Rank 2 --}} @if($second)
-
{{ strtoupper(substr($second['nama'], 0, 1)) }}
+
+ @if(!empty($second['foto_profil'])) + + @else + {{ strtoupper(substr($second['nama'], 0, 1)) }} + @endif +
{{ $second['nama'] }}
โญ {{ number_format($second['exp']) }}
2
@endif - {{-- Rank 1 --}}
๐Ÿ‘‘ - {{ strtoupper(substr($first['nama'], 0, 1)) }} + @if(!empty($first['foto_profil'])) + + @else + {{ strtoupper(substr($first['nama'], 0, 1)) }} + @endif
{{ $first['nama'] }}
โญ {{ number_format($first['exp']) }}
1
- {{-- Rank 3 --}} @if($third)
-
{{ strtoupper(substr($third['nama'], 0, 1)) }}
+
+ @if(!empty($third['foto_profil'])) + + @else + {{ strtoupper(substr($third['nama'], 0, 1)) }} + @endif +
{{ $third['nama'] }}
โญ {{ number_format($third['exp']) }}
3
@@ -205,9 +140,13 @@
@endif - {{-- My Rank Banner --}} @if($myRank)
+ @if(!empty($myRank['foto_profil'])) + + @else +
{{ strtoupper(substr($myRank['nama'], 0, 1)) }}
+ @endif
#{{ $myRank['ranking'] }}
Posisimu saat ini
@@ -218,16 +157,13 @@
@endif - {{-- Tabel semua --}}

๐Ÿ“‹ Semua Peringkat

@foreach($leaderboard as $item) @php $isMe = $item['id_siswa'] === $siswaLogin->id_siswa; - $rankClass = match($item['ranking']) { - 1 => 'gold', 2 => 'silver', 3 => 'bronze', default => '' - }; + $rankClass = match($item['ranking']) { 1=>'gold', 2=>'silver', 3=>'bronze', default=>'' }; @endphp
@@ -237,10 +173,19 @@ @else {{ $item['ranking'] }} @endif
+ + @if(!empty($item['foto_profil'])) + + @else +
{{ strtoupper(substr($item['nama'], 0, 1)) }}
+ @endif +
{{ $item['nama'] }} - @if($isMe) Kamu @endif + @if($isMe) + Kamu + @endif
{{ $item['nisn'] }}
diff --git a/resources/views/siswa/profile/edit.blade.php b/resources/views/siswa/profile/edit.blade.php new file mode 100644 index 0000000..642f465 --- /dev/null +++ b/resources/views/siswa/profile/edit.blade.php @@ -0,0 +1,255 @@ +@extends('siswa.layouts.app') + +@section('title', 'Edit Profil') + +@push('styles') + +@endpush + +@section('content') + +@php $siswa = Auth::guard('siswa')->user(); @endphp + +

Edit Profil

+

Perbarui foto profil dan password akunmu.

+ +@if(session('success')) +
โœ“ {{ session('success') }}
+@endif + +@if($errors->any()) +
+
    + @foreach($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+@endif + +
+ @csrf + @method('PUT') + +
+ + {{-- Foto Profil --}} +
+ @if($siswa->foto_profil) + Foto Profil + @else +
+ + + +
+ + @endif + +
+

Format: JPG, PNG, WEBP. Maks. 2MB.

+ + +
+
+ + {{-- Info tidak bisa diubah --}} +
+ + +
+ +
+ + +
+ +
+ + {{-- Password --}} +
+ + +
+ +
+ + +
+ +
+ +
+ +
+
+ +@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index bb3aa00..3fb21d2 100644 --- a/routes/web.php +++ b/routes/web.php @@ -13,16 +13,16 @@ use App\Http\Controllers\Admin\MapelController as AdminMapelController; use App\Http\Controllers\Admin\ChallengeController as AdminChallengeController; use App\Http\Controllers\Admin\LeaderboardController as AdminLeaderboardController; +use App\Http\Controllers\Admin\ProfileController as AdminProfileController; use App\Http\Controllers\Admin\MateriTugasController as AdminMateriTugasController; - // GURU CONTROLLERS use App\Http\Controllers\Guru\LoginController as GuruLoginController; use App\Http\Controllers\Guru\DashboardController as GuruDashboardController; use App\Http\Controllers\Guru\GuruController as GuruGuruController; use App\Http\Controllers\Guru\KelasController as GuruKelasController; use App\Http\Controllers\Guru\SiswaController as GuruSiswaController; -use App\Http\Controllers\Guru\ProfilController as GuruProfilController; +use App\Http\Controllers\Guru\ProfileController as GuruProfileController; use App\Http\Controllers\Guru\MapelController as GuruMapelController; use App\Http\Controllers\Guru\LeaderboardController as GuruLeaderboardController; @@ -33,6 +33,7 @@ use App\Http\Controllers\Siswa\TugasController as SiswaTugasController; use App\Http\Controllers\Siswa\ChallengeController as SiswaChallengeController; use App\Http\Controllers\Siswa\LeaderboardController as SiswaLeaderboardController; +use App\Http\Controllers\Siswa\ProfileController as SiswaProfileController; // ==================== // LANDING PAGE @@ -87,9 +88,8 @@ return view('admin.notif'); })->name('notif'); - Route::get('/profil', function () { - return view('admin.profil'); - })->name('profil'); + Route::get('/profile', [AdminProfileController::class, 'edit'])->name('profile.edit'); + Route::put('/profile', [AdminProfileController::class, 'update'])->name('profile.update'); // โ”€โ”€ GURU โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Route::get('/guru/kelas-by-mapel', [AdminGuruController::class, 'getKelasByMapel']) @@ -111,7 +111,6 @@ Route::delete('/tugas/{id}', [AdminMateriTugasController::class, 'destroyTugas'])->name('tugas.destroy'); // โ”€โ”€ CHALLENGE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - // WAJIB di atas Route::resource agar tidak konflik dengan {challenge} wildcard Route::get('/challenge/{id}/edit-data', [AdminChallengeController::class, 'editData']) ->name('challenge.editData'); Route::resource('challenge', AdminChallengeController::class); @@ -155,10 +154,8 @@ Route::get('/tugas/{id}/detail', [GuruMapelController::class, 'detailTugas'])->name('tugas.detail'); Route::delete('/tugas/{id}', [GuruMapelController::class, 'destroyTugas'])->name('tugas.destroy'); - - // Profil (Edit) - Route::get('/profil', [GuruProfilController::class, 'show'])->name('profil.show'); - Route::put('/profil', [GuruProfilController::class, 'update'])->name('profil.update'); + Route::get('/profile', [GuruProfileController::class, 'edit'])->name('profile.edit'); + Route::put('/profile', [GuruProfileController::class, 'update'])->name('profile.update'); // LOGOUT GURU Route::post('/logout', [GuruLoginController::class, 'logout'])->name('logout'); @@ -188,6 +185,10 @@ //LEADERBOARD SISWA Route::get('/leaderboard', [SiswaLeaderboardController::class, 'index'])->name('leaderboard.index'); + + //PROFILE SISWA + Route::get('/profile', [SiswaProfileController::class, 'edit'])->name('profile.edit'); + Route::put('/profile', [SiswaProfileController::class, 'update'])->name('profile.update'); // LOGOUT SISWA Route::post('/logout', [SiswaLoginController::class, 'logout'])->name('logout');