refactor: update EmployeeController to use ToggleStatusRequest for status toggling and streamline EmployeeService methods for improved validation and clarity

This commit is contained in:
Yoga Pangestu 2026-06-21 01:16:22 +07:00
parent 0803cbeb96
commit b7fddf0597
10 changed files with 37 additions and 45 deletions

View File

@ -9,6 +9,7 @@
use App\Http\Controllers\Concerns\ParsesDataTableQuery; use App\Http\Controllers\Concerns\ParsesDataTableQuery;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Hr\EmployeeRequest; use App\Http\Requests\Admin\Hr\EmployeeRequest;
use App\Http\Requests\Admin\ToggleStatusRequest;
use App\Models\User; use App\Models\User;
use App\Services\Hr\EmployeeService; use App\Services\Hr\EmployeeService;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
@ -91,13 +92,9 @@ public function update(EmployeeRequest $request, User $user): RedirectResponse
return redirect()->route('admin.hr.employees.index'); return redirect()->route('admin.hr.employees.index');
} }
public function toggleStatus(Request $request, User $user): RedirectResponse public function toggleStatus(ToggleStatusRequest $request, User $user): RedirectResponse
{ {
$validated = $request->validate([ $this->employeeService->toggleStatus($user, $request->validated());
'is_active' => ['required', 'boolean'],
]);
$this->employeeService->toggleStatus($user, $validated['is_active']);
$this->flashStatusUpdated('pegawai'); $this->flashStatusUpdated('pegawai');

View File

@ -35,22 +35,12 @@ public function paginateForIndex(
}); });
}); });
}) })
->when( ->when($role !== '', fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', $role)))
$role !== '', ->when($gender !== '', fn ($query) => $query->whereHas('profile', fn ($query) => $query->where('gender', $gender)))
fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', $role)) ->when($employmentStatus !== '', function ($query) use ($employmentStatus): void {
) $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus));
->when( })
$gender !== '', ->when($isActive !== '', fn ($query) => $query->where('is_active', $isActive === '1'));
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']); $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']);
@ -144,12 +134,12 @@ public function update(User $user, array $validated): void
}); });
} }
public function toggleStatus(User $user, bool $isActive): void public function toggleStatus(User $user, array $validated): void
{ {
$user->is_active = $isActive; $user->is_active = $validated['is_active'];
$user->save(); $user->save();
if (! $isActive) { if (! $validated['is_active']) {
DB::table('sessions')->where('user_id', $user->id)->delete(); DB::table('sessions')->where('user_id', $user->id)->delete();
} }
} }

View File

@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Head, Link } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3';
import { ArrowLeft } from '@lucide/vue'; import { ArrowLeft } from '@lucide/vue';
import EmployeeForm from '@/components/admin/hr/EmployeeForm.vue'; import EmployeeForm from './form/EmployeeForm.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { EnumOption } from '@/types/employee'; import type { EnumOption } from '@/types/employee';
@ -14,15 +14,12 @@ defineProps<{
</script> </script>
<template> <template>
<Head title="Tambah Pegawai" /> <Head title="Tambah Pegawai" />
<AdminLayout> <AdminLayout>
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"> <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="space-y-1"> <div class="space-y-1">
<h2 class="text-2xl font-bold tracking-tight"> <h2 class="text-2xl font-bold tracking-tight">Tambah Pegawai</h2>
Tambah Pegawai
</h2>
</div> </div>
<Button variant="outline" as-child class="shrink-0 self-start sm:self-center"> <Button variant="outline" as-child class="shrink-0 self-start sm:self-center">
@ -33,7 +30,6 @@ defineProps<{
</Button> </Button>
</div> </div>
<EmployeeForm submit-url="/admin/hr/employees" method="post" submit-label="Simpan" :genders="genders" <EmployeeForm :genders="genders" :employment-statuses="employmentStatuses" :roles="roles" />
:employment-statuses="employmentStatuses" :roles="roles" />
</AdminLayout> </AdminLayout>
</template> </template>

View File

@ -2,7 +2,7 @@
import { Head, Link } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3';
import { ArrowLeft } from '@lucide/vue'; import { ArrowLeft } from '@lucide/vue';
import { computed } from 'vue'; import { computed } from 'vue';
import EmployeeForm from '@/components/admin/hr/EmployeeForm.vue'; import EmployeeForm from './form/EmployeeForm.vue';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { EmployeeListItem, EnumOption } from '@/types/employee'; import type { EmployeeListItem, EnumOption } from '@/types/employee';

View File

@ -2,12 +2,15 @@
import { Head, Link } from '@inertiajs/vue3'; import { Head, Link } from '@inertiajs/vue3';
import { Plus } from '@lucide/vue'; import { Plus } from '@lucide/vue';
import { computed, ref, watch } from 'vue'; import { computed, ref, watch } from 'vue';
import { columns } from '@/components/admin/hr/employees/columns'; import { columns } from './table/columns';
import { DataTable } from '@/components/data-table'; import { DataTable } from '@/components/data-table';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Card, CardContent } from '@/components/ui/card'; import { Card, CardContent } from '@/components/ui/card';
import { useCan } from '@/composables/useCan'; import { useCan } from '@/composables/useCan';
import { useDataTableQuery, useDataTableQuerySync } from '@/composables/useDataTableQuery'; import {
useDataTableQuery,
useDataTableQuerySync,
} from '@/composables/useDataTableQuery';
import AdminLayout from '@/layouts/AdminLayout.vue'; import AdminLayout from '@/layouts/AdminLayout.vue';
import type { DataTableFilterDef, DataTableSort } from '@/types/data-table'; import type { DataTableFilterDef, DataTableSort } from '@/types/data-table';
import type { EnumOption, PaginatedEmployees } from '@/types/employee'; import type { EnumOption, PaginatedEmployees } from '@/types/employee';
@ -107,15 +110,12 @@ watch(
</script> </script>
<template> <template>
<Head title="Pegawai" /> <Head title="Pegawai" />
<AdminLayout> <AdminLayout>
<div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"> <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
<div class="space-y-1"> <div class="space-y-1">
<h2 class="text-2xl font-bold tracking-tight"> <h2 class="text-2xl font-bold tracking-tight">Pegawai</h2>
Pegawai
</h2>
</div> </div>
<Button v-if="can('employees.create')" as-child class="shrink-0 self-start sm:self-center"> <Button v-if="can('employees.create')" as-child class="shrink-0 self-start sm:self-center">
@ -128,10 +128,19 @@ watch(
<Card class="min-w-0"> <Card class="min-w-0">
<CardContent class="min-w-0"> <CardContent class="min-w-0">
<DataTable v-model:search="search" :columns="columns" :data="employees.data" :pagination="pagination" <DataTable
:pagination-links="employees.links" :sort="currentSort" :filter-defs="filterDefs" v-model:search="search"
:filter-values="filterValues" @sort-change="setSort" @filter-change="setFilter" :columns="columns"
@filters-reset="resetFilters" /> :data="employees.data"
:pagination="pagination"
:pagination-links="employees.links"
:sort="currentSort"
:filter-defs="filterDefs"
:filter-values="filterValues"
@sort-change="setSort"
@filter-change="setFilter"
@filters-reset="resetFilters"
/>
</CardContent> </CardContent>
</Card> </Card>
</AdminLayout> </AdminLayout>

View File

@ -1,10 +1,10 @@
import type { ColumnDef } from '@tanstack/vue-table'; import type { ColumnDef } from '@tanstack/vue-table';
import { h } from 'vue'; import { h } from 'vue';
import DataTableActions from '@/components/admin/hr/employees/data-table-actions.vue';
import EmployeeStatusToggle from '@/components/admin/hr/employees/employee-status-toggle.vue';
import { DataTableColumnHeader } from '@/components/data-table'; import { DataTableColumnHeader } from '@/components/data-table';
import { Badge } from '@/components/ui/badge'; import { Badge } from '@/components/ui/badge';
import type { EmployeeListItem } from '@/types/employee'; import type { EmployeeListItem } from '@/types/employee';
import DataTableActions from './data-table-actions.vue';
import EmployeeStatusToggle from './employee-status-toggle.vue';
export const columns: ColumnDef<EmployeeListItem>[] = [ export const columns: ColumnDef<EmployeeListItem>[] = [
{ {