logo name
This commit is contained in:
parent
b2c5d494ab
commit
780492d9b4
|
|
@ -48,7 +48,7 @@ public function headings(): array
|
|||
|
||||
return [
|
||||
['LAPORAN REKAPITULASI LEMBUR PEGAWAI'],
|
||||
['MPG HRIS Enterprise System'],
|
||||
['HRIS MP Enterprise System'],
|
||||
['Periode: ' . $namaBulan . ' ' . $this->tahun],
|
||||
['Dicetak: ' . Carbon::now()->translatedFormat('d F Y, H:i') . ' WIB'],
|
||||
[],
|
||||
|
|
@ -215,7 +215,7 @@ public function registerEvents(): array
|
|||
]);
|
||||
|
||||
$noteRow = $summaryRow + 2;
|
||||
$sheet->setCellValue("A{$noteRow}", '* Laporan dibuat otomatis oleh sistem MPG HRIS. Data bersumber dari catatan lembur yang telah disetujui.');
|
||||
$sheet->setCellValue("A{$noteRow}", '* Laporan dibuat otomatis oleh sistem HRIS MP. Data bersumber dari catatan lembur yang telah disetujui.');
|
||||
$sheet->getStyle("A{$noteRow}")->getFont()->setItalic(true)->setSize(8)->getColor()->setRGB('94A3B8');
|
||||
$sheet->mergeCells("A{$noteRow}:I{$noteRow}");
|
||||
},
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public function headings(): array
|
|||
|
||||
return [
|
||||
['LAPORAN REKAPITULASI PRESENSI PEGAWAI'],
|
||||
['MPG HRIS Enterprise System'],
|
||||
['HRIS MP Enterprise System'],
|
||||
['Periode: ' . $namaBulan . ' ' . $this->tahun],
|
||||
['Dicetak: ' . Carbon::now()->translatedFormat('d F Y, H:i') . ' WIB'],
|
||||
[],
|
||||
|
|
@ -239,7 +239,7 @@ public function registerEvents(): array
|
|||
|
||||
// Catatan kaki
|
||||
$noteRow = $summaryRow + 2;
|
||||
$sheet->setCellValue("A{$noteRow}", '* Laporan dibuat otomatis oleh sistem MPG HRIS. Data bersumber dari catatan presensi dan lembur bulan berjalan.');
|
||||
$sheet->setCellValue("A{$noteRow}", '* Laporan dibuat otomatis oleh sistem HRIS MP. Data bersumber dari catatan presensi dan lembur bulan berjalan.');
|
||||
$sheet->getStyle("A{$noteRow}")->getFont()->setItalic(true)->setSize(8)->getColor()->setRGB('94A3B8');
|
||||
$sheet->mergeCells("A{$noteRow}:K{$noteRow}");
|
||||
},
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ public function index(Request $request)
|
|||
if (Storage::disk('local')->exists($datasetPath)) {
|
||||
$files = Storage::disk('local')->files($datasetPath);
|
||||
foreach ($files as $file) {
|
||||
if (preg_match('/frame_\d+\.jpg$/', $file)) {
|
||||
if (preg_match('/\/frame_\d+\.jpg$/', $file)) {
|
||||
$frameList[] = $file;
|
||||
}
|
||||
}
|
||||
|
|
@ -153,9 +153,12 @@ public function reset($id)
|
|||
|
||||
public function showFrame($userId, $frameIndex)
|
||||
{
|
||||
$rawFilePath = "face_datasets/{$userId}/raw_frame_{$frameIndex}.jpg";
|
||||
$filePath = "face_datasets/{$userId}/frame_{$frameIndex}.jpg";
|
||||
|
||||
if (Storage::disk('local')->exists($filePath)) {
|
||||
if (Storage::disk('local')->exists($rawFilePath)) {
|
||||
return response()->file(Storage::disk('local')->path($rawFilePath));
|
||||
} elseif (Storage::disk('local')->exists($filePath)) {
|
||||
return response()->file(Storage::disk('local')->path($filePath));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,8 +107,8 @@ private function generateIdKaryawan($tglBergabung, $idDivisi, $idJabatan)
|
|||
|
||||
$nomorUrut = str_pad($nextNumber, 3, '0', STR_PAD_LEFT);
|
||||
|
||||
// Format: MPG-202603-ITST-001
|
||||
return "MPG-{$yearMonth}-{$kodeTengah}-{$nomorUrut}";
|
||||
// Format: MP-202603-ITST-001
|
||||
return "MP-{$yearMonth}-{$kodeTengah}-{$nomorUrut}";
|
||||
}
|
||||
|
||||
public function store(StorePegawaiRequest $request)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ protected static function booted()
|
|||
|
||||
if (empty($model->nomor_surat)) {
|
||||
$count = static::whereYear('created_at', date('Y'))->count() + 1;
|
||||
$model->nomor_surat = sprintf('%03d/MPG/IZN/%s', $count, date('Y'));
|
||||
$model->nomor_surat = sprintf('%03d/MP/IZN/%s', $count, date('Y'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ public function run()
|
|||
$hrd = User::updateOrCreate(
|
||||
['email' => 'hrd@mpg.co.id'],
|
||||
[
|
||||
'nik' => 'MPG-202401-HRMG-001',
|
||||
'nik' => 'MP-202401-HRMG-001',
|
||||
'nama_lengkap' => 'HRD Manager',
|
||||
'password' => Hash::make('Mpg123!'),
|
||||
'status_aktif' => 1,
|
||||
|
|
@ -69,7 +69,7 @@ public function run()
|
|||
$pegawai = User::updateOrCreate(
|
||||
['email' => 'budi@mpg.co.id'],
|
||||
[
|
||||
'nik' => 'MPG-202401-HRST-001',
|
||||
'nik' => 'MP-202401-HRST-001',
|
||||
'nama_lengkap' => 'Budi Santoso',
|
||||
'password' => Hash::make('Mpg123!'),
|
||||
'status_aktif' => 1,
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 26 KiB |
|
|
@ -61,10 +61,10 @@ def detect_face(gray_frame):
|
|||
return faces[0]
|
||||
|
||||
|
||||
def process_frame(gray_frame):
|
||||
def process_frame(frame, gray_frame):
|
||||
face_rect = detect_face(gray_frame)
|
||||
if face_rect is None:
|
||||
return None, "no_face"
|
||||
return None, None, "no_face"
|
||||
|
||||
(x, y, w, h) = face_rect
|
||||
|
||||
|
|
@ -74,18 +74,19 @@ def process_frame(gray_frame):
|
|||
x2 = min(gray_frame.shape[1], x + w + padding)
|
||||
y2 = min(gray_frame.shape[0], y + h + padding)
|
||||
|
||||
face_crop = gray_frame[y1:y2, x1:x2]
|
||||
face_crop_gray = gray_frame[y1:y2, x1:x2]
|
||||
face_crop_color = frame[y1:y2, x1:x2]
|
||||
|
||||
face_resized = cv2.resize(face_crop, FACE_SIZE, interpolation=cv2.INTER_AREA)
|
||||
face_resized = cv2.resize(face_crop_gray, FACE_SIZE, interpolation=cv2.INTER_AREA)
|
||||
|
||||
blur_score = get_blur_score(face_resized)
|
||||
if blur_score < BLUR_THRESHOLD:
|
||||
return None, f"blur ({round(blur_score, 1)})"
|
||||
return None, None, f"blur ({round(blur_score, 1)})"
|
||||
|
||||
face_denoised = cv2.GaussianBlur(face_resized, (3, 3), 0)
|
||||
face_final = apply_clahe(face_denoised)
|
||||
|
||||
return face_final, "ok"
|
||||
return face_final, face_crop_color, "ok"
|
||||
|
||||
|
||||
def extract_frames(video_path, output_dir, max_frames=100):
|
||||
|
|
@ -127,7 +128,7 @@ def extract_frames(video_path, output_dir, max_frames=100):
|
|||
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
face_img, status = process_frame(gray)
|
||||
face_img, face_color, status = process_frame(frame, gray)
|
||||
|
||||
if face_img is None:
|
||||
if "blur" in status:
|
||||
|
|
@ -138,7 +139,9 @@ def extract_frames(video_path, output_dir, max_frames=100):
|
|||
continue
|
||||
|
||||
filename = f"frame_{saved_count:03d}.jpg"
|
||||
filename_raw = f"raw_frame_{saved_count:03d}.jpg"
|
||||
cv2.imwrite(os.path.join(output_dir, filename), face_img)
|
||||
cv2.imwrite(os.path.join(output_dir, filename_raw), face_color)
|
||||
saved_count += 1
|
||||
|
||||
frame_idx += 1
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html lang="id" class="h-full bg-white">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Login Administrator - Absensi Digital</title>
|
||||
<title>Login Administrator - HRIS MP</title>
|
||||
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ class="absolute inset-0 h-full w-full object-cover"
|
|||
<div class="flex-1 flex flex-col justify-center py-12 px-4 sm:px-6 lg:px-20 xl:px-24 bg-white">
|
||||
<div class="mx-auto w-full max-w-sm lg:w-96">
|
||||
|
||||
<div class="mb-8">
|
||||
<div class="mb-8 text-center flex flex-col items-center">
|
||||
<h2 class="text-3xl font-extrabold text-[#130F26] tracking-tight">Sign in</h2>
|
||||
<p class="mt-2 text-sm text-slate-500">
|
||||
Masuk menggunakan akun administrator Anda.
|
||||
|
|
|
|||
|
|
@ -141,25 +141,36 @@ class="!mb-0" />
|
|||
<td class="px-6 py-4">
|
||||
@if($faceStatus !== 'unregistered')
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
@php
|
||||
$poses = ['depan' => 'Depan', 'kanan' => 'Kanan', 'kiri' => 'Kiri', 'bawah' => 'Bawah'];
|
||||
@endphp
|
||||
@foreach($poses as $poseKey => $poseLabel)
|
||||
@if(isset($user->face_photos[$poseKey]))
|
||||
<div class="relative group cursor-pointer" onclick="openFacePreview('{{ route('face.photo', [$user->id, $poseKey]) }}', '{{ $user->nama_lengkap }}', '{{ $poseLabel }}')">
|
||||
<img src="{{ route('face.photo', [$user->id, $poseKey]) }}"
|
||||
@if(isset($user->face_frames) && $user->face_frame_count > 0)
|
||||
@php
|
||||
// Ambil 4 frame representatif (atau kurang jika tidak sampai 4)
|
||||
$frameCount = $user->face_frame_count;
|
||||
$step = max(1, floor($frameCount / 4));
|
||||
$selectedFrames = [];
|
||||
|
||||
for ($i = 0; $i < $frameCount; $i += $step) {
|
||||
if (count($selectedFrames) < 4) {
|
||||
// Extract "01" dari "face_datasets/1/frame_01.jpg"
|
||||
if (preg_match('/frame_(\d+)\.jpg$/', $user->face_frames[$i], $matches)) {
|
||||
$selectedFrames[] = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
@foreach($selectedFrames as $index => $frameIdx)
|
||||
<div class="relative group cursor-pointer" onclick="openFacePreview('{{ route('face.frame', [$user->id, $frameIdx]) }}', '{{ $user->nama_lengkap }}', 'Frame {{ $frameIdx }}')">
|
||||
<img src="{{ route('face.frame', [$user->id, $frameIdx]) }}"
|
||||
class="w-12 h-12 rounded-lg object-cover border-2 border-slate-200 group-hover:border-primary transition-colors shadow-sm">
|
||||
<span class="absolute -bottom-1 left-1/2 -translate-x-1/2 text-[9px] font-bold bg-slate-800 text-white px-1.5 py-0.5 rounded-full leading-none whitespace-nowrap">{{ $poseLabel }}</span>
|
||||
<span class="absolute -bottom-1 left-1/2 -translate-x-1/2 text-[9px] font-bold bg-slate-800 text-white px-1.5 py-0.5 rounded-full leading-none whitespace-nowrap">Fr {{ $frameIdx }}</span>
|
||||
</div>
|
||||
@else
|
||||
<div class="w-12 h-12 rounded-lg bg-slate-100 border-2 border-dashed border-slate-300 flex items-center justify-center relative">
|
||||
<svg class="w-4 h-4 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z"></path>
|
||||
</svg>
|
||||
<span class="absolute -bottom-1 left-1/2 -translate-x-1/2 text-[9px] font-bold bg-slate-400 text-white px-1.5 py-0.5 rounded-full leading-none whitespace-nowrap">{{ $poseLabel }}</span>
|
||||
</div>
|
||||
@endif
|
||||
@endforeach
|
||||
@endforeach
|
||||
@else
|
||||
<div class="text-xs text-slate-400 italic flex items-center justify-center">
|
||||
<svg class="w-4 h-4 mr-1 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"></path></svg>
|
||||
Memproses...
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<div class="text-center text-xs text-slate-400 italic">Belum ada foto</div>
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@
|
|||
{{-- KOP SURAT --}}
|
||||
<div class="kop">
|
||||
<div class="kop-left">
|
||||
<div class="company-name">MPG HRIS Enterprise System</div>
|
||||
<div class="company-name">HRIS MP Enterprise System</div>
|
||||
<div class="company-sub">Human Resource Information System</div>
|
||||
</div>
|
||||
<div class="kop-right">
|
||||
|
|
@ -337,7 +337,7 @@
|
|||
{{-- FOOTER --}}
|
||||
<div class="footer-area">
|
||||
<div class="footer-left">
|
||||
<p>* Laporan ini dibuat secara otomatis oleh sistem MPG HRIS.</p>
|
||||
<p>* Laporan ini dibuat secara otomatis oleh sistem HRIS MP.</p>
|
||||
<p>* Data bersumber dari catatan presensi dan lembur bulan berjalan.</p>
|
||||
</div>
|
||||
<div class="footer-right">
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@
|
|||
class="fixed inset-y-0 left-0 w-72 bg-white border-r border-slate-200 flex flex-col h-full transition-transform duration-300 font-sans z-[100] shadow-xl lg:shadow-sm lg:static lg:flex-shrink-0">
|
||||
|
||||
<div class="flex items-center justify-center h-28 border-b border-slate-100 bg-white">
|
||||
<div class="text-center">
|
||||
<span class="block text-3xl font-extrabold tracking-tight text-[#130F26]">
|
||||
MPG<span class="text-blue-600">HRIS</span>
|
||||
</span>
|
||||
<span class="text-[10px] font-bold text-slate-400 uppercase tracking-[0.2em] mt-1 block">Enterprise System</span>
|
||||
<div class="text-center px-4 pt-2">
|
||||
<img src="{{ asset('logo.png') }}" class="h-20 w-auto mx-auto object-contain border-none shadow-none" alt="HRIS MP Logo">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue