update: deploy
parent
6ab4d52e7f
commit
8d0f9277cd
|
@ -3,6 +3,10 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class ProfileController extends Controller
|
||||
{
|
||||
|
@ -10,4 +14,194 @@ class ProfileController extends Controller
|
|||
{
|
||||
return view('components/users/viewProfile');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show change password form
|
||||
*/
|
||||
public function changePasswordForm()
|
||||
{
|
||||
return view('profile.change-password');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user password
|
||||
*/
|
||||
public function updatePassword(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'current_password' => ['required', 'string'],
|
||||
'password' => [
|
||||
'required',
|
||||
'string',
|
||||
'min:8',
|
||||
'confirmed',
|
||||
'regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^A-Za-z0-9]).{8,}$/',
|
||||
],
|
||||
], [
|
||||
'current_password.required' => 'Password saat ini wajib diisi.',
|
||||
'password.min' => 'Password baru minimal 8 karakter.',
|
||||
'password.confirmed' => 'Konfirmasi password tidak cocok.',
|
||||
'password.regex' => 'Password harus mengandung huruf besar, huruf kecil, angka, dan simbol khusus.',
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
// Verify current password
|
||||
if (!Hash::check($request->current_password, $user->password)) {
|
||||
throw ValidationException::withMessages([
|
||||
'current_password' => ['Password saat ini tidak benar.'],
|
||||
]);
|
||||
}
|
||||
|
||||
// Update password
|
||||
$user->update([
|
||||
'password' => Hash::make($request->password),
|
||||
]);
|
||||
|
||||
// Revoke all API tokens for security (if using Sanctum)
|
||||
if (method_exists($user, 'tokens')) {
|
||||
$user->tokens()->delete();
|
||||
}
|
||||
|
||||
// Logout from current session for security
|
||||
Auth::logout();
|
||||
|
||||
// Invalidate the session
|
||||
$request->session()->invalidate();
|
||||
$request->session()->regenerateToken();
|
||||
|
||||
return redirect()->route('login.index')
|
||||
->with('success', 'Password berhasil diubah. Silakan login kembali dengan password baru.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show change email form
|
||||
*/
|
||||
public function changeEmailForm()
|
||||
{
|
||||
return view('profile.change-email');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user email
|
||||
*/
|
||||
public function updateEmail(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$request->validate([
|
||||
'current_password' => ['required', 'string'],
|
||||
'email' => [
|
||||
'required',
|
||||
'string',
|
||||
'email',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
], [
|
||||
'current_password.required' => 'Password saat ini wajib diisi untuk konfirmasi.',
|
||||
'email.required' => 'Email baru wajib diisi.',
|
||||
'email.email' => 'Format email tidak valid.',
|
||||
'email.unique' => 'Email sudah digunakan oleh pengguna lain.',
|
||||
]);
|
||||
|
||||
// Verify current password
|
||||
if (!Hash::check($request->current_password, $user->password)) {
|
||||
throw ValidationException::withMessages([
|
||||
'current_password' => ['Password saat ini tidak benar.'],
|
||||
]);
|
||||
}
|
||||
|
||||
// Update email
|
||||
$user->update([
|
||||
'email' => $request->email,
|
||||
]);
|
||||
|
||||
return redirect()->route('profile.change-email')
|
||||
->with('success', 'Email berhasil diubah.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show edit profile form
|
||||
*/
|
||||
public function edit()
|
||||
{
|
||||
$user = Auth::user();
|
||||
return view('profile.edit', compact('user'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user profile
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
||||
$request->validate([
|
||||
'name' => ['required', 'string', 'max:255'],
|
||||
'username' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:255',
|
||||
Rule::unique('users')->ignore($user->id),
|
||||
],
|
||||
], [
|
||||
'name.required' => 'Nama wajib diisi.',
|
||||
'username.required' => 'Username wajib diisi.',
|
||||
'username.unique' => 'Username sudah digunakan oleh pengguna lain.',
|
||||
]);
|
||||
|
||||
$user->update([
|
||||
'name' => $request->name,
|
||||
'username' => $request->username,
|
||||
]);
|
||||
|
||||
return redirect()->route('profile.edit')
|
||||
->with('success', 'Profil berhasil diperbarui.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user profile photo
|
||||
*/
|
||||
public function updatePhoto(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'profile_photo' => ['required', 'image', 'mimes:jpeg,png,jpg,gif', 'max:2048'],
|
||||
], [
|
||||
'profile_photo.required' => 'Foto profil wajib dipilih.',
|
||||
'profile_photo.image' => 'File harus berupa gambar.',
|
||||
'profile_photo.mimes' => 'Format foto harus jpeg, png, jpg, atau gif.',
|
||||
'profile_photo.max' => 'Ukuran foto maksimal 2MB.',
|
||||
]);
|
||||
|
||||
$user = Auth::user();
|
||||
|
||||
// Delete old photo if exists
|
||||
if ($user->profile_photo && file_exists(public_path('storage/profile_photos/' . $user->profile_photo))) {
|
||||
unlink(public_path('storage/profile_photos/' . $user->profile_photo));
|
||||
}
|
||||
|
||||
// Store new photo
|
||||
$file = $request->file('profile_photo');
|
||||
$filename = time() . '_' . $user->id . '.' . $file->getClientOriginalExtension();
|
||||
|
||||
// Create directory if not exists
|
||||
$uploadPath = public_path('storage/profile_photos');
|
||||
if (!file_exists($uploadPath)) {
|
||||
mkdir($uploadPath, 0755, true);
|
||||
}
|
||||
|
||||
$file->move($uploadPath, $filename);
|
||||
|
||||
// Update user profile photo
|
||||
$user->update([
|
||||
'profile_photo' => $filename,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Foto profil berhasil diperbarui.',
|
||||
'photo_url' => asset('storage/profile_photos/' . $filename)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Concerns\HasUuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
@ -12,7 +13,21 @@ use Spatie\Permission\Traits\HasRoles;
|
|||
class User extends Authenticatable
|
||||
{
|
||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
||||
use HasApiTokens, HasFactory, Notifiable, HasRoles;
|
||||
use HasApiTokens, HasFactory, HasUuids, Notifiable, HasRoles;
|
||||
|
||||
/**
|
||||
* The primary key type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyType = 'string';
|
||||
|
||||
/**
|
||||
* Indicates if the IDs are auto-incrementing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $incrementing = false;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
@ -24,6 +39,7 @@ class User extends Authenticatable
|
|||
'email',
|
||||
'username',
|
||||
'password',
|
||||
'profile_photo',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\URL;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
|
@ -19,6 +20,9 @@ class AppServiceProvider extends ServiceProvider
|
|||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
if ($this->app->environment('production')) {
|
||||
URL::forceScheme('https');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,13 @@ return new class extends Migration
|
|||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->uuid('id')->primary();
|
||||
$table->string('name');
|
||||
$table->string('email')->unique();
|
||||
$table->string('username')->nullable()->unique();
|
||||
$table->timestamp('email_verified_at')->nullable();
|
||||
$table->string('password');
|
||||
$table->string('profile_photo')->nullable();
|
||||
$table->rememberToken();
|
||||
$table->timestamps();
|
||||
});
|
||||
|
@ -29,7 +31,7 @@ return new class extends Migration
|
|||
|
||||
Schema::create('sessions', function (Blueprint $table) {
|
||||
$table->string('id')->primary();
|
||||
$table->foreignId('user_id')->nullable()->index();
|
||||
$table->uuid('user_id')->nullable()->index();
|
||||
$table->string('ip_address', 45)->nullable();
|
||||
$table->text('user_agent')->nullable();
|
||||
$table->longText('payload');
|
||||
|
|
|
@ -13,7 +13,9 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->morphs('tokenable');
|
||||
$table->string('tokenable_type');
|
||||
$table->string('tokenable_id');
|
||||
$table->index(['tokenable_type', 'tokenable_id']);
|
||||
$table->text('name');
|
||||
$table->string('token', 64)->unique();
|
||||
$table->text('abilities')->nullable();
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('username')->nullable()->unique()->after('email');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropUnique(['username']);
|
||||
$table->dropColumn('username');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -51,7 +51,7 @@ return new class extends Migration
|
|||
$table->unsignedBigInteger($pivotPermission);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->string($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotPermission)
|
||||
|
@ -62,20 +62,23 @@ return new class extends Migration
|
|||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
$table->primary(
|
||||
[$columnNames['team_foreign_key'], $pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary'
|
||||
);
|
||||
} else {
|
||||
$table->primary([$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary');
|
||||
$table->primary(
|
||||
[$pivotPermission, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_permissions_permission_model_type_primary'
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Schema::create($tableNames['model_has_roles'], static function (Blueprint $table) use ($tableNames, $columnNames, $pivotRole, $teams) {
|
||||
$table->unsignedBigInteger($pivotRole);
|
||||
|
||||
$table->string('model_type');
|
||||
$table->unsignedBigInteger($columnNames['model_morph_key']);
|
||||
$table->string($columnNames['model_morph_key']);
|
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index');
|
||||
|
||||
$table->foreign($pivotRole)
|
||||
|
@ -86,11 +89,15 @@ return new class extends Migration
|
|||
$table->unsignedBigInteger($columnNames['team_foreign_key']);
|
||||
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index');
|
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
$table->primary(
|
||||
[$columnNames['team_foreign_key'], $pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary'
|
||||
);
|
||||
} else {
|
||||
$table->primary([$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary');
|
||||
$table->primary(
|
||||
[$pivotRole, $columnNames['model_morph_key'], 'model_type'],
|
||||
'model_has_roles_role_model_type_primary'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -6,112 +6,177 @@
|
|||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card basic-data-table">
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-3 gap-3">
|
||||
<!-- Header Section -->
|
||||
<div class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-4 gap-3">
|
||||
<div>
|
||||
<h5 class="mb-0">Edit Pengguna: {{ $user->name }}</h5>
|
||||
<h5 class="mb-0">Edit Pengguna</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('admin.users.index') }}"
|
||||
class="btn btn-secondary btn-sm d-flex align-items-center gap-2">
|
||||
<div>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-secondary btn-sm d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="iconoir:arrow-left"></iconify-icon>
|
||||
<span>Kembali</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error Messages -->
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||
<div class="d-flex align-items-center mb-2">
|
||||
<iconify-icon icon="material-symbols:error" class="me-2"></iconify-icon>
|
||||
<strong>Terjadi kesalahan:</strong>
|
||||
</div>
|
||||
<ul class="mb-0 ps-3">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('admin.users.update', $user) }}">
|
||||
<!-- Form -->
|
||||
<form method="POST" action="{{ route('admin.users.update', $user) }}" class="needs-validation" novalidate>
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<!-- Personal Information Section -->
|
||||
<div class="mb-4">
|
||||
<h6 class="mb-3 text-primary d-flex align-items-center">
|
||||
<iconify-icon icon="mdi:account-circle" class="me-2"></iconify-icon>
|
||||
Informasi Personal
|
||||
</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Nama Lengkap</label>
|
||||
<input type="text" name="name" class="form-control" required
|
||||
value="{{ old('name', $user->name) }}" placeholder="Masukkan nama lengkap">
|
||||
<label class="form-label fw-medium">
|
||||
Nama Lengkap <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
name="name"
|
||||
class="form-control @error('name') is-invalid @enderror"
|
||||
required
|
||||
value="{{ old('name', $user->name) }}"
|
||||
placeholder="Masukkan nama lengkap">
|
||||
@error('name')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" name="email" class="form-control" required
|
||||
value="{{ old('email', $user->email) }}" placeholder="Masukkan email">
|
||||
<label class="form-label fw-medium">
|
||||
Email <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="email"
|
||||
name="email"
|
||||
class="form-control @error('email') is-invalid @enderror"
|
||||
required
|
||||
value="{{ old('email', $user->email) }}"
|
||||
placeholder="Masukkan email">
|
||||
@error('email')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Username</label>
|
||||
<input type="text" name="username" class="form-control" required
|
||||
value="{{ old('username', $user->username) }}" placeholder="Masukkan username">
|
||||
<label class="form-label fw-medium">
|
||||
Username <span class="text-danger">*</span>
|
||||
</label>
|
||||
<input type="text"
|
||||
name="username"
|
||||
class="form-control @error('username') is-invalid @enderror"
|
||||
required
|
||||
value="{{ old('username', $user->username) }}"
|
||||
placeholder="Masukkan username">
|
||||
@error('username')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Password Baru</label>
|
||||
<input type="password" name="password" class="form-control"
|
||||
placeholder="Kosongkan jika tidak ingin mengubah">
|
||||
<div class="form-text">Kosongkan jika tidak ingin mengubah password. Password harus minimal 8
|
||||
karakter, mengandung huruf besar, huruf kecil, angka, dan simbol khusus.</div>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Konfirmasi Password Baru</label>
|
||||
<input type="password" name="password_confirmation" class="form-control"
|
||||
placeholder="Konfirmasi password baru">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<label class="form-label">Roles</label>
|
||||
<!-- Divider -->
|
||||
<hr class="my-4">
|
||||
|
||||
<!-- Password Section -->
|
||||
<div class="mb-4">
|
||||
<h6 class="mb-3 text-primary d-flex align-items-center">
|
||||
<iconify-icon icon="mdi:lock" class="me-2"></iconify-icon>
|
||||
Keamanan
|
||||
</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label fw-medium">Password Baru</label>
|
||||
<input type="password"
|
||||
name="password"
|
||||
class="form-control @error('password') is-invalid @enderror"
|
||||
placeholder="Kosongkan jika tidak ingin mengubah">
|
||||
<div class="form-text d-flex align-items-center">
|
||||
<iconify-icon icon="mdi:information" class="me-1"></iconify-icon>
|
||||
Kosongkan jika tidak ingin mengubah password. Password minimal 8 karakter dengan huruf besar, kecil, angka, dan simbol.
|
||||
</div>
|
||||
@error('password')
|
||||
<div class="invalid-feedback">{{ $message }}</div>
|
||||
@enderror
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label fw-medium">Konfirmasi Password Baru</label>
|
||||
<input type="password"
|
||||
name="password_confirmation"
|
||||
class="form-control"
|
||||
placeholder="Konfirmasi password baru">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Roles Section -->
|
||||
<div class="mb-4">
|
||||
<h6 class="mb-3 text-primary d-flex align-items-center">
|
||||
<iconify-icon icon="mdi:shield-account" class="me-2"></iconify-icon>
|
||||
Roles & Permissions
|
||||
</h6>
|
||||
<div class="p-3 bg-light rounded-3">
|
||||
@if ($roles->count() > 0)
|
||||
<div class="row g-2">
|
||||
@foreach ($roles as $role)
|
||||
<div class="col-12 col-md-4">
|
||||
<div class="form-check style-check d-flex align-items-center">
|
||||
<input class="form-check-input border border-neutral-300 me-8" type="checkbox"
|
||||
name="roles[]" value="{{ $role->name }}" id="role_{{ $role->id }}"
|
||||
<div class="col-12 col-sm-6 col-md-4">
|
||||
<div class="form-check style-check d-flex align-items-center gap-2">
|
||||
<input class="form-check-input border border-neutral-300"
|
||||
type="checkbox"
|
||||
name="roles[]"
|
||||
value="{{ $role->name }}"
|
||||
id="role_{{ $role->id }}"
|
||||
{{ in_array($role->name, old('roles', $userRoles)) ? 'checked' : '' }}>
|
||||
<label class="form-check-label"
|
||||
for="role_{{ $role->id }}">{{ $role->name }}</label>
|
||||
<label class="form-check-label fw-medium" for="role_{{ $role->id }}">
|
||||
{{ ucfirst($role->name) }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Info -->
|
||||
<div class="mt-4">
|
||||
<div class="alert alert-info">
|
||||
<h6>Informasi Pengguna:</h6>
|
||||
<ul class="mb-0">
|
||||
<li>Dibuat: {{ $user->created_at->format('d/m/Y H:i:s') }}</li>
|
||||
<li>Terakhir diperbarui: {{ $user->updated_at->format('d/m/Y H:i:s') }}</li>
|
||||
@if ($user->email_verified_at)
|
||||
<li>Email diverifikasi: {{ $user->email_verified_at->format('d/m/Y H:i:s') }}</li>
|
||||
@else
|
||||
<li class="text-warning">Email belum diverifikasi</li>
|
||||
<div class="text-center text-muted py-3">
|
||||
<iconify-icon icon="mdi:shield-off" class="fs-2 mb-2"></iconify-icon>
|
||||
<p class="mb-0">Tidak ada roles yang tersedia</p>
|
||||
</div>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex gap-2">
|
||||
<button class="btn btn-primary d-flex align-items-center gap-2">
|
||||
<!-- Action Buttons -->
|
||||
<div class="d-flex align-items-center gap-2 pt-3 border-top">
|
||||
<button type="submit" class="btn btn-primary d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="material-symbols:save"></iconify-icon>
|
||||
<span>Perbarui</span>
|
||||
<span>Perbarui Pengguna</span>
|
||||
</button>
|
||||
<a href="{{ route('admin.users.show', $user) }}" class="btn btn-info d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="lucide:eye"></iconify-icon>
|
||||
<span>Lihat Detail</span>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-light d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="material-symbols:cancel"></iconify-icon>
|
||||
<span>Batal</span>
|
||||
</a>
|
||||
<a href="{{ route('admin.users.index') }}" class="btn btn-light">Batal</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<div
|
||||
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-3 gap-3">
|
||||
<div>
|
||||
<h5 class="mb-0">Detail Pengguna: {{ $user->name }}</h5>
|
||||
<h5 class="mb-0">Detail Pengguna:</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('admin.users.index') }}"
|
||||
|
@ -51,10 +51,6 @@
|
|||
</div>
|
||||
<div class="card-body">
|
||||
<table class="table table-borderless mb-0">
|
||||
<tr>
|
||||
<td width="150"><strong>ID:</strong></td>
|
||||
<td>{{ $user->id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>Nama:</strong></td>
|
||||
<td>{{ $user->name }}</td>
|
||||
|
@ -63,11 +59,6 @@
|
|||
<td><strong>Email:</strong></td>
|
||||
<td>
|
||||
{{ $user->email }}
|
||||
@if ($user->email_verified_at)
|
||||
<span class="badge bg-success ms-2">Terverifikasi</span>
|
||||
@else
|
||||
<span class="badge bg-warning ms-2">Belum Terverifikasi</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@ -133,8 +124,8 @@
|
|||
<h6 class="mb-0">Ringkasan Aktivitas</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<div class="row g-4">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-light text-center">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Total Role</h6>
|
||||
|
@ -142,7 +133,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-light text-center">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Total Permission</h6>
|
||||
|
@ -150,23 +141,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card bg-light text-center">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Status Email</h6>
|
||||
@if ($user->email_verified_at)
|
||||
<h3 class="text-success mb-0">✓</h3>
|
||||
@else
|
||||
<h3 class="text-warning mb-0">✗</h3>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-light text-center">
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">Akun Aktif</h6>
|
||||
<h3 class="text-success mb-0">{{ $user->created_at->diffInDays(now()) }} hari
|
||||
<h3 class="text-success mb-0">{{ max(1, $user->created_at->diffInDays(now())) }} hari
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -207,24 +207,33 @@
|
|||
</div><!-- Notification dropdown end --> --}}
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="d-flex justify-content-center align-items-center rounded-circle" type="button" data-bs-toggle="dropdown">
|
||||
<iconify-icon icon="solar:user-linear" class="text-primary-light text-xl w-40-px h-40-px d-flex justify-content-center align-items-center bg-neutral-200 rounded-circle"></iconify-icon>
|
||||
<button class="d-flex justify-content-center align-items-center rounded-circle" type="button"
|
||||
data-bs-toggle="dropdown">
|
||||
<iconify-icon icon="solar:user-linear"
|
||||
class="text-primary-light text-xl w-40-px h-40-px d-flex justify-content-center align-items-center bg-neutral-200 rounded-circle"></iconify-icon>
|
||||
</button>
|
||||
<div class="dropdown-menu to-top dropdown-menu-sm">
|
||||
<div class="py-12 px-16 radius-8 bg-primary-50 mb-16 d-flex align-items-center justify-content-between gap-2">
|
||||
<div
|
||||
class="py-12 px-16 radius-8 bg-primary-50 mb-16 d-flex align-items-center justify-content-between gap-2">
|
||||
<div>
|
||||
<h6 class="text-lg text-primary-light fw-semibold mb-2">{{ auth()->user()->name ?? 'User' }}</h6>
|
||||
<span class="text-secondary-light fw-medium text-sm">{{ optional(auth()->user())->getRoleNames()->implode(', ') ?? '-' }}</span>
|
||||
<h6 class="text-lg text-primary-light fw-semibold mb-2">
|
||||
{{ auth()->user()->name ?? 'User' }}</h6>
|
||||
<span
|
||||
class="text-secondary-light fw-medium text-sm">{{ optional(auth()->user())->getRoleNames()->implode(', ') ?? '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="to-top-list">
|
||||
<li>
|
||||
<a class="dropdown-item text-black px-0 py-8 hover-bg-transparent hover-text-primary d-flex align-items-center gap-3" href="{{ route('profile.index') }}">
|
||||
<iconify-icon icon="solar:user-linear" class="icon text-xl"></iconify-icon> My Profile
|
||||
<a class="dropdown-item text-black px-0 py-8 hover-bg-transparent hover-text-primary d-flex align-items-center gap-3"
|
||||
href="{{ route('profile.index') }}">
|
||||
<iconify-icon icon="solar:user-linear" class="icon text-xl"></iconify-icon> Profil
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a id="btn-logout" class="dropdown-item text-black px-0 py-8 hover-bg-transparent hover-text-danger d-flex align-items-center gap-3" href="#">
|
||||
<a id="btn-logout"
|
||||
class="dropdown-item text-black px-0 py-8 hover-bg-transparent hover-text-danger d-flex align-items-center gap-3"
|
||||
href="#">
|
||||
<iconify-icon icon="lucide:power" class="icon text-xl"></iconify-icon> Log Out
|
||||
</a>
|
||||
</li>
|
||||
|
@ -251,10 +260,15 @@
|
|||
if (token) {
|
||||
await fetch('{{ url('/api/auth/logout') }}', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': 'Bearer ' + token, 'Accept': 'application/json' }
|
||||
headers: {
|
||||
'Authorization': 'Bearer ' + token,
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
} catch (err) { /* ignore */ }
|
||||
} catch (err) {
|
||||
/* ignore */
|
||||
}
|
||||
|
||||
localStorage.removeItem('auth_token');
|
||||
localStorage.removeItem('auth_user');
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
@extends('layout.layout')
|
||||
@php
|
||||
$title='View Profile';
|
||||
$subTitle = 'View Profile';
|
||||
$script ='<script>
|
||||
// ======================== Upload Image Start =====================
|
||||
$title = 'Profil Pengguna';
|
||||
$subTitle = 'Kelola Profil Anda';
|
||||
@endphp
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
// Upload Image functionality
|
||||
function readURL(input) {
|
||||
if (input.files && input.files[0]) {
|
||||
var reader = new FileReader();
|
||||
|
@ -15,122 +18,259 @@
|
|||
reader.readAsDataURL(input.files[0]);
|
||||
}
|
||||
}
|
||||
$("#imageUpload").change(function() {
|
||||
readURL(this);
|
||||
});
|
||||
// ======================== Upload Image End =====================
|
||||
|
||||
// ================== Password Show Hide Js Start ==========
|
||||
function initializePasswordToggle(toggleSelector) {
|
||||
$(toggleSelector).on("click", function() {
|
||||
$(this).toggleClass("ri-eye-off-line");
|
||||
var input = $($(this).attr("data-toggle"));
|
||||
if (input.attr("type") === "password") {
|
||||
input.attr("type", "text");
|
||||
} else {
|
||||
input.attr("type", "password");
|
||||
function uploadProfilePhoto(file) {
|
||||
// Double check if already uploading
|
||||
if (isUploading) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('profile_photo', file);
|
||||
formData.append('_token', '{{ csrf_token() }}');
|
||||
|
||||
// Show loading
|
||||
const uploadLabel = $('label[for="imageUpload"]');
|
||||
const originalContent = uploadLabel.html();
|
||||
uploadLabel.html('<div class="spinner-border spinner-border-sm" role="status"></div>');
|
||||
|
||||
$.ajax({
|
||||
url: '{{ route('profile.update-photo') }}',
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
// Update image preview
|
||||
$("#imagePreview").css("background-image", "url(" + response.photo_url + ")");
|
||||
|
||||
// Show success message (only one)
|
||||
showNotification('success', response.message);
|
||||
|
||||
// Clear file input to prevent duplicate uploads
|
||||
$("#imageUpload").val('');
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
let errorMessage = 'Terjadi kesalahan saat mengupload foto.';
|
||||
if (xhr.responseJSON && xhr.responseJSON.errors) {
|
||||
const errors = xhr.responseJSON.errors;
|
||||
if (errors.profile_photo) {
|
||||
errorMessage = errors.profile_photo[0];
|
||||
}
|
||||
}
|
||||
showNotification('error', errorMessage);
|
||||
|
||||
// Clear file input on error
|
||||
$("#imageUpload").val('');
|
||||
},
|
||||
complete: function() {
|
||||
// Restore button
|
||||
uploadLabel.html(originalContent);
|
||||
|
||||
// Reset uploading flag
|
||||
isUploading = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
// Call the function
|
||||
initializePasswordToggle(".toggle-password");
|
||||
// ========================= Password Show Hide Js End ===========================
|
||||
</script>';
|
||||
@endphp
|
||||
|
||||
function showNotification(type, message) {
|
||||
// Remove ALL existing alerts to prevent duplicates
|
||||
$('.alert').remove();
|
||||
|
||||
const alertClass = type === 'success' ? 'alert-success' : 'alert-danger';
|
||||
const iconClass = type === 'success' ? 'material-symbols:check-circle' : 'material-symbols:error';
|
||||
|
||||
const notification = `
|
||||
<div class="alert ${alertClass} alert-dismissible fade show" role="alert">
|
||||
<iconify-icon icon="${iconClass}" class="me-2"></iconify-icon>
|
||||
${message}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Add notification to the top of the profile settings card
|
||||
$('.col-lg-8 .card-body').prepend(notification);
|
||||
|
||||
// Auto dismiss after 5 seconds
|
||||
setTimeout(function() {
|
||||
$('.alert').fadeOut(function() {
|
||||
$(this).remove();
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
let isUploading = false;
|
||||
|
||||
$(document).ready(function() {
|
||||
$("#imageUpload").change(function() {
|
||||
const file = this.files[0];
|
||||
|
||||
// Prevent multiple uploads
|
||||
if (isUploading) {
|
||||
showNotification('error', 'Upload sedang berlangsung, harap tunggu...');
|
||||
$(this).val(''); // Clear input
|
||||
return;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
// Validate file size (2MB)
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
showNotification('error', 'Ukuran file maksimal 2MB.');
|
||||
$(this).val(''); // Clear input
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate file type
|
||||
const allowedTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'];
|
||||
if (!allowedTypes.includes(file.type)) {
|
||||
showNotification('error', 'Format file harus jpeg, png, jpg, atau gif.');
|
||||
$(this).val(''); // Clear input
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear any existing alerts before starting upload
|
||||
$('.alert').remove();
|
||||
|
||||
// Set uploading flag
|
||||
isUploading = true;
|
||||
|
||||
// Preview image
|
||||
readURL(this);
|
||||
|
||||
// Upload image
|
||||
uploadProfilePhoto(file);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@section('content')
|
||||
<!-- Alert box at the top -->
|
||||
<div class="alert alert-warning radius-8 mb-24">
|
||||
<div class="d-flex align-items-start">
|
||||
<i class="ri-information-line me-2 mt-1"></i>
|
||||
<div>
|
||||
<ul class="mb-0">
|
||||
<li class="mb-8">Sinkronisasi akun hanya dapat dilakukan jika NIB anda sudah terdaftar di OSS-RBA, jika NIB yang anda daftarkan di Akun Arndalnet terdapat kesalahan, silahkan hubungi helpdesk Arndalnet (+62 851-8666-0568).</li>
|
||||
<li class="mb-8">Jika Anda ingin mengubah email untuk kebutuhan mengganti email akun anda yang sekarang menjadi email baru, silahkan anda mengubahnya dibawah lalu klik ubah.</li>
|
||||
<li>Jika Anda adalah Pelaku Usaha mandiri dengan kondisi belum melakukan integrasi akun dengan OSS-RBA. Silahkan anda klik tombol "Sinkronisasi ke Akun Pelaku Usaha OSS-RBA" untuk menyamakan email saat ini dengan email yang terdaftar di OSS-RBA (pastikan NIB sudah sama dengan yang terdaftar di OSS-RBA).</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" class="btn-close ms-auto" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row gy-4">
|
||||
<div class="col-lg-4">
|
||||
<div class="user-grid-card position-relative border radius-16 overflow-hidden bg-base h-100">
|
||||
<img src="{{ asset('assets/images/user-grid/user-grid-bg1.png') }}" alt="" class="w-100 object-fit-cover">
|
||||
<div class="pb-24 ms-16 mb-24 me-16 mt--100">
|
||||
<div class="text-center border border-top-0 border-start-0 border-end-0">
|
||||
<img src="{{ asset('assets/images/user-grid/user-grid-img14.png') }}" alt="" class="border br-white border-width-2-px w-200-px h-200-px rounded-circle object-fit-cover">
|
||||
<h6 class="mb-0 mt-16">Helmy Zulhidayat</h6>
|
||||
<span class="text-secondary-light mb-16">amdal.jakarta@gmail.com</span>
|
||||
</div>
|
||||
<div class="mt-24">
|
||||
<h6 class="text-xl mb-16">Personal Info</h6>
|
||||
<ul>
|
||||
<li class="d-flex align-items-center gap-1 mb-12">
|
||||
<span class="w-30 text-md fw-semibold text-primary-light">Full Name</span>
|
||||
<span class="w-70 text-secondary-light fw-medium">: Helmy Zulhidayat</span>
|
||||
</li>
|
||||
<li class="d-flex align-items-center gap-1 mb-12">
|
||||
<span class="w-30 text-md fw-semibold text-primary-light"> Email</span>
|
||||
<span class="w-70 text-secondary-light fw-medium">: amdal.jakarta@gmail.com</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-8">
|
||||
<div class="card h-100">
|
||||
<div class="card-body p-24">
|
||||
<h5 class="text-primary-light border-bottom pb-2 mb-4">Akun</h5>
|
||||
|
||||
<div class="tab-content" id="pills-tabContent">
|
||||
<div class="tab-pane fade show active" id="pills-edit-profile" role="tabpanel" aria-labelledby="pills-edit-profile-tab" tabindex="0">
|
||||
<h6 class="text-md text-primary-light mb-16">Profile Image</h6>
|
||||
<!-- Upload Image Start -->
|
||||
<div class="mb-24 mt-16">
|
||||
<div class="avatar-upload">
|
||||
<div class="avatar-edit position-absolute bottom-0 end-0 me-24 mt-16 z-1 cursor-pointer">
|
||||
<input type='file' id="imageUpload" accept=".png, .jpg, .jpeg" hidden>
|
||||
<label for="imageUpload" class="w-32-px h-32-px d-flex justify-content-center align-items-center bg-primary-50 text-primary-600 border border-primary-600 bg-hover-primary-100 text-lg rounded-circle">
|
||||
<div class="card-body text-center">
|
||||
<!-- Profile Image -->
|
||||
<div class="mb-3">
|
||||
<div class="avatar-upload d-inline-block position-relative">
|
||||
<div class="avatar-edit position-absolute bottom-0 end-0 z-1 cursor-pointer">
|
||||
<input type='file' id="imageUpload" accept=".png,.jpg,.jpeg,.gif" hidden>
|
||||
<label for="imageUpload"
|
||||
class="w-32-px h-32-px d-flex justify-content-center align-items-center bg-primary-50 text-primary-600 border border-primary-600 bg-hover-primary-100 text-lg rounded-circle">
|
||||
<iconify-icon icon="solar:camera-outline" class="icon"></iconify-icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="avatar-preview">
|
||||
<div id="imagePreview">
|
||||
@php
|
||||
$defaultPhoto = asset('assets/images/user-grid/user-grid-img14.png');
|
||||
$userPhoto = auth()->user()->profile_photo
|
||||
? asset('storage/profile_photos/' . auth()->user()->profile_photo)
|
||||
: $defaultPhoto;
|
||||
@endphp
|
||||
<div id="imagePreview"
|
||||
style="border-radius: 50%; background-image: url('{{ $userPhoto }}'); background-size: cover; background-position: center; border: 3px solid #fff; box-shadow: 0 2px 10px rgba(0,0,0,0.1);">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Upload Image End -->
|
||||
<form action="#">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-20">
|
||||
<label for="name" class="form-label fw-semibold text-primary-light text-sm mb-8">Full Name <span class="text-danger-600">*</span></label>
|
||||
<input type="text" class="form-control radius-8" id="name" value="Helmy Zulhidayat" readonly>
|
||||
|
||||
<!-- User Info -->
|
||||
<h5 class="mb-1">{{ auth()->user()->name ?? 'User' }}</h5>
|
||||
<p class="text-muted mb-3">{{ auth()->user()->email ?? 'email@example.com' }}</p>
|
||||
|
||||
<!-- User Role -->
|
||||
@if (auth()->user()->roles->count() > 0)
|
||||
<div class="mb-3">
|
||||
@foreach (auth()->user()->roles as $role)
|
||||
<span class="badge bg-primary me-1">{{ $role->name }}</span>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="mb-20">
|
||||
<label for="email" class="form-label fw-semibold text-primary-light text-sm mb-8">Email <span class="text-danger-600">*</span></label>
|
||||
<input type="email" class="form-control radius-8" id="email" value="amdal.jakarta@gmail.com" readonly>
|
||||
@endif
|
||||
|
||||
<!-- Account Info -->
|
||||
<div class="text-start">
|
||||
<h6 class="text-primary mb-3">Informasi Akun</h6>
|
||||
<div class="small text-muted">
|
||||
<div class="d-flex justify-content-between mb-2">
|
||||
<span>Bergabung:</span>
|
||||
<span>{{ auth()->user()->created_at->format('d/m/Y') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<button type="button" class="btn btn-success px-4 py-2 radius-8">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-lg-8">
|
||||
<div class="card h-100">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title mb-4">Pengaturan Profil</h5>
|
||||
|
||||
<!-- Profile Actions -->
|
||||
<div class="row g-3">
|
||||
<div class="col-md-4">
|
||||
<div class="card border-0 bg-light h-100">
|
||||
<div
|
||||
class="card-body d-flex flex-column justify-content-center align-items-center text-center">
|
||||
<iconify-icon icon="solar:pen-linear" class="text-success fs-1 mb-3"></iconify-icon>
|
||||
<h6>Edit Profil</h6>
|
||||
<p class="text-muted small">Ubah nama dan username</p>
|
||||
<a href="{{ route('profile.edit') }}"
|
||||
class="d-flex justify-content-center align-items-center btn btn-success btn-sm">
|
||||
<iconify-icon icon="solar:pen-linear" class="me-1"></iconify-icon>
|
||||
Edit
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card border-0 bg-light h-100">
|
||||
<div
|
||||
class="card-body d-flex flex-column justify-content-center align-items-center text-center">
|
||||
<iconify-icon icon="solar:lock-password-linear"
|
||||
class="text-warning fs-1 mb-3"></iconify-icon>
|
||||
<h6>Ubah Password</h6>
|
||||
<p class="text-muted small">Ganti password akun</p>
|
||||
<a href="{{ route('profile.change-password') }}"
|
||||
class="d-flex justify-content-center align-items-center btn btn-warning btn-sm">
|
||||
<iconify-icon icon="solar:lock-password-linear" class="me-1"></iconify-icon>
|
||||
Ubah
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning px-4 py-2 radius-8">
|
||||
Ubah Password
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning px-4 py-2 radius-8">
|
||||
Ubah Email
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card border-0 bg-light h-100">
|
||||
<div
|
||||
class="card-body d-flex flex-column justify-content-center align-items-center text-center">
|
||||
<iconify-icon icon="solar:letter-linear" class="text-info fs-1 mb-3"></iconify-icon>
|
||||
<h6>Ubah Email</h6>
|
||||
<p class="text-muted small">Ganti alamat email</p>
|
||||
<a href="{{ route('profile.change-email') }}"
|
||||
class="d-flex justify-content-center align-items-center btn btn-info btn-sm">
|
||||
<iconify-icon icon="solar:letter-linear" class="me-1"></iconify-icon>
|
||||
Ubah
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quick Info -->
|
||||
<div class="mt-4">
|
||||
<div class="alert alert-info">
|
||||
<iconify-icon icon="material-symbols:info" class="me-2"></iconify-icon>
|
||||
<strong>Tips Keamanan:</strong>
|
||||
<ul class="mb-0 mt-2">
|
||||
<li>Gunakan password yang kuat dengan kombinasi huruf, angka, dan simbol</li>
|
||||
<li>Perbarui informasi profil secara berkala</li>
|
||||
<li>Jaga kerahasiaan informasi login Anda</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,203 @@
|
|||
@extends('layout.layout')
|
||||
|
||||
@php
|
||||
$title = 'Ubah Email';
|
||||
$subTitle = 'Profil Pengguna';
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card basic-data-table">
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-3 gap-3">
|
||||
<div>
|
||||
<h5 class="mb-0">Ubah Email</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-secondary btn-sm d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="iconoir:arrow-left"></iconify-icon>
|
||||
<span>Kembali</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('profile.update-email') }}" id="emailChangeForm">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Email Saat Ini</label>
|
||||
<input type="email" class="form-control" value="{{ Auth::user()->email }}" readonly>
|
||||
</div>
|
||||
|
||||
<div class="col-12"></div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Email Baru <span class="text-danger">*</span></label>
|
||||
<input type="email" name="email" class="form-control" required value="{{ old('email') }}"
|
||||
placeholder="Masukkan email baru">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Password Saat Ini <span class="text-danger">*</span></label>
|
||||
<div class="position-relative">
|
||||
<input type="password" name="current_password" id="current_password_email"
|
||||
class="form-control pe-5" required placeholder="Masukkan password untuk konfirmasi">
|
||||
<button type="button"
|
||||
class="btn btn-link position-absolute end-0 top-50 translate-middle-y pe-3 text-secondary toggle-password"
|
||||
data-target="#current_password_email">
|
||||
<iconify-icon icon="solar:eye-linear" class="eye-open"></iconify-icon>
|
||||
<iconify-icon icon="solar:eye-closed-linear" class="eye-closed d-none"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-text">Password diperlukan untuk konfirmasi keamanan.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex gap-2">
|
||||
<button class="btn btn-primary d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="material-symbols:save"></iconify-icon>
|
||||
<span>Ubah Email</span>
|
||||
</button>
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-light">Batal</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Confirmation Modal -->
|
||||
<div class="modal fade" id="confirmEmailChangeModal" tabindex="-1" aria-labelledby="confirmEmailChangeModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header border-0 pb-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<div
|
||||
class="w-48-px h-48-px bg-info-subtle rounded-circle d-flex align-items-center justify-content-center">
|
||||
<iconify-icon icon="material-symbols:mail" class="text-info fs-3"></iconify-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="modal-title mb-1" id="confirmEmailChangeModalLabel">Konfirmasi Ubah Email</h5>
|
||||
<p class="text-muted mb-0 small">Pastikan email baru sudah benar</p>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body pt-2">
|
||||
<div class="alert alert-info border-0 bg-info-subtle">
|
||||
<div class="d-flex">
|
||||
<iconify-icon icon="material-symbols:info" class="text-info me-2 mt-1"></iconify-icon>
|
||||
<div>
|
||||
<strong>Informasi:</strong>
|
||||
<ul class="mb-0 mt-2">
|
||||
<li>Email akan <strong>langsung diubah</strong> setelah konfirmasi</li>
|
||||
<li>Pastikan <strong>email baru sudah benar</strong> dan dapat diakses</li>
|
||||
<li>Gunakan email ini untuk <strong>login selanjutnya</strong></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-light p-3 rounded">
|
||||
<div class="row">
|
||||
<div class="col-12 mb-2">
|
||||
<small class="text-muted">Email saat ini:</small>
|
||||
<div class="fw-medium">{{ Auth::user()->email }}</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<small class="text-muted">Email baru:</small>
|
||||
<div class="fw-medium text-primary" id="newEmailPreview">-</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer border-0 pt-0">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal">
|
||||
<iconify-icon icon="material-symbols:close" class="me-1"></iconify-icon>
|
||||
Batal
|
||||
</button>
|
||||
<button type="button" class="btn btn-info" id="confirmEmailChange">
|
||||
<iconify-icon icon="material-symbols:mail" class="me-1"></iconify-icon>
|
||||
Ya, Ubah Email
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Password toggle functionality
|
||||
$('.toggle-password').on('click', function() {
|
||||
const target = $(this).data('target');
|
||||
const input = $(target);
|
||||
const eyeOpen = $(this).find('.eye-open');
|
||||
const eyeClosed = $(this).find('.eye-closed');
|
||||
|
||||
if (input.attr('type') === 'password') {
|
||||
input.attr('type', 'text');
|
||||
eyeOpen.addClass('d-none');
|
||||
eyeClosed.removeClass('d-none');
|
||||
} else {
|
||||
input.attr('type', 'password');
|
||||
eyeOpen.removeClass('d-none');
|
||||
eyeClosed.addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// Custom modal confirmation before email change
|
||||
$('#emailChangeForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Get new email value and show in modal
|
||||
const newEmail = $('input[name="email"]').val();
|
||||
if (newEmail) {
|
||||
$('#newEmailPreview').text(newEmail);
|
||||
$('#confirmEmailChangeModal').modal('show');
|
||||
} else {
|
||||
// If no email entered, show validation
|
||||
$('input[name="email"]').focus();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle modal confirmation
|
||||
$('#confirmEmailChange').on('click', function() {
|
||||
// Hide modal
|
||||
$('#confirmEmailChangeModal').modal('hide');
|
||||
|
||||
// Add loading state to button
|
||||
const btn = $(this);
|
||||
const originalText = btn.html();
|
||||
btn.html(
|
||||
'<span class="spinner-border spinner-border-sm me-2" role="status"></span>Mengubah Email...'
|
||||
);
|
||||
btn.prop('disabled', true);
|
||||
|
||||
// Submit form after modal closes
|
||||
setTimeout(function() {
|
||||
$('#emailChangeForm')[0].submit();
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
|
@ -0,0 +1,214 @@
|
|||
@extends('layout.layout')
|
||||
|
||||
@php
|
||||
$title = 'Ubah Password';
|
||||
$subTitle = 'Profil Pengguna';
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card basic-data-table">
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-3 gap-3">
|
||||
<div>
|
||||
<h5 class="mb-0">Ubah Password</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-secondary btn-sm d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="iconoir:arrow-left"></iconify-icon>
|
||||
<span>Kembali</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('profile.update-password') }}" id="passwordChangeForm">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<div class="alert alert-warning d-flex align-items-center">
|
||||
<iconify-icon icon="material-symbols:warning" class="me-2"></iconify-icon>
|
||||
<div>
|
||||
<strong>Peringatan Keamanan:</strong> Setelah mengubah password, Anda akan otomatis logout
|
||||
dan diarahkan ke halaman login. Pastikan Anda mengingat password baru sebelum melanjutkan.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Password Saat Ini <span class="text-danger">*</span></label>
|
||||
<div class="position-relative">
|
||||
<input type="password" name="current_password" id="current_password" class="form-control pe-5"
|
||||
required placeholder="Masukkan password saat ini">
|
||||
<button type="button"
|
||||
class="btn btn-link position-absolute end-0 top-50 translate-middle-y pe-3 text-secondary toggle-password"
|
||||
data-target="#current_password">
|
||||
<iconify-icon icon="solar:eye-linear" class="eye-open"></iconify-icon>
|
||||
<iconify-icon icon="solar:eye-closed-linear" class="eye-closed d-none"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12"></div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Password Baru <span class="text-danger">*</span></label>
|
||||
<div class="position-relative">
|
||||
<input type="password" name="password" id="new_password" class="form-control pe-5" required
|
||||
placeholder="Masukkan password baru">
|
||||
<button type="button"
|
||||
class="btn btn-link position-absolute end-0 top-50 translate-middle-y pe-3 text-secondary toggle-password"
|
||||
data-target="#new_password">
|
||||
<iconify-icon icon="solar:eye-linear" class="eye-open"></iconify-icon>
|
||||
<iconify-icon icon="solar:eye-closed-linear" class="eye-closed d-none"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
<div class="form-text">Password harus minimal 8 karakter, mengandung huruf besar, huruf
|
||||
kecil,
|
||||
angka, dan simbol khusus.</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Konfirmasi Password Baru <span class="text-danger">*</span></label>
|
||||
<div class="position-relative">
|
||||
<input type="password" name="password_confirmation" id="confirm_password"
|
||||
class="form-control pe-5" required placeholder="Konfirmasi password baru">
|
||||
<button type="button"
|
||||
class="btn btn-link position-absolute end-0 top-50 translate-middle-y pe-3 text-secondary toggle-password"
|
||||
data-target="#confirm_password">
|
||||
<iconify-icon icon="solar:eye-linear" class="eye-open"></iconify-icon>
|
||||
<iconify-icon icon="solar:eye-closed-linear" class="eye-closed d-none"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary d-flex align-items-center gap-2" id="changePasswordBtn">
|
||||
<iconify-icon icon="material-symbols:save"></iconify-icon>
|
||||
<span>Ubah Password</span>
|
||||
</button>
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-light">Batal</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Custom Confirmation Modal -->
|
||||
<div class="modal fade" id="confirmPasswordChangeModal" tabindex="-1" aria-labelledby="confirmPasswordChangeModalLabel"
|
||||
aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header border-0 pb-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<div class="me-3">
|
||||
<div
|
||||
class="w-48-px h-48-px bg-warning-subtle rounded-circle d-flex align-items-center justify-content-center">
|
||||
<iconify-icon icon="material-symbols:warning" class="text-warning fs-3"></iconify-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h5 class="modal-title mb-1" id="confirmPasswordChangeModalLabel">Konfirmasi Ubah Password</h5>
|
||||
<p class="text-muted mb-0 small">Pastikan Anda yakin dengan keputusan ini</p>
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body pt-2">
|
||||
<div class="alert alert-warning border-0 bg-warning-subtle">
|
||||
<div class="d-flex">
|
||||
<iconify-icon icon="material-symbols:info" class="text-warning me-2 mt-1"></iconify-icon>
|
||||
<div>
|
||||
<strong>Perhatian:</strong>
|
||||
<ul class="mb-0 mt-2">
|
||||
<li>Anda akan <strong>otomatis logout</strong> dari semua perangkat</li>
|
||||
<li>Perlu <strong>login ulang</strong> dengan password baru</li>
|
||||
<li>Pastikan Anda <strong>mengingat password baru</strong> sebelum melanjutkan</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mb-0">Apakah Anda yakin ingin mengubah password sekarang?</p>
|
||||
</div>
|
||||
<div class="modal-footer border-0 pt-0 d-flex align-items-center justify-content-center">
|
||||
<button type="button" class="btn btn-light d-flex align-items-center" data-bs-dismiss="modal">
|
||||
<iconify-icon icon="material-symbols:close" class="me-1"></iconify-icon>
|
||||
Batal
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning d-flex align-items-center" id="confirmPasswordChange">
|
||||
<iconify-icon icon="material-symbols:lock-reset" class="me-1"></iconify-icon>
|
||||
Ya, Ubah Password
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
// Password toggle functionality
|
||||
$('.toggle-password').on('click', function() {
|
||||
const target = $(this).data('target');
|
||||
const input = $(target);
|
||||
const eyeOpen = $(this).find('.eye-open');
|
||||
const eyeClosed = $(this).find('.eye-closed');
|
||||
|
||||
if (input.attr('type') === 'password') {
|
||||
input.attr('type', 'text');
|
||||
eyeOpen.addClass('d-none');
|
||||
eyeClosed.removeClass('d-none');
|
||||
} else {
|
||||
input.attr('type', 'password');
|
||||
eyeOpen.removeClass('d-none');
|
||||
eyeClosed.addClass('d-none');
|
||||
}
|
||||
});
|
||||
|
||||
// Custom modal confirmation before password change
|
||||
$('#passwordChangeForm').on('submit', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// Show custom modal instead of alert
|
||||
$('#confirmPasswordChangeModal').modal('show');
|
||||
});
|
||||
|
||||
// Handle modal confirmation
|
||||
$('#confirmPasswordChange').on('click', function() {
|
||||
// Hide modal
|
||||
$('#confirmPasswordChangeModal').modal('hide');
|
||||
|
||||
// Add loading state to button
|
||||
const btn = $(this);
|
||||
const originalText = btn.html();
|
||||
btn.html(
|
||||
'<span class="spinner-border spinner-border-sm me-2" role="status"></span>Mengubah Password...'
|
||||
);
|
||||
btn.prop('disabled', true);
|
||||
|
||||
// Submit form after modal closes
|
||||
setTimeout(function() {
|
||||
$('#passwordChangeForm')[0].submit();
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
|
@ -0,0 +1,106 @@
|
|||
@extends('layout.layout')
|
||||
|
||||
@php
|
||||
$title = 'Edit Profil';
|
||||
$subTitle = 'Profil Pengguna';
|
||||
@endphp
|
||||
|
||||
@section('content')
|
||||
|
||||
<div class="card basic-data-table">
|
||||
<div class="card-body">
|
||||
<div
|
||||
class="d-flex flex-column flex-md-row justify-content-between align-items-start align-items-md-center mb-3 gap-3">
|
||||
<div>
|
||||
<h5 class="mb-0">Edit Profil</h5>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-secondary btn-sm d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="iconoir:arrow-left"></iconify-icon>
|
||||
<span>Kembali</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (session('success'))
|
||||
<div class="alert alert-success">{{ session('success') }}</div>
|
||||
@endif
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('profile.update') }}">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Nama Lengkap <span class="text-danger">*</span></label>
|
||||
<input type="text" name="name" class="form-control" required
|
||||
value="{{ old('name', $user->name) }}" placeholder="Masukkan nama lengkap">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Username <span class="text-danger">*</span></label>
|
||||
<input type="text" name="username" class="form-control" required
|
||||
value="{{ old('username', $user->username) }}" placeholder="Masukkan username">
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Email</label>
|
||||
<input type="email" class="form-control" value="{{ $user->email }}" readonly>
|
||||
<div class="form-text">
|
||||
<a href="{{ route('profile.change-email') }}" class="text-primary">Klik di sini untuk mengubah
|
||||
email</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label">Password</label>
|
||||
<input type="password" class="form-control" value="••••••••" readonly>
|
||||
<div class="form-text">
|
||||
<a href="{{ route('profile.change-password') }}" class="text-primary">Klik di sini untuk
|
||||
mengubah password</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User Info -->
|
||||
<div class="mt-4">
|
||||
<div class="alert alert-light">
|
||||
<h6>Informasi Akun:</h6>
|
||||
<ul class="mb-0">
|
||||
<li>Bergabung: {{ $user->created_at->format('d/m/Y H:i:s') }}</li>
|
||||
<li>Terakhir diperbarui: {{ $user->updated_at->format('d/m/Y H:i:s') }}</li>
|
||||
<li>Role:
|
||||
@if ($user->roles->count() > 0)
|
||||
@foreach ($user->roles as $role)
|
||||
<span class="badge bg-primary me-1">{{ $role->name }}</span>
|
||||
@endforeach
|
||||
@else
|
||||
<span class="badge bg-secondary">Tidak ada role</span>
|
||||
@endif
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4 d-flex gap-2">
|
||||
<button class="btn btn-primary d-flex align-items-center gap-2">
|
||||
<iconify-icon icon="material-symbols:save"></iconify-icon>
|
||||
<span>Simpan Perubahan</span>
|
||||
</button>
|
||||
<a href="{{ route('profile.index') }}" class="btn btn-light">Batal</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endsection
|
|
@ -153,9 +153,16 @@ Route::prefix('admin')->middleware(['web.auth'])->group(function () {
|
|||
Route::get('/penugasan', [PenugasanController::class, 'index'])->name('penugasan.index');
|
||||
});
|
||||
|
||||
// Profile
|
||||
Route::prefix('admin')->middleware(['web.auth'])->group(function () {
|
||||
Route::get('/profile', [ProfileController::class, 'index'])->name('profile.index');
|
||||
// Profile Management
|
||||
Route::prefix('admin/profile')->middleware(['web.auth'])->group(function () {
|
||||
Route::get('/', [ProfileController::class, 'index'])->name('profile.index');
|
||||
Route::get('/edit', [ProfileController::class, 'edit'])->name('profile.edit');
|
||||
Route::put('/update', [ProfileController::class, 'update'])->name('profile.update');
|
||||
Route::get('/change-password', [ProfileController::class, 'changePasswordForm'])->name('profile.change-password');
|
||||
Route::put('/change-password', [ProfileController::class, 'updatePassword'])->name('profile.update-password');
|
||||
Route::get('/change-email', [ProfileController::class, 'changeEmailForm'])->name('profile.change-email');
|
||||
Route::put('/change-email', [ProfileController::class, 'updateEmail'])->name('profile.update-email');
|
||||
Route::post('/update-photo', [ProfileController::class, 'updatePhoto'])->name('profile.update-photo');
|
||||
});
|
||||
|
||||
// News Management
|
||||
|
|
Loading…
Reference in New Issue