Compare commits
No commits in common. "fdda679141c813be11708225a745fb184a4d52d4" and "50b0ec2c1b2ee78ceecfcf9aca0e37dc09a1ee36" have entirely different histories.
fdda679141
...
50b0ec2c1b
|
|
@ -1,107 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\DataSoalModel;
|
||||
use App\Models\TestSessionsModel;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class HalamanUjianController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
|
||||
$id_session = null;
|
||||
if(session('id_test_sessions') != null) {
|
||||
$id_session = session('id_test_sessions');
|
||||
} else if($request->id_test_sessions != null) {
|
||||
$id_session = $request->id_test_sessions;
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
|
||||
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
|
||||
if($data_session != null) {
|
||||
if($data_session->status_session != '1') {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes belum dimulai atau telah usai. Silahkan cek status dengan kode untuk informasi lebih lanjut.');
|
||||
}
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
|
||||
$question_number = null;
|
||||
$data_question = null;
|
||||
if(session('question') != null) {
|
||||
$question_number = session('question');
|
||||
} else if($request->question != null) {
|
||||
$question_number = $request->question;
|
||||
} else {
|
||||
$question_number = 1;
|
||||
}
|
||||
|
||||
$data_question = DataSoalModel::all();
|
||||
$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];
|
||||
|
||||
return view("user.pages.ujian.index", compact('data_session', 'data_question', 'total_question', 'is_last_question', 'question_number'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -34,15 +34,10 @@ public function store(Request $request)
|
|||
|
||||
$testSession = TestSessionsModel::create([
|
||||
'id_booking' => $request->id_booking,
|
||||
'status_session' => '0',
|
||||
'is_active' => '0',
|
||||
'status_session' => 0, // Set status awal sebagai "Belum Dimulai"
|
||||
]);
|
||||
|
||||
return redirect()->route('tutorial-tes.index')->with([
|
||||
'id_booking' => $testSession->id_booking,
|
||||
'id_test_sessions' => $testSession->id_test_sessions,
|
||||
'token_session' => $testSession->token_session,
|
||||
]);
|
||||
return redirect()->route('cek-status.show', $request->id_booking)->with('success', 'Sesi tes berhasil dibuat. Token: ' . $testSession->token_session);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -58,7 +53,6 @@ public function show(string $id)
|
|||
'status_session' => $data->status_session,
|
||||
'token_session' => $data->token_session,
|
||||
'id_booking' => $data->id_booking,
|
||||
'id_test_sessions' => $data->id_test_sessions,
|
||||
]);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TobiiDataController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\TestSessionsModel;
|
||||
use App\Models\TobiiDataModel;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class TobiiReceiverController extends Controller
|
||||
{
|
||||
/**
|
||||
* Fetch eye tracking data from database.
|
||||
*/
|
||||
public function fetchDataTobii($id_test_sessions)
|
||||
{
|
||||
$data_tobii = TobiiDataModel::where('id_test_sessions', $id_test_sessions)->orderByDesc('timestamp')->first();
|
||||
if ($data_tobii) {
|
||||
Log::info('DATA DIAMBIL WEB', [
|
||||
'timestamp_data' => $data_tobii->timestamp,
|
||||
'created_at' => $data_tobii->created_at,
|
||||
'time_now' => now()->timestamp * 1000
|
||||
]);
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
'msg' => 'Data tobii ditemukan (' . $id_test_sessions . ')',
|
||||
'gaze_x' => $data_tobii->gaze_x,
|
||||
'gaze_y' => $data_tobii->gaze_y,
|
||||
]);
|
||||
} else {
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'msg' => 'Data tobii tidak ditemukan (' . $id_test_sessions . ')',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
try {
|
||||
$data_sessions = TestSessionsModel::where('id_test_sessions', $request->id_test_sessions)->first();
|
||||
if($data_sessions != null) {
|
||||
if($request->token_session == $data_sessions->token_session) {
|
||||
if($data_sessions->status_session == '1') {
|
||||
$is_valid = '0';
|
||||
if($data_sessions->is_active == '1') {
|
||||
$is_valid = '1';
|
||||
}
|
||||
// simpan data tobii ke db
|
||||
$data_tobii = TobiiDataModel::create([
|
||||
'gaze_x' => $request->gaze_x,
|
||||
'gaze_y' => $request->gaze_y,
|
||||
'timestamp' => Carbon::createFromTimestampMs($request->timestamp),
|
||||
'is_valid' => $is_valid,
|
||||
'id_test_sessions' => $request->id_test_sessions,
|
||||
]);
|
||||
Log::info('DATA MASUK API', [
|
||||
'timestamp_client' => Carbon::createFromTimestampMs($request->timestamp),
|
||||
'time_server' => now()->timestamp * 1000
|
||||
]);
|
||||
return response()->json(['message' => 'Data tobii berhasil disimpan.'], 200);
|
||||
} else {
|
||||
return response()->json(['message' => 'Sesi tes belum aktif.'], 403);
|
||||
}
|
||||
} else {
|
||||
return response()->json(['message' => 'Token sesi tidak valid.'], 401);
|
||||
}
|
||||
} else {
|
||||
return response()->json(['message' => 'Data sesi tes tidak ditemukan.'], 404);
|
||||
}
|
||||
} catch(\Exception $e) {
|
||||
return response()->json(['message' => 'Terjadi kesalahan saat menyimpan data tobii.', 'error' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
$data_tobii = TobiiDataModel::where('id_test_sessions', $id)->orderByDesc('timestamp')->first();
|
||||
if ($data_tobii && $data_tobii->timestamp->lt(now()->subSeconds(20))) {
|
||||
return response()->json([
|
||||
'status' => false,
|
||||
'msg' => 'Data tobii kadaluarsa (' . $id . ')',
|
||||
'connected' => false,
|
||||
]);
|
||||
}
|
||||
return response()->json([
|
||||
'status' => true,
|
||||
'connected' => true,
|
||||
'msg' => 'Data tobii ditemukan (' . $id . ')',
|
||||
'data_tobii' => $data_tobii,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\TestSessionsModel;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class TutorialTesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/**
|
||||
* TODO
|
||||
* 1. simpan sesi tobii di db
|
||||
* 2. simpan data mata lewat db
|
||||
* 3. di tabel session harus ada is_active atau lainnya biar nanti kalo misal aktif ujian, data mata di terima dan langsung dimasukkan wifi
|
||||
* 4. pada backend tobii, masukin token dan id yang ada di tabel session, biar nanti di compare cocok atau tidak
|
||||
* 5. itu aja sih
|
||||
*/
|
||||
$id_session = null;
|
||||
if(session('id_test_sessions') != null) {
|
||||
$id_session = session('id_test_sessions');
|
||||
} else if($request->id_test_sessions != null) {
|
||||
$id_session = $request->id_test_sessions;
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
|
||||
$data_session = TestSessionsModel::where('id_test_sessions', $id_session)->first();
|
||||
if($data_session != null) {
|
||||
if($data_session->status_session == '0') {
|
||||
$data_session->update(['status_session' => '1']);
|
||||
}
|
||||
} else {
|
||||
return redirect()->route('cek-status.index')->with('error', 'Data sesi tes tidak ditemukan. Silakan mulai tes terlebih dahulu.');
|
||||
}
|
||||
return view('user.pages.tutorial_tes.index', compact('data_session'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*/
|
||||
public function show(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*/
|
||||
public function edit(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*/
|
||||
public function update(Request $request, string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*/
|
||||
public function destroy(string $id)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -17,8 +17,7 @@ class TestSessionsModel extends Model
|
|||
protected $fillable = [
|
||||
'status_session',
|
||||
'token_session',
|
||||
'id_booking',
|
||||
'is_active',
|
||||
'id_booking'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
|
|
@ -37,10 +36,6 @@ protected static function boot()
|
|||
if (empty($model->token_session)) {
|
||||
$model->token_session = \Illuminate\Support\Str::random(50);
|
||||
}
|
||||
|
||||
if (empty($model->is_active)) {
|
||||
$model->is_active = '0';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TobiiDataModel extends Model
|
||||
{
|
||||
protected $table = 'tobii_data';
|
||||
|
||||
protected $primaryKey = 'id_tobii_data';
|
||||
|
||||
protected $keyType = 'string';
|
||||
|
||||
public $incrementing = false;
|
||||
|
||||
protected $fillable = [
|
||||
'id_tobii_data',
|
||||
'gaze_x',
|
||||
'gaze_y',
|
||||
'timestamp',
|
||||
'id_test_sessions',
|
||||
'is_valid',
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'id_tobii_data' => 'string',
|
||||
'gaze_x' => 'float',
|
||||
'gaze_y' => 'float',
|
||||
'timestamp' => 'datetime',
|
||||
'id_test_sessions' => 'string',
|
||||
];
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->id_tobii_data)) {
|
||||
$model->id_tobii_data = (string) \Illuminate\Support\Str::uuid();
|
||||
}
|
||||
if (empty($model->is_valid)) {
|
||||
$model->is_valid = '0';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -16,8 +16,7 @@
|
|||
'role.auth' => RoleAuth::class,
|
||||
]);
|
||||
$middleware->validateCsrfTokens(except: [
|
||||
'api/eye/test',
|
||||
'tobii-receiver'
|
||||
'api/eye/test'
|
||||
]);
|
||||
})
|
||||
->withExceptions(function (Exceptions $exceptions): void {
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('tobii_data', function (Blueprint $table) {
|
||||
$table->uuid('id_tobii_data')->primary();
|
||||
$table->string('gaze_x')->nullable()->default(0);
|
||||
$table->string('gaze_y')->nullable()->default(0);
|
||||
$table->string('timestamp');
|
||||
$table->uuid('id_test_sessions');
|
||||
$table->timestamps();
|
||||
|
||||
// Foreign key constraint
|
||||
$table->foreign('id_test_sessions')->references('id_test_sessions')->on('test_sessions')->onDelete('cascade');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('tobii_data');
|
||||
}
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('test_sessions', function (Blueprint $table) {
|
||||
$table->string('is_active')->default('0')->after('token_session');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('test_sessions', function (Blueprint $table) {
|
||||
$table->dropColumn('is_active');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('tobii_data', function (Blueprint $table) {
|
||||
$table->enum('is_valid', ['0', '1'])->default('0')->after('timestamp');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('tobii_data', function (Blueprint $table) {
|
||||
$table->dropColumn('is_valid');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('soal', function (Blueprint $table) {
|
||||
$table->text('pertanyaan')->change();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('soal', function (Blueprint $table) {
|
||||
$table->string('pertanyaan', 255)->change();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
||||
<title>@yield('title') - Smart Anxiety</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="keywords" content="">
|
||||
<meta id="_token" value="{{ csrf_token() }}">
|
||||
|
||||
<!-- Favicons -->
|
||||
<link href="{{ asset('assets/users/assets/img/favicon.png') }}" rel="icon">
|
||||
<link href="{{ asset('assets/users/assets/img/apple-touch-icon.png') }}" rel="apple-touch-icon">
|
||||
|
||||
<!-- Fonts -->
|
||||
<link href="https://fonts.googleapis.com" rel="preconnect">
|
||||
<link href="https://fonts.gstatic.com" rel="preconnect" crossorigin>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Montserrat:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Lato:ital,wght@0,100;0,300;0,400;0,700;0,900;1,100;1,300;1,400;1,700;1,900&display=swap"
|
||||
rel="stylesheet">
|
||||
|
||||
<!-- Vendor CSS Files -->
|
||||
<link href="{{ asset('assets/users/assets/vendor/bootstrap/css/bootstrap.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/users/assets/vendor/bootstrap-icons/bootstrap-icons.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/users/assets/vendor/aos/aos.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/users/assets/vendor/glightbox/css/glightbox.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/users/assets/vendor/fontawesome-free/css/all.min.css') }}" rel="stylesheet">
|
||||
<link href="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- Main CSS File -->
|
||||
<link href="{{ asset('assets/users/assets/css/main.css') }}" rel="stylesheet">
|
||||
|
||||
<!-- =======================================================
|
||||
* Template Name: Clinic
|
||||
* Template URL: https://bootstrapmade.com/clinic-bootstrap-template/
|
||||
* Updated: Jul 23 2025 with Bootstrap v5.3.7
|
||||
* Author: BootstrapMade.com
|
||||
* License: https://bootstrapmade.com/license/
|
||||
======================================================== -->
|
||||
</head>
|
||||
|
||||
<body class="index-page" style="@yield('body_status_overflow')">
|
||||
|
||||
{{-- @include('user.layouts.navbar') --}}
|
||||
|
||||
<main class="main" style="@yield('main_style')">
|
||||
|
||||
@yield('content')
|
||||
|
||||
</main>
|
||||
|
||||
{{-- @include('user.layouts.footer') --}}
|
||||
|
||||
<!-- Scroll Top -->
|
||||
<a href="#!" id="scroll-top" class="scroll-top d-flex align-items-center justify-content-center"><i
|
||||
class="bi bi-arrow-up-short"></i></a>
|
||||
|
||||
<!-- Preloader -->
|
||||
<div id="preloader"></div>
|
||||
|
||||
<!-- Vendor JS Files -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/bootstrap/js/bootstrap.bundle.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/php-email-form/validate.js') }}"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/aos/aos.js') }}"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/glightbox/js/glightbox.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/purecounter/purecounter_vanilla.js') }}"></script>
|
||||
<script src="{{ asset('assets/users/assets/vendor/swiper/swiper-bundle.min.js') }}"></script>
|
||||
|
||||
<!-- Main JS File -->
|
||||
<script src="{{ asset('assets/users/assets/js/main.js') }}"></script>
|
||||
|
||||
@yield('script')
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -100,18 +100,6 @@
|
|||
</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')
|
||||
|
|
@ -161,7 +149,6 @@ function searchUserStatus() {
|
|||
$('#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);
|
||||
$('#result_test_status').html('Belum Dimulai');
|
||||
$('#result_test_status').removeClass();
|
||||
$('#result_test_status').addClass('fw-bold text-white bg-secondary p-2 rounded-pill');
|
||||
|
|
@ -170,18 +157,13 @@ function searchUserStatus() {
|
|||
$('#result_test_status').html('Sedang Berlangsung');
|
||||
$('#result_test_status').removeClass();
|
||||
$('#result_test_status').addClass('fw-bold text-white bg-warning p-2 rounded-pill');
|
||||
let test_url = '{{ route('tutorial-tes.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
|
||||
$('#result_test_form').hide();
|
||||
$('#result_test_link').show();
|
||||
$('#result_test_link').html('Tes Sedang Berlangsung, Klik untuk Lanjutkan Tes');
|
||||
$('#result_test_link').attr('href', test_url.replace('__ID_TEST_SESSIONS__', test_session.id_test_sessions));
|
||||
} else if(test_session.status_session == 2) {
|
||||
$('#result_test_status').html('Selesai');
|
||||
$('#result_test_status').removeClass();
|
||||
$('#result_test_status').addClass('fw-bold text-white bg-success p-2 rounded-pill');
|
||||
}
|
||||
} else if(!test_session.status) {
|
||||
$('#id_booking_input').val(response.id_booking);
|
||||
console.log(test_session.msg);
|
||||
$('#result_test').show();
|
||||
$('#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!');
|
||||
|
||||
|
|
@ -226,7 +208,6 @@ function getTestSession(id_booking) {
|
|||
'status': true,
|
||||
'msg': 'Data ditemukan (' + id_booking + ')',
|
||||
'id_booking': response.id_booking,
|
||||
'id_test_sessions': response.id_test_sessions,
|
||||
'status_session': response.status_session,
|
||||
'token_session': response.token_session
|
||||
};
|
||||
|
|
@ -260,13 +241,4 @@ function startSessionTest() {
|
|||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
@if (session('error'))
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var toast = new bootstrap.Toast(document.getElementById('liveToast'));
|
||||
toast.show();
|
||||
});
|
||||
</script>
|
||||
@endif
|
||||
@endsection
|
||||
|
|
@ -1,388 +0,0 @@
|
|||
@section('title', 'Tutorial Test Kecemasan')
|
||||
@section('body_status_overflow', 'overflow: hidden;')
|
||||
@section('main_style', 'width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center;')
|
||||
@extends('user.layouts.test_layout.index')
|
||||
@section('content')
|
||||
<div class="container" id="tutorial_panel">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8" id="tutorial_1">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title fw-bold mb-4">Tutorial Tes Kecemasan</h3>
|
||||
<p class="card-text mb-3">Berikut adalah tutorial untuk menjalankan tes kecemasan dari sistem kami. Pastikan kamu sudah membaca dan memahami setiap langkah yang ada di bawah ini sebelum memulai tes.</p>
|
||||
<ol>
|
||||
<li><strong>Persiapan:</strong> Pastikan kondisi kamu berada di tempat yang tenang dan nyaman.</li>
|
||||
<li><strong>Durasi Tes:</strong> Tes ini akan memakan waktu sekitar 2-5 menit, tergantung pada kecepatanmu dalam menjawab pertanyaan.</li>
|
||||
<li><strong>Jenis Pertanyaan:</strong> Tes ini terdiri dari beberapa pertanyaan yang dirancang untuk mengukur tingkat kecemasanmu. Jawablah setiap pertanyaan dengan jujur dan sesuai dengan perasaanmu saat ini.</li>
|
||||
<li><strong>Hasil Tes:</strong> Setelah menyelesaikan tes, hasilnya akan dianalisis oleh sistem kami dan akan diberikan kepada psikolog yang menangani kasusmu. Psikolog akan memberikan feedback dan rekomendasi berdasarkan hasil tes tersebut. Kamu juga akan menerima laporan hasil tes secara detail dan juga bisa dilihat berdasarkan kode tes yang kamu dapatkan saat melakukan booking.</li>
|
||||
<li><strong>Konsultasi Lanjutan:</strong> Jika hasil tes menunjukkan bahwa kamu mengalami tingkat kecemasan yang tinggi, psikolog mungkin akan menyarankan sesi konsultasi lanjutan untuk membahas hasil tes dan langkah selanjutnya yang bisa diambil.</li>
|
||||
</ol>
|
||||
<p class="card-text mt-3">Jika kamu sudah siap, silakan klik tombol "Next" di bawah ini untuk setup lingkungan terlebih dahulu.</p>
|
||||
<button class="btn btn-primary" onclick="showTutorial(2, 'tutorial_1')">Next</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8" id="tutorial_2">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title fw-bold mb-4">Setup Lingkungan</h3>
|
||||
<p class="card-text mb-3">Sebelum tes dimulai, setup alat Tobii dibawah ini:</p>
|
||||
<ol>
|
||||
<li><strong>Persiapan:</strong> Pastikan Tobii sudah terhubung dan berfungsi dengan baik.</li>
|
||||
<li><strong>Penempatan:</strong> Tempatkan Tobii di posisi yang sesuai untuk mendeteksi gerakan mata dengan akurat.</li>
|
||||
<li><strong>Hubungkan Tobii:</strong> Hubungkan Tobii ke dalam web dengan menggunakan 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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8" id="tutorial_3">
|
||||
<div class="card shadow-sm border-0">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title fw-bold mb-4">Tes Keakuratan Mata</h3>
|
||||
<p class="card-text mb-3">Sebelum tes dimulai, cek keakuratan device Tobii anda (disarankan full-screen), jika tidak akurat, lakukan kalibrasi kepada administrator.</p>
|
||||
<button class="btn btn-primary" id="back_btn" onclick="showTutorial(2, 'tutorial_3')">Back</button>
|
||||
<button class="btn btn-secondary" id="fullscreen_btn" onclick="openFullscreen(this)" data-status="fullscreen">Fullscreen</button>
|
||||
<button class="btn btn-secondary" id="hide_btn" onclick="hidePanelTutorial(this)" data-status="hide">Hide</button>
|
||||
<a class="btn btn-primary" id="start_ujian" href="#">Mulai Ujian</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- btn show -->
|
||||
<button type="button" class="btn btn-secondary position-absolute" onclick="showCalibrationPoints()" id="show_calibration" style="z-index: 999">Show</button>
|
||||
<div class="position-absolute bg-white" style="width: 100vw; height: 100vh; z-index: -1;" id="calibration_point">
|
||||
<!-- 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
|
||||
|
||||
@section('script')
|
||||
<script>
|
||||
let getDataInterval = false;
|
||||
let checkTobiiInterval = null;
|
||||
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 showTutorial(step, tutorialId) {
|
||||
$(`#${tutorialId}`).hide();
|
||||
$(`#tutorial_${step}`).show();
|
||||
|
||||
if(step === 2 || step === 3) {
|
||||
startTobii();
|
||||
checkTobiiInterval = setInterval(() => {
|
||||
checkTobiiConnection();
|
||||
}, 2000);
|
||||
} else {
|
||||
if(checkTobiiInterval) {
|
||||
clearInterval(checkTobiiInterval);
|
||||
}
|
||||
stopTobii();
|
||||
}
|
||||
|
||||
if(step === 3) {
|
||||
$('#calibration_point').show();
|
||||
let test_url = '{{ route('ujian.index', ['id_test_sessions' => '__ID_TEST_SESSIONS__']) }}';
|
||||
$('#start_ujian').attr('href', test_url.replace('__ID_TEST_SESSIONS__', SESSION_ID));
|
||||
} else {
|
||||
$('#calibration_point').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function hidePanelTutorial(btn) {
|
||||
const status = $(btn).attr('data-status');
|
||||
if (status === 'hide') {
|
||||
$('#tutorial_panel').hide();
|
||||
$('#show_calibration').show();
|
||||
}
|
||||
}
|
||||
|
||||
function showCalibrationPoints() {
|
||||
$('#show_calibration').toggle();
|
||||
$('#tutorial_panel').toggle();
|
||||
}
|
||||
|
||||
function moveTheEye(x, y) {
|
||||
const eye = $('#the_eye');
|
||||
eye.css({ left: x + 'px', top: y + 'px' });
|
||||
}
|
||||
|
||||
function openFullscreen() {
|
||||
const status = $('#fullscreen_btn').attr('data-status');
|
||||
const elem = document.documentElement;
|
||||
if (status === 'fullscreen') {
|
||||
if (elem.requestFullscreen) {
|
||||
elem.requestFullscreen();
|
||||
} else if (elem.webkitRequestFullscreen) {
|
||||
elem.webkitRequestFullscreen(); // Safari
|
||||
} else if (elem.msRequestFullscreen) {
|
||||
elem.msRequestFullscreen(); // IE
|
||||
}
|
||||
$('#fullscreen_btn').attr('data-status', 'exit-fullscreen');
|
||||
} else if (status === 'exit-fullscreen') {
|
||||
if (document.exitFullscreen) {
|
||||
document.exitFullscreen();
|
||||
} else if (document.webkitExitFullscreen) {
|
||||
document.webkitExitFullscreen(); // Safari
|
||||
} else if (document.msExitFullscreen) {
|
||||
document.msExitFullscreen(); // IE
|
||||
}
|
||||
$('#fullscreen_btn').attr('data-status', 'fullscreen');
|
||||
}
|
||||
}
|
||||
|
||||
function generateLinkApiTobii() {
|
||||
const linkApi = '{{ env("WEBSOCKET_URL") }}'.replace('ws://', '');
|
||||
const linkId = SESSION_ID;
|
||||
const linkToken = TOKEN_SESSION;
|
||||
$('#link_api_tobii').val(linkApi);
|
||||
$('#link_id_tobii').val(linkId);
|
||||
$('#link_token_tobii').val(linkToken);
|
||||
}
|
||||
|
||||
function copyLinkApiTobii() {
|
||||
const linkApi = $('#link_api_tobii').val();
|
||||
navigator.clipboard.writeText(linkApi)
|
||||
.then(() => {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Link API berhasil disalin!',
|
||||
showConfirmButton: true,
|
||||
timer: 1500
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal menyalin Link API',
|
||||
text: err,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyLinkIdTobii() {
|
||||
const linkId = $('#link_id_tobii').val();
|
||||
navigator.clipboard.writeText(linkId)
|
||||
.then(() => {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Link ID berhasil disalin!',
|
||||
showConfirmButton: true,
|
||||
timer: 1500
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal menyalin Link ID',
|
||||
text: err,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function copyLinkTokenTobii() {
|
||||
const linkToken = $('#link_token_tobii').val();
|
||||
navigator.clipboard.writeText(linkToken)
|
||||
.then(() => {
|
||||
Swal.fire({
|
||||
icon: 'success',
|
||||
title: 'Link Token berhasil disalin!',
|
||||
showConfirmButton: true,
|
||||
timer: 1500
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
Swal.fire({
|
||||
icon: 'error',
|
||||
title: 'Gagal menyalin Link Token',
|
||||
text: err,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkTobiiConnection() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "check_tobii_connection",
|
||||
session_id: SESSION_ID,
|
||||
}));
|
||||
|
||||
if(tobiiConnectedStatus) {
|
||||
$('#status_tobii').text('Status Tobii: Terhubung').removeClass('text-danger').addClass('text-success');
|
||||
$('#next_btn_connect_tobii').show();
|
||||
} else {
|
||||
$('#status_tobii').text('Status Tobii: Tidak Terhubung').removeClass('text-success').addClass('text-danger');
|
||||
$('#next_btn_connect_tobii').hide();
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDataTobii() {
|
||||
try {
|
||||
const response = await fetch('{{ route("tobii-receiver.fetchData", ['id_test_sessions' => $data_session->id_test_sessions]) }}');
|
||||
if (!response.ok) {
|
||||
throw new Error('Network response was not ok');
|
||||
}
|
||||
const data = await response.json();
|
||||
moveTheEye(data.gaze_x, data.gaze_y);
|
||||
} catch (error) {
|
||||
console.error('Error fetching Tobii data:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function startTobii() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "start",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
function stopTobii() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "stop",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('#tutorial_2').hide();
|
||||
$('#tutorial_3').hide();
|
||||
$('#next_btn_connect_tobii').hide();
|
||||
$('#calibration_point').hide();
|
||||
$('#show_calibration').hide();
|
||||
generateLinkApiTobii();
|
||||
|
||||
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>
|
||||
@endsection
|
||||
|
|
@ -1,146 +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" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0"></ul>
|
||||
<div class="d-flex fw-bold">Time Left: <span id="time_left"></span></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" style="text-align: justify">{{ $data_question->pertanyaan }}</div>
|
||||
<div class="col-md-12">
|
||||
<div class="fs-4 fw-bold p-2">Jawaban:</div>
|
||||
<div class="form-check m-2">
|
||||
<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>
|
||||
</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>
|
||||
@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)
|
||||
<div class="btn btn-secondary" onclick="changeQuestion({{ $question_number - 1 }})">Previous</div>
|
||||
@endif
|
||||
|
||||
@if ($is_last_question)
|
||||
<div class="btn btn-success" onclick="finishExam()">Finish</div>
|
||||
@else
|
||||
<div class="btn btn-primary" onclick="changeQuestion({{ $question_number + 1 }})">Next</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('script')
|
||||
<script>
|
||||
const ws = new WebSocket('{{ env("WEBSOCKET_URL") }}');
|
||||
let SESSION_ID = '{{ $data_session->id_test_sessions }}';
|
||||
let TOKEN_SESSION = '{{ $data_session->token_session }}';
|
||||
|
||||
function changeQuestion(num) {
|
||||
let url_temp = window.location.href;
|
||||
let current_num = new URLSearchParams(window.location.search).get('question');
|
||||
stopTobii();
|
||||
if(!url_temp.includes('question')) {
|
||||
window.location.href = url_temp + '&question=' + num;
|
||||
} else if(url_temp.includes('question')) {
|
||||
window.location.href = window.location.href.replace('&question=' + current_num, '&question=' + num);
|
||||
}
|
||||
}
|
||||
|
||||
function finishExam() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "stop",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
//send_data_to_db
|
||||
ws.send(JSON.stringify({
|
||||
type: "send_data_to_db",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
ws.send(JSON.stringify({
|
||||
type: "update_status",
|
||||
status_sessions: false,
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
function startTobii() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "start",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
function stopTobii() {
|
||||
ws.send(JSON.stringify({
|
||||
type: "command",
|
||||
action: "stop",
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
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: true,
|
||||
session_id: SESSION_ID
|
||||
}));
|
||||
|
||||
startTobii();
|
||||
};
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
@ -4,13 +4,10 @@
|
|||
use App\Http\Controllers\CekStatusController;
|
||||
use App\Http\Controllers\DashboardController;
|
||||
use App\Http\Controllers\DataSoalController;
|
||||
use App\Http\Controllers\HalamanUjianController;
|
||||
use App\Http\Controllers\HasilTesController;
|
||||
use App\Http\Controllers\LandingController;
|
||||
use App\Http\Controllers\ProfileController;
|
||||
use App\Http\Controllers\TestSessionsController;
|
||||
use App\Http\Controllers\TobiiReceiverController;
|
||||
use App\Http\Controllers\TutorialTesController;
|
||||
use App\Http\Controllers\UsersController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
|
@ -33,11 +30,7 @@
|
|||
Route::get('/about', [LandingController::class, 'about'])->name('beranda.about');
|
||||
Route::resource('booking', BookingController::class)->only(['store']);
|
||||
Route::resource('cek-status', CekStatusController::class)->only(['index', 'show']);
|
||||
Route::resource('tutorial-tes', TutorialTesController::class)->only(['index']);
|
||||
Route::resource('test-sessions', TestSessionsController::class)->only(['store', 'show']);
|
||||
Route::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::middleware(['auth', 'role.auth'])->group(function() {
|
||||
Route::resource('dashboard', DashboardController::class);
|
||||
Route::resource('users', UsersController::class);
|
||||
|
|
@ -49,8 +42,8 @@
|
|||
Route::resource('hasil_tes', HasilTesController::class);
|
||||
});
|
||||
|
||||
Route::get('api/eye/test', function(Request $req) {
|
||||
return $req->token;
|
||||
Route::post('api/eye/test', function(Request $req) {
|
||||
return $req->all();
|
||||
});
|
||||
|
||||
require __DIR__.'/auth.php';
|
||||
|
|
|
|||
Loading…
Reference in New Issue