membuat code pengembangan, merubah status menjadi penilaian dan menambahkan akun batasan untuk login
This commit is contained in:
parent
4c335c9481
commit
76876f94ef
@ -5,11 +5,15 @@ namespace App\Http\Controllers;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\MasterPitStopPraAkre;
|
||||
|
||||
class AuthController extends Controller
|
||||
{
|
||||
public function login(){
|
||||
return view('auth.login');
|
||||
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
||||
return view('auth.login', [
|
||||
'totalSteps' => $totalSteps,
|
||||
]);
|
||||
}
|
||||
|
||||
public function submitLogin(Request $request){
|
||||
@ -17,8 +21,25 @@ class AuthController extends Controller
|
||||
'namauser' => 'required',
|
||||
'password' => 'required'
|
||||
]);
|
||||
$user = User::where('namauser', $request->namauser)->first();
|
||||
|
||||
$allowedIds = [
|
||||
727,
|
||||
1755,
|
||||
2184,
|
||||
2549,
|
||||
993,
|
||||
3053,
|
||||
2319,
|
||||
1995,
|
||||
2011,
|
||||
2145,
|
||||
1113,
|
||||
2998
|
||||
];
|
||||
$user = User::where('namauser', $request->namauser)->first();
|
||||
if (!in_array($user->id, $allowedIds)) {
|
||||
return back()->with(['error' => 'Akun Anda tidak diizinkan login']);
|
||||
}
|
||||
if ($user && $user->passcode === sha1($request->password)) {
|
||||
auth()->login($user);
|
||||
$request->session()->regenerate();
|
||||
@ -34,4 +55,21 @@ class AuthController extends Controller
|
||||
request()->session()->regenerateToken();
|
||||
return redirect('/login');
|
||||
}
|
||||
// query dibawah digunakan untuk mencari data akun user login
|
||||
// select ls.id, ls.namauser, ls.objectpegawaifk, pm.nama
|
||||
// FROM pegawai_m pm
|
||||
// left join loginuser_s ls on pm.id = ls.objectpegawaifk
|
||||
// WHERE nama ILIKE ANY (ARRAY[
|
||||
// '%Sarvita Dewi%',
|
||||
// '%Milwiyandia%',
|
||||
// '%Zulkarnaen%',
|
||||
// '%Ripka perdija surbakti%',
|
||||
// '%Arum Budiarti%',
|
||||
// '%Ghufran Haning Putra%',
|
||||
// '%Ifah Kisyafah%',
|
||||
// '%Putri rishki Roma Dani%',
|
||||
// '%Putri Milenia Ramadhanti%',
|
||||
// '%Nurul susilowati%',
|
||||
// '%Joko Prasetio%'
|
||||
// ]);
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ class PitStopController extends Controller
|
||||
public function pitstop(){
|
||||
$masterPitStop = MasterPitStopPraAkre::where('statusenabled', true)->get();
|
||||
$data = [
|
||||
'title' => 'Pit Stop',
|
||||
'title' => 'PitStop',
|
||||
'masterPitStop' => $masterPitStop
|
||||
];
|
||||
return view('pitstop.index', $data);
|
||||
@ -122,7 +122,7 @@ class PitStopController extends Controller
|
||||
DB::raw('ukp.id as unit_id'),
|
||||
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
||||
DB::raw('pg.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
||||
|
||||
@ -206,7 +206,7 @@ class PitStopController extends Controller
|
||||
->select([
|
||||
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
||||
DB::raw('pl.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
||||
|
||||
@ -338,7 +338,6 @@ class PitStopController extends Controller
|
||||
{
|
||||
$unitId = $request->query('unit_id');
|
||||
$unitId = is_null($unitId) || $unitId === '' ? null : (int) $unitId;
|
||||
|
||||
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
||||
$generatedAt = now();
|
||||
|
||||
@ -362,7 +361,7 @@ class PitStopController extends Controller
|
||||
DB::raw('ukp.id as unit_id'),
|
||||
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
||||
DB::raw('pg.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
||||
|
||||
@ -408,7 +407,7 @@ class PitStopController extends Controller
|
||||
])->setPaper('a4', 'landscape');
|
||||
|
||||
$filename = 'monitoring-pra-akreditasi-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
||||
return $pdf->download($filename);
|
||||
return $pdf->stream($filename);
|
||||
}
|
||||
|
||||
// Mode detail: PDF per unit (lebih aman untuk memory).
|
||||
@ -442,13 +441,12 @@ class PitStopController extends Controller
|
||||
DB::raw('pg.id as pegawai_id'),
|
||||
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
||||
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -503,7 +501,7 @@ class PitStopController extends Controller
|
||||
])->setPaper('a4', 'landscape');
|
||||
|
||||
$filename = 'monitoring-pra-akreditasi-unit-' . $unitId . '-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
||||
return $pdf->download($filename);
|
||||
return $pdf->stream($filename);
|
||||
}
|
||||
|
||||
public function monitoringPdfExternal(Request $request)
|
||||
@ -530,7 +528,7 @@ class PitStopController extends Controller
|
||||
->select([
|
||||
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
||||
DB::raw('pl.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
||||
|
||||
@ -566,7 +564,7 @@ class PitStopController extends Controller
|
||||
])->setPaper('a4', 'landscape');
|
||||
|
||||
$filename = 'monitoring-karyawan-luar-ringkasan-' . $generatedAt->format('Ymd-Hi') . '.pdf';
|
||||
return $pdf->download($filename);
|
||||
return $pdf->stream($filename);
|
||||
}
|
||||
|
||||
// Detail per tipe
|
||||
@ -585,14 +583,13 @@ class PitStopController extends Controller
|
||||
'pl.id',
|
||||
DB::raw("coalesce(pl.nama, '-') as nama"),
|
||||
DB::raw("coalesce(pl.nik, '-') as nik"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -666,7 +663,7 @@ class PitStopController extends Controller
|
||||
DB::raw('ukp.id as unit_id'),
|
||||
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
||||
DB::raw('pg.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy('ukp.id', 'ukp.name', 'pg.id');
|
||||
|
||||
@ -737,13 +734,12 @@ class PitStopController extends Controller
|
||||
'pg.id',
|
||||
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
||||
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -807,7 +803,7 @@ class PitStopController extends Controller
|
||||
->select([
|
||||
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as tipe"),
|
||||
DB::raw('pl.id as pegawai_id'),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
])
|
||||
->groupBy(DB::raw("coalesce(nullif(pl.tipe, ''), '-')"), 'pl.id');
|
||||
|
||||
@ -864,14 +860,13 @@ class PitStopController extends Controller
|
||||
'pl.id',
|
||||
DB::raw("coalesce(pl.nama, '-') as nama"),
|
||||
DB::raw("coalesce(pl.nik, '-') as nik"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -945,13 +940,12 @@ class PitStopController extends Controller
|
||||
'pg.id',
|
||||
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
||||
DB::raw("coalesce(pg.nip_pns, '-') as nip_pns"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -961,7 +955,6 @@ class PitStopController extends Controller
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1040,14 +1033,13 @@ class PitStopController extends Controller
|
||||
'pl.id',
|
||||
DB::raw("coalesce(pl.nama, '-') as nama"),
|
||||
DB::raw("coalesce(pl.nik, '-') as nik"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1058,7 +1050,6 @@ class PitStopController extends Controller
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1142,13 +1133,12 @@ class PitStopController extends Controller
|
||||
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
||||
DB::raw("coalesce(pg.nip_pns, '-') as identitas"),
|
||||
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1158,7 +1148,6 @@ class PitStopController extends Controller
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1183,14 +1172,13 @@ class PitStopController extends Controller
|
||||
DB::raw("coalesce(pl.nama, '-') as nama"),
|
||||
DB::raw("coalesce(pl.nik, '-') as identitas"),
|
||||
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as unit_name"),
|
||||
DB::raw("count(distinct m.id) filter (where p.status='lulus') as lulus_count"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1201,7 +1189,6 @@ class PitStopController extends Controller
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.status = 'lulus'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
@ -1285,13 +1272,13 @@ class PitStopController extends Controller
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->where('p.pegawai_id', $pegawaiId)
|
||||
->where('p.status', 'lulus')
|
||||
// ->where('p.status', 'lulus')
|
||||
->whereNotNull('m.id')
|
||||
->select([
|
||||
'p.id',
|
||||
'p.masterpitstop_id',
|
||||
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
||||
'p.status',
|
||||
'p.nilai',
|
||||
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
||||
])
|
||||
->orderByDesc('p.id')
|
||||
@ -1327,14 +1314,13 @@ class PitStopController extends Controller
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->where('p.tipe_karyawan', 'luar')
|
||||
->where('p.status', 'lulus')
|
||||
->where('p.pegawai_id', $pegawaiId)
|
||||
->whereNotNull('m.id')
|
||||
->select([
|
||||
'p.id',
|
||||
'p.masterpitstop_id',
|
||||
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
||||
'p.status',
|
||||
'p.nilai',
|
||||
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
||||
])
|
||||
->orderByDesc('p.id')
|
||||
@ -1364,7 +1350,7 @@ class PitStopController extends Controller
|
||||
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
||||
|
||||
$lockedSteps = PraAkre::where('pegawai_id', $pegawaiId)
|
||||
->where('status', 'lulus')
|
||||
// ->where('status', 'lulus')
|
||||
->distinct()
|
||||
->pluck('masterpitstop_id');
|
||||
|
||||
@ -1394,7 +1380,7 @@ class PitStopController extends Controller
|
||||
|
||||
$lockedSteps = PraAkre::where('pegawai_id', $pegawaiId)
|
||||
->where('tipe_karyawan', 'luar')
|
||||
->where('status', 'lulus')
|
||||
// ->where('status', 'lulus')
|
||||
->distinct()
|
||||
->pluck('masterpitstop_id');
|
||||
|
||||
@ -1414,9 +1400,10 @@ class PitStopController extends Controller
|
||||
$validator = Validator::make($request->all(), [
|
||||
'karyawan_id' => ['required', 'integer'],
|
||||
'step' => 'required',
|
||||
'status' => 'required|in:lulus,tidak_lulus',
|
||||
// 'status' => 'required|in:lulus,tidak_lulus',
|
||||
'unit_id' => 'nullable|string|max:15',
|
||||
'tipe_karyawan' => 'nullable|in:internal,luar',
|
||||
'nilai' => 'required'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@ -1460,13 +1447,13 @@ class PitStopController extends Controller
|
||||
$alreadyPassed = PraAkre::where('pegawai_id', $pegawaiId)
|
||||
->where('tipe_karyawan', $tipeKaryawan)
|
||||
->where('masterpitstop_id', $masterPitstopId)
|
||||
->where('status', 'lulus')
|
||||
// ->where('status', 'lulus')
|
||||
->exists();
|
||||
|
||||
if ($alreadyPassed) {
|
||||
return response()->json([
|
||||
'error' => 1,
|
||||
'message' => 'Step ini sudah lulus dan terkunci.',
|
||||
'message' => 'Pitstop ini sudah terkunci.',
|
||||
], 409);
|
||||
}
|
||||
|
||||
@ -1474,7 +1461,8 @@ class PitStopController extends Controller
|
||||
'pegawai_id' => $pegawaiId,
|
||||
'masterpitstop_id' => $masterPitstopId,
|
||||
'unit_id' => $tipeKaryawan === 'luar' ? null : ($payload['unit_id'] ?? null),
|
||||
'status' => $payload['status'],
|
||||
// 'status' => $payload['status'],
|
||||
'nilai' => $payload['nilai'],
|
||||
'tipe_karyawan' => $payload['tipe_karyawan'],
|
||||
'action_at' => auth()->user()->objectpegawaifk
|
||||
,
|
||||
@ -1493,4 +1481,230 @@ class PitStopController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function progressDetailGhost(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_m,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'error' => 1,
|
||||
'message' => 'Validasi gagal.',
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
||||
|
||||
$rows = DB::connection('pgsql')
|
||||
->table('public.praakre as p')
|
||||
->leftJoin('public.masterpitstop as m', function ($join) {
|
||||
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->where('p.pegawai_id', $pegawaiId)
|
||||
->whereNotNull('m.id')
|
||||
->select([
|
||||
'p.id',
|
||||
'p.masterpitstop_id',
|
||||
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
||||
'p.nilai',
|
||||
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
||||
])
|
||||
->orderByDesc('p.id')
|
||||
->limit(500)
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'error' => 0,
|
||||
'data' => $rows,
|
||||
]);
|
||||
}
|
||||
|
||||
public function progressDetailExternalGhost(Request $request)
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'pegawai_id' => 'required|integer|exists:pgsql.public.pegawai_luar_pl,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'error' => 1,
|
||||
'message' => 'Validasi gagal.',
|
||||
'errors' => $validator->errors(),
|
||||
], 422);
|
||||
}
|
||||
|
||||
$pegawaiId = (int) $validator->validated()['pegawai_id'];
|
||||
|
||||
$rows = DB::connection('pgsql')
|
||||
->table('public.praakre as p')
|
||||
->leftJoin('public.masterpitstop as m', function ($join) {
|
||||
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->where('p.tipe_karyawan', 'luar')
|
||||
->where('p.status', 'lulus')
|
||||
->where('p.pegawai_id', $pegawaiId)
|
||||
->whereNotNull('m.id')
|
||||
->select([
|
||||
'p.id',
|
||||
'p.masterpitstop_id',
|
||||
DB::raw("coalesce(m.nama, '-') as step_nama"),
|
||||
'p.status',
|
||||
DB::raw("to_char(p.created_at, 'DD-MM-YYYY HH24:MI') as created_at"),
|
||||
])
|
||||
->orderByDesc('p.id')
|
||||
->limit(500)
|
||||
->get();
|
||||
|
||||
return response()->json([
|
||||
'error' => 0,
|
||||
'data' => $rows,
|
||||
]);
|
||||
}
|
||||
|
||||
public function dataProgressAllKaryawanGhost(Request $request){
|
||||
$draw = $this->dtInt($request->input('draw'), 1);
|
||||
$start = $this->dtInt($request->input('start'), 0);
|
||||
$length = $this->dtInt($request->input('length'), 10);
|
||||
if ($length < 1) $length = 10;
|
||||
if ($length > 200) $length = 200;
|
||||
|
||||
$search = trim((string) data_get($request->all(), 'search.value', ''));
|
||||
|
||||
$totalSteps = (int) MasterPitStopPraAkre::where('statusenabled', true)->count();
|
||||
|
||||
// Internal
|
||||
$internal = DB::connection('pgsql')
|
||||
->table('public.mappegawaijabatantounitkerja_m as mp')
|
||||
->join('public.pegawai_m as pg', 'pg.id', '=', 'mp.objectpegawaifk')
|
||||
->join('public.unitkerjapegawai_m as ukp', 'ukp.id', '=', 'mp.objectunitkerjapegawaifk')
|
||||
->leftJoin('public.praakre as p', 'p.pegawai_id', '=', 'pg.id')
|
||||
->leftJoin('public.masterpitstop as m', function ($join) {
|
||||
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->where('mp.statusenabled', true)
|
||||
->where('mp.isprimary', true)
|
||||
->where('pg.statusenabled', true)
|
||||
->where('pg.kedudukanfk', 1)
|
||||
->where('ukp.statusenabled', true)
|
||||
->select([
|
||||
DB::raw("'internal' as tipe_karyawan"),
|
||||
'pg.id',
|
||||
DB::raw("coalesce(pg.namalengkap, '-') as nama"),
|
||||
DB::raw("coalesce(ukp.name, '-') as unit_name"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
), 0) as belum_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pg.id
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
), '') as belum_steps"),
|
||||
])
|
||||
->groupBy('pg.id', 'pg.namalengkap', 'pg.nip_pns', 'ukp.name');
|
||||
|
||||
// External
|
||||
$external = DB::connection('pgsql')
|
||||
->table('public.pegawai_luar_pl as pl')
|
||||
->leftJoin('public.praakre as p', function ($join) {
|
||||
$join->on('p.pegawai_id', '=', 'pl.id')
|
||||
->where('p.tipe_karyawan', 'luar');
|
||||
})
|
||||
->leftJoin('public.masterpitstop as m', function ($join) {
|
||||
$join->on(DB::raw('m.id::text'), '=', 'p.masterpitstop_id')
|
||||
->where('m.statusenabled', true);
|
||||
})
|
||||
->select([
|
||||
DB::raw("'luar' as tipe_karyawan"),
|
||||
'pl.id',
|
||||
DB::raw("coalesce(pl.nama, '-') as nama"),
|
||||
DB::raw("coalesce(nullif(pl.tipe, ''), '-') as unit_name"),
|
||||
DB::raw("count(distinct m.id) as lulus_count"),
|
||||
DB::raw("coalesce((
|
||||
select count(*)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
), 0) as belum_count"),
|
||||
DB::raw("coalesce((
|
||||
select string_agg(ms.nama, ', ' order by ms.id)
|
||||
from public.masterpitstop ms
|
||||
left join public.praakre px
|
||||
on px.pegawai_id = pl.id
|
||||
and px.tipe_karyawan = 'luar'
|
||||
and px.masterpitstop_id = ms.id::text
|
||||
where ms.statusenabled = true
|
||||
and px.id is null
|
||||
), '') as belum_steps"),
|
||||
])
|
||||
->groupBy('pl.id', 'pl.nama', 'pl.nik', DB::raw("coalesce(nullif(pl.tipe, ''), '-')"));
|
||||
|
||||
$union = $internal->unionAll($external);
|
||||
|
||||
$baseNoSearch = DB::connection('pgsql')->query()->fromSub($union, 'u');
|
||||
$base = DB::connection('pgsql')->query()->fromSub($union, 'u');
|
||||
|
||||
if ($search !== '') {
|
||||
$base->where(function ($q) use ($search) {
|
||||
$q->where('u.nama', 'ILIKE', '%' . $search . '%')
|
||||
->orWhere('u.unit_name', 'ILIKE', '%' . $search . '%')
|
||||
->orWhere('u.tipe_karyawan', 'ILIKE', '%' . $search . '%');
|
||||
});
|
||||
}
|
||||
|
||||
$recordsTotal = DB::connection('pgsql')->query()->fromSub($baseNoSearch, 't')->count();
|
||||
$recordsFiltered = $search === ''
|
||||
? $recordsTotal
|
||||
: DB::connection('pgsql')->query()->fromSub($base, 't')->count();
|
||||
|
||||
$rows = $base
|
||||
->orderByDesc('lulus_count')
|
||||
->orderBy('nama')
|
||||
->offset($start)
|
||||
->limit($length)
|
||||
->get();
|
||||
|
||||
$data = $rows->map(function ($r) use ($totalSteps) {
|
||||
$lulus = (int) ($r->lulus_count ?? 0);
|
||||
$pct = $totalSteps > 0 ? round(($lulus / $totalSteps) * 100, 1) : 0;
|
||||
return [
|
||||
'tipe_karyawan' => (string) ($r->tipe_karyawan ?? 'internal'),
|
||||
'id' => (int) ($r->id ?? 0),
|
||||
'nama' => (string) ($r->nama ?? '-'),
|
||||
'unit_name' => (string) ($r->unit_name ?? '-'),
|
||||
'lulus_count' => $lulus,
|
||||
'pct' => $pct,
|
||||
'selesai' => $totalSteps > 0 ? ($lulus >= $totalSteps ? 1 : 0) : 0,
|
||||
'belum_count' => (int) ($r->belum_count ?? 0),
|
||||
'belum_steps' => (string) ($r->belum_steps ?? ''),
|
||||
];
|
||||
})->values();
|
||||
|
||||
return response()->json([
|
||||
'draw' => $draw,
|
||||
'recordsTotal' => $recordsTotal,
|
||||
'recordsFiltered' => $recordsFiltered,
|
||||
'data' => $data,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,8 +2,49 @@
|
||||
|
||||
@section('custom_css')
|
||||
<style>
|
||||
.table td, .table th {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.progress {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
.container-fluid {
|
||||
padding: 0 10px !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.left-panel {
|
||||
background: linear-gradient(135deg, #eef2f7, #f8f9fb);
|
||||
min-height: 100vh;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
background: #ffffff;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.card-custom {
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 8px 25px rgba(0,0,0,0.08);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.login-card {
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.table thead th {
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
@ -17,15 +58,36 @@
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-8 hide-xs bg-secondary vh-100">
|
||||
<div class="col-md-8 left-panel d-flex align-items-center justify-content-center">
|
||||
<div class="d-flex align-items-center justify-content-center h-75 flex-column">
|
||||
<img src="{{ asset('metronic/assets/media/illustrations/sigma-1/10.png') }}" alt="" srcset="" class="h-75">
|
||||
<div class="mt-5">
|
||||
<span class="fs-1 fw-bold" id="title_selamat_datang"></span>
|
||||
<div class="card h-150 flex-column">
|
||||
<div class="card-body table-responsive">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h4 class="fw-bold mb-0">Monitoring Pra Akreditasi</h4>
|
||||
|
||||
<input type="text" id="searchAllKaryawan"
|
||||
class="form-control w-250px"
|
||||
placeholder="Cari karyawan...">
|
||||
</div>
|
||||
<table id="tblAllKaryawan" class="table align-middle table-row-dashed fs-6 gy-3 w-100">
|
||||
<thead>
|
||||
<tr class="text-muted fw-semibold fs-7 text-uppercase gs-0">
|
||||
<th>Nama</th>
|
||||
<th>Unit / Tipe</th>
|
||||
<th style="width: 320px">Progress</th>
|
||||
<th>Belum dikerjakan</th>
|
||||
<th class="text-end">Jenis</th>
|
||||
<th class="text-end">Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="fw-semibold text-gray-800"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 py-10 px-5">
|
||||
<div class="col-md-4 right-panel">
|
||||
<div class="d-flex align-items-center justify-content-center h-100 flex-column">
|
||||
<center>
|
||||
<img src="{{ asset('assets/img/logo-fullname.png') }}" alt="" srcset="" class="w-50">
|
||||
@ -61,95 +123,297 @@
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
<div class="modal fade" id="modalAllDetail" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Detail Progress</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-muted mb-4" id="allDetailNama"></div>
|
||||
<div class="table-responsive">
|
||||
<table class="table align-middle table-row-dashed fs-6 gy-3">
|
||||
<thead>
|
||||
<tr class="text-muted fw-semibold fs-7 text-uppercase gs-0">
|
||||
<th>Nama Step</th>
|
||||
<th>Nilai</th>
|
||||
<th class="text-end">Waktu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="fw-semibold text-gray-800" id="allDetailTable">
|
||||
<tr>
|
||||
<td colspan="4" class="text-center text-muted py-6">Memuat data...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="modalBelum" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">PitStop Belum Dikerjakan</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-dark fw-semibold mb-4" id="belumNama"></div>
|
||||
<ul id="belumList" class="mb-0 ps-5"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@section('custom_js')
|
||||
<script>
|
||||
@if (session('error'))
|
||||
toastr.error("{{ session('error') }}");
|
||||
@endif
|
||||
function escapeHtml(text) {
|
||||
return $('<div>').text(text).html();
|
||||
}
|
||||
$(document).ready(function () {
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#togglePassword').on('click', function () {
|
||||
let input = $('#password');
|
||||
let icon = $(this).find('i');
|
||||
// =========================
|
||||
// TOGGLE PASSWORD
|
||||
// =========================
|
||||
$('#togglePassword').on('click', function () {
|
||||
let input = $('#password');
|
||||
let icon = $(this).find('i');
|
||||
|
||||
if (input.attr('type') === 'password') {
|
||||
input.attr('type', 'text');
|
||||
icon.removeClass('fa-eye').addClass('fa-eye-slash');
|
||||
} else {
|
||||
input.attr('type', 'password');
|
||||
icon.removeClass('fa-eye-slash').addClass('fa-eye');
|
||||
if (input.attr('type') === 'password') {
|
||||
input.attr('type', 'text');
|
||||
icon.removeClass('fa-eye').addClass('fa-eye-slash');
|
||||
} else {
|
||||
input.attr('type', 'password');
|
||||
icon.removeClass('fa-eye-slash').addClass('fa-eye');
|
||||
}
|
||||
});
|
||||
|
||||
// =========================
|
||||
// TOTAL STEP
|
||||
// =========================
|
||||
const totalSteps = Number(@json((int) ($totalSteps ?? 0)));
|
||||
|
||||
// =========================
|
||||
// ESCAPE HTML (WAJIB ADA)
|
||||
// =========================
|
||||
|
||||
|
||||
// =========================
|
||||
// FORM VALIDATION (FIXED)
|
||||
// =========================
|
||||
const form = document.getElementById('form_login');
|
||||
|
||||
var validator = FormValidation.formValidation(form, {
|
||||
fields: {
|
||||
'namauser': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Username masih kosong'
|
||||
}
|
||||
}
|
||||
},
|
||||
'password': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Password masih kosong'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap: new FormValidation.plugins.Bootstrap5({
|
||||
rowSelector: '.fv-row'
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
$('#form_permintaan_submit').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
validator.validate().then(function (status) {
|
||||
if (status === 'Valid') {
|
||||
form.submit();
|
||||
}
|
||||
});
|
||||
});
|
||||
var typed = new Typed("#title_selamat_datang", {
|
||||
strings: ["Selamat Datang", "Di Halaman Admin", "Permintaan IT", "Silahkan Masukkan Username Dan Password", "Jika Belum Memiliki Akun", "Silahkan Hubungi Tim IT"],
|
||||
typeSpeed: 30,
|
||||
});
|
||||
|
||||
// Define form element
|
||||
const form = document.getElementById('form_login');
|
||||
const token = $('meta[name="csrf-token"]').attr('content');
|
||||
// =========================
|
||||
// DATATABLE INIT (FIXED)
|
||||
// =========================
|
||||
const allTable = $('#tblAllKaryawan').DataTable({
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
searchDelay: 350,
|
||||
dom: 'rtip',
|
||||
pageLength: 10,
|
||||
order: [[2, 'desc']],
|
||||
ajax: {
|
||||
url: '/data/progress-all-karyawan-ghost',
|
||||
type: 'GET',
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: null,
|
||||
render: function (row) {
|
||||
const nama = escapeHtml(row.nama ?? '-');
|
||||
// const idt = escapeHtml(row.identitas ?? '-');
|
||||
// const label = row.tipe_karyawan === 'luar' ? 'NIK' : 'NIP';
|
||||
|
||||
// Init form validation rules. For more info check the FormValidation plugin's official documentation:https://formvalidation.io/
|
||||
var validator = FormValidation.formValidation(
|
||||
form,
|
||||
{
|
||||
fields: {
|
||||
'username': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Username masih kosong'
|
||||
}
|
||||
}
|
||||
},
|
||||
'password': {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'Password masih kosong'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap: new FormValidation.plugins.Bootstrap5({
|
||||
rowSelector: '.fv-row',
|
||||
eleInvalidClass: '',
|
||||
eleValidClass: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Submit button handler
|
||||
const submitButton = document.getElementById('form_permintaan_submit');
|
||||
submitButton.addEventListener('click', function (e) {
|
||||
// Prevent default button action
|
||||
e.preventDefault();
|
||||
|
||||
// Validate form before submit
|
||||
if (validator) {
|
||||
validator.validate().then(function (status) {
|
||||
if (status == 'Valid') {
|
||||
submitButton.setAttribute('data-kt-indicator', 'on');
|
||||
submitButton.disabled = true;
|
||||
setTimeout(function () {
|
||||
submitButton.removeAttribute('data-kt-indicator');
|
||||
submitButton.disabled = false;
|
||||
}, 2000);
|
||||
|
||||
if (!form.querySelector('input[name="_token"]')) {
|
||||
const input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = '_token';
|
||||
input.value = token;
|
||||
form.appendChild(input);
|
||||
}
|
||||
form.submit();
|
||||
return `
|
||||
<div>
|
||||
<div class="fw-bold">${nama}</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'unit_name',
|
||||
render: data => `<span>${escapeHtml(data ?? '-')}</span>`
|
||||
},
|
||||
{
|
||||
data: null,
|
||||
orderable: false,
|
||||
render: function (row) {
|
||||
const pct = Number(row.pct ?? 0);
|
||||
|
||||
return `
|
||||
<div>
|
||||
<div class="d-flex justify-content-between small text-muted">
|
||||
<span>${row.lulus_count ?? 0} / ${totalSteps}</span>
|
||||
<span>${pct}%</span>
|
||||
</div>
|
||||
<div class="progress mt-1" style="height:6px;">
|
||||
<div class="progress-bar bg-success" style="width:${pct}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
},
|
||||
{
|
||||
data: null,
|
||||
className: 'text-center',
|
||||
orderable: false,
|
||||
render: function (data, type, row) {
|
||||
const c = Number(row.belum_count ?? 0);
|
||||
if (c <= 0) return '<span class="text-muted">-</span>';
|
||||
return `<a href="#" class="showBelum" data-nama="${escapeHtml(row.nama)}" data-steps="${escapeHtml(row.belum_steps ?? '')}"><span class="badge badge-warning text-dark">${c} pitstop</span></a>`;
|
||||
},
|
||||
},
|
||||
{
|
||||
data: 'tipe_karyawan',
|
||||
className: 'text-end',
|
||||
render: function (data) {
|
||||
return data === 'luar'
|
||||
? '<span class="badge bg-warning text-dark">Eksternal</span>'
|
||||
: '<span class="badge bg-primary text-white">Internal</span>';
|
||||
}
|
||||
},
|
||||
{
|
||||
data: null,
|
||||
className: 'text-end',
|
||||
orderable: false,
|
||||
render: function (row) {
|
||||
return `
|
||||
<button class="btn btn-sm btn-primary viewDetailAll" data-id="${row.id}" data-nama="${row.nama}">
|
||||
Detail
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
// =========================
|
||||
// SEARCH FIX (DEBOUNCE)
|
||||
// =========================
|
||||
let timer = null;
|
||||
|
||||
$('#searchAllKaryawan').on('keyup', function () {
|
||||
const val = $(this).val();
|
||||
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(() => {
|
||||
allTable.search(val).draw();
|
||||
}, 300);
|
||||
});
|
||||
|
||||
$(document).on('click', '.viewDetailAll', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
const id = Number($(this).data('id'));
|
||||
const tipe = String($(this).data('tipe') ?? 'internal');
|
||||
const nama = String($(this).data('nama') ?? '-');
|
||||
|
||||
$('#allDetailNama').text(`${nama}`);
|
||||
$('#allDetailTable').html('<tr><td colspan="4" class="text-center text-muted py-6">Memuat data...</td></tr>');
|
||||
|
||||
const url = tipe === 'luar' ? '/pitstop/progress-detail-external-ghost' : '/pitstop/progress-detail-ghost';
|
||||
$.get(url, { pegawai_id: id })
|
||||
.done(function (res) {
|
||||
renderDetailRows(res?.data ?? []);
|
||||
})
|
||||
.fail(function () {
|
||||
$('#allDetailTable').html('<tr><td colspan="4" class="text-center text-muted py-6">Gagal memuat data</td></tr>');
|
||||
});
|
||||
|
||||
new bootstrap.Modal(document.getElementById('modalAllDetail')).show();
|
||||
});
|
||||
|
||||
const renderDetailRows = (rows) => {
|
||||
if (!rows.length) {
|
||||
$('#allDetailTable').html('<tr><td colspan="4" class="text-center text-muted py-6">Belum ada data</td></tr>');
|
||||
return;
|
||||
}
|
||||
|
||||
const html = rows
|
||||
.map((r) => {
|
||||
const status = String(r.status ?? '-');
|
||||
const badge =
|
||||
status === 'lulus'
|
||||
? '<span class="badge badge-light-success">Lulus</span>'
|
||||
: status === 'tidak_lulus'
|
||||
? '<span class="badge badge-light-danger">Tidak Lulus</span>'
|
||||
: `<span class="badge badge-light">${escapeHtml(status)}</span>`;
|
||||
|
||||
const waktu = r.created_at ? String(r.created_at) : '-';
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(r.step_nama ?? '-')}</td>
|
||||
<td>${r.nilai}</td>
|
||||
<td class="text-end">${escapeHtml(waktu)}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
$('#allDetailTable').html(html);
|
||||
};
|
||||
|
||||
});
|
||||
$(document).on('click', '.showBelum', function (e) {
|
||||
e.preventDefault();
|
||||
const nama = $(this).data('nama');
|
||||
const nip = $(this).data('nip');
|
||||
const stepsRaw = String($(this).data('steps') ?? '').trim();
|
||||
|
||||
$('#belumNama').text(nama + ' (NIP ' + nip +')');
|
||||
|
||||
if (!stepsRaw) {
|
||||
$('#belumList').html('<li class="text-muted">Tidak ada data.</li>');
|
||||
} else {
|
||||
const steps = stepsRaw.split(',').map((s) => s.trim()).filter(Boolean);
|
||||
const html = steps.map((s) => `<li><span class="fw-semibold">${escapeHtml(s)}</span></li>`).join('');
|
||||
$('#belumList').html(html || '<li class="text-muted">Tidak ada data.</li>');
|
||||
}
|
||||
|
||||
new bootstrap.Modal(document.getElementById('modalBelum')).show();
|
||||
});
|
||||
|
||||
</script>
|
||||
@endsection
|
||||
|
||||
@ -44,11 +44,11 @@
|
||||
<div class="d-flex flex-wrap gap-6">
|
||||
<label class="form-check form-check-sm form-check-custom form-check-solid mb-0">
|
||||
<input class="form-check-input" type="radio" name="karyawan_type" id="karyawanTypeInternal" value="internal" checked />
|
||||
<span class="form-check-label fw-semibold">Internal</span>
|
||||
<span class="form-check-label fw-semibold">Karyawan Internal</span>
|
||||
</label>
|
||||
<label class="form-check form-check-sm form-check-custom form-check-solid mb-0">
|
||||
<input class="form-check-input" type="radio" name="karyawan_type" id="karyawanTypeLuar" value="luar" />
|
||||
<span class="form-check-label fw-semibold">Karyawan Luar</span>
|
||||
<span class="form-check-label fw-semibold">Karyawan Eksternal</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-text">Mode pencarian akan menyesuaikan tipe karyawan.</div>
|
||||
@ -97,7 +97,7 @@
|
||||
<div class="d-flex flex-stack flex-grow-1">
|
||||
<div class="fw-semibold">
|
||||
<div class="text-gray-900 fw-bold">Info</div>
|
||||
<div class="text-gray-700">Step akan terkunci jika sudah berstatus lulus.</div>
|
||||
<div class="text-gray-700">Data pitstop yang telah diinput tidak akan ditampilkan kembali.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -113,8 +113,22 @@
|
||||
</select>
|
||||
<div class="form-text" id="stepHint"></div>
|
||||
</div>
|
||||
|
||||
<div class="mb-2">
|
||||
<div class="mb-4">
|
||||
<label for="nilai" class="form-label" id="label_nilai">Nilai (0-100)</label>
|
||||
<input
|
||||
type="number"
|
||||
id="nilai"
|
||||
name="nilai"
|
||||
class="form-control"
|
||||
min="0"
|
||||
max="100"
|
||||
step="1"
|
||||
inputmode="numeric"
|
||||
autocomplete="off"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
{{-- <div class="mb-2">
|
||||
<label class="form-label d-block">Status</label>
|
||||
<div class="d-flex flex-wrap gap-6">
|
||||
<label class="form-check form-check-sm form-check-custom form-check-solid">
|
||||
@ -126,7 +140,7 @@
|
||||
<span class="form-check-label">Tidak Lulus</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
@ -263,7 +277,7 @@
|
||||
const availableCount = $step.find('option').length;
|
||||
if (!availableCount) {
|
||||
$form.find('button[type="submit"]').prop('disabled', true);
|
||||
$stepHint.html('<span class="text-success fw-semibold">Semua step sudah lulus</span>');
|
||||
$stepHint.html('<span class="text-success fw-semibold">Semua step sudah selesai dikerjakan</span>');
|
||||
}
|
||||
})
|
||||
.fail(function () {
|
||||
@ -304,7 +318,7 @@
|
||||
$('#nip').val($(this).data('nip'));
|
||||
$('#karyawan_id').val($(this).data('id'));
|
||||
lockExistingSteps($(this).data('id'));
|
||||
getKaryawanType() === 'luar' ? $("#label_nip").text('NIK') : $("#label_nip").text('NIP')
|
||||
getKaryawanType() === 'luar' ? $('#label_nip').text('NIK') : $('#label_nip').text('NIP');
|
||||
new bootstrap.Modal(document.getElementById('modalPitstop')).show();
|
||||
});
|
||||
|
||||
@ -324,11 +338,27 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const rawNilai = String($('#nilai').val() ?? '').trim();
|
||||
const nilai = rawNilai === '' ? NaN : Number(rawNilai);
|
||||
if (!Number.isFinite(nilai) || nilai < 0 || nilai > 100) {
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
position: 'top-end',
|
||||
icon: 'warning',
|
||||
title: 'Nilai harus di antara 0 sampai 100.',
|
||||
showConfirmButton: false,
|
||||
timer: 2400,
|
||||
timerProgressBar: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = {
|
||||
karyawan_id: $('#karyawan_id').val(),
|
||||
step: $('#step').val(),
|
||||
status: $('input[name="status"]:checked').val(),
|
||||
tipe_karyawan: getKaryawanType()
|
||||
// status: $('input[name="status"]:checked').val(),
|
||||
nilai: nilai,
|
||||
tipe_karyawan: getKaryawanType(),
|
||||
};
|
||||
$.ajax({
|
||||
url: '/pitstop/submit',
|
||||
|
||||
@ -4,25 +4,139 @@
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{ $title ?? 'Monitoring Pra Akreditasi' }}</title>
|
||||
<style>
|
||||
/* * { font-family: DejaVu Sans, sans-serif; } */
|
||||
body { font-size: 10px; color: #111827; }
|
||||
.h1 { font-size: 16px; font-weight: 700; margin: 0; }
|
||||
.meta { margin-top: 4px; color: #6b7280; font-size: 10px; }
|
||||
/* Jangan paksa 1 unit utuh di 1 halaman (bisa bikin halaman 1 kosong) */
|
||||
.unit { margin-top: 14px; }
|
||||
.unit-head { padding: 8px 10px; border: 1px solid #e5e7eb; background: #f9fafb; }
|
||||
.unit-title { font-size: 12px; font-weight: 700; margin: 0; }
|
||||
.unit-meta { margin-top: 3px; color: #6b7280; font-size: 10px; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 8px; }
|
||||
.table th, .table td { border: 1px solid #e5e7eb; padding: 6px; vertical-align: top; }
|
||||
.table th { background: #f9fafb; text-align: left; font-weight: 700; }
|
||||
.text-right { text-align: right; }
|
||||
.badge { display: inline-block; padding: 2px 6px; border-radius: 10px; font-size: 10px; background: #eef2ff; color: #3730a3; }
|
||||
.badge-ok { background: #dcfce7; color: #166534; }
|
||||
.badge-warn { background: #fff7ed; color: #9a3412; }
|
||||
.muted { color: #6b7280; }
|
||||
</style>
|
||||
<style>
|
||||
/* ===== GLOBAL ===== */
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: DejaVu Sans, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 1.35;
|
||||
color: #111827;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* ===== HEADER ===== */
|
||||
.h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.meta {
|
||||
margin-top: 4px;
|
||||
color: #6b7280;
|
||||
font-size: 10.5px;
|
||||
}
|
||||
|
||||
/* ===== UNIT ===== */
|
||||
.unit {
|
||||
margin-top: 16px;
|
||||
page-break-inside: auto;
|
||||
}
|
||||
|
||||
.unit-head {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #e5e7eb;
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
.unit-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.unit-meta {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* ===== TABLE ===== */
|
||||
.table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 7px 9px;
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.col-no {
|
||||
font-size: 9px;
|
||||
padding: 3px 4px;
|
||||
width: 18px !important;
|
||||
min-width: 18px !important;
|
||||
max-width: 18px !important;
|
||||
}
|
||||
|
||||
.table th {
|
||||
background: #f9fafb;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Keep header repeated on page-break (PDF renderers) */
|
||||
thead { display: table-header-group; }
|
||||
tfoot { display: table-footer-group; }
|
||||
/* Avoid making tables "unbreakable" (can push content to next page) */
|
||||
tr { page-break-inside: auto; }
|
||||
td, th { page-break-inside: auto; }
|
||||
|
||||
.unit-head { page-break-inside: avoid; }
|
||||
|
||||
/* Zebra biar enak dibaca */
|
||||
.table tr:nth-child(even) {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
/* ===== ALIGN ===== */
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ===== BADGE ===== */
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 10.5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-ok {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.badge-warn {
|
||||
background: #fff7ed;
|
||||
color: #9a3412;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* ===== PRINT FIX ===== */
|
||||
@page {
|
||||
margin: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
@ -30,32 +144,34 @@
|
||||
<div class="meta">
|
||||
Dicetak: {{ optional($generatedAt)->format('Y-m-d H:i') }}
|
||||
</div>
|
||||
<div class="meta">
|
||||
Total PitStop Aktif: {{ (int) ($totalSteps ?? 0) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (($isSummaryOnly ?? false) === true)
|
||||
<table class="table" style="margin-top: 14px;">
|
||||
<colgroup>
|
||||
<col style="width: 18px">
|
||||
<col>
|
||||
<col style="width: 110px">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 28px">No</th>
|
||||
<th>Unit</th>
|
||||
<th class="text-right" style="width: 110px">Karyawan Selesai / Total Karyawan</th>
|
||||
<th style="width: 5px;" class="nowrap col-no">No</th>
|
||||
<th style="width: 70%;">Unit</th>
|
||||
<th class="text-right nowrap" style="width: 25%;">Karyawan Selesai / Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($units ?? [] as $i => $u)
|
||||
<tr>
|
||||
<td class="text-right">{{ $i + 1 }}</td>
|
||||
<td class="">{{ $i + 1 }}</td>
|
||||
<td>
|
||||
<div style="font-weight: 700;">{{ $u->unit_name }}</div>
|
||||
{{ $u->unit_name }}
|
||||
</td>
|
||||
<td class="text-right">{{ number_format((int) $u->pegawai_selesai) }}/{{ number_format((int) $u->total_pegawai) }}</td>
|
||||
<td class="text-right nowrap">{{ number_format((int) $u->pegawai_selesai) }}/{{ number_format((int) $u->total_pegawai) }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="muted">Tidak ada data.</td>
|
||||
<td colspan="3" class="muted">Tidak ada data.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
@ -72,13 +188,20 @@
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
<col style="width: 18px">
|
||||
<col style="width: 210px">
|
||||
<col style="width: 120px">
|
||||
<col style="width: 120px">
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 28px">No</th>
|
||||
<th style="width: 210px">Nama</th>
|
||||
<th style="width: 120px">NIP</th>
|
||||
<th class="text-right" style="width: 120px">Lulus / Total PitStop</th>
|
||||
<th>PitStop Belum Selesai</th>
|
||||
<th style="width: 5%;" class="nowrap col-no">No</th>
|
||||
<th style="width: 25%;">Nama</th>
|
||||
<th style="width: 15%;" class="nowrap">NIP</th>
|
||||
<th class="text-right nowrap" style="width: 15%;">Lulus / Total PitStop</th>
|
||||
<th style="width: 40%;">PitStop Belum Selesai</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -87,15 +210,15 @@
|
||||
$selesai = ((int) ($p->total_steps ?? 0)) > 0 && ((int) ($p->lulus_steps ?? 0)) >= ((int) ($p->total_steps ?? 0));
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="text-right">{{ $i + 1 }}</td>
|
||||
<td class="text-right nowrap col-no">{{ $i + 1 }}</td>
|
||||
<td>{{ $p->nama }}</td>
|
||||
<td>{{ $p->nip_pns }}</td>
|
||||
<td class="text-right">{{ number_format((int) $p->lulus_steps) }}/{{ number_format((int) $p->total_steps) }}</td>
|
||||
<td class="nowrap">{{ $p->nip_pns }}</td>
|
||||
<td class="text-right nowrap">{{ number_format((int) $p->lulus_steps) }}/{{ number_format((int) $p->total_steps) }}</td>
|
||||
<td>{{ $selesai ? '-' : ($p->belum_selesai_steps !== '' ? $p->belum_selesai_steps : '-') }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="7" class="muted">Tidak ada data pegawai.</td>
|
||||
<td colspan="5" class="muted">Tidak ada data pegawai.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
|
||||
@ -1,53 +1,174 @@
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{ $title ?? 'Monitoring Karyawan Luar' }}</title>
|
||||
<style>
|
||||
* { font-family: DejaVu Sans, sans-serif; }
|
||||
body { font-size: 10px; color: #111827; }
|
||||
.h1 { font-size: 16px; font-weight: 700; margin: 0; }
|
||||
.meta { margin-top: 4px; color: #6b7280; font-size: 10px; }
|
||||
.section { margin-top: 14px; }
|
||||
.section-head { padding: 8px 10px; border: 1px solid #e5e7eb; background: #f9fafb; }
|
||||
.section-title { font-size: 12px; font-weight: 700; margin: 0; }
|
||||
.section-meta { margin-top: 3px; color: #6b7280; font-size: 10px; }
|
||||
.table { width: 100%; border-collapse: collapse; margin-top: 8px; }
|
||||
.table th, .table td { border: 1px solid #e5e7eb; padding: 6px; vertical-align: top; }
|
||||
.table th { background: #f9fafb; text-align: left; font-weight: 700; }
|
||||
.text-right { text-align: right; }
|
||||
.muted { color: #6b7280; }
|
||||
</style>
|
||||
<title>{{ $title ?? 'Monitoring Pra Akreditasi' }}</title>
|
||||
<style>
|
||||
/* ===== GLOBAL ===== */
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: DejaVu Sans, Arial, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 1.35;
|
||||
color: #111827;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* ===== HEADER ===== */
|
||||
.h1 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.meta {
|
||||
margin-top: 4px;
|
||||
color: #6b7280;
|
||||
font-size: 10.5px;
|
||||
}
|
||||
|
||||
/* ===== UNIT ===== */
|
||||
.unit {
|
||||
margin-top: 16px;
|
||||
page-break-inside: auto;
|
||||
}
|
||||
|
||||
.unit-head {
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #e5e7eb;
|
||||
background: #f3f4f6;
|
||||
}
|
||||
|
||||
.unit-title {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.unit-meta {
|
||||
margin-top: 4px;
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* ===== TABLE ===== */
|
||||
.table {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
border: 1px solid #e5e7eb;
|
||||
padding: 7px 9px;
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
.col-no {
|
||||
font-size: 9px;
|
||||
padding: 3px 4px;
|
||||
width: 18px !important;
|
||||
min-width: 18px !important;
|
||||
max-width: 18px !important;
|
||||
}
|
||||
|
||||
.table th {
|
||||
background: #f9fafb;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Keep header repeated on page-break (PDF renderers) */
|
||||
thead { display: table-header-group; }
|
||||
tfoot { display: table-footer-group; }
|
||||
/* Avoid making tables "unbreakable" (can push content to next page) */
|
||||
tr { page-break-inside: auto; }
|
||||
td, th { page-break-inside: auto; }
|
||||
|
||||
.unit-head { page-break-inside: avoid; }
|
||||
|
||||
/* Zebra biar enak dibaca */
|
||||
.table tr:nth-child(even) {
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
/* ===== ALIGN ===== */
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ===== BADGE ===== */
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 12px;
|
||||
font-size: 10.5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-ok {
|
||||
background: #dcfce7;
|
||||
color: #166534;
|
||||
}
|
||||
|
||||
.badge-warn {
|
||||
background: #fff7ed;
|
||||
color: #9a3412;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #6b7280;
|
||||
}
|
||||
|
||||
/* ===== PRINT FIX ===== */
|
||||
@page {
|
||||
margin: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div class="h1">{{ $title ?? 'Monitoring Karyawan Luar' }}</div>
|
||||
<div class="h1">{{ $title ?? 'Monitoring Pra Akreditasi' }}</div>
|
||||
<div class="meta">
|
||||
Dicetak: {{ optional($generatedAt)->format('Y-m-d H:i') }}
|
||||
</div>
|
||||
<div class="meta">
|
||||
Total PitStop Aktif: {{ (int) ($totalSteps ?? 0) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (($isSummaryOnly ?? false) === true)
|
||||
<table class="table" style="margin-top: 14px;">
|
||||
<colgroup>
|
||||
<col style="width: 18px">
|
||||
<col>
|
||||
<col style="width: 110px">
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 28px">No</th>
|
||||
<th>Tipe</th>
|
||||
<th class="text-right" style="width: 130px">Selesai / Total</th>
|
||||
<th style="width: 5%;" class="nowrap col-no">No</th>
|
||||
<th style="width: 80%;">Tipe</th>
|
||||
<th class="text-right nowrap" style="width: 15%;">Karyawan Selesai / Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse ($types ?? [] as $i => $t)
|
||||
<tr>
|
||||
<td class="text-right">{{ $i + 1 }}</td>
|
||||
<td class="text-right nowrap col-no">{{ $i + 1 }}</td>
|
||||
<td>
|
||||
<div style="font-weight: 700;">{{ $t->tipe }}</div>
|
||||
{{ $t->tipe }}
|
||||
</td>
|
||||
<td class="text-right">{{ number_format((int) $t->pegawai_selesai) }}/{{ number_format((int) $t->total_pegawai) }}</td>
|
||||
<td class="text-right nowrap">{{ number_format((int) $t->pegawai_selesai) }}/{{ number_format((int) $t->total_pegawai) }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
@ -58,23 +179,30 @@
|
||||
</table>
|
||||
@else
|
||||
@forelse ($types ?? [] as $t)
|
||||
<div class="section">
|
||||
<div class="section-head">
|
||||
<div class="section-title">{{ $t->tipe }}</div>
|
||||
<div class="section-meta">
|
||||
<div class="unit">
|
||||
<div class="unit-head">
|
||||
<div class="unit-title">{{ $t->tipe }}</div>
|
||||
<div class="unit-meta">
|
||||
Total Karyawan: <b>{{ number_format((int) $t->total_pegawai) }}</b>
|
||||
| Karyawan Selesai: <b>{{ number_format((int) $t->pegawai_selesai) }}</b>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table">
|
||||
<colgroup>
|
||||
<col style="width: 10%;">
|
||||
<col style="width: 25%;">
|
||||
<col style="width: 25%;">
|
||||
<col style="width: 40%;">
|
||||
<col>
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 28px">No</th>
|
||||
<th style="width: 230px">Nama</th>
|
||||
<th style="width: 140px">NIK</th>
|
||||
<th class="text-right" style="width: 120px">Lulus / Total PitStop</th>
|
||||
<th>PitStop Belum Selesai</th>
|
||||
<th style="width: 5%;" class="">No</th>
|
||||
<th style="width: 25%;">Nama</th>
|
||||
<th style="width: 10%;" class="">NIK</th>
|
||||
<th style="width: 15%;">Lulus / Total PitStop</th>
|
||||
<th style="width: 45%;">PitStop Belum Selesai</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@ -83,15 +211,15 @@
|
||||
$selesai = ((int) ($p->total_steps ?? 0)) > 0 && ((int) ($p->lulus_steps ?? 0)) >= ((int) ($p->total_steps ?? 0));
|
||||
@endphp
|
||||
<tr>
|
||||
<td class="text-right">{{ $i + 1 }}</td>
|
||||
<td class="text-right nowrap col-no">{{ $i + 1 }}</td>
|
||||
<td>{{ $p->nama }}</td>
|
||||
<td>{{ $p->nik }}</td>
|
||||
<td class="text-right">{{ number_format((int) $p->lulus_steps) }}/{{ number_format((int) $p->total_steps) }}</td>
|
||||
<td class="nowrap">{{ $p->nik }}</td>
|
||||
<td class="text-right nowrap">{{ number_format((int) $p->lulus_steps) }}/{{ number_format((int) $p->total_steps) }}</td>
|
||||
<td>{{ $selesai ? '-' : ($p->belum_selesai_steps !== '' ? $p->belum_selesai_steps : '-') }}</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="5" class="muted">Tidak ada data karyawan.</td>
|
||||
<td colspan="5" class="muted">Tidak ada data pegawai.</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
@ -103,4 +231,3 @@
|
||||
@endif
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
<thead>
|
||||
<tr class="text-muted fw-semibold fs-7 text-uppercase gs-0">
|
||||
<th>Nama Step</th>
|
||||
<th>Status</th>
|
||||
<th>Nilai</th>
|
||||
<th class="text-end">Waktu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -129,19 +129,12 @@
|
||||
const html = rows
|
||||
.map((r) => {
|
||||
const status = String(r.status ?? '-');
|
||||
const badge =
|
||||
status === 'lulus'
|
||||
? '<span class="badge badge-light-success">Lulus</span>'
|
||||
: status === 'tidak_lulus'
|
||||
? '<span class="badge badge-light-danger">Tidak Lulus</span>'
|
||||
: `<span class="badge badge-light">${escapeHtml(status)}</span>`;
|
||||
|
||||
const waktu = r.created_at ? String(r.created_at) : '-';
|
||||
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(r.step_nama ?? '-')}</td>
|
||||
<td>${badge}</td>
|
||||
<td>${r.nilai}</td>
|
||||
<td class="text-end">${escapeHtml(waktu)}</td>
|
||||
</tr>`;
|
||||
})
|
||||
|
||||
@ -20,7 +20,7 @@
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/pdf">Internal</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/pdf-external">External</a>
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/pdf-external">Eksternal</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li>
|
||||
@ -30,7 +30,7 @@
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/excel">Internal</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/excel-external">External</a>
|
||||
<a class="dropdown-item" href="/monitoring-pra-akreditasi/excel-external">Eksternal</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@ -157,7 +157,7 @@
|
||||
<thead>
|
||||
<tr class="text-muted fw-semibold fs-7 text-uppercase gs-0">
|
||||
<th>Nama Step</th>
|
||||
<th>Status</th>
|
||||
<th>Nilai</th>
|
||||
<th class="text-end">Waktu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -222,7 +222,7 @@
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(r.step_nama ?? '-')}</td>
|
||||
<td>${badge}</td>
|
||||
<td>${r.nilai}</td>
|
||||
<td class="text-end">${escapeHtml(waktu)}</td>
|
||||
</tr>`;
|
||||
})
|
||||
@ -422,7 +422,7 @@
|
||||
render: function (data) {
|
||||
const tipe = String(data ?? 'internal');
|
||||
return tipe === 'luar'
|
||||
? '<span class="badge badge-light-warning text-dark">External</span>'
|
||||
? '<span class="badge badge-light-warning text-dark">Eksternal</span>'
|
||||
: '<span class="badge badge-light-primary">Internal</span>';
|
||||
},
|
||||
},
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
<thead>
|
||||
<tr class="text-muted fw-semibold fs-7 text-uppercase gs-0">
|
||||
<th>Nama Step</th>
|
||||
<th>Status</th>
|
||||
<th>Nilai</th>
|
||||
<th class="text-end">Waktu</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -139,7 +139,7 @@
|
||||
return `
|
||||
<tr>
|
||||
<td>${escapeHtml(r.step_nama ?? '-')}</td>
|
||||
<td>${badge}</td>
|
||||
<td>${r.nilai}</td>
|
||||
<td class="text-end">${escapeHtml(waktu)}</td>
|
||||
</tr>`;
|
||||
})
|
||||
|
||||
@ -20,7 +20,7 @@ Route::middleware(['auth'])->group(function(){
|
||||
Route::get('/monitoring-pra-akreditasi/pdf-external', [PitStopController::class, 'monitoringPdfExternal']);
|
||||
Route::get('/monitoring-pra-akreditasi/excel', [PitStopController::class, 'monitoringExcel']);
|
||||
Route::get('/monitoring-pra-akreditasi/excel-external', [PitStopController::class, 'monitoringExcelExternal']);
|
||||
|
||||
|
||||
Route::get('/pitstop/progress-unit/{unit_id}', [PitStopController::class, 'progressUnitDetail']);
|
||||
Route::get('/pitstop/progress-external/{tipe}', [PitStopController::class, 'progressExternalDetail']);
|
||||
Route::get('/data/progress-Internal', [PitStopController::class, 'dataProgress']);
|
||||
@ -48,3 +48,6 @@ Route::middleware(['auth'])->group(function(){
|
||||
|
||||
Route::get('/login', [AuthController::class, 'login'])->name('login');
|
||||
Route::post('/login', [AuthController::class, 'submitLogin']);
|
||||
Route::get('/data/progress-all-karyawan-ghost', [PitStopController::class, 'dataProgressAllKaryawanGhost']);
|
||||
Route::get('/pitstop/progress-detail-ghost', [PitStopController::class, 'progressDetailGhost']);
|
||||
Route::get('/pitstop/progress-detail-external-ghost', [PitStopController::class, 'progressDetailExternal']);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user