Roles HRD, SPV, MNGR, STAFF

This commit is contained in:
jouel88 2026-03-20 14:38:59 +07:00
parent d6c09fe1ae
commit 99dfe31f64
13 changed files with 332 additions and 339 deletions

View File

@ -19,7 +19,7 @@ public function index(Request $request)
{ {
$query = User::with(['divisi', 'jabatan', 'kantor', 'roles']) $query = User::with(['divisi', 'jabatan', 'kantor', 'roles'])
->whereDoesntHave('roles', function ($q) { ->whereDoesntHave('roles', function ($q) {
$q->where('nama_role', 'admin'); $q->where('nama_role', 'hrd');
}); });
if ($request->filled('filter_jabatan')) { if ($request->filled('filter_jabatan')) {
@ -49,7 +49,7 @@ public function index(Request $request)
$allKantor = Kantor::withCount([ $allKantor = Kantor::withCount([
'users as total_pegawai' => function ($q) { 'users as total_pegawai' => function ($q) {
$q->whereDoesntHave('roles', function ($sq) { $q->whereDoesntHave('roles', function ($sq) {
$sq->where('nama_role', 'admin'); $sq->where('nama_role', 'hrd');
}); });
} }
])->get(); ])->get();
@ -57,11 +57,11 @@ public function index(Request $request)
$stats = [ $stats = [
'kantor_list' => $allKantor, 'kantor_list' => $allKantor,
'total' => User::whereDoesntHave('roles', function ($q) { 'total' => User::whereDoesntHave('roles', function ($q) {
$q->where('nama_role', 'admin'); $q->where('nama_role', 'hrd');
})->count(), })->count(),
'active' => User::where('status_aktif', 1) 'active' => User::where('status_aktif', 1)
->whereDoesntHave('roles', function ($q) { ->whereDoesntHave('roles', function ($q) {
$q->where('nama_role', 'admin'); $q->where('nama_role', 'hrd');
})->count(), })->count(),
]; ];

View File

@ -26,7 +26,7 @@ public function index()
public function create() public function create()
{ {
$pegawai = User::with('kantor')->whereDoesntHave('roles', function ($q) { $pegawai = User::with('kantor')->whereDoesntHave('roles', function ($q) {
$q->where('nama_role', 'admin')->orWhere('nama_role', 'Admin'); $q->where('nama_role', 'hrd');
})->get(); })->get();
$kantor = \App\Models\Kantor::orderBy('nama_kantor', 'asc')->get(); $kantor = \App\Models\Kantor::orderBy('nama_kantor', 'asc')->get();

View File

@ -12,7 +12,7 @@ public function authorize(): bool
{ {
return $this->user()->roles->contains(function ($role) { return $this->user()->roles->contains(function ($role) {
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']); return strtolower($role->nama_role) === 'hrd';
}); });
} }

View File

@ -111,14 +111,14 @@ public function hasPermission($permissionSlug): bool
public function isGlobalAdmin(): bool public function isGlobalAdmin(): bool
{ {
return $this->roles->contains(function ($role) { return $this->roles->contains(function ($role) {
return in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']); return strtolower($role->nama_role) === 'hrd';
}); });
} }
public function isSuperAdmin(): bool public function isSuperAdmin(): bool
{ {
return $this->roles->contains(function ($role) { return $this->roles->contains(function ($role) {
return in_array(strtolower($role->nama_role), ['super admin', 'super_admin']); return strtolower($role->nama_role) === 'hrd';
}); });
} }

View File

@ -54,6 +54,8 @@ public function enrollFace($userId, array $photos)
->where('id', $userId) ->where('id', $userId)
->update(['is_face_registered' => 1]); ->update(['is_face_registered' => 1]);
$trainingSuccess = false;
try { try {
$pythonPath = env('PYTHON_PATH', 'python'); $pythonPath = env('PYTHON_PATH', 'python');
$scriptPath = base_path('python_scripts/train_face.py'); $scriptPath = base_path('python_scripts/train_face.py');
@ -73,22 +75,26 @@ public function enrollFace($userId, array $photos)
$process->run(); $process->run();
if (!$process->isSuccessful()) { if (!$process->isSuccessful()) {
\Illuminate\Support\Facades\Log::warning("Face Training Failed (silently caught): " . $process->getErrorOutput()); \Illuminate\Support\Facades\Log::warning("Face Training Failed: " . $process->getErrorOutput());
} else { } else {
$output = json_decode($process->getOutput(), true); $output = json_decode($process->getOutput(), true);
if (!isset($output['status']) || $output['status'] !== 'success') { if (isset($output['status']) && $output['status'] === 'success') {
\Illuminate\Support\Facades\Log::warning("Face Training Failed (silently caught): " . ($output['message'] ?? 'Unknown Error')); $trainingSuccess = true;
} else {
\Illuminate\Support\Facades\Log::warning("Face Training Failed: " . ($output['message'] ?? 'Unknown Error'));
} }
} }
} catch (\Exception $trainEx) { } catch (\Exception $trainEx) {
\Illuminate\Support\Facades\Log::warning("Face Training Error (silently caught): " . $trainEx->getMessage()); \Illuminate\Support\Facades\Log::warning("Face Training Error: " . $trainEx->getMessage());
} }
$relativeModelPath = "face_models/user_{$userId}.yml"; $relativeModelPath = "face_models/user_{$userId}.yml";
// Jika training Python berhasil → otomatis verified
// Jika training gagal → tetap pending (is_verified = 0), butuh approval manual HRD
DB::table('data_wajah')->where('id_user', $userId)->update([ DB::table('data_wajah')->where('id_user', $userId)->update([
'path_model_yml' => $relativeModelPath, 'path_model_yml' => $relativeModelPath,
'is_verified' => 0, 'is_verified' => $trainingSuccess ? 1 : 0,
]); ]);
DB::commit(); DB::commit();

View File

@ -2,46 +2,27 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Models\User;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
class DatabaseSeeder extends Seeder class DatabaseSeeder extends Seeder
{ {
public function run(): void public function run(): void
{ {
// Panggil MasterDataSeeder terlebih dahulu untuk data dasar (Divisi, Jabatan, Kantor, Role, User Admin)
$this->call([ $this->call([
// 1. Data master: Role, Divisi, Jabatan, Kantor, User HRD & contoh staff
MasterDataSeeder::class, MasterDataSeeder::class,
]);
// Tambahan data demo jika diperlukan (Opsional) // 2. Permission per role
$kantor = \App\Models\Kantor::first();
$divisi = \App\Models\Divisi::first();
$jabatan = \App\Models\Jabatan::where('nama_jabatan', 'Staff')->first() ?? \App\Models\Jabatan::first();
$users = User::factory(5)->create([
'id_kantor' => $kantor->id_kantor,
'id_divisi' => $divisi->id_divisi,
'id_jabatan' => $jabatan->id_jabatan,
]);
$rolePegawai = \App\Models\Role::where('nama_role', 'pegawai')->first();
if ($rolePegawai) {
foreach ($users as $user) {
$user->roles()->attach($rolePegawai->id_role);
}
}
// Panggil seeder fitur lainnya
$this->call([
PermissionSeeder::class, PermissionSeeder::class,
// 3. Data lookup / referensi
PresensiStatusSeeder::class, PresensiStatusSeeder::class,
PresensiSeeder::class,
JenisIzinSeeder::class, JenisIzinSeeder::class,
StatusPengajuanSeeder::class, StatusPengajuanSeeder::class,
PengajuanIzinSeeder::class,
SuperAdminSeeder::class, // Menambah super administrator dengan role admin // 4. Data dummy (opsional, comment jika tidak diperlukan di production)
// PresensiSeeder::class,
// PengajuanIzinSeeder::class,
]); ]);
} }
} }

View File

@ -3,31 +3,12 @@
namespace Database\Seeders; namespace Database\Seeders;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Role; use App\Models\Role;
class FixLegacyRolesSeeder extends Seeder class FixLegacyRolesSeeder extends Seeder
{ {
public function run() public function run()
{ {
$this->command->info('Tidak ada migrasi legacy yang perlu dilakukan (sistem sudah menggunakan pivot roles).');
$roleAdmin = Role::firstOrCreate(['nama_role' => 'admin']);
$rolePegawai = Role::firstOrCreate(['nama_role' => 'pegawai']);
$oldAdmins = User::where('role', 'admin')->get();
foreach ($oldAdmins as $user) {
if (!$user->roles()->where('nama_role', 'admin')->exists()) {
$user->roles()->attach($roleAdmin->id_role ?? $roleAdmin->id);
$this->command->info("Migrated legacy admin: {$user->email}");
}
}
$oldStaff = User::where('role', 'pegawai')->get();
foreach ($oldStaff as $user) {
if (!$user->roles()->where('nama_role', 'pegawai')->exists()) {
$user->roles()->attach($rolePegawai->id_role ?? $rolePegawai->id);
$this->command->info("Migrated legacy staff: {$user->email}");
}
}
} }
} }

View File

@ -43,27 +43,27 @@ public function run()
] ]
); );
// Roles
$roleAdmin = \App\Models\Role::firstOrCreate(['nama_role' => 'admin']);
$roleHrd = \App\Models\Role::firstOrCreate(['nama_role' => 'hrd']); $roleHrd = \App\Models\Role::firstOrCreate(['nama_role' => 'hrd']);
$roleManager = \App\Models\Role::firstOrCreate(['nama_role' => 'manager']); $roleManager = \App\Models\Role::firstOrCreate(['nama_role' => 'manager']);
$rolePegawai = \App\Models\Role::firstOrCreate(['nama_role' => 'pegawai']); $roleSupervisor = \App\Models\Role::firstOrCreate(['nama_role' => 'supervisor']);
$roleStaff = \App\Models\Role::firstOrCreate(['nama_role' => 'staff']);
$admin = User::updateOrCreate( $hrd = User::updateOrCreate(
['email' => 'admin@mpg.co.id'], ['nik' => '999999999'],
[ [
'nama_lengkap' => 'Super Administrator', 'nama_lengkap' => 'HRD Manager',
'password' => Hash::make('admin123'), 'email' => 'hrd@mpg.co.id',
'nik' => '999999999', 'password' => Hash::make('Mpg123!'),
'status_aktif' => 1, 'status_aktif' => 1,
'id_divisi' => $divIT->id_divisi, 'id_divisi' => $divHR->id_divisi,
'id_jabatan' => $jabMgr->id_jabatan, 'id_jabatan' => $jabMgr->id_jabatan,
'id_kantor' => $kPusat->id_kantor, 'id_kantor' => $kPusat->id_kantor,
'tgl_bergabung' => now(), 'tgl_bergabung' => now(),
'sisa_cuti' => 12,
] ]
); );
if (!$admin->roles()->where('nama_role', 'admin')->exists()) { if (!$hrd->roles()->where('nama_role', 'hrd')->exists()) {
$admin->roles()->attach($roleAdmin->id_role); $hrd->roles()->attach($roleHrd->id_role);
} }
$pegawai = User::updateOrCreate( $pegawai = User::updateOrCreate(
@ -77,10 +77,11 @@ public function run()
'id_jabatan' => $jabStf->id_jabatan, 'id_jabatan' => $jabStf->id_jabatan,
'id_kantor' => $kCabang->id_kantor, 'id_kantor' => $kCabang->id_kantor,
'tgl_bergabung' => now(), 'tgl_bergabung' => now(),
'sisa_cuti' => 12,
] ]
); );
if (!$pegawai->roles()->where('nama_role', 'pegawai')->exists()) { if (!$pegawai->roles()->where('nama_role', 'staff')->exists()) {
$pegawai->roles()->attach($rolePegawai->id_role); $pegawai->roles()->attach($roleStaff->id_role);
} }
} }
} }

View File

@ -5,30 +5,34 @@
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use App\Models\Permission; use App\Models\Permission;
use App\Models\Role; use App\Models\Role;
use Illuminate\Support\Str;
class PermissionSeeder extends Seeder class PermissionSeeder extends Seeder
{ {
public function run(): void public function run(): void
{ {
$permissions = [ $permissions = [
'view_dashboard', 'view_dashboard',
// Data Master
'manage_divisi', 'manage_divisi',
'manage_jabatan', 'manage_jabatan',
'manage_kantor', 'manage_kantor',
'manage_shift', 'manage_shift',
'manage_hari_libur', 'manage_hari_libur',
'manage_cuti',
// Data Pegawai
'view_pegawai', 'view_pegawai',
'create_pegawai', 'create_pegawai',
'edit_pegawai', 'edit_pegawai',
'delete_pegawai', 'delete_pegawai',
'view_pegawai_detail', 'view_pegawai_detail',
// Penjadwalan
'view_jadwal',
'manage_jadwal',
// Presensi
'view_presensi_all', 'view_presensi_all',
'view_presensi_team', 'view_presensi_team',
'view_presensi_self', 'view_presensi_self',
@ -36,20 +40,37 @@ public function run(): void
'approve_presensi', 'approve_presensi',
'correction_presensi', 'correction_presensi',
// Izin
'view_izin_all', 'view_izin_all',
'view_izin_team', 'view_izin_team',
'create_izin', 'create_izin',
'approve_izin', 'approve_izin',
// Surat Izin
'view_surat_izin',
'approve_surat_izin',
// Lembur
'view_lembur_all', 'view_lembur_all',
'view_lembur_team', 'view_lembur_team',
'create_lembur', 'create_lembur',
'approve_lembur', 'approve_lembur',
// Poin
'manage_poin',
// Laporan
'view_laporan', // laporan kehadiran
'view_laporan_izin', // laporan izin/cuti
'view_laporan_lembur', // laporan lembur
// Pengumuman
'manage_pengumuman',
// Face Recognition
'manage_face_data', 'manage_face_data',
'view_laporan', // Sistem
'manage_users', 'manage_users',
'manage_roles', 'manage_roles',
'manage_permissions', 'manage_permissions',
@ -62,49 +83,50 @@ public function run(): void
); );
} }
$adminRole = Role::where('nama_role', 'admin')->first(); // ─── HRD ─── akses penuh ke semua permission
if ($adminRole) {
$allPermissions = Permission::all();
$adminRole->permissions()->sync($allPermissions);
}
$hrdRole = Role::where('nama_role', 'hrd')->first(); $hrdRole = Role::where('nama_role', 'hrd')->first();
if ($hrdRole) { if ($hrdRole) {
$hrdPermissions = Permission::whereIn('nama_permission', [ $hrdRole->permissions()->sync(Permission::all());
'view_dashboard',
'manage_divisi', 'manage_jabatan', 'manage_kantor', 'manage_shift', 'manage_hari_libur',
'view_pegawai', 'create_pegawai', 'edit_pegawai', 'view_pegawai_detail',
'view_presensi_all', 'approve_presensi', 'correction_presensi',
'view_izin_all', 'approve_izin',
'view_lembur_all', 'approve_lembur',
'manage_face_data',
'view_laporan'
])->get();
$hrdRole->permissions()->sync($hrdPermissions);
} }
// ─── MANAGER ─── approve presensi & izin, lihat laporan kehadiran & izin
$managerRole = Role::where('nama_role', 'manager')->first(); $managerRole = Role::where('nama_role', 'manager')->first();
if ($managerRole) { if ($managerRole) {
$managerPermissions = Permission::whereIn('nama_permission', [ $perms = Permission::whereIn('nama_permission', [
'view_dashboard', 'view_dashboard',
'view_pegawai', 'view_pegawai_detail', 'view_pegawai', 'view_pegawai_detail',
'view_presensi_team', 'view_jadwal',
'view_presensi_team', 'approve_presensi',
'view_izin_team', 'approve_izin', 'view_izin_team', 'approve_izin',
'view_lembur_team', 'approve_lembur' 'view_surat_izin', 'approve_surat_izin',
'view_laporan',
'view_laporan_izin',
])->get(); ])->get();
$managerRole->permissions()->sync($managerPermissions); $managerRole->permissions()->sync($perms);
} }
$pegawaiRole = Role::where('nama_role', 'pegawai')->first(); // ─── SUPERVISOR ─── approve presensi, lihat laporan kehadiran & penjadwalan
if ($pegawaiRole) { $supervisorRole = Role::where('nama_role', 'supervisor')->first();
$pegawaiPermissions = Permission::whereIn('nama_permission', [ if ($supervisorRole) {
$perms = Permission::whereIn('nama_permission', [
'view_dashboard', 'view_dashboard',
'view_jadwal',
'view_presensi_team', 'approve_presensi',
'view_laporan',
])->get();
$supervisorRole->permissions()->sync($perms);
}
// ─── STAFF ─── hanya mobile (tidak ada view_dashboard = tidak bisa akses web)
$staffRole = Role::where('nama_role', 'staff')->first();
if ($staffRole) {
$perms = Permission::whereIn('nama_permission', [
'view_presensi_self', 'view_presensi_self',
'create_presensi', 'create_presensi',
'create_izin', 'create_izin',
'create_lembur' 'create_lembur',
])->get(); ])->get();
$pegawaiRole->permissions()->sync($pegawaiPermissions); $staffRole->permissions()->sync($perms);
} }
} }
} }

View File

@ -3,53 +3,17 @@
namespace Database\Seeders; namespace Database\Seeders;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Role;
use App\Models\Divisi;
use App\Models\Jabatan;
use App\Models\Kantor;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\DB;
/**
* SuperAdminSeeder sudah tidak digunakan.
* Fungsinya telah dipindahkan ke MasterDataSeeder (user HRD dibuat di sana).
* File ini dipertahankan agar tidak ada error jika masih dirujuk,
* namun tidak melakukan apa-apa.
*/
class SuperAdminSeeder extends Seeder class SuperAdminSeeder extends Seeder
{ {
public function run() public function run(): void
{ {
$this->command->info('SuperAdminSeeder: tidak melakukan apa-apa (lihat MasterDataSeeder).');
$divisi = Divisi::first() ?? Divisi::create(['nama_divisi' => 'IT Dept']);
$jabatan = Jabatan::first() ?? Jabatan::create(['nama_jabatan' => 'Super Admin']);
$kantor = Kantor::first() ?? Kantor::create(['nama_kantor' => 'Headquarters', 'alamat' => 'Cloud', 'tipe' => 'Pusat']);
$roleAdmin = Role::firstOrCreate(
['nama_role' => 'admin'],
['keterangan' => 'Administrator with Full Access']
);
$user = User::updateOrCreate(
['email' => 'superadmin@mpg.co.id'],
[
'nama_lengkap' => 'Super Administrator',
'password' => Hash::make('password'),
'nik' => '77777777',
'no_telp' => '081234567890',
'alamat' => 'Server Room',
'status_aktif' => 1,
'tgl_bergabung' => now(),
'id_divisi' => $divisi->id_divisi ?? $divisi->id,
'id_jabatan' => $jabatan->id_jabatan ?? $jabatan->id,
'id_kantor' => $kantor->id_kantor ?? $kantor->id,
'sisa_cuti' => 12,
]
);
if (!$user->roles()->where('nama_role', 'admin')->exists()) {
$user->roles()->attach($roleAdmin->id_role ?? $roleAdmin->id);
$this->command->info('Role admin attached to user.');
}
$this->command->info('Super Admin created successfully!');
$this->command->info('Email: superadmin@mpg.co.id');
$this->command->info('Password: password');
} }
} }

View File

@ -12,14 +12,26 @@ class="fixed inset-y-0 left-0 w-72 bg-white border-r border-slate-200 flex flex-
</div> </div>
@php @php
$isAdmin = Auth::user()->roles->contains(function ($role) { $roleNama = strtolower(Auth::user()->roles->first()?->nama_role ?? '');
return strtolower($role->nama_role) === 'admin'; $isHrd = $roleNama === 'hrd';
}); $isManager = $roleNama === 'manager';
$isSuperAdmin = Auth::user()->isSuperAdmin(); $isSupervisor = $roleNama === 'supervisor';
$isAdminOrSuperAdmin = Auth::user()->isGlobalAdmin(); $isStaff = $roleNama === 'staff';
// Alias untuk kondisi gabungan
$canManage = $isHrd; // hanya HRD
$canViewPegawai = $isHrd || $isManager; // HRD & Manager
$canViewPresensi = $isHrd || $isManager || $isSupervisor;
$canApproveIzin = $isHrd || $isManager;
$canViewLaporan = $isHrd || $isManager || $isSupervisor; // laporan kehadiran
$canViewLaporanIzin = $isHrd || $isManager;
$canViewJadwal = $isHrd || $isManager || $isSupervisor;
$canAccessWeb = $isHrd || $isManager || $isSupervisor;
@endphp @endphp
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto no-scrollbar"> <nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto no-scrollbar">
{{-- ── Dashboard ── --}}
<div class="space-y-1"> <div class="space-y-1">
<a href="{{ route('dashboard') }}" <a href="{{ route('dashboard') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('dashboard') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('dashboard') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
@ -33,7 +45,8 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</a> </a>
</div> </div>
@if($isAdminOrSuperAdmin) {{-- ════════════════════════════════ SEKSI: MANAJEMEN ════════════════════════════════ --}}
@if($canManage || $canViewPegawai)
<div class="pt-6 pb-3 px-4 flex items-center gap-3"> <div class="pt-6 pb-3 px-4 flex items-center gap-3">
<div class="h-px bg-slate-200 flex-1"></div> <div class="h-px bg-slate-200 flex-1"></div>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Manajemen</span> <span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Manajemen</span>
@ -41,7 +54,9 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
@if($isSuperAdmin)
{{-- Verifikasi Wajah HRD only --}}
@if($isHrd)
<a href="{{ route('face.index') }}" <a href="{{ route('face.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('face.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('face.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('face.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('face.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -52,12 +67,13 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
<span class="font-semibold text-sm">Verifikasi Wajah</span> <span class="font-semibold text-sm">Verifikasi Wajah</span>
@php $pendingFace = \App\Models\User::where('is_face_registered', 0)->whereHas('dataWajah')->count(); @endphp @php $pendingFace = \App\Models\User::where('is_face_registered', 0)->whereHas('dataWajah')->count(); @endphp
@if($pendingFace > 0) @if($pendingFace > 0)
<span <span class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingFace }}</span>
class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingFace }}</span>
@endif @endif
</a> </a>
@endif @endif
{{-- Data Karyawan HRD & Manager --}}
@if($canViewPegawai)
<a href="{{ route('pegawai.index') }}" <a href="{{ route('pegawai.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('pegawai.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('pegawai.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('pegawai.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('pegawai.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -68,7 +84,10 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</svg> </svg>
<span class="font-semibold text-sm">Data Karyawan</span> <span class="font-semibold text-sm">Data Karyawan</span>
</a> </a>
@endif
{{-- Penjadwalan HRD, Manager, Supervisor --}}
@if($canViewJadwal)
<a href="{{ route('jadwal.index') }}" <a href="{{ route('jadwal.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('jadwal.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('jadwal.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('jadwal.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('jadwal.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -78,10 +97,13 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</svg> </svg>
<span class="font-semibold text-sm">Penjadwalan</span> <span class="font-semibold text-sm">Penjadwalan</span>
</a> </a>
@endif
</div> </div>
@endif @endif
@if($isAdminOrSuperAdmin) {{-- ════════════════════════════════ SEKSI: ABSENSI ════════════════════════════════ --}}
@if($canViewLaporan || $canViewPresensi)
<div class="pt-6 pb-3 px-4 flex items-center gap-3"> <div class="pt-6 pb-3 px-4 flex items-center gap-3">
<div class="h-px bg-slate-200 flex-1"></div> <div class="h-px bg-slate-200 flex-1"></div>
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Absensi</span> <span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Absensi</span>
@ -89,6 +111,9 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</div> </div>
<div class="space-y-1"> <div class="space-y-1">
{{-- Laporan Kehadiran HRD, Manager, Supervisor --}}
@if($canViewLaporan)
<a href="{{ route('laporan.index') }}" <a href="{{ route('laporan.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan.index') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan.index') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan.index') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan.index') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -98,8 +123,10 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</svg> </svg>
<span class="font-semibold text-sm">Laporan Kehadiran</span> <span class="font-semibold text-sm">Laporan Kehadiran</span>
</a> </a>
@endif
@if($isAdminOrSuperAdmin) {{-- Laporan Lembur HRD only --}}
@if($isHrd)
<a href="{{ route('laporan-lembur.index') }}" <a href="{{ route('laporan-lembur.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan-lembur.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan-lembur.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan-lembur.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan-lembur.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -111,6 +138,8 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</a> </a>
@endif @endif
{{-- Laporan Izin/Cuti HRD & Manager --}}
@if($canViewLaporanIzin)
<a href="{{ route('laporan.izin') }}" <a href="{{ route('laporan.izin') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan.izin') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('laporan.izin') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan.izin') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('laporan.izin') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -120,23 +149,25 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
</svg> </svg>
<span class="font-semibold text-sm">Laporan Izin/Cuti</span> <span class="font-semibold text-sm">Laporan Izin/Cuti</span>
</a> </a>
@endif
{{-- Monitoring Presensi HRD, Manager, Supervisor --}}
@if($canViewPresensi)
<a href="{{ route('presensi.index') }}" <a href="{{ route('presensi.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('presensi.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('presensi.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('presensi.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('presensi.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
fill="none" stroke="currentColor" viewBox="0 0 24 24"> fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg> </svg>
<span class="flex-1 font-semibold text-sm">Monitoring Presensi</span> <span class="flex-1 font-semibold text-sm">Monitoring Presensi</span>
@if(isset($pendingPresensi) && $pendingPresensi > 0) @if(isset($pendingPresensi) && $pendingPresensi > 0)
<span class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full"> <span class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingPresensi }}</span>
{{ $pendingPresensi }}
</span>
@endif @endif
</a> </a>
@endif
{{-- Manajemen Izin HRD & Manager --}}
@if($canApproveIzin)
<a href="{{ route('izin.index') }}" <a href="{{ route('izin.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('izin.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('izin.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('izin.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('izin.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -152,6 +183,7 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
@endif @endif
</a> </a>
{{-- Surat Izin HRD & Manager --}}
<a href="{{ route('surat-izin.index') }}" <a href="{{ route('surat-izin.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('surat-izin.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('surat-izin.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('surat-izin.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('surat-izin.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -166,18 +198,10 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingSurat }}</span> <span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingSurat }}</span>
@endif @endif
</a> </a>
@endif
<a href="{{ route('pengumuman.index') }}" {{-- Lembur & Poin HRD only --}}
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('pengumuman.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> @if($isHrd)
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('pengumuman.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z">
</path>
</svg>
<span class="font-semibold text-sm">Pengumuman</span>
</a>
<a href="{{ route('lembur.index') }}" <a href="{{ route('lembur.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('lembur.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('lembur.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('lembur.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300" <svg class="w-5 h-5 mr-3 {{ request()->routeIs('lembur.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
@ -207,8 +231,25 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingPoin }}</span> <span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingPoin }}</span>
@endif @endif
</a> </a>
</div>
{{-- Pengumuman HRD only --}}
<a href="{{ route('pengumuman.index') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('pengumuman.*') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
<svg class="w-5 h-5 mr-3 {{ request()->routeIs('pengumuman.*') ? 'text-white' : 'text-slate-400 group-hover:text-slate-600' }} group-hover:scale-110 transition-transform duration-300"
fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M11 5.882V19.24a1.76 1.76 0 01-3.417.592l-2.147-6.15M18 13a3 3 0 100-6M5.436 13.683A4.001 4.001 0 017 6h1.832c4.1 0 7.625-1.234 9.168-3v14c-1.543-1.766-5.067-3-9.168-3H7a3.988 3.988 0 01-1.564-.317z">
</path>
</svg>
<span class="font-semibold text-sm">Pengumuman</span>
</a>
@endif
</div>
@endif
{{-- ════════════════════════════════ SEKSI: DATA MASTER (HRD only) ════════════════════════════════ --}}
@if($isHrd)
<div x-data="{ open: {{ request()->routeIs('divisi.*', 'jabatan.*', 'kantor.*', 'role.*', 'shift.*', 'hari-libur.*', 'cuti.*') ? 'true' : 'false' }} }" <div x-data="{ open: {{ request()->routeIs('divisi.*', 'jabatan.*', 'kantor.*', 'role.*', 'shift.*', 'hari-libur.*', 'cuti.*') ? 'true' : 'false' }} }"
class="space-y-1"> class="space-y-1">
@ -250,12 +291,10 @@ class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs
Data Jabatan Data Jabatan
</a> </a>
@if($isSuperAdmin)
<a href="{{ route('role.index') }}" <a href="{{ route('role.index') }}"
class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('role.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}"> class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('role.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}">
Data Role Data Role
</a> </a>
@endif
<a href="{{ route('shift.index') }}" <a href="{{ route('shift.index') }}"
class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('shift.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}"> class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('shift.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}">
@ -276,6 +315,8 @@ class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs
@endif @endif
</nav> </nav>
{{-- ── Footer: Pengaturan Akun & Logout ── --}}
<div class="px-8 py-6 border-t border-slate-100 mt-auto bg-slate-50/50"> <div class="px-8 py-6 border-t border-slate-100 mt-auto bg-slate-50/50">
<a href="{{ route('profile.edit') }}" <a href="{{ route('profile.edit') }}"
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('profile.edit') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}"> class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('profile.edit') ? 'bg-[#130F26] text-white shadow-lg shadow-[#130F26]/30' : 'text-slate-500 hover:bg-slate-50 hover:text-slate-900' }}">
@ -310,7 +351,7 @@ class="flex w-full items-center px-4 py-3 rounded-xl text-red-500 hover:bg-red-5
display: none; display: none;
} }
.no-scrollbar { .no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */ -ms-overflow-style: none;
scrollbar-width: none; /* Firefox */ scrollbar-width: none;
} }
</style> </style>

View File

@ -1,4 +1,4 @@
@extends('layouts.app') @extends('layouts.app')
@section('title', 'Monitoring Presensi') @section('title', 'Monitoring Presensi')
@ -24,7 +24,7 @@
<x-page-header title="Monitoring Presensi" subtitle="Pantau kehadiran pegawai harian."> <x-page-header title="Monitoring Presensi" subtitle="Pantau kehadiran pegawai harian.">
<div class="flex gap-2"> <div class="flex gap-2">
@if(Auth::user()->roles->contains(fn($role) => in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']))) @if(Auth::user()->roles->contains(fn($role) => strtolower($role->nama_role) === 'hrd'))
<a href="{{ route('presensi.create') }}" class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-lg text-white bg-slate-800 hover:bg-slate-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-slate-900 transition-colors shadow-sm text-sm h-[42px]"> <a href="{{ route('presensi.create') }}" class="inline-flex items-center justify-center px-4 py-2 border border-transparent font-medium rounded-lg text-white bg-slate-800 hover:bg-slate-900 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-slate-900 transition-colors shadow-sm text-sm h-[42px]">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"> <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path>
@ -212,7 +212,7 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold
</button> </button>
@endif @endif
@if(Auth::user()->roles->contains(fn($role) => in_array(strtolower($role->nama_role), ['admin', 'super admin', 'super_admin']))) @if(Auth::user()->roles->contains(fn($role) => strtolower($role->nama_role) === 'hrd'))
<a href="{{ route('presensi.edit', $p->id_presensi) }}" class="p-1.5 text-blue-600 hover:text-blue-800 bg-blue-50 hover:bg-blue-100 rounded-lg transition-colors border border-blue-100" title="Koreksi Jam/Status"> <a href="{{ route('presensi.edit', $p->id_presensi) }}" class="p-1.5 text-blue-600 hover:text-blue-800 bg-blue-50 hover:bg-blue-100 rounded-lg transition-colors border border-blue-100" title="Koreksi Jam/Status">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg> <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg>
</a> </a>

View File

@ -74,11 +74,10 @@
Route::post('/tanda-tangan', [SignatureController::class, 'store'])->name('signature.store'); Route::post('/tanda-tangan', [SignatureController::class, 'store'])->name('signature.store');
}); });
Route::middleware(['auth', 'role:admin'])->group(function () { Route::middleware(['auth', 'role:hrd'])->group(function () {
Route::resource('divisi', DivisiController::class)->except(['create', 'edit', 'show']); Route::resource('divisi', DivisiController::class)->except(['create', 'edit', 'show']);
Route::resource('jabatan', JabatanController::class); Route::resource('jabatan', JabatanController::class);
Route::resource('kantor', KantorController::class)->except(['create', 'show', 'edit']); Route::resource('kantor', KantorController::class)->except(['create', 'show', 'edit']);
// Role route moved to super admin group
Route::resource('shift', \App\Http\Controllers\ShiftController::class)->except(['create', 'edit', 'show']); Route::resource('shift', \App\Http\Controllers\ShiftController::class)->except(['create', 'edit', 'show']);
Route::resource('jadwal', \App\Http\Controllers\JadwalController::class)->except(['edit', 'show']); Route::resource('jadwal', \App\Http\Controllers\JadwalController::class)->except(['edit', 'show']);
Route::resource('pegawai', PegawaiController::class); Route::resource('pegawai', PegawaiController::class);
@ -99,9 +98,7 @@
Route::get('/tukar-shift/jadwal-user', [\App\Http\Controllers\TukarShiftController::class, 'getJadwalUser'])->name('tukar-shift.jadwal-user'); Route::get('/tukar-shift/jadwal-user', [\App\Http\Controllers\TukarShiftController::class, 'getJadwalUser'])->name('tukar-shift.jadwal-user');
Route::resource('tukar-shift', \App\Http\Controllers\TukarShiftController::class)->only(['index', 'create', 'store']); Route::resource('tukar-shift', \App\Http\Controllers\TukarShiftController::class)->only(['index', 'create', 'store']);
});
Route::middleware(['auth', 'role:super admin,super_admin'])->group(function () {
Route::get('/permissions', [PermissionController::class, 'index'])->name('permission.index'); Route::get('/permissions', [PermissionController::class, 'index'])->name('permission.index');
Route::post('/permissions', [PermissionController::class, 'store'])->name('permission.store'); Route::post('/permissions', [PermissionController::class, 'store'])->name('permission.store');
Route::post('/permissions/sync/{id_role}', [PermissionController::class, 'sync'])->name('permission.sync'); Route::post('/permissions/sync/{id_role}', [PermissionController::class, 'sync'])->name('permission.sync');