Compare commits

...

7 Commits

Author SHA1 Message Date
Daeng Deni Mardaeni
c348af2484 (usermanagement): tambah fitur export users dengan filter pencarian
- Modifikasi `UsersExport` untuk menerima parameter search
- Tambah filter whereAny (name, email) di `collection()`
- Tambah kolom "Roles" dengan mapping roles (pluck + implode)
- Null safety branch pakai optional chaining
- Update formatting kolom export
- Modifikasi `UsersController@export` untuk terima & teruskan search
- Batasi role berdasarkan role user login
- Konsistensikan pencarian di `index()` pakai whereAny
- Hapus validasi NIK di profile update
- Tambah ID pada tombol export di `index.blade.php`
- Tambah fungsi JS `updateExportUrl()` untuk sinkronisasi search
- Null safety render branch & role di DataTable
- Tambah listener untuk update URL export saat search
- Perbaiki formatting & indentasi kode
2025-08-15 08:35:06 +07:00
Daeng Deni Mardaeni
e3c7bf711c fix(usermanagement): perbaiki kondisi izin pada metode datatables di UsersController
- Mengubah kunci izin dari `usermanagement.view` menjadi `usermanagement.read` untuk konsistensi naming convention di seluruh sistem.
2025-06-22 21:31:55 +07:00
Daeng Deni Mardaeni
7cb2f798d0 refactor(usermanagement): gunakan middleware untuk autentikasi dan inisialisasi user di semua controller
- Mengubah properti `user` dari `public` menjadi `protected` di semua controller terkait:
  - **PermissionsController**
  - **PositionsController**
  - **RolesController**
  - **UsersController**

- Menghapus inisialisasi manual user dengan `Auth::guard('web')->user()` dari konstruktor.

- Menambahkan middleware:
  - `auth` untuk memastikan bahwa hanya pengguna yang telah login dapat mengakses controller.
  - Middleware tambahan anonim untuk mengassign properti `user` setelah middleware `auth` dijalankan.
2025-06-22 20:52:51 +07:00
Daeng Deni Mardaeni
21521b384e feat(usermanagement): ubah respons abort menjadi JSON untuk akses terlarang di beberapa controller
- Mengganti respons `abort(403)` menjadi respons JSON yang lebih informatif di beberapa controller:
  - **PermissionsController**
    - Penyesuaian pada metode penghapusan dan pengambilan data untuk datatable.
    - Menampilkan pesan error dan status success=false jika pengguna tidak memiliki izin.
  - **PositionsController**
    - Perubahan serupa diterapkan pada metode penghapusan posisi dan pengambilan data untuk datatable.
  - **RolesController**
    - Penyesuaian dilakukan pada metode pengambilan data untuk datatable.
  - **UsersController**
    - Ubah logika pada metode penghapusan dan pengambilan data pengguna ke JSON.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-22 18:56:06 +07:00
Daeng Deni Mardaeni
0a2add800e feat(usermanagement): perbarui seeders untuk grup permission & tambah slug izin restore
- **Perubahan pada Seeder**:
  - Menghapus grup permission `basic-data` dari `PermissionGroupSeeder`, menyisakan hanya `usermanagement` untuk konsistensi.
  - Menambahkan slug baru `restore` ke daftar izin di `PermissionsSeeder` untuk mendukung operasi pemulihan data pada fitur yang relevan.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-22 18:48:43 +07:00
Daeng Deni Mardaeni
fdbef3a5e8 feat(usermanagement): perbaiki otorisasi, tambah fitur ekspor, dan optimalkan logika pada beberapa controller
- **Perbaikan Izin Akses**:
  - Mengganti kunci permission pada beberapa metode agar lebih konsisten:
    - `usermanagement.store` menjadi `usermanagement.create` (store).
    - `usermanagement.edit` menjadi `usermanagement.update` (edit/update).
    - `usermanagement.read` tetap diatur sesuai context (index/view).
  - Menambahkan `abort(403)` pada metode yang belum memiliki pengecekan izin untuk memastikan keamanan.

- **Peningkatan Fitur**:
  - Menambahkan fitur ekspor pada `PermissionsController`, `PositionsController`, `RolesController`, dan `UsersController`:
    - Cek validasi izin sebelum melakukan ekspor.
    - Mendukung pengunduhan file Excel.

- **Optimalisasi Logika**:
  - Menggabungkan properti `user` di semua controller dengan mendefinisikannya melalui konstruktor.
  - Menghapus redundansi load user menggunakan `Auth::guard('web')->user()` di setiap metode.
  - Menyederhanakan pengaturan logging aktivitas untuk setiap operasi CRUD.

- **Penyesuaian & Penambahan**:
  - Menambahkan slug `restore` ke daftar permission terkait untuk operasi pemulihan yang diimplementasikan.
  - Menghapus komentar kode yang tidak digunakan dan mendokumentasikan ulang logika penting untuk lebih jelas.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-22 18:11:14 +07:00
Daeng Deni Mardaeni
becbf8aee2 feat(usermanagement): tambahkan helper untuk cek role and permission
- Perbarui file `module.json`:
  - Menambahkan path baru pada array `files` untuk memuat helper: `app/Helpers/RolePermission.php`.

- Tambahkan helper baru `RolePermission.php`:
  - Fungsi `check_permission`:
    - Mengecek apakah pengguna yang terautentikasi memiliki permission tertentu.
    - Mendukung opsi untuk mengembalikan respons `abort(403)` jika permission tidak valid.
  - Fungsi `user_has_role`:
    - Mengecek apakah pengguna yang terautentikasi memiliki salah satu role dari daftar yang diberikan.
    - Membandingkan nama role pengguna dengan array input menggunakan mekanisme intersect.

Signed-off-by: Daeng Deni Mardaeni <ddeni05@gmail.com>
2025-06-22 10:59:30 +07:00
10 changed files with 215 additions and 119 deletions

View File

@@ -9,10 +9,21 @@ use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use Modules\Usermanagement\Models\User;
class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection, withMapping
class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection, WithMapping
{
protected $search;
public function __construct($search = null)
{
$this->search = $search;
}
public function collection(){
return User::all();
return User::query()
->when($this->search, function ($query) {
$query->whereAny(['name','email'],'like','%'.$this->search.'%');
})
->get();
}
public function map($row): array{
@@ -21,7 +32,8 @@ class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection,
$row->name,
$row->email,
$row->nik,
$row->branch->name,
$row->branch?->name,
$row->roles?->pluck('name')->implode(', '),
$row->created_at
];
}
@@ -32,6 +44,7 @@ class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection,
'Email',
'NIK',
'Branch',
'Roles',
'Created At'
];
}
@@ -39,7 +52,7 @@ class UsersExport implements WithColumnFormatting, WithHeadings, FromCollection,
public function columnFormats(): array{
return [
'A' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_NUMBER,
'F' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DATETIME
'G' => \PhpOffice\PhpSpreadsheet\Style\NumberFormat::FORMAT_DATE_DATETIME
];
}
}

View File

@@ -0,0 +1,30 @@
<?php
use Illuminate\Support\Facades\Auth;
if (!function_exists('check_permission')) {
function check_permission(string $permission, bool $abort = true): bool
{
$user = Auth::user();
if (!$user || !$user->can($permission)) {
if ($abort) {
abort(403, 'Unauthorized');
}
return false;
}
return true;
}
}
if (!function_exists('user_has_role')) {
function user_has_role(array $roles): bool
{
$user = Auth::user();
if (!$user) return false;
return $user->roles->pluck('name')->intersect($roles)->isNotEmpty();
}
}

View File

@@ -23,7 +23,7 @@
/**
* @var \Illuminate\Contracts\Auth\Authenticatable|null
*/
public $user;
protected $user;
/**
* UsersController constructor.
@@ -32,7 +32,14 @@
*/
public function __construct()
{
$this->user = Auth::guard('web')->user();
// Mengatur middleware auth
$this->middleware('auth');
// Mengatur user setelah middleware auth dijalankan
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
/**
@@ -63,8 +70,8 @@
public function store(PermissionRequest $request)
{
// Check if the authenticated user has the required permission to store permissions
if (is_null($this->user) || !$this->user->can('usermanagement.store')) {
abort(403, 'Sorry! You are not allowed to store permissions.');
if (is_null($this->user) || !$this->user->can('usermanagement.create')) {
abort(403, 'Sorry! You are not allowed to create permissions.');
}
$validate = $request->validated();
@@ -80,7 +87,8 @@
$group_name . '.delete',
$group_name . '.export',
$group_name . '.authorize',
$group_name . '.report'
$group_name . '.report',
$group_name . '.restore'
];
foreach ($data as $permission) {
@@ -126,7 +134,7 @@
public function edit($id)
{
// Check if the authenticated user has the required permission to edit permissions
if (is_null($this->user) || !$this->user->can('usermanagement.edit')) {
if (is_null($this->user) || !$this->user->can('usermanagement.update')) {
abort(403, 'Sorry! You are not allowed to edit permissions.');
}
@@ -173,7 +181,8 @@
$group_name . '.delete',
$group_name . '.export',
$group_name . '.authorize',
$group_name . '.report'
$group_name . '.report',
$group_name . '.restore'
];
$i = 0;
@@ -203,7 +212,7 @@
{
// Check if the authenticated user has the required permission to delete permissions
if (is_null($this->user) || !$this->user->can('usermanagement.delete')) {
abort(403, 'Sorry! You are not allowed to delete permissions.');
return response()->json(['message' => 'Sorry! You are not allowed to delete permissions.','success' => false]);
}
$permission = PermissionGroup::find($id);
@@ -258,7 +267,7 @@
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
abort(403, 'Sorry! You are not allowed to view users.');
return response()->json(['message' => 'Sorry! You are not allowed to view permissions.','success' => false]);
}
// Retrieve data from the database
@@ -325,6 +334,11 @@
public function export()
{
// Check if the authenticated user has the required permission to export permissions
if (is_null($this->user) || !$this->user->can('usermanagement.export')) {
abort(403, 'Sorry! You are not allowed to export permissions.');
}
return Excel::download(new PermissionExport, 'permissions.xlsx');
}
}

View File

@@ -23,7 +23,24 @@
/**
* @var \Illuminate\Contracts\Auth\Authenticatable|null
*/
public $user;
protected $user;
/**
* UsersController constructor.
*
* Initializes the user property with the authenticated user.
*/
public function __construct()
{
// Mengatur middleware auth
$this->middleware('auth');
// Mengatur user setelah middleware auth dijalankan
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
/**
* Display a listing of the resource.
@@ -32,11 +49,8 @@
*/
public function index()
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to view positions
if (is_null($user) || !$user->can('usermanagement.read')) {
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
abort(403, 'Sorry! You are not allowed to view positions.');
}
@@ -56,12 +70,9 @@
*/
public function store(PositionRequest $request)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to store positions
if (is_null($user) || !$user->can('usermanagement.create')) {
abort(403, 'Sorry! You are not allowed to store positions.');
if (is_null($this->user) || !$this->user->can('usermanagement.create')) {
abort(403, 'Sorry! You are not allowed to create positions.');
}
// Get validated data
@@ -89,11 +100,8 @@
*/
public function create()
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to create positions
if (is_null($user) || !$user->can('usermanagement.create')) {
if (is_null($this->user) || !$this->user->can('usermanagement.create')) {
abort(403, 'Sorry! You are not allowed to create positions.');
}
@@ -110,11 +118,8 @@
*/
public function edit($id)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to edit positions
if (is_null($user) || !$user->can('usermanagement.update')) {
if (is_null($this->user) || !$this->user->can('usermanagement.update')) {
abort(403, 'Sorry! You are not allowed to edit positions.');
}
@@ -135,11 +140,8 @@
*/
public function update(PositionRequest $request, $id)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to update positions
if (is_null($user) || !$user->can('usermanagement.update')) {
if (is_null($this->user) || !$this->user->can('usermanagement.update')) {
abort(403, 'Sorry! You are not allowed to update positions.');
}
@@ -173,27 +175,24 @@
*/
public function destroy($id)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to delete positions
if (is_null($user) || !$user->can('usermanagement.delete')) {
abort(403, 'Sorry! You are not allowed to delete positions.');
if (is_null($this->user) || !$this->user->can('usermanagement.delete')) {
return response()->json(['message' => 'Sorry! You are not allowed to delete positions.','success' => false]);
}
// Find the position by ID
$position = Position::findOrFail($id);
// Check if the position has associated roles
if ($position->roles()->count() > 0) {
return redirect()->route('users.positions.index')
->with('error', 'Cannot delete position because it has associated roles.');
}
try {
// If no errors, delete the position from the database
$position->delete();
// Redirect to the positions index page with a success message
return redirect()->route('users.positions.index')
->with('success', 'Position deleted successfully.');
@@ -213,12 +212,9 @@
*/
public function dataForDatatables(Request $request)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to view positions
if (is_null($user) || !$user->can('usermanagement.read')) {
abort(403, 'Sorry! You are not allowed to view positions.');
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
return response()->json(['message' => 'Sorry! You are not allowed to view positions.','success' => false]);
}
// Retrieve data from the database
@@ -286,11 +282,8 @@
*/
public function export(Request $request)
{
// Get the authenticated user
$user = Auth::guard('web')->user();
// Check if the authenticated user has the required permission to export positions
if (is_null($user) || !$user->can('usermanagement.export')) {
if (is_null($this->user) || !$this->user->can('usermanagement.export')) {
abort(403, 'Sorry! You are not allowed to export positions.');
}

View File

@@ -26,7 +26,7 @@
/**
* @var \Illuminate\Contracts\Auth\Authenticatable|null
*/
public $user;
protected $user;
/**
* UsersController constructor.
@@ -35,7 +35,14 @@
*/
public function __construct()
{
$this->user = Auth::guard('web')->user();
// Mengatur middleware auth
$this->middleware('auth');
// Mengatur user setelah middleware auth dijalankan
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
/**
@@ -260,7 +267,7 @@
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
abort(403, 'Sorry! You are not allowed to view users.');
return response()->json(['message' => 'Sorry! You are not allowed to view roles.','success' => false]);
}
// Retrieve data from the database
@@ -344,6 +351,10 @@
public function export()
{
if (is_null($this->user) || !$this->user->can('usermanagement.export')) {
abort(403, 'Sorry! You are not allowed to export roles.');
}
return Excel::download(new RolesExport, 'roles.xlsx');
}
}

View File

@@ -9,7 +9,7 @@
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Maatwebsite\Excel\Facades\Excel;
use Modules\Lpj\Models\Branch;
use Modules\Basicdata\Models\Branch;
use Modules\Usermanagement\Exports\UsersExport;
use Modules\Usermanagement\Http\Requests\User as UserRequest;
use Modules\Usermanagement\Models\Role;
@@ -28,7 +28,7 @@
/**
* @var \Illuminate\Contracts\Auth\Authenticatable|null
*/
public $user;
protected $user;
/**
* UsersController constructor.
@@ -37,7 +37,14 @@
*/
public function __construct()
{
$this->user = Auth::guard('web')->user();
// Mengatur middleware auth
$this->middleware('auth');
// Mengatur user setelah middleware auth dijalankan
$this->middleware(function ($request, $next) {
$this->user = Auth::user();
return $next($request);
});
}
/**
@@ -49,7 +56,7 @@
public function index()
{
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
//abort(403, 'Sorry! You are not allowed to view users.');
abort(403, 'Sorry! You are not allowed to view users.');
}
return view('usermanagement::users.index');
@@ -65,8 +72,8 @@
*/
public function dataForDatatables(Request $request)
{
if (is_null($this->user) || !$this->user->can('usermanagement.view')) {
//abort(403, 'Sorry! You are not allowed to view users.');
if (is_null($this->user) || !$this->user->can('usermanagement.read')) {
return response()->json(['message' => 'Sorry! You are not allowed to view users.','success' => false]);
}
// Retrieve data from the database
@@ -75,11 +82,7 @@
// Apply search filter if provided
if ($request->has('search') && !empty($request->get('search'))) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q
->whereRaw('LOWER(name) LIKE ?', ['%' . strtolower($search) . '%'])
->orWhereRaw('LOWER(email) LIKE ?', ['%' . strtolower($search) . '%']);
});
$query->whereAny(['name','email'],'like','%'.$search.'%');
}
// Apply sorting if provided
@@ -135,8 +138,8 @@
*/
public function edit($id)
{
if (is_null($this->user) || !$this->user->can('usermanagement.edit')) {
//abort(403, 'Sorry! You are not allowed to edit users.');
if (is_null($this->user) || !$this->user->can('usermanagement.update')) {
abort(403, 'Sorry! You are not allowed to edit users.');
}
$user = User::find($id);
@@ -156,7 +159,7 @@
public function destroy($id)
{
if (is_null($this->user) || !$this->user->can('usermanagement.delete')) {
//abort(403, 'Sorry! You are not allowed to delete users.');
return response()->json(['message' => 'Sorry! You are not allowed to delete users.','success' => false]);
}
$user = User::find($id);
@@ -198,6 +201,10 @@
*/
public function store(UserRequest $request)
{
if (is_null($this->user) || !$this->user->can('usermanagement.create')) {
abort(403, 'Sorry! You are not allowed to create a user.');
}
$validated = $request->validated();
if ($validated) {
@@ -223,7 +230,7 @@
public function create()
{
if (is_null($this->user) || !$this->user->can('usermanagement.create')) {
//abort(403, 'Sorry! You are not allowed to create a user.');
abort(403, 'Sorry! You are not allowed to create a user.');
}
$roles = Role::all();
@@ -231,9 +238,16 @@
return view('usermanagement::users.create', compact('roles', 'branches'));
}
public function export()
public function export(Request $request)
{
return Excel::download(new UsersExport, 'users.xlsx');
if (is_null($this->user) || !$this->user->can('usermanagement.export')) {
abort(403, 'Sorry! You are not allowed to export users.');
}
// Get search parameter from request
$search = $request->get('search');
return Excel::download(new UsersExport($search), 'users.xlsx');
}
public function profile()
@@ -249,7 +263,6 @@
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users,email,' . $user->id,
'nik' => 'required|string|max:255|unique:users,nik,' . $user->id,
'sign' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048',
]);
@@ -316,7 +329,7 @@
public function update(UserRequest $request, $id)
{
if (is_null($this->user) || !$this->user->can('usermanagement.update')) {
//abort(403, 'Sorry! You are not allowed to update users.');
abort(403, 'Sorry! You are not allowed to update users.');
}
$validated = $request->validated();

View File

@@ -28,8 +28,7 @@
public function data()
{
return [
['name' => 'usermanagement'],
['name' => 'basic-data']
['name' => 'usermanagement']
];
}
}

View File

@@ -53,7 +53,7 @@
{
$actions = [];
// list of permission actions
$crud = ['create', 'read', 'update', 'delete','export', 'authorize', 'report'];
$crud = ['create', 'read', 'update', 'delete','export', 'authorize', 'report','restore'];
foreach ($crud as $value) {

View File

@@ -8,7 +8,9 @@
"providers": [
"Modules\\Usermanagement\\Providers\\UsermanagementServiceProvider"
],
"files": [],
"files": [
"app/Helpers/RolePermission.php"
],
"menu": {
"main": [],
"master": [],

View File

@@ -7,8 +7,9 @@
@section('content')
<div class="container-fluid">
<div class="grid">
<div class="card card-grid min-w-full" data-datatable="false" data-datatable-page-size="5" data-datatable-state-save="true" id="users-table" data-api-url="{{ route('users.datatables') }}">
<div class="card-header py-5 flex-wrap">
<div class="min-w-full card card-grid" data-datatable="false" data-datatable-page-size="5"
data-datatable-state-save="true" id="users-table" data-api-url="{{ route('users.datatables') }}">
<div class="flex-wrap py-5 card-header">
<h3 class="card-title">
List of Users
</h3>
@@ -21,50 +22,54 @@
</div>
<div class="flex flex-wrap gap-2.5 lg:gap-5">
<div class="h-[24px] border border-r-gray-200"> </div>
<a class="btn btn-sm btn-light" href="{{ route('users.export') }}"> Export to Excel </a>
<a class="btn btn-sm btn-light" id="export-btn" href="{{ route('users.export') }}"> Export to
Excel </a>
<a class="btn btn-sm btn-primary" href="{{ route('users.create') }}"> Add User </a>
</div>
</div>
</div>
<div class="card-body">
<div class="scrollable-x-auto">
<table class="table table-auto table-border align-middle text-gray-700 font-medium text-sm" data-datatable-table="true">
<table class="table text-sm font-medium text-gray-700 align-middle table-auto table-border"
data-datatable-table="true">
<thead>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox"/>
</th>
<th class="min-w-[250px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Name </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="email">
<span class="sort"> <span class="sort-label"> Email </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="nik">
<span class="sort"> <span class="sort-label"> NIK </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="branch">
<span class="sort"> <span class="sort-label"> Branch </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="role">
<span class="sort"> <span class="sort-label"> Role </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr>
<tr>
<th class="w-14">
<input class="checkbox checkbox-sm" data-datatable-check="true" type="checkbox" />
</th>
<th class="min-w-[250px]" data-datatable-column="name">
<span class="sort"> <span class="sort-label"> Name </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="email">
<span class="sort"> <span class="sort-label"> Email </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="nik">
<span class="sort"> <span class="sort-label"> NIK </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="branch">
<span class="sort"> <span class="sort-label"> Branch </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[185px]" data-datatable-column="role">
<span class="sort"> <span class="sort-label"> Role </span>
<span class="sort-icon"> </span> </span>
</th>
<th class="min-w-[50px] text-center" data-datatable-column="actions">Action</th>
</tr>
</thead>
</table>
</div>
<div class="card-footer justify-center md:justify-between flex-col md:flex-row gap-3 text-gray-600 text-2sm font-medium">
<div class="flex items-center gap-2">
<div
class="flex-col gap-3 justify-center font-medium text-gray-600 card-footer md:justify-between md:flex-row text-2sm">
<div class="flex gap-2 items-center">
Show
<select class="select select-sm w-16" data-datatable-size="true" name="perpage"> </select> per page
<select class="w-16 select select-sm" data-datatable-size="true" name="perpage"> </select> per
page
</div>
<div class="flex items-center gap-4">
<div class="flex gap-4 items-center">
<span data-datatable-info="true"> </span>
<div class="pagination" data-datatable-pagination="true">
</div>
@@ -82,7 +87,7 @@
function deleteData(data) {
Swal.fire({
title: 'Are you sure?',
text: "You won't be able to revert this!" ,
text: "You won't be able to revert this!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
@@ -92,14 +97,14 @@
if (result.isConfirmed) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': '{{ csrf_token() }}'
'X-CSRF-TOKEN': '{{ csrf_token() }}'
}
});
$.ajax(`users/${data}`, {
type: 'DELETE'
}).then((response) => {
swal.fire('Deleted!', 'User has been deleted.','success').then(() => {
swal.fire('Deleted!', 'User has been deleted.', 'success').then(() => {
window.location.reload();
});
}).catch((error) => {
@@ -113,6 +118,20 @@
<script type="module">
const element = document.querySelector('#users-table');
const searchInput = document.getElementById('search');
const exportBtn = document.getElementById('export-btn');
// Update export URL with filters
function updateExportUrl() {
let url = new URL(exportBtn.href);
if (searchInput.value) {
url.searchParams.set('search', searchInput.value);
} else {
url.searchParams.delete('search');
}
exportBtn.href = url.toString();
};
const apiUrl = element.getAttribute('data-api-url');
const dataTableOptions = {
@@ -141,12 +160,13 @@
branch: {
title: 'Branch',
render: (item, data) => {
return data.branch.name;
return data.branch?.name || '-';
},
},
role: {
title: 'Role',
render: (item, data) => {
console.log(data);
return data.roles.map(role => role.name).join(', ');
},
},
@@ -168,10 +188,11 @@
let dataTable = new KTDataTable(element, dataTableOptions);
// Custom search functionality
searchInput.addEventListener('input', function () {
searchInput.addEventListener('input', function() {
const searchValue = this.value.trim();
dataTable.search(searchValue, true);
updateExportUrl();
dataTable.goPage(1);
});
</script>
@endpush