Compare commits

...

19 Commits

Author SHA1 Message Date
Mahayoga 8e032dd1fb Merge pull request 'halaman-psikolog' (#1) from halaman-psikolog into master
Reviewed-on: #1
2026-07-06 12:37:22 +07:00
Mahayoga 1d8ade06f1 WIP: Bagian data mata bisa di downloaf 2026-06-13 20:56:20 +07:00
Mahayoga 043e2a81c0 WIP: Perbaikan validasi booking (belum mari) 2026-06-13 20:56:00 +07:00
Mahayoga a475b0a740 WIP: penambahan data soal 2026-05-30 22:04:55 +07:00
Mahayoga 7f6cf7dcd6 WIP: nambah parameter normal di halaman hasil ujian 2026-05-27 21:08:36 +07:00
Mahayoga d0bcdd2949 WIP: ngubah total score doang 2026-05-26 17:35:56 +07:00
Mahayoga 22f532cdd6 WIP: Overlay 2026-05-26 04:32:07 +07:00
Mahayoga 1357d96c78 WIP: confidence model 2026-05-25 20:51:17 +07:00
Mahayoga aebcdbb844 WIP: perbaikan data soal 2026-05-23 21:10:58 +07:00
Mahayoga 48c822c558 WIP: dashboard 2026-05-23 18:17:44 +07:00
Mahayoga e2954898e9 WIP: Halaman data hasil kecemasan 2026-05-23 15:55:58 +07:00
Mahayoga cc783674b6 In Progress: halaman psikolog bagian data soal 2026-05-21 03:29:03 +07:00
Mahayoga f11c3a879d WIP: Auth page 2026-05-21 00:27:11 +07:00
Mahayoga d07e24e39b WIP: perbaikan reverse soal dan jawaban 2026-05-20 12:25:14 +07:00
Mahayoga 6c41ac4cf3 WIP: Halaman hasil ujian 2026-05-20 11:23:50 +07:00
Mahayoga 01258eb92d WIP: Statistik mata 2026-05-19 22:36:49 +07:00
Mahayoga 9a895c57ba In Progress: adding screen dimension to db 2026-05-19 19:21:01 +07:00
Mahayoga 3b6968c2ae WIP: Fix landing page 2026-05-19 04:36:03 +07:00
Mahayoga 057cdaffa9 WIP: email booking 2026-05-17 20:41:08 +07:00
41 changed files with 2451 additions and 647 deletions

View File

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

View File

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

View File

@ -2,10 +2,13 @@
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
{
@ -14,6 +17,28 @@ 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,
@ -87,6 +112,14 @@ public function store(Request $request)
'unix_expired_time' => $tgl_request
]);
Mail::to($request->email)->send(new SendUniqueCode(
$request->nama_lengkap,
$kode_unik,
date('H:i:s', $tgl_request - 86399),
date('H:i:s', $tgl_request),
$request->tgl_booking,
));
return response()->json([
'status' => true,
'msg' => 'Booking success!'
@ -133,8 +166,10 @@ public function update(Request $request, string $id)
'status_tes' => ['required']
]);
BookingModel::where('id_booking', $id)->update([
'status_tes' => $request->status_tes
$data = BookingModel::where('id_booking', $id)->first();
$data->update([
'status_tes' => str($request->status_tes)
]);
return response()->json([

View File

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

View File

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

View File

@ -2,14 +2,50 @@
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) {
@ -24,22 +60,40 @@ public function getAllAnswer(Request $request) {
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
];
@ -73,6 +127,90 @@ public function index(Request $request)
$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') {
@ -80,9 +218,15 @@ public function index(Request $request)
'status_session' => '2',
'is_active' => '0'
]);
return view('user.pages.finish_ujian.index', compact('id_session'));
$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') {
return view('user.pages.finish_ujian.index', compact('id_session'));
$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.');

View File

@ -2,10 +2,34 @@
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.
*/
@ -35,7 +59,20 @@ 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!'
]);
}
/**
@ -59,6 +96,21 @@ public function update(Request $request, string $id)
*/
public function destroy(string $id)
{
//
$data = TestSessionsModel::where('id_test_sessions', $id)->first();
if($data != null) {
$data_booking = BookingModel::where('id_booking', $data->id_booking)->first();
$data_booking->update([
'status_tes' => '0'
]);
return response()->json([
'status' => true,
'msg' => 'Data berhasil dinonaktifkan'
]);
}
return response()->json([
'status' => false,
'msg' => 'Data tidak ditemukan!'
]);
}
}

View File

@ -7,6 +7,22 @@
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.
*/
@ -36,6 +52,8 @@ 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([

View File

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

View File

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

View File

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

View File

@ -21,6 +21,8 @@ class TestSessionsModel extends Model
'unix_start_time',
'is_active',
'unix_end_time',
'screen_w',
'screen_h'
];
protected $casts = [

View File

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

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -1,9 +1,9 @@
<nav class="pc-sidebar">
<div class="navbar-wrapper">
<div class="m-header">
<a href="{{ route('dashboard.index') }}" class="b-brand text-primary">
<a href="{{ route('dashboard.index') }}" class="b-brand text-primary fs-3 fw-bold text-dark">
<!-- ======== Change your logo from here ============ -->
<img src="{{ asset('assets/admin/assets/images/logo-dark.svg') }}" class="img-fluid logo-lg" alt="logo" id="logo-admin">
{{ env('APP_NAME') }}
</a>
</div>
<div class="navbar-content">

View File

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

View File

@ -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">Menunggu Konfirmasi</option>
<option value="0">Nonaktif</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 = ['warning', 'info', 'success'];
let status_dict_text = ['Menunggu Konfirmasi', 'Siap/Sedang Tes', 'Selesai'];
let status_dict = ['secondary', 'info', 'success'];
let status_dict_text = ['Nonaktif', 'Siap/Sedang Tes', 'Selesai'];
$(document).ready(function() {
table = new DataTable("#table-data", {
ajax: {

View File

@ -41,30 +41,13 @@
<thead>
<tr>
<th>No</th>
<th>Dummy</th>
<th>Dummy</th>
<th>Dummy</th>
<th>Nama</th>
<th>Kode Unik</th>
<th>Tgl dan Jam Ujian</th>
<th>Status Data</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>
@ -72,10 +55,229 @@
<!-- [ 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>
new DataTable("#table-data", {});
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'
});
}
}
};
});
</script>
@endsection

View File

@ -93,13 +93,10 @@
<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_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>
<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>
</select>
</div>
</div>
@ -146,13 +143,10 @@
<input type="text" class="form-control" id="jawaban_e" name="jawaban_e">
</div>
<div class="col-md-6 my-1">
<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>
<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>
</select>
</div>
</div>
@ -200,13 +194,10 @@
<input type="text" class="form-control" id="edit_jawaban_e" name="edit_jawaban_e">
</div>
<div class="col-md-6 my-1">
<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>
<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>
</select>
</div>
</div>
@ -296,7 +287,7 @@ function simpanAddData() {
'jawaban_c': $('#jawaban_c').val(),
'jawaban_d': $('#jawaban_d').val(),
'jawaban_e': $('#jawaban_e').val(),
'jawaban_benar': $('#jawaban_benar').val(),
'is_reverse': $('#is_reverse').val(),
}, function(data, status) {
$('#addModal').modal('hide');
Swal.fire({
@ -319,7 +310,7 @@ function getDataInfo(btn) {
$('#info_jawaban_c').attr('disabled', '');
$('#info_jawaban_d').attr('disabled', '');
$('#info_jawaban_e').attr('disabled', '');
$('#info_jawaban_benar').attr('disabled', '');
$('#info_is_reverse').attr('disabled', '');
$('#info_pertanyaan').val(data.data.pertanyaan);
$('#info_jawaban_a').val(data.data.jawaban_a);
@ -327,7 +318,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_jawaban_benar').val(data.data.jawaban_benar);
$('#info_is_reverse').val(data.data.is_reverse);
$('#info_pertanyaan').attr('disabled', 'disabled');
$('#info_jawaban_a').attr('disabled', 'disabled');
@ -335,7 +326,7 @@ function getDataInfo(btn) {
$('#info_jawaban_c').attr('disabled', 'disabled');
$('#info_jawaban_d').attr('disabled', 'disabled');
$('#info_jawaban_e').attr('disabled', 'disabled');
$('#info_jawaban_benar').attr('disabled', 'disabled');
$('#info_is_reverse').attr('disabled', 'disabled');
}
});
}
@ -352,7 +343,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_jawaban_benar').val(data.data.jawaban_benar);
$('#edit_is_reverse').val(data.data.is_reverse);
}
});
}
@ -370,7 +361,7 @@ function simpanEditData() {
'jawaban_c': $('#edit_jawaban_c').val(),
'jawaban_d': $('#edit_jawaban_d').val(),
'jawaban_e': $('#edit_jawaban_e').val(),
'jawaban_benar': $('#edit_jawaban_benar').val(),
'is_reverse': $('#edit_is_reverse').val(),
}, function(data, status) {
if(data.status) {
$('#editModal').modal('hide');

View File

@ -25,7 +25,16 @@
<div class="col-sm-12">
<div class="card">
<div class="card-header">
<h5>Tabel Data</h5>
<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>
</div>
<div class="card-body">
<table class="table" id="table-data">
@ -48,6 +57,45 @@
</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">
@ -66,12 +114,15 @@
<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>
@ -167,6 +218,7 @@ 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);
}
});
}
@ -181,6 +233,30 @@ 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__']) }}';
@ -189,13 +265,14 @@ function simpanEditData() {
'_method': 'PUT',
'name': $('#edit_nama_user').val(),
'email': $('#edit_email').val(),
'role': $('#edit_role').val()
'role': $('#edit_role').val(),
'alamat': $('#edit_alamat').val()
}, function(data, status) {
if(data.status) {
$('#editModal').modal('hide');
Swal.fire({
title: "Info",
text: "Data berhasil ditambahkan!",
text: "Data berhasil diubah!",
icon: "success"
});
fetchRowData();

View File

@ -1,25 +1,169 @@
<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.') }}
<!DOCTYPE html>
<html lang="en">
<!-- [Head] start -->
<head>
<title>Lupa Password | {{ env('APP_NAME') }}</title>
<!-- [Meta] -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimal-ui">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="description"
content="Mantis is made using Bootstrap 5 design framework. Download the free admin template & use it for your project.">
<meta name="keywords"
content="Mantis, Dashboard UI Kit, Bootstrap 5, Admin Template, Admin Dashboard, CRM, CMS, Bootstrap Admin Template">
<meta name="author" content="CodedThemes">
<!-- [Favicon] icon -->
<link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
</div>
</div>
<!-- [ Pre-loader ] End -->
<!-- Session Status -->
<x-auth-session-status class="mb-4" :status="session('status')" />
<form method="POST" action="{{ route('password.email') }}">
@csrf
<!-- Email Address -->
<div>
<x-input-label for="email" :value="__('Email')" />
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
<x-input-error :messages="$errors->get('email')" class="mt-2" />
<div 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="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Email Password Reset Link') }}
</x-primary-button>
<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>
</form>
</x-guest-layout>
<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>

View File

@ -3,7 +3,7 @@
<!-- [Head] start -->
<head>
<title>Login | Smart Anxiety</title>
<title>Login | {{ 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">
@ -50,7 +50,7 @@
<div class="auth-wrapper v3">
<div class="auth-form">
<div class="auth-header">
<a href="#"><img src="{{ asset('assets/admin/assets/images/logo-dark.svg') }}" alt="img"></a>
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</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">Forgot Password?</h5>
<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="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="#">Beranda</a></li>
<li class="list-inline-item"><a href="#">Contact us</a></li>
<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> -->

View File

@ -1,39 +1,198 @@
<x-guest-layout>
<form method="POST" action="{{ route('password.store') }}">
@csrf
<!DOCTYPE html>
<html lang="en">
<!-- [Head] start -->
<!-- Password Reset Token -->
<input type="hidden" name="token" value="{{ $request->route('token') }}">
<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">
<!-- 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" />
<!-- [Favicon] icon -->
<link rel="icon" href="{{ asset('assets/admin/assets/images/favicon.svg') }}" type="image/x-icon"> <!-- [Google Font] Family -->
<link rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=Public+Sans:wght@300;400;500;600;700&display=swap"
id="main-font-link">
<!-- [Tabler Icons] https://tablericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/tabler-icons.min.css') }}">
<!-- [Feather Icons] https://feathericons.com -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/feather.css') }}">
<!-- [Font Awesome Icons] https://fontawesome.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/fontawesome.css') }}">
<!-- [Material Icons] https://fonts.google.com/icons -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/fonts/material.css') }}">
<!-- [Template CSS Files] -->
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style.css') }}" id="main-style-link">
<link rel="stylesheet" href="{{ asset('assets/admin/assets/css/style-preset.css') }}">
<meta id="_token" value="{{ csrf_token() }}">
</head>
<!-- [Head] end -->
<!-- [Body] Start -->
<body>
<!-- [ Pre-loader ] start -->
<div class="loader-bg">
<div class="loader-track">
<div class="loader-fill"></div>
</div>
</div>
<!-- [ Pre-loader ] End -->
<div class="auth-main">
<div class="auth-wrapper v3">
<div class="auth-form">
<div class="auth-header">
<a href="{{ route('beranda.index') }}" class="fs-1 text-dark">{{ env('APP_NAME') }}</a>
</div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" />
<div 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>
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
<div 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>
<div class="flex items-center justify-end mt-4">
<x-primary-button>
{{ __('Reset Password') }}
</x-primary-button>
</div>
</form>
</x-guest-layout>
<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>

View File

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

View File

@ -8,23 +8,22 @@
<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">Clinic</span>
<span class="sitename">{{ env('APP_NAME') }}</span>
</a>
<p class="brand-description">Crafting exceptional digital experiences through thoughtful design and
innovative solutions that elevate your brand presence.</p>
<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>
<div class="contact-info mt-5">
<div class="contact-item">
<i class="bi bi-geo-alt"></i>
<span>123 Creative Boulevard, Design District, NY 10012</span>
<span>Politeknik Negeri Jember, Jurusan Teknologi Informasi, Jl. Mastrip, Krajan Timur, Sumbersari, Kec. Sumbersari, Kabupaten Jember, Jawa Timur</span>
</div>
<div class="contact-item">
<i class="bi bi-telephone"></i>
<span>+1 (555) 987-6543</span>
<span>+62 8233 7341 446</span>
</div>
<div class="contact-item">
<i class="bi bi-envelope"></i>
<span>hello@designstudio.com</span>
<span>e31231392@student.polije.ac.id</span>
</div>
</div>
</div>
@ -34,65 +33,32 @@
<div class="footer-nav-wrapper">
<div class="row">
<div class="col-6 col-lg-3">
<div class="col-6 col-lg-5">
<div class="nav-column">
<h6>Studio</h6>
<h6>Informasi</h6>
<nav class="footer-nav">
<a href="#!">Our Story</a>
<a href="#!">Design Process</a>
<a href="#!">Portfolio</a>
<a href="#!">Case Studies</a>
<a href="#!">Awards</a>
<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>
</nav>
</div>
</div>
<div class="col-6 col-lg-3">
<div class="col-6 col-lg-5">
<div class="nav-column">
<h6>Services</h6>
<h6>Contact Person</h6>
<nav class="footer-nav">
<a href="#!">Brand Identity</a>
<a href="#!">Web Design</a>
<a href="#!">Mobile Apps</a>
<a href="#!">Digital Strategy</a>
<a href="#!">Consultation</a>
<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>
</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">
@ -102,7 +68,7 @@
<div class="col-lg-6">
<div class="copyright">
<p>© <span class="sitename">Clinic</span>. All rights reserved.</p>
<p>© <span class="sitename">{{ env('APP_NAME') }}</span>. All rights reserved.</p>
</div>
</div>
@ -112,11 +78,7 @@
<a href="#!">Terms of Service</a>
<a href="#!">Cookie Policy</a>
<div class="credits">
<!-- 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>
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>
</div>
</div>
</div>

View File

@ -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>
<i class="bi bi-phone d-flex align-items-center ms-4"><span>+62 8233 7341 446</span></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>
</div>
<div class="social-links d-none d-md-flex align-items-center">
<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>
<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>
</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">Smart Anxiety</h1>
<h1 class="sitename">{{ env('APP_NAME') }}</h1>
</a>
<nav id="navmenu" class="navmenu">
<ul>
<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>
<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>
@if (session('is_logged_in'))
<li class="dropdown"><a href="#"><span>{{ Auth::user()->name }}</span> <i class="bi bi-chevron-down toggle-dropdown"></i></a>
<ul>

View File

@ -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/health/facilities-6.webp') }}" class="img-fluid main-image" alt="Healthcare facility">
<img src="{{ asset('assets/users/assets/img/tobii_eye_tracker_device.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/health/facilities-6.webp') }}" class="img-fluid main-image" alt="Healthcare facility">
<img src="{{ asset('assets/users/assets/img/gangguan-cemas-menyeluruh.jpg') }}" 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-heart-pulse"></i>
<i class="bi bi-eye"></i>
</div>
<h4>Compassion</h4>
<p>Membantu tenaga profesional dalam proses asesmen kecemasan</p>
<h4>Eye Movement Monitoring</h4>
<p>Memantau pergerakan mata dan pola fokus pengguna selama proses asesmen berlangsung.</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-clipboard-data"></i>
<i class="bi bi-activity"></i>
</div>
<h4>Excellence</h4>
<p>Menyediakan analisis berbasis data terhadap respon visual pasien</p>
<h4>Anxiety Estimation</h4>
<p>Menganalisis tingkat kecemasan berdasarkan data visual menggunakan model machine learning.</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-flask"></i>
<i class="bi bi-clipboard2-pulse"></i>
</div>
<h4>Integrity</h4>
<p>Menyajikan hasil estimasi tingkat kecemasan secara sistematis</p>
<h4>Decision Support</h4>
<p>Membantu tenaga profesional dalam proses evaluasi kondisi psikologis pengguna.</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-regex"></i>
<i class="bi bi-display"></i>
</div>
<h4>Innovation</h4>
<p>Mendukung proses pengambilan keputusan selama konsultasi</p>
<h4>Real-Time Visualization</h4>
<p>Menampilkan hasil analisis dan aktivitas visual pengguna secara real-time pada dashboard.</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-eye"></i>
<i class="bi bi-camera-video"></i>
</div>
<h4>Compassion</h4>
<p>Kamera menangkap pergerakan pupil pengguna</p>
<h4>Eye Tracking Capture</h4>
<p>Kamera atau eye tracker menangkap koordinat dan 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>Innovation</h4>
<p>Model machine learning melakukan klasifikasi</p>
<h4>Data Processing</h4>
<p>Data gaze dan pergerakan mata diproses menjadi fitur analisis.</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-easel"></i>
<i class="bi bi-cpu-fill"></i>
</div>
<h4>Innovation</h4>
<p>Hasil estimasi kecemasan ditampilkan pada dashboard</p>
<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>
</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">Camera</a>
aria-selected="true" data-aos="fade-up" data-aos-delay="100">Facial Analysis</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">Eye Detection</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="150">Gaze Tracking</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">Feature Extraction</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="200">Analytics</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">ML Prediction</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="250">AI Assessment</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">Result</a>
aria-selected="false" data-aos="fade-up" data-aos-delay="300">Technologies</a>
</div>
</div>
</div>
@ -214,51 +214,53 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<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>
<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>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-brain"></i>
<i class="bi bi-person-bounding-box"></i>
</div>
<div class="service-content">
<h4>Brain Monitoring</h4>
<p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.</p>
<h4>Face Detection</h4>
<p>Sistem mendeteksi area wajah pengguna secara real-time selama asesmen berlangsung.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-wave-square"></i>
<i class="bi bi-eye"></i>
</div>
<div class="service-content">
<h4>EEG Testing</h4>
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia.</p>
<h4>Eye Movement Tracking</h4>
<p>Pergerakan mata dan titik fokus pengguna dianalisis untuk memperoleh pola visual.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-stethoscope"></i>
<i class="bi bi-emoji-neutral"></i>
</div>
<div class="service-content">
<h4>Neurological Exam</h4>
<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium.</p>
<h4>Emotion Observation</h4>
<p>Ekspresi wajah digunakan sebagai indikator tambahan dalam analisis kecemasan.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-file-medical"></i>
<i class="bi bi-cpu"></i>
</div>
<div class="service-content">
<h4>Treatment Plans</h4>
<p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis.</p>
<h4>AI Classification</h4>
<p>Model machine learning melakukan estimasi tingkat kecemasan berdasarkan data visual pengguna.</p>
</div>
</div>
</div>
@ -277,53 +279,54 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<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.
<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.
</p>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-cut"></i>
<i class="bi bi-eye"></i>
</div>
<div class="service-content">
<h4>Minimally Invasive</h4>
<p>Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet.</p>
<h4>Gaze Tracking</h4>
<p>Sistem melacak arah pandangan dan titik fokus mata pengguna secara real-time.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-tools"></i>
<i class="bi bi-crosshair"></i>
</div>
<div class="service-content">
<h4>Advanced Procedures</h4>
<p>Consectetur, adipisci velit, sed quia non numquam eius modi tempora.</p>
<h4>Fixation Analysis</h4>
<p>Durasi fokus pengguna pada area tertentu dianalisis untuk mendeteksi pola perhatian visual.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-shield-alt"></i>
<i class="bi bi-grid-3x3-gap"></i>
</div>
<div class="service-content">
<h4>Safe Operations</h4>
<p>Incidunt ut labore et dolore magnam aliquam quaerat voluptatem.</p>
<h4>Heatmap Visualization</h4>
<p>Pergerakan mata divisualisasikan dalam bentuk heatmap untuk melihat distribusi perhatian pengguna.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-clock"></i>
<i class="bi bi-cpu"></i>
</div>
<div class="service-content">
<h4>Recovery Support</h4>
<p>Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis.</p>
<h4>AI-Based Classification</h4>
<p>Model machine learning mengklasifikasikan tingkat kecemasan berdasarkan pola gaze pengguna.</p>
</div>
</div>
</div>
@ -342,53 +345,54 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<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>
<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>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="far fa-smile"></i>
<i class="bi bi-grid-3x3-gap"></i>
</div>
<div class="service-content">
<h4>Oral Health</h4>
<p>Consequatur aut perferendis doloribus asperiores repellat tempore.</p>
<h4>Heatmap Analytics</h4>
<p>Visualisasi heatmap digunakan untuk melihat distribusi perhatian visual pengguna pada layar.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-tooth"></i>
<i class="bi bi-activity"></i>
</div>
<div class="service-content">
<h4>Teeth Cleaning</h4>
<p>Et harum quidem rerum facilis est et expedita distinctio nam libero.</p>
<h4>Real-Time Monitoring</h4>
<p>Sistem memantau aktivitas pengguna dan data eye tracking secara langsung selama asesmen berlangsung.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-star"></i>
<i class="bi bi-graph-up-arrow"></i>
</div>
<div class="service-content">
<h4>Cosmetic Dentistry</h4>
<p>Tempore cum soluta nobis est eligendi optio cumque nihil impedit quo minus.</p>
<h4>Anxiety Prediction</h4>
<p>Model machine learning menghasilkan estimasi tingkat kecemasan berdasarkan pola visual pengguna.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-cog"></i>
<i class="bi bi-display"></i>
</div>
<div class="service-content">
<h4>Orthodontics</h4>
<p>Id quod maxime placeat facere possimus, omnis voluptas assumenda est.</p>
<h4>Interactive Dashboard</h4>
<p>Seluruh hasil analisis divisualisasikan melalui dashboard interaktif yang mudah dipahami.</p>
</div>
</div>
</div>
@ -408,52 +412,53 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<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>
<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>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-eye"></i>
<i class="bi bi-bullseye"></i>
</div>
<div class="service-content">
<h4>Vision Testing</h4>
<p>Sint et voluptatum sint quia dolor sit amet consectetur adipiscing elit.</p>
<h4>Attention Analysis</h4>
<p>Sistem mengevaluasi fokus dan perhatian visual pengguna selama proses asesmen berlangsung.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-camera"></i>
<i class="bi bi-emoji-neutral"></i>
</div>
<div class="service-content">
<h4>Retinal Imaging</h4>
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua ut.</p>
<h4>Facial Behavior</h4>
<p>Ekspresi wajah dianalisis untuk membantu mendeteksi perubahan perilaku emosional pengguna.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-bolt"></i>
<i class="bi bi-diagram-3"></i>
</div>
<div class="service-content">
<h4>Laser Surgery</h4>
<p>Enim ad minim veniam quis nostrud exercitation ullamco laboris nisi.</p>
<h4>Pattern Recognition</h4>
<p>Model AI mengenali pola visual tertentu yang berkaitan dengan tingkat kecemasan pengguna.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-prescription-bottle"></i>
<i class="bi bi-cpu"></i>
</div>
<div class="service-content">
<h4>Eye Care Plans</h4>
<p>Ut aliquip ex ea commodo consequat duis aute irure dolor in reprehenderit.</p>
<h4>AI Assessment</h4>
<p>Machine learning menghasilkan estimasi tingkat kecemasan berdasarkan kombinasi data visual pengguna.</p>
</div>
</div>
</div>
@ -473,52 +478,53 @@
</div>
<div class="col-lg-8 order-lg-1">
<div class="department-info">
<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>
<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>
<div class="row mt-4">
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-heartbeat"></i>
<i class="bi bi-eye"></i>
</div>
<div class="service-content">
<h4>Heart Monitoring</h4>
<p>Mollit anim id est laborum sed ut perspiciatis unde omnis iste natus error.</p>
<h4>Eye Tracking Device</h4>
<p>Perangkat eye tracker digunakan untuk menangkap koordinat dan pergerakan mata pengguna secara real-time.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-chart-line"></i>
<i class="bi bi-cpu"></i>
</div>
<div class="service-content">
<h4>ECG Analysis</h4>
<p>Sit voluptatem accusantium doloremque laudantium totam rem aperiam.</p>
<h4>Machine Learning</h4>
<p>Model AI menganalisis pola visual pengguna untuk menghasilkan estimasi tingkat kecemasan.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-tint"></i>
<i class="bi bi-wifi"></i>
</div>
<div class="service-content">
<h4>Blood Tests</h4>
<p>Eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae.</p>
<h4>Real-Time Communication</h4>
<p>Teknologi WebSocket digunakan untuk mengirim data monitoring secara langsung dan responsif.</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="service-item">
<div class="service-icon">
<i class="fas fa-shield-heart"></i>
<i class="bi bi-display"></i>
</div>
<div class="service-content">
<h4>Preventive Care</h4>
<p>Vitae dicta sunt explicabo nemo enim ipsam voluptatem quia voluptas sit.</p>
<h4>Interactive Dashboard</h4>
<p>Dashboard interaktif menampilkan visualisasi data, heatmap, dan hasil analisis AI secara real-time.</p>
</div>
</div>
</div>
@ -565,7 +571,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/tensorflow_logo.webp') }}" class="img-fluid" alt="Tensorflow Logo">
<img src="{{ asset('assets/users/assets/img/logo/node-js.png') }}" class="img-fluid" alt="Node.js Logo">
</div>
</div>
</div><!-- End Certifications Row -->

View File

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

View File

@ -1,6 +1,23 @@
@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">
@ -18,7 +35,7 @@
<nav class="breadcrumbs">
<div class="container">
<ol>
<li><a href="index.html">Home</a></li>
<li><a href="{{ route('beranda.index') }}">Home</a></li>
<li class="current">Hasil Tes</li>
</ol>
</div>
@ -27,32 +44,303 @@
<!-- About Section -->
<section id="about" class="about section">
<div class="container" data-aos="fade-up" data-aos-delay="100">
<table class="table" id="table-data-hasil-ujian">
<thead>
<tr>
<th>No</th>
<th>Pertanyaan</th>
<th>Jawaban</th>
</tr>
</thead>
<tbody></tbody>
</table>
<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">
<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">Grafik Kecepatan Mata</h2>
<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">Heatmap Pergerakan Mata</h2>
<h2 class="title text-center">Heatmap Pergerakan Mata</h2>
<div style="position: relative; aspect-ratio: 16/9;">
<img src="{{ asset('assets/users/assets/img/overlay/overlay.png') }}" style="width:100%; height:100%; object-fit: cover;">
<img src="{{ asset('assets/users/assets/img/overlay/overlay.png') }}" style="width:100%; height:100%; object-fit: cover; position: absolute;">
<div id="heatmapChart" style="aspect-ratio: 16/9;"></div>
</div>
</div>
<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 -->
@ -79,10 +367,17 @@
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];
@ -141,10 +436,136 @@ function renderVelocityChart(timeseries) {
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,
@ -167,27 +588,85 @@ function renderVelocityChart(timeseries) {
data: null,
render: function(data, type, row) {
let renderedJawaban = null;
if(row.jawaban_key == 'a') {
renderedJawaban = `<span class="badge text-bg-primary">${row.jawaban}</span>`;
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') {
renderedJawaban = `<span class="badge" style="background-color: #fc7938; color: white;">${row.jawaban}</span>`;
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') {
renderedJawaban = `<span class="badge text-bg-danger">${row.jawaban}</span>`;
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') {
renderedJawaban = `<span class="badge text-bg-warning">${row.jawaban}</span>`;
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',
@ -196,23 +675,69 @@ function renderVelocityChart(timeseries) {
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// console.log(data);
if(data.type === 'json_file_data') {
if(data.data != null) {
data_tobii = data.data;
data_tobii = null;
let xhttp = new XMLHttpRequest();
heatmapContainer = document.getElementById('heatmapChart');
clientWidth = heatmapContainer.clientWidth;
clientHeight = heatmapContainer.clientHeight;
scaleX = clientWidth / 1366;
scaleY = clientHeight / 768;
heatmapInstance = h337.create({
container: heatmapContainer,
radius: 40,
maxOpacity: 0.6,
blur: 0.85
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
});
loadData(data_tobii);
}
}
};

View File

@ -19,7 +19,7 @@
</p>
<div class="hero-actions" data-aos="fade-right" data-aos-delay="600">
<a href="{{ route('beranda.about') }}" class="btn btn-primary">Learn About The System</a>
<a href="#appointment" class="btn btn-primary">Coba Sekarang</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,30 +41,7 @@
<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/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>
<img src="{{ asset('assets/users/assets/img/health/depresi_crop.jpg') }}" alt="Modern Healthcare Facility" class="img-fluid">
</div>
<div class="background-elements">
<div class="element element-1"></div>
@ -96,7 +73,7 @@
</p>
<div class="cta-section">
<a href="about.html" class="btn-primary">Learn More About Us</a>
<a href="{{ route('beranda.about') }}" class="btn-primary">Learn More About Us</a>
</div>
</div>
</div>
@ -104,7 +81,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/facilities-9.webp') }}" alt="Modern medical facility" class="img-fluid">
<img src="{{ asset('assets/users/assets/img/health/about.jpg') }}" alt="Modern medical facility" class="img-fluid">
</div>
{{-- <div class="floating-card">
<div class="card-content">
@ -146,7 +123,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-heartbeat"></i>
<i class="fas fa-message"></i>
</div>
</div>
<div class="service-content">
@ -169,7 +146,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-brain"></i>
<i class="fas fa-face-rolling-eyes"></i>
</div>
</div>
<div class="service-content">
@ -192,7 +169,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-bone"></i>
<i class="fas fa-chart-gantt"></i>
</div>
</div>
<div class="service-content">
@ -216,7 +193,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-child"></i>
<i class="fas fa-computer"></i>
</div>
</div>
<div class="service-content">
@ -324,7 +301,7 @@
<h1>Make an Appointment</h1>
</div><!-- End Section Title -->
<div class="container" data-aos="fade-up" data-aos-delay="100">
<div class="container" data-aos="fade-up" data-aos-delay="100" id="appointment">
<div class="row">
<div class="col-lg-10 mx-auto">
@ -340,8 +317,8 @@
<i class="bi bi-calendar-check"></i>
</div>
<div class="step-content">
<h4>Select Service</h4>
<p>Choose the medical service you need</p>
<h4>Isi Data Diri</h4>
<p>Mohon isi data diri Anda dengan lengkap</p>
</div>
</div>
<div class="step">
@ -349,8 +326,8 @@
<i class="bi bi-clock"></i>
</div>
<div class="step-content">
<h4>Pick Date &amp; Time</h4>
<p>Select your preferred appointment slot</p>
<h4>Ambil Tanggal &amp; Waktu</h4>
<p>Pilih tanggal dan waktu yang paling cocok untuk Anda</p>
</div>
</div>
<div class="step">
@ -358,8 +335,8 @@
<i class="bi bi-person-check"></i>
</div>
<div class="step-content">
<h4>Confirm Details</h4>
<p>Provide your information and confirm</p>
<h4>Konfirmasi Detail</h4>
<p>Periksa kembali semua detail yang telah Anda masukkan</p>
</div>
</div>
</div>
@ -412,7 +389,14 @@
<script>
function sendAppointment() {
$('#error_msg').hide();
Swal.fire({
title: "Loading",
text: "Sedang memproses booking kamu, tunggu sebentar yaa!",
icon: "info",
showConfirmButton: false,
allowOutsideClick: false
});
let name = $('#nama_lengkap').val();
let email = $('#email').val();
let no_telp = $('#no_telp').val();

View File

@ -30,8 +30,8 @@
<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" id="text_question" style="text-align: justify"></div>
<div class="col-md-12" id="answer_field">
<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>
@ -300,6 +300,7 @@ function finishExam() {
ws.send(JSON.stringify({
type: "command",
action: "stop",
finish: true,
session_id: SESSION_ID
}));

View File

@ -36,6 +36,7 @@
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);
@ -45,8 +46,11 @@
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']);
@ -54,10 +58,17 @@
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('api/eye/test', function(Request $req) {
return $req->token;
Route::get('email/test', function(Request $req) {
return view('layouts.mail-send-code', [
'code' => 'ABC123',
'name' => 'Mahayoga',
'startExpirationTime' => '09:00:00',
'endExpirationTime' => '09:05:00',
'tglExpired' => '2023-10-01'
]);
});
require __DIR__.'/auth.php';