Roles HRD, SPV, MNGR, STAFF
This commit is contained in:
parent
d6c09fe1ae
commit
99dfe31f64
|
|
@ -19,7 +19,7 @@ public function index(Request $request)
|
|||
{
|
||||
$query = User::with(['divisi', 'jabatan', 'kantor', 'roles'])
|
||||
->whereDoesntHave('roles', function ($q) {
|
||||
$q->where('nama_role', 'admin');
|
||||
$q->where('nama_role', 'hrd');
|
||||
});
|
||||
|
||||
if ($request->filled('filter_jabatan')) {
|
||||
|
|
@ -49,7 +49,7 @@ public function index(Request $request)
|
|||
$allKantor = Kantor::withCount([
|
||||
'users as total_pegawai' => function ($q) {
|
||||
$q->whereDoesntHave('roles', function ($sq) {
|
||||
$sq->where('nama_role', 'admin');
|
||||
$sq->where('nama_role', 'hrd');
|
||||
});
|
||||
}
|
||||
])->get();
|
||||
|
|
@ -57,11 +57,11 @@ public function index(Request $request)
|
|||
$stats = [
|
||||
'kantor_list' => $allKantor,
|
||||
'total' => User::whereDoesntHave('roles', function ($q) {
|
||||
$q->where('nama_role', 'admin');
|
||||
$q->where('nama_role', 'hrd');
|
||||
})->count(),
|
||||
'active' => User::where('status_aktif', 1)
|
||||
->whereDoesntHave('roles', function ($q) {
|
||||
$q->where('nama_role', 'admin');
|
||||
$q->where('nama_role', 'hrd');
|
||||
})->count(),
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public function index()
|
|||
public function create()
|
||||
{
|
||||
$pegawai = User::with('kantor')->whereDoesntHave('roles', function ($q) {
|
||||
$q->where('nama_role', 'admin')->orWhere('nama_role', 'Admin');
|
||||
$q->where('nama_role', 'hrd');
|
||||
})->get();
|
||||
|
||||
$kantor = \App\Models\Kantor::orderBy('nama_kantor', 'asc')->get();
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ public function authorize(): bool
|
|||
{
|
||||
|
||||
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';
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -111,14 +111,14 @@ public function hasPermission($permissionSlug): bool
|
|||
public function isGlobalAdmin(): bool
|
||||
{
|
||||
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
|
||||
{
|
||||
return $this->roles->contains(function ($role) {
|
||||
return in_array(strtolower($role->nama_role), ['super admin', 'super_admin']);
|
||||
return strtolower($role->nama_role) === 'hrd';
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@ public function enrollFace($userId, array $photos)
|
|||
->where('id', $userId)
|
||||
->update(['is_face_registered' => 1]);
|
||||
|
||||
$trainingSuccess = false;
|
||||
|
||||
try {
|
||||
$pythonPath = env('PYTHON_PATH', 'python');
|
||||
$scriptPath = base_path('python_scripts/train_face.py');
|
||||
|
|
@ -73,22 +75,26 @@ public function enrollFace($userId, array $photos)
|
|||
$process->run();
|
||||
|
||||
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 {
|
||||
$output = json_decode($process->getOutput(), true);
|
||||
if (!isset($output['status']) || $output['status'] !== 'success') {
|
||||
\Illuminate\Support\Facades\Log::warning("Face Training Failed (silently caught): " . ($output['message'] ?? 'Unknown Error'));
|
||||
if (isset($output['status']) && $output['status'] === 'success') {
|
||||
$trainingSuccess = true;
|
||||
} else {
|
||||
\Illuminate\Support\Facades\Log::warning("Face Training Failed: " . ($output['message'] ?? 'Unknown Error'));
|
||||
}
|
||||
}
|
||||
} 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";
|
||||
|
||||
// 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([
|
||||
'path_model_yml' => $relativeModelPath,
|
||||
'is_verified' => 0,
|
||||
'is_verified' => $trainingSuccess ? 1 : 0,
|
||||
]);
|
||||
|
||||
DB::commit();
|
||||
|
|
|
|||
|
|
@ -2,46 +2,27 @@
|
|||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DatabaseSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
// Panggil MasterDataSeeder terlebih dahulu untuk data dasar (Divisi, Jabatan, Kantor, Role, User Admin)
|
||||
$this->call([
|
||||
// 1. Data master: Role, Divisi, Jabatan, Kantor, User HRD & contoh staff
|
||||
MasterDataSeeder::class,
|
||||
]);
|
||||
|
||||
// Tambahan data demo jika diperlukan (Opsional)
|
||||
$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([
|
||||
// 2. Permission per role
|
||||
PermissionSeeder::class,
|
||||
|
||||
// 3. Data lookup / referensi
|
||||
PresensiStatusSeeder::class,
|
||||
PresensiSeeder::class,
|
||||
JenisIzinSeeder::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,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,31 +3,12 @@
|
|||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use App\Models\User;
|
||||
use App\Models\Role;
|
||||
|
||||
class FixLegacyRolesSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
|
||||
$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}");
|
||||
}
|
||||
}
|
||||
$this->command->info('Tidak ada migrasi legacy yang perlu dilakukan (sistem sudah menggunakan pivot roles).');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,61 +26,62 @@ public function run()
|
|||
$kPusat = Kantor::firstOrCreate(
|
||||
['nama_kantor' => 'Kantor Pusat'],
|
||||
[
|
||||
'alamat' => 'Jl. Jendral Sudirman No. 1, Jakarta',
|
||||
'latitude' => -6.2088,
|
||||
'alamat' => 'Jl. Jendral Sudirman No. 1, Jakarta',
|
||||
'latitude' => -6.2088,
|
||||
'longitude' => 106.8456,
|
||||
'radius' => 200
|
||||
'radius' => 200
|
||||
]
|
||||
);
|
||||
|
||||
$kCabang = Kantor::firstOrCreate(
|
||||
['nama_kantor' => 'Curah Manis Studio'],
|
||||
[
|
||||
'alamat' => 'Jl. Curah Manis, Malang',
|
||||
'latitude' => -7.9839,
|
||||
'alamat' => 'Jl. Curah Manis, Malang',
|
||||
'latitude' => -7.9839,
|
||||
'longitude' => 112.6214,
|
||||
'radius' => 200
|
||||
'radius' => 200
|
||||
]
|
||||
);
|
||||
|
||||
// Roles
|
||||
$roleAdmin = \App\Models\Role::firstOrCreate(['nama_role' => 'admin']);
|
||||
$roleHrd = \App\Models\Role::firstOrCreate(['nama_role' => 'hrd']);
|
||||
$roleManager = \App\Models\Role::firstOrCreate(['nama_role' => 'manager']);
|
||||
$rolePegawai = \App\Models\Role::firstOrCreate(['nama_role' => 'pegawai']);
|
||||
$roleHrd = \App\Models\Role::firstOrCreate(['nama_role' => 'hrd']);
|
||||
$roleManager = \App\Models\Role::firstOrCreate(['nama_role' => 'manager']);
|
||||
$roleSupervisor = \App\Models\Role::firstOrCreate(['nama_role' => 'supervisor']);
|
||||
$roleStaff = \App\Models\Role::firstOrCreate(['nama_role' => 'staff']);
|
||||
|
||||
$admin = User::updateOrCreate(
|
||||
['email' => 'admin@mpg.co.id'],
|
||||
$hrd = User::updateOrCreate(
|
||||
['nik' => '999999999'],
|
||||
[
|
||||
'nama_lengkap' => 'Super Administrator',
|
||||
'password' => Hash::make('admin123'),
|
||||
'nik' => '999999999',
|
||||
'status_aktif' => 1,
|
||||
'id_divisi' => $divIT->id_divisi,
|
||||
'id_jabatan' => $jabMgr->id_jabatan,
|
||||
'id_kantor' => $kPusat->id_kantor,
|
||||
'nama_lengkap' => 'HRD Manager',
|
||||
'email' => 'hrd@mpg.co.id',
|
||||
'password' => Hash::make('Mpg123!'),
|
||||
'status_aktif' => 1,
|
||||
'id_divisi' => $divHR->id_divisi,
|
||||
'id_jabatan' => $jabMgr->id_jabatan,
|
||||
'id_kantor' => $kPusat->id_kantor,
|
||||
'tgl_bergabung' => now(),
|
||||
'sisa_cuti' => 12,
|
||||
]
|
||||
);
|
||||
if (!$admin->roles()->where('nama_role', 'admin')->exists()) {
|
||||
$admin->roles()->attach($roleAdmin->id_role);
|
||||
if (!$hrd->roles()->where('nama_role', 'hrd')->exists()) {
|
||||
$hrd->roles()->attach($roleHrd->id_role);
|
||||
}
|
||||
|
||||
$pegawai = User::updateOrCreate(
|
||||
['email' => 'budi@mpg.co.id'],
|
||||
[
|
||||
'nama_lengkap' => 'Budi Santoso',
|
||||
'password' => Hash::make('Mpg123!'),
|
||||
'nik' => '350712345678',
|
||||
'status_aktif' => 1,
|
||||
'id_divisi' => $divHR->id_divisi,
|
||||
'id_jabatan' => $jabStf->id_jabatan,
|
||||
'id_kantor' => $kCabang->id_kantor,
|
||||
'nama_lengkap' => 'Budi Santoso',
|
||||
'password' => Hash::make('Mpg123!'),
|
||||
'nik' => '350712345678',
|
||||
'status_aktif' => 1,
|
||||
'id_divisi' => $divHR->id_divisi,
|
||||
'id_jabatan' => $jabStf->id_jabatan,
|
||||
'id_kantor' => $kCabang->id_kantor,
|
||||
'tgl_bergabung' => now(),
|
||||
'sisa_cuti' => 12,
|
||||
]
|
||||
);
|
||||
if (!$pegawai->roles()->where('nama_role', 'pegawai')->exists()) {
|
||||
$pegawai->roles()->attach($rolePegawai->id_role);
|
||||
if (!$pegawai->roles()->where('nama_role', 'staff')->exists()) {
|
||||
$pegawai->roles()->attach($roleStaff->id_role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,30 +5,34 @@
|
|||
use Illuminate\Database\Seeder;
|
||||
use App\Models\Permission;
|
||||
use App\Models\Role;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class PermissionSeeder extends Seeder
|
||||
{
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
|
||||
$permissions = [
|
||||
|
||||
'view_dashboard',
|
||||
|
||||
// Data Master
|
||||
'manage_divisi',
|
||||
'manage_jabatan',
|
||||
'manage_kantor',
|
||||
'manage_shift',
|
||||
'manage_hari_libur',
|
||||
'manage_cuti',
|
||||
|
||||
// Data Pegawai
|
||||
'view_pegawai',
|
||||
'create_pegawai',
|
||||
'edit_pegawai',
|
||||
'delete_pegawai',
|
||||
'view_pegawai_detail',
|
||||
|
||||
// Penjadwalan
|
||||
'view_jadwal',
|
||||
'manage_jadwal',
|
||||
|
||||
// Presensi
|
||||
'view_presensi_all',
|
||||
'view_presensi_team',
|
||||
'view_presensi_self',
|
||||
|
|
@ -36,20 +40,37 @@ public function run(): void
|
|||
'approve_presensi',
|
||||
'correction_presensi',
|
||||
|
||||
// Izin
|
||||
'view_izin_all',
|
||||
'view_izin_team',
|
||||
'create_izin',
|
||||
'approve_izin',
|
||||
|
||||
// Surat Izin
|
||||
'view_surat_izin',
|
||||
'approve_surat_izin',
|
||||
|
||||
// Lembur
|
||||
'view_lembur_all',
|
||||
'view_lembur_team',
|
||||
'create_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',
|
||||
|
||||
'view_laporan',
|
||||
|
||||
// Sistem
|
||||
'manage_users',
|
||||
'manage_roles',
|
||||
'manage_permissions',
|
||||
|
|
@ -62,49 +83,50 @@ public function run(): void
|
|||
);
|
||||
}
|
||||
|
||||
$adminRole = Role::where('nama_role', 'admin')->first();
|
||||
if ($adminRole) {
|
||||
$allPermissions = Permission::all();
|
||||
$adminRole->permissions()->sync($allPermissions);
|
||||
}
|
||||
|
||||
// ─── HRD ─── akses penuh ke semua permission
|
||||
$hrdRole = Role::where('nama_role', 'hrd')->first();
|
||||
if ($hrdRole) {
|
||||
$hrdPermissions = Permission::whereIn('nama_permission', [
|
||||
'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);
|
||||
$hrdRole->permissions()->sync(Permission::all());
|
||||
}
|
||||
|
||||
// ─── MANAGER ─── approve presensi & izin, lihat laporan kehadiran & izin
|
||||
$managerRole = Role::where('nama_role', 'manager')->first();
|
||||
if ($managerRole) {
|
||||
$managerPermissions = Permission::whereIn('nama_permission', [
|
||||
$perms = Permission::whereIn('nama_permission', [
|
||||
'view_dashboard',
|
||||
'view_pegawai', 'view_pegawai_detail',
|
||||
'view_presensi_team',
|
||||
'view_jadwal',
|
||||
'view_presensi_team', 'approve_presensi',
|
||||
'view_izin_team', 'approve_izin',
|
||||
'view_lembur_team', 'approve_lembur'
|
||||
'view_surat_izin', 'approve_surat_izin',
|
||||
'view_laporan',
|
||||
'view_laporan_izin',
|
||||
])->get();
|
||||
$managerRole->permissions()->sync($managerPermissions);
|
||||
$managerRole->permissions()->sync($perms);
|
||||
}
|
||||
|
||||
$pegawaiRole = Role::where('nama_role', 'pegawai')->first();
|
||||
if ($pegawaiRole) {
|
||||
$pegawaiPermissions = Permission::whereIn('nama_permission', [
|
||||
// ─── SUPERVISOR ─── approve presensi, lihat laporan kehadiran & penjadwalan
|
||||
$supervisorRole = Role::where('nama_role', 'supervisor')->first();
|
||||
if ($supervisorRole) {
|
||||
$perms = Permission::whereIn('nama_permission', [
|
||||
'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',
|
||||
'create_presensi',
|
||||
'create_izin',
|
||||
'create_lembur'
|
||||
'create_lembur',
|
||||
])->get();
|
||||
$pegawaiRole->permissions()->sync($pegawaiPermissions);
|
||||
$staffRole->permissions()->sync($perms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,53 +3,17 @@
|
|||
namespace Database\Seeders;
|
||||
|
||||
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
|
||||
{
|
||||
public function run()
|
||||
public function run(): void
|
||||
{
|
||||
|
||||
$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');
|
||||
$this->command->info('SuperAdminSeeder: tidak melakukan apa-apa (lihat MasterDataSeeder).');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,15 +11,27 @@ class="fixed inset-y-0 left-0 w-72 bg-white border-r border-slate-200 flex flex-
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@php
|
||||
$isAdmin = Auth::user()->roles->contains(function ($role) {
|
||||
return strtolower($role->nama_role) === 'admin';
|
||||
});
|
||||
$isSuperAdmin = Auth::user()->isSuperAdmin();
|
||||
$isAdminOrSuperAdmin = Auth::user()->isGlobalAdmin();
|
||||
@endphp
|
||||
@php
|
||||
$roleNama = strtolower(Auth::user()->roles->first()?->nama_role ?? '');
|
||||
$isHrd = $roleNama === 'hrd';
|
||||
$isManager = $roleNama === 'manager';
|
||||
$isSupervisor = $roleNama === 'supervisor';
|
||||
$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
|
||||
|
||||
<nav class="flex-1 px-4 py-6 space-y-2 overflow-y-auto no-scrollbar">
|
||||
|
||||
{{-- ── Dashboard ── --}}
|
||||
<div class="space-y-1">
|
||||
<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' }}">
|
||||
|
|
@ -33,7 +45,8 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
|
|||
</a>
|
||||
</div>
|
||||
|
||||
@if($isAdminOrSuperAdmin)
|
||||
{{-- ════════════════════════════════ SEKSI: MANAJEMEN ════════════════════════════════ --}}
|
||||
@if($canManage || $canViewPegawai)
|
||||
<div class="pt-6 pb-3 px-4 flex items-center gap-3">
|
||||
<div class="h-px bg-slate-200 flex-1"></div>
|
||||
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Manajemen</span>
|
||||
|
|
@ -41,47 +54,56 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
|
|||
</div>
|
||||
|
||||
<div class="space-y-1">
|
||||
@if($isSuperAdmin)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Verifikasi Wajah</span>
|
||||
@php $pendingFace = \App\Models\User::where('is_face_registered', 0)->whereHas('dataWajah')->count(); @endphp
|
||||
@if($pendingFace > 0)
|
||||
<span
|
||||
class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingFace }}</span>
|
||||
|
||||
{{-- Verifikasi Wajah – HRD only --}}
|
||||
@if($isHrd)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Verifikasi Wajah</span>
|
||||
@php $pendingFace = \App\Models\User::where('is_face_registered', 0)->whereHas('dataWajah')->count(); @endphp
|
||||
@if($pendingFace > 0)
|
||||
<span class="ml-auto bg-red-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingFace }}</span>
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Data Karyawan</span>
|
||||
</a>
|
||||
{{-- Data Karyawan – HRD & Manager --}}
|
||||
@if($canViewPegawai)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Data Karyawan</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Penjadwalan – HRD, Manager, Supervisor --}}
|
||||
@if($canViewJadwal)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Penjadwalan</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Penjadwalan</span>
|
||||
</a>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if($isAdminOrSuperAdmin)
|
||||
{{-- ════════════════════════════════ SEKSI: ABSENSI ════════════════════════════════ --}}
|
||||
@if($canViewLaporan || $canViewPresensi)
|
||||
<div class="pt-6 pb-3 px-4 flex items-center gap-3">
|
||||
<div class="h-px bg-slate-200 flex-1"></div>
|
||||
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-widest">Absensi</span>
|
||||
|
|
@ -89,126 +111,145 @@ class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group
|
|||
</div>
|
||||
|
||||
<div class="space-y-1">
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Kehadiran</span>
|
||||
</a>
|
||||
|
||||
@if($isAdminOrSuperAdmin)
|
||||
<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' }}">
|
||||
<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"
|
||||
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" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Lembur</span>
|
||||
</a>
|
||||
{{-- Laporan Kehadiran – HRD, Manager, Supervisor --}}
|
||||
@if($canViewLaporan)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 17v-2m3 2v-4m3 4v-6m2 10H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Kehadiran</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Laporan Lembur – HRD only --}}
|
||||
@if($isHrd)
|
||||
<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' }}">
|
||||
<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"
|
||||
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" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Lembur</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Laporan Izin/Cuti – HRD & Manager --}}
|
||||
@if($canViewLaporanIzin)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Izin/Cuti</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Monitoring Presensi – HRD, Manager, Supervisor --}}
|
||||
@if($canViewPresensi)
|
||||
<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' }}">
|
||||
<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">
|
||||
<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>
|
||||
<span class="flex-1 font-semibold text-sm">Monitoring Presensi</span>
|
||||
@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">{{ $pendingPresensi }}</span>
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Manajemen Izin – HRD & Manager --}}
|
||||
@if($canApproveIzin)
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Manajemen Izin</span>
|
||||
@php $pendingIzin = \App\Models\PengajuanIzin::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingIzin > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingIzin }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
{{-- Surat Izin – HRD & Manager --}}
|
||||
<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' }}">
|
||||
<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"
|
||||
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>
|
||||
<span class="flex-1 font-semibold text-sm">Surat Izin</span>
|
||||
@php $pendingSurat = \App\Models\SuratIzin::whereIn('status_surat', ['menunggu_manajer', 'menunggu_hrd'])->count(); @endphp
|
||||
@if($pendingSurat > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingSurat }}</span>
|
||||
@endif
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Lembur & Poin – HRD only --}}
|
||||
@if($isHrd)
|
||||
<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' }}">
|
||||
<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"
|
||||
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>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Lembur & Poin</span>
|
||||
@php $pendingLembur = \App\Models\Lembur::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingLembur > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingLembur }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
<a href="{{ route('penggunaan-poin.index') }}"
|
||||
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('penggunaan-poin.*') ? '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('penggunaan-poin.*') ? '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="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Persetujuan Poin</span>
|
||||
@php $pendingPoin = \App\Models\PenggunaanPoin::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingPoin > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingPoin }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
{{-- 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
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span class="font-semibold text-sm">Laporan Izin/Cuti</span>
|
||||
</a>
|
||||
|
||||
<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' }}">
|
||||
<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">
|
||||
<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>
|
||||
|
||||
<span class="flex-1 font-semibold text-sm">Monitoring Presensi</span>
|
||||
|
||||
@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">
|
||||
{{ $pendingPresensi }}
|
||||
</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Manajemen Izin</span>
|
||||
@php $pendingIzin = \App\Models\PengajuanIzin::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingIzin > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingIzin }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
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>
|
||||
<span class="flex-1 font-semibold text-sm">Surat Izin</span>
|
||||
@php $pendingSurat = \App\Models\SuratIzin::whereIn('status_surat', ['menunggu_manajer', 'menunggu_hrd'])->count(); @endphp
|
||||
@if($pendingSurat > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingSurat }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
<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>
|
||||
|
||||
<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' }}">
|
||||
<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"
|
||||
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>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Lembur & Poin</span>
|
||||
@php $pendingLembur = \App\Models\Lembur::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingLembur > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingLembur }}</span>
|
||||
@endif
|
||||
</a>
|
||||
|
||||
<a href="{{ route('penggunaan-poin.index') }}"
|
||||
class="flex items-center px-4 py-3 rounded-xl transition-all duration-200 group {{ request()->routeIs('penggunaan-poin.*') ? '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('penggunaan-poin.*') ? '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="M9 12l2 2 4-4M7.835 4.697a3.42 3.42 0 001.946-.806 3.42 3.42 0 014.438 0 3.42 3.42 0 001.946.806 3.42 3.42 0 013.138 3.138 3.42 3.42 0 00.806 1.946 3.42 3.42 0 010 4.438 3.42 3.42 0 00-.806 1.946 3.42 3.42 0 01-3.138 3.138 3.42 3.42 0 00-1.946.806 3.42 3.42 0 01-4.438 0 3.42 3.42 0 00-1.946-.806 3.42 3.42 0 01-3.138-3.138 3.42 3.42 0 00-.806-1.946 3.42 3.42 0 010-4.438 3.42 3.42 0 00.806-1.946 3.42 3.42 0 013.138-3.138z">
|
||||
</path>
|
||||
</svg>
|
||||
<span class="flex-1 font-semibold text-sm">Persetujuan Poin</span>
|
||||
@php $pendingPoin = \App\Models\PenggunaanPoin::where('id_status', 1)->count(); @endphp
|
||||
@if($pendingPoin > 0)
|
||||
<span class="ml-auto bg-orange-500 text-white text-[10px] font-bold px-2 py-0.5 rounded-full">{{ $pendingPoin }}</span>
|
||||
@endif
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{{-- ════════════════════════════════ SEKSI: DATA MASTER (HRD only) ════════════════════════════════ --}}
|
||||
@if($isHrd)
|
||||
<div x-data="{ open: {{ request()->routeIs('divisi.*', 'jabatan.*', 'kantor.*', 'role.*', 'shift.*', 'hari-libur.*', 'cuti.*') ? 'true' : 'false' }} }"
|
||||
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
|
||||
</a>
|
||||
|
||||
@if($isSuperAdmin)
|
||||
<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' }}">
|
||||
Data Role
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<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' }}">
|
||||
|
|
@ -266,7 +305,7 @@ class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs
|
|||
class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('hari-libur.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}">
|
||||
Hari Libur
|
||||
</a>
|
||||
|
||||
|
||||
<a href="{{ route('cuti.index') }}"
|
||||
class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs('cuti.*') ? 'bg-slate-100 text-[#130F26] font-bold border-l-4 border-[#130F26]' : 'text-slate-500 hover:text-slate-900 hover:bg-slate-50' }}">
|
||||
Sisa Cuti Pegawai
|
||||
|
|
@ -276,6 +315,8 @@ class="block py-2.5 px-4 text-sm rounded-lg transition-all {{ request()->routeIs
|
|||
@endif
|
||||
|
||||
</nav>
|
||||
|
||||
{{-- ── Footer: Pengaturan Akun & Logout ── --}}
|
||||
<div class="px-8 py-6 border-t border-slate-100 mt-auto bg-slate-50/50">
|
||||
<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' }}">
|
||||
|
|
@ -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;
|
||||
}
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@extends('layouts.app')
|
||||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Monitoring Presensi')
|
||||
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<x-page-header title="Monitoring Presensi" subtitle="Pantau kehadiran pegawai harian.">
|
||||
<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]">
|
||||
<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>
|
||||
|
|
@ -212,7 +212,7 @@ class="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-bold
|
|||
</button>
|
||||
@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">
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -74,11 +74,10 @@
|
|||
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('jabatan', JabatanController::class);
|
||||
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('jadwal', \App\Http\Controllers\JadwalController::class)->except(['edit', 'show']);
|
||||
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::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::post('/permissions', [PermissionController::class, 'store'])->name('permission.store');
|
||||
Route::post('/permissions/sync/{id_role}', [PermissionController::class, 'sync'])->name('permission.sync');
|
||||
|
|
|
|||
Loading…
Reference in New Issue