refactor: restrict role-based permissions and update employee management flow accordingly
This commit is contained in:
parent
57c311eaa1
commit
cffea55157
@ -28,13 +28,27 @@ public function __construct(
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$tableQuery = $this->parseDataTableQuery($request);
|
||||
$role = $request->string('role')->toString();
|
||||
$gender = $request->string('gender')->toString();
|
||||
$employmentStatus = $request->string('employment_status')->toString();
|
||||
$isActive = $request->string('is_active')->toString();
|
||||
|
||||
return Inertia::render('admin/hr/employees/Index', [
|
||||
'employees' => $this->employeeService->paginateForIndex($tableQuery, $employmentStatus),
|
||||
'employees' => $this->employeeService->paginateForIndex(
|
||||
$tableQuery,
|
||||
$role,
|
||||
$gender,
|
||||
$employmentStatus,
|
||||
$isActive
|
||||
),
|
||||
'filters' => $this->dataTableFilters($tableQuery, [
|
||||
'role' => $role,
|
||||
'gender' => $gender,
|
||||
'employment_status' => $employmentStatus,
|
||||
'is_active' => $isActive,
|
||||
]),
|
||||
'roles' => Role::assignableSelectOptions(),
|
||||
'genders' => Gender::selectOptions(),
|
||||
'employmentStatuses' => EmploymentStatus::selectOptions(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -15,8 +15,13 @@ class EmployeeService
|
||||
/**
|
||||
* @param array{search: string, sort: string, direction: 'asc'|'desc'} $tableQuery
|
||||
*/
|
||||
public function paginateForIndex(array $tableQuery, string $employmentStatus): LengthAwarePaginator
|
||||
{
|
||||
public function paginateForIndex(
|
||||
array $tableQuery,
|
||||
string $role = '',
|
||||
string $gender = '',
|
||||
string $employmentStatus = '',
|
||||
string $isActive = '',
|
||||
): LengthAwarePaginator {
|
||||
$query = User::query()
|
||||
->with(['profile', 'employee', 'roles'])
|
||||
->whereHas('employee')
|
||||
@ -31,9 +36,21 @@ public function paginateForIndex(array $tableQuery, string $employmentStatus): L
|
||||
});
|
||||
});
|
||||
})
|
||||
->when(
|
||||
$role !== '',
|
||||
fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', $role))
|
||||
)
|
||||
->when(
|
||||
$gender !== '',
|
||||
fn ($query) => $query->whereHas('profile', fn ($query) => $query->where('gender', $gender))
|
||||
)
|
||||
->when(
|
||||
$employmentStatus !== '',
|
||||
fn ($query) => $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus))
|
||||
)
|
||||
->when(
|
||||
$isActive !== '',
|
||||
fn ($query) => $query->where('is_active', $isActive === '1')
|
||||
);
|
||||
|
||||
$this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']);
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { useMediaQuery } from '@vueuse/core';
|
||||
import { ListFilter, Search } from '@lucide/vue';
|
||||
import { computed } from 'vue';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
@ -55,6 +56,10 @@ function onFilterChange(key: string, value: string): void {
|
||||
function resetFilters(): void {
|
||||
emit('filters-reset');
|
||||
}
|
||||
|
||||
const isMobile = useMediaQuery('(max-width: 640px)');
|
||||
const selectSide = computed(() => (isMobile.value ? 'bottom' : 'left'));
|
||||
const selectSideOffset = computed(() => (isMobile.value ? 4 : 12));
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -83,7 +88,16 @@ function resetFilters(): void {
|
||||
</Badge>
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="end" class="w-80 space-y-4 p-4">
|
||||
<PopoverContent
|
||||
align="end"
|
||||
class="w-80 space-y-4 p-4"
|
||||
@pointer-down-outside="(event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (target.closest('[data-slot=select-content]') || target.closest('[data-slot=select-trigger]')) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}"
|
||||
>
|
||||
<div class="space-y-1">
|
||||
<h4 class="text-sm font-medium">
|
||||
Filter
|
||||
@ -116,7 +130,7 @@ function resetFilters(): void {
|
||||
<SelectTrigger :id="`filter-${filter.key}`" class="w-full">
|
||||
<SelectValue :placeholder="filter.placeholder ?? 'Semua'" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectContent class="z-[300]" :side="selectSide" :side-offset="selectSideOffset">
|
||||
<SelectItem value="all">
|
||||
Semua
|
||||
</SelectItem>
|
||||
|
||||
@ -18,8 +18,13 @@ const props = defineProps<{
|
||||
search: string;
|
||||
sort?: string;
|
||||
direction?: 'asc' | 'desc';
|
||||
role?: string;
|
||||
gender?: string;
|
||||
employment_status?: string;
|
||||
is_active?: string;
|
||||
};
|
||||
roles: EnumOption[];
|
||||
genders: EnumOption[];
|
||||
employmentStatuses: EnumOption[];
|
||||
}>();
|
||||
|
||||
@ -29,22 +34,46 @@ const search = ref(props.filters.search ?? '');
|
||||
const { query, setSearch, setSort, setFilter, resetFilters, syncFromServer } = useDataTableQuery({
|
||||
url: '/admin/hr/employees',
|
||||
initial: { ...props.filters },
|
||||
filterKeys: ['employment_status'],
|
||||
filterKeys: ['role', 'gender', 'employment_status', 'is_active'],
|
||||
});
|
||||
|
||||
useDataTableQuerySync(() => props.filters, syncFromServer);
|
||||
|
||||
const filterDefs = computed<DataTableFilterDef[]>(() => [
|
||||
{
|
||||
key: 'role',
|
||||
label: 'Role',
|
||||
type: 'select',
|
||||
options: props.roles,
|
||||
},
|
||||
{
|
||||
key: 'gender',
|
||||
label: 'Jenis Kelamin',
|
||||
type: 'select',
|
||||
options: props.genders,
|
||||
},
|
||||
{
|
||||
key: 'employment_status',
|
||||
label: 'Status Kepegawaian',
|
||||
type: 'select',
|
||||
options: props.employmentStatuses,
|
||||
},
|
||||
{
|
||||
key: 'is_active',
|
||||
label: 'Status Akun',
|
||||
type: 'select',
|
||||
options: [
|
||||
{ value: '1', label: 'Aktif' },
|
||||
{ value: '0', label: 'Nonaktif' },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
||||
const filterValues = computed(() => ({
|
||||
role: query.value.role ?? '',
|
||||
gender: query.value.gender ?? '',
|
||||
employment_status: query.value.employment_status ?? '',
|
||||
is_active: query.value.is_active ?? '',
|
||||
}));
|
||||
|
||||
const currentSort = computed<DataTableSort | null>(() => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user