store/app/Http/Controllers/Admin/Hr/EmployeeController.php

282 lines
9.2 KiB
PHP

<?php
namespace App\Http\Controllers\Admin\Hr;
use App\Enums\EmploymentStatus;
use App\Enums\Gender;
use App\Http\Controllers\Concerns\ParsesDataTableQuery;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\Hr\EmployeeRequest;
use App\Models\Employee;
use App\Models\User;
use App\Models\UserProfile;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Inertia\Inertia;
use Inertia\Response;
class EmployeeController extends Controller
{
use ParsesDataTableQuery;
public function index(Request $request): Response
{
$tableQuery = $this->parseDataTableQuery($request);
$search = $tableQuery['search'];
$sort = $tableQuery['sort'];
$direction = $tableQuery['direction'];
$employmentStatus = $request->string('employment_status')->toString();
$query = User::query()
->with(['profile', 'employee'])
->whereHas('employee')
->when($search !== '', function ($query) use ($search): void {
$query->where(function ($query) use ($search): void {
$query->where('email', 'like', "%{$search}%")
->orWhere('username', 'like', "%{$search}%")
->orWhereHas('profile', function ($query) use ($search): void {
$query->where('full_name', 'like', "%{$search}%")
->orWhere('phone_number', 'like', "%{$search}%");
});
});
})
->when(
$employmentStatus !== '',
fn ($query) => $query->whereHas('employee', fn ($query) => $query->where('employment_status', $employmentStatus))
);
$this->applySorting($query, $sort, $direction);
$employees = $query
->paginate(10)
->withQueryString()
->through(fn (User $user) => $this->transformEmployee($user));
return Inertia::render('admin/hr/employees/Index', [
'employees' => $employees,
'filters' => $this->dataTableFilters($tableQuery, [
'employment_status' => $employmentStatus,
]),
'employmentStatuses' => EmploymentStatus::selectOptions(),
]);
}
public function create(): Response
{
return Inertia::render('admin/hr/employees/Create', [
'genders' => Gender::selectOptions(),
'employmentStatuses' => EmploymentStatus::selectOptions(),
]);
}
public function store(EmployeeRequest $request): RedirectResponse
{
$validated = $request->validated();
DB::transaction(function () use ($validated): void {
$user = User::create([
'email' => $validated['email'],
'username' => $validated['username'],
'password' => Hash::make(config('auth.password_default')),
]);
UserProfile::create([
'user_id' => $user->id,
'full_name' => $validated['full_name'],
'phone_number' => $validated['phone_number'],
'gender' => $validated['gender'],
'birth_date' => $validated['birth_date'],
'address' => $validated['address'],
]);
Employee::create([
'user_id' => $user->id,
'join_date' => $validated['join_date'],
'employment_status' => $validated['employment_status'],
'base_salary' => $validated['base_salary'],
]);
});
Inertia::flash('success', 'Pegawai berhasil ditambahkan.');
return redirect()->route('admin.hr.employees.index');
}
public function edit(User $user): Response
{
$user->load(['profile', 'employee']);
return Inertia::render('admin/hr/employees/Edit', [
'genders' => Gender::selectOptions(),
'employmentStatuses' => EmploymentStatus::selectOptions(),
'employee' => $this->transformEmployeeForForm($user),
]);
}
public function update(EmployeeRequest $request, User $user): RedirectResponse
{
$validated = $request->validated();
$employee = $user->employee;
DB::transaction(function () use ($validated, $user, $employee): void {
$user->email = $validated['email'];
$user->username = $validated['username'];
$user->save();
$profile = $user->profile;
$profile->full_name = $validated['full_name'];
$profile->phone_number = $validated['phone_number'];
$profile->gender = $validated['gender'];
$profile->birth_date = $validated['birth_date'];
$profile->address = $validated['address'];
$profile->save();
$employee->join_date = $validated['join_date'];
$employee->employment_status = $validated['employment_status'];
$employee->base_salary = $validated['base_salary'];
$employee->save();
});
Inertia::flash('success', 'Data pegawai berhasil diperbarui.');
return redirect()->route('admin.hr.employees.index');
}
public function toggleStatus(Request $request, User $user): RedirectResponse
{
$validated = $request->validate([
'is_active' => ['required', 'boolean'],
]);
$user->is_active = $validated['is_active'];
$user->save();
if (! $validated['is_active']) {
DB::table('sessions')->where('user_id', $user->id)->delete();
}
Inertia::flash('success', 'Status pegawai berhasil diperbarui.');
return back();
}
public function resetPassword(User $user): RedirectResponse
{
$user->password = config('auth.password_default');
$user->save();
DB::table('sessions')->where('user_id', $user->id)->delete();
Inertia::flash('success', 'Kata sandi berhasil direset. Pengguna telah logout dari semua sesi.');
return back();
}
public function destroy(User $user): RedirectResponse
{
DB::transaction(function () use ($user): void {
$user->employee?->delete();
$user->profile?->delete();
$user->delete();
});
Inertia::flash('success', 'Pegawai berhasil dihapus.');
return redirect()->route('admin.hr.employees.index');
}
private function applySorting(Builder $query, string $sort, string $direction): void
{
$employeeSorts = [
'join_date',
'base_salary',
'employment_status',
];
if (in_array($sort, $employeeSorts, true)) {
$query->orderBy(
Employee::select($sort)
->whereColumn('employees.user_id', 'users.id')
->limit(1),
$direction
);
return;
}
if ($sort === 'full_name') {
$query->orderBy(
UserProfile::select('full_name')
->whereColumn('user_profiles.user_id', 'users.id')
->limit(1),
$direction
);
return;
}
if ($sort === 'email') {
$query->orderBy('email', $direction);
return;
}
$query->latest();
}
/**
* @return array<string, mixed>
*/
private function transformEmployeeForForm(User $user): array
{
$employee = $user->employee;
$profile = $user->profile;
return [
'id' => $user->id,
'email' => $user->email,
'username' => $user->username,
'full_name' => $profile->full_name,
'phone_number' => $profile->phone_number,
'gender' => $profile->gender?->value,
'birth_date' => $profile->birth_date?->format('Y-m-d'),
'address' => $profile->address,
'join_date' => $employee->join_date?->format('Y-m-d'),
'employment_status' => $employee->employment_status?->value,
'base_salary' => $employee->base_salary,
];
}
/**
* @return array<string, mixed>
*/
private function transformEmployee(User $user): array
{
$employee = $user->employee;
$profile = $user->profile;
return [
'id' => $user->id,
'join_date' => $employee->join_date_formatted,
'resign_date' => $employee->resign_date_formatted,
'employment_status' => $employee->employment_status?->value,
'employment_status_label' => $employee->employment_status?->label(),
'base_salary' => $employee->base_salary,
'base_salary_formatted' => $employee->base_salary_formatted,
'email' => $user->email,
'username' => $user->username,
'is_active' => $user->is_active,
'full_name' => $profile->full_name,
'phone_number' => $profile->phone_number,
'gender' => $profile->gender?->value,
'gender_label' => $profile->gender?->label(),
'birth_date' => $profile->birth_date_formatted,
'address' => $profile->address,
];
}
}