Files
database-pertani-web/resources/views/konfigurasi/user/index.blade.php
T

398 lines
19 KiB
PHP

@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 Pengguna</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">Semua Akun Terdaftar</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">Pengguna Aktif</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">Email Terverifikasi</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">Pengguna Tertunda</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">Emails Belum Terverifikasi</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>
<a class="btn btn-sm btn-primary" href="{{ route('users.create') }}">
<i class="ti tabler-plus me-1"></i> Tambah User Baru
</a>
</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>Aksi</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>
@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>
@if(!$user->email_verified_at)
<button type="button"
class="btn btn-primary px-9 d-flex align-items-center btn-verify shadow-sm waves-effect waves-light"
style="margin-left: 60px;"
data-url="{{ route('users.verify', $user->id) }}">
<i class="ti tabler-user-check me-2"></i> Verify
</button>
@endif
</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.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 url = $(this).data('url');
Swal.fire({
title: 'Verifikasi Akun',
icon: 'info',
iconColor: '#696cff',
width: '28em',
html: `
<p class="text-muted mb-4" style="font-size: 0.95rem;">Tentukan role akses untuk pengguna ini agar dapat masuk ke dalam sistem AgroMonev.</p>
<div class="px-2 px-md-4 mb-2">
<select id="role-select" class="form-select form-select-md text-start shadow-none" style="cursor: pointer; border-radius: 8px; border-color: #d9dee3;">
<option value="" selected disabled>-- Pilih Role Akses --</option>
<option value="super_admin">🟣 Super Admin</option>
<option value="admin">🟣 Admin</option>
<option value="fasilitator">🟣 Fasilitator</option>
<option value="offtaker">🟣 Offtaker</option>
</select>
</div>
`,
showCancelButton: true,
confirmButtonText: '<i class="ti tabler-check me-1"></i> Simpan',
cancelButtonText: 'Batal',
customClass: {
popup: 'rounded-4',
confirmButton: 'btn btn-primary me-3 waves-effect waves-light',
cancelButton: 'btn btn-label-secondary waves-effect'
},
buttonsStyling: false,
preConfirm: () => {
const role = Swal.getPopup().querySelector('#role-select').value;
if (!role) {
Swal.showValidationMessage('Silakan pilih role terlebih dahulu!');
}
return { role: role };
}
}).then(function (result) {
if (result.isConfirmed) {
const payload = {
_token: csrfToken,
_method: 'PUT',
role: result.value.role
};
$.ajax({
url: url,
type: 'POST',
data: payload,
success: function (res) {
if (res.status === 'success') {
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: res.message,
showConfirmButton: false,
timer: 1500,
customClass: { popup: 'rounded-4' }
}).then(() => {
window.location.reload();
});
} else {
Swal.fire({ icon: 'error', title: 'Gagal!', text: res.message, customClass: { popup: 'rounded-4' } });
}
},
error: function (xhr) {
let errorMsg = xhr.responseJSON ? xhr.responseJSON.message : 'Terjadi kesalahan pada server.';
Swal.fire({ icon: 'error', title: 'Error!', text: errorMsg, customClass: { popup: 'rounded-4' } });
}
});
}
});
});
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');
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}`,
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.' })
});
}
});
});
});
</script>
@endpush