Update User

This commit is contained in:
2026-04-21 10:10:09 +07:00
parent 5af0924cdf
commit 224d8754c8
6 changed files with 644 additions and 38 deletions
@@ -5,6 +5,9 @@ namespace App\Http\Controllers\Web\Konfigurasi;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Models\User; use App\Models\User;
use App\Models\Profile;
use App\Enums\Role;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash; use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
@@ -14,47 +17,112 @@ class UserController extends Controller
{ {
$query = User::orderBy('created_at', 'desc'); $query = User::orderBy('created_at', 'desc');
if ($request->search) { $tab = $request->get('tab', 'active');
$query->where('name', 'like', '%' . $request->search . '%') if ($tab === 'pending') {
->orWhere('email', 'like', '%' . $request->search . '%'); $query->whereNull('email_verified_at');
} else {
$query->whereNotNull('email_verified_at');
}
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
$q->where('name', 'like', '%' . $search . '%')
->orWhere('email', 'like', '%' . $search . '%');
});
}
if ($request->filled('role')) {
$query->where('role', $request->role);
} }
$users = $query->paginate($request->per_page ?? 10); $users = $query->paginate($request->per_page ?? 10);
return view('master.users.index', compact('users')); $totalUsers = User::count();
$activeUsers = User::whereNotNull('email_verified_at')->count();
$pendingUsers = User::whereNull('email_verified_at')->count();
$roles = Role::cases();
return view('konfigurasi.user.index', compact('users', 'totalUsers', 'activeUsers', 'pendingUsers', 'roles', 'tab'));
}
public function verify($id)
{
try {
$user = User::findOrFail($id);
$user->email_verified_at = now();
$user->save();
return response()->json([
'status' => 'success',
'message' => 'User berhasil diverifikasi dan diaktifkan.'
]);
} catch (\Exception $e) {
return response()->json([
'status' => 'error',
'message' => 'Gagal verifikasi user.'
], 500);
}
} }
public function store(Request $request) public function store(Request $request)
{ {
$validator = Validator::make($request->all(), [ $validator = Validator::make($request->all(), [
'name' => 'required|string|max:255', 'name' => ['required', 'string', 'max:255'],
'email' => 'required|email|unique:users,email|max:255', 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => 'required|min:6', 'password' => ['required', 'string', 'min:8', 'confirmed'],
'role' => 'required|string|max:255', 'role' => ['required', 'string'],
], [
'password.confirmed' => 'Konfirmasi password tidak cocok!',
'password.min' => 'Password minimal 8 karakter!',
'email.unique' => 'Email sudah terdaftar.',
'required' => 'Kolom :attribute wajib diisi.'
]); ]);
if ($validator->fails()) { if ($validator->fails()) {
return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422); return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);
} }
User::create([ try {
'name' => $request->name, DB::transaction(function () use ($request) {
'email' => $request->email,
'password' => Hash::make($request->password), // Enkripsi password
'role' => $request->role,
]);
return response()->json(['status' => 'success', 'message' => 'User berhasil ditambahkan']); $user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
'role' => $request->role,
'created_by' => auth()->id(),
]);
Profile::create([
'user_id' => $user->id,
'role' => $request->role,
'nama' => $request->name,
'email' => $request->email,
'created_by' => auth()->id(),
]);
});
return response()->json([
'status' => 'success',
'message' => 'User baru berhasil ditambahkan.'
]);
} catch (\Exception $e) {
return response()->json([
'status' => 'error',
'message' => 'Gagal menyimpan data: ' . $e->getMessage()
], 500);
}
} }
public function show($id) public function show($id)
{ {
try { $user = User::findOrFail($id);
$user = User::findOrFail($id);
return response()->json(['status' => 'success', 'data' => $user]); return response()->json(['status' => 'success', 'data' => $user]);
} catch (\Exception $e) {
return response()->json(['status' => 'error', 'message' => 'User tidak ditemukan'], 404);
}
} }
public function update(Request $request, $id) public function update(Request $request, $id)
@@ -62,9 +130,6 @@ class UserController extends Controller
$user = User::findOrFail($id); $user = User::findOrFail($id);
$validator = Validator::make($request->all(), [ $validator = Validator::make($request->all(), [
'name' => 'required|string|max:255',
'email' => 'required|email|max:255|unique:users,email,' . $id, // Pengecualian email unik untuk ID ini
'role' => 'required|string|max:255',
'password' => 'nullable|min:6', 'password' => 'nullable|min:6',
]); ]);
@@ -72,15 +137,7 @@ class UserController extends Controller
return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422); return response()->json(['status' => 'error', 'errors' => $validator->errors()], 422);
} }
$user->name = $request->name; $user->password = Hash::make($request->password);
$user->email = $request->email;
$user->role = $request->role;
// Update password HANYA JIKA diisi
if ($request->filled('password')) {
$user->password = Hash::make($request->password);
}
$user->save(); $user->save();
return response()->json(['status' => 'success', 'message' => 'User berhasil diupdate']); return response()->json(['status' => 'success', 'message' => 'User berhasil diupdate']);
+2 -1
View File
@@ -5,6 +5,7 @@ namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail; // use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Enums\Role;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasOne; use Illuminate\Database\Eloquent\Relations\HasOne;
@@ -32,7 +33,7 @@ class User extends Authenticatable
return [ return [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
'password' => 'hashed', 'password' => 'hashed',
'role' => \App\Enums\Role::class, 'role' => Role::class,
]; ];
} }
@@ -0,0 +1,52 @@
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasAddUser" aria-labelledby="offcanvasAddUserLabel">
<div class="offcanvas-header border-bottom">
<h5 id="offcanvasAddUserLabel" class="offcanvas-title">Tambah User Baru</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
<form class="add-new-user pt-0" id="formAddUser" action="{{ route('users.store') }}" method="POST">
@csrf
<div class="mb-4">
<label class="form-label" for="add-user-fullname">Nama Lengkap</label>
<input type="text" class="form-control" id="add-user-fullname" placeholder="John Doe" name="name" required />
</div>
<div class="mb-4">
<label class="form-label" for="add-user-email">Email</label>
<input type="email" id="add-user-email" class="form-control" placeholder="john.doe@example.com" name="email" required />
</div>
<div class="mb-4">
<label class="form-label" for="add-user-role">User Role</label>
<select id="add-user-role" class="form-select" name="role" required>
<option value="">Pilih Role</option>
@foreach($roles as $roleEnum)
<option value="{{ $roleEnum->value }}">{{ ucfirst(str_replace('_', ' ', $roleEnum->value)) }}</option>
@endforeach
</select>
</div>
<div class="mb-4 form-password-toggle">
<label class="form-label" for="add-user-password">Password</label>
<div class="input-group input-group-merge">
<input type="password" id="add-user-password" name="password" class="form-control" placeholder="&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;" required />
<span class="input-group-text cursor-pointer" onclick="togglePassword(this)">
<i class="ti tabler-eye-off"></i>
</span>
</div>
</div>
<div class="mb-4 form-password-toggle">
<label class="form-label" for="add-user-password-confirm">Konfirmasi Password</label>
<div class="input-group input-group-merge">
<input type="password" id="add-user-password-confirm" name="password_confirmation" class="form-control" placeholder="&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;" required />
<span class="input-group-text cursor-pointer" onclick="togglePassword(this)">
<i class="ti tabler-eye-off"></i>
</span>
</div>
</div>
<div class="mt-6 d-flex gap-3">
<button type="submit" class="btn btn-primary flex-grow-1 data-submit">Simpan</button>
<button type="reset" class="btn btn-label-secondary flex-grow-1" data-bs-dismiss="offcanvas">Batal</button>
</div>
</form>
</div>
</div>
@@ -0,0 +1,53 @@
<div class="offcanvas offcanvas-end" tabindex="-1" id="offcanvasEdit" aria-labelledby="offcanvasEditLabel">
<div class="offcanvas-header border-bottom">
<h5 id="offcanvasEditLabel" class="offcanvas-title">Ubah Password User</h5>
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<div class="offcanvas-body mx-0 flex-grow-0 p-6 h-100">
<form id="formEdit" method="POST">
@csrf
@method('PUT')
<div class="alert alert-label-info mb-6" role="alert">
<div class="d-flex align-items-center mb-2">
<span class="ti tabler-user ti-xs me-2"></span>
<span class="fw-medium text-heading">Nama:</span>
<span class="ms-auto fw-bold" id="editUserName"></span>
</div>
<hr class="my-2">
<div class="d-flex align-items-center mt-2">
<span class="ti tabler-mail ti-xs me-2"></span>
<span class="fw-medium text-heading">Email:</span>
<span class="ms-auto" id="editEmail"></span>
</div>
</div>
<div class="mb-4 form-password-toggle">
<label class="form-label" for="edit-password">Password Baru</label>
<div class="input-group input-group-merge">
<input type="password" id="edit-password" name="password" class="form-control" placeholder="&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;" required />
<span class="input-group-text cursor-pointer" onclick="togglePassword(this)">
<i class="ti tabler-eye-off"></i>
</span>
</div>
</div>
<div class="mb-6 form-password-toggle">
<label class="form-label" for="edit-password-confirm">Konfirmasi Password Baru</label>
<div class="input-group input-group-merge">
<input type="password" id="edit-password-confirm" name="password_confirmation" class="form-control" placeholder="&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;&#xb7;" required />
<span class="input-group-text cursor-pointer" onclick="togglePassword(this)">
<i class="ti tabler-eye-off"></i>
</span>
</div>
</div>
<div class="d-flex gap-3">
<button type="submit" class="btn btn-primary flex-grow-1">Update Password</button>
<button type="button" class="btn btn-label-secondary flex-grow-1" data-bs-dismiss="offcanvas">Batal</button>
</div>
</form>
</div>
</div>
@@ -0,0 +1,445 @@
@extends('layout.main')
@section('content')
<div class="container-xxl flex-grow-1 container-p-y">
<div class="row g-6 mb-6">
<div class="col-sm-6 col-xl-4">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between">
<div class="content-left">
<span class="text-heading">Total Users</span>
<div class="d-flex align-items-center my-1">
<h4 class="mb-0 me-2">{{ number_format($totalUsers ?? 0) }}</h4>
</div>
<small class="mb-0">All registered accounts</small>
</div>
<div class="avatar">
<span class="avatar-initial rounded bg-label-primary">
<i class="icon-base ti tabler-users icon-26px"></i>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-4">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between">
<div class="content-left">
<span class="text-heading">Active Users</span>
<div class="d-flex align-items-center my-1">
<h4 class="mb-0 me-2">{{ number_format($activeUsers ?? 0) }}</h4>
</div>
<small class="mb-0">Verified Emails</small>
</div>
<div class="avatar">
<span class="avatar-initial rounded bg-label-success">
<i class="icon-base ti tabler-user-check icon-26px"></i>
</span>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-6 col-xl-4">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-start justify-content-between">
<div class="content-left">
<span class="text-heading">Pending Users</span>
<div class="d-flex align-items-center my-1">
<h4 class="mb-0 me-2">{{ number_format($pendingUsers ?? 0) }}</h4>
</div>
<small class="mb-0">Unverified Emails</small>
</div>
<div class="avatar">
<span class="avatar-initial rounded bg-label-warning">
<i class="icon-base ti tabler-user-search icon-26px"></i>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<ul class="nav nav-pills mb-4" role="tablist">
<li class="nav-item">
<a class="nav-link {{ $tab == 'active' ? 'active' : '' }}" href="{{ route('users.index', ['tab' => 'active', 'role' => request('role'), 'search' => request('search')]) }}">
<i class="ti tabler-user-check me-1"></i> Active Users
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ $tab == 'pending' ? 'active' : '' }}" href="{{ route('users.index', ['tab' => 'pending', 'role' => request('role'), 'search' => request('search')]) }}">
<i class="ti tabler-clock me-1"></i> Pending Verifications
@if(($pendingUsers ?? 0) > 0)
<span class="badge rounded-pill badge-center h-px-20 w-px-20 bg-danger ms-1">{{ $pendingUsers }}</span>
@endif
</a>
</li>
</ul>
<div class="card">
<div class="card-header border-bottom d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">Daftar Pengguna</h5>
<button class="btn btn-sm btn-primary" type="button" data-bs-toggle="offcanvas" data-bs-target="#offcanvasAddUser">
<i class="ti tabler-plus me-1"></i> Add New User
</button>
</div>
<form method="GET" action="{{ route('users.index') }}" id="filterForm">
<input type="hidden" name="tab" value="{{ $tab }}">
<div class="card-body border-bottom pt-4">
<div class="row g-3 align-items-center">
<div class="col-md-auto">
<div class="d-flex align-items-center">
<label class="me-2 text-nowrap">Show</label>
<select name="per_page" class="form-select form-select-sm w-auto" onchange="this.form.submit()">
<option value="10" {{ request('per_page') == 10 ? 'selected' : '' }}>10</option>
<option value="25" {{ request('per_page') == 25 ? 'selected' : '' }}>25</option>
<option value="50" {{ request('per_page') == 50 ? 'selected' : '' }}>50</option>
</select>
<label class="ms-2 text-nowrap">entries</label>
</div>
</div>
<div class="col-md-3">
<select name="role" class="form-select form-select-sm" onchange="this.form.submit()">
<option value="">-- All Roles --</option>
@foreach($roles as $roleEnum)
<option value="{{ $roleEnum->value }}" {{ request('role') == $roleEnum->value ? 'selected' : '' }}>
{{ ucfirst(str_replace('_', ' ', $roleEnum->value)) }}
</option>
@endforeach
</select>
</div>
<div class="col-md-auto ms-auto">
<div class="input-group input-group-sm">
<input type="text" name="search" class="form-control" placeholder="Search name or email..." value="{{ request('search') }}">
<button type="submit" class="btn btn-primary"><i class="ti tabler-search"></i></button>
@if(request()->anyFilled(['search', 'role']))
<a href="{{ route('users.index', ['tab' => $tab]) }}" class="btn btn-label-secondary" title="Reset Filters"><i class="ti tabler-refresh"></i></a>
@endif
</div>
</div>
</div>
</div>
</form>
<div class="table-responsive text-nowrap">
<table class="table table-hover">
<thead class="border-top">
<tr>
<th>No</th>
<th>User</th>
<th>Role</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@forelse($users as $index => $user)
<tr>
<td>{{ $users->firstItem() + $index }}</td>
<td>
<div class="d-flex justify-content-start align-items-center user-name">
<div class="avatar-wrapper me-3">
<div class="avatar avatar-sm">
<span class="avatar-initial rounded-circle bg-label-dark">{{ strtoupper(substr($user->name, 0, 2)) }}</span>
</div>
</div>
<div class="d-flex flex-column">
<span class="fw-medium text-heading">{{ $user->name }}</span>
<small class="text-muted">{{ $user->email }}</small>
</div>
</div>
</td>
<td>
@php
$roleKey = ($user->role instanceof \App\Enums\Role) ? $user->role->value : $user->role;
$roleColors = [
'super_admin' => 'bg-label-danger',
'admin' => 'bg-label-warning',
'fasilitator' => 'bg-label-info',
'petani' => 'bg-label-success',
];
$color = $roleColors[$roleKey] ?? 'bg-label-secondary';
@endphp
<span class="badge {{ $color }}">
{{ ucfirst(str_replace('_', ' ', $roleKey)) }}
</span>
</td>
<td>
@if($user->email_verified_at)
<span class="badge bg-label-success">Verified</span>
@else
<span class="badge bg-label-warning">Pending</span>
<form action="{{ route('users.verify', $user->id) }}" method="POST" class="d-inline">
@csrf
@method('PATCH')
<button type="button" class="btn btn-xs btn-outline-success ms-2 btn-verify">Verify</button>
</form>
</form>
@endif
</td>
<td>
<div class="d-flex align-items-center">
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill edit-record" title="Edit" data-id="{{ $user->id }}"><i class="ti tabler-edit ti-md"></i></a>
<a href="javascript:;" class="btn btn-icon btn-text-secondary rounded-pill delete-record" data-id="{{ $user->id }}" data-name="{{ $user->name }}" title="Delete"><i class="ti tabler-trash ti-md"></i></a>
</div>
</td>
</tr>
@empty
<tr><td colspan="5" class="text-center py-4">No users found.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div class="card-footer d-flex justify-content-center justify-content-md-end border-top">
{{ $users->appends(request()->query())->links('pagination::bootstrap-5') }}
</div>
</div>
@include('konfigurasi.user.add')
@include('konfigurasi.user.edit')
</div>
@endsection
@push('scripts')
<script>
'use strict';
const csrfToken = "{{ csrf_token() }}";
$(document).ready(function () {
$(document).on('click', '.btn-verify', function (e) {
e.preventDefault();
const form = $(this).closest('form');
const url = form.attr('action');
const formData = new FormData(form[0]);
Swal.fire({
title: 'Verifikasi User?',
text: "User ini akan diaktifkan dan dapat login ke dalam sistem.",
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Ya, Verifikasi!',
cancelButtonText: 'Batal',
customClass: {
confirmButton: 'btn btn-success me-3',
cancelButton: 'btn btn-label-secondary'
},
buttonsStyling: false
}).then(function (result) {
if (result.value) {
$.ajax({
url: url,
type: 'POST',
data: formData,
processData: false,
contentType: false,
headers: {
'Accept': 'application/json'
},
success: function (res) {
if (res.status === 'success') {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: res.message,
showConfirmButton: false,
timer: 1500
}).then(() => {
window.location.reload();
});
} else {
Swal.fire({ icon: 'error', title: 'Gagal!', text: res.message });
}
},
error: function (xhr) {
let errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Terjadi kesalahan pada server.';
Swal.fire({ icon: 'error', title: 'Error!', text: errorMsg });
}
});
}
});
});
const offcanvasEditEl = document.getElementById('offcanvasEdit');
let bsOffcanvasEdit;
if (offcanvasEditEl) {
bsOffcanvasEdit = new bootstrap.Offcanvas(offcanvasEditEl);
}
$(document).on('click', '.edit-record', function (e) {
e.preventDefault();
const id = $(this).data('id');
const offcanvasEditEl = document.getElementById('offcanvasEdit');
if (!id) return;
$(this).html('<span class="spinner-border spinner-border-sm" role="status"></span>');
const btn = $(this);
$.ajax({
url: `/users/${id}`,
type: 'GET',
success: function (res) {
btn.html('<i class="ti tabler-edit ti-md"></i>');
if (res.status === 'success') {
const user = res.data;
$('#editUserName').text(user.name);
$('#editEmail').text(user.email);
$('#formEdit').attr('action', `/users/${user.id}`);
$('#formEdit')[0].reset();
const bsOffcanvasEdit = bootstrap.Offcanvas.getOrCreateInstance(offcanvasEditEl);
bsOffcanvasEdit.show();
}
},
error: function () {
btn.html('<i class="ti tabler-edit ti-md"></i>');
Swal.fire({ icon: 'error', title: 'Error', text: 'Gagal mengambil data user.' });
}
});
});
$('#formEdit').on('submit', function (e) {
e.preventDefault();
const form = $(this);
const submitBtn = form.find('button[type="submit"]');
submitBtn.prop('disabled', true).text('Menyimpan...');
$.ajax({
url: form.attr('action'),
type: 'POST',
data: form.serialize(),
success: function (res) {
if (res.status === 'success') {
bootstrap.Offcanvas.getInstance(document.getElementById('offcanvasEdit')).hide();
Swal.fire({ icon: 'success', title: 'Berhasil!', text: res.message, showConfirmButton: false, timer: 1500 })
.then(() => window.location.reload());
}
},
error: function (xhr) {
submitBtn.prop('disabled', false).text('Update Password');
let errorMsg = xhr.responseJSON?.message || 'Gagal mengupdate password.';
if (xhr.responseJSON?.errors) {
errorMsg = Object.values(xhr.responseJSON.errors).map(err => err.join(', ')).join('<br>');
}
Swal.fire({ icon: 'error', title: 'Gagal!', html: errorMsg });
}
});
});
$(document).on('click', '.delete-record', function () {
const id = $(this).data('id');
const name = $(this).data('name');
Swal.fire({
title: 'Hapus Pengguna?',
text: `Apakah kamu yakin ingin menghapus ${name}?`,
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Ya, hapus!',
cancelButtonText: 'Batal',
customClass: { confirmButton: 'btn btn-danger me-3', cancelButton: 'btn btn-label-secondary' },
buttonsStyling: false
}).then(function (result) {
if (result.value) {
$.ajax({
url: `/users/${id}`, // Sesuaikan dengan route destroy kamu
type: 'DELETE',
headers: { 'X-CSRF-TOKEN': csrfToken },
success: function (res) {
Swal.fire({ icon: 'success', title: 'Berhasil dihapus!', text: res.message, showConfirmButton: false, timer: 1500 })
.then(() => window.location.reload());
},
error: () => Swal.fire({ icon: 'error', title: 'Error!', text: 'Failed to delete data.' })
});
}
});
});
});
document.addEventListener("DOMContentLoaded", function() {
function togglePassword(element) {
const input = element.parentElement.querySelector('input');
const icon = element.querySelector('i');
if (input.type === 'password') {
input.type = 'text';
icon.className = 'ti ti-eye tabler-eye';
} else {
input.type = 'password';
icon.className = 'ti ti-eye-off tabler-eye-off';
}
}
const formAddUser = document.getElementById('formAddUser');
const offcanvasElement = document.getElementById('offcanvasAddUser');
if (formAddUser && offcanvasElement) {
formAddUser.addEventListener('submit', function(e) {
e.preventDefault();
let formData = new FormData(this);
let submitBtn = this.querySelector('button[type="submit"]');
submitBtn.disabled = true;
let originalText = submitBtn.innerHTML;
submitBtn.innerHTML = 'Menyimpan...';
fetch(this.action, {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest',
'Accept': 'application/json'
}
})
.then(response => response.json())
.then(data => {
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
if (data.status === 'success') {
let bsOffcanvas = bootstrap.Offcanvas.getInstance(offcanvasElement) || new bootstrap.Offcanvas(offcanvasElement);
bsOffcanvas.hide();
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: data.message,
showConfirmButton: false,
timer: 1500
}).then(() => {
window.location.reload();
});
} else {
let errorMsg = data.message || 'Terjadi kesalahan.';
if (data.errors) {
errorMsg = Object.values(data.errors).map(err => err.join(', ')).join('<br>');
}
Swal.fire({ icon: 'error', title: 'Gagal!', html: errorMsg });
}
})
.catch(error => {
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
Swal.fire({ icon: 'error', title: 'Error', text: 'Koneksi bermasalah atau terjadi kesalahan server.' });
});
});
}
});
</script>
@endpush
+2 -4
View File
@@ -6,7 +6,6 @@ use Illuminate\Support\Facades\Route;
Route::get('/login', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'login'])->name('login'); Route::get('/login', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'login'])->name('login');
Route::get('/register', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'register'])->name('register'); Route::get('/register', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'register'])->name('register');
Route::post('/create-account', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'createAccount'])->name('auth.createAccount'); Route::post('/create-account', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'createAccount'])->name('auth.createAccount');
Route::patch('/users/{user}/verify', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'verify'])->name('users.verify');
Route::post('/authenticate', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'authenticate'])->name('auth.authenticate'); Route::post('/authenticate', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'authenticate'])->name('auth.authenticate');
Route::post('/logout', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'logout'])->name('logout'); Route::post('/logout', [App\Http\Controllers\Web\Konfigurasi\AuthController::class, 'logout'])->name('logout');
@@ -21,9 +20,8 @@ Route::middleware('auth')
Route::get('/akselerasi', [App\Http\Controllers\Web\Dashboard\AkselerasiController::class, 'index'])->name('dashboard.akselerasi'); Route::get('/akselerasi', [App\Http\Controllers\Web\Dashboard\AkselerasiController::class, 'index'])->name('dashboard.akselerasi');
// User // User
Route::get('/users', [App\Http\Controllers\Web\Konfigurasi\UserController::class, 'index'])->name('users.index'); Route::resource('users', App\Http\Controllers\Web\Konfigurasi\UserController::class);
Route::get('/api/users-list', [App\Http\Controllers\Web\Konfigurasi\UserController::class, 'getUsers'])->name('api.users.list'); Route::patch('/users/{user}/verify', [App\Http\Controllers\Web\Konfigurasi\UserController::class, 'verify'])->name('users.verify');
// });
// Provinsi // Provinsi
Route::get('/provinsi', [App\Http\Controllers\Web\Master\ProvinsiController::class, 'index'])->name('provinsi.index'); Route::get('/provinsi', [App\Http\Controllers\Web\Master\ProvinsiController::class, 'index'])->name('provinsi.index');