halaman-psikolog #1

Merged
Mahayoga merged 52 commits from halaman-psikolog into master 2026-07-06 12:37:30 +07:00
4 changed files with 391 additions and 46 deletions
Showing only changes of commit 6c41ac4cf3 - Show all commits

View File

@ -11,6 +11,39 @@
class FinishUjianController extends Controller
{
public function getNotAnswered(Request $request) {
$data_session = TestSessionsModel::where('id_test_sessions', $request->id_test_sessions)->first();
if($data_session != null) {
if($data_session->status_session == '0') {
return response()->json([
'status' => false,
'message' => 'Data sesi tes dinonaktifkan. Silahkan cek status dengan kode untuk informasi lebih lanjut.'
]);
} else if($data_session->status_session == '2') {
$soal = DataSoalModel::all();
$data_ujian = [];
foreach($soal as $detail) {
$data_soal = DetailTestModel::where('id_soal', $detail->id_soal)->where('id_test_sessions', $request->id_test_sessions)->first();
if($data_soal == null) {
$data_ujian[] = [
'id_soal' => $detail->id_soal,
'soal' => $detail->pertanyaan,
];
}
}
return response()->json([
'status' => true,
'data' => $data_ujian
]);
}
} else {
return response()->json([
'status' => false,
'message' => 'Data sesi tes tidak ditemukan.'
]);
}
}
public function getAllAnswer(Request $request) {
$data_session = TestSessionsModel::where('id_test_sessions', $request->id_test_sessions)->first();
if($data_session != null) {
@ -80,6 +113,7 @@ public function index(Request $request)
$data_booking = BookingModel::where('id_booking', $data_session->id_booking)->first();
$data_information = [
'kode' => $data_booking->kode_unik,
'nama' => $data_booking->nama_lengkap,
'email' => $data_booking->email,
'no_hp' => $data_booking->no_telp,
@ -113,10 +147,13 @@ public function index(Request $request)
}
}
$data_aswered = [
'total_question' => $question_count,
'answered' => $answered,
'unanswered' => $soalTidakTerjawab,
'totalScore' => $totalScore
];
$data_booking = BookingModel::where('id_booking', $data_session->id_booking)->first();
if($data_session->status_session == '0') {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes dinonaktifkan. Silahkan cek status dengan kode untuk informasi lebih lanjut.');
} else if($data_session->status_session == '1') {
@ -124,8 +161,14 @@ public function index(Request $request)
'status_session' => '2',
'is_active' => '0'
]);
$data_booking->update([
'status_tes' => '2'
]);
return view('user.pages.finish_ujian.index', compact('id_session', 'difference', 'data_information', 'screen_dim', 'data_aswered'));
} else if($data_session->status_session == '2') {
$data_booking->update([
'status_tes' => '2'
]);
return view('user.pages.finish_ujian.index', compact('id_session', 'difference', 'data_information', 'screen_dim', 'data_aswered'));
}
} else {

View File

@ -198,9 +198,22 @@ function searchUserStatus() {
$('#result_test_form').show();
}
} else if(response.status_data == 2) {
let test_session = getTestSession(response.id_booking);
$('#alert_status').removeClass();
$('#alert_status').addClass('alert alert-success');
$('#alert_status').html('Kamu sudah melakukan tes, dan bisa cek hasil dengan tombol dibawah');
$('#result_test_status').html('Selesai');
$('#result_test_status').removeClass();
$('#result_test_status').addClass('fw-bold text-white bg-success p-2 rounded-pill');
let test_url = '{{ route('hasil-tes.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
$('#result_test_form').hide();
$('#result_test_link').show();
$('#result_test_link').html('Tes Sudah Selesai, Klik untuk melihat hasil');
$('#result_test_link').attr('href', test_url.replace('__ID_TEST_SESSIONS__', test_session.id_test_sessions));
$('#result_test').show();
}
} else {
Swal.fire({

View File

@ -35,7 +35,7 @@
<nav class="breadcrumbs">
<div class="container">
<ol>
<li><a href="index.html">Home</a></li>
<li><a href="{{ route('beranda.index') }}">Home</a></li>
<li class="current">Hasil Tes</li>
</ol>
</div>
@ -44,24 +44,125 @@
<!-- About Section -->
<section id="about" class="about section">
<div class="container">
<div class="container mt-5">
<h1 class="text-center mb-4">
Prediksi & Analisis Kecemasan
</h1>
<div class="row g-4">
<!-- STAI Score -->
<div class="col-md-4">
<div class="card h-100 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div class="col-md-10">
<h4 class="card-title">
Skor STAI-T
</h4>
<h2 class="mt-4">
{{ $data_aswered['totalScore'] }}
</h2>
<p class="text-muted">
Hasil dari kuesioner kecemasan
</p>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-clipboard2-pulse fs-3"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Anxiety Level -->
<div class="col-md-4">
<div class="card h-100 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div class="col-md-10">
<h4 class="card-title">
Tingkat Kecemasan
</h4>
@if ($data_aswered['totalScore'] >= 20)
<h2 class="mt-4 text-success">
Normal
</h2>
@elseif ($data_aswered['totalScore'] <= 44)
<h2 class="mt-4 text-warning">
Sedang
</h2>
@elseif ($data_aswered['totalScore'] <= 80)
<h2 class="mt-4 text-danger">
Tinggi
</h2>
@endif
<p class="text-muted">
Berdasarkan skor <a href="https://headway.co/resources/state-trait-anxiety-inventory-scoring" target="_blank"><i>STAI-T</i></a>
</p>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-emoji-neutral fs-3"></i>
</div>
</div>
</div>
</div>
</div>
<!-- AI Prediction -->
<div class="col-md-4">
<div class="card h-100 shadow-sm">
<div class="card-body">
<div class="d-flex justify-content-between align-items-start">
<div class="col-md-10">
<h4 class="card-title">
Prediksi AI
</h4>
<h5 class="mt-4">
Belum tersedia
</h5>
<p class="text-muted">
Model AI masih dalam tahap pengembangan
</p>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-cpu fs-3"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-md-12">
<h2 class="title text-center">Detail Tes/Ujian kamu</h2>
<div class="row">
<div class="col-md-4 col-6 rounded p-3">
<div class="container border border-primary rounded h-100 p-2 bg-custom">
<h3>Informasi Pribadi</h3>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Informasi Pribadi</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-person-vcard fs-4"></i>
</div>
</div>
<ul class="list-unstyled">
<li><strong>Kode Booking:</strong> {{ $data_information['kode'] }}</li>
<li><strong>Nama:</strong> {{ $data_information['nama'] }}</li>
<li><strong>Email:</strong> {{ $data_information['email'] }}</li>
<li><strong>Nomor Handphone:</strong> {{ $data_information['no_hp'] }}</li>
</ul>
</div>
</div>
<div class="col-md-4 col-6 rounded p-3">
<div class="container border border-primary rounded h-100 p-2 bg-custom">
<h3>Informasi Ujian</h3>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Informasi Ujian</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-clipboard fs-4"></i>
</div>
</div>
<ul class="list-unstyled">
<li><strong>Durasi Ujian:</strong> {{ $difference }}</li>
<li><strong>Resolusi Layar (saat ujian):</strong> {{ $screen_dim['width'] }} x {{ $screen_dim['height'] }}</li>
@ -69,44 +170,108 @@
</ul>
</div>
</div>
<div class="col-md-4 col-6 primary p-3">
<div class="container border border-success rounded h-100 p-2 bg-custom">
<h3>Hasil Ujian (STAI-T)</h3>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Hasil Ujian (STAI-T)</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-easel fs-4"></i>
</div>
</div>
<ul class="list-unstyled">
<li><strong>Total Skor:</strong> {{ $data_aswered['totalScore'] }}</li>
<li><strong>Jumlah Soal:</strong> {{ $data_aswered['total_question'] }}</li>
<li><strong>Soal terjawab:</strong> {{ $data_aswered['answered'] }}</li>
<li><strong>Soal tidak terjawab:</strong> {{ $data_aswered['unanswered'] }}</li>
<li><strong>Total Skor:</strong> {{ $data_aswered['totalScore'] }}</li>
</ul>
</div>
</div>
</div>
<div class="row">
<div class="stats-grid">
<div class="stat-card">
<h3>Avg Velocity</h3>
<p id="avgVelocity"></p>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Avg Velocity</h5>
</div>
<div class="stat-card">
<h3>Fixation Ratio</h3>
<p id="fixationRatio"></p>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-speedometer2 fs-4"></i>
</div>
<div class="stat-card">
<h3>Total Eye Distance</h3>
<p id="totalDistance"></p>
</div>
<div class="stat-card">
<h3>Most Viewed Area</h3>
<p id="mostViewedArea"></p>
<h4 id="avgVelocity"></h4>
<div class="row mt-2">
<div class="col-md-12">
<div class="btn btn-link p-0" onclick="showInsight('velocity')"><i class="bi bi-info-circle"></i> Lihat Insight</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Fixation Ratio</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-bullseye fs-4"></i>
</div>
</div>
<h4 id="fixationRatio"></h4>
<div class="row mt-2">
<div class="col-md-12">
<div class="btn btn-link p-0" onclick="showInsight('fixation')"><i class="bi bi-info-circle"></i> Lihat Insight</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Total Eye Distance</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-arrows-fullscreen fs-4"></i>
</div>
</div>
<h4 id="totalDistance"></h4>
<div class="row mt-2">
<div class="col-md-12">
<div class="btn btn-link p-0" onclick="showInsight('distance')"><i class="bi bi-info-circle"></i> Lihat Insight</div>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="bg-custom p-4 my-3 border rounded">
<div class="row">
<div class="col-md-10">
<h5 class="text-body">Most Viewed Area</h5>
</div>
<div class="col-md-2 d-flex justify-content-center align-items-center bg-primary-subtle border border primary rounded-circle" style="aspect-ratio: 1/1;">
<i class="bi bi-geo-alt fs-4"></i>
</div>
</div>
<h4 id="mostViewedArea"></h4>
<div class="row mt-2">
<div class="col-md-12">
<div class="btn btn-link p-0" onclick="showInsight('area')"><i class="bi bi-info-circle"></i> Lihat Insight</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container" data-aos="fade-up" data-aos-delay="100">
</div>
</div>
<div class="container mt-5" data-aos="fade-up" data-aos-delay="100">
<div class="row">
<div class="col-lg-12">
<h2 class="title text-center">Tabel soal yang telah dijawab</h2>
</div>
<div class="col-md-12 mt-2">
<table class="table" id="table-data-hasil-ujian">
<thead>
<tr>
@ -120,16 +285,34 @@
</table>
</div>
<div class="container">
<div class="col-lg-12">
<h2 class="title text-center">Tabel soal yang tidak dijawab</h2>
</div>
<div class="col-md-12 mt-2">
<table class="table" id="table-data-soal-not-answer">
<thead>
<tr>
<th>No</th>
<th>Pertanyaan</th>
<th>Jawaban</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-lg-12">
<h2 class="title">Grafik Kecepatan Mata</h2>
<h2 class="title text-center">Grafik Kecepatan Mata</h2>
<canvas id="velocityChart"></canvas>
</div>
<div class="col-lg-12 mt-5">
<h2 class="title">Heatmap Pergerakan Mata</h2>
<h2 class="title text-center">Heatmap Pergerakan Mata</h2>
<div style="position: relative; aspect-ratio: 16/9;">
<img src="{{ asset('assets/users/assets/img/overlay/overlay.png') }}" style="width:100%; height:100%; object-fit: cover;">
<img src="{{ asset('assets/users/assets/img/overlay/overlay.png') }}" style="width:100%; height:100%; object-fit: cover; position: absolute;">
<div id="heatmapChart" style="aspect-ratio: 16/9;"></div>
</div>
</div>
@ -246,6 +429,85 @@ function renderStats(stats) {
.innerText = stats.most_viewed_area;
}
function showInsight(type) {
let title = null;
let html = null;
if(type === "velocity") {
title = "Avg Velocity";
html = `
<p>
Rata-rata kecepatan gerakan mata selama ujian.
</p>
<hr>
<b>Nilai tinggi:</b>
<p>
Mata aktif berpindah area,
Aktivitas visual tinggi
</p>
<b>Nilai rendah:</b>
<p>
Fokus lebih stabil,
Gerakan mata lebih tenang
</p>
`;
} else if(type === "fixation") {
title = "Fixation Ratio";
html = `
<p>
Persentase waktu mata berada pada area tertentu.
</p>
<hr>
<b>Semakin tinggi:</b>
<p>
Fokus lebih lama pada suatu area,
Perhatian lebih stabil
</p>
`;
}
else if(type === "distance") {
title = "Total Eye Distance";
html = `
<p>
Total jarak perpindahan mata selama ujian.
</p>
<hr>
<b>Nilai besar:</b>
<p>
Mata banyak menjelajah layar,
Aktivitas visual tinggi
</p>
`;
}
else if(type === "area") {
title = "Most Viewed Area";
html = `
<p>
Area layar yang paling sering dilihat selama ujian.
</p>
<hr>
<b>Insight:</b>
<p>
Menunjukkan fokus utama pengguna,
Dapat membantu memahami pola perhatian
</p>
`;
} else {
title = "Huh?";
html = `<h1>Hello There :D</h1>`;
}
Swal.fire({
title: title,
html: html,
icon: 'info',
showConfirmButton: true,
});
}
$(document).ready(function() {
table = new DataTable("#table-data-hasil-ujian", {
searching: false,
@ -298,6 +560,32 @@ function renderStats(stats) {
]
});
table = new DataTable("#table-data-soal-not-answer", {
searching: false,
paging: false,
ajax: {
url: '{{ route('hasil-tes.getNotAnswered', ['id_test_sessions' => $id_session]) }}',
dataSrc: 'data' // Specify the key containing the data array
},
columns: [
{
data: null,
render: function(data, type, row, meta) {
return meta.row + 1;
}
},
{
data: 'soal'
},
{
data: null,
render: function(data, type, row, meta) {
return `<span class="badge text-bg-secondary">Tidak dijawab</span>`;
}
}
]
});
ws.onopen = () => {
console.log("Connected to WebSocket");
Swal.fire({

View File

@ -46,6 +46,7 @@
Route::get('ujian/fetch/navigation-field', [HalamanUjianController::class, 'getNavigationField'])->name('ujian.navigationField');
Route::resource('hasil-tes', FinishUjianController::class)->only(['index', 'show']);
Route::get('hasil-tes/get/all-answer', [FinishUjianController::class, 'getAllAnswer'])->name('hasil-tes.getAllAnswer');
Route::get('hasil-tes/get/all-not-answer', [FinishUjianController::class, 'getNotAnswered'])->name('hasil-tes.getNotAnswered');
Route::middleware(['auth', 'role.auth'])->group(function() {
Route::resource('dashboard', DashboardController::class);
Route::resource('users', UsersController::class);