Compare commits
No commits in common. "master" and "websocket-tobii" have entirely different histories.
|
|
@ -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)]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,9 @@
|
|||
|
||||
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
|
||||
{
|
||||
|
|
@ -17,28 +13,6 @@ class BookingController extends Controller
|
|||
*/
|
||||
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,
|
||||
|
|
@ -100,7 +74,6 @@ public function store(Request $request)
|
|||
]);
|
||||
|
||||
$kode_unik = $this->generateCode();
|
||||
$tgl_request = Carbon::parse($request->tgl_booking)->timestamp + 86399;
|
||||
|
||||
BookingModel::create([
|
||||
'nama_lengkap' => $request->nama_lengkap,
|
||||
|
|
@ -108,18 +81,9 @@ public function store(Request $request)
|
|||
'no_telp' => $request->no_telp,
|
||||
'tgl_booking' => $request->tgl_booking,
|
||||
'deskripsi_tambahan' => $request->deskripsi_tambahan,
|
||||
'kode_unik' => $kode_unik,
|
||||
'unix_expired_time' => $tgl_request
|
||||
'kode_unik' => $kode_unik
|
||||
]);
|
||||
|
||||
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!'
|
||||
|
|
@ -166,10 +130,8 @@ public function update(Request $request, string $id)
|
|||
'status_tes' => ['required']
|
||||
]);
|
||||
|
||||
$data = BookingModel::where('id_booking', $id)->first();
|
||||
|
||||
$data->update([
|
||||
'status_tes' => str($request->status_tes)
|
||||
BookingModel::where('id_booking', $id)->update([
|
||||
'status_tes' => $request->status_tes
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
|
|
|
|||
|
|
@ -38,19 +38,6 @@ 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 . ')',
|
||||
|
|
@ -59,8 +46,6 @@ public function show(string $id)
|
|||
'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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -2,176 +2,12 @@
|
|||
|
||||
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.
|
||||
*/
|
||||
|
|
@ -191,112 +27,34 @@ public function index(Request $request)
|
|||
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;
|
||||
// }
|
||||
$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++;
|
||||
// }
|
||||
$data_question = DataSoalModel::all();
|
||||
$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];
|
||||
|
||||
// $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'));
|
||||
return view("user.pages.ujian.index", compact('data_session', 'data_question', 'total_question', 'is_last_question', 'question_number'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -312,30 +70,7 @@ public function create()
|
|||
*/
|
||||
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.'
|
||||
]);
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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!'
|
||||
]);
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,22 +7,6 @@
|
|||
|
||||
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.
|
||||
*/
|
||||
|
|
@ -52,8 +36,6 @@ public function store(Request $request)
|
|||
'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([
|
||||
|
|
|
|||
|
|
@ -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([
|
||||
|
|
|
|||
|
|
@ -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 [];
|
||||
}
|
||||
}
|
||||
|
|
@ -22,8 +22,7 @@ class BookingModel extends Model
|
|||
'kode_unik',
|
||||
'tgl_booking',
|
||||
'deskripsi_tambahan',
|
||||
'status_tes',
|
||||
'unix_expired_time'
|
||||
'status_tes'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
@ -39,11 +38,7 @@ protected static function boot()
|
|||
}
|
||||
|
||||
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
|
||||
$model->status_tes = '0';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -18,11 +18,7 @@ class TestSessionsModel extends Model
|
|||
'status_session',
|
||||
'token_session',
|
||||
'id_booking',
|
||||
'unix_start_time',
|
||||
'is_active',
|
||||
'unix_end_time',
|
||||
'screen_w',
|
||||
'screen_h'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8448
composer.lock_1
|
|
@ -65,7 +65,7 @@
|
|||
|
|
||||
*/
|
||||
|
||||
'timezone' => 'Asia/Jakarta',
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -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');
|
||||
}
|
||||
};
|
||||
|
Before Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 214 KiB |
|
Before Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
<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>No</th>
|
||||
<th>Nama</th>
|
||||
<th>Email</th>
|
||||
<th>Telepon</th>
|
||||
<th>Tanggal Booking</th>
|
||||
<th>Status Tes</th>
|
||||
<th>Status Sesi</th>
|
||||
<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>
|
||||
@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>
|
||||
</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
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
<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="0">Menunggu Konfirmasi</option>
|
||||
<option value="1">Siap/Sedang Tes</option>
|
||||
<option value="2">Selesai</option>
|
||||
</select>
|
||||
|
|
@ -183,8 +183,8 @@
|
|||
let table = null;
|
||||
let idEdit = null;
|
||||
let idHapus = null;
|
||||
let status_dict = ['secondary', 'info', 'success'];
|
||||
let status_dict_text = ['Nonaktif', 'Siap/Sedang Tes', 'Selesai'];
|
||||
let status_dict = ['warning', 'info', 'success'];
|
||||
let status_dict_text = ['Menunggu Konfirmasi', 'Siap/Sedang Tes', 'Selesai'];
|
||||
$(document).ready(function() {
|
||||
table = new DataTable("#table-data", {
|
||||
ajax: {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,169 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<!-- [Head] start -->
|
||||
<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>
|
||||
|
||||
<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">
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="mb-4" :status="session('status')" />
|
||||
|
||||
<!-- [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') }}">
|
||||
<form method="POST" action="{{ route('password.email') }}">
|
||||
@csrf
|
||||
|
||||
<meta id="_token" value="{{ csrf_token() }}">
|
||||
<!-- 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>
|
||||
|
||||
</head>
|
||||
<!-- [Head] end -->
|
||||
<!-- [Body] Start -->
|
||||
|
||||
<body>
|
||||
<!-- [ Pre-loader ] start -->
|
||||
<div class="loader-bg">
|
||||
<div class="loader-track">
|
||||
<div class="loader-fill"></div>
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<x-primary-button>
|
||||
{{ __('Email Password Reset Link') }}
|
||||
</x-primary-button>
|
||||
</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>
|
||||
</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>
|
||||
<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>
|
||||
|
|
|
|||
|
|
@ -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> -->
|
||||
|
|
|
|||
|
|
@ -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') }}">
|
||||
<!-- 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>
|
||||
|
||||
<meta id="_token" value="{{ csrf_token() }}">
|
||||
<!-- 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>
|
||||
|
||||
</head>
|
||||
<!-- [Head] end -->
|
||||
<!-- [Body] Start -->
|
||||
<!-- Confirm Password -->
|
||||
<div class="mt-4">
|
||||
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
|
||||
|
||||
<body>
|
||||
<!-- [ Pre-loader ] start -->
|
||||
<div class="loader-bg">
|
||||
<div class="loader-track">
|
||||
<div class="loader-fill"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- [ Pre-loader ] End -->
|
||||
<x-text-input id="password_confirmation" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password_confirmation" required autocomplete="new-password" />
|
||||
|
||||
<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>
|
||||
<x-input-error :messages="$errors->get('password_confirmation')" 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>
|
||||
</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 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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -28,9 +28,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,7 +60,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>
|
||||
|
|
@ -73,10 +69,6 @@ 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>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
<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 -->
|
||||
|
|
@ -21,16 +21,16 @@
|
|||
<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="{{ route('cek-status.index') }}">Cek Status</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>
|
||||
|
|
|
|||
|
|
@ -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 -->
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@
|
|||
<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">Tgl Booking: <span id="tgl_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>
|
||||
|
|
@ -85,8 +85,6 @@
|
|||
<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>
|
||||
|
|
@ -139,29 +137,28 @@ function searchUserStatus() {
|
|||
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'];
|
||||
let status_dict = ['Belum dikonfirmasi (cek email anda)', 'Sudah dikonfirmasi, 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>");
|
||||
$('#tgl_booking').html(response.tgl_booking);
|
||||
$('#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!');
|
||||
$('#alert_status').addClass('alert alert-primary');
|
||||
$('#alert_status').html('Kamu belum dikonfirmasi dengan psikolog, cek waktu konsultasi pada email anda untuk melakukan aktivasi!');
|
||||
} else if(response.status_data == 1) {
|
||||
$('#alert_status').removeClass();
|
||||
$('#alert_status').addClass('alert alert-info');
|
||||
$('#alert_status').html('Kamu bisa memulai tes sekarang!');
|
||||
$('#alert_status').html('Kamu sudah dikonfirmasi oleh psikolog!');
|
||||
|
||||
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!');
|
||||
$('#result_test_title').html('Kamu sudah dikonfirmasi oleh psikolog! 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);
|
||||
|
|
@ -182,15 +179,11 @@ function searchUserStatus() {
|
|||
$('#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_title').html('Kamu sudah dikonfirmasi oleh psikolog! 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();
|
||||
|
|
@ -198,22 +191,9 @@ function searchUserStatus() {
|
|||
$('#result_test_form').show();
|
||||
}
|
||||
} else if(response.status_data == 2) {
|
||||
let test_session = getTestSession(response.id_booking);
|
||||
|
||||
$('#alert_status').removeClass();
|
||||
$('#alert_status').addClass('alert alert-success');
|
||||
$('#alert_status').html('Kamu sudah melakukan tes, dan bisa cek hasil dengan tombol dibawah');
|
||||
|
||||
$('#result_test_status').html('Selesai');
|
||||
$('#result_test_status').removeClass();
|
||||
$('#result_test_status').addClass('fw-bold text-white bg-success p-2 rounded-pill');
|
||||
let test_url = '{{ route('hasil-tes.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
|
||||
$('#result_test_form').hide();
|
||||
$('#result_test_link').show();
|
||||
$('#result_test_link').html('Tes Sudah Selesai, Klik untuk melihat hasil');
|
||||
$('#result_test_link').attr('href', test_url.replace('__ID_TEST_SESSIONS__', test_session.id_test_sessions));
|
||||
|
||||
$('#result_test').show();
|
||||
}
|
||||
} else {
|
||||
Swal.fire({
|
||||
|
|
@ -274,8 +254,6 @@ function startSessionTest() {
|
|||
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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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,7 +324,7 @@
|
|||
<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">
|
||||
|
|
@ -317,8 +340,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 +349,8 @@
|
|||
<i class="bi bi-clock"></i>
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<h4>Ambil Tanggal & Waktu</h4>
|
||||
<p>Pilih tanggal dan waktu yang paling cocok untuk Anda</p>
|
||||
<h4>Pick Date & Time</h4>
|
||||
<p>Select your preferred appointment slot</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="step">
|
||||
|
|
@ -335,8 +358,8 @@
|
|||
<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>
|
||||
|
|
@ -354,7 +377,7 @@
|
|||
<input type="tel" name="phone" id="no_telp" class="form-control" placeholder="Nomor Telepon" 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...">
|
||||
<input type="date" name="date" id="tgl_book" class="form-control" required="" aria-describedby="dateHelp">
|
||||
<div id="dateHelp" class="form-text">Untuk detail jam, akan dikirim melalui email mu yaa.</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
|
|
@ -389,13 +412,6 @@
|
|||
<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();
|
||||
|
|
@ -468,14 +484,5 @@ function sendAppointment() {
|
|||
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
|
||||
|
|
@ -30,10 +30,37 @@
|
|||
<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>Hubungkan Tobii:</strong> Hubungkan Tobii ke dalam web dengan menggunakan link API dibawah ini.</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>
|
||||
<h5 class="">Link API Tobii:</h5>
|
||||
<div class="row px-3">
|
||||
<div class="col-md-11">
|
||||
<input type="text" disabled id="link_api_tobii" class="input form-control mb-3" value="">
|
||||
</div>
|
||||
<div class="col-md-1 p-0">
|
||||
<button class="btn btn-secondary" onclick="copyLinkApiTobii()">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="">Link ID Tobii:</h5>
|
||||
<div class="row px-3">
|
||||
<div class="col-md-11">
|
||||
<input type="text" disabled id="link_id_tobii" class="input form-control mb-3" value="">
|
||||
</div>
|
||||
<div class="col-md-1 p-0">
|
||||
<button class="btn btn-secondary" onclick="copyLinkIdTobii()">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<h5 class="">Link Token Tobii:</h5>
|
||||
<div class="row px-3">
|
||||
<div class="col-md-11">
|
||||
<input type="text" disabled id="link_token_tobii" class="input form-control mb-3" value="">
|
||||
</div>
|
||||
<div class="col-md-1 p-0">
|
||||
<button class="btn btn-secondary" onclick="copyLinkTokenTobii()">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
|
|
@ -57,42 +84,55 @@
|
|||
<!-- 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>
|
||||
<!-- row 1 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 2%; left: 96%"></div>
|
||||
|
||||
<!-- row 2 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 19.2%; left: 96%"></div>
|
||||
|
||||
<!-- row 3 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 38.4%; left: 96%"></div>
|
||||
|
||||
<!-- row 4 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 57.6%; left: 96%"></div>
|
||||
|
||||
<!-- row 5 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 76.8%; left: 96%"></div>
|
||||
|
||||
<!-- row 6 -->
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 19.2%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 38.4%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 57.6%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 76.8%"></div>
|
||||
<div class="rounded-circle bg-primary position-absolute" style="width: 0.5%; aspect-ratio: 1/1; top: 96%; left: 96%"></div>
|
||||
|
||||
<div id="the_eye" class="rounded-circle bg-danger position-absolute" style="width: 0.5%; aspect-ratio: 1/1;"></div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
|
|
@ -100,90 +140,20 @@
|
|||
<script>
|
||||
let getDataInterval = false;
|
||||
let checkTobiiInterval = null;
|
||||
let tobiiConnectedStatus = false;
|
||||
let ws = null;
|
||||
let reconnectDelay = 1000;
|
||||
let maxReconnectDelay = 10000;
|
||||
let tobiiConnectedStatus = true;
|
||||
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
|
||||
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();
|
||||
checkTobiiInterval = setInterval(() => {
|
||||
checkTobiiConnection();
|
||||
// checkTobiiInterval = setInterval(() => {
|
||||
// checkTobiiConnection();
|
||||
// }, 2000);
|
||||
}, 2000);
|
||||
} else {
|
||||
if(checkTobiiInterval) {
|
||||
clearInterval(checkTobiiInterval);
|
||||
|
|
@ -312,10 +282,10 @@ function copyLinkTokenTobii() {
|
|||
}
|
||||
|
||||
function checkTobiiConnection() {
|
||||
// ws.send(JSON.stringify({
|
||||
// type: "check_tobii_connection",
|
||||
// session_id: SESSION_ID,
|
||||
// }));
|
||||
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');
|
||||
|
|
@ -339,39 +309,6 @@ function checkTobiiConnection() {
|
|||
}
|
||||
}
|
||||
|
||||
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",
|
||||
|
|
@ -395,8 +332,56 @@ function stopTobii() {
|
|||
$('#calibration_point').hide();
|
||||
$('#show_calibration').hide();
|
||||
generateLinkApiTobii();
|
||||
startWebsocket();
|
||||
console.log("hehehehehehehehehhehehe");
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log("Connected to WebSocket");
|
||||
ws.send(JSON.stringify({
|
||||
type: "register",
|
||||
session_id: SESSION_ID,
|
||||
token_session: TOKEN_SESSION,
|
||||
role: "web"
|
||||
}));
|
||||
|
||||
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 === 'temp_data') {
|
||||
// console.log('Received temp_data:', data);
|
||||
// if((Date.now() - data.data[0].timestamp) < 5000) {
|
||||
// tobiiConnectedStatus = true;
|
||||
// } else {
|
||||
// tobiiConnectedStatus = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if(data.type === 'tobii_data') {
|
||||
try {
|
||||
moveTheEye(data.gaze_x, data.gaze_y);
|
||||
} catch(error) {
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
|
||||
// if(data.type === 'status_tobii') {
|
||||
// if(data.status) {
|
||||
// tobiiConnectedStatus = true;
|
||||
// } else if(!data.status) {
|
||||
// tobiiConnectedStatus = false;
|
||||
// }
|
||||
// }
|
||||
|
||||
if(data.type === 'reset_start_tobii') {
|
||||
startTobii();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -7,19 +7,9 @@
|
|||
<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">
|
||||
<div class="collapse navbar-collapse" 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 class="d-flex fw-bold">Time Left: <span id="time_left"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
@ -29,25 +19,38 @@
|
|||
<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>
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_a">
|
||||
<label class="form-check-label" for="jawaban_a">{{ $data_question->jawaban_a }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_b">
|
||||
<label class="form-check-label" for="jawaban_b">{{ $data_question->jawaban_b }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_c">
|
||||
<label class="form-check-label" for="jawaban_c">{{ $data_question->jawaban_c }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_d">
|
||||
<label class="form-check-label" for="jawaban_d">{{ $data_question->jawaban_d }}</label>
|
||||
</div>
|
||||
<div class="form-check m-2">
|
||||
<input class="form-check-input" type="radio" name="jawaban_final" id="jawaban_e">
|
||||
<label class="form-check-label" for="jawaban_e">{{ $data_question->jawaban_e }}</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
|
||||
@for ($i = 0; $i < $total_question; $i++)
|
||||
<div onclick="changeQuestion({{ $i + 1 }})" class="col-md-1 btn d-flex justify-content-center align-items-center bg-light-subtle border rounded p-0 m-1" style="aspect-ratio: 1/1.5;">{{ $i + 1 }}</div>
|
||||
@endfor
|
||||
|
||||
<div class="col-md-12 p-0 mt-3">
|
||||
@if ($question_number > 1)
|
||||
|
|
@ -61,28 +64,6 @@
|
|||
@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>
|
||||
|
|
@ -94,41 +75,10 @@
|
|||
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;
|
||||
|
|
@ -137,96 +87,7 @@ function changeQuestion(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",
|
||||
|
|
@ -244,10 +105,6 @@ function finishExam() {
|
|||
status_sessions: false,
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
window.location.href = "{{ route('hasil-tes.index') }}?id_test_sessions=" + SESSION_ID;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function startTobii() {
|
||||
|
|
@ -266,63 +123,6 @@ function stopTobii() {
|
|||
}));
|
||||
}
|
||||
|
||||
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");
|
||||
|
|
@ -333,43 +133,13 @@ function checkFullscreen() {
|
|||
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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
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;
|
||||
|
|
@ -36,21 +35,11 @@
|
|||
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']);
|
||||
|
|
@ -58,17 +47,10 @@
|
|||
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'
|
||||
]);
|
||||
Route::get('api/eye/test', function(Request $req) {
|
||||
return $req->token;
|
||||
});
|
||||
|
||||
require __DIR__.'/auth.php';
|
||||
|
|
|
|||