Compare commits

..

No commits in common. "master" and "template" have entirely different histories.

71 changed files with 970 additions and 15345 deletions

View File

@ -28,7 +28,7 @@ public function create(Request $request): View
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
public function store(Request $request): RedirectResponse
{
$request->validate([
'token' => ['required'],
@ -51,17 +51,12 @@ function (User $user) use ($request) {
}
);
return response()->json([
'status' => $status == Password::PASSWORD_RESET,
'msg' => $status == Password::PASSWORD_RESET ? 'Password reset successful' : 'Password reset failed'
]);
// If the password was successfully reset, we will redirect the user back to
// the application's home authenticated view. If there is an error we can
// redirect them back to where they came from with their error message.
// return $status == Password::PASSWORD_RESET
// ? redirect()->route('login')->with('status', __($status))
// : back()->withInput($request->only('email'))
// ->withErrors(['email' => __($status)]);
return $status == Password::PASSWORD_RESET
? redirect()->route('login')->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}

View File

@ -23,7 +23,7 @@ public function create(): View
*
* @throws \Illuminate\Validation\ValidationException
*/
public function store(Request $request)
public function store(Request $request): RedirectResponse
{
$request->validate([
'email' => ['required', 'email'],
@ -36,14 +36,9 @@ public function store(Request $request)
$request->only('email')
);
return response()->json([
'status' => $status == Password::RESET_LINK_SENT,
'msg' => __($status)
]);
// return $status == Password::RESET_LINK_SENT
// ? back()->with('status', __($status))
// : back()->withInput($request->only('email'))
// ->withErrors(['email' => __($status)]);
return $status == Password::RESET_LINK_SENT
? back()->with('status', __($status))
: back()->withInput($request->only('email'))
->withErrors(['email' => __($status)]);
}
}

View File

@ -1,193 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Mail\SendUniqueCode;
use App\Models\BookingModel;
use App\Models\TestSessionsModel;
use Carbon\Carbon;
use Generator;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
class BookingController extends Controller
{
/**
* Getch Data Booking
*/
public function getchData() {
$data = BookingModel::get();
$data_ = $data->toArray();
foreach($data_ as $key => $value) {
if(time() > $value['unix_expired_time'] && $value['status_tes'] != '2') {
$data_session = TestSessionsModel::where('id_booking', $value['id_booking'])->first();
$data_booking = BookingModel::where('id_booking', $value['id_booking'])->first();
if($data_session != null) {
$data_session->update([
'status_session' => '2',
'is_active' => '0'
]);
$data_booking->update([
'status_tes' => '2'
]);
} else {
$data_booking->update([
'status_tes' => '0'
]);
}
}
}
$data = BookingModel::orderBy('updated_at', 'desc')->get();
return response()->json([
'status' => true,
'data' => $data->toArray()
]);
}
/**
* Random Char and Number
*/
public function generateCode() {
$kode_unik = '';
$charABC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
for($i = 0; $i < 6; $i++) {
$randNum = random_int(0, 1);
if($randNum == 0) {
$kode_unik .= $charABC[random_int(0, strlen($charABC) - 1)];
} else if($randNum == 1) {
$kode_unik .= str(random_int(0, 9));
}
}
$dataAvl = BookingModel::find($kode_unik, 'kode_unik');
if($dataAvl != null) {
$this->generateCode();
} else {
return $kode_unik;
}
}
/**
* Display a listing of the resource.
*/
public function index()
{
return view('admin.pages.data_booking.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
$request->validate([
'nama_lengkap' => ['required', 'string'],
'email' => ['required', 'string'],
'no_telp' => ['required', 'string'],
'tgl_booking' => ['required', 'string'],
'deskripsi_tambahan' => ['required', 'string']
]);
$kode_unik = $this->generateCode();
$tgl_request = Carbon::parse($request->tgl_booking)->timestamp + 86399;
BookingModel::create([
'nama_lengkap' => $request->nama_lengkap,
'email' => $request->email,
'no_telp' => $request->no_telp,
'tgl_booking' => $request->tgl_booking,
'deskripsi_tambahan' => $request->deskripsi_tambahan,
'kode_unik' => $kode_unik,
'unix_expired_time' => $tgl_request
]);
Mail::to($request->email)->send(new SendUniqueCode(
$request->nama_lengkap,
$kode_unik,
date('H:i:s', $tgl_request - 86399),
date('H:i:s', $tgl_request),
$request->tgl_booking,
));
return response()->json([
'status' => true,
'msg' => 'Booking success!'
]);
} catch(\Exception $e) {
return response()->json([
'status' => false,
'msg' => $e->getMessage()
]);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$data = BookingModel::where('id_booking', $id)->first();
return response()->json([
'status' => true,
'data' => $data
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$data = BookingModel::where('id_booking', $id)->first();
return response()->json([
'status' => true,
'data' => $data
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$request->validate([
'status_tes' => ['required']
]);
$data = BookingModel::where('id_booking', $id)->first();
$data->update([
'status_tes' => str($request->status_tes)
]);
return response()->json([
'status' => true,
'msg' => 'Data berhasil diedit'
]);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
BookingModel::where('id_booking', $id)->delete();
return response()->json([
'status' => true,
'msg' => 'Data berhasil dihapus'
]);
}
}

View File

@ -1,97 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookingModel;
use Illuminate\Http\Request;
class CekStatusController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
return view('user.pages.cek_status.index');
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$data = BookingModel::where('kode_unik', $id)->first();
if($data != null) {
if($data->status_tes == '1' && $data->unix_expired_time < time()) { // Lebih dari exp
$data->update([
'status_tes' => '0'
]);
} else if($data->status_tes == '1' && time() < ($data->unix_expired_time - 86399)) { // Kurang dari exp 00.00
$data->update([
'status_tes' => '0'
]);
} else if($data->status_tes == '0' && time() > ($data->unix_expired_time - 86399) && time() < ($data->unix_expired_time)) {
$data->update([
'status_tes' => '1'
]);
}
return response()->json([
'status' => true,
'msg' => 'Data ditemukan (' . $id . ')',
'id_booking' => $data->id_booking,
'status_data' => $data->status_tes,
'nama_lengkap' => $data->nama_lengkap,
'kode_unik' => $data->kode_unik,
'tgl_booking' => $data->tgl_booking,
'start_test' => date('H:i:s', $data->unix_expired_time - 86399),
'end_test' => date('H:i:s', $data->unix_expired_time),
'deskripsi_tambahan' => $data->deskripsi_tambahan,
]);
} else {
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan (' . $id . ')'
]);
}
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -2,90 +2,10 @@
namespace App\Http\Controllers;
use App\Models\BookingModel;
use App\Models\LogKecemasanModel;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
class DashboardController extends Controller
{
public function getDataForDashboardTable()
{
$data_booking = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d') . '%')->get();
$result = [];
foreach ($data_booking as $booking) {
$status_session = '0';
$data_sessions = TestSessionsModel::where('id_booking', $booking->id_booking)->first();
if($data_sessions != null) {
$status_session = $data_sessions->status_session;
}
$result[] = [
'nama_lengkap' => $booking->nama_lengkap,
'email' => $booking->email,
'no_telp' => $booking->no_telp,
'tanggal_booking' => $booking->created_at->format('Y-m-d'),
'status_session' => $status_session,
'status_tes' => $booking->status_tes,
];
}
return response()->json([
'status' => true,
'data' => $result
]);
}
public function getDataDashboard()
{
$data_booking_today = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d') . '%')->count();
$data_booking_yesterday = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d', strtotime('-1 day')) . '%')->count();
$data_booking_month = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m') . '%')->count();
$booking_diff = $data_booking_month - $data_booking_today;
$booking_percent = $data_booking_month > 0 ? ($booking_diff / $data_booking_month) * 100 : 0;
$data_tes_today = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d') . '%')->where('status_tes', '2')->count();
$data_tes_yesterday = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d', strtotime('-1 day')) . '%')->where('status_tes', '2')->count();
$data_tes_month = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m') . '%')->where('status_tes', '2')->count();
$tes_diff = $data_tes_month - $data_tes_today;
$tes_percent = $data_tes_month > 0 ? ($tes_diff / $data_tes_month) * 100 : 0;
$data_tes_berlangsung_today = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d') . '%')->where('status_tes', '1')->count();
$data_tes_berlangsung_yesterday = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m-d', strtotime('-1 day')) . '%')->where('status_tes', '1')->count();
$data_tes_berlangsung_month = BookingModel::where('created_at', 'LIKE', '%' . date('Y-m') . '%')->where('status_tes', '1')->count();
$tes_berlangsung_diff = $data_tes_berlangsung_month - $data_tes_berlangsung_today;
$tes_berlangsung_percent = $data_tes_berlangsung_month > 0 ? ($tes_berlangsung_diff / $data_tes_berlangsung_month) * 100 : 0;
$data_rata_rata_kecemasan_today = LogKecemasanModel::where('created_at', 'LIKE', '%' . date('Y-m-d') . '%')->avg('skor_kecemasan');
$data_rata_rata_kecemasan_yesterday = LogKecemasanModel::where('created_at', 'LIKE', '%' . date('Y-m-d', strtotime('-1 day')) . '%')->avg('skor_kecemasan');
$data_rata_rata_kecemasan_month = LogKecemasanModel::where('created_at', 'LIKE', '%' . date('Y-m') . '%')->avg('skor_kecemasan');
$rata_rata_kecemasan_diff = $data_rata_rata_kecemasan_month - $data_rata_rata_kecemasan_today;
$rata_rata_kecemasan_percent = $data_rata_rata_kecemasan_month > 0 ? ($rata_rata_kecemasan_diff / $data_rata_rata_kecemasan_month) * 100 : 0;
return response()->json([
'total_booking' => $data_booking_today,
'booking_percent' => number_format($booking_percent, 1),
'booking_diff' => $booking_diff,
'booking_trend' => $booking_diff >= 0 ? 'bertambah' : 'berkurang',
'from_month_booking_count' => $data_booking_month,
'total_tes' => $data_tes_today,
'tes_percent' => number_format($tes_percent, 1),
'tes_diff' => $tes_diff,
'tes_trend' => $tes_diff >= 0 ? 'bertambah' : 'berkurang',
'from_month_tes_count' => $data_tes_month,
'total_tes_berlangsung' => $data_tes_berlangsung_today,
'tes_berlangsung_percent' => number_format($tes_berlangsung_percent, 1),
'tes_berlangsung_diff' => $tes_berlangsung_diff,
'tes_berlangsung_trend' => $tes_berlangsung_diff >= 0 ? 'bertambah' : 'berkurang',
'from_month_tes_berlangsung_count' => $data_tes_berlangsung_month,
'rata_rata_kecemasan' => number_format($data_rata_rata_kecemasan_today, 1),
'rata_rata_kecemasan_percent' => number_format($rata_rata_kecemasan_percent, 1),
'rata_rata_kecemasan_diff' => number_format($rata_rata_kecemasan_diff, 1),
'rata_rata_kecemasan_trend' => $rata_rata_kecemasan_diff >= 0 ? 'bertambah' : 'berkurang',
'from_month_rata_rata_kecemasan' => number_format($data_rata_rata_kecemasan_month, 1),
]);
}
/**
* Display a listing of the resource.
*/

View File

@ -14,7 +14,7 @@ class DataSoalController extends Controller
public function getData() {
$data = DataSoalModel::get();
return response()->json([
'status' => true,
'status' => true,
'data' => $data->toArray()
]);
}
@ -46,7 +46,7 @@ public function store(Request $request)
'jawaban_c' => $request->jawaban_c,
'jawaban_d' => $request->jawaban_d,
'jawaban_e' => $request->jawaban_e,
'is_reverse' => $request->is_reverse,
'jawaban_benar' => $request->jawaban_benar,
]);
return response()->json([
@ -91,7 +91,7 @@ public function update(Request $request, string $id)
'jawaban_c' => $request->jawaban_c,
'jawaban_d' => $request->jawaban_d,
'jawaban_e' => $request->jawaban_e,
'is_reverse' => $request->is_reverse,
'jawaban_benar' => $request->jawaban_benar,
]);
return response()->json([

View File

@ -1,283 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookingModel;
use App\Models\DataSoalModel;
use App\Models\DetailTestModel;
use App\Models\LogKecemasanModel;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
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,
'skor' => 0
];
}
}
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) {
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') {
$detail_test = DetailTestModel::where('id_test_sessions', $request->id_test_sessions)->get();
$data_ujian = [];
foreach($detail_test as $detail) {
$data_soal = DataSoalModel::where('id_soal', $detail->id_soal)->first();
$data_jawaban = $detail->jawaban;
$skor = null;
if($data_jawaban == 'a') {
$data_jawaban = $data_soal->jawaban_a;
$skor = 1;
} else if($data_jawaban == 'b') {
$data_jawaban = $data_soal->jawaban_b;
$skor = 2;
} else if($data_jawaban == 'c') {
$data_jawaban = $data_soal->jawaban_c;
$skor = 3;
} else if($data_jawaban == 'd') {
$data_jawaban = $data_soal->jawaban_d;
$skor = 4;
} else if($data_jawaban == 'e') {
$data_jawaban = $data_soal->jawaban_e;
} else {
$data_jawaban = 'Tidak menjawab';
}
if($detail->jawaban == 'a' && $data_soal->is_reverse == 1) {
$skor = 4;
} else if($detail->jawaban == 'b' && $data_soal->is_reverse == 1) {
$skor = 3;
} else if($detail->jawaban == 'c' && $data_soal->is_reverse == 1) {
$skor = 2;
} else if($detail->jawaban == 'd' && $data_soal->is_reverse == 1) {
$skor = 1;
}
$data_ujian[] = [
'id_soal' => $detail->id_soal,
'jawaban' => $data_jawaban,
'is_reverse' => $data_soal->is_reverse,
'skor' => $skor,
'jawaban_key' => $detail->jawaban,
'soal' => $data_soal->pertanyaan
];
}
return response()->json([
'status' => true,
'data' => $data_ujian
]);
}
} else {
return response()->json([
'status' => false,
'message' => 'Data sesi tes tidak ditemukan.'
]);
}
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$id_session = null;
if(session('id_test_sessions') != null) {
$id_session = session('id_test_sessions');
} else if($request->id_test_sessions != null) {
$id_session = $request->id_test_sessions;
} else {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
}
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
if($data_session != null) {
$start = strtotime($data_session->created_at);
$end = strtotime($data_session->updated_at);
$difference = gmdate("i:s", $end - $start);
$data_booking = BookingModel::where('id_booking', $data_session->id_booking)->first();
if($data_booking != null) {
if($data_booking->status_tes == '0') {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan atau telah dinonaktifkan.');
}
}
$data_information = [
'kode' => $data_booking->kode_unik,
'nama' => $data_booking->nama_lengkap,
'email' => $data_booking->email,
'no_hp' => $data_booking->no_telp,
];
$screen_dim = [
'width' => $data_session->screen_w,
'height' => $data_session->screen_h
];
$answered = DetailTestModel::where('id_test_sessions', $id_session)->where('jawaban', '!=', null)->count();
$question_count = DataSoalModel::all()->count();
$soalTerjawab = $answered;
$soalTidakTerjawab = $question_count - $answered;
$totalScore = 0;
$detail_test = DetailTestModel::where('id_test_sessions', $request->id_test_sessions)->get();
foreach($detail_test as $detail) {
$data_soal = DataSoalModel::where('id_soal', $detail->id_soal)->first();
$data_jawaban = $detail->jawaban;
if($data_soal->is_reverse == 1) {
if($data_jawaban == 'a') {
$totalScore += 4;
} else if($data_jawaban == 'b') {
$totalScore += 3;
} else if($data_jawaban == 'c') {
$totalScore += 2;
} else if($data_jawaban == 'd') {
$totalScore += 1;
} else if($data_jawaban == 'e') {
$totalScore += 0;
}
} else {
if($data_jawaban == 'a') {
$totalScore += 1;
} else if($data_jawaban == 'b') {
$totalScore += 2;
} else if($data_jawaban == 'c') {
$totalScore += 3;
} else if($data_jawaban == 'd') {
$totalScore += 4;
} else if($data_jawaban == 'e') {
$totalScore += 5;
}
}
}
$data_aswered = [
'total_question' => $question_count,
'answered' => $answered,
'unanswered' => $soalTidakTerjawab,
'totalScore' => $totalScore
];
$log_kecemasan = LogKecemasanModel::where('id_test_sessions', $id_session)->first();
if($log_kecemasan == null) {
LogKecemasanModel::create([
'id_booking' => $data_session->id_booking,
'id_test_sessions' => $id_session,
'start_timestamp' => $start,
'end_timestamp' => $end,
'difference_timestamp' => $end - $start,
'screen_width' => $data_session->screen_w,
'screen_height' => $data_session->screen_h,
'answered_count' => $answered,
'not_answered_count' => $soalTidakTerjawab,
'total_question' => $question_count,
'skor_kecemasan' => $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') {
$data_session->update([
'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 {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan.');
}
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -1,372 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\BookingModel;
use App\Models\DataSoalModel;
use App\Models\DetailTestModel;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
class HalamanUjianController extends Controller
{
function fetchQuestion(Request $request) {
$data_question = DataSoalModel::all();
if($data_question != null) {
$number_question = $request->question_index;
if($number_question <= 0 || $number_question > count($data_question)) {
$number_question = 1;
}
return response()->json([
'status' => true,
'data' => $data_question[$number_question - 1]
]);
} else {
return response()->json([
'status' => false,
'message' => 'Data soal tidak ditemukan.'
]);
}
}
public function getCurrentAnswer(Request $request) {
$data_choice = DataSoalModel::where('id_soal', $request->id_question)->get();
$choices = [];
if($data_choice != null) {
foreach($data_choice as $choice) {
if($choice->jawaban_a != null) {
$choices[] = [
'key' => 'a',
'value' => $choice->jawaban_a
];
}
if($choice->jawaban_b != null) {
$choices[] = [
'key' => 'b',
'value' => $choice->jawaban_b
];
}
if($choice->jawaban_c != null) {
$choices[] = [
'key' => 'c',
'value' => $choice->jawaban_c
];
}
if($choice->jawaban_d != null) {
$choices[] = [
'key' => 'd',
'value' => $choice->jawaban_d
];
}
if($choice->jawaban_e != null) {
$choices[] = [
'key' => 'e',
'value' => $choice->jawaban_e
];
}
}
} else {
return response()->json([
'status' => false,
'jawaban' => null,
'choices' => null
]);
}
$data_answer = DetailTestModel::where('id_soal', $request->id_question)
->where('id_test_sessions', $request->session_id)
->first();
if($data_answer != null) {
return response()->json([
'status' => true,
'jawaban' => $data_answer->jawaban,
'choices' => $choices
]);
} else {
return response()->json([
'status' => true,
'jawaban' => null,
'choices' => $choices
]);
}
}
public function getNavigationField(Request $request) {
$id_session = null;
if(session('session_id') != null) {
$id_session = session('session_id');
} else if($request->session_id != null) {
$id_session = $request->session_id;
} else {
return response()->json([
'status' => false,
'msg' => 'Test session id tidak ditemukan'
]);
}
$data_soal = DataSoalModel::all();
$result = [];
$index = 1;
foreach($data_soal as $soal) {
$data_jawaban = DetailTestModel::where(['id_soal' => $soal->id_soal, 'id_test_sessions' => $id_session])->first();
if($data_jawaban != null) {
$result[] = [
'index' => $index,
'answered' => true,
'data' => $data_jawaban
];
} else {
$result[] = [
'index' => $index,
'answered' => false
];
}
$index += 1;
}
return response()->json([
'status' => true,
'data' => $result
]);
}
public function getTimeLeft(Request $request) {
$data_session = TestSessionsModel::where('id_test_sessions', $request->session_id)->first();
if($data_session != null) {
if($data_session->status_session != '1') {
return response()->json([
'status' => 'error',
'message' => 'Data sesi tes belum dimulai atau telah usai. Silahkan cek status dengan kode untuk informasi lebih lanjut.'
]);
} else if($data_session->status_session == '1') {
if($data_session->is_active == '1') {
$time_left = $data_session->unix_end_time - time();
if($time_left <= 0) {
$data_session->update([
'status_session' => '2',
'is_active' => '0'
]);
return response()->json([
'status' => 'error',
'message' => 'Waktu sesi tes telah habis. Silahkan cek status dengan kode untuk informasi lebih lanjut.'
]);
} else {
return response()->json([
'status' => 'success',
'time_left' => $data_session->unix_end_time
]);
}
} else {
return response()->json([
'status' => 'error',
'message' => 'Sesi tes belum aktif. Silahkan mulai tes terlebih dahulu.'
]);
}
}
} else {
return response()->json([
'status' => 'error',
'message' => 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.'
]);
}
}
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
$id_session = null;
if(session('id_test_sessions') != null) {
$id_session = session('id_test_sessions');
} else if($request->id_test_sessions != null) {
$id_session = $request->id_test_sessions;
} else {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
}
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
if($data_session != null) {
if($data_session->status_session != '1') {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes belum dimulai atau telah usai. Silahkan cek status dengan kode untuk informasi lebih lanjut.');
} else if($data_session->status_session == '1') {
if($data_session->is_active == '0') {
$data_session->update([
'is_active' => '1',
'unix_start_time' => time(),
'unix_end_time' => time() + (20 * 60)
]);
} else if($data_session->is_active == '1') {
if(time() > $data_session->unix_end_time) {
$data_booking = BookingModel::where('id_booking', $data_session->id_booking)->first();
$data_session->update([
'status_session' => '2',
'is_active' => '0'
]);
$data_booking->update([
'status_tes' => '2'
]);
return redirect()->route('cek-status.index')->with('error', 'Waktu sesi tes telah habis. Silahkan cek status dengan kode untuk informasi lebih lanjut.');
}
}
}
} else {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
}
// $question_number = null;
// $data_question = null;
// if(session('question') != null) {
// $question_number = session('question');
// } else if($request->question != null) {
// $question_number = $request->question;
// } else {
// $question_number = 1;
// }
// $data_question = DataSoalModel::all();
// $answered_question = [];
// $index_question = 1;
// foreach($data_question as $detail) {
// $detail_answer = DetailTestModel::where('id_soal', $detail->id_soal)
// ->where('id_test_sessions', $id_session)
// ->first();
// if($detail_answer != null) {
// $answered_question[] = [
// 'id_soal' => $detail->id_soal,
// 'nomor_soal' => $index_question,
// 'answered' => true,
// 'jawaban' => $detail_answer->jawaban
// ];
// } else {
// $answered_question[] = [
// 'id_soal' => $detail->id_soal,
// 'nomor_soal' => $index_question,
// 'answered' => false,
// 'jawaban' => null
// ];
// }
// $index_question++;
// }
// $total_question = null;
// $is_last_question = false;
// if($question_number <= 0 || $question_number > count($data_question)) {
// $question_number = 1;
// }
// if(count($data_question) == $question_number) {
// $is_last_question = true;
// }
// $total_question = count($data_question);
// $data_question = $data_question[$question_number - 1];
// $answer = [];
// if($data_question->jawaban_a != null) {
// $answer[] = [
// 'key' => 'a',
// 'value' => $data_question->jawaban_a
// ];
// }
// if($data_question->jawaban_b != null) {
// $answer[] = [
// 'key' => 'b',
// 'value' => $data_question->jawaban_b
// ];
// }
// if($data_question->jawaban_c != null) {
// $answer[] = [
// 'key' => 'c',
// 'value' => $data_question->jawaban_c
// ];
// }
// if($data_question->jawaban_d != null) {
// $answer[] = [
// 'key' => 'd',
// 'value' => $data_question->jawaban_d
// ];
// }
// if($data_question->jawaban_e != null) {
// $answer[] = [
// 'key' => 'e',
// 'value' => $data_question->jawaban_e
// ];
// }
// dd($answer);
return view("user.pages.ujian.temp_index", compact('data_session'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$data_session = TestSessionsModel::where('id_test_sessions', $request->session_id)->first();
if($data_session != null) {
if($data_session->status_session != '1') {
return response()->json([
'status' => 'error',
'message' => 'Data sesi tes belum dimulai atau telah usai. Silahkan cek status dengan kode untuk informasi lebih lanjut.'
]);
}
DetailTestModel::updateOrCreate(
[
'id_soal' => $request->id_question,
'id_test_sessions' => $request->session_id
],
[
'jawaban' => $request->jawaban_final
]
);
} else {
return response()->json([
'status' => 'error',
'message' => 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.'
]);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -2,34 +2,10 @@
namespace App\Http\Controllers;
use App\Models\BookingModel;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
class HasilTesController extends Controller
{
public function fetchData() {
$data_booking = BookingModel::orderBy('updated_at', 'desc')->get();
$result = [];
foreach($data_booking as $booking) {
$data_test = TestSessionsModel::where('id_booking', $booking->id_booking)->first();
if($data_test != null) {
$result[] = [
'id_test_session' => $data_test->id_test_sessions,
'nama_lengkap' => $booking->nama_lengkap,
'tgl_tes' => $data_test->created_at->format('d-m-Y'),
'jam_tes' => $data_test->created_at->format('H:i'),
'kode_booking' => $booking->kode_unik,
'status_tes' => $booking->status_tes
];
}
}
return response()->json([
'status' => true,
'data' => $result
]);
}
/**
* Display a listing of the resource.
*/
@ -59,20 +35,7 @@ public function store(Request $request)
*/
public function show(string $id)
{
$data = TestSessionsModel::where('id_test_sessions', $id)->first();
if($data != null) {
$data_booking = BookingModel::where('id_booking', $data->id_booking)->first();
return response()->json([
'status' => true,
'nama' => $data_booking->nama_lengkap
]);
}
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan!'
]);
//
}
/**
@ -96,21 +59,6 @@ public function update(Request $request, string $id)
*/
public function destroy(string $id)
{
$data = TestSessionsModel::where('id_test_sessions', $id)->first();
if($data != null) {
$data_booking = BookingModel::where('id_booking', $data->id_booking)->first();
$data_booking->update([
'status_tes' => '0'
]);
return response()->json([
'status' => true,
'msg' => 'Data berhasil dinonaktifkan'
]);
}
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan!'
]);
//
}
}

View File

@ -1,112 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
class TestSessionsController extends Controller
{
public function getScreen(Request $request) {
$data = TestSessionsModel::where('id_test_sessions', $request->id_test_sessions)->first();
if($data != null) {
return response()->json([
'status' => true,
'screen_w' => $data->screen_w,
'screen_h' => $data->screen_h
]);
} else {
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan!'
]);
}
}
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$request->validate([
'id_booking' => 'required|exists:booking,id_booking',
]);
$testSession = TestSessionsModel::create([
'id_booking' => $request->id_booking,
'status_session' => '0',
'is_active' => '0',
'screen_w' => $request->screen_w,
'screen_h' => $request->screen_h
]);
return redirect()->route('tutorial-tes.index')->with([
'id_booking' => $testSession->id_booking,
'id_test_sessions' => $testSession->id_test_sessions,
'token_session' => $testSession->token_session,
]);
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$data = TestSessionsModel::where('id_booking', $id)->first();
if($data != null) {
return response()->json([
'status' => true,
'msg' => 'Data ditemukan (' . $id . ')',
'status_session' => $data->status_session,
'token_session' => $data->token_session,
'id_booking' => $data->id_booking,
'id_test_sessions' => $data->id_test_sessions,
]);
}
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan (' . $id . ')',
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class TobiiDataController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -1,140 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\TestSessionsModel;
use App\Models\TobiiDataModel;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class TobiiReceiverController extends Controller
{
/**
* Fetch eye tracking data from database.
*/
public function fetchDataTobii($id_test_sessions)
{
$data_tobii = TobiiDataModel::where('id_test_sessions', $id_test_sessions)->orderByDesc('timestamp')->first();
if ($data_tobii) {
Log::info('DATA DIAMBIL WEB', [
'timestamp_data' => $data_tobii->timestamp,
'created_at' => $data_tobii->created_at,
'time_now' => now()->timestamp * 1000
]);
return response()->json([
'status' => true,
'msg' => 'Data tobii ditemukan (' . $id_test_sessions . ')',
'gaze_x' => $data_tobii->gaze_x,
'gaze_y' => $data_tobii->gaze_y,
]);
} else {
return response()->json([
'status' => false,
'msg' => 'Data tobii tidak ditemukan (' . $id_test_sessions . ')',
]);
}
}
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
try {
$data_sessions = TestSessionsModel::where('id_test_sessions', $request->id_test_sessions)->first();
if($data_sessions != null) {
if($request->token_session == $data_sessions->token_session) {
if($data_sessions->status_session == '1') {
$is_valid = '0';
if($data_sessions->is_active == '1') {
$is_valid = '1';
}
// simpan data tobii ke db
$data_tobii = TobiiDataModel::create([
'gaze_x' => $request->gaze_x,
'gaze_y' => $request->gaze_y,
'timestamp' => Carbon::createFromTimestampMs($request->timestamp),
'is_valid' => $is_valid,
'id_test_sessions' => $request->id_test_sessions,
]);
Log::info('DATA MASUK API', [
'timestamp_client' => Carbon::createFromTimestampMs($request->timestamp),
'time_server' => now()->timestamp * 1000
]);
return response()->json(['message' => 'Data tobii berhasil disimpan.'], 200);
} else {
return response()->json(['message' => 'Sesi tes belum aktif.'], 403);
}
} else {
return response()->json(['message' => 'Token sesi tidak valid.'], 401);
}
} else {
return response()->json(['message' => 'Data sesi tes tidak ditemukan.'], 404);
}
} catch(\Exception $e) {
return response()->json(['message' => 'Terjadi kesalahan saat menyimpan data tobii.', 'error' => $e->getMessage()], 500);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$data_tobii = TobiiDataModel::where('id_test_sessions', $id)->orderByDesc('timestamp')->first();
if ($data_tobii && $data_tobii->timestamp->lt(now()->subSeconds(20))) {
return response()->json([
'status' => false,
'msg' => 'Data tobii kadaluarsa (' . $id . ')',
'connected' => false,
]);
}
return response()->json([
'status' => true,
'connected' => true,
'msg' => 'Data tobii ditemukan (' . $id . ')',
'data_tobii' => $data_tobii,
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -1,90 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\TestSessionsModel;
use Illuminate\Http\Request;
class TutorialTesController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(Request $request)
{
/**
* TODO
* 1. simpan sesi tobii di db
* 2. simpan data mata lewat db
* 3. di tabel session harus ada is_active atau lainnya biar nanti kalo misal aktif ujian, data mata di terima dan langsung dimasukkan wifi
* 4. pada backend tobii, masukin token dan id yang ada di tabel session, biar nanti di compare cocok atau tidak
* 5. itu aja sih
*/
$id_session = null;
if(session('id_test_sessions') != null) {
$id_session = session('id_test_sessions');
} else if($request->id_test_sessions != null) {
$id_session = $request->id_test_sessions;
} else {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
}
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
if($data_session != null) {
if($data_session->status_session == '0') {
$data_session->update(['status_session' => '1']);
}
} else {
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
}
return view('user.pages.tutorial_tes.index', compact('data_session'));
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@ -4,7 +4,6 @@
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class UsersController extends Controller
{
@ -12,7 +11,7 @@ class UsersController extends Controller
* Display data for javascript ajax
*/
public function getData() {
$data = User::where('id', '!=', Auth::user()->id)->get();
$data = User::get();
return response()->json([
'status' => true,
'data' => $data->toArray()
@ -40,18 +39,7 @@ public function create()
*/
public function store(Request $request)
{
$data = User::create([
'name' => $request->name,
'email' => $request->email,
'role' => $request->role,
'alamat' => $request->alamat,
'password' => bcrypt('password', ['rounds' => 12])
]);
return response()->json([
'status' => true,
'msg' => 'Data berhasil di tambahkan'
]);
//
}
/**
@ -86,8 +74,7 @@ public function update(Request $request, string $id)
$data = User::where('id', $id)->update([
'name' => $request->name,
'email' => $request->email,
'role' => $request->role,
'alamat' => $request->alamat
'role' => $request->role
]);
return response()->json([

View File

@ -1,62 +0,0 @@
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class SendUniqueCode extends Mailable
{
use Queueable, SerializesModels;
/**
* Create a new message instance.
*/
public function __construct(public string $name, public string $code, public string $startExpirationTime, public string $endExpirationTime, public string $tglExpired)
{
}
/**
* Get the message envelope.
*/
public function envelope(): Envelope
{
return new Envelope(
subject: 'Selamat datang di Smart Anxiety',
);
}
/**
* Get the message content definition.
*/
public function content(): Content
{
return new Content(
view: 'layouts.mail-send-code',
with: [
'code' => $this->code,
'name' => $this->name,
'startExpirationTime' => $this->startExpirationTime,
'endExpirationTime' => $this->endExpirationTime,
'tglExpired' => $this->tglExpired
],
);
}
/**
* Get the attachments for the message.
*
* @return array<int, Attachment>
*/
public function attachments(): array
{
return [];
}
}

View File

@ -1,50 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class BookingModel extends Model
{
protected $table = 'booking';
protected $primaryKey = 'id_booking';
protected $keyType = 'string';
public $incrementing = false;
protected $fillable = [
'nama_lengkap',
'email',
'no_telp',
'kode_unik',
'tgl_booking',
'deskripsi_tambahan',
'status_tes',
'unix_expired_time'
];
protected $casts = [
'id_booking' => 'string',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_booking)) {
$model->id_booking = Str::uuid();
}
if(empty($model->status_tes)) {
$model->status_tes = '1';
}
if(empty($model->unix_expired_time)) {
$model->unix_expired_time = (string) (time() + 86399); // Set expiration time to 24 hour from now
}
});
}
}

View File

@ -1,38 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class DetailTestModel extends Model
{
protected $table = 'detail_test';
protected $primaryKey = 'id_detail_test';
protected $keyType = 'string';
public $incrementing = false;
protected $fillable = [
'id_detail_test',
'id_soal',
'id_test_sessions',
'jawaban'
];
protected $casts = [
'id_detail_test' => 'string',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_detail_test)) {
$model->id_detail_test = Str::uuid();
}
});
}
}

View File

@ -1,47 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class LogKecemasanModel extends Model
{
protected $table = 'log_hasil_kecemasan';
protected $primaryKey = 'id_log_kecemasan';
protected $keyType = 'string';
public $incrementing = false;
protected $fillable = [
'id_log_kecemasan',
'id_booking',
'id_test_sessions',
'start_timestamp',
'end_timestamp',
'difference_timestamp',
'screen_width',
'screen_height',
'answered_count',
'not_answered_count',
'total_question',
'skor_kecemasan'
];
protected $casts = [
'id_log_kecemasan' => 'string',
'id_booking' => 'string',
'id_test_sessions' => 'string',
];
public static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_log_kecemasan)) {
$model->id_log_kecemasan = (string) \Illuminate\Support\Str::uuid();
}
});
}
}

View File

@ -1,51 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TestSessionsModel extends Model
{
protected $table = 'test_sessions';
protected $primaryKey = 'id_test_sessions';
protected $keyType = 'string';
public $incrementing = false;
protected $fillable = [
'status_session',
'token_session',
'id_booking',
'unix_start_time',
'is_active',
'unix_end_time',
'screen_w',
'screen_h'
];
protected $casts = [
'id_test_sessions' => 'string',
'id_booking' => 'string',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_test_sessions)) {
$model->id_test_sessions = (string) \Illuminate\Support\Str::uuid();
}
if (empty($model->token_session)) {
$model->token_session = \Illuminate\Support\Str::random(50);
}
if (empty($model->is_active)) {
$model->is_active = '0';
}
});
}
}

View File

@ -1,46 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class TobiiDataModel extends Model
{
protected $table = 'tobii_data';
protected $primaryKey = 'id_tobii_data';
protected $keyType = 'string';
public $incrementing = false;
protected $fillable = [
'id_tobii_data',
'gaze_x',
'gaze_y',
'timestamp',
'id_test_sessions',
'is_valid',
];
protected $casts = [
'id_tobii_data' => 'string',
'gaze_x' => 'float',
'gaze_y' => 'float',
'timestamp' => 'datetime',
'id_test_sessions' => 'string',
];
protected static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_tobii_data)) {
$model->id_tobii_data = (string) \Illuminate\Support\Str::uuid();
}
if (empty($model->is_valid)) {
$model->is_valid = '0';
}
});
}
}

View File

@ -21,8 +21,7 @@ class User extends Authenticatable
'name',
'email',
'password',
'role',
'alamat'
'role'
];
/**
@ -47,14 +46,4 @@ protected function casts(): array
'password' => 'hashed',
];
}
public static function boot()
{
parent::boot();
static::creating(function ($model) {
if (empty($model->id_user)) {
$model->id_user = (string) \Illuminate\Support\Str::uuid();
}
});
}
}

View File

@ -15,10 +15,6 @@
$middleware->alias([
'role.auth' => RoleAuth::class,
]);
$middleware->validateCsrfTokens(except: [
'api/eye/test',
'tobii-receiver'
]);
})
->withExceptions(function (Exceptions $exceptions): void {
//

676
composer.lock generated

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -65,7 +65,7 @@
|
*/
'timezone' => 'Asia/Jakarta',
'timezone' => 'UTC',
/*
|--------------------------------------------------------------------------

View File

@ -1,31 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('booking', function (Blueprint $table) {
$table->uuid('id_booking')->primary();
$table->string('nama_lengkap');
$table->string('email');
$table->string('no_telp');
$table->string('kode_unik', 6);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('booking');
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->date('tgl_booking')->after('no_telp');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->dropColumn('tgl_booking');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->text('deskripsi_tambahan')->after('no_telp');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->dropColumn('deskripsi_tambahan');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->enum('status_tes', [0, 1, 2]);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->dropColumn('status_tes');
});
}
};

View File

@ -1,33 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('test_sessions', function (Blueprint $table) {
$table->uuid('id_test_sessions')->primary();
$table->enum('status_session', [0, 1, 2]);
$table->string('token_session', 50)->unique();
$table->uuid('id_booking');
$table->timestamps();
// Foreign Key
$table->foreign('id_booking')->references('id_booking')->on('booking')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('test_sessions');
}
};

View File

@ -1,34 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('tobii_data', function (Blueprint $table) {
$table->uuid('id_tobii_data')->primary();
$table->string('gaze_x')->nullable()->default(0);
$table->string('gaze_y')->nullable()->default(0);
$table->string('timestamp');
$table->uuid('id_test_sessions');
$table->timestamps();
// Foreign key constraint
$table->foreign('id_test_sessions')->references('id_test_sessions')->on('test_sessions')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('tobii_data');
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->string('is_active')->default('0')->after('token_session');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->dropColumn('is_active');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('tobii_data', function (Blueprint $table) {
$table->enum('is_valid', ['0', '1'])->default('0')->after('timestamp');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('tobii_data', function (Blueprint $table) {
$table->dropColumn('is_valid');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->text('pertanyaan')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->string('pertanyaan', 255)->change();
});
}
};

View File

@ -1,34 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('detail_test', function (Blueprint $table) {
$table->dropForeign(['id_test']);
$table->dropColumn('id_test');
$table->char('id_test_sessions', 36)->after('id_soal');
$table->foreign('id_test_sessions')->references('id_test_sessions')->on('test_sessions')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('detail_test', function (Blueprint $table) {
$table->dropForeign(['id_test_sessions']);
$table->dropColumn('id_test_sessions');
$table->unsignedBigInteger('id_test')->after('id_soal');
$table->foreign('id_test')->references('id_test')->on('test')->onDelete('cascade');
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('detail_test', function (Blueprint $table) {
$table->foreign('id_soal')->references('id_soal')->on('soal')->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('detail_test', function (Blueprint $table) {
$table->dropForeign(['id_soal']);
});
}
};

View File

@ -1,30 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->char('unix_start_time', 20)->default(0)->after('token_session');
$table->char('unix_end_time', 20)->default(0)->after('is_active');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->dropColumn('unix_start_time');
$table->dropColumn('unix_end_time');
});
}
};

View File

@ -1,36 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->string('jawaban_a')->nullable()->change();
$table->string('jawaban_b')->nullable()->change();
$table->string('jawaban_c')->nullable()->change();
$table->string('jawaban_d')->nullable()->change();
$table->string('jawaban_e')->nullable()->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->string('jawaban_a')->change();
$table->string('jawaban_b')->change();
$table->string('jawaban_c')->change();
$table->string('jawaban_d')->change();
$table->string('jawaban_e')->change();
});
}
};

View File

@ -1,28 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->char('unix_expired_time', 20)->after('kode_unik');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('booking', function (Blueprint $table) {
$table->dropColumn('unix_expired_time');
});
}
};

View File

@ -1,30 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->char('screen_w', 20)->after('unix_end_time');
$table->char('screen_h', 20)->after('screen_w');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('test_sessions', function (Blueprint $table) {
$table->dropColumn('screen_w');
$table->dropColumn('screen_h');
});
}
};

View File

@ -1,30 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->enum('jawaban_benar', [0, 1])->default(0)->change();
$table->renameColumn('jawaban_benar', 'is_reverse');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('soal', function (Blueprint $table) {
$table->renameColumn('is_reverse', 'jawaban_benar');
$table->enum('jawaban_benar', ['a', 'b', 'c', 'd', 'e'])->change();
});
}
};

View File

@ -1,38 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('log_hasil_kecemasan', function (Blueprint $table) {
$table->uuid('id_log_kecemasan')->primary();
$table->uuid('id_booking');
$table->uuid('id_test_sessions');
$table->char('start_timestamp', 20);
$table->char('end_timestamp', 20);
$table->char('difference_timestamp', 20);
$table->char('screen_width', 10);
$table->char('screen_height', 10);
$table->integer('answered_count');
$table->integer('not_answered_count');
$table->integer('total_question');
$table->integer('skor_kecemasan');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('log_hasil_kecemasan');
}
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,9 +1,9 @@
<nav class="pc-sidebar">
<div class="navbar-wrapper">
<div class="m-header">
<a href="{{ route('dashboard.index') }}" class="b-brand text-primary fs-3 fw-bold text-dark">
<a href="{{ route('dashboard.index') }}" class="b-brand text-primary">
<!-- ======== Change your logo from here ============ -->
{{ env('APP_NAME') }}
<img src="{{ asset('assets/admin/assets/images/logo-dark.svg') }}" class="img-fluid logo-lg" alt="logo" id="logo-admin">
</a>
</div>
<div class="navbar-content">
@ -29,12 +29,6 @@
@endif
@if(Auth::user()->role == 'psikolog')
<li class="pc-item">
<a href="{{ route('booking.index') }}" class="pc-link">
<span class="pc-micon"><i class="ti ti-credit-card"></i></span>
<span class="pc-mtext">Data Booking</span>
</a>
</li>
<li class="pc-item">
<a href="{{ route('soal.index') }}" class="pc-link">
<span class="pc-micon"><i class="ti ti-credit-card"></i></span>

View File

@ -24,15 +24,10 @@
<div class="col-md-6 col-xl-3">
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">Total Booking hari ini</h6>
<h4 class="mb-3">
<span id="total_booking"></span>
<span class="badge bg-light-primary border border-primary">
<i class="ti" id="trending-icon-booking"></i>
<span id="booking_percent">%</span>
</span>
</h4>
<p class="mb-0 text-muted text-sm">Booking <span id="booking_trend">bertambah</span> <span class="text-primary" id="from_month_booking_count"></span> dari bulan lalu
<h6 class="mb-2 f-w-400 text-muted">Total Page Views</h6>
<h4 class="mb-3">4,42,236 <span class="badge bg-light-primary border border-primary"><i
class="ti ti-trending-up"></i> 59.3%</span></h4>
<p class="mb-0 text-muted text-sm">You made an extra <span class="text-primary">35,000</span> this year
</p>
</div>
</div>
@ -40,146 +35,271 @@
<div class="col-md-6 col-xl-3">
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">Total tes selesai hari ini</h6>
<h4 class="mb-3">
<span id="total_tes"></span>
<span class="badge bg-light-primary border border-primary">
<i class="ti" id="trending-icon-tes"></i>
<span id="tes_percent">%</span>
</span>
</h4>
<p class="mb-0 text-muted text-sm">Tes <span id="tes_trend">bertambah</span> <span class="text-primary" id="from_month_tes_count"></span> dari bulan lalu
</p>
<h6 class="mb-2 f-w-400 text-muted">Total Users</h6>
<h4 class="mb-3">78,250 <span class="badge bg-light-success border border-success"><i
class="ti ti-trending-up"></i> 70.5%</span></h4>
<p class="mb-0 text-muted text-sm">You made an extra <span class="text-success">8,900</span> this year</p>
</div>
</div>
</div>
<div class="col-md-6 col-xl-3">
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">Total tes masih berlangsung hari ini</h6>
<h4 class="mb-3">
<span id="total_tes_berlangsung"></span>
<span class="badge bg-light-primary border border-primary">
<i class="ti" id="trending-icon-tes-berlangsung"></i>
<span id="tes_berlangsung_percent">%</span>
</span>
</h4>
<p class="mb-0 text-muted text-sm">Tes yang sedang berlangsung <span id="tes_berlangsung_trend">bertambah</span> <span class="text-primary" id="from_month_tes_berlangsung_count"></span> dari bulan lalu
</p>
<h6 class="mb-2 f-w-400 text-muted">Total Order</h6>
<h4 class="mb-3">18,800 <span class="badge bg-light-warning border border-warning"><i
class="ti ti-trending-down"></i> 27.4%</span></h4>
<p class="mb-0 text-muted text-sm">You made an extra <span class="text-warning">1,943</span> this year</p>
</div>
</div>
</div>
<div class="col-md-6 col-xl-3">
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">Rata rata skor kecemasan hari ini</h6>
<h4 class="mb-3">
<span id="rata_rata_kecemasan"></span>
<span class="badge bg-light-primary border border-primary">
<i class="ti" id="trending-icon-rata-rata"></i>
<span id="rata_rata_kecemasan_percent">%</span>
</span>
</h4>
<p class="mb-0 text-muted text-sm">Rata rata skor kecemasan <span id="rata_rata_kecemasan_trend">bertambah</span> <span class="text-primary" id="from_month_rata_rata_kecemasan_count"></span> dari bulan lalu
<h6 class="mb-2 f-w-400 text-muted">Total Sales</h6>
<h4 class="mb-3">$35,078 <span class="badge bg-light-danger border border-danger"><i
class="ti ti-trending-down"></i> 27.4%</span></h4>
<p class="mb-0 text-muted text-sm">You made an extra <span class="text-danger">$20,395</span> this year
</p>
</div>
</div>
</div>
<div class="col-md-12 col-xl-8">
<h5 class="mb-3">Tabel Monitoring Tes</h5>
<table id="table-data-booking" class="table table-bordered">
<thead>
<tr>
<th>No</th>
<th>Nama</th>
<th>Email</th>
<th>Telepon</th>
<th>Tanggal Booking</th>
<th>Status Tes</th>
<th>Status Sesi</th>
</tr>
</thead>
</table>
<div class="d-flex align-items-center justify-content-between mb-3">
<h5 class="mb-0">Unique Visitor</h5>
<ul class="nav nav-pills justify-content-end mb-0" id="chart-tab-tab" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link" id="chart-tab-home-tab" data-bs-toggle="pill" data-bs-target="#chart-tab-home"
type="button" role="tab" aria-controls="chart-tab-home" aria-selected="true">Month</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link active" id="chart-tab-profile-tab" data-bs-toggle="pill"
data-bs-target="#chart-tab-profile" type="button" role="tab" aria-controls="chart-tab-profile"
aria-selected="false">Week</button>
</li>
</ul>
</div>
<div class="card">
<div class="card-body">
<div class="tab-content" id="chart-tab-tabContent">
<div class="tab-pane" id="chart-tab-home" role="tabpanel" aria-labelledby="chart-tab-home-tab"
tabindex="0">
<div id="visitor-chart-1"></div>
</div>
<div class="tab-pane show active" id="chart-tab-profile" role="tabpanel"
aria-labelledby="chart-tab-profile-tab" tabindex="0">
<div id="visitor-chart"></div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12 col-xl-4">
<h5 class="mb-3">Income Overview</h5>
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">This Week Statistics</h6>
<h3 class="mb-3">$7,650</h3>
<div id="income-overview-chart"></div>
</div>
</div>
</div>
<div class="col-md-12 col-xl-8">
<h5 class="mb-3">Recent Orders</h5>
<div class="card tbl-card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover table-borderless mb-0">
<thead>
<tr>
<th>TRACKING NO.</th>
<th>PRODUCT NAME</th>
<th>TOTAL ORDER</th>
<th>STATUS</th>
<th class="text-end">TOTAL AMOUNT</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Camera Lens</td>
<td>40</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-danger f-10 m-r-5"></i>Rejected</span>
</td>
<td class="text-end">$40,570</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Laptop</td>
<td>300</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-warning f-10 m-r-5"></i>Pending</span>
</td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Mobile</td>
<td>355</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-success f-10 m-r-5"></i>Approved</span></td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Camera Lens</td>
<td>40</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-danger f-10 m-r-5"></i>Rejected</span>
</td>
<td class="text-end">$40,570</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Laptop</td>
<td>300</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-warning f-10 m-r-5"></i>Pending</span>
</td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Mobile</td>
<td>355</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-success f-10 m-r-5"></i>Approved</span></td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Camera Lens</td>
<td>40</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-danger f-10 m-r-5"></i>Rejected</span>
</td>
<td class="text-end">$40,570</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Laptop</td>
<td>300</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-warning f-10 m-r-5"></i>Pending</span>
</td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Mobile</td>
<td>355</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-success f-10 m-r-5"></i>Approved</span></td>
<td class="text-end">$180,139</td>
</tr>
<tr>
<td><a href="#" class="text-muted">84564564</a></td>
<td>Mobile</td>
<td>355</td>
<td><span class="d-flex align-items-center gap-2"><i
class="fas fa-circle text-success f-10 m-r-5"></i>Approved</span></td>
<td class="text-end">$180,139</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div class="col-md-12 col-xl-4">
<h5 class="mb-3">Analytics Report</h5>
<div class="card">
<div class="list-group list-group-flush">
<a href="#"
class="list-group-item list-group-item-action d-flex align-items-center justify-content-between">Company
Finance Growth<span class="h5 mb-0">+45.14%</span></a>
<a href="#"
class="list-group-item list-group-item-action d-flex align-items-center justify-content-between">Company
Expenses Ratio<span class="h5 mb-0">0.58%</span></a>
<a href="#"
class="list-group-item list-group-item-action d-flex align-items-center justify-content-between">Business
Risk Cases<span class="h5 mb-0">Low</span></a>
</div>
<div class="card-body px-2">
<div id="analytics-report-chart"></div>
</div>
</div>
</div>
<div class="col-md-12 col-xl-8">
<h5 class="mb-3">Sales Report</h5>
<div class="card">
<div class="card-body">
<h6 class="mb-2 f-w-400 text-muted">This Week Statistics</h6>
<h3 class="mb-0">$7,650</h3>
<div id="sales-report-chart"></div>
</div>
</div>
</div>
<div class="col-md-12 col-xl-4">
<h5 class="mb-3">Transaction History</h5>
<div class="card">
<div class="list-group list-group-flush">
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex">
<div class="flex-shrink-0">
<div class="avtar avtar-s rounded-circle text-success bg-light-success">
<i class="ti ti-gift f-18"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="mb-1">Order #002434</h6>
<p class="mb-0 text-muted">Today, 2:00 AM</P>
</div>
<div class="flex-shrink-0 text-end">
<h6 class="mb-1">+ $1,430</h6>
<p class="mb-0 text-muted">78%</P>
</div>
</div>
</a>
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex">
<div class="flex-shrink-0">
<div class="avtar avtar-s rounded-circle text-primary bg-light-primary">
<i class="ti ti-message-circle f-18"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="mb-1">Order #984947</h6>
<p class="mb-0 text-muted">5 August, 1:45 PM</P>
</div>
<div class="flex-shrink-0 text-end">
<h6 class="mb-1">- $302</h6>
<p class="mb-0 text-muted">8%</P>
</div>
</div>
</a>
<a href="#" class="list-group-item list-group-item-action">
<div class="d-flex">
<div class="flex-shrink-0">
<div class="avtar avtar-s rounded-circle text-danger bg-light-danger">
<i class="ti ti-settings f-18"></i>
</div>
</div>
<div class="flex-grow-1 ms-3">
<h6 class="mb-1">Order #988784</h6>
<p class="mb-0 text-muted">7 hours ago</P>
</div>
<div class="flex-shrink-0 text-end">
<h6 class="mb-1">- $682</h6>
<p class="mb-0 text-muted">16%</P>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
@endsection
@section('script')
<script>
let table = null;
$(document).ready(function() {
$.get('{{ route("dashboard.fetchData") }}', function(data) {
$('#total_booking').text(data.total_booking);
$('#booking_percent').text(data.booking_percent + '%');
$('#from_month_booking_count').text(data.from_month_booking_count);
$('#booking_trend').text(data.booking_trend);
if (data.booking_diff >= 0) {
$('#trending-icon-booking').addClass('ti-trending-up');
$('#booking_percent').addClass('text-primary');
} else {
$('#trending-icon-booking').addClass('ti-trending-down');
$('#booking_percent').addClass('text-danger');
}
$('#total_tes').text(data.total_tes);
$('#tes_percent').text(data.tes_percent + '%');
$('#from_month_tes_count').text(data.from_month_tes_count);
$('#tes_trend').text(data.tes_trend);
if (data.tes_diff >= 0) {
$('#trending-icon-tes').addClass('ti-trending-up');
$('#tes_percent').addClass('text-primary');
} else {
$('#trending-icon-tes').addClass('ti-trending-down');
$('#tes_percent').addClass('text-danger');
}
$('#total_tes_berlangsung').text(data.total_tes_berlangsung);
$('#tes_berlangsung_percent').text(data.tes_berlangsung_percent + '%');
$('#from_month_tes_berlangsung_count').text(data.from_month_tes_berlangsung_count);
$('#tes_berlangsung_trend').text(data.tes_berlangsung_trend);
if (data.tes_berlangsung_diff >= 0) {
$('#trending-icon-tes-berlangsung').addClass('ti-trending-up');
$('#tes_berlangsung_percent').addClass('text-primary');
} else {
$('#trending-icon-tes-berlangsung').addClass('ti-trending-down');
$('#tes_berlangsung_percent').addClass('text-danger');
}
$('#rata_rata_kecemasan').text(data.rata_rata_kecemasan);
$('#rata_rata_kecemasan_percent').text(data.rata_rata_kecemasan_percent + '%');
$('#from_month_rata_rata_kecemasan_count').text(data.from_month_rata_rata_kecemasan);
$('#rata_rata_kecemasan_trend').text(data.rata_rata_kecemasan_trend);
if (data.rata_rata_kecemasan_diff >= 0) {
$('#trending-icon-rata-rata').addClass('ti-trending-up');
$('#rata_rata_kecemasan_percent').addClass('text-primary');
} else {
$('#trending-icon-rata-rata').addClass('ti-trending-down');
$('#rata_rata_kecemasan_percent').addClass('text-danger');
}
table = new DataTable('#table-data-booking', {
searching: false,
paging: false,
ajax: {
url: '{{ route("dashboard.fetchDataTable") }}',
},
columns: [
{
data: null,
render: function(data, type, row, meta) {
return meta.row + 1;
}
},
{ data: 'nama_lengkap' },
{ data: 'email', name: 'email' },
{ data: 'no_telp' },
{ data: 'tanggal_booking' },
{ data: 'status_tes' },
{ data: 'status_session' },
]
});
});
});
</script>
@endsection

View File

@ -1,357 +0,0 @@
@extends('admin.layouts.app')
@section('content')
<!-- [ breadcrumb ] start -->
<div class="page-header">
<div class="page-block">
<div class="row align-items-center">
<div class="col-md-12">
<div class="page-header-title">
<h5 class="m-b-10">Data Booking Pengguna</h5>
</div>
<ul class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('dashboard.index') }}">Home</a></li>
<li class="breadcrumb-item"><a href="javascript: void(0)">Data Master</a></li>
<li class="breadcrumb-item" aria-current="page">Halaman Data Booking Pengguna</li>
</ul>
</div>
</div>
</div>
</div>
<!-- [ breadcrumb ] end -->
<!-- [ Main Content ] start -->
<div class="row">
<!-- [ sample-page ] start -->
<div class="col-sm-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-md-6">
<h5>Kumpulan Data Booking</h5>
</div>
</div>
</div>
<div class="card-body">
<div class="alert alert-info alert-dismissible fade show" role="alert">
<strong>Note:</strong> Untuk detail lainnya, silahkan tekan tombol info.
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
<table class="table" id="table-data">
<thead>
<tr>
<th>No</th>
<th>Nama Lengkap</th>
<th>Email</th>
<th>No Telp</th>
<th>Kode Unik</th>
<th>Tgl Booking</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<!-- [ sample-page ] end -->
</div>
<!-- [ Main Content ] end -->
<!-- Info Modal -->
<div class="modal fade" id="infoModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Info Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12 my-1">
<label for="info_nama_lengkap" class="form-label">Nama Lengkap</label>
<input disabled type="text" class="form-control" id="info_nama_lengkap" name="info_nama_lengkap">
</div>
<div class="col-md-12 my-1">
<label for="info_email" class="form-label">Email</label>
<input disabled type="text" class="form-control" id="info_email" name="info_email">
</div>
<div class="col-md-12 my-1">
<label for="info_no_telp" class="form-label">Nomor Telepon</label>
<input disabled type="text" class="form-control" id="info_no_telp" name="info_no_telp">
</div>
<div class="col-md-12 my-1">
<label for="info_kode_unik" class="form-label">Kode Unik</label>
<input disabled type="text" class="form-control" id="info_kode_unik" name="info_kode_unik">
</div>
<div class="col-md-12 my-1">
<label for="info_tgl_booking" class="form-label">Tanggal Booking</label>
<input disabled type="text" class="form-control" id="info_tgl_booking" name="info_tgl_booking">
</div>
<div class="col-md-12 my-1">
<label for="info_status_tes" class="form-label">Status</label>
<br>
<button disabled class="btn btn-primary" id="info_status_tes"></button>
</div>
<div class="col-md-12 my-1">
<label for="info_deskripsi_tambahan" class="form-label">Deskripsi Tambahan</label>
<input disabled type="text" class="form-control" id="info_deskripsi_tambahan" name="info_deskripsi_tambahan">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
</div>
</div>
</div>
</div>
<!-- Edit Modal -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Edit Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12 my-1">
<label for="edit_nama_lengkap" class="form-label">Nama Lengkap</label>
<input disabled type="text" class="form-control" id="edit_nama_lengkap" name="edit_nama_lengkap">
</div>
<div class="col-md-12 my-1">
<label for="edit_email" class="form-label">Email</label>
<input disabled type="text" class="form-control" id="edit_email" name="edit_email">
</div>
<div class="col-md-12 my-1">
<label for="edit_no_telp" class="form-label">Nomor Telepon</label>
<input disabled type="text" class="form-control" id="edit_no_telp" name="edit_no_telp">
</div>
<div class="col-md-12 my-1">
<label for="edit_kode_unik" class="form-label">Kode Unik</label>
<input disabled type="text" class="form-control" id="edit_kode_unik" name="edit_kode_unik">
</div>
<div class="col-md-12 my-1">
<label for="edit_tgl_booking" class="form-label">Tanggal Booking</label>
<input disabled type="text" class="form-control" id="edit_tgl_booking" name="edit_tgl_booking">
</div>
<div class="col-md-12 my-1">
<label for="edit_status_tes" class="form-label">Status</label>
<select class="form-select" name="edit_status_tes" id="edit_status_tes">
<option value="0">Nonaktif</option>
<option value="1">Siap/Sedang Tes</option>
<option value="2">Selesai</option>
</select>
</div>
<div class="col-md-12 my-1">
<label for="edit_deskripsi_tambahan" class="form-label">Deskripsi Tambahan</label>
<input disabled type="text" class="form-control" id="edit_deskripsi_tambahan" name="edit_deskripsi_tambahan">
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Tutup</button>
<button type="button" class="btn btn-primary" onclick="simpanEditData()">Simpan</button>
</div>
</div>
</div>
</div>
<!-- Modal Delete -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Hapus Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Apakah anda akan menghapus data booking dengan nama "<span id="delete_booking" class="fw-bold"></span>" ini?
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-danger" onclick="hapusData()">Hapus</button>
</div>
</div>
</div>
</div>
@endsection
@section('script')
<script>
let table = null;
let idEdit = null;
let idHapus = null;
let status_dict = ['secondary', 'info', 'success'];
let status_dict_text = ['Nonaktif', 'Siap/Sedang Tes', 'Selesai'];
$(document).ready(function() {
table = new DataTable("#table-data", {
ajax: {
url: '{{ route('booking.fetchData') }}',
},
columns: [
{
data: null,
render: function(data, type, row, meta) {
return meta.row + 1;
}
},
{
data: 'nama_lengkap'
},
{
data: 'email'
},
{
data: 'no_telp'
},
{
data: 'kode_unik'
},
{
data: 'tgl_booking'
},
{
data: null,
render: function(data, type, row, meta) {
return `
<span class="badge rounded-pill text-bg-${status_dict[data.status_tes]}">${status_dict_text[data.status_tes]}</span>
`;
}
},
{
data: null,
render: function(data, type, row, meta) {
return `
<div class="btn-group">
<button type="button" class="btn btn-primary btn-sm rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#infoModal" onclick="getDataInfo(this)" data-id="${data.id_booking}">
<i class="ti ti-file-info"></i>
</button>
<button type="button" class="btn btn-info btn-sm rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#editModal" onclick="getDataEdit(this)" data-id="${data.id_booking}">
<i class="ti ti-edit"></i>
</button>
<button class="btn btn-sm btn-danger delete-btn rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#deleteModal" onclick="getDataHapus(this)" data-id="${data.id_booking}">
<i class="ti ti-trash"></i>
</button>
</div>
`;
}
}
]
});
});
function fetchRowData() {
table.ajax.reload(null, false);
}
function getDataInfo(btn) {
let idShow = btn.getAttribute('data-id');
let urlShow = '{{ route('booking.show', ['__ID__']) }}';
$.get(urlShow.replace('__ID__', idShow), function(data, status) {
if(data.status) {
$('#info_nama_lengkap').val(data.data.nama_lengkap);
$('#info_email').val(data.data.email);
$('#info_no_telp').val(data.data.no_telp);
$('#info_kode_unik').val(data.data.kode_unik);
$('#info_tgl_booking').val(data.data.tgl_booking);
$('#info_status_tes').html(status_dict_text[data.data.status_tes]);
$('#info_deskripsi_tambahan').val(data.data.deskripsi_tambahan);
$('#info_nama_lengkap').attr('disabled', 'disabled');
$('#info_email').attr('disabled', 'disabled');
$('#info_no_telp').attr('disabled', 'disabled');
$('#info_kode_unik').attr('disabled', 'disabled');
$('#info_tgl_booking').attr('disabled', 'disabled');
$('#info_status_tes').attr('disabled', 'disabled');
$('#info_deskripsi_tambahan').attr('disabled', 'disabled');
$('#info_status_tes').removeClass();
$('#info_status_tes').addClass(`btn btn-${status_dict[data.data.status_tes]}`);
}
});
}
function getDataEdit(btn) {
idEdit = btn.getAttribute('data-id');
let urlEdit = '{{ route('booking.edit', ['__ID__']) }}';
$.get(urlEdit.replace('__ID__', idEdit), function(data, status) {
if(data.status) {
$('#edit_nama_lengkap').val(data.data.nama_lengkap);
$('#edit_email').val(data.data.email);
$('#edit_no_telp').val(data.data.no_telp);
$('#edit_kode_unik').val(data.data.kode_unik);
$('#edit_tgl_booking').val(data.data.tgl_booking);
$('#edit_status_tes').val(data.data.status_tes);
$('#edit_deskripsi_tambahan').val(data.data.deskripsi_tambahan);
$('#edit_nama_lengkap').attr('disabled', 'disabled');
$('#edit_email').attr('disabled', 'disabled');
$('#edit_no_telp').attr('disabled', 'disabled');
$('#edit_kode_unik').attr('disabled', 'disabled');
$('#edit_tgl_booking').attr('disabled', 'disabled');
$('#edit_status_tes').removeAttr('disabled');
$('#edit_deskripsi_tambahan').attr('disabled', 'disabled');
}
});
}
function simpanEditData() {
if(idEdit != null) {
let urlUpdate = '{{ route('booking.update', ['__ID__']) }}';
$.post(urlUpdate.replace('__ID__', idEdit), {
'_token': document.getElementById('_token').getAttribute('value'),
'_method': 'PUT',
'status_tes': $('#edit_status_tes').val()
}, function(data, status) {
if(data.status) {
$('#editModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil di edit!",
icon: "success"
});
fetchRowData();
idEdit = null;
}
});
}
}
function getDataHapus(btn) {
idHapus = btn.getAttribute('data-id');
let urlShow = '{{ route('booking.show', ['__ID__']) }}';
$.get(urlShow.replace('__ID__', idHapus), function(data, status) {
if(data.status) {
$('#delete_booking').html(data.data.nama_lengkap);
}
});
}
function hapusData() {
if(idHapus != null) {
let urlDestroy = '{{ route('booking.destroy', ['__ID__']) }}';
$.post(urlDestroy.replace('__ID__', idHapus), {
'_token': document.getElementById('_token').getAttribute('value'),
'_method': 'DELETE'
}, function(data, status) {
if(data.status) {
$('#deleteModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil dihapus!",
icon: "success"
});
fetchRowData();
idHapus = null;
}
});
}
}
</script>
@endsection

View File

@ -41,13 +41,30 @@
<thead>
<tr>
<th>No</th>
<th>Nama</th>
<th>Kode Unik</th>
<th>Tgl dan Jam Ujian</th>
<th>Status Data</th>
<th>Dummy</th>
<th>Dummy</th>
<th>Dummy</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>lorem</td>
<td>lorem</td>
<td>lorem</td>
<td>
<div class="btn-group">
<button type="button" class="btn btn-info btn-sm rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#editModal" onclick="getDataEdit(this)" data-id="${data.id}">
<i class="ti ti-edit"></i>
</button>
<button class="btn btn-sm btn-danger delete-btn rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#deleteModal" onclick="getDataHapus(this)" data-id="${data.id}">
<i class="ti ti-trash"></i>
</button>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
@ -55,229 +72,10 @@
<!-- [ sample-page ] end -->
</div>
<!-- [ Main Content ] end -->
<!-- Modal Delete -->
<div class="modal fade" id="deleteModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Hapus Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Apakah anda akan menghapus data dengan nama "<span id="delete_test" class="fw-bold"></span>" ini? (data hanya akan dinonaktikan)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-danger" onclick="hapusData()">Hapus</button>
</div>
</div>
</div>
</div>
{{-- <!-- Modal Restore -->
<div class="modal fade" id="restoreModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Restore Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
Apakah anda akan memulihkan data dengan nama "<span id="restore_test" class="fw-bold"></span>" ini? (data akan diperiksa dengan status terakhirnya)
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-danger" onclick="restoreData()">Hapus</button>
</div>
</div>
</div>
</div> --}}
@endsection
@section('script')
<script>
let idHapus = null;
let tableData = null;
let ws = null;
function fetchRowData() {
if(tableData != null) {
tableData.ajax.reload(null, false);
}
}
function getDataInfo(btn) {
let idShow = btn.getAttribute('data-id');
Swal.fire({
title: 'Alert',
icon: 'question',
text: 'Apakah Anda ingin melihat hasil dari data ini?',
confirmButtonText: 'Ya',
cancelButtonText: 'Tidak',
showCancelButton: true,
showCloseButton: true,
}).then((result) => {
if (result.isConfirmed) {
window.open("{{ route('hasil-tes.index') }}?id_test_sessions=" + idShow, "_blank");
}
});
}
function getDataDownload(btn) {
let idShow = btn.getAttribute('data-id');
Swal.fire({
title: 'Alert',
icon: 'question',
text: 'Apakah Anda ingin mendownload hasil dari data ini?',
confirmButtonText: 'Ya',
cancelButtonText: 'Tidak',
showCancelButton: true,
showCloseButton: true,
}).then((result) => {
if (result.isConfirmed) {
ws.send(JSON.stringify({
'type': 'download_hasil_tes',
'id_test_sessions': idShow
}));
}
});
}
function getDataHapus(btn) {
idHapus = btn.getAttribute('data-id');
let urlShow = '{{ route('hasil_tes.show', ['__ID__']) }}';
$.get(urlShow.replace('__ID__', idHapus), function(data, status) {
if(data.status) {
$('#delete_test').html(data.nama);
}
});
}
function hapusData() {
if(idHapus != null) {
let urlDestroy = '{{ route('hasil_tes.destroy', ['__ID__']) }}';
$.post(urlDestroy.replace('__ID__', idHapus), {
'_token': document.getElementById('_token').getAttribute('value'),
'_method': 'DELETE'
}, function(data, status) {
if(data.status) {
$('#deleteModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil dinonakstifkan!",
icon: "success"
});
fetchRowData();
idHapus = null;
}
});
}
}
$(document).ready(function() {
tableData = new DataTable("#table-data", {
'ajax': {
'url': '{{ route('hasil-tes.fetchData') }}'
},
'columns': [
{
data: null,
render: function(data, type, row, meta) {
return meta.row + 1;
}
},
{
data: 'nama_lengkap'
},
{
data: 'kode_booking'
},
{
data: null,
render: function(data, type, row, meta) {
return `${data.tgl_tes} ${data.jam_tes}`;
}
},
{
data: null,
render: function(data, type, row, meta) {
let bgClass = ['secondary', 'warning', 'success'];
let text = ['Nonaktif', 'Dalam Ujian', 'Selesai'];
return `
<span class="badge rounded-pill text-bg-${bgClass[data.status_tes]}">${text[data.status_tes]}</span>
`;
}
},
{
data: null,
render: function(data, type, row, meta) {
if(data.status_tes == 0) {
return `
<div class="btn-group">
<a class="btn btn-info btn-sm rounded-circle mx-1 text-light" onclick="getDataInfo(this)" data-id="${data.id_test_session}">
<i class="ti ti-file-info"></i>
</a>
</div>
`;
}
return `
<div class="btn-group">
<a class="btn btn-info btn-sm rounded-circle mx-1 text-light" onclick="getDataInfo(this)" data-id="${data.id_test_session}">
<i class="ti ti-file-info"></i>
</a>
<button class="btn btn-sm btn-success rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#downloadModal" onclick="getDataDownload(this)" data-id="${data.id_test_session}">
<i class="ti ti-download"></i>
</button>
<button class="btn btn-sm btn-danger delete-btn rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#deleteModal" onclick="getDataHapus(this)" data-id="${data.id_test_session}">
<i class="ti ti-trash"></i>
</button>
</div>
`;
}
},
]
});
console.log("Connecting to WebSocket...");
ws = new WebSocket("{{ env('WEBSOCKET_URL') }}");
ws.onopen = function() {
console.log("WebSocket connection established.");
};
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
if(data.type === 'download_hasil_tes_response') {
if(data.data != null) {
console.log(data)
const blob = new Blob([JSON.stringify(data.data)], { type: 'text/plain;charset=utf-8' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.href = url;
link.download = `hasil_tes_${data.id_test_sessions}.json`;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
Swal.fire({
title: 'Sukses',
text: 'Hasil tes berhasil didownload!',
icon: 'success'
});
} else {
Swal.fire({
title: 'Error',
text: 'Gagal mendownload hasil tes.',
icon: 'error'
});
}
}
};
});
new DataTable("#table-data", {});
</script>
@endsection

View File

@ -93,10 +93,13 @@
<input disabled type="text" class="form-control" id="info_jawaban_e" name="info_jawaban_e">
</div>
<div class="col-md-6 my-1">
<label for="info_is_reverse" class="form-label">Apakah jawaban positif?</label>
<select disabled class="form-select" name="info_is_reverse" id="info_is_reverse">
<option value="0">Tidak</option>
<option value="1">Ya</option>
<label for="info_jawaban_benar" class="form-label">Jawaban Benar</label>
<select disabled class="form-select" name="info_jawaban_benar" id="info_jawaban_benar">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
<option value="d">D</option>
<option value="e">E</option>
</select>
</div>
</div>
@ -143,10 +146,13 @@
<input type="text" class="form-control" id="jawaban_e" name="jawaban_e">
</div>
<div class="col-md-6 my-1">
<label for="is_reverse" class="form-label">Apakah jawaban positif?</label>
<select class="form-select" name="is_reverse" id="is_reverse">
<option value="0">Tidak</option>
<option value="1">Ya</option>
<label for="jawaban_benar" class="form-label">Jawaban Benar</label>
<select class="form-select" name="jawaban_benar" id="jawaban_benar">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
<option value="d">D</option>
<option value="e">E</option>
</select>
</div>
</div>
@ -194,10 +200,13 @@
<input type="text" class="form-control" id="edit_jawaban_e" name="edit_jawaban_e">
</div>
<div class="col-md-6 my-1">
<label for="is_reverse" class="form-label">Apakah jawaban positif?</label>
<select class="form-select" name="edit_is_reverse" id="edit_is_reverse">
<option value="0">Tidak</option>
<option value="1">Ya</option>
<label for="edit_jawaban_benar" class="form-label">Jawaban Benar</label>
<select class="form-select" name="edit_jawaban_benar" id="edit_jawaban_benar">
<option value="a">A</option>
<option value="b">B</option>
<option value="c">C</option>
<option value="d">D</option>
<option value="e">E</option>
</select>
</div>
</div>
@ -287,7 +296,7 @@ function simpanAddData() {
'jawaban_c': $('#jawaban_c').val(),
'jawaban_d': $('#jawaban_d').val(),
'jawaban_e': $('#jawaban_e').val(),
'is_reverse': $('#is_reverse').val(),
'jawaban_benar': $('#jawaban_benar').val(),
}, function(data, status) {
$('#addModal').modal('hide');
Swal.fire({
@ -310,7 +319,7 @@ function getDataInfo(btn) {
$('#info_jawaban_c').attr('disabled', '');
$('#info_jawaban_d').attr('disabled', '');
$('#info_jawaban_e').attr('disabled', '');
$('#info_is_reverse').attr('disabled', '');
$('#info_jawaban_benar').attr('disabled', '');
$('#info_pertanyaan').val(data.data.pertanyaan);
$('#info_jawaban_a').val(data.data.jawaban_a);
@ -318,7 +327,7 @@ function getDataInfo(btn) {
$('#info_jawaban_c').val(data.data.jawaban_c);
$('#info_jawaban_d').val(data.data.jawaban_d);
$('#info_jawaban_e').val(data.data.jawaban_e);
$('#info_is_reverse').val(data.data.is_reverse);
$('#info_jawaban_benar').val(data.data.jawaban_benar);
$('#info_pertanyaan').attr('disabled', 'disabled');
$('#info_jawaban_a').attr('disabled', 'disabled');
@ -326,7 +335,7 @@ function getDataInfo(btn) {
$('#info_jawaban_c').attr('disabled', 'disabled');
$('#info_jawaban_d').attr('disabled', 'disabled');
$('#info_jawaban_e').attr('disabled', 'disabled');
$('#info_is_reverse').attr('disabled', 'disabled');
$('#info_jawaban_benar').attr('disabled', 'disabled');
}
});
}
@ -343,7 +352,7 @@ function getDataEdit(btn) {
$('#edit_jawaban_c').val(data.data.jawaban_c);
$('#edit_jawaban_d').val(data.data.jawaban_d);
$('#edit_jawaban_e').val(data.data.jawaban_e);
$('#edit_is_reverse').val(data.data.is_reverse);
$('#edit_jawaban_benar').val(data.data.jawaban_benar);
}
});
}
@ -361,7 +370,7 @@ function simpanEditData() {
'jawaban_c': $('#edit_jawaban_c').val(),
'jawaban_d': $('#edit_jawaban_d').val(),
'jawaban_e': $('#edit_jawaban_e').val(),
'is_reverse': $('#edit_is_reverse').val(),
'jawaban_benar': $('#edit_jawaban_benar').val(),
}, function(data, status) {
if(data.status) {
$('#editModal').modal('hide');

View File

@ -25,16 +25,7 @@
<div class="col-sm-12">
<div class="card">
<div class="card-header">
<div class="row">
<div class="col-md-6">
<h5>Data Users</h5>
</div>
<div class="col-md-6 d-flex justify-content-end">
<button class="btn btn-sm btn-info delete-btn rounded-circle mx-1" data-bs-toggle="modal" data-bs-target="#addModal">
<i class="ti ti-database-import"></i>
</button>
</div>
</div>
<h5>Tabel Data</h5>
</div>
<div class="card-body">
<table class="table" id="table-data">
@ -57,45 +48,6 @@
</div>
<!-- [ Main Content ] end -->
<!-- Modal Add -->
<div class="modal fade" id="addModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Add Data</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-6 my-1">
<label for="add_nama_user" class="form-label">Nama User</label>
<input type="text" class="form-control" id="add_nama_user" name="add_nama_user">
</div>
<div class="col-md-6 my-1">
<label for="add_email" class="form-label">Email</label>
<input type="text" class="form-control" id="add_email" name="add_email">
</div>
<div class="col-md-6 my-1">
<label for="add_alamat" class="form-label">Alamat</label>
<input type="text" class="form-control" id="add_alamat" name="add_alamat">
</div>
<div class="col-md-6 my-1">
<label for="add_role" class="form-label">Role</label>
<select class="form-select" name="add_role" id="add_role">
<option value="admin">Admin</option>
<option value="psikolog">Psikolog</option>
</select>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="button" class="btn btn-primary" onclick="simpanAddData()">Simpan</button>
</div>
</div>
</div>
</div>
<!-- Modal Edit -->
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
@ -114,15 +66,12 @@
<label for="edit_email" class="form-label">Email</label>
<input type="text" class="form-control" id="edit_email" name="edit_email">
</div>
<div class="col-md-6 my-1">
<label for="edit_alamat" class="form-label">Alamat</label>
<input type="text" class="form-control" id="edit_alamat" name="edit_alamat">
</div>
<div class="col-md-6 my-1">
<label for="edit_role" class="form-label">Role</label>
<select class="form-select" name="edit_role" id="edit_role">
<option value="admin">Admin</option>
<option value="psikolog">Psikolog</option>
<option value="user">User</option>
</select>
</div>
</div>
@ -218,7 +167,6 @@ function getDataEdit(btn) {
$('#edit_nama_user').val(data.data.name);
$('#edit_email').val(data.data.email);
$('#edit_role').val(data.data.role);
$('#edit_alamat').val(data.data.alamat);
}
});
}
@ -233,30 +181,6 @@ function getDataHapus(btn) {
});
}
function simpanAddData() {
$.post('{{ route('users.store') }}', {
'_token': document.getElementById('_token').getAttribute('value'),
'name': $('#add_nama_user').val(),
'email': $('#add_email').val(),
'role': $('#add_role').val(),
'alamat': $('#add_alamat').val()
}, function(data, status) {
if(data.status) {
$('#addModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil ditambahkan!",
icon: "success"
});
fetchRowData();
$('#add_nama_user').val('');
$('#add_email').val('');
$('#add_role').val('admin');
$('#add_alamat').val('');
}
});
}
function simpanEditData() {
if(idEdit != null) {
let urlUpdate = '{{ route('users.update', ['__ID__']) }}';
@ -265,14 +189,13 @@ function simpanEditData() {
'_method': 'PUT',
'name': $('#edit_nama_user').val(),
'email': $('#edit_email').val(),
'role': $('#edit_role').val(),
'alamat': $('#edit_alamat').val()
'role': $('#edit_role').val()
}, function(data, status) {
if(data.status) {
$('#editModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil diubah!",
text: "Data berhasil ditambahkan!",
icon: "success"
});
fetchRowData();

View File

@ -1,169 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<!-- [Head] start -->
<head>
<title>Lupa Password | {{ env('APP_NAME') }}</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description"
content="Mantis is made using Bootstrap 5 design framework. Download the free admin template & use it for your project.">
<meta name="keywords"
content="Mantis, Dashboard UI Kit, Bootstrap 5, Admin Template, Admin Dashboard, CRM, CMS, Bootstrap Admin Template">
<meta name="author" content="CodedThemes">
<!-- [Favicon] icon -->
<link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
<x-guest-layout>
<div class="mb-4 text-sm text-gray-600 dark:text-gray-400">
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
</div>
</div>
<!-- [ Pre-loader ] End -->
<div class="auth-main">
<div class="auth-wrapper v3">
<div class="auth-form">
<div class="auth-header">
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('password.email') }}">
@csrf
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<div class="card my-5">
<div class="card-body">
<div class="d-flex justify-content-between align-items-end mb-4">
<h3 class="mb-0"><b>Lupa Password</b></h3>
</div>
<div class="form-group mb-3">
<p class="text-muted">Lupa password Anda? Masukkan email Anda dan kami akan mengirimkan link untuk mereset password.</p>
</div>
<div class="form-group mb-3">
<label class="form-label">Email Address</label>
<input type="email" id="email" class="form-control" placeholder="Email Address">
</div>
<div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doForgotPassword()">Kirim Link Reset Password</button>
</div>
</div>
<div class="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Email Password Reset Link') }}
</x-primary-button>
</div>
<div class="auth-footer row">
<!-- <div class=""> -->
<div class="col my-1">
<p class="m-0">Copyright {{ date('Y') }} © <a href="https://polije.ac.id" target="_blank"> Politeknik Negeri Jember</a></p>
</div>
<div class="col-auto my-1">
<ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
</ul>
</div>
<!-- </div> -->
</div>
</div>
</div>
</div>
<!-- [ Main Content ] end -->
<!-- Required Js -->
<script src="{{ asset('assets/admin/assets/js/plugins/popper.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/simplebar.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/bootstrap.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/fonts/custom-font.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/pcoded.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/feather.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>layout_change('light');</script>
<script>change_box_container('false');</script>
<script>layout_rtl_change('false');</script>
<script>preset_change("preset-1");</script>
<script>font_change("Public-Sans");</script>
<script>
function doForgotPassword() {
try {
Swal.fire({
title: "Loading",
text: "Sedang memproses, tunggu sebentar yaa!",
icon: "info",
showConfirmButton: false,
allowOutsideClick: false
});
let token = document.getElementById('_token').getAttribute('value');
let email = document.getElementById('email').value;
if(email == '' || email == null) {
Swal.fire({
title: "Info",
text: "Email tidak boleh kosong!",
icon: "warning"
});
return;
}
let xhttp = new XMLHttpRequest();
let formData = new FormData();
formData.append('_token', token);
formData.append('email', email);
xhttp.onreadystatechange = function() {
if(this.status == 200) {
let jsonData = JSON.parse(this.responseText);
if(jsonData.status) {
Swal.fire({
title: "Info",
text: "Link reset password telah dikirim ke email Anda!",
icon: "success"
});
} else {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, cek email Anda!",
icon: "error"
});
}
} else {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, koneksi ke server gagal, coba lagi nanti!",
icon: "error"
});
}
}
xhttp.open('POST', '{{ route("password.email") }}', false);
xhttp.send(formData);
} catch(error) {
Swal.fire({
title: "Info",
text: "Gagal mengirim link reset password, kesalahan pada server, coba lagi nanti!",
icon: "error"
});
}
}
</script>
</body>
<!-- [Body] end -->
</html>
</form>
</x-guest-layout>

View File

@ -3,7 +3,7 @@
<!-- [Head] start -->
<head>
<title>Login | {{ env('APP_NAME') }}</title>
<title>Login | Smart Anxiety</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
@ -50,7 +50,7 @@
<div class="auth-wrapper v3">
<div class="auth-form">
<div class="auth-header">
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
<a href="#"><img src="{{ asset('assets/admin/assets/images/logo-dark.svg') }}" alt="img"></a>
</div>
<div class="card my-5">
<div class="card-body">
@ -67,7 +67,7 @@
<input type="password" id="password" class="form-control" placeholder="Password">
</div>
<div class="d-flex mt-1 justify-content-between">
<h5 class="text-secondary f-w-400"><a href="{{ route('password.request') }}">Forgot Password?</a></h5>
<h5 class="text-secondary f-w-400">Forgot Password?</h5>
</div>
<div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doLogin()">Login</button>
@ -81,8 +81,8 @@
</div>
<div class="col-auto my-1">
<ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
<li class="list-inline-item"><a href="#">Beranda</a></li>
<li class="list-inline-item"><a href="#">Contact us</a></li>
</ul>
</div>
<!-- </div> -->

View File

@ -1,198 +1,39 @@
<!DOCTYPE html>
<html lang="en">
<!-- [Head] start -->
<x-guest-layout>
<form method="POST" action="{{ route('password.store') }}">
@csrf
<head>
<title>Reset Password | {{ env('APP_NAME') }}</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description"
content="Mantis is made using Bootstrap 5 design framework. Download the free admin template & use it for your project.">
<meta name="keywords"
content="Mantis, Dashboard UI Kit, Bootstrap 5, Admin Template, Admin Dashboard, CRM, CMS, Bootstrap Admin Template">
<meta name="author" content="CodedThemes">
<!-- Password Reset Token -->
<input type="hidden" name="token" value="{{ $request->route('token') }}">
<!-- [Favicon] icon -->
<link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
</div>
</div>
<!-- [ Pre-loader ] End -->
<div class="auth-main">
<div class="auth-wrapper v3">
<div class="auth-form">
<div class="auth-header">
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
</div>
<div class="card my-5">
<div class="card-body">
<div class="d-flex justify-content-between align-items-end mb-4">
<h3 class="mb-0"><b>Reset Password</b></h3>
{{-- <a href="#" class="link-primary">Don't have an account?</a> --}}
</div>
<div class="form-group mb-3">
<label class="form-label">Email Address</label>
<input type="email" id="email" class="form-control" placeholder="Email Address" value="{{ request()->get('email') }}">
</div>
<div class="form-group mb-3">
<label class="form-label">Password</label>
<input type="password" id="password" class="form-control" placeholder="Password">
</div>
<div class="form-group mb-3">
<label class="form-label">Confirm Password</label>
<input type="password" id="password_confirmation" class="form-control" placeholder="Confirm Password">
</div>
<input type="hidden" id="reset_token" value="{{ request()->route('token') }}">
<div class="d-flex mt-1 justify-content-between">
<h5 class="text-secondary f-w-400"><a href="{{ route('password.request') }}">Forgot Password?</a></h5>
</div>
<div class="d-grid mt-4">
<button type="button" class="btn btn-primary" onclick="doResetPassword()">Reset Password</button>
</div>
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
<div class="auth-footer row">
<!-- <div class=""> -->
<div class="col my-1">
<p class="m-0">Copyright {{ date('Y') }} © <a href="https://polije.ac.id" target="_blank"> Politeknik Negeri Jember</a></p>
</div>
<div class="col-auto my-1">
<ul class="list-inline footer-link mb-0">
<li class="list-inline-item"><a href="{{ route('beranda.index') }}">Beranda</a></li>
<li class="list-inline-item"><a href="{{ route('beranda.index') }}#footer">Contact us</a></li>
</ul>
</div>
<!-- </div> -->
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
</div>
</div>
</div>
<!-- [ Main Content ] end -->
<!-- Required Js -->
<script src="{{ asset('assets/admin/assets/js/plugins/popper.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/simplebar.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/bootstrap.min.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/fonts/custom-font.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/pcoded.js') }}"></script>
<script src="{{ asset('assets/admin/assets/js/plugins/feather.min.js') }}"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>layout_change('light');</script>
<script>change_box_container('false');</script>
<script>layout_rtl_change('false');</script>
<script>preset_change("preset-1");</script>
<script>font_change("Public-Sans");</script>
<script>
function doResetPassword() {
try {
let csrfToken = document.getElementById('_token').getAttribute('value');
let resetToken = document.getElementById('reset_token').value;
let email = document.getElementById('email').value;
let password = document.getElementById('password').value;
let password_confirmation = document.getElementById('password_confirmation').value;
if(email == '' || email == null) {
Swal.fire({
title: "Info",
text: "Email tidak boleh kosong!",
icon: "warning"
});
return;
}
if(password == '' || password == null) {
Swal.fire({
title: "Info",
text: "Password tidak boleh kosong!",
icon: "warning"
});
return;
}
if(password !== password_confirmation) {
Swal.fire({
title: "Info",
text: "Password dan konfirmasi password tidak cocok!",
icon: "warning"
});
return;
}
let xhttp = new XMLHttpRequest();
let formData = new FormData();
formData.append('_token', csrfToken);
formData.append('token', resetToken);
formData.append('email', email);
formData.append('password', password);
formData.append('password_confirmation', password_confirmation);
xhttp.onreadystatechange = function() {
if(this.status == 200) {
let jsonData = JSON.parse(this.responseText);
if(jsonData.status) {
Swal.fire({
title: "Info",
text: "Password berhasil direset!",
icon: "success"
});
window.location.href = '{{ route('login') }}';
} else {
Swal.fire({
title: "Info",
text: "Terdapat kesalahan!",
icon: "error"
});
}
} else {
Swal.fire({
title: "Info",
text: "Reset password gagal, koneksi ke server gagal, coba lagi nanti!",
icon: "error"
});
}
}
xhttp.open('POST', '{{ route("password.store") }}', false);
xhttp.send(formData);
} catch(error) {
Swal.fire({
title: "Info",
text: "Reset password gagal, kesalahan pada server, coba lagi nanti!",
icon: "error"
});
}
}
</script>
</body>
<!-- [Body] end -->
</html>
<div class="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Reset Password') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@ -1,273 +0,0 @@
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kode Unik Anda</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
/* background: linear-gradient(135deg, #84cc16 0%, #65a30d 100%); */
padding: 40px 20px;
line-height: 1.6;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background: #ffffff;
border-radius: 16px;
overflow: hidden;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.header {
background: linear-gradient(135deg, #1e3ce6 0%, #b0b8ff 100%);
padding: 40px 30px;
text-align: center;
}
.header h1 {
color: #ffffff;
font-size: 28px;
font-weight: 700;
margin-bottom: 10px;
}
.header p {
color: rgba(255, 255, 255, 0.9);
font-size: 16px;
}
.content {
padding: 50px 40px;
}
.greeting {
font-size: 24px;
color: #2d3748;
font-weight: 600;
margin-bottom: 20px;
}
.message {
color: #4a5568;
font-size: 16px;
margin-bottom: 30px;
line-height: 1.8;
}
.button-container {
text-align: center;
margin: 40px 0;
color: #ffffff;
}
.reset-button {
display: inline-block;
background: linear-gradient(135deg, #84cc16 0%, #65a30d 100%);
color: #ffffff !important;
padding: 16px 48px;
text-decoration: none;
border-radius: 12px;
font-weight: 600;
font-size: 16px;
box-shadow: 0 10px 25px rgba(132, 204, 22, 0.4);
transition: all 0.3s ease;
}
.reset-button:hover {
transform: translateY(-2px);
box-shadow: 0 15px 35px rgba(132, 204, 22, 0.5);
}
.info-box {
background: #f7fee7;
border-left: 4px solid #7065ff;
padding: 20px;
border-radius: 8px;
margin: 30px 0;
}
.info-box .code {
background: #f7fee7;
border-left: 4px solid #7065ff;
padding: 20px;
border-radius: 8px;
margin: 30px 0;
}
.info-box p {
color: #4a5568;
font-size: 14px;
margin: 0;
}
.info-box strong {
color: #2d3748;
}
.warning {
background: #fff5f5;
border-left: 4px solid #f56565;
padding: 15px;
border-radius: 8px;
margin: 20px 0;
}
.warning p {
color: #742a2a;
font-size: 14px;
margin: 0;
}
.alternative-link {
background: #edf2f7;
padding: 20px;
border-radius: 8px;
margin: 30px 0;
}
.alternative-link p {
color: #4a5568;
font-size: 13px;
margin-bottom: 10px;
}
.alternative-link a {
color: #84cc16;
word-break: break-all;
font-size: 12px;
}
.footer {
background: #2d3748;
padding: 40px;
text-align: center;
}
.footer p {
color: #a0aec0;
font-size: 14px;
margin-bottom: 10px;
}
.footer .company-name {
color: #ffffff;
font-weight: 600;
margin-bottom: 20px;
}
.social-links {
margin: 20px 0;
}
.social-links a {
display: inline-block;
margin: 0 10px;
color: #a0aec0;
text-decoration: none;
font-size: 14px;
}
.social-links a:hover {
color: #ffffff;
}
@media only screen and (max-width: 600px) {
body {
padding: 20px 10px;
}
.content {
padding: 30px 20px;
}
.header {
padding: 30px 20px;
}
.header h1 {
font-size: 24px;
}
.greeting {
font-size: 20px;
}
.reset-button {
padding: 14px 36px;
font-size: 15px;
}
}
</style>
</head>
<body>
<div class="email-container">
<!-- Header -->
<div class="header">
<div class="logo">
</div>
<h1>Smart Anxiety</h1>
<p>Sistem Pendeteksi Kecemasan</p>
</div>
<!-- Content -->
<div class="content">
<h2 class="greeting">Halo! 👋</h2>
<p class="message">
🔑 Berikut adalah kode unik Anda untuk verifikasi booking:
</p>
<div class="info-box code">
<h1 style="text-align: center">{{ $code }}</h1>
</div>
<div class="info-box">
<p><strong> Penting:</strong> Kode unik ini akan berlaku pada tanggal <strong>{{ $tglExpired }}</strong>, dari jam <strong>{{ $startExpirationTime }}</strong> sampai <strong>{{ $endExpirationTime }}</strong></p>
</div>
{{-- <div class="warning">
<p><strong>⚠️ Tidak meminta reset password?</strong> Abaikan email ini dan tidak ada perubahan yang akan
dilakukan pada akun Anda.</p>
</div> --}}
{{-- <div class="alternative-link">
<p><strong>Mengalami masalah dengan tombol di atas?</strong></p>
<p>Salin dan tempel URL berikut ke browser Anda:</p>
<a href="{{ $url }}">{{ $url }}</a>
</div> --}}
<p class="message" style="margin-top: 40px; font-size: 14px; color: #718096;">
Salam hangat,<br>
<strong>Tim Smart Anxiety</strong>
</p>
</div>
<!-- Footer -->
<div class="footer">
<p class="company-name">Smart Anxiety</p>
<p>Email ini dikirim secara otomatis, mohon tidak membalas email ini.</p>
<p style="margin-top: 20px; font-size: 12px;">
© {{ date('Y') }} Smart Anxiety. All rights reserved.
</p>
<div class="social-links">
<a href="#">Bantuan</a>
<a href="#">Kebijakan Privasi</a>
<a href="#">Syarat & Ketentuan</a>
</div>
</div>
</div>
</body>
</html>

View File

@ -8,22 +8,23 @@
<div class="col-lg-5">
<div class="brand-section">
<a href="index.html" class="logo d-flex align-items-center mb-4">
<span class="sitename">{{ env('APP_NAME') }}</span>
<span class="sitename">Clinic</span>
</a>
<p class="brand-description">Sistem berbasis web yang membantu proses asesmen kecemasan melalui analisis pergerakan pupil mata menggunakan teknologi eye-tracking dan machine learning.</p>
<p class="brand-description">Crafting exceptional digital experiences through thoughtful design and
innovative solutions that elevate your brand presence.</p>
<div class="contact-info mt-5">
<div class="contact-item">
<i class="bi bi-geo-alt"></i>
<span>Politeknik Negeri Jember, Jurusan Teknologi Informasi, Jl. Mastrip, Krajan Timur, Sumbersari, Kec. Sumbersari, Kabupaten Jember, Jawa Timur</span>
<span>123 Creative Boulevard, Design District, NY 10012</span>
</div>
<div class="contact-item">
<i class="bi bi-telephone"></i>
<span>+62 8233 7341 446</span>
<span>+1 (555) 987-6543</span>
</div>
<div class="contact-item">
<i class="bi bi-envelope"></i>
<span>e31231392@student.polije.ac.id</span>
<span>hello@designstudio.com</span>
</div>
</div>
</div>
@ -33,32 +34,65 @@
<div class="footer-nav-wrapper">
<div class="row">
<div class="col-6 col-lg-5">
<div class="col-6 col-lg-3">
<div class="nav-column">
<h6>Informasi</h6>
<h6>Studio</h6>
<nav class="footer-nav">
<a href="https://maps.app.goo.gl/mLViMQhvs2KUq6An9" target="_blank">Politeknik Negeri Jember</a>
<a href="https://maps.app.goo.gl/2FpPBrs67Akm4PMZ9" target="_blank">Jurusan Teknologi Informasi</a>
<a href="https://jti.polije.ac.id/lab/ksi" target="_blank">Lab. Komputasi Sistem Informasi</a>
<a href="https://maps.app.goo.gl/C3eKW5gSoKqCTRYq8" target="_blank">Poliklinik Politeknik Negeri Jember</a>
<a href="#!">Our Story</a>
<a href="#!">Design Process</a>
<a href="#!">Portfolio</a>
<a href="#!">Case Studies</a>
<a href="#!">Awards</a>
</nav>
</div>
</div>
<div class="col-6 col-lg-5">
<div class="col-6 col-lg-3">
<div class="nav-column">
<h6>Contact Person</h6>
<h6>Services</h6>
<nav class="footer-nav">
<a href="mailto:khafid@polije.ac.id" target="_blank">Khafidurrohman Agustianto, S.Pd, M.Eng</a>
<a href="mailto:myoga.bahtiar@gmail.com" target="_blank">Mahayoga Ksatria Hanafi Bahtiar</a>
<a href="#!">Brand Identity</a>
<a href="#!">Web Design</a>
<a href="#!">Mobile Apps</a>
<a href="#!">Digital Strategy</a>
<a href="#!">Consultation</a>
</nav>
</div>
</div>
<div class="col-6 col-lg-3">
<div class="nav-column">
<h6>Resources</h6>
<nav class="footer-nav">
<a href="#!">Design Blog</a>
<a href="#!">Style Guide</a>
<a href="#!">Free Assets</a>
<a href="#!">Tutorials</a>
<a href="#!">Inspiration</a>
</nav>
</div>
</div>
<div class="col-6 col-lg-3">
<div class="nav-column">
<h6>Connect</h6>
<nav class="footer-nav">
<a href="#!">Start Project</a>
<a href="#!">Schedule Call</a>
<a href="#!">Join Newsletter</a>
<a href="#!">Follow Updates</a>
<a href="#!">Partnership</a>
</nav>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="footer-bottom">
@ -68,7 +102,7 @@
<div class="col-lg-6">
<div class="copyright">
<p>© <span class="sitename">{{ env('APP_NAME') }}</span>. All rights reserved.</p>
<p>© <span class="sitename">Clinic</span>. All rights reserved.</p>
</div>
</div>
@ -78,7 +112,11 @@
<a href="#!">Terms of Service</a>
<a href="#!">Cookie Policy</a>
<div class="credits">
Designed by <a href="https://github.com/Mahayoga" target="_blank">Mahayoga</a>. Distributed by <a href="https://jti.polije.ac.id/lab/ksi" target="_blank">Lab. Komputasi Sistem Informasi</a>
<!-- All the links in the footer should remain intact. -->
<!-- You can delete the links only if you've purchased the pro version. -->
<!-- Licensing information: https://bootstrapmade.com/license/ -->
<!-- Purchase the pro version with working PHP/AJAX contact form: [buy-url] -->
Designed by <a href="https://bootstrapmade.com/">BootstrapMade</a>. Distributed by <a href="https://themewagon.com" target="_blank">ThemeWagon</a>
</div>
</div>
</div>

View File

@ -7,7 +7,6 @@
<title>@yield('title') - Smart Anxiety</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta id="_token" value="{{ csrf_token() }}">
<!-- Favicons -->
<link href="{{ asset('assets/users/assets/img/favicon.png') }}" rel="icon">
@ -28,9 +27,6 @@
<link href="{{ asset('assets/users/assets/vendor/fontawesome-free/css/all.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.css') }}" rel="stylesheet">
<link href="https://cdn.datatables.net/2.3.7/css/dataTables.dataTables.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<!-- Main CSS File -->
<link href="{{ asset('assets/users/assets/css/main.css') }}" rel="stylesheet">
@ -63,9 +59,6 @@ class="bi bi-arrow-up-short"></i></a>
<div id="preloader"></div>
<!-- Vendor JS Files -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="{{ asset('assets/users/assets/vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/php-email-form/validate.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/aos/aos.js') }}"></script>
@ -73,15 +66,9 @@ class="bi bi-arrow-up-short"></i></a>
<script src="{{ asset('assets/users/assets/vendor/purecounter/purecounter_vanilla.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.js') }}"></script>
<script src="https://cdn.datatables.net/2.3.7/js/dataTables.min.js" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/heatmap.js/2.0.1/heatmap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<!-- Main JS File -->
<script src="{{ asset('assets/users/assets/js/main.js') }}"></script>
@yield('script')
</body>
</html>

View File

@ -5,32 +5,32 @@
<div class="contact-info d-flex align-items-center">
<i class="bi bi-envelope d-flex align-items-center"><a
href="mailto:e31231392@student.polije.ac.id">e31231392@student.polije.ac.id</a></i>
<a href="https://wa.me/6282337341446" target="_blank"><i class="bi bi-phone d-flex align-items-center ms-4"><span>+62 8233 7341 446</span></i></a>
<i class="bi bi-phone d-flex align-items-center ms-4"><span>+62 8233 7341 446</span></i>
</div>
<div class="social-links d-none d-md-flex align-items-center">
<a href="https://github.com/Mahayoga" class="twitter"><i class="bi bi-github"></i></a>
<a href="https://www.instagram.com/_myoga.exe.zip/" class="instagram"><i class="bi bi-instagram"></i></a>
<a href="https://discord.com/users/681789849342050304" class="linkedin"><i class="bi bi-discord"></i></a>
<a href="#!" class="twitter"><i class="bi bi-github"></i></a>
<a href="#!" class="instagram"><i class="bi bi-instagram"></i></a>
<a href="#!" class="linkedin"><i class="bi bi-discord"></i></a>
</div>
</div>
</div><!-- End Top Bar -->
<div class="branding d-flex align-items-center">
<div class="branding d-flex align-items-cente">
<div class="container position-relative d-flex align-items-center justify-content-between">
<a href="{{ route('beranda.index') }}" class="logo d-flex align-items-center">
<!-- Uncomment the line below if you also wish to use an image logo -->
<!-- <img src="assets/img/logo.webp" alt=""> -->
<h1 class="sitename">{{ env('APP_NAME') }}</h1>
<h1 class="sitename">Smart Anxiety</h1>
</a>
<nav id="navmenu" class="navmenu">
<ul>
<li><a href="{{ route('beranda.index') }}" class="{{ request()->routeIs('beranda.index') ? 'active' : '' }}">Home</a></li>
<li><a href="{{ route('beranda.about') }}" class="{{ request()->routeIs('beranda.about') ? 'active' : '' }}">About</a></li>
<li><a href="{{ route('beranda.about') }}#system-architecture-tabs" class="">System Architecture</a></li>
<li><a href="{{ route('cek-status.index') }}" class="{{ request()->routeIs('cek-status.index') ? 'active' : '' }}">Cek Status</a></li>
<li><a href="#footer">Contact</a></li>
<li><a href="{{ route('beranda.index') }}" class="active">Home</a></li>
<li><a href="{{ route('beranda.about') }}">About</a></li>
<li><a href="{{ route('beranda.about') }}#system-architecture-tabs">System Architecture</a></li>
<li><a href="services.html">Services</a></li>
<li><a href="contact.html">Contact</a></li>
@if (session('is_logged_in'))
<li class="dropdown"><a href="#"><span>{{ Auth::user()->name }}</span> <i class="bi bi-chevron-down toggle-dropdown"></i></a>
<ul>

View File

@ -1,79 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta content="width=device-width, initial-scale=1.0" name="viewport">
<title>@yield('title') - Smart Anxiety</title>
<meta name="description" content="">
<meta name="keywords" content="">
<meta id="_token" value="{{ csrf_token() }}">
<!-- Favicons -->
<link href="{{ asset('assets/users/assets/img/favicon.png') }}" rel="icon">
<link href="{{ asset('assets/users/assets/img/apple-touch-icon.png') }}" rel="apple-touch-icon">
<!-- Fonts -->
<link href="https://fonts.googleapis.com" rel="preconnect">
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
rel="stylesheet">
<!-- Vendor CSS Files -->
<link href="{{ asset('assets/users/assets/vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/aos/aos.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/glightbox/css/glightbox.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/fontawesome-free/css/all.min.css') }}" rel="stylesheet">
<link href="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.css') }}" rel="stylesheet">
<!-- Main CSS File -->
<link href="{{ asset('assets/users/assets/css/main.css') }}" rel="stylesheet">
<!-- =======================================================
* Template Name: Clinic
* Template URL: https://bootstrapmade.com/clinic-bootstrap-template/
* Updated: Jul 23 2025 with Bootstrap v5.3.7
* Author: BootstrapMade.com
* License: https://bootstrapmade.com/license/
======================================================== -->
</head>
<body class="index-page" style="@yield('body_status_overflow')">
{{-- @include('user.layouts.navbar') --}}
<main class="main" style="@yield('main_style')">
@yield('content')
</main>
{{-- @include('user.layouts.footer') --}}
<!-- Scroll Top -->
<a href="#!" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
class="bi bi-arrow-up-short"></i></a>
<!-- Preloader -->
<div id="preloader"></div>
<!-- Vendor JS Files -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="{{ asset('assets/users/assets/vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/php-email-form/validate.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/aos/aos.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/glightbox/js/glightbox.min.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/purecounter/purecounter_vanilla.js') }}"></script>
<script src="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.js') }}"></script>
<!-- Main JS File -->
<script src="{{ asset('assets/users/assets/js/main.js') }}"></script>
@yield('script')
</body>
</html>

View File

@ -40,7 +40,7 @@
<div class="col-lg-6" data-aos="fade-left" data-aos-delay="200">
<div class="image-wrapper">
<img src="{{ asset('assets/users/assets/img/tobii_eye_tracker_device.webp') }}" class="img-fluid main-image" alt="Healthcare facility">
<img src="{{ asset('assets/users/assets/img/health/facilities-6.webp') }}" class="img-fluid main-image" alt="Healthcare facility">
</div><!-- End Image Wrapper -->
</div>
</div>
@ -48,7 +48,7 @@
<div class="row align-items-center my-5">
<div class="col-lg-6" data-aos="fade-left" data-aos-delay="200">
<div class="image-wrapper">
<img src="{{ asset('assets/users/assets/img/gangguan-cemas-menyeluruh.jpg') }}" class="img-fluid main-image" alt="Healthcare facility">
<img src="{{ asset('assets/users/assets/img/health/facilities-6.webp') }}" class="img-fluid main-image" alt="Healthcare facility">
</div><!-- End Image Wrapper -->
</div>
@ -72,40 +72,40 @@
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="100">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-eye"></i>
<i class="bi bi-heart-pulse"></i>
</div>
<h4>Eye Movement Monitoring</h4>
<p>Memantau pergerakan mata dan pola fokus pengguna selama proses asesmen berlangsung.</p>
<h4>Compassion</h4>
<p>Membantu tenaga profesional dalam proses asesmen kecemasan</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="200">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-activity"></i>
<i class="bi bi-clipboard-data"></i>
</div>
<h4>Anxiety Estimation</h4>
<p>Menganalisis tingkat kecemasan berdasarkan data visual menggunakan model machine learning.</p>
<h4>Excellence</h4>
<p>Menyediakan analisis berbasis data terhadap respon visual pasien</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="300">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-clipboard2-pulse"></i>
<i class="bi bi-flask"></i>
</div>
<h4>Decision Support</h4>
<p>Membantu tenaga profesional dalam proses evaluasi kondisi psikologis pengguna.</p>
<h4>Integrity</h4>
<p>Menyajikan hasil estimasi tingkat kecemasan secara sistematis</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="400">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-display"></i>
<i class="bi bi-regex"></i>
</div>
<h4>Real-Time Visualization</h4>
<p>Menampilkan hasil analisis dan aktivitas visual pengguna secara real-time pada dashboard.</p>
<h4>Innovation</h4>
<p>Mendukung proses pengambilan keputusan selama konsultasi</p>
</div>
</div>
</div><!-- End Values Row -->
@ -123,40 +123,40 @@
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="100">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-camera-video"></i>
<i class="bi bi-eye"></i>
</div>
<h4>Eye Tracking Capture</h4>
<p>Kamera atau eye tracker menangkap koordinat dan pergerakan pupil pengguna.</p>
<h4>Compassion</h4>
<p>Kamera menangkap pergerakan pupil pengguna</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="300">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-bar-chart-steps"></i>
</div>
<h4>Integrity</h4>
<p>Fitur pergerakan mata diekstraksi</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="400">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-cpu"></i>
</div>
<h4>Data Processing</h4>
<p>Data gaze dan pergerakan mata diproses menjadi fitur analisis.</p>
<h4>Innovation</h4>
<p>Model machine learning melakukan klasifikasi</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="400">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-cpu-fill"></i>
<i class="bi bi-easel"></i>
</div>
<h4>Machine Learning Classification</h4>
<p>Model machine learning melakukan klasifikasi tingkat kecemasan berdasarkan pola visual.</p>
</div>
</div>
<div class="col-lg-3 col-md-6" data-aos="fade-up" data-aos-delay="400">
<div class="value-item">
<div class="value-icon">
<i class="bi bi-layout-text-window-reverse"></i>
</div>
<h4>Result Visualization</h4>
<p>Hasil estimasi kecemasan ditampilkan dalam bentuk dashboard dan visualisasi data.</p>
<h4>Innovation</h4>
<p>Hasil estimasi kecemasan ditampilkan pada dashboard</p>
</div>
</div>
</div><!-- End Values Row -->
@ -183,19 +183,19 @@
data-aos-delay="400">
<a class="nav-link department-tab active" id="neurology-tab" data-bs-toggle="pill"
href="#camera-tabs" role="tab" aria-controls="camera-tabs"
aria-selected="true" data-aos="fade-up" data-aos-delay="100">Facial Analysis</a>
aria-selected="true" data-aos="fade-up" data-aos-delay="100">Camera</a>
<a class="nav-link department-tab" id="surgery-tab" data-bs-toggle="pill"
href="#eye-detection-tabs" role="tab" aria-controls="eye-detection-tabs"
aria-selected="false" data-aos="fade-up" data-aos-delay="150">Gaze Tracking</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="150">Eye Detection</a>
<a class="nav-link department-tab" id="dental-tab" data-bs-toggle="pill"
href="#departments-tabs-dental" role="tab" aria-controls="departments-tabs-dental"
aria-selected="false" data-aos="fade-up" data-aos-delay="200">Analytics</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="200">Feature Extraction</a>
<a class="nav-link department-tab" id="ophthalmology-tab" data-bs-toggle="pill"
href="#departments-tabs-ophthalmology" role="tab" aria-controls="departments-tabs-ophthalmology"
aria-selected="false" data-aos="fade-up" data-aos-delay="250">AI Assessment</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="250">ML Prediction</a>
<a class="nav-link department-tab" id="cardiology-tab" data-bs-toggle="pill"
href="#departments-tabs-cardiology" role="tab" aria-controls="departments-tabs-cardiology"
aria-selected="false" data-aos="fade-up" data-aos-delay="300">Technologies</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="300">Result</a>
</div>
</div>
</div>
@ -214,53 +214,51 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<h2 class="department-title">Facial Expression Analysis</h2>
<p class="department-description">
Kamera digunakan untuk menangkap ekspresi wajah dan pergerakan pengguna selama proses asesmen berlangsung.
Data visual ini digunakan sebagai sumber analisis tambahan untuk membantu model machine learning dalam mengestimasi tingkat kecemasan pengguna.
</p>
<h2 class="department-title">Camera</h2>
<p class="department-description">Kamera digunakan pada sistem ini untuk menangkap dan merekam pergerakan pengguna sebagai referensi kedua dari 'eye tracking'. Data dari rekaman kamera ini akan digunakan untuk menjadikan ekspresi muka sebagai bobot kedua dari menentukan kecemasan.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-person-bounding-box"></i>
<i class="fas fa-brain"></i>
</div>
<div class="service-content">
<h4>Face Detection</h4>
<p>Sistem mendeteksi area wajah pengguna secara real-time selama asesmen berlangsung.</p>
<h4>Brain Monitoring</h4>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-eye"></i>
<i class="fas fa-wave-square"></i>
</div>
<div class="service-content">
<h4>Eye Movement Tracking</h4>
<p>Pergerakan mata dan titik fokus pengguna dianalisis untuk memperoleh pola visual.</p>
<h4>EEG Testing</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-emoji-neutral"></i>
<i class="fas fa-stethoscope"></i>
</div>
<div class="service-content">
<h4>Emotion Observation</h4>
<p>Ekspresi wajah digunakan sebagai indikator tambahan dalam analisis kecemasan.</p>
<h4>Neurological Exam</h4>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-cpu"></i>
<i class="fas fa-file-medical"></i>
</div>
<div class="service-content">
<h4>AI Classification</h4>
<p>Model machine learning melakukan estimasi tingkat kecemasan berdasarkan data visual pengguna.</p>
<h4>Treatment Plans</h4>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.</p>
</div>
</div>
</div>
@ -279,54 +277,53 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<h2 class="department-title">Eye Tracking Analysis</h2>
<p class="department-description">
Sistem melakukan analisis pergerakan mata pengguna menggunakan teknologi eye tracking untuk memperoleh pola perhatian visual selama proses asesmen.
Data gaze yang diperoleh digunakan sebagai fitur utama dalam proses estimasi tingkat kecemasan berbasis machine learning.
<h2 class="department-title">Eye Detection</h2>
<p class="department-description">Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-eye"></i>
<i class="fas fa-cut"></i>
</div>
<div class="service-content">
<h4>Gaze Tracking</h4>
<p>Sistem melacak arah pandangan dan titik fokus mata pengguna secara real-time.</p>
<h4>Minimally Invasive</h4>
<p>Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-crosshair"></i>
<i class="fas fa-tools"></i>
</div>
<div class="service-content">
<h4>Fixation Analysis</h4>
<p>Durasi fokus pengguna pada area tertentu dianalisis untuk mendeteksi pola perhatian visual.</p>
<h4>Advanced Procedures</h4>
<p>Consectetur, adipisci velit, sed quia non numquam eius modi tempora.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-grid-3x3-gap"></i>
<i class="fas fa-shield-alt"></i>
</div>
<div class="service-content">
<h4>Heatmap Visualization</h4>
<p>Pergerakan mata divisualisasikan dalam bentuk heatmap untuk melihat distribusi perhatian pengguna.</p>
<h4>Safe Operations</h4>
<p>Incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-cpu"></i>
<i class="fas fa-clock"></i>
</div>
<div class="service-content">
<h4>AI-Based Classification</h4>
<p>Model machine learning mengklasifikasikan tingkat kecemasan berdasarkan pola gaze pengguna.</p>
<h4>Recovery Support</h4>
<p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis.</p>
</div>
</div>
</div>
@ -345,54 +342,53 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<h2 class="department-title">Result Visualization</h2>
<p class="department-description">
Sistem menampilkan hasil analisis eye tracking dan estimasi kecemasan dalam bentuk visualisasi data interaktif secara real-time.
Dashboard digunakan untuk membantu proses observasi, evaluasi, dan interpretasi hasil analisis pengguna.
</p>
<h2 class="department-title">Dental Care Department</h2>
<p class="department-description">Suscipit laboriosam, nisi ut aliquid ex ea commodi
consequatur. Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil
molestiae.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-grid-3x3-gap"></i>
<i class="far fa-smile"></i>
</div>
<div class="service-content">
<h4>Heatmap Analytics</h4>
<p>Visualisasi heatmap digunakan untuk melihat distribusi perhatian visual pengguna pada layar.</p>
<h4>Oral Health</h4>
<p>Consequatur aut perferendis doloribus asperiores repellat tempore.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-activity"></i>
<i class="fas fa-tooth"></i>
</div>
<div class="service-content">
<h4>Real-Time Monitoring</h4>
<p>Sistem memantau aktivitas pengguna dan data eye tracking secara langsung selama asesmen berlangsung.</p>
<h4>Teeth Cleaning</h4>
<p>Et harum quidem rerum facilis est et expedita distinctio nam libero.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-graph-up-arrow"></i>
<i class="fas fa-star"></i>
</div>
<div class="service-content">
<h4>Anxiety Prediction</h4>
<p>Model machine learning menghasilkan estimasi tingkat kecemasan berdasarkan pola visual pengguna.</p>
<h4>Cosmetic Dentistry</h4>
<p>Tempore cum soluta nobis est eligendi optio cumque nihil impedit quo minus.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-display"></i>
<i class="fas fa-cog"></i>
</div>
<div class="service-content">
<h4>Interactive Dashboard</h4>
<p>Seluruh hasil analisis divisualisasikan melalui dashboard interaktif yang mudah dipahami.</p>
<h4>Orthodontics</h4>
<p>Id quod maxime placeat facere possimus, omnis voluptas assumenda est.</p>
</div>
</div>
</div>
@ -412,53 +408,52 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<h2 class="department-title">Behavioral Analysis</h2>
<p class="department-description">
Sistem menganalisis pola perilaku visual pengguna berdasarkan pergerakan mata, fokus perhatian, dan ekspresi wajah untuk membantu proses estimasi tingkat kecemasan secara lebih akurat.
</p>
<h2 class="department-title">Ophthalmology Department</h2>
<p class="department-description">Omnis dolor repellendus temporibus autem quibusdam et aut
officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-bullseye"></i>
<i class="fas fa-eye"></i>
</div>
<div class="service-content">
<h4>Attention Analysis</h4>
<p>Sistem mengevaluasi fokus dan perhatian visual pengguna selama proses asesmen berlangsung.</p>
<h4>Vision Testing</h4>
<p>Sint et voluptatum sint quia dolor sit amet consectetur adipiscing elit.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-emoji-neutral"></i>
<i class="fas fa-camera"></i>
</div>
<div class="service-content">
<h4>Facial Behavior</h4>
<p>Ekspresi wajah dianalisis untuk membantu mendeteksi perubahan perilaku emosional pengguna.</p>
<h4>Retinal Imaging</h4>
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-diagram-3"></i>
<i class="fas fa-bolt"></i>
</div>
<div class="service-content">
<h4>Pattern Recognition</h4>
<p>Model AI mengenali pola visual tertentu yang berkaitan dengan tingkat kecemasan pengguna.</p>
<h4>Laser Surgery</h4>
<p>Enim ad minim veniam quis nostrud exercitation ullamco laboris nisi.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-cpu"></i>
<i class="fas fa-prescription-bottle"></i>
</div>
<div class="service-content">
<h4>AI Assessment</h4>
<p>Machine learning menghasilkan estimasi tingkat kecemasan berdasarkan kombinasi data visual pengguna.</p>
<h4>Eye Care Plans</h4>
<p>Ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit.</p>
</div>
</div>
</div>
@ -478,53 +473,52 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<h2 class="department-title">Core Technologies</h2>
<p class="department-description">
Sistem dibangun menggunakan kombinasi teknologi eye tracking, machine learning, dan visualisasi data real-time untuk mendukung proses analisis kecemasan secara interaktif dan akurat.
</p>
<h2 class="department-title">Cardiology Department</h2>
<p class="department-description">In voluptate velit esse cillum dolore eu fugiat nulla pariatur
excepteur sint occaecat cupidatat non proident sunt in culpa qui officia deserunt.</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-eye"></i>
<i class="fas fa-heartbeat"></i>
</div>
<div class="service-content">
<h4>Eye Tracking Device</h4>
<p>Perangkat eye tracker digunakan untuk menangkap koordinat dan pergerakan mata pengguna secara real-time.</p>
<h4>Heart Monitoring</h4>
<p>Mollit anim id est laborum sed ut perspiciatis unde omnis iste natus error.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-cpu"></i>
<i class="fas fa-chart-line"></i>
</div>
<div class="service-content">
<h4>Machine Learning</h4>
<p>Model AI menganalisis pola visual pengguna untuk menghasilkan estimasi tingkat kecemasan.</p>
<h4>ECG Analysis</h4>
<p>Sit voluptatem accusantium doloremque laudantium totam rem aperiam.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-wifi"></i>
<i class="fas fa-tint"></i>
</div>
<div class="service-content">
<h4>Real-Time Communication</h4>
<p>Teknologi WebSocket digunakan untuk mengirim data monitoring secara langsung dan responsif.</p>
<h4>Blood Tests</h4>
<p>Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="bi bi-display"></i>
<i class="fas fa-shield-heart"></i>
</div>
<div class="service-content">
<h4>Interactive Dashboard</h4>
<p>Dashboard interaktif menampilkan visualisasi data, heatmap, dan hasil analisis AI secara real-time.</p>
<h4>Preventive Care</h4>
<p>Vitae dicta sunt explicabo nemo enim ipsam voluptatem quia voluptas sit.</p>
</div>
</div>
</div>
@ -571,7 +565,7 @@
</div>
<div class="col-lg-2 col-md-3 col-sm-4 col-6" data-aos="zoom-in" data-aos-delay="400">
<div class="certification-item">
<img src="{{ asset('assets/users/assets/img/logo/node-js.png') }}" class="img-fluid" alt="Node.js Logo">
<img src="{{ asset('assets/users/assets/img/logo/tensorflow_logo.webp') }}" class="img-fluid" alt="Tensorflow Logo">
</div>
</div>
</div><!-- End Certifications Row -->

View File

@ -1,294 +0,0 @@
@section('title', 'Cek Status')
@extends('user.layouts.index')
@section('content')
<!-- Page Title -->
<div class="page-title">
<div class="heading">
<div class="container">
<div class="row d-flex justify-content-center text-center">
<div class="col-lg-8">
<h1 class="heading-title">Cek Status</h1>
<p class="mb-0">
Cek status data kamu dari sini ya, jika kamu sudah mendapatkan kode dari email setelah melakukan booking, kamu bisa melakukan tes kecemasan dari pakar atau juga cek hasil tes disini dengan kode tadi.
</p>
</div>
</div>
</div>
</div>
<nav class="breadcrumbs">
<div class="container">
<ol>
<li><a href="index.html">Home</a></li>
<li class="current">Cek Status</li>
</ol>
</div>
</nav>
</div><!-- End Page Title -->
<!-- About Section -->
<section id="about" class="about section">
<div class="container" data-aos="fade-up" data-aos-delay="100">
<div class="row justify-content-center">
<div class="col-md-8 my-3">
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">Form Cek</h5>
<h6 class="card-subtitle mb-2 text-body-secondary text-center">Masukkan kode yang kamu dapatkan disini</h6>
<div class="row justify-content-center">
<div class="col-md-9 my-3">
<input class="form-control" type="text" name="kode_cek" id="kode_cek" placeholder="Kode kamu....">
</div>
<div class="col-md-9 mb-3">
<div class="row justify-content-center">
<button type="button" class="btn btn-primary text-white fw-bold" onclick="searchUserStatus()">Cari</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-12 my-3" id="result_data">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Hasil Pencarian
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item">Nama Lengkap: <span id="nama_lengkap"></span></li>
<li class="list-group-item">Kode Unik: <span id="kode_unik"></span></li>
<li class="list-group-item">Tgl dan Jam Ujian (sesuai booking): <span id="tgl_booking"></span><span id="jam_booking"></span></li>
<li class="list-group-item">Deskripsi Tambahan: <span id="deskripsi"></span></li>
<li class="list-group-item">Status Tes: <span id="status"></span></li>
</ul>
</div>
</div>
<div class="col-md-8 my-4">
<div class="alert alert-primary" role="alert" id="alert_status">
A simple primary alert—check it out!
</div>
</div>
</div>
</div>
<div class="col-md-8 my-3" id="result_test">
<div class="card">
<div class="card-body">
<h5 class="card-title text-center">Lakukan Tes</h5>
<h6 class="card-subtitle mb-2 text-body-secondary text-center" id="result_test_title">Kalau kamu sudah siap menjalankan tes, klik tombol di bawah untuk mulai tes kecemasan dari sistem kami!</h6>
<div class="row justify-content-center">
<div class="col-md-12 text-center my-3">
<span>Status tes kamu: <span id="result_test_status" class="fw-bold text-white bg-secondary p-2 rounded-pill">Belum Dimulai</span></span>
</div>
<div class="col-md-9 mb-3">
<div class="row justify-content-center">
<form action="" method="POST" id="result_test_form">
@csrf
<input type="hidden" name="id_booking" id="id_booking_input">
<input type="hidden" name="screen_w" id="screen_w">
<input type="hidden" name="screen_h" id="screen_h">
<div class="row justify-content-center">
<button type="button" class="btn btn-primary text-white fw-bold" onclick="startSessionTest()">Mulai Tes</button>
</div>
</form>
<a href="#" class="btn btn-primary text-white fw-bold" id="result_test_link">Mulai Tes</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section><!-- /About Section -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto"><i class="bi bi-exclamation-triangle"></i> Kesalahan</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
{{ session('error') }}
</div>
</div>
</div>
@endsection
@section('script')
<script>
$('#result_data').hide();
$('#result_test').hide();
$('#result_test_form').hide();
$('#result_test_link').hide();
function searchUserStatus() {
$('#result_data').hide();
$('#result_test').hide();
Swal.fire({
title: 'Status',
text: 'Mencari data...',
icon: 'info',
showConfirmButton: false,
allowOutsideClick: false,
allowEscapeKey: false
});
let the_code = $('#kode_cek').val();
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
let status_dict = ['Sesi anda dinonaktifkan karena telah kedaluwarsa atau belum sesuai jadwal yang telah di booking', 'Belum melakukan/menyelesaikan tes', 'Sudah melakukan tes'];
if(response.status) {
$('#result_data').show();
$('#nama_lengkap').html(response.nama_lengkap);
$('#kode_unik').html(response.kode_unik);
$('#tgl_booking').html(`<b>${response.tgl_booking}</b>`);
$('#jam_booking').html(", Valid dari jam <b>" + response.start_test + "</b>, sampai dengan jam <b>" + response.end_test + "</b>");
$('#deskripsi').html(response.deskripsi_tambahan);
$('#status').html(status_dict[response.status_data]);
Swal.close();
if(response.status_data == 0) {
$('#alert_status').removeClass();
$('#alert_status').addClass('alert alert-warning');
$('#alert_status').html('Session kamu dinonaktifkan atau belum sesuai jam yang telah di booking!');
} else if(response.status_data == 1) {
$('#alert_status').removeClass();
$('#alert_status').addClass('alert alert-info');
$('#alert_status').html('Kamu bisa memulai tes sekarang!');
let test_session = getTestSession(response.id_booking);
$('#result_test').show();
$('#result_test_title').html('Kalau kamu sudah siap menjalankan tes, klik tombol di bawah untuk mulai tes kecemasan dari sistem kami!');
if(test_session.status) {
if(test_session.status_session == 0) {
$('#id_booking_input').val(response.id_booking);
$('#result_test_status').html('Belum Dimulai');
$('#result_test_status').removeClass();
$('#result_test_status').addClass('fw-bold text-white bg-secondary p-2 rounded-pill');
$('#result_test_form').show();
} else if(test_session.status_session == 1) {
$('#result_test_status').html('Sedang Berlangsung');
$('#result_test_status').removeClass();
$('#result_test_status').addClass('fw-bold text-white bg-warning p-2 rounded-pill');
let test_url = '{{ route('tutorial-tes.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
$('#result_test_form').hide();
$('#result_test_link').show();
$('#result_test_link').html('Tes Sedang Berlangsung, Klik untuk Lanjutkan Tes');
$('#result_test_link').attr('href', test_url.replace('__ID_TEST_SESSIONS__', test_session.id_test_sessions));
} else if(test_session.status_session == 2) {
$('#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_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));
}
} else if(!test_session.status) {
$('#id_booking_input').val(response.id_booking);
$('#result_test').show();
$('#result_test_title').html('Kalau kamu sudah siap menjalankan tes, klik tombol di bawah untuk mulai tes kecemasan dari sistem kami!');
$('#result_test_status').html('Belum Dimulai');
$('#result_test_status').removeClass();
$('#result_test_status').addClass('fw-bold text-white bg-secondary p-2 rounded-pill');
$('#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({
title: 'Status',
text: 'Data tidak ditemukan',
icon: 'error',
});
// Swal.close();
}
}
};
let url = '{{ route('cek-status.show', ['__CODE__']) }}';
xhttp.open('GET', url.replace('__CODE__', the_code));
xhttp.send();
}
function getTestSession(id_booking) {
let xhttp = new XMLHttpRequest();
let result = {
'status': false,
'msg': 'Data tidak ditemukan (' + id_booking + ')',
};
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if(response.status) {
result = {
'status': true,
'msg': 'Data ditemukan (' + id_booking + ')',
'id_booking': response.id_booking,
'id_test_sessions': response.id_test_sessions,
'status_session': response.status_session,
'token_session': response.token_session
};
}
}
};
let url = '{{ route('test-sessions.show', ['__ID__']) }}';
xhttp.open('GET', url.replace('__ID__', id_booking), false);
xhttp.send();
return result;
}
function startSessionTest() {
let id_booking = $('#id_booking_input').val();
let url = '{{ route('test-sessions.store') }}';
let form = $('#result_test_form');
Swal.fire({
title: 'Konfirmasi',
text: 'Apakah kamu yakin ingin memulai tes sekarang?',
icon: 'question',
showCancelButton: true,
confirmButtonText: 'Ya, mulai tes!',
cancelButtonText: 'Nggak jadi deh'
}).then((result) => {
if(result.isConfirmed) {
$('#screen_w').val(window.screen.width);
$('#screen_h').val(window.screen.height);
form.attr('action', url);
form.submit();
}
});
}
</script>
@if (session('error'))
<script>
$(document).ready(function() {
var toast = new bootstrap.Toast(document.getElementById('liveToast'));
toast.show();
});
</script>
@endif
@endsection

View File

@ -1,756 +0,0 @@
@section('title', 'Hasil Tes')
@extends('user.layouts.index')
@section('content')
<style>
.stats-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 16px;
}
.stat-card {
padding: 20px;
border-radius: 12px;
background: #f5f5f5;
}
.bg-custom {
background: #f5f5f5;
}
</style>
<!-- Page Title -->
<div class="page-title">
<div class="heading">
<div class="container">
<div class="row d-flex justify-content-center text-center">
<div class="col-lg-8">
<h1 class="heading-title">Hasil Tes Anda</h1>
<p class="mb-0">
Cek hasil tes kamu dari sini ya, jika kamu sudah mendapatkan kode dari email setelah melakukan booking, kamu bisa melihat hasil tes disini dengan kode tadi.
</p>
</div>
</div>
</div>
</div>
<nav class="breadcrumbs">
<div class="container">
<ol>
<li><a href="{{ route('beranda.index') }}">Home</a></li>
<li class="current">Hasil Tes</li>
</ol>
</div>
</nav>
</div><!-- End Page Title -->
<!-- About Section -->
<section id="about" class="about section">
<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'] <= 37)
<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>
<h2 class="mt-4" id="result-model">
Loading...
</h2>
<p class="text-muted">
Model Confidence: <span id="confidence-model"></span>
</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">
<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">
<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>
<li><strong>Jumlah Pergerakan Mata:</strong> <span id="total_movement">0</span></li>
</ul>
</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">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>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="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">Detail Confidence Prediksi Model</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>Normal:</strong> <span id="normal-confidence">0%</span></li>
<li><strong>Sedang:</strong> <span id="sedang-confidence"></span></li>
<li><strong>Tinggi:</strong> <span id="tinggi-confidence"></span></li>
</ul>
</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">Avg Velocity</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-speedometer2 fs-4"></i>
</div>
</div>
<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>
</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>
<th>No</th>
<th>Pertanyaan</th>
<th>Jawaban</th>
<th>Skor</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<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>
<th>Skor</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 text-center">Grafik Kecepatan Mata</h2>
<canvas id="velocityChart"></canvas>
</div>
<div class="col-lg-12 mt-5">
<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; position: absolute;">
<div id="heatmapChart" style="aspect-ratio: 16/9;"></div>
</div>
</div>
<div class="col-lg-12 mt-5">
<h2 class="title text-center">Heatmap Pergerakan Mata (Grid)</h2>
<div style="position: relative; aspect-ratio: 16/9;">
<img src="{{ asset('assets/users/assets/img/overlay/overlay_grid.png') }}" style="width:100%; height:100%; object-fit: cover; position: absolute;">
<div id="heatmapChartGrid" style="aspect-ratio: 16/9;"></div>
</div>
</div>
</div>
</div>
</section><!-- /About Section -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto"><i class="bi bi-exclamation-triangle"></i> Kesalahan</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
{{ session('error') }}
</div>
</div>
</div>
@endsection
@section('script')
<script>
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
let table = null;
let data_tobii = null;
let heatmapContainer = null;
let clientWidth = null;
let clientHeight = null;
let recordedScreenWidth = null
let recordedScreenHeight = null
let mappedHeatmapData = null;
let mappedHeatmapDataGrid = null;
let scaleX = null;
let scaleY = null;
let heatmapInstance = null;
let heatmapInstanceGrid = null;
let score = null;
let totalScore = null;
let soalTerjawab = 0;
function renderVelocityChart(timeseries) {
const base = timeseries.timestamp[0];
const labels = timeseries.timestamp.map(t => (t - base) / 1000);
const ctx = document.getElementById('velocityChart').getContext('2d');
new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: 'Velocity',
data: timeseries.velocity,
borderWidth: 2,
tension: 0.3
}]
},
options: {
responsive: true,
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return "Velocity: " + context.raw.toFixed(4);
}
}
}
},
scales: {
x: {
display: false
}
}
}
});
}
async function loadData(data) {
const res = await fetch("{{ env('PYTHON_API_URL') }}/extract", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
const result = await res.json();
if(result != null) {
renderVelocityChart(result.timeseries);
mappedHeatmapData = result.heatmap.map(point => ({
x: point.x * scaleX,
y: point.y * scaleY,
value: point.value
}));
heatmapInstance.setData({
max: 10,
data: mappedHeatmapData
});
mappedHeatmapDataGrid = result.heatmap.map(point => ({
x: point.x * scaleX,
y: point.y * scaleY,
value: point.value
}));
heatmapInstanceGrid.setData({
max: 10,
data: mappedHeatmapDataGrid
});
heatmapContainer.style.removeProperty('position');
renderStats(result.statistics);
}
}
async function getPredict(data) {
const res = await fetch("{{ env('PYTHON_API_URL') }}/predict", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data)
});
const result = await res.json();
if(result != null) {
let classBg = ['text-success', 'text-warning', 'text-danger'];
let textResult = ['Normal', 'Sedang', 'Tinggi'];
$('#result-model').addClass(classBg[result.hasil_prediksi]);
$('#result-model').html(textResult[result.hasil_prediksi]);
$('#confidence-model').html(result.confidence + '%');
$('#normal-confidence').html(result.detail_probabilitas.normal + "%");
$('#sedang-confidence').html(result.detail_probabilitas.sedang + "%");
$('#tinggi-confidence').html(result.detail_probabilitas.tinggi + "%");
Swal.close();
}
}
function renderStats(stats) {
document.getElementById("avgVelocity")
.innerText = stats.avg_velocity.toFixed(4);
document.getElementById("fixationRatio")
.innerText = stats.fixation_ratio.toFixed(2) + "%";
document.getElementById("totalDistance")
.innerText = stats.total_distance.toFixed(2);
document.getElementById("mostViewedArea")
.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,
paging: false,
ajax: {
url: '{{ route('hasil-tes.getAllAnswer', ['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) {
let renderedJawaban = null;
if(row.jawaban_key == 'a') {
if(row.is_reverse == 1) {
renderedJawaban = `<span class="badge text-bg-danger">${row.jawaban}</span>`;
} else {
renderedJawaban = `<span class="badge text-bg-primary">${row.jawaban}</span>`;
}
} else if(row.jawaban_key == 'b') {
if(row.is_reverse == 1) {
renderedJawaban = `<span class="badge text-bg-warning">${row.jawaban}</span>`;
} else {
renderedJawaban = `<span class="badge" style="background-color: #fc7938; color: white;">${row.jawaban}</span>`;
}
} else if(row.jawaban_key == 'c') {
if(row.is_reverse == 1) {
renderedJawaban = `<span class="badge" style="background-color: #fc7938; color: white;">${row.jawaban}</span>`;
} else {
renderedJawaban = `<span class="badge text-bg-warning">${row.jawaban}</span>`;
}
} else if(row.jawaban_key == 'd') {
if(row.is_reverse == 1) {
renderedJawaban = `<span class="badge text-bg-primary">${row.jawaban}</span>`;
} else {
renderedJawaban = `<span class="badge text-bg-danger">${row.jawaban}</span>`;
}
} else if(row.jawaban_key == 'e') {
renderedJawaban = `<span class="badge text-bg-success">${row.jawaban}</span>`;
score = 5;
} else {
renderedJawaban = `<span class="badge text-bg-secondary">${row.jawaban}</span>`;
}
return renderedJawaban;
}
},
{
data: 'skor',
}
]
});
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>`;
}
},
{
data: 'skor'
}
]
});
ws.onopen = () => {
console.log("Connected to WebSocket");
Swal.fire({
title: 'Status',
text: 'Memuat data...',
icon: 'info',
showConfirmButton: false,
allowOutsideClick: false,
allowEscapeKey: false
});
ws.send(JSON.stringify({
type: 'get_json_file',
session_id: '{{ $id_session }}'
}));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// console.log(data);
if(data.type === 'json_file_data') {
if(data.data != null) {
data_tobii = null;
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let data_ = JSON.parse(this.responseText);
$('#total_movement').html(data.data.length + " (1 detik = 3 pergerakan)");
if(data_.status) {
heatmapContainer = document.getElementById('heatmapChart');
clientWidth = heatmapContainer.clientWidth;
clientHeight = heatmapContainer.clientHeight;
recordedScreenWidth = data_.screen_w;
recordedScreenHeight = data_.screen_h;
scaleX = clientWidth / recordedScreenWidth;
scaleY = clientHeight / recordedScreenHeight;
data_tobii = {
data: data.data,
screen_w: recordedScreenWidth,
screen_h: recordedScreenHeight
};
heatmapInstance = h337.create({
container: heatmapContainer,
radius: 40,
maxOpacity: 0.6,
blur: 0.85
});
heatmapInstanceGrid = h337.create({
container: document.getElementById('heatmapChartGrid'),
radius: 40,
maxOpacity: 0.6,
blur: 0.85
});
loadData(data_tobii);
getPredict(data_tobii.data);
} else {
Swal.fire({
title: 'Error',
text: 'Gagal mencari data, silahkan coba lagi nanti',
icon: 'error',
showConfirmButton: true,
allowOutsideClick: false,
allowEscapeKey: false
});
}
}
};
xhttp.open('GET', '{{ route('test-sessions.getScreen', ['id_test_sessions' => $id_session]) }}', true);
xhttp.send();
} else {
Swal.fire({
title: 'Error',
text: 'Gagal memuat data mata, silahkan coba lagi nanti',
icon: 'error',
showConfirmButton: true,
allowOutsideClick: false,
allowEscapeKey: false
});
}
}
};
};
});
</script>
@if (session('error'))
<script>
$(document).ready(function() {
var toast = new bootstrap.Toast(document.getElementById('liveToast'));
toast.show();
});
</script>
@endif
@endsection

View File

@ -19,7 +19,7 @@
</p>
<div class="hero-actions" data-aos="fade-right" data-aos-delay="600">
<a href="#appointment" class="btn btn-primary">Coba Sekarang</a>
<a href="{{ route('beranda.about') }}" class="btn btn-primary">Learn About The System</a>
<a href="https://www.youtube.com/watch?v=Y7f98aduVJ8" class="btn btn-outline glightbox">
<i class="bi bi-archive me-2"></i>
View Research
@ -41,7 +41,30 @@
<div class="col-lg-6">
<div class="hero-visual" data-aos="fade-left" data-aos-delay="400">
<div class="main-image">
<img src="{{ asset('assets/users/assets/img/health/depresi_crop.jpg') }}" alt="Modern Healthcare Facility" class="img-fluid">
<img src="{{ asset('assets/users/assets/img/health/staff-10.webp') }}" alt="Modern Healthcare Facility" class="img-fluid">
<div class="floating-card appointment-card">
<div class="card-icon">
<i class="bi bi-calendar-check"></i>
</div>
<div class="card-content">
<h6>Next Available</h6>
<p>Today 2:30 PM</p>
<small>Dr. Sarah Johnson</small>
</div>
</div>
<div class="floating-card rating-card">
<div class="card-content">
<div class="rating-stars">
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
<i class="bi bi-star-fill"></i>
</div>
<h6>4.9/5</h6>
<small>1,234 Reviews</small>
</div>
</div>
</div>
<div class="background-elements">
<div class="element element-1"></div>
@ -73,7 +96,7 @@
</p>
<div class="cta-section">
<a href="{{ route('beranda.about') }}" class="btn-primary">Learn More About Us</a>
<a href="about.html" class="btn-primary">Learn More About Us</a>
</div>
</div>
</div>
@ -81,7 +104,7 @@
<div class="col-lg-6" data-aos="fade-left" data-aos-delay="300">
<div class="about-visual">
<div class="main-image">
<img src="{{ asset('assets/users/assets/img/health/about.jpg') }}" alt="Modern medical facility" class="img-fluid">
<img src="{{ asset('assets/users/assets/img/health/facilities-9.webp') }}" alt="Modern medical facility" class="img-fluid">
</div>
{{-- <div class="floating-card">
<div class="card-content">
@ -123,7 +146,7 @@
<div class="service-image">
<img src="{{ asset('assets/users/assets/img/health/cardiology-2.webp') }}" alt="Cardiology Services" class="img-fluid">
<div class="service-overlay">
<i class="fas fa-message"></i>
<i class="fas fa-heartbeat"></i>
</div>
</div>
<div class="service-content">
@ -146,7 +169,7 @@
<div class="service-image">
<img src="{{ asset('assets/users/assets/img/health/neurology-3.webp') }}" alt="Neurology Services" class="img-fluid">
<div class="service-overlay">
<i class="fas fa-face-rolling-eyes"></i>
<i class="fas fa-brain"></i>
</div>
</div>
<div class="service-content">
@ -169,7 +192,7 @@
<div class="service-image">
<img src="{{ asset('assets/users/assets/img/health/orthopedics-1.webp') }}" alt="Orthopedics Services" class="img-fluid">
<div class="service-overlay">
<i class="fas fa-chart-gantt"></i>
<i class="fas fa-bone"></i>
</div>
</div>
<div class="service-content">
@ -193,7 +216,7 @@
<div class="service-image">
<img src="{{ asset('assets/users/assets/img/health/pediatrics-4.webp') }}" alt="Pediatrics Services" class="img-fluid">
<div class="service-overlay">
<i class="fas fa-computer"></i>
<i class="fas fa-child"></i>
</div>
</div>
<div class="service-content">
@ -301,14 +324,15 @@
<h1>Make an Appointment</h1>
</div><!-- End Section Title -->
<div class="container" data-aos="fade-up" data-aos-delay="100" id="appointment">
<div class="container" data-aos="fade-up" data-aos-delay="100">
<div class="row">
<div class="col-lg-10 mx-auto">
<div class="booking-wrapper">
<div class="booking-header text-center" data-aos="fade-up" data-aos-delay="200">
<h2>Schedule Your Appointment</h2>
<p>Jika ingin mencoba sistem kami, jadwalkan periksa kamu dengan mengisi form dibawah ini yaa! Dan batalkan kapan saja!</p>
<p>Book your medical appointment in just a few simple steps. Our experienced healthcare professionals
are ready to provide you with the best care possible.</p>
</div>
<div class="booking-steps" data-aos="fade-up" data-aos-delay="300">
@ -317,8 +341,8 @@
<i class="bi bi-calendar-check"></i>
</div>
<div class="step-content">
<h4>Isi Data Diri</h4>
<p>Mohon isi data diri Anda dengan lengkap</p>
<h4>Select Service</h4>
<p>Choose the medical service you need</p>
</div>
</div>
<div class="step">
@ -326,8 +350,8 @@
<i class="bi bi-clock"></i>
</div>
<div class="step-content">
<h4>Ambil Tanggal &amp; Waktu</h4>
<p>Pilih tanggal dan waktu yang paling cocok untuk Anda</p>
<h4>Pick Date &amp; Time</h4>
<p>Select your preferred appointment slot</p>
</div>
</div>
<div class="step">
@ -335,45 +359,68 @@
<i class="bi bi-person-check"></i>
</div>
<div class="step-content">
<h4>Konfirmasi Detail</h4>
<p>Periksa kembali semua detail yang telah Anda masukkan</p>
<h4>Confirm Details</h4>
<p>Provide your information and confirm</p>
</div>
</div>
</div>
<div class="appointment-form" data-aos="fade-up" data-aos-delay="400">
<div class="php-email-form">
<form action="forms/book-appointment.php" method="post" class="php-email-form">
<div class="row gy-4">
<div class="col-md-6">
<input type="text" name="nama_lengkap" id="nama_lengkap" class="form-control" placeholder="Nama Lengkap" required="">
<input type="text" name="name" class="form-control" placeholder="Full Name" required="">
</div>
<div class="col-md-6">
<input type="email" name="email" id="email" class="form-control" placeholder="Alamat Email Aktif" required="">
<input type="email" name="email" class="form-control" placeholder="Email Address" required="">
</div>
<div class="col-md-6">
<input type="tel" name="phone" id="no_telp" class="form-control" placeholder="Nomor Telepon" required="">
<input type="tel" name="phone" class="form-control" placeholder="Phone Number" required="">
</div>
<div class="col-md-6">
<input type="text" name="date" id="tgl_book" class="form-control" required="" aria-describedby="dateHelp" placeholder="Pilih tanggal...">
<div id="dateHelp" class="form-text">Untuk detail jam, akan dikirim melalui email mu yaa.</div>
<select name="department" class="form-select" required="">
<option value="">Select Department</option>
<option value="general">General Consultation</option>
<option value="cardiology">Cardiology</option>
<option value="neurology">Neurology</option>
<option value="orthopedics">Orthopedics</option>
<option value="pediatrics">Pediatrics</option>
<option value="dermatology">Dermatology</option>
<option value="oncology">Oncology</option>
</select>
</div>
<div class="col-md-6">
<input type="date" name="date" class="form-control" required="">
</div>
<div class="col-md-6">
<select name="doctor" class="form-select" required="">
<option value="">Select Doctor</option>
<option value="dr-sarah-johnson">Dr. Sarah Johnson</option>
<option value="dr-michael-chen">Dr. Michael Chen</option>
<option value="dr-emily-davis">Dr. Emily Davis</option>
<option value="dr-robert-smith">Dr. Robert Smith</option>
<option value="dr-lisa-brown">Dr. Lisa Brown</option>
<option value="dr-david-wilson">Dr. David Wilson</option>
<option value="dr-maria-rodriguez">Dr. Maria Rodriguez</option>
</select>
</div>
<div class="col-12">
<textarea name="message" class="form-control" rows="4" id="deskripsi"
placeholder="Tambahan deskripsi (optional)"></textarea>
<textarea name="message" class="form-control" rows="4"
placeholder="Additional notes or symptoms (optional)"></textarea>
</div>
<div class="col-12">
<div class="loading" id="loading_btn">Loading</div>
<div class="alert alert-danger" id="error_msg" role="alert" style="display: none"></div>
<div class="loading">Loading</div>
<div class="error-message"></div>
<div class="sent-message">Your appointment has been scheduled. Thank you!</div>
<button type="button" class="btn-book" onclick="sendAppointment()">Book Appointment Now</button>
<button type="submit" class="btn-book">Book Appointment Now</button>
</div>
</div>
</div>
</form>
</div>
<div class="emergency-info" data-aos="fade-up" data-aos-delay="500">
<p><i class="bi bi-exclamation-triangle"></i> Untuk darurat, harap hubungi <strong>112</strong>
atau kunjungi rumah sakit terdekat.</p>
<p><i class="bi bi-exclamation-triangle"></i> For medical emergencies, please call <strong>911</strong>
or go to the nearest emergency room.</p>
</div>
</div>
@ -383,99 +430,4 @@
</div>
</section><!-- /Appointmnet Section -->
@endsection
@section('script')
<script>
function sendAppointment() {
$('#error_msg').hide();
Swal.fire({
title: "Loading",
text: "Sedang memproses booking kamu, tunggu sebentar yaa!",
icon: "info",
showConfirmButton: false,
allowOutsideClick: false
});
let name = $('#nama_lengkap').val();
let email = $('#email').val();
let no_telp = $('#no_telp').val();
let tgl_book = $('#tgl_book').val();
let deskripsi = $('#deskripsi').val();
if(!name) {
$('#error_msg').html('<i class="bi bi-exclamation-octagon"></i> Silahkan lengkapi nama lengkap kamu yaa!');
$('#error_msg').show();
}
if(!email) {
$('#error_msg').html('<i class="bi bi-exclamation-octagon"></i> Silahkan lengkapi email kamu yaa!');
$('#error_msg').show();
}
if(!no_telp) {
$('#error_msg').html('<i class="bi bi-exclamation-octagon"></i> Silahkan lengkapi nomor telepon kamu kamu yaa!');
$('#error_msg').show();
}
if(!tgl_book) {
$('#error_msg').html('<i class="bi bi-exclamation-octagon"></i> Silahkan lengkapi tanggal booking kamu yaa!');
$('#error_msg').show();
}
let xhttp = new XMLHttpRequest();
let formData = new FormData();
formData.append('nama_lengkap', name);
formData.append('email', email);
formData.append('no_telp', no_telp);
formData.append('tgl_booking', tgl_book);
if(!deskripsi) {
formData.append('deskripsi_tambahan', 'Tidak ada (tidak diisi)');
} else {
formData.append('deskripsi_tambahan', deskripsi);
}
formData.append('_token', document.getElementById('_token').getAttribute('value'));
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if(response.status) {
Swal.fire({
title: "Info",
text: "Kamu berhasil daftar. Cek email kamu untuk lebih lanjut!",
icon: "success"
});
$('#nama_lengkap').val('');
$('#email').val('');
$('#no_telp').val('');
$('#tgl_book').val('');
$('#deskripsi').val('');
} else if(response.status == false) {
Swal.fire({
title: "Info",
text: "Terjadi kesalahan, coba ulangi lagi yaa!",
icon: "warning"
});
} else {
Swal.fire({
title: "Info",
text: "Terjadi kesalahan dari server, coba lagi nanti!",
icon: "danger"
});
}
}
}
xhttp.open('POST', '{{ route('booking.store') }}');
xhttp.send(formData);
}
$(document).ready(function() {
flatpickr("#tgl_book", {
enableTime: false,
dateFormat: "Y-m-d",
minDate: 'today',
maxDate: new Date().fp_incr(7)
});
});
</script>
@endsection

View File

@ -1,403 +0,0 @@
@section('title', 'Tutorial Test Kecemasan')
@section('body_status_overflow', 'overflow: hidden;')
@section('main_style', 'width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center;')
@extends('user.layouts.test_layout.index')
@section('content')
<div class="container" id="tutorial_panel">
<div class="row justify-content-center">
<div class="col-md-8" id="tutorial_1">
<div class="card shadow-sm border-0">
<div class="card-body">
<h3 class="card-title fw-bold mb-4">Tutorial Tes Kecemasan</h3>
<p class="card-text mb-3">Berikut adalah tutorial untuk menjalankan tes kecemasan dari sistem kami. Pastikan kamu sudah membaca dan memahami setiap langkah yang ada di bawah ini sebelum memulai tes.</p>
<ol>
<li><strong>Persiapan:</strong> Pastikan kondisi kamu berada di tempat yang tenang dan nyaman.</li>
<li><strong>Durasi Tes:</strong> Tes ini akan memakan waktu sekitar 2-5 menit, tergantung pada kecepatanmu dalam menjawab pertanyaan.</li>
<li><strong>Jenis Pertanyaan:</strong> Tes ini terdiri dari beberapa pertanyaan yang dirancang untuk mengukur tingkat kecemasanmu. Jawablah setiap pertanyaan dengan jujur dan sesuai dengan perasaanmu saat ini.</li>
<li><strong>Hasil Tes:</strong> Setelah menyelesaikan tes, hasilnya akan dianalisis oleh sistem kami dan akan diberikan kepada psikolog yang menangani kasusmu. Psikolog akan memberikan feedback dan rekomendasi berdasarkan hasil tes tersebut. Kamu juga akan menerima laporan hasil tes secara detail dan juga bisa dilihat berdasarkan kode tes yang kamu dapatkan saat melakukan booking.</li>
<li><strong>Konsultasi Lanjutan:</strong> Jika hasil tes menunjukkan bahwa kamu mengalami tingkat kecemasan yang tinggi, psikolog mungkin akan menyarankan sesi konsultasi lanjutan untuk membahas hasil tes dan langkah selanjutnya yang bisa diambil.</li>
</ol>
<p class="card-text mt-3">Jika kamu sudah siap, silakan klik tombol "Next" di bawah ini untuk setup lingkungan terlebih dahulu.</p>
<button class="btn btn-primary" onclick="showTutorial(2, 'tutorial_1')">Next</button>
</div>
</div>
</div>
<div class="col-md-8" id="tutorial_2">
<div class="card shadow-sm border-0">
<div class="card-body">
<h3 class="card-title fw-bold mb-4">Setup Lingkungan</h3>
<p class="card-text mb-3">Sebelum tes dimulai, setup alat Tobii dibawah ini:</p>
<ol>
<li><strong>Persiapan:</strong> Pastikan Tobii sudah terhubung dan berfungsi dengan baik.</li>
<li><strong>Penempatan:</strong> Tempatkan Tobii di posisi yang sesuai untuk mendeteksi gerakan mata dengan akurat.</li>
<li><strong>Hubungkan Tobii:</strong> Hubungkan Tobii ke dalam web dengan menggunakan aplikasi API, jika tidak terhubung, hubungi administrator.</li>
<li><strong>Hasil:</strong> Setelah menghubungkan ke web berhasil, akan muncul notifikasi bahwa Tobii telah terhubung.</li>
<li><strong>Selanjutnya:</strong> Melakukan kalibrasi mata dengan Tobii.</li>
</ol>
<p class="card-text mt-3" id="status_tobii">Memuat...</p>
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(1, 'tutorial_2')">Back</button>
<button class="btn btn-primary" id="next_btn_connect_tobii" onclick="showTutorial(3, 'tutorial_2')">Next</button>
</div>
</div>
</div>
<div class="col-md-8" id="tutorial_3">
<div class="card shadow-sm border-0">
<div class="card-body">
<h3 class="card-title fw-bold mb-4">Tes Keakuratan Mata</h3>
<p class="card-text mb-3">Sebelum tes dimulai, cek keakuratan device Tobii anda (disarankan full-screen), jika tidak akurat, lakukan kalibrasi kepada administrator.</p>
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(2, 'tutorial_3')">Back</button>
<button class="btn btn-secondary" id="fullscreen_btn" onclick="openFullscreen(this)" data-status="fullscreen">Fullscreen</button>
<button class="btn btn-secondary" id="hide_btn" onclick="hidePanelTutorial(this)" data-status="hide">Hide</button>
<a class="btn btn-primary" id="start_ujian" href="#">Mulai Ujian</a>
</div>
</div>
</div>
</div>
</div>
<!-- btn show -->
<button type="button" class="btn btn-secondary position-absolute" onclick="showCalibrationPoints()" id="show_calibration" style="z-index: 999">Show</button>
<div class="position-absolute bg-white" style="width: 100vw; height: 100vh; z-index: -1;" id="calibration_point">
<table class="w-100 h-100">
<tr>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
</tr>
<tr>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
</tr>
<tr>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
<td align="center">
<div class="rounded-circle bg-primary" style="width: 3%; aspect-ratio: 1/1;"></div>
</td>
</tr>
</table>
<div id="the_eye" class="rounded-circle bg-danger position-absolute" style="width: 1%; aspect-ratio: 1/1;"></div>
</div>
@endsection
@section('script')
<script>
let getDataInterval = false;
let checkTobiiInterval = null;
let tobiiConnectedStatus = false;
let ws = null;
let reconnectDelay = 1000;
let maxReconnectDelay = 10000;
let SESSION_ID = '{{ $data_session->id_test_sessions }}';
let TOKEN_SESSION = '{{ $data_session->token_session }}';
function startWebsocket() {
console.log("Connecting to WebSocket...");
ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
ws.onopen = () => {
console.log("Connected to WebSocket");
reconnectDelay = 1000;
ws.send(JSON.stringify({
type: "register",
session_id: SESSION_ID,
token_session: TOKEN_SESSION,
role: "web"
}));
searchingTobiiDevice();
ws.send(JSON.stringify({
type: "update_status",
status_sessions: false,
id_session: SESSION_ID
}));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received data from WebSocket:', data);
if(data.type === 'tobii_data') {
try {
moveTheEye(data.gaze_x, data.gaze_y);
} catch(error) {
console.log(error);
}
}
if(data.type === 'status_tobii_device') {
if(data.status) {
console.log('Tobii device is connected');
tobiiConnectedStatus = true;
} else {
console.log('Tobii device is not connected');
tobiiConnectedStatus = false;
searchingTobiiDevice();
}
checkTobiiConnection();
}
if(data.type === 'reset_start_tobii') {
startTobii();
}
};
ws.onerror = function (error) {
console.log("WebSocket error");
};
ws.onclose = function () {
setTimeout(() => {
reconnectDelay = Math.min(
reconnectDelay * 2,
maxReconnectDelay
);
console.log("Disconnected from WebSocket. Retrying in " + reconnectDelay + " ms...");
startWebsocket();
}, reconnectDelay);
};
}
function showTutorial(step, tutorialId) {
$(`#${tutorialId}`).hide();
$(`#tutorial_${step}`).show();
if(step === 2 || step === 3) {
startTobii();
checkTobiiConnection();
// checkTobiiInterval = setInterval(() => {
// checkTobiiConnection();
// }, 2000);
} else {
if(checkTobiiInterval) {
clearInterval(checkTobiiInterval);
}
stopTobii();
}
if(step === 3) {
$('#calibration_point').show();
let test_url = '{{ route('ujian.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
$('#start_ujian').attr('href', test_url.replace('__ID_TEST_SESSIONS__', SESSION_ID));
} else {
$('#calibration_point').hide();
}
}
function hidePanelTutorial(btn) {
const status = $(btn).attr('data-status');
if (status === 'hide') {
$('#tutorial_panel').hide();
$('#show_calibration').show();
}
}
function showCalibrationPoints() {
$('#show_calibration').toggle();
$('#tutorial_panel').toggle();
}
function moveTheEye(x, y) {
const eye = $('#the_eye');
eye.css({ left: x + 'px', top: y + 'px' });
}
function openFullscreen() {
const status = $('#fullscreen_btn').attr('data-status');
const elem = document.documentElement;
if (status === 'fullscreen') {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen(); // Safari
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'exit-fullscreen');
} else if (status === 'exit-fullscreen') {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen(); // Safari
} else if (document.msExitFullscreen) {
document.msExitFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'fullscreen');
}
}
function generateLinkApiTobii() {
const linkApi = '{{ env("WEBSOCKET_URL") }}'.replace('ws://', '');
const linkId = SESSION_ID;
const linkToken = TOKEN_SESSION;
$('#link_api_tobii').val(linkApi);
$('#link_id_tobii').val(linkId);
$('#link_token_tobii').val(linkToken);
}
function copyLinkApiTobii() {
const linkApi = $('#link_api_tobii').val();
navigator.clipboard.writeText(linkApi)
.then(() => {
Swal.fire({
icon: 'success',
title: 'Link API berhasil disalin!',
showConfirmButton: true,
timer: 1500
});
})
.catch(err => {
Swal.fire({
icon: 'error',
title: 'Gagal menyalin Link API',
text: err,
});
});
}
function copyLinkIdTobii() {
const linkId = $('#link_id_tobii').val();
navigator.clipboard.writeText(linkId)
.then(() => {
Swal.fire({
icon: 'success',
title: 'Link ID berhasil disalin!',
showConfirmButton: true,
timer: 1500
});
})
.catch(err => {
Swal.fire({
icon: 'error',
title: 'Gagal menyalin Link ID',
text: err,
});
});
}
function copyLinkTokenTobii() {
const linkToken = $('#link_token_tobii').val();
navigator.clipboard.writeText(linkToken)
.then(() => {
Swal.fire({
icon: 'success',
title: 'Link Token berhasil disalin!',
showConfirmButton: true,
timer: 1500
});
})
.catch(err => {
Swal.fire({
icon: 'error',
title: 'Gagal menyalin Link Token',
text: err,
});
});
}
function checkTobiiConnection() {
// ws.send(JSON.stringify({
// type: "check_tobii_connection",
// session_id: SESSION_ID,
// }));
if(tobiiConnectedStatus) {
$('#status_tobii').text('Status Tobii: Terhubung').removeClass('text-danger').addClass('text-success');
$('#next_btn_connect_tobii').show();
} else {
$('#status_tobii').text('Status Tobii: Tidak Terhubung').removeClass('text-success').addClass('text-danger');
$('#next_btn_connect_tobii').hide();
}
}
async function fetchDataTobii() {
try {
const response = await fetch('{{ route("tobii-receiver.fetchData", ['id_test_sessions' => $data_session->id_test_sessions]) }}');
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
moveTheEye(data.gaze_x, data.gaze_y);
} catch (error) {
console.error('Error fetching Tobii data:', error);
}
}
async function searchingTobiiDevice() {
try {
console.log('Searching for tobii...');
const response = await fetch('{{ env('TOBII_API_URL') }}', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
session_id: SESSION_ID,
token: TOKEN_SESSION,
url: "{{ env('WEBSOCKET_URL') }}"
})
}
);
if (!response.ok) {
console.error('Failed to get tobii device, retrying...');
setTimeout(5000);
searchingTobiiDevice();
return;
}
const data = await response.json();
if(data.session_id == SESSION_ID && data.token == TOKEN_SESSION) {
tobiiConnectedStatus = true;
console.log('Done searching...');
}
} catch (error) {
console.error('Error getting Tobii device:', error);
setTimeout(5000);
searchingTobiiDevice();
}
}
function startTobii() {
ws.send(JSON.stringify({
type: "command",
action: "start",
session_id: SESSION_ID
}));
}
function stopTobii() {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
}
$(document).ready(function() {
$('#tutorial_2').hide();
$('#tutorial_3').hide();
$('#next_btn_connect_tobii').hide();
$('#calibration_point').hide();
$('#show_calibration').hide();
generateLinkApiTobii();
startWebsocket();
console.log("hehehehehehehehehhehehe");
});
</script>
@endsection

View File

@ -1,376 +0,0 @@
@section('title', 'Ujian Kecemasan')
{{-- @section('body_status_overflow', 'overflow: hidden;') --}}
@section('main_style', 'min-height: 100vh;')
@extends('user.layouts.test_layout.index')
@section('content')
<div class="container-fluid p-0 d-flex flex-column" style="min-height: 100vh">
<nav class="navbar navbar-expand-lg bg-body-tertiary px-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Smart Anxiety</a>
<div class="collapse navbar-collapse justify-content-between" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<div class="d-flex col-md-4">
<div class="col-md-4 d-flex justify-content-center align-items-center">
Time Left: <span id="time_left"></span>
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<span id="bg_status_tobii" class="rounded bg-warning d-block mx-2" style="width: 10px; aspect-ratio: 1/1;"></span>Status Tobii
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<button id="fullscreen_btn" data-status="fullscreen" class="btn btn-sm btn-outline-secondary" onclick="openFullscreen()">Fullscreen</button>
</div>
</div>
</div>
</div>
</nav>
<div class="d-flex flex-grow-1 container-fluid">
<div class="row flex-grow-1">
<div class="col-md-9 border-end">
<div class="row justify-content-center flex-column p-4">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2">Soal</div>
<div class="col-md-12 d-none" id="id_question" value="{{ $data_question->id_soal }}"></div>
<div class="col-md-12 p-2" style="text-align: justify">{{ $data_question->pertanyaan }}</div>
<div class="col-md-12">
<div class="fs-4 fw-bold p-2">Jawaban:</div>
@foreach ($answer as $item)
<div class="form-check m-2">
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_{{ $item['key'] }}">
<label class="form-check-label" for="jawaban_{{ $item['key'] }}">{{ $item['value'] }}</label>
</div>
@endforeach
</div>
</div>
</div>
<div class="col-md-3">
<div class="row p-3">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2 mb-3">Navigasi Soal</div>
@foreach ($answered_question as $question)
<div onclick="changeQuestion({{ $question['nomor_soal'] }})" id="nomor_{{ $question['nomor_soal'] }}" class="col-md-1 btn d-flex justify-content-center align-items-center {{ $question['answered'] ? 'bg-secondary-subtle' : 'bg-light-subtle' }} border rounded p-0 m-1" style="aspect-ratio: 1/1.5;">{{ $question['nomor_soal'] }}</div>
@endforeach
<div class="col-md-12 p-0 mt-3">
@if ($question_number > 1)
<div class="btn btn-secondary" onclick="changeQuestion({{ $question_number - 1 }})">Previous</div>
@endif
@if ($is_last_question)
<div class="btn btn-success" onclick="finishExam()">Finish</div>
@else
<div class="btn btn-primary" onclick="changeQuestion({{ $question_number + 1 }})">Next</div>
@endif
</div>
</div>
<div class="row p-3">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Instruksi</h5>
<p class="card-text">Silahkan baca soal dengan teliti dan pilih jawaban yang paling tepat.</p>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-light-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban BELUM diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-secondary-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban SUDAH diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-info border rounded p-0 m-1 text-white" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa anda sedang membaca/menjawab soal ini.</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('script')
<script>
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
let SESSION_ID = '{{ $data_session->id_test_sessions }}';
let TOKEN_SESSION = '{{ $data_session->token_session }}';
let UNIX_END_TIME = null;
function changeQuestion(num) {
let url_temp = window.location.href;
let current_num = new URLSearchParams(window.location.search).get('question');
let xhttp = new XMLHttpRequest();
let the_answer = null;
let token = document.getElementById('_token').getAttribute('value');
let formData = new FormData();
if(!current_num) {
current_num = '{{ $question_number }}';
}
if(current_num == num) {
console.log('same question');
return;
}
document.getElementsByName('jawaban_final').forEach(element => {
if (element.checked) {
the_answer = {
key: element.id.split('_')[1],
};
}
});
if(the_answer) {
formData.append('jawaban_final', the_answer.key);
formData.append('_token', token);
formData.append('question', num);
formData.append('id_question', $('#id_question').attr('value'));
formData.append('session_id', SESSION_ID);
xhttp.open("POST", "{{ route('ujian.store') }}", false);
xhttp.send(formData);
}
stopTobii();
if(!url_temp.includes('question')) {
window.location.href = url_temp + '&question=' + num;
} else if(url_temp.includes('question')) {
window.location.href = window.location.href.replace('&question=' + current_num, '&question=' + num);
}
}
function getCurrentAnswer() {
let id_question = $('#id_question').attr('value');
let xhttp = new XMLHttpRequest();
let current_num = new URLSearchParams(window.location.search).get('question');
if(!current_num) {
current_num = '{{ $question_number }}';
}
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
document.getElementById('nomor_' + current_num).classList.remove('bg-light-subtle');
document.getElementById('nomor_' + current_num).classList.remove('bg-secondary-subtle');
document.getElementById('nomor_' + current_num).classList.add('bg-info');
document.getElementById('nomor_' + current_num).classList.add('text-white');
if(response.status == 'success') {
document.getElementsByName('jawaban_final').forEach(element => {
if (element.id.split('_')[1] == response.jawaban) {
element.checked = true;
}
});
}
}
};
xhttp.open("GET", "{{ route('ujian.getCurrentAnswer') }}?id_question=" + id_question + "&session_id=" + SESSION_ID, false);
xhttp.send();
}
function getTimeLeft() {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
UNIX_END_TIME = response.time_left;
}
};
xhttp.open("GET", "{{ route('ujian.getTimeLeft') }}?session_id=" + SESSION_ID, false);
xhttp.send();
}
function updateTimeLeft() {
let time_left = UNIX_END_TIME - Math.floor(Date.now() / 1000);
if(time_left < 0) {
time_left = 0;
finishExam();
}
let minutes = Math.floor(time_left / 60);
let seconds = time_left % 60;
document.getElementById('time_left').innerText = ' ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
function finishExam() {
Swal.fire({
title: 'Alert',
icon: 'question',
text: 'Apakah Anda yakin ingin mengakhiri ujian? (aksi tidak dapat dikembalikan)',
confirmButtonText: 'Ya',
cancelButtonText: 'Tidak',
showCancelButton: true,
showCloseButton: true,
}).then((result) => {
if (result.isConfirmed) {
event.preventDefault();
let current_num = new URLSearchParams(window.location.search).get('question');
let xhttp = new XMLHttpRequest();
let the_answer = null;
let token = document.getElementById('_token').getAttribute('value');
let formData = new FormData();
document.getElementsByName('jawaban_final').forEach(element => {
if (element.checked) {
the_answer = {
key: element.id.split('_')[1],
};
}
});
if(the_answer) {
formData.append('jawaban_final', the_answer.key);
formData.append('_token', token);
formData.append('question', current_num);
formData.append('id_question', $('#id_question').attr('value'));
formData.append('session_id', SESSION_ID);
xhttp.open("POST", "{{ route('ujian.store') }}", false);
xhttp.send(formData);
console.log("sending answer (finish)");
}
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
//send_data_to_db
ws.send(JSON.stringify({
type: "send_data_to_db",
session_id: SESSION_ID
}));
ws.send(JSON.stringify({
type: "update_status",
status_sessions: false,
session_id: SESSION_ID
}));
window.location.href = "{{ route('hasil-tes.index') }}?id_test_sessions=" + SESSION_ID;
}
});
}
function startTobii() {
ws.send(JSON.stringify({
type: "command",
action: "start",
session_id: SESSION_ID
}));
}
function stopTobii() {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
}
function openFullscreen() {
const status = $('#fullscreen_btn').attr('data-status');
const elem = document.documentElement;
if (status === 'fullscreen') {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen(); // Safari
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'exit-fullscreen');
$('#fullscreen_btn').text('Exit Fullscreen');
s.send(JSON.stringify({
type: "command",
action: "start",
session_id: SESSION_ID
}));
} else if (status === 'exit-fullscreen') {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen(); // Safari
} else if (document.msExitFullscreen) {
document.msExitFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'fullscreen');
$('#fullscreen_btn').text('Enter Fullscreen');
}
}
function checkFullscreen() {
if (!document.fullscreenElement) {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
Swal.fire({
title: 'Alert',
icon: 'warning',
text: 'Anda keluar dari mode fullscreen, harap masuk ke mode fullscreen untuk melanjutkan ujian.',
confirmButtonText: 'Ya',
showCancelButton: false,
showCloseButton: false,
allowOutsideClick: false,
allowEscapeKey: false,
backdrop: `rgba(0, 0, 0, 0.4)`
}).then((result) => {
if (result.isConfirmed) {
openFullscreen();
}
});
}
}
$(document).ready(function() {
ws.onopen = () => {
console.log("Connected to WebSocket");
ws.send(JSON.stringify({
type: "register",
session_id: SESSION_ID,
token_session: TOKEN_SESSION,
role: "web"
}));
document.addEventListener('fullscreenchange', checkFullscreen);
checkFullscreen();
ws.send(JSON.stringify({
type: "update_status",
status_sessions: true,
session_id: SESSION_ID
}));
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if(data.type === 'reset_start_tobii') {
startTobii();
}
if(data.type === 'status_tobii_device') {
if(data.status) {
console.log('Tobii device is connected');
// document.getElementById('status_tobii_device').innerText = 'Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.remove('bg-danger');
document.getElementById('bg_status_tobii').classList.add('bg-success');
} else {
console.log('Tobii device is not connected');
// document.getElementById('status_tobii_device').innerText = 'Not Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
}
}
};
startTobii();
getCurrentAnswer();
getTimeLeft();
setInterval(updateTimeLeft, 1000);
};
});
</script>
@endsection

View File

@ -1,508 +0,0 @@
@section('title', 'Ujian Kecemasan')
{{-- @section('body_status_overflow', 'overflow: hidden;') --}}
@section('main_style', 'min-height: 100vh;')
@extends('user.layouts.test_layout.index')
@section('content')
<div class="container-fluid p-0 d-flex flex-column" style="min-height: 100vh">
<nav class="navbar navbar-expand-lg bg-body-tertiary px-2">
<div class="container-fluid">
<a class="navbar-brand" href="#">Smart Anxiety</a>
<div class="collapse navbar-collapse justify-content-between" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
<div class="d-flex col-md-4">
<div class="col-md-4 d-flex justify-content-center align-items-center">
Time Left: <span id="time_left"></span>
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<span id="bg_status_tobii" class="rounded bg-warning d-block mx-2" style="width: 10px; aspect-ratio: 1/1;"></span>Status Tobii
</div>
<div class="col-md-4 d-flex justify-content-center align-items-center">
<button id="fullscreen_btn" data-status="fullscreen" class="btn btn-sm btn-outline-secondary" onclick="openFullscreen()">Fullscreen</button>
</div>
</div>
</div>
</div>
</nav>
<div class="d-flex flex-grow-1 container-fluid">
<div class="row flex-grow-1">
<div class="col-md-9 border-end">
<div class="row justify-content-center flex-column p-4">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2">Soal</div>
<div class="col-md-12 p-2 d-none" id="id_question" style="text-align: justify"></div>
<div class="col-md-12 p-2 fs-1 text-muted" id="text_question" style="text-align: justify"></div>
<div class="col-md-12 fs-1 text-muted" id="answer_field">
<div class="fs-4 fw-bold p-2">Jawaban:</div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="row p-3" id="navigation_field">
<div class="col-md-12 border-bottom fs-4 fw-bold p-2 mb-3">Navigasi Soal</div>
</div>
<div class="row p-3">
<div class="col-md-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Instruksi</h5>
<p class="card-text">Silahkan baca soal dengan teliti dan pilih jawaban yang paling tepat.</p>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-light-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban BELUM diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-secondary-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa jawaban SUDAH diisi.</span>
</div>
<div class="card-text d-flex align-items-center">
<span class="col-md-1 bg-info border rounded p-0 m-1 text-white" style="aspect-ratio: 1/1.5;"></span>
<span>adalah tanda bahwa anda sedang membaca/menjawab soal ini.</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@endsection
@section('script')
<script>
let ws = null;
let reconnectDelay = 1000;
let maxReconnectDelay = 10000;
const SESSION_ID = '{{ $data_session->id_test_sessions }}';
const TOKEN_SESSION = '{{ $data_session->token_session }}';
let UNIX_END_TIME = null;
let QUESTION_INDEX = 1;
let QUESTION_ID = null;
let CURRENT_BTN = null;
let CAPTION_BTN = null;
function startWebsocket() {
console.log("Connecting to WebSocket...");
ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
ws.onopen = () => {
console.log("Connected to WebSocket");
ws.send(JSON.stringify({
type: "register",
session_id: SESSION_ID,
token_session: TOKEN_SESSION,
role: "web"
}));
document.addEventListener('fullscreenchange', checkFullscreen);
ws.send(JSON.stringify({
type: "update_status",
status_sessions: true,
session_id: SESSION_ID
}));
searchingTobiiDevice()
checkFullscreen();
getTimeLeft();
setInterval(updateTimeLeft, 1000);
getNavigationField();
setCurrentNavigation();
fetchQuestion(QUESTION_INDEX);
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
if(data.type === 'reset_start_tobii') {
startTobii();
}
if(data.type === 'status_tobii_device') {
if(data.status) {
// console.log('Tobii device is connected');
// document.getElementById('status_tobii_device').innerText = 'Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.remove('bg-danger');
document.getElementById('bg_status_tobii').classList.add('bg-success');
} else {
console.log('Tobii device is not connected');
searchingTobiiDevice();
// document.getElementById('status_tobii_device').innerText = 'Not Connected';
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
}
}
};
ws.onerror = function (error) {
console.log("WebSocket error");
};
ws.onclose = function () {
setTimeout(() => {
reconnectDelay = Math.min(
reconnectDelay * 2,
maxReconnectDelay
);
console.log("Disconnected from WebSocket. Retrying in " + reconnectDelay + " ms...");
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
startWebsocket();
}, reconnectDelay);
};
}
async function searchingTobiiDevice() {
try {
console.log('Searching for tobii...');
const response = await fetch('{{ env('TOBII_API_URL') }}', {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
session_id: SESSION_ID,
token: TOKEN_SESSION,
url: "{{ env('WEBSOCKET_URL') }}"
})
}
);
if (!response.ok) {
console.error('Failed to get tobii device, retrying...');
setTimeout(5000);
searchingTobiiDevice();
return;
}
const data = await response.json();
if(data.session_id == SESSION_ID && data.token == TOKEN_SESSION) {
// tobiiConnectedStatus = true;
startTobii();
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
console.log('Done searching...');
}
} catch (error) {
console.error('Error getting Tobii device:', error);
document.getElementById('bg_status_tobii').classList.remove('bg-success');
document.getElementById('bg_status_tobii').classList.remove('bg-warning');
document.getElementById('bg_status_tobii').classList.add('bg-danger');
setTimeout(5000);
searchingTobiiDevice();
}
}
function changeQuestion(num) {
Swal.showLoading();
let xhttp = new XMLHttpRequest();
let the_answer = null;
let token = document.getElementById('_token').getAttribute('value');
let formData = new FormData();
if(QUESTION_INDEX == num) {
console.log('same question');
Swal.close();
return;
}
document.getElementsByName('jawaban_final').forEach(element => {
if (element.checked) {
the_answer = {
key: element.id.split('_')[1],
};
}
});
if(the_answer) {
formData.append('jawaban_final', the_answer.key);
formData.append('_token', token);
formData.append('question', num);
formData.append('id_question', QUESTION_ID);
formData.append('session_id', SESSION_ID);
xhttp.open("POST", "{{ route('ujian.store') }}", true);
xhttp.send(formData);
}
// stopTobii();
QUESTION_INDEX = num;
getNavigationField();
fetchQuestion(QUESTION_INDEX);
}
function setCurrentNavigation() {
$('#nomor_' + QUESTION_INDEX).removeClass('bg-light-subtle');
$('#nomor_' + QUESTION_INDEX).removeClass('bg-secondary-subtle');
$('#nomor_' + QUESTION_INDEX).addClass('bg-info');
}
function fetchQuestion(question_index) {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if(response.status) {
$('#text_question').html(response.data.pertanyaan);
QUESTION_ID = response.data.id_soal;
getCurrentAnswer(response.data.id_soal);
} else {
Swal.fire({
title: 'Error',
icon: 'error',
text: 'Terjadi kesalahan saat mengambil soal. Silahkan refresh halaman ini.',
confirmButtonText: 'OK'
});
}
}
}
xhttp.open("GET", "{{ route('ujian.fetchQuestion') }}?session_id=" + SESSION_ID + "&question_index=" + question_index, true);
xhttp.send();
}
function finishExam() {
Swal.fire({
title: 'Alert',
icon: 'question',
text: 'Apakah Anda yakin ingin mengakhiri ujian? (aksi tidak dapat dikembalikan)',
confirmButtonText: 'Ya',
cancelButtonText: 'Tidak',
showCancelButton: true,
showCloseButton: true,
}).then((result) => {
if (result.isConfirmed) {
event.preventDefault();
let xhttp = new XMLHttpRequest();
let the_answer = null;
let token = document.getElementById('_token').getAttribute('value');
let formData = new FormData();
document.getElementsByName('jawaban_final').forEach(element => {
if (element.checked) {
the_answer = {
key: element.id.split('_')[1],
};
}
});
if(the_answer) {
formData.append('jawaban_final', the_answer.key);
formData.append('_token', token);
formData.append('question', QUESTION_INDEX);
formData.append('id_question', QUESTION_ID);
formData.append('session_id', SESSION_ID);
xhttp.open("POST", "{{ route('ujian.store') }}", false);
xhttp.send(formData);
console.log("sending answer (finish)");
}
ws.send(JSON.stringify({
type: "command",
action: "stop",
finish: true,
session_id: SESSION_ID
}));
//send_data_to_db
ws.send(JSON.stringify({
type: "send_data_to_db",
session_id: SESSION_ID
}));
ws.send(JSON.stringify({
type: "update_status",
status_sessions: false,
session_id: SESSION_ID
}));
window.location.href = "{{ route('hasil-tes.index') }}?id_test_sessions=" + SESSION_ID;
}
});
}
function getCurrentAnswer(id_question) {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if (response.status) {
let choices_html = '';
$('#answer_field').html('<div class="fs-4 fw-bold p-2">Jawaban:</div>');
response.choices.forEach((choice) => {
choices_html += `
<div class="form-check m-2">
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_${choice.key}">
<label class="form-check-label" for="jawaban_${choice.key}">${choice.value}</label>
</div>
`;
});
$('#answer_field').append(choices_html);
if(response.jawaban != null) {
document.getElementsByName('jawaban_final').forEach(element => {
if (element.id.split('_')[1] == response.jawaban) {
element.checked = true;
}
});
}
Swal.close();
checkFullscreen();
}
}
};
xhttp.open("GET", "{{ route('ujian.getCurrentAnswer') }}?session_id=" + SESSION_ID + "&id_question=" + id_question, false);
xhttp.send();
}
function getNavigationField() {
let xhttp = new XMLHttpRequest();
let total_question = 0;
xhttp.onreadystatechange = function() {
if(this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
if(response.status) {
let navigation_field = '<div class="col-md-12 border-bottom fs-4 fw-bold p-2 mb-3">Navigasi Soal</div>';
$('#navigation_field').html(navigation_field);
response.data.forEach((q) => {
let answered = 'bg-light-subtle';
if(q.answered) {
answered = 'bg-secondary-subtle'
}
navigation_field += `
<div onclick="changeQuestion(${q.index})" id="nomor_${q.index}" class="col-md-1 btn d-flex justify-content-center align-items-center ${answered} border rounded p-0 m-1" style="aspect-ratio: 1/1.5;">${q.index}</div>
`;
total_question += 1;
});
if(QUESTION_INDEX <= total_question) {
let next_num = 0;
next_num = QUESTION_INDEX + 1;
if(next_num > total_question) {
// tombol finish dan back
navigation_field += `
<div class="btn btn-secondary mb-2" onclick="changeQuestion(${QUESTION_INDEX - 1})">Back</div>
`;
navigation_field += `
<div class="btn btn-success" onclick="finishExam()">Finish</div>
`;
} else {
if((QUESTION_INDEX - 1) != 0) {
navigation_field += `
<div class="btn btn-secondary mb-2" onclick="changeQuestion(${QUESTION_INDEX - 1})">Back</div>
`;
}
navigation_field += `
<div class="btn btn-primary" status="false" onclick="changeQuestion(${QUESTION_INDEX + 1})">Next</div>
`;
}
}
$('#navigation_field').html(navigation_field);
setCurrentNavigation();
}
}
};
xhttp.open('GET', '{{ route('ujian.navigationField') }}?session_id=' + SESSION_ID, true);
xhttp.send();
}
function getTimeLeft() {
let xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let response = JSON.parse(this.responseText);
console.log('Time left:', response.time_left);
UNIX_END_TIME = response.time_left;
}
};
xhttp.open("GET", "{{ route('ujian.getTimeLeft') }}?session_id=" + SESSION_ID, false);
xhttp.send();
}
function updateTimeLeft() {
let time_left = UNIX_END_TIME - Math.floor(Date.now() / 1000);
if(time_left < 0) {
time_left = 0;
finishExam();
}
let minutes = Math.floor(time_left / 60);
let seconds = time_left % 60;
document.getElementById('time_left').innerText = ' ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
}
function startTobii() {
ws.send(JSON.stringify({
type: "command",
action: "start",
session_id: SESSION_ID
}));
}
function stopTobii() {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
}
function openFullscreen() {
const status = $('#fullscreen_btn').attr('data-status');
const elem = document.documentElement;
if (status === 'fullscreen') {
if (elem.requestFullscreen) {
elem.requestFullscreen();
} else if (elem.webkitRequestFullscreen) {
elem.webkitRequestFullscreen(); // Safari
} else if (elem.msRequestFullscreen) {
elem.msRequestFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'exit-fullscreen');
$('#fullscreen_btn').text('Exit Fullscreen');
startTobii();
} else if (status === 'exit-fullscreen') {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen(); // Safari
} else if (document.msExitFullscreen) {
document.msExitFullscreen(); // IE
}
$('#fullscreen_btn').attr('data-status', 'fullscreen');
$('#fullscreen_btn').text('Enter Fullscreen');
}
}
function checkFullscreen() {
if (!document.fullscreenElement) {
ws.send(JSON.stringify({
type: "command",
action: "stop",
session_id: SESSION_ID
}));
Swal.fire({
title: 'Alert',
icon: 'warning',
text: 'Anda keluar dari mode fullscreen, harap masuk ke mode fullscreen untuk melanjutkan ujian.',
confirmButtonText: 'Ya',
showCancelButton: false,
showCloseButton: false,
allowOutsideClick: false,
allowEscapeKey: false,
backdrop: `rgba(0, 0, 0, 0.4)`
}).then((result) => {
if (result.isConfirmed) {
openFullscreen();
}
});
}
}
$(document).ready(function() {
startWebsocket();
});
</script>
@endsection

View File

@ -1,19 +1,11 @@
<?php
use App\Http\Controllers\BookingController;
use App\Http\Controllers\CekStatusController;
use App\Http\Controllers\DashboardController;
use App\Http\Controllers\DataSoalController;
use App\Http\Controllers\FinishUjianController;
use App\Http\Controllers\HalamanUjianController;
use App\Http\Controllers\HasilTesController;
use App\Http\Controllers\LandingController;
use App\Http\Controllers\ProfileController;
use App\Http\Controllers\TestSessionsController;
use App\Http\Controllers\TobiiReceiverController;
use App\Http\Controllers\TutorialTesController;
use App\Http\Controllers\UsersController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
@ -32,43 +24,13 @@
Route::resource('beranda', LandingController::class)->only(['index']);
Route::get('/about', [LandingController::class, 'about'])->name('beranda.about');
Route::resource('booking', BookingController::class)->only(['store']);
Route::resource('cek-status', CekStatusController::class)->only(['index', 'show']);
Route::resource('tutorial-tes', TutorialTesController::class)->only(['index']);
Route::resource('test-sessions', TestSessionsController::class)->only(['store', 'show']);
Route::get('test-sessions/get/screen', [TestSessionsController::class, 'getScreen'])->name('test-sessions.getScreen');
Route::resource('tobii-receiver', TobiiReceiverController::class)->only(['store', 'show']);
Route::get('tobii-receiver/fetch/data/{id_test_sessions}', [TobiiReceiverController::class, 'fetchDataTobii'])->name('tobii-receiver.fetchData');
Route::resource('ujian', HalamanUjianController::class);
Route::get('ujian/get/current-answer', [HalamanUjianController::class, 'getCurrentAnswer'])->name('ujian.getCurrentAnswer');
Route::get('ujian/get/time-left', [HalamanUjianController::class, 'getTimeLeft'])->name('ujian.getTimeLeft');
Route::get('ujian/fetch/question', [HalamanUjianController::class, 'fetchQuestion'])->name('ujian.fetchQuestion');
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::get('dashboard/fetch/data', [DashboardController::class, 'getDataDashboard'])->name('dashboard.fetchData');
Route::get('dashboard/fetch/data-table', [DashboardController::class, 'getDataForDashboardTable'])->name('dashboard.fetchDataTable');
Route::resource('users', UsersController::class);
Route::get('users/fetch/data', [UsersController::class, 'getData'])->name('users.fetchData');
Route::resource('booking', BookingController::class)->except(['store']);
Route::get('booking/fetch/data', [BookingController::class, 'getchData'])->name('booking.fetchData');
Route::resource('soal', DataSoalController::class);
Route::get('soal/fetch/data', [DataSoalController::class, 'getData'])->name('soal.fetchData');
Route::resource('hasil_tes', HasilTesController::class);
Route::get('hasil_tes/fetch/data', [HasilTesController::class, 'fetchData'])->name('hasil-tes.fetchData');
});
Route::get('email/test', function(Request $req) {
return view('layouts.mail-send-code', [
'code' => 'ABC123',
'name' => 'Mahayoga',
'startExpirationTime' => '09:00:00',
'endExpirationTime' => '09:05:00',
'tglExpired' => '2023-10-01'
]);
});
require __DIR__.'/auth.php';