1161 lines
43 KiB
PHP
1161 lines
43 KiB
PHP
@extends('layouts.app')
|
||
|
||
@section('title', 'Landing Page - Murid Ceria')
|
||
|
||
@push('styles')
|
||
<script src="https://kit.fontawesome.com/95c0931704.js" crossorigin="anonymous"></script>
|
||
<link rel="stylesheet" href="{{asset("assets/css/custom.css")}}">
|
||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
|
||
@endpush
|
||
|
||
@section('header')
|
||
<!-- Start .header-section -->
|
||
<div id="home" class="header-section flex-box-middle section gradiant-background header-curbed-circle background-circles header-software">
|
||
<div id="particles-js" class="particles-container"></div>
|
||
<div id="navigation" class="navigation is-transparent" data-spy="affix" data-offset-top="5">
|
||
<nav class="navbar navbar-default">
|
||
<div class="container">
|
||
<!-- Brand and toggle get grouped for better mobile display -->
|
||
<div class="navbar-header">
|
||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#site-collapse-nav" aria-expanded="false">
|
||
<span class="sr-only">Toggle navigation</span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
<span class="icon-bar"></span>
|
||
</button>
|
||
<a class="navbar-brand" href="#home">
|
||
<img class="logo logo-light" src="images/logo-muridceria.png" alt="logo" />
|
||
<img class="logo logo-color" src="images/logo-muridceria.png" alt="logo" />
|
||
</a>
|
||
</div>
|
||
|
||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||
<div class="collapse navbar-collapse font-secondary" id="site-collapse-nav">
|
||
<ul class="nav nav-list navbar-nav navbar-right">
|
||
<li><a class="nav-item" href="#home">Beranda</a></li>
|
||
<li><a class="nav-item" href="#huruf">Kenali Huruf</a></li>
|
||
<li><a class="nav-item" href="#about">Belajar</a></li>
|
||
<li><a class="nav-item" href="#features">Baca</a></li>
|
||
<li><a class="nav-item" href="#students">Riwayat</a></li>
|
||
<li><a class="nav-item" href="#another">Bantuan</a></li>
|
||
<li><a class="nav-item" href="#testimonial">Pesan</a></li>
|
||
</ul>
|
||
</div><!-- /.navbar-collapse -->
|
||
</div><!-- /.container -->
|
||
</nav>
|
||
</div><!-- .navigation -->
|
||
|
||
<div class="header-content pt-90">
|
||
<div class="container">
|
||
<div class="row text-center">
|
||
<div class="col-md-8 col-md-offset-2">
|
||
<div class="header-texts">
|
||
<h1 class="cd-headline clip is-full-width wow fadeInUp" data-wow-duration="2s">
|
||
<span>Murid Ceria </span>
|
||
<span class="cd-words-wrapper">
|
||
<b class="is-visible"></b>
|
||
<b>Membaca Lancar Sekolah Nyaman</b>
|
||
<b>Yuk Rajin Membaca Bacaan Menarik!</b>
|
||
</span>
|
||
</h1>
|
||
@if (!Auth::user())
|
||
<ul class="buttons">
|
||
<li>
|
||
<a href="{{ route('login') }}" class="button button-border button-transparent wow fadeInUp" data-wow-duration=".9s" data-wow-delay=".9s">
|
||
L O G I N
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
@else
|
||
<ul class="buttons">
|
||
@if(Auth::user()->role_id !== '9e3efb34-c5ef-416e-b31e-58ba13807301')
|
||
<li>
|
||
<a href="{{ route('dashboard') }}" class="button button-border button-transparent wow fadeInUp" data-wow-duration=".9s" data-wow-delay=".9s">
|
||
Selamat bergabung, {{ Auth::user()->name }}
|
||
</a>
|
||
</li>
|
||
@else
|
||
{{-- Jika siswa, tombol disable / nonaktif --}}
|
||
<li>
|
||
<button class="button button-border button-transparent wow fadeInUp" data-wow-duration=".9s" data-wow-delay=".9s" disabled>
|
||
Selamat bergabung, {{ Auth::user()->name }}
|
||
</button>
|
||
</li>
|
||
@endif
|
||
{{-- Tambahkan tombol Logout di sini --}}
|
||
<li>
|
||
<form action="{{ route('logout') }}" method="POST" style="display:inline;">
|
||
@csrf
|
||
<button type="submit" class="button button-border button-transparent text-danger wow fadeInUp" data-wow-duration=".9s" data-wow-delay=".9s">
|
||
Logout
|
||
</button>
|
||
</form>
|
||
</li>
|
||
</ul>
|
||
@endif
|
||
|
||
</div>
|
||
</div><!-- .col -->
|
||
</div><!-- .row -->
|
||
<div class="row text-center">
|
||
<div class="col-md-10 col-md-offset-1">
|
||
<div class="header-mockups">
|
||
<div class="header-laptop-mockup black wow fadeInUp" data-wow-duration="1s" data-wow-delay=".6s" >
|
||
<img src="images/home-dashboard.png" alt="software-screen" />
|
||
</div>
|
||
<div class="iphonex-flat-mockup wow fadeInUp" data-wow-duration="1s" data-wow-delay=".9s">
|
||
<img src="images/home-dashboard.png" alt="app screen">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endsection
|
||
|
||
@section('content')
|
||
<!-- FITUR PENGENALAN HURUF -->
|
||
<div id="huruf" class="about-section section white-bg">
|
||
<div class="container tab-fix">
|
||
<div class="section-head text-center">
|
||
<div class="row">
|
||
<div class="col-md-8 col-md-offset-2">
|
||
<h2 class="heading">Kenali <span>Huruf dan Angka</span></h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Video Slider -->
|
||
<div class="slider-container">
|
||
<div class="video-wrapper">
|
||
<div class="video-slider" id="videoSlider">
|
||
<video class="video-slide active" controls muted>
|
||
<source src="video/belajar-membaca-huruf.mp4" type="video/mp4">
|
||
Browser Anda tidak mendukung video!
|
||
</video>
|
||
<video class="video-slide" controls muted>
|
||
<source src="video/belajar-membaca-angka.mp4" type="video/mp4">
|
||
Browser Anda tidak mendukung video!
|
||
</video>
|
||
</div>
|
||
<button id="prev" class="arrow left-arrow">❮</button>
|
||
<button id="next" class="arrow right-arrow">❯</button>
|
||
</div>
|
||
<div id="videoError" class="error-message"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="writing-container">
|
||
<h3 class="text-center">Coba Menulis Huruf, Angka, atau Kata</h3>
|
||
<p class="text-center">Tulis huruf, angka, atau kata dengan jelas di dalam kotak.</p>
|
||
<canvas id="writingCanvas" width="800" height="500"></canvas>
|
||
<div class="button-group">
|
||
<button id="clearCanvas">Hapus</button>
|
||
<button id="detectButton">Deteksi</button>
|
||
</div>
|
||
<div id="recognitionResult"></div>
|
||
</div>
|
||
|
||
{{-- FITUR PEMBELAJARAN VIDEO INTERAKTIF --}}
|
||
<div id="about" class="about-section section white-bg">
|
||
<div class="container tab-fix">
|
||
<div class="section-head text-center">
|
||
<div class="row">
|
||
<div class="col-md-8 col-md-offset-2">
|
||
<h2 class="heading">Pembelajaran <span>Nyaman</span></h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="container">
|
||
<!-- Swiper Slider -->
|
||
<div class="swiper mySwiper py-4">
|
||
<div class="swiper-wrapper">
|
||
@foreach ($pembelajarans as $pembelajaran)
|
||
<div class="swiper-slide">
|
||
<div class="row align-items-center g-4">
|
||
<!-- Video dan Audio -->
|
||
<div class="col-md-6">
|
||
<div class="media wow fadeInLeft" data-wow-duration=".5s">
|
||
<!-- Video -->
|
||
<div class="media-card mb-4">
|
||
@if ($pembelajaran->video)
|
||
<div class="video-wrapper">
|
||
<video width="100%" controls class="rounded">
|
||
<source src="{{ asset('video/' . $pembelajaran->video) }}" type="video/mp4">
|
||
Browser Anda tidak mendukung pemutaran video.
|
||
</video>
|
||
</div>
|
||
@else
|
||
<div class="placeholder-card text-center bg-light rounded p-4">
|
||
<i class="fas fa-video-slash fa-2x text-muted mb-2"></i>
|
||
<p class="mb-0 text-muted">Tidak ada video tersedia</p>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
<!-- Audio -->
|
||
<div class="media-card">
|
||
@if ($pembelajaran->audio)
|
||
<div class="audio-wrapper wow fadeInUp" data-wow-duration=".5s" data-wow-delay=".2s">
|
||
<audio controls class="w-100 rounded">
|
||
<source src="{{ asset('audio/' . $pembelajaran->audio) }}" type="audio/mpeg">
|
||
Browser Anda tidak mendukung pemutaran audio.
|
||
</audio>
|
||
</div>
|
||
@else
|
||
<div class="placeholder-card text-center bg-light rounded p-4 wow fadeInUp" data-wow-duration=".5s" data-wow-delay=".2s">
|
||
<i class="fas fa-volume-mute fa-2x text-muted mb-2"></i>
|
||
<p class="mb-0 text-muted">Tidak ada audio tersedia</p>
|
||
</div>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Bacaan -->
|
||
<div class="col-md-6">
|
||
<div class="txt-entry bg-light p-4 rounded shadow-sm h-100 d-flex flex-column justify-content-between wow fadeInRight" data-wow-duration=".5s">
|
||
<p class="text-secondary mb-2">Silahkan Mencoba</p>
|
||
<h4 id="bacaan-{{ $pembelajaran->id }}" class="mb-3 text-primary">{{ $pembelajaran->bacaan ?? 'Tidak ada bacaan.' }}</h4>
|
||
<button class="button mt-auto" onclick="mulaiRekaman({{ $pembelajaran->id }})">
|
||
Mulai Membaca
|
||
</button>
|
||
<p class="mt-3"><strong>Hasil:</strong> <span id="hasil-{{ $pembelajaran->id }}">-</span></p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endforeach
|
||
</div>
|
||
|
||
<!-- Tombol Navigasi -->
|
||
<div class="swiper-button-next custom-swiper-button"></div>
|
||
<div class="swiper-button-prev custom-swiper-button"></div>
|
||
|
||
<!-- Pagination -->
|
||
<div class="swiper-pagination"></div>
|
||
</div>
|
||
|
||
<!-- SwiperJS Init -->
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function() {
|
||
var swiper = new Swiper(".mySwiper", {
|
||
slidesPerView: 1,
|
||
spaceBetween: 10,
|
||
navigation: {
|
||
nextEl: ".swiper-button-next",
|
||
prevEl: ".swiper-button-prev",
|
||
},
|
||
pagination: {
|
||
el: ".swiper-pagination",
|
||
clickable: true,
|
||
},
|
||
});
|
||
});
|
||
</script>
|
||
|
||
<!-- Swiper CSS -->
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.css">
|
||
|
||
<!-- Swiper JS -->
|
||
<script src="https://cdn.jsdelivr.net/npm/swiper@9/swiper-bundle.min.js"></script>
|
||
|
||
<!-- Font Awesome untuk ikon placeholder -->
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
||
|
||
<script>
|
||
function hitungAkurasi(teksAsli, teksDibaca) {
|
||
function levenshtein(a, b) {
|
||
let tmp;
|
||
if (a.length === 0) return b.length;
|
||
if (b.length === 0) return a.length;
|
||
if (a.length > b.length) tmp = a, a = b, b = tmp;
|
||
|
||
let row = Array(a.length + 1).fill(0).map((_, i) => i);
|
||
for (let i = 1; i <= b.length; i++) {
|
||
let prev = i;
|
||
for (let j = 1; j <= a.length; j++) {
|
||
let val = b[i - 1] === a[j - 1] ? row[j - 1] : Math.min(row[j - 1] + 1, prev + 1, row[j] + 1);
|
||
row[j - 1] = prev;
|
||
prev = val;
|
||
}
|
||
row[a.length] = prev;
|
||
}
|
||
return row[a.length];
|
||
}
|
||
|
||
let distance = levenshtein(teksAsli.toLowerCase(), teksDibaca.toLowerCase());
|
||
let maxLength = Math.max(teksAsli.length, teksDibaca.length);
|
||
let similarity = ((maxLength - distance) / maxLength) * 100;
|
||
|
||
return similarity;
|
||
}
|
||
|
||
function mulaiRekaman(id) {
|
||
const teksAsli = document.getElementById(`bacaan-${id}`).innerText;
|
||
const hasilEl = document.getElementById(`hasil-${id}`);
|
||
|
||
if (!('webkitSpeechRecognition' in window)) {
|
||
alert('Browser tidak mendukung speech recognition.');
|
||
return;
|
||
}
|
||
|
||
let recognition = new webkitSpeechRecognition();
|
||
recognition.lang = "id-ID";
|
||
recognition.continuous = false;
|
||
recognition.interimResults = false;
|
||
|
||
recognition.start();
|
||
|
||
recognition.onresult = function(event) {
|
||
let teksDibaca = event.results[0][0].transcript;
|
||
let akurasi = hitungAkurasi(teksAsli, teksDibaca);
|
||
|
||
if (akurasi >= 80) {
|
||
hasilEl.innerHTML = `Benar ✅ (Akurasi: ${akurasi.toFixed(2)}%)`;
|
||
hasilEl.style.color = "green";
|
||
} else {
|
||
hasilEl.innerHTML = `Salah ❌ (Akurasi: ${akurasi.toFixed(2)}%)`;
|
||
hasilEl.style.color = "red";
|
||
}
|
||
};
|
||
|
||
recognition.onerror = function(event) {
|
||
hasilEl.innerHTML = "Terjadi kesalahan, coba lagi.";
|
||
hasilEl.style.color = "red";
|
||
};
|
||
}
|
||
</script>
|
||
</div>
|
||
|
||
<div id="features" class="features-box-section section pb-90 white-bg">
|
||
<div class="container tab-fix">
|
||
<div class="section-head text-center">
|
||
<div class="row">
|
||
<div class="col-md-6 col-sm-8 col-md-offset-3 col-sm-offset-2">
|
||
<h2 class="heading" id="titleHeading">Membaca <span>Yuk!</span></h2>
|
||
</div>
|
||
</div>
|
||
<div class="row text-center">
|
||
<div class="col-md-12">
|
||
<p id="randomText" class="lead font-weight-bold">Sedang memuat...</p>
|
||
<div class="timer-box">
|
||
<img src="images/waktu-berlari.gif" alt="Timer Animasi" class="timer-gif">
|
||
<p id="countdown" class="countdown-text">120</p>
|
||
</div>
|
||
<button id="startRecognition" class="btn-start">
|
||
<i class="ti ti-microphone"></i> Mulai Membaca
|
||
</button>
|
||
|
||
<p class="mt-3" id="recognizedWrap" style="display: none;">
|
||
<strong>Hasil Rekaman:</strong> <span id="recognizedText">...</span>
|
||
</p>
|
||
|
||
<div id="result" style="display: none; margin-top: 20px;">
|
||
<h3>Hasil Penilaian</h3>
|
||
<p><strong>Biner Naive Bayes Classifier:</strong> <span id="finalScore"></span></p>
|
||
<p><strong>Tingkat Pemahaman:</strong> <span id="comprehensionLevel"></span></p>
|
||
<p><strong>Akurasi:</strong> <span id="accuracy"></span></p>
|
||
<p><strong>Waktu Pengerjaan:</strong> <span id="timeTaken"></span> detik</p>
|
||
<p><strong>Keterangan:</strong> <span id="evaluation"></span></p>
|
||
</div>
|
||
|
||
<button id="nextText" class="btn btn-success mt-3" style="visibility: hidden; position: absolute; right: 10px; top: 30px;">
|
||
Selanjutnya
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Start .team-section -->
|
||
<div class="team-section section grey-background pb-90" id="students">
|
||
<div class="container">
|
||
<div class="section-head text-center">
|
||
<div class="row">
|
||
<div class="col-md-8 col-md-offset-2">
|
||
<h2 class="heading">Riwayat <span>Membaca</span></h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="row">
|
||
<div class="col-md-10 col-md-offset-1">
|
||
<div class="table-responsive">
|
||
@if($riwayat->isEmpty())
|
||
<p class="text-center text-muted">Belum ada riwayat membaca.</p>
|
||
@else
|
||
<table class="table table-bordered table-striped">
|
||
<thead class="bg-primary text-white">
|
||
<tr>
|
||
<th>No</th>
|
||
<th>Nilai Biner</th>
|
||
<th>Tingkat Pemahaman</th>
|
||
<th>Akurasi</th>
|
||
<th>Waktu Mengerjakan</th>
|
||
<th>Keterangan</th>
|
||
<th>Tanggal</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
@forelse ($riwayat as $index => $data)
|
||
<tr>
|
||
<td>{{ $index + 1 }}</td>
|
||
<td>{{ $data->nilai_akhir }}</td>
|
||
<td>{{ $data->tingkat_pemahaman }}%</td>
|
||
<td>{{ $data->akurasi }}%</td>
|
||
<td>{{ $data->waktu_mengerjakan }} detik</td>
|
||
<td>{{ $data->evaluasi }}</td>
|
||
<td>{{ optional($data->created_at)->format('d M Y') }}</td>
|
||
</tr>
|
||
@empty
|
||
<tr>
|
||
<td colspan="7" class="text-center text-muted">Belum ada riwayat membaca.</td>
|
||
</tr>
|
||
@endforelse
|
||
</tbody>
|
||
</table>
|
||
@endif
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Start .faq-section -->
|
||
<div class="faq-section section white-bg pt-120 pb-100">
|
||
<div class="container">
|
||
<div class="faq-alt">
|
||
<div class="row tab-fix">
|
||
<div class="col-md-4 tab-center mobile-center col-md-offset-1">
|
||
<div class="side-heading">
|
||
<h2 class="heading">Panduan <span>Website</span></h2>
|
||
<p>Pelajari alur website berikut untuk memaksimalkan penggunaan.</p>
|
||
</div>
|
||
</div><!-- .col -->
|
||
<div class="col-md-6">
|
||
<!-- Accordion -->
|
||
<div class="panel-group accordion" id="another" role="tablist" aria-multiselectable="true">
|
||
<div class="panel panel-default">
|
||
<div class="panel-heading" role="tab" id="accordion-i1">
|
||
<h6 class="panel-title">
|
||
<a role="button" data-toggle="collapse" data-parent="#another" href="#accordion-pane-i1" aria-expanded="false">
|
||
Apa yang bisa dilakukan guru pada website ini ?
|
||
<span class="plus-minus"><span></span></span>
|
||
</a>
|
||
</h6>
|
||
</div>
|
||
<div id="accordion-pane-i1" class="panel-collapse collapse in" role="tabpanel" aria-labelledby="accordion-i1">
|
||
<div class="panel-body">
|
||
<p>1. Bertindak mengelola website admin</p>
|
||
<p>2. Guru dapat memasukkan video interaktif serta latihan bacaan siswa sesuai dengan pembelajaran yang diajarkan di sekolah.</p>
|
||
<p>3. Guru dapat melihat riwayat baca siswa dan mengajarkan kekurangan siswa sesuai evaluasi yang diberikan sistem.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- each panel for accordion -->
|
||
<div class="panel panel-default">
|
||
<div class="panel-heading" role="tab" id="accordion-i2">
|
||
<h6 class="panel-title">
|
||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#another" href="#accordion-pane-i2" aria-expanded="false">
|
||
Apa saja yang dilakukan siswa pada website ini?
|
||
<span class="plus-minus"><span></span></span>
|
||
</a>
|
||
</h6>
|
||
</div>
|
||
<div id="accordion-pane-i2" class="panel-collapse collapse" role="tabpanel" aria-labelledby="accordion-i2">
|
||
<div class="panel-body">
|
||
<p>1. Siswa dapat melihat fitur pengenalan huruf berupa video-video pembelajaran yang menarik serta dapat menulis.</p>
|
||
<p>2. Siswa dapat melihat fitur pembelajaran interaktif serta membaca bacaan latihan yang sesuai dengan materi video sebagai praktek.</p>
|
||
<p>3. Siswa dapat membaca fitur membaca dari sistem untuk mengetahui nilai dan evaluasi kekurangan.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- each panel for accordion -->
|
||
<div class="panel panel-default">
|
||
<div class="panel-heading" role="tab" id="accordion-i3">
|
||
<h6 class="panel-title">
|
||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#another" href="#accordion-pane-i3" aria-expanded="false">
|
||
Apakah website ini universal ?
|
||
<span class="plus-minus"><span></span></span>
|
||
</a>
|
||
</h6>
|
||
</div>
|
||
<div id="accordion-pane-i3" class="panel-collapse collapse" role="tabpanel" aria-labelledby="accordion-i3">
|
||
<div class="panel-body">
|
||
<p>Ya website ini universal bisa diakses siapapun, namun untuk siswa yang sudah dibuatkan akun akan semakin mudah karena riwayat membaca dapat dilihat untuk meningkatkan kemampuan membaca.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- each panel for accordion -->
|
||
<div class="panel panel-default">
|
||
<div class="panel-heading" role="tab" id="accordion-i4">
|
||
<h6 class="panel-title">
|
||
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#another" href="#accordion-pane-i4" aria-expanded="false">
|
||
Apakah ada data guru pada website admin ?
|
||
<span class="plus-minus"><span></span></span>
|
||
</a>
|
||
</h6>
|
||
</div>
|
||
<div id="accordion-pane-i4" class="panel-collapse collapse" role="tabpanel" aria-labelledby="accordion-i4">
|
||
<div class="panel-body">
|
||
<p>Data guru dan data siswa terdapat pada website admin hal tersebut bertujuan dapat melakukan pemantauan pada masing-masing siswa, dan data guru digunakan sebagai penanggung jawab pembimbing pada setiap siswa.</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Beri Masukan Kepada Guru Admin -->
|
||
<div id="testimonial" class="contact-section section gradiant-background pb-90">
|
||
<div class="container">
|
||
<div class="section-head heading-light text-center">
|
||
<div class="row">
|
||
<div class="col-md-8 col-md-offset-2">
|
||
<h2 class="heading heading-light">Beri Masukan</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="row justify-content-center">
|
||
<div class="container d-flex justify-content-center">
|
||
<div class="fullscreen-container">
|
||
<div class="col-md-6 mx-auto">
|
||
<div class="contact-form white-bg text-center">
|
||
<h3>Pesan Bagi Guru Admin</h3>
|
||
<p>Masukan sangat dibutuhkan agar pengembangan website semakin baik</p>
|
||
<form id="contact-form" class="form-message" action="{{ route('contact.store') }}" method="post">
|
||
@csrf
|
||
<div class="form-results"></div>
|
||
<div class="form-group row fix-gutter-10">
|
||
<div class="form-field col-sm-6 gutter-10 form-m-bttm">
|
||
<input name="contact-name" type="text" placeholder="Nama *" class="form-control required">
|
||
</div>
|
||
<div class="form-field col-sm-6 gutter-10">
|
||
<input name="contact-email" type="email" placeholder="Email *" class="form-control required email">
|
||
</div>
|
||
</div>
|
||
<div class="form-group row fix-gutter-10">
|
||
<div class="form-field col-md-6 gutter-10 form-m-bttm">
|
||
<input name="contact-phone" type="text" placeholder="Nomor Telepon *" class="form-control required">
|
||
</div>
|
||
<div class="form-field col-md-6 gutter-10">
|
||
<input name="contact-subject" type="text" placeholder="Topik *" class="form-control required">
|
||
</div>
|
||
</div>
|
||
<div class="form-group row">
|
||
<div class="form-field col-md-12">
|
||
<textarea name="contact-message" placeholder="Masukan *" class="txtarea form-control required"></textarea>
|
||
</div>
|
||
</div>
|
||
<button type="submit" class="button solid-btn sb-h">Kirim</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
const texts = [
|
||
"Anak bermain di taman", "Ibu sedang memasak", "Saya suka membaca",
|
||
"Dia sedang belajar", "Mobil merah impian", "membaca itu seru",
|
||
"Burung berkicau merdu", "Kucing lucu sekali", "Matematika tambah kurang",
|
||
"Sekolah perlu membaca", "Membaca buku pelajaran", "Olahraga sebelum belajar",
|
||
"Sapi makan rumput", "Sekolah setiap pagi", "Rajin pangkal pandai",
|
||
"Bunga mekar indah", "Menjaga kebersihan", "Menjadi pribadi yang baik",
|
||
"Teruslah belajar", "Cita-cita perlu digapai",
|
||
"Belajar sopan santun", "Membaca dengan rajin", "Belajar tatakrama"
|
||
];
|
||
|
||
function getRandomTexts(array, count) {
|
||
return array.sort(() => Math.random() - 0.5).slice(0, count);
|
||
}
|
||
|
||
const selectedTexts = getRandomTexts(texts, 12);
|
||
let index = 0, totalWords = 0, totalCorrectWords = 0;
|
||
let totalCorrectSentences = 0;
|
||
let startTime, totalTimeSpent = 0, timer;
|
||
let recognitionActive = false;
|
||
|
||
// Array untuk menyimpan akurasi per teks (untuk menghitung pemahaman)
|
||
let textAccuracies = [];
|
||
let predictions = [];
|
||
let actualLabels = [];
|
||
|
||
const randomTextElement = document.getElementById("randomText");
|
||
const recognizedTextElement = document.getElementById("recognizedText");
|
||
const recognizedWrap = document.getElementById("recognizedWrap");
|
||
const accuracyElement = document.getElementById("accuracy");
|
||
const comprehensionElement = document.getElementById("comprehensionLevel");
|
||
const timeTakenElement = document.getElementById("timeTaken");
|
||
const finalScoreElement = document.getElementById("finalScore");
|
||
const evaluationElement = document.getElementById("evaluation");
|
||
const resultSection = document.getElementById("result");
|
||
const startRecognitionButton = document.getElementById("startRecognition");
|
||
const countdownElement = document.getElementById("countdown");
|
||
const nextTextButton = document.getElementById("nextText");
|
||
|
||
let countdownStartTime;
|
||
const totalDuration = 120;
|
||
|
||
function startTimer() {
|
||
clearInterval(timer);
|
||
countdownStartTime = Date.now();
|
||
timer = setInterval(() => {
|
||
const elapsed = Math.floor((Date.now() - countdownStartTime) / 1000);
|
||
const remaining = Math.max(0, totalDuration - elapsed);
|
||
countdownElement.textContent = remaining;
|
||
if (remaining <= 0) {
|
||
stopRecognition();
|
||
clearInterval(timer);
|
||
calculateFinalScore();
|
||
}
|
||
}, 1000);
|
||
}
|
||
|
||
function loadNewText() {
|
||
if (index >= selectedTexts.length) {
|
||
stopRecognition();
|
||
clearInterval(timer);
|
||
calculateFinalScore();
|
||
return;
|
||
}
|
||
randomTextElement.textContent = selectedTexts[index];
|
||
index++;
|
||
startTime = Date.now();
|
||
recognizedTextElement.textContent = "...";
|
||
recognizedWrap.style.display = "none";
|
||
resultSection.style.display = "none";
|
||
nextTextButton.style.visibility = "hidden";
|
||
}
|
||
|
||
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
|
||
if (!SpeechRecognition) {
|
||
alert("Browser Anda tidak mendukung Web Speech API.");
|
||
return;
|
||
}
|
||
|
||
const recognition = new SpeechRecognition();
|
||
recognition.lang = "id-ID";
|
||
recognition.continuous = true;
|
||
recognition.interimResults = false;
|
||
|
||
startRecognitionButton.addEventListener("click", function () {
|
||
if (!recognitionActive) {
|
||
recognizedTextElement.textContent = "Mendengarkan...";
|
||
resultSection.style.display = "none";
|
||
startTimer();
|
||
recognition.start();
|
||
recognitionActive = true;
|
||
}
|
||
});
|
||
|
||
recognition.onresult = function (event) {
|
||
const transcript = event.results[event.results.length - 1][0].transcript.trim();
|
||
if (!transcript) return;
|
||
|
||
recognizedTextElement.textContent = transcript;
|
||
recognizedWrap.style.display = "block";
|
||
|
||
const originalText = randomTextElement.textContent;
|
||
const accuracy = calculateAccuracy(originalText, transcript);
|
||
accuracyElement.textContent = accuracy.toFixed(2);
|
||
|
||
const originalWords = originalText.split(" ");
|
||
totalWords += originalWords.length;
|
||
totalCorrectWords += (accuracy / 100) * originalWords.length;
|
||
|
||
// Simpan akurasi per teks untuk menghitung pemahaman
|
||
textAccuracies.push(accuracy);
|
||
|
||
const timeUsed = (Date.now() - startTime) / 1000;
|
||
totalTimeSpent += timeUsed;
|
||
|
||
// Untuk contoh, asumsikan label sebenarnya bervariasi
|
||
// Dalam implementasi nyata, ambil dari database atau input guru
|
||
// Misalnya, secara acak untuk simulasi: 70% Mahir (1), 30% Tidak Mahir (0)
|
||
actualLabels.push(Math.random() > 0.3 ? 1 : 0);
|
||
|
||
nextTextButton.style.visibility = 'visible';
|
||
};
|
||
|
||
recognition.onend = function () {
|
||
if (recognitionActive) {
|
||
recognition.start();
|
||
}
|
||
};
|
||
|
||
function stopRecognition() {
|
||
recognitionActive = false;
|
||
recognition.stop();
|
||
}
|
||
|
||
function calculateAccuracy(original, spoken) {
|
||
const originalWords = original.toLowerCase().split(" ");
|
||
const spokenWords = spoken.toLowerCase().split(" ");
|
||
let correctCount = 0;
|
||
originalWords.forEach((word, i) => {
|
||
if (spokenWords[i] && spokenWords[i] === word) {
|
||
correctCount++;
|
||
}
|
||
});
|
||
return (correctCount / originalWords.length) * 100;
|
||
}
|
||
|
||
function naiveBayesClassifier(accuracy, comprehension, timeTaken) {
|
||
const diskretisasi = (nilai, batas) => {
|
||
if (nilai >= batas[2]) return "tinggi";
|
||
if (nilai >= batas[1]) return "sedang";
|
||
return "rendah";
|
||
};
|
||
|
||
const accuracyLevel = diskretisasi(accuracy, [0, 50, 80]);
|
||
const comprehensionLevel = diskretisasi(comprehension, [0, 50, 80]);
|
||
const timeLevel = timeTaken <= 40 ? "cepat" : timeTaken <= 80 ? "sedang" : "lambat";
|
||
|
||
const model = {
|
||
mahir: {
|
||
accuracy: { tinggi: 0.7, sedang: 0.2, rendah: 0.1 },
|
||
comprehension: { tinggi: 0.6, sedang: 0.3, rendah: 0.1 },
|
||
time: { cepat: 0.6, sedang: 0.3, lambat: 0.1 },
|
||
prior: 0.5
|
||
},
|
||
tidak_mahir: {
|
||
accuracy: { tinggi: 0.2, sedang: 0.5, rendah: 0.3 },
|
||
comprehension: { tinggi: 0.2, sedang: 0.5, rendah: 0.3 },
|
||
time: { cepat: 0.2, sedang: 0.4, lambat: 0.4 },
|
||
prior: 0.5
|
||
}
|
||
};
|
||
|
||
const hitungProbabilitas = (kelas) => {
|
||
const data = model[kelas];
|
||
return (
|
||
data.accuracy[accuracyLevel] *
|
||
data.comprehension[comprehensionLevel] *
|
||
data.time[timeLevel] *
|
||
data.prior
|
||
);
|
||
};
|
||
|
||
const pMahir = hitungProbabilitas("mahir");
|
||
const pTidakMahir = hitungProbabilitas("tidak_mahir");
|
||
|
||
return pMahir > pTidakMahir ? "Mahir" : "Tidak Mahir";
|
||
}
|
||
|
||
function calculateConfusionMatrix(predictions, actualLabels) {
|
||
let TP = 0, TN = 0, FP = 0, FN = 0;
|
||
|
||
for (let i = 0; i < predictions.length; i++) {
|
||
if (predictions[i] === 1 && actualLabels[i] === 1) TP++; // True Positive
|
||
else if (predictions[i] === 0 && actualLabels[i] === 0) TN++; // True Negative
|
||
else if (predictions[i] === 1 && actualLabels[i] === 0) FP++; // False Positive
|
||
else if (predictions[i] === 0 && actualLabels[i] === 1) FN++; // False Negative
|
||
}
|
||
|
||
return { TP, TN, FP, FN };
|
||
}
|
||
|
||
function calculateMetrics(TP, TN, FP, FN) {
|
||
const accuracy = (TP + TN + FP + FN) > 0 ? (TP + TN) / (TP + TN + FP + FN) * 100 : 0;
|
||
const precision = (TP + FP) > 0 ? (TP / (TP + FP)) * 100 : 0;
|
||
const recall = (TP + FN) > 0 ? (TP / (TP + FN)) * 100 : 0;
|
||
|
||
return { accuracy, precision, recall };
|
||
}
|
||
|
||
function calculateFinalScore() {
|
||
// Hitung akurasi rata-rata
|
||
let avgAccuracy = totalWords > 0 ? (totalCorrectWords / totalWords) * 100 : 0;
|
||
|
||
// Hitung tingkat pemahaman berdasarkan rata-rata akurasi per teks
|
||
let comprehensionScore = textAccuracies.length > 0
|
||
? textAccuracies.reduce((sum, acc) => sum + acc, 0) / textAccuracies.length
|
||
: 0;
|
||
|
||
let totalTimeUsed = parseFloat(totalTimeSpent.toFixed(2));
|
||
|
||
// Hitung prediksi menggunakan nilai akhir
|
||
let evaluation = naiveBayesClassifier(avgAccuracy, comprehensionScore, totalTimeUsed);
|
||
let finalScore = evaluation === "Mahir" ? 1 : 0;
|
||
|
||
// Isi predictions berdasarkan evaluasi akhir
|
||
predictions = Array(textAccuracies.length).fill(finalScore);
|
||
|
||
accuracyElement.textContent = avgAccuracy.toFixed(2);
|
||
comprehensionElement.textContent = comprehensionScore.toFixed(2);
|
||
timeTakenElement.textContent = totalTimeUsed;
|
||
finalScoreElement.textContent = finalScore;
|
||
evaluationElement.textContent = evaluation;
|
||
resultSection.style.display = "block";
|
||
|
||
// Hitung confusion matrix
|
||
const { TP, TN, FP, FN } = calculateConfusionMatrix(predictions, actualLabels);
|
||
|
||
// Hitung metrik
|
||
const { accuracy, precision, recall } = calculateMetrics(TP, TN, FP, FN);
|
||
|
||
// Tampilkan metrik di HTML
|
||
const metricsDiv = document.createElement('div');
|
||
metricsDiv.innerHTML = `
|
||
<h3>Metrik Evaluasi Model</h3>
|
||
<p><strong>Akurasi:</strong> ${accuracy.toFixed(2)}%</p>
|
||
<p><strong>Presisi:</strong> ${precision.toFixed(2)}%</p>
|
||
<p><strong>Recall:</strong> ${recall.toFixed(2)}%</p>
|
||
`;
|
||
resultSection.appendChild(metricsDiv);
|
||
|
||
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
||
const userId = document.querySelector('meta[name="user-id"]')?.getAttribute('content');
|
||
|
||
if (csrfToken && userId) {
|
||
fetch('http://127.0.0.1:8000/admin/riwayat/store', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
'X-CSRF-TOKEN': csrfToken
|
||
},
|
||
body: JSON.stringify({
|
||
user_id: userId,
|
||
nilai_akhir: finalScore,
|
||
tingkat_pemahaman: comprehensionScore,
|
||
akurasi: avgAccuracy,
|
||
waktu_mengerjakan: totalTimeUsed,
|
||
evaluasi: evaluation
|
||
})
|
||
})
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
Swal.fire({
|
||
title: 'Berhasil!',
|
||
text: 'Hasil membaca berhasil disimpan!',
|
||
icon: 'success',
|
||
confirmButtonText: 'OK'
|
||
});
|
||
})
|
||
.catch(error => console.error('Error:', error));
|
||
} else {
|
||
console.error("CSRF token atau User ID tidak ditemukan.");
|
||
}
|
||
}
|
||
|
||
nextTextButton.addEventListener("click", function () {
|
||
nextTextButton.style.visibility = 'hidden';
|
||
loadNewText();
|
||
});
|
||
|
||
loadNewText();
|
||
});
|
||
</script>
|
||
|
||
<script>
|
||
document.addEventListener("DOMContentLoaded", function () {
|
||
let index = 0;
|
||
const videos = document.querySelectorAll(".video-slide");
|
||
const totalVideos = videos.length;
|
||
|
||
function showVideo(i) {
|
||
videos.forEach(video => {
|
||
video.style.display = "none";
|
||
video.style.opacity = "0";
|
||
});
|
||
|
||
videos[i].style.display = "block";
|
||
setTimeout(() => {
|
||
videos[i].style.opacity = "1";
|
||
}, 50);
|
||
|
||
videos[i].play();
|
||
}
|
||
|
||
document.getElementById("prev").addEventListener("click", function () {
|
||
index = (index - 1 + totalVideos) % totalVideos;
|
||
showVideo(index);
|
||
});
|
||
|
||
document.getElementById("next").addEventListener("click", function () {
|
||
index = (index + 1) % totalVideos;
|
||
showVideo(index);
|
||
});
|
||
|
||
showVideo(index);
|
||
});
|
||
</script>
|
||
<script>
|
||
function fetchMessages() {
|
||
fetch("{{ route('messages.index') }}")
|
||
.then(response => response.json())
|
||
.then(data => {
|
||
let messageDropdown = document.querySelector("#messageDropdown .dropdown-menu");
|
||
let badge = document.querySelector("#messageDropdown .badge");
|
||
messageDropdown.innerHTML = ""; // Kosongkan daftar sebelumnya
|
||
|
||
if (data.length > 0) {
|
||
badge.textContent = data.length; // Update badge count
|
||
data.forEach(message => {
|
||
let item = `<a class="dropdown-item">
|
||
<strong>${message.name}</strong><br>
|
||
${message.message.substring(0, 50)}...
|
||
<small class="text-muted d-block">${message.created_at}</small>
|
||
</a>
|
||
<div class="dropdown-divider"></div>`;
|
||
messageDropdown.innerHTML += item;
|
||
});
|
||
} else {
|
||
badge.style.display = "none";
|
||
messageDropdown.innerHTML = `<a class="dropdown-item text-center">Tidak ada pesan</a>`;
|
||
}
|
||
});
|
||
}
|
||
|
||
// Panggil setiap 10 detik
|
||
setInterval(fetchMessages, 10000);
|
||
|
||
</script>
|
||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||
<script>
|
||
$(document).ready(function() {
|
||
$('#contact-form').submit(function(e) {
|
||
e.preventDefault();
|
||
|
||
$.ajax({
|
||
url: "{{ route('contact.store') }}",
|
||
type: "POST",
|
||
data: $(this).serialize(),
|
||
dataType: "json",
|
||
success: function(response) {
|
||
if (response.success) {
|
||
// Tampilkan notifikasi sukses
|
||
Swal.fire({
|
||
icon: 'success',
|
||
title: 'Pesan Terkirim!',
|
||
text: response.message,
|
||
timer: 2000,
|
||
showConfirmButton: false
|
||
});
|
||
|
||
// Reset form setelah submit berhasil
|
||
$('#contact-form')[0].reset();
|
||
|
||
// Perbarui daftar pesan di navbar
|
||
loadMessages();
|
||
}
|
||
},
|
||
error: function(xhr) {
|
||
// Tampilkan notifikasi error jika ada masalah
|
||
Swal.fire({
|
||
icon: 'error',
|
||
title: 'Oops...',
|
||
text: 'Terjadi kesalahan! Coba lagi.'
|
||
});
|
||
}
|
||
});
|
||
});
|
||
|
||
function loadMessages() {
|
||
$.ajax({
|
||
url: "{{ route('messages.index') }}",
|
||
type: "GET",
|
||
success: function(response) {
|
||
$('#messageDropdown .dropdown-menu').html(response);
|
||
}
|
||
});
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/tesseract.js@4.1.1/dist/tesseract.min.js"></script>
|
||
<script>
|
||
// Video Slider
|
||
const slider = document.getElementById('videoSlider');
|
||
const slides = document.querySelectorAll('.video-slide');
|
||
const prev = document.getElementById('prev');
|
||
const next = document.getElementById('next');
|
||
const videoError = document.getElementById('videoError');
|
||
let currentSlide = 0;
|
||
|
||
// Cek apakah video dapat dimuat
|
||
slides.forEach((slide, index) => {
|
||
const source = slide.querySelector('source');
|
||
const videoPath = source.getAttribute('src');
|
||
const video = document.createElement('video');
|
||
video.src = videoPath;
|
||
video.onloadeddata = () => {
|
||
console.log(`Video ${videoPath} dimuat dengan sukses.`);
|
||
};
|
||
video.onerror = () => {
|
||
videoError.innerText = `Gagal memuat video: ${videoPath}. Pastikan file ada di folder yang benar.`;
|
||
};
|
||
});
|
||
|
||
function updateSlider() {
|
||
// Hentikan semua video dan reset ke awal
|
||
slides.forEach(slide => {
|
||
slide.pause();
|
||
slide.currentTime = 0;
|
||
slide.style.display = 'none'; // Pastikan slide non-aktif disembunyikan
|
||
slide.style.visibility = 'hidden';
|
||
});
|
||
|
||
// Tampilkan slide aktif
|
||
slides[currentSlide].style.display = 'block';
|
||
slides[currentSlide].style.visibility = 'visible';
|
||
slides[currentSlide].classList.add('active');
|
||
|
||
// Geser slider
|
||
slider.style.transform = `translateX(0)`; // Tidak perlu translateX karena hanya satu slide yang terlihat
|
||
|
||
// Mainkan video aktif
|
||
slides[currentSlide].play().catch(err => {
|
||
console.error('Error playing video:', err);
|
||
videoError.innerText = 'Gagal memutar video. Pastikan format didukung.';
|
||
});
|
||
|
||
console.log(`Current slide: ${currentSlide}, Video: ${slides[currentSlide].querySelector('source').getAttribute('src')}`);
|
||
}
|
||
|
||
next.addEventListener('click', () => {
|
||
slides[currentSlide].classList.remove('active');
|
||
currentSlide = (currentSlide + 1) % slides.length;
|
||
updateSlider();
|
||
});
|
||
|
||
prev.addEventListener('click', () => {
|
||
slides[currentSlide].classList.remove('active');
|
||
currentSlide = (currentSlide - 1 + slides.length) % slides.length;
|
||
updateSlider();
|
||
});
|
||
|
||
// Inisialisasi slider
|
||
updateSlider();
|
||
|
||
// Canvas Drawing
|
||
const canvas = document.getElementById('writingCanvas');
|
||
const ctx = canvas.getContext('2d');
|
||
let isDrawing = false;
|
||
|
||
canvas.addEventListener('mousedown', startDrawing);
|
||
canvas.addEventListener('mousemove', draw);
|
||
canvas.addEventListener('mouseup', stopDrawing);
|
||
canvas.addEventListener('mouseout', stopDrawing);
|
||
|
||
function startDrawing(e) {
|
||
isDrawing = true;
|
||
ctx.beginPath();
|
||
ctx.moveTo(e.offsetX, e.offsetY);
|
||
}
|
||
|
||
function draw(e) {
|
||
if (!isDrawing) return;
|
||
ctx.lineWidth = 10;
|
||
ctx.lineCap = 'round';
|
||
ctx.strokeStyle = 'black';
|
||
ctx.lineTo(e.offsetX, e.offsetY);
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(e.offsetX, e.offsetY);
|
||
}
|
||
|
||
function stopDrawing() {
|
||
isDrawing = false;
|
||
ctx.beginPath();
|
||
}
|
||
|
||
// Clear Canvas
|
||
document.getElementById('clearCanvas').addEventListener('click', () => {
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
document.getElementById('recognitionResult').innerText = '';
|
||
});
|
||
|
||
// Image Preprocessing
|
||
function preprocessImage(canvas) {
|
||
const tempCanvas = document.createElement('canvas');
|
||
const tempCtx = tempCanvas.getContext('2d');
|
||
tempCanvas.width = canvas.width;
|
||
tempCanvas.height = canvas.height;
|
||
|
||
tempCtx.drawImage(canvas, 0, 0);
|
||
const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
|
||
const data = imageData.data;
|
||
|
||
// Konversi ke grayscale
|
||
for (let i = 0; i < data.length; i += 4) {
|
||
const avg = (data[i] + data[i + 1] + data[i + 2]) / 3;
|
||
data[i] = data[i + 1] = data[i + 2] = avg;
|
||
}
|
||
|
||
// Thresholding untuk meningkatkan kontras
|
||
const threshold = 200;
|
||
for (let i = 0; i < data.length; i += 4) {
|
||
const value = data[i] < threshold ? 0 : 255;
|
||
data[i] = data[i + 1] = data[i + 2] = value;
|
||
}
|
||
|
||
tempCtx.putImageData(imageData, 0, 0);
|
||
return tempCanvas.toDataURL('image/png');
|
||
}
|
||
|
||
// Detect Writing
|
||
document.getElementById('detectButton').addEventListener('click', () => {
|
||
const imageUrl = preprocessImage(canvas);
|
||
|
||
Tesseract.recognize(
|
||
imageUrl,
|
||
'eng',
|
||
{
|
||
logger: m => console.log(m),
|
||
tessedit_char_whitelist: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ',
|
||
tessedit_pageseg_mode: 6,
|
||
tessedit_ocr_engine_mode: 1,
|
||
}
|
||
).then(({ data: { text } }) => {
|
||
const cleanedText = text.trim();
|
||
document.getElementById('recognitionResult').innerText = cleanedText
|
||
? `Hasil Deteksi: ${cleanedText}`
|
||
: 'Tidak dapat mendeteksi tulisan. Tulis dengan lebih jelas.';
|
||
}).catch(err => {
|
||
console.error('OCR Error:', err);
|
||
document.getElementById('recognitionResult').innerText = 'Gagal mendeteksi. Coba lagi.';
|
||
});
|
||
});
|
||
</script>
|
||
|
||
@endsection
|
||
|
||
@section('footer')
|
||
<!-- Start .footer-section -->
|
||
<div class="footer-section section">
|
||
<div class="container">
|
||
<div class="row text-center">
|
||
<div class="col-md-12">
|
||
<ul class="footer-navigation inline-list">
|
||
<li><a class="nav-item" href="#home">Beranda</a></li>
|
||
<li><a class="nav-item" href="#huruf">Kenali Huruf</a></li>
|
||
<li><a class="nav-item" href="#about">Belajar</a></li>
|
||
<li><a class="nav-item" href="#features">Baca</a></li>
|
||
<li><a class="nav-item" href="#students">Riwayat</a></li>
|
||
<li><a class="nav-item" href="#another">Bantuan</a></li>
|
||
<li><a class="nav-item" href="#testimonial">Pesan</a></li>
|
||
</ul>
|
||
<ul class="social-list inline-list">
|
||
<li><a href="#"><em class="fa fa-facebook"></em></a></li>
|
||
<li><a href="#"><em class="fa fa-twitter"></em></a></li>
|
||
<li><a href="#"><em class="fa fa-linkedin"></em></a></li>
|
||
<li><a href="#"><em class="fa fa-instagram"></em></a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
@endsection |