[update] Counting Fixing with New Logic

This commit is contained in:
Zhaqian Rouf Alfauzi 2025-02-08 21:10:42 +07:00
parent 078536b0d9
commit 5aa5f680ab
22 changed files with 1727 additions and 168 deletions

View File

@ -20,6 +20,15 @@ public function index()
return view('pages.admin.add-admin', compact('admins'));
}
public function showSantri()
{
// Ambil semua user yang ber-role admin
$santris = User::where('role', 'santri')->get();
return view('pages.admin.add-santri', compact('santris'));
}
public function dashboard()
{
@ -63,6 +72,15 @@ public function destroy($id)
return redirect()->route('admin.add')->with('success', 'Admin berhasil dihapus.');
}
public function destroySantri($id)
{
$admin = User::findOrFail($id);
$admin->delete();
return redirect()->route('santri.add')->with('success', 'Santri berhasil dihapus.');
}
/**
* Tampilkan form ubah password (Admin).
*/

View File

@ -0,0 +1,48 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class ClassifiactionController extends Controller
{
/**
* Menampilkan data ujian (examData)
*
* @return \Illuminate\View\View
*/
public function examData()
{
// Tambahkan logika untuk mengambil data ujian dari database jika diperlukan
// Contoh: $data = Exam::all();
// Return view dengan data yang diperlukan
return view('pages.admin.exam-data'); // Pastikan view ini telah dibuat
}
/**
* Menampilkan data pelatihan (trainData)
*
* @return \Illuminate\View\View
*/
public function trainData()
{
// Tambahkan logika untuk mengambil data pelatihan
// Contoh: $data = Train::all();
return view('pages.admin.train-data'); // Pastikan view ini telah dibuat
}
/**
* Menampilkan hasil klasifikasi (classificationResult)
*
* @return \Illuminate\View\View
*/
public function classificationResult()
{
// Tambahkan logika untuk mengolah dan menampilkan hasil klasifikasi
// Misalnya, menjalankan algoritma atau mengambil data dari model
return view('pages.admin.class-result'); // Pastikan view ini telah dibuat
}
}

View File

@ -6,6 +6,7 @@
use App\Models\Riwayat;
use Carbon\Carbon;
use Illuminate\Support\Facades\Auth;
use App\Models\User;
class HitungController extends Controller
{
@ -29,28 +30,28 @@ public function processCounting(Request $request)
{
$request->validate([
'year' => 'required|integer',
'alquran' => 'required|integer|min:0',
'alhadis' => 'required|integer|min:0',
'alquran' => 'required|integer|min:0|max:606', // maksimal 606 halaman
'alhadis' => 'required|integer|min:0|max:1997', // maksimal 1997 halaman
]);
// Buat objek Carbon dari "1 Januari [year angkatan]"
// Buat objek Carbon dari "1 Januari [tahun angkatan]"
$start = Carbon::create($request->year, 1, 1); // 1 Jan tahun angkatan
$now = Carbon::today(); // Hari ini (tanggal saja)
$x = $start->diffInDays($now);
// Jumlah halaman diisi
// Jumlah halaman yang diisi (alquran + alhadis)
$y = $request->alquran + $request->alhadis;
// Default nilai n dan status
$n = 0;
$status = 'Tidak Tercapai';
// 1) Jika y >= 2603, langsung "Tercapai"
// 1) Jika jumlah halaman (y) >= 2603, langsung "Tercapai"
if ($y >= 2603) {
$n = 100; // atau nilai lain yang Anda inginkan
$n = 100; // Anda dapat mengganti nilai sesuai kebutuhan
$status = 'Tercapai';
}
// 2) Jika y < 2603 dan x > 0, hitung kecepatan
// 2) Jika y < 2603 dan x > 0, hitung kecepatan pencapaian
elseif ($x > 0) {
$userSpeed = $y / $x;
$targetSpeed = 2603 / 1095;
@ -69,11 +70,6 @@ public function processCounting(Request $request)
'status' => $status,
]);
// Ambil entri terbaru untuk ditampilkan
$latest = Riwayat::where('user_id', Auth::id())
->orderBy('created_at', 'desc')
->first();
// Kembali ke halaman counting dengan pesan sukses
return redirect()->route('countingSantri')
->with('success', 'Data berhasil dihitung dan disimpan!');
@ -89,6 +85,9 @@ public function history()
->orderBy('created_at', 'desc')
->get();
return view('pages.santri.history', compact('riwayat'));
// Ambil data admin (sesuaikan query dengan struktur database Anda)
$admins = User::where('role', 'admin')->get();
return view('pages.santri.history', compact('riwayat', 'admins'));
}
}

View File

@ -7,47 +7,68 @@
class MunaqosahController extends Controller
{
/**
* Hapus data riwayat berdasarkan ID.
*/
// Method untuk menghapus data riwayat (digunakan di admin dan santri)
public function destroy($id)
{
// Cari data Riwayat
$riwayat = Riwayat::findOrFail($id);
// Hapus
$riwayat->delete();
// Redirect balik dengan pesan sukses
return redirect()->back()->with('success', 'Data riwayat berhasil dihapus.');
}
/**
* Kirim data riwayat ke admin (misalnya tandai "is_sent" atau terserah logika Anda).
* Kirim data riwayat ke admin yang dipilih.
*/
public function send($id)
public function send(Request $request, $id)
{
// Cari data Riwayat
$riwayat = Riwayat::findOrFail($id);
$request->validate([
'admin_id' => 'required|exists:users,id', // pastikan admin_id valid
]);
// Misalnya Anda punya kolom "sent_to_admin" (boolean) atau "sent_at" (datetime) untuk menandai bahwa data sudah dikirim
// Contoh: kita set "sent_at" menjadi sekarang
$riwayat = Riwayat::findOrFail($id);
$riwayat->admin_id = $request->admin_id;
$riwayat->sent_at = now();
$riwayat->munaqosah_status = 'Sedang di Verifikasi';
$riwayat->save();
// Redirect balik dengan pesan sukses
return redirect()->back()->with('success', 'Data berhasil dikirim ke admin.');
}
// Contoh: Tampilkan semua Riwayat yang "sent_at" != null
public function showMunaqosah()
{
$riwayat = Riwayat::whereNotNull('sent_at')
->orderBy('created_at', 'desc')
->get();
/**
* Tampilkan data munaqosah untuk admin.
*/
public function showMunaqosah()
{
$riwayat = Riwayat::whereNotNull('sent_at')
->where('admin_id', auth()->id()) // hanya data untuk admin yang sedang login
->orderBy('created_at', 'desc')
->get();
return view('pages.admin.data-santri', compact('riwayat'));
}
return view('pages.admin.data-santri', compact('riwayat'));
}
/**
* Verifikasi data munaqosah.
*/
public function verify($id)
{
$riwayat = Riwayat::findOrFail($id);
$riwayat->munaqosah_status = 'Terverifikasi';
$riwayat->save();
return redirect()->back()->with('success', 'Data telah diverifikasi.');
}
/**
* Tolak data munaqosah.
*/
public function reject($id)
{
$riwayat = Riwayat::findOrFail($id);
$riwayat->munaqosah_status = 'Ditolak';
$riwayat->save();
return redirect()->back()->with('success', 'Data telah ditolak.');
}
}

View File

@ -19,6 +19,8 @@ class Riwayat extends Model
'nilai_n',
'status',
'sent_at',
'admin_id',
'munaqosah_status',
];
/**

View File

@ -9,7 +9,8 @@
"guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10",
"laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8"
"laravel/tinker": "^2.8",
"maatwebsite/excel": "^3.1"
},
"require-dev": {
"fakerphp/faker": "^1.9.1",

595
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "9c491b8531eec05ba41a11d9276a5749",
"content-hash": "fd4872b22b5625c027fc603f79579a78",
"packages": [
{
"name": "brick/math",
@ -135,6 +135,166 @@
],
"time": "2023-12-11T17:09:12+00:00"
},
{
"name": "composer/pcre",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"reference": "b2bed4734f0cc156ee1fe9c0da2550420d99a21e",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0"
},
"conflict": {
"phpstan/phpstan": "<1.11.10"
},
"require-dev": {
"phpstan/phpstan": "^1.12 || ^2",
"phpstan/phpstan-strict-rules": "^1 || ^2",
"phpunit/phpunit": "^8 || ^9"
},
"type": "library",
"extra": {
"phpstan": {
"includes": [
"extension.neon"
]
},
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Pcre\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
}
],
"description": "PCRE wrapping library that offers type-safe preg_* replacements.",
"keywords": [
"PCRE",
"preg",
"regex",
"regular expression"
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.3.2"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-11-12T16:29:46+00:00"
},
{
"name": "composer/semver",
"version": "3.4.3",
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/semver/zipball/4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"reference": "4313d26ada5e0c4edfbd1dc481a92ff7bff91f12",
"shasum": ""
},
"require": {
"php": "^5.3.2 || ^7.0 || ^8.0"
},
"require-dev": {
"phpstan/phpstan": "^1.11",
"symfony/phpunit-bridge": "^3 || ^7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Semver\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nils Adermann",
"email": "naderman@naderman.de",
"homepage": "http://www.naderman.de"
},
{
"name": "Jordi Boggiano",
"email": "j.boggiano@seld.be",
"homepage": "http://seld.be"
},
{
"name": "Rob Bast",
"email": "rob.bast@gmail.com",
"homepage": "http://robbast.nl"
}
],
"description": "Semver library that offers utilities, version constraint parsing and validation.",
"keywords": [
"semantic",
"semver",
"validation",
"versioning"
],
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
"source": "https://github.com/composer/semver/tree/3.4.3"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2024-09-19T14:15:21+00:00"
},
{
"name": "dflydev/dot-access-data",
"version": "v3.0.3",
@ -506,6 +666,67 @@
],
"time": "2023-10-06T06:47:41+00:00"
},
{
"name": "ezyang/htmlpurifier",
"version": "v4.18.0",
"source": {
"type": "git",
"url": "https://github.com/ezyang/htmlpurifier.git",
"reference": "cb56001e54359df7ae76dc522d08845dc741621b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b",
"reference": "cb56001e54359df7ae76dc522d08845dc741621b",
"shasum": ""
},
"require": {
"php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0"
},
"require-dev": {
"cerdic/css-tidy": "^1.7 || ^2.0",
"simpletest/simpletest": "dev-master"
},
"suggest": {
"cerdic/css-tidy": "If you want to use the filter 'Filter.ExtractStyleBlocks'.",
"ext-bcmath": "Used for unit conversion and imagecrash protection",
"ext-iconv": "Converts text to and from non-UTF-8 encodings",
"ext-tidy": "Used for pretty-printing HTML"
},
"type": "library",
"autoload": {
"files": [
"library/HTMLPurifier.composer.php"
],
"psr-0": {
"HTMLPurifier": "library/"
},
"exclude-from-classmap": [
"/library/HTMLPurifier/Language/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"LGPL-2.1-or-later"
],
"authors": [
{
"name": "Edward Z. Yang",
"email": "admin@htmlpurifier.org",
"homepage": "http://ezyang.com"
}
],
"description": "Standards compliant HTML filter written in PHP",
"homepage": "http://htmlpurifier.org/",
"keywords": [
"html"
],
"support": {
"issues": "https://github.com/ezyang/htmlpurifier/issues",
"source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0"
},
"time": "2024-11-01T03:51:45+00:00"
},
{
"name": "fruitcake/php-cors",
"version": "v1.3.0",
@ -1884,6 +2105,272 @@
],
"time": "2024-09-21T08:32:55+00:00"
},
{
"name": "maatwebsite/excel",
"version": "3.1.62",
"source": {
"type": "git",
"url": "https://github.com/SpartnerNL/Laravel-Excel.git",
"reference": "decfb9140161fcc117571e47e35ddf27983189ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/decfb9140161fcc117571e47e35ddf27983189ce",
"reference": "decfb9140161fcc117571e47e35ddf27983189ce",
"shasum": ""
},
"require": {
"composer/semver": "^3.3",
"ext-json": "*",
"illuminate/support": "5.8.*||^6.0||^7.0||^8.0||^9.0||^10.0||^11.0",
"php": "^7.0||^8.0",
"phpoffice/phpspreadsheet": "^1.29.7",
"psr/simple-cache": "^1.0||^2.0||^3.0"
},
"require-dev": {
"laravel/scout": "^7.0||^8.0||^9.0||^10.0",
"orchestra/testbench": "^6.0||^7.0||^8.0||^9.0",
"predis/predis": "^1.1"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Excel": "Maatwebsite\\Excel\\Facades\\Excel"
},
"providers": [
"Maatwebsite\\Excel\\ExcelServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Maatwebsite\\Excel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Patrick Brouwers",
"email": "patrick@spartner.nl"
}
],
"description": "Supercharged Excel exports and imports in Laravel",
"keywords": [
"PHPExcel",
"batch",
"csv",
"excel",
"export",
"import",
"laravel",
"php",
"phpspreadsheet"
],
"support": {
"issues": "https://github.com/SpartnerNL/Laravel-Excel/issues",
"source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.62"
},
"funding": [
{
"url": "https://laravel-excel.com/commercial-support",
"type": "custom"
},
{
"url": "https://github.com/patrickbrouwers",
"type": "github"
}
],
"time": "2025-01-04T12:14:36+00:00"
},
{
"name": "maennchen/zipstream-php",
"version": "3.1.2",
"source": {
"type": "git",
"url": "https://github.com/maennchen/ZipStream-PHP.git",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"reference": "aeadcf5c412332eb426c0f9b4485f6accba2a99f",
"shasum": ""
},
"require": {
"ext-mbstring": "*",
"ext-zlib": "*",
"php-64bit": "^8.2"
},
"require-dev": {
"brianium/paratest": "^7.7",
"ext-zip": "*",
"friendsofphp/php-cs-fixer": "^3.16",
"guzzlehttp/guzzle": "^7.5",
"mikey179/vfsstream": "^1.6",
"php-coveralls/php-coveralls": "^2.5",
"phpunit/phpunit": "^11.0",
"vimeo/psalm": "^6.0"
},
"suggest": {
"guzzlehttp/psr7": "^2.4",
"psr/http-message": "^2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"ZipStream\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paul Duncan",
"email": "pabs@pablotron.org"
},
{
"name": "Jonatan Männchen",
"email": "jonatan@maennchen.ch"
},
{
"name": "Jesse Donat",
"email": "donatj@gmail.com"
},
{
"name": "András Kolesár",
"email": "kolesar@kolesar.hu"
}
],
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
"keywords": [
"stream",
"zip"
],
"support": {
"issues": "https://github.com/maennchen/ZipStream-PHP/issues",
"source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.2"
},
"funding": [
{
"url": "https://github.com/maennchen",
"type": "github"
}
],
"time": "2025-01-27T12:07:53+00:00"
},
{
"name": "markbaker/complex",
"version": "3.0.2",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPComplex.git",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"reference": "95c56caa1cf5c766ad6d65b6344b807c1e8405b9",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Complex\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@lange.demon.co.uk"
}
],
"description": "PHP Class for working with complex numbers",
"homepage": "https://github.com/MarkBaker/PHPComplex",
"keywords": [
"complex",
"mathematics"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPComplex/issues",
"source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.2"
},
"time": "2022-12-06T16:21:08+00:00"
},
{
"name": "markbaker/matrix",
"version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/MarkBaker/PHPMatrix.git",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/728434227fe21be27ff6d86621a1b13107a2562c",
"reference": "728434227fe21be27ff6d86621a1b13107a2562c",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-master",
"phpcompatibility/php-compatibility": "^9.3",
"phpdocumentor/phpdocumentor": "2.*",
"phploc/phploc": "^4.0",
"phpmd/phpmd": "2.*",
"phpunit/phpunit": "^7.0 || ^8.0 || ^9.0",
"sebastian/phpcpd": "^4.0",
"squizlabs/php_codesniffer": "^3.7"
},
"type": "library",
"autoload": {
"psr-4": {
"Matrix\\": "classes/src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Baker",
"email": "mark@demon-angel.eu"
}
],
"description": "PHP Class for working with matrices",
"homepage": "https://github.com/MarkBaker/PHPMatrix",
"keywords": [
"mathematics",
"matrix",
"vector"
],
"support": {
"issues": "https://github.com/MarkBaker/PHPMatrix/issues",
"source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.1"
},
"time": "2022-12-02T22:17:43+00:00"
},
{
"name": "monolog/monolog",
"version": "3.7.0",
@ -2384,6 +2871,112 @@
],
"time": "2023-02-08T01:06:31+00:00"
},
{
"name": "phpoffice/phpspreadsheet",
"version": "1.29.10",
"source": {
"type": "git",
"url": "https://github.com/PHPOffice/PhpSpreadsheet.git",
"reference": "c80041b1628c4f18030407134fe88303661d4e4e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/c80041b1628c4f18030407134fe88303661d4e4e",
"reference": "c80041b1628c4f18030407134fe88303661d4e4e",
"shasum": ""
},
"require": {
"composer/pcre": "^1||^2||^3",
"ext-ctype": "*",
"ext-dom": "*",
"ext-fileinfo": "*",
"ext-gd": "*",
"ext-iconv": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlreader": "*",
"ext-xmlwriter": "*",
"ext-zip": "*",
"ext-zlib": "*",
"ezyang/htmlpurifier": "^4.15",
"maennchen/zipstream-php": "^2.1 || ^3.0",
"markbaker/complex": "^3.0",
"markbaker/matrix": "^3.0",
"php": "^7.4 || ^8.0",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "dev-main",
"dompdf/dompdf": "^1.0 || ^2.0 || ^3.0",
"friendsofphp/php-cs-fixer": "^3.2",
"mitoteam/jpgraph": "^10.3",
"mpdf/mpdf": "^8.1.1",
"phpcompatibility/php-compatibility": "^9.3",
"phpstan/phpstan": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.0",
"squizlabs/php_codesniffer": "^3.7",
"tecnickcom/tcpdf": "^6.5"
},
"suggest": {
"dompdf/dompdf": "Option for rendering PDF with PDF Writer",
"ext-intl": "PHP Internationalization Functions",
"mitoteam/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers",
"mpdf/mpdf": "Option for rendering PDF with PDF Writer",
"tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer"
},
"type": "library",
"autoload": {
"psr-4": {
"PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maarten Balliauw",
"homepage": "https://blog.maartenballiauw.be"
},
{
"name": "Mark Baker",
"homepage": "https://markbakeruk.net"
},
{
"name": "Franck Lefevre",
"homepage": "https://rootslabs.net"
},
{
"name": "Erik Tilt"
},
{
"name": "Adrien Crivelli"
}
],
"description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine",
"homepage": "https://github.com/PHPOffice/PhpSpreadsheet",
"keywords": [
"OpenXML",
"excel",
"gnumeric",
"ods",
"php",
"spreadsheet",
"xls",
"xlsx"
],
"support": {
"issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues",
"source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.29.10"
},
"time": "2025-02-08T02:56:14+00:00"
},
{
"name": "phpoption/phpoption",
"version": "1.9.3",

View File

@ -0,0 +1,24 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
public function up(): void
{
Schema::table('riwayats', function (Blueprint $table) {
$table->unsignedBigInteger('admin_id')->nullable()->after('user_id');
$table->string('munaqosah_status')->nullable()->after('status');
// Jika perlu, tambahkan relasi foreign key
// $table->foreign('admin_id')->references('id')->on('users')->onDelete('set null');
});
}
public function down(): void
{
Schema::table('riwayats', function (Blueprint $table) {
$table->dropColumn(['admin_id', 'munaqosah_status']);
});
}
};

View File

@ -0,0 +1,27 @@
<?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('santris', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('santris');
}
};

View File

@ -14,16 +14,16 @@ public function run()
User::create([
'name' => null, // admin tidak butuh name, boleh dikosongi
'nis' => null, // admin tidak butuh NIS
'email' => 'admin@example.com',
'email' => 'muhammadfirdaus@gmail.com',
'password' => Hash::make('123456'), // password: 123456
'role' => 'admin'
]);
// Santri account
User::create([
'name' => 'Santri Testing',
'nis' => '12345',
'email' => 'santri@example.com',
'name' => 'Zhaqian',
'nis' => 'A13411',
'email' => 'santri@gmail.com',
'password' => Hash::make('123456'), // password: 123456
'role' => 'santri',
'jenis_kelamin' => 'Laki-laki',

View File

@ -22,7 +22,11 @@
<div class="card">
<div class="card-body">
<h5 class="card-title">Data Admin</h5>
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
{{-- Tabel Admin --}}
<table id="addAdminTable" class="table">
<thead>
@ -37,16 +41,33 @@
<tr>
<td>{{ $index+1 }}</td>
<td>{{ $admin->email }}</td>
<td>
<form action="{{ route('admin.delete', $admin->id) }}" method="POST"
onsubmit="return confirm('Yakin ingin menghapus admin ini?')">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm" type="submit">
<i class='bx bx-trash'></i>
</button>
</form>
</td>
<td>
<form action="{{ route('admin.delete', $admin->id) }}" method="POST" id="deleteForm{{ $admin->id }}">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm" type="button" onclick="confirmDelete({{ $admin->id }})">
<i class='bx bx-trash'></i>
</button>
</form>
</td>
<script>
function confirmDelete(adminId) {
Swal.fire({
title: 'Yakin ingin menghapus admin ini?',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#d33',
cancelButtonColor: '#3085d6',
confirmButtonText: 'Ya, hapus!',
cancelButtonText: 'Batal'
}).then((result) => {
if (result.isConfirmed) {
document.getElementById('deleteForm' + adminId).submit();
}
});
}
</script>
</tr>
@endforeach
</tbody>
@ -56,6 +77,9 @@
href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<!-- SweetAlert2 CSS & JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>
<script>
$(document).ready(function () {
$('#addAdminTable').DataTable({

View File

@ -0,0 +1,110 @@
@extends('layouts.app-admin')
<title>Data Santri | SR Klasifikasi</title>
@section('content')
<main id="main" class="main">
<div class="row">
<div class="pagetitle d-flex justify-content-between align-items-center">
<h1>Santri</h1>
</div>
<nav>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Admin</a></li>
<li class="breadcrumb-item active">Data Santri</li>
</ol>
</nav>
<div class="col-12 dashboard">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Daftar Santri</h5>
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
{{-- Tabel Data Santri --}}
<table id="addSantriTable" class="table">
<thead>
<tr>
<th>No</th>
<th>Nama</th>
<th>Email</th>
<th>Asal Daerah</th>
<th>Jenis Kelamin</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($santris as $index => $santri)
<tr>
<td>{{ $index + 1 }}</td>
<td>{{ $santri->name }}</td>
<td>{{ $santri->email }}</td>
<td>{{ $santri->asal_daerah }}</td>
<td>{{ $santri->jenis_kelamin }}</td>
<td>
<form action="{{ route('santri.delete', $santri->id) }}" method="POST"
onsubmit="return confirmDelete({{ $santri->id }})">
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm" type="button"
onclick="confirmDelete({{ $santri->id }})">
<i class='bx bx-trash'></i>
</button>
</form>
</td>
</tr>
@endforeach
</tbody>
</table>
<!-- DataTables CSS & JS -->
<!-- SweetAlert2 CSS & JS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.css">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>
<link rel="stylesheet"
href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$('#addSantriTable').DataTable({
"language": {
"search": "Cari:",
"lengthMenu": "Tampilkan _MENU_ data",
"zeroRecords": "Tidak ada data yang cocok",
"info": "Menampilkan _START_ sampai _END_ dari _TOTAL_ data",
"infoEmpty": "Tidak ada data tersedia",
"infoFiltered": "(disaring dari _MAX_ total data)"
}
});
});
function confirmDelete(santriId) {
Swal.fire({
title: 'Yakin ingin menghapus Santri ini?',
text: 'Data yang dihapus tidak bisa dikembalikan!',
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Ya, hapus!',
cancelButtonText: 'Batal',
reverseButtons: true
}).then((result) => {
if (result.isConfirmed) {
// Submit the form if confirmed
document.getElementById('deleteSantriForm' + santriId).submit();
}
});
}
</script>
</div>
</div>
</div>
</div>
</div>
</main>
@endsection

View File

@ -17,11 +17,221 @@
<div class="col-12 dashboard">
<div class="row">
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<div class="col-12 dashboard">
<div class="row">
<div class="col-xxl-6 col-md-6">
<div class="card info-card sales-card">
<div class="card-body">
<h5 class="card-title">Santri <span>| Jumlah</span></h5>
<div class="d-flex align-items-center">
<div
class="card-icon rounded-circle d-flex align-items-center justify-content-center">
<i class='bx bx-universal-access'></i>
</div>
<div class="ps-3">
<h6>400</h6>
</div>
</div>
</div>
</div>
</div>
<div class="col-xxl-6 col-md-6 mb-3">
<div class="card info-card revenue-card">
<div class="card-body">
<h5 class="card-title">Lulusan <span>| Jumlah</span></h5>
<div class="d-flex align-items-center">
<div
class="card-icon rounded-circle d-flex align-items-center justify-content-center">
<i class='bx bx-child'></i>
</div>
<div class="ps-3">
<h6>400</h6>
</div>
</div>
</div>
</div>
</div>
<div class="col-12">
<div class="card">
<div class="card-body pb-0">
<h5 class="card-title">Klasifikasi</h5>
<div id="trafficChart" style="min-height: 400px;" class="echart"></div>
<script>
document.addEventListener("DOMContentLoaded", () => {
echarts.init(document.querySelector("#trafficChart")).setOption({
tooltip: {
trigger: 'item'
},
legend: {
top: '5%',
left: 'center'
},
series: [{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
emphasis: {
label: {
show: true,
fontSize: '18',
fontWeight: 'bold'
}
},
labelLine: {
show: false
},
data: [{
value: 1048,
name: 'Tepat Waktu'
},
{
value: 735,
name: 'Terlambat'
},
]
}]
});
});
</script>
</div>
</div><!-- End Website Traffic -->
</div>
<div class="col-xxl-6 col-md-6 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title justify-content-center d-flex">Jenis Kelamin</h5>
<div id="jenisKelamin"></div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
new ApexCharts(document.querySelector("#jenisKelamin"), {
series: [{
name: 'Laki Laki',
data: [21,22,23,24,25],
}, {
name: 'Perempuan',
data: [11, 32, 45,32, 41]
}],
chart: {
height: 350,
type: 'area',
toolbar: {
show: false
},
},
markers: {
size: 4
},
colors: ['#4154f1', '#2eca6a'],
fill: {
type: "gradient",
gradient: {
shadeIntensity: 1,
opacityFrom: 0.3,
opacityTo: 0.4,
stops: [0, 90, 100]
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: 'smooth',
width: 2
},
xaxis: {
type: 'year',
categories: ["2021","2022", "2023", "2024", "2025"
]
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm'
},
}
}).render();
});
</script>
<!-- End Line Chart -->
</div>
<div class="col-xxl-6 col-md-6">
<div class="card">
<div class="card-body">
<h5 class="card-title justify-content-center d-flex">Asal Daerah</h5>
<div id="asalDaerah"></div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () =>
{
new ApexCharts(document.querySelector("#asalDaerah"), {
series: [{
name: 'Luar Jawa',
data: [21,22,23,24,25],
}, {
name: 'Jawa',
data: [11, 32, 45,32, 41]
}],
chart: {
height: 350,
type: 'area',
toolbar: {
show: false
},
},
markers: {
size: 4
},
colors: ['#F14141FF', '#C72ECAFF'],
fill: {
type: "gradient",
gradient: {
shadeIntensity: 1,
opacityFrom: 0.3,
opacityTo: 0.4,
stops: [0, 90, 100]
}
},
dataLabels: {
enabled: false
},
stroke: {
curve: 'smooth',
width: 2
},
xaxis: {
type: 'year',
categories: ["2021","2022", "2023", "2024", "2025"
]
},
tooltip: {
x: {
format: 'dd/MM/yy HH:mm'
},
}
}).render();
});
</script>
</div>
</div>
@endif
<!-- Waktu Card -->
</div>
<div class="col-xxl-12 col-md-12">
<div class="row">
<!-- Card Tanggal -->

View File

@ -53,14 +53,76 @@
<td>{{ number_format($item->nilai_n, 2) }}</td>
<td>{{ $item->status }}</td>
<td>
<a href="#" class="btn btn-success btn-sm">
<i class='bx bxs-check-circle'></i> Verifikasi
</a>
@if($item->munaqosah_status === 'Sedang di Verifikasi')
<!-- Jika belum ada keputusan, tampilkan tombol Verifikasi, Tolak, dan Delete -->
<!-- Tombol Verifikasi -->
<form action="{{ route('munaqosah.verify', $item->id) }}" method="POST" style="display:inline;">
@csrf
<button type="submit" class="btn btn-success btn-sm">
<i class='bx bxs-check-circle'></i> Verifikasi
</button>
</form>
<!-- Tombol Tolak -->
<form action="{{ route('munaqosah.reject', $item->id) }}" method="POST" style="display:inline;">
@csrf
<button type="submit" class="btn btn-warning btn-sm">
<i class='bx bxs-x-circle'></i> Tolak
</button>
</form>
<!-- Tombol Delete dengan SweetAlert -->
<button class="btn btn-danger btn-sm btn-delete" data-id="{{ $item->id }}">
<i class='bx bxs-trash'></i> Delete
</button>
@else
<!-- Jika sudah ada keputusan (verified atau ditolak), tampilkan badge "Selesai" -->
<span class="badge bg-info">Selesai</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
<!-- Sertakan SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).on('click', '.btn-delete', function(e){
e.preventDefault();
var id = $(this).data('id');
Swal.fire({
title: 'Apakah Anda yakin?',
text: "Data akan dihapus permanen!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Ya, hapus!'
}).then((result) => {
if (result.isConfirmed) {
// Buat form secara dinamis untuk melakukan request DELETE
var form = $('<form>', {
'method': 'POST',
'action': '/admin/munaqosah/' + id
});
var token = '{{ csrf_token() }}';
var hiddenInput = $('<input>', {
'name': '_token',
'value': token,
'type': 'hidden'
});
var hiddenMethod = $('<input>', {
'name': '_method',
'value': 'DELETE',
'type': 'hidden'
});
form.append(hiddenInput, hiddenMethod).appendTo('body').submit();
}
})
});
</script>
<!-- DataTables CSS & JS -->
<link rel="stylesheet"

View File

@ -0,0 +1,70 @@
@extends('layouts.app-admin')
@section('content')
<main id="main" class="main">
<div class="row">
<div class="pagetitle">
<h1>Data Latih</h1>
<nav>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Admin</a></li>
<li class="breadcrumb-item active">Data Latih</li>
</ol>
</nav>
</div>
<!-- Import & Export Buttons -->
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Tindakan</h5>
<form action="{{ route('data-latih.import') }}" method="POST" enctype="multipart/form-data">
@csrf
<input type="file" name="file" required>
<button type="submit" class="btn btn-primary">Import Excel</button>
</form>
<a href="{{ route('data-latih.export') }}" class="btn btn-success">Export Excel</a>
</div>
</div>
</div>
<!-- Data Table -->
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Data Latih</h5>
<table id="dataTable" class="table">
<thead>
<tr>
<th>Nama</th>
<th>Jenis Kelamin</th>
<th>NIS</th>
<th>Asal Daerah</th>
<th>Tahun Angkatan</th>
<th>Capaian Hadis</th>
<th>Capaian Al Qur'an</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($data as $santri)
<tr>
<td>{{ $santri->nama }}</td>
<td>{{ $santri->jenis_kelamin }}</td>
<td>{{ $santri->nis }}</td>
<td>{{ $santri->asal_daerah }}</td>
<td>{{ $santri->tahun_angkatan }}</td>
<td>{{ $santri->capaian_hadis }}</td>
<td>{{ $santri->capaian_quran }}</td>
<td>{{ $santri->status }}</td>
<td>
<!-- Aksi buttons -->
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</main>
@endsection

View File

@ -0,0 +1,165 @@
@extends('layouts.app-admin')
<title>Data Munaqosah | SR Klasifikasi</title>
@section('content')
<main id="main" class="main">
<div class="row">
<div class="pagetitle">
<h1>Munaqosah</h1>
<nav>
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Admin</a></li>
<li class="breadcrumb-item active">Munaqosah Santri</li>
</ol>
</nav>
</div>
<div class="col-12 dashboard">
<div class="row">
<div class="col-lg-12">
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
<div class="card">
<div class="card-body">
<h5 class="card-title">Munaqosah Santri</h5>
<!-- Tabel Riwayat -->
<table id="dataTable" class="table">
<thead>
<tr>
<th>Nama Santri</th>
<th>Tanggal</th>
<th>Tahun Angkatan</th>
<th>Al-Qur'an Isi</th>
<th>Al-Hadis Isi</th>
<th>Nilai N</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach($riwayat as $item)
<tr>
<td>{{ $item->user->name ?? '—' }}</td>
<td>{{ $item->created_at->format('Y-m-d') }}</td>
<td>{{ $item->tahun_angkatan }}</td>
<td>{{ $item->alquran }}</td>
<td>{{ $item->alhadis }}</td>
<td>{{ number_format($item->nilai_n, 2) }}</td>
<td>{{ $item->status }}</td>
<td>
@if($item->munaqosah_status === 'Sedang di Verifikasi')
<!-- Jika belum ada keputusan, tampilkan tombol Verifikasi, Tolak, dan Delete -->
<!-- Tombol Verifikasi -->
<form action="{{ route('munaqosah.verify', $item->id) }}" method="POST"
style="display:inline;">
@csrf
<button type="submit" class="btn btn-success btn-sm">
<i class='bx bxs-check-circle'></i> Verifikasi
</button>
</form>
<!-- Tombol Tolak -->
<form action="{{ route('munaqosah.reject', $item->id) }}" method="POST"
style="display:inline;">
@csrf
<button type="submit" class="btn btn-warning btn-sm">
<i class='bx bxs-x-circle'></i> Tolak
</button>
</form>
<!-- Tombol Delete dengan SweetAlert -->
<button class="btn btn-danger btn-sm btn-delete" data-id="{{ $item->id }}">
<i class='bx bxs-trash'></i> Delete
</button>
@else
<!-- Jika sudah ada keputusan (verified atau ditolak), tampilkan badge "Selesai" -->
<span class="badge bg-info">Selesai</span>
@endif
</td>
</tr>
@endforeach
</tbody>
</table>
<!-- Sertakan SweetAlert2 -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script>
$(document).on('click', '.btn-delete', function(e){
e.preventDefault();
var id = $(this).data('id');
Swal.fire({
title: 'Apakah Anda yakin?',
text: "Data akan dihapus permanen!",
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Ya, hapus!'
}).then((result) => {
if (result.isConfirmed) {
// Buat form secara dinamis untuk melakukan request DELETE
var form = $('<form>', {
'method': 'POST',
'action': '/admin/munaqosah/' + id
});
var token = '{{ csrf_token() }}';
var hiddenInput = $('<input>', {
'name': '_token',
'value': token,
'type': 'hidden'
});
var hiddenMethod = $('<input>', {
'name': '_method',
'value': 'DELETE',
'type': 'hidden'
});
form.append(hiddenInput, hiddenMethod).appendTo('body').submit();
}
})
});
</script>
<!-- DataTables CSS & JS -->
<link rel="stylesheet"
href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css">
<!-- Tambahkan CSS Responsive -->
<link rel="stylesheet"
href="https://cdn.datatables.net/responsive/2.4.1/css/responsive.dataTables.min.css">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
<!-- Tambahkan JS Responsive -->
<script src="https://cdn.datatables.net/responsive/2.4.1/js/dataTables.responsive.min.js">
</script>
<script>
$(document).ready(function () {
$('#dataTable').DataTable({
responsive: true, // Aktifkan fitur responsif
"language": {
"search": "Cari:",
"lengthMenu": "Tampilkan _MENU_ data",
"zeroRecords": "Tidak ada data yang cocok",
"info": "Menampilkan _START_ sampai _END_ dari _TOTAL_ data",
"infoEmpty": "Tidak ada data tersedia",
"infoFiltered": "(disaring dari _MAX_ total data)"
}
});
});
</script>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
@endsection

View File

@ -37,7 +37,7 @@
<div class="card-body">
<h5 class="card-title">Hitung Status</h5>
<!-- Form POST ke route countingSantri.post (ganti sesuai route Anda) -->
<!-- Form POST ke route countingSantri.post -->
<form class="row g-3" action="{{ route('countingSantri.post') }}" method="POST">
@csrf
<div class="col-md-12">
@ -45,12 +45,12 @@
value="{{ old('year') }}" required>
</div>
<div class="col-md-6">
<input type="number" class="form-control" placeholder="Jumlah Al-Qur'an Isi" name="alquran"
value="{{ old('alquran') }}" required>
<input type="number" class="form-control" placeholder="Jumlah Al-Qur'an Isi : Max 606"
name="alquran" value="{{ old('alquran') }}" max="606" required>
</div>
<div class="col-md-6">
<input type="number" class="form-control" placeholder="Jumlah Al-Hadis Isi" name="alhadis"
value="{{ old('alhadis') }}" required>
<input type="number" class="form-control" placeholder="Jumlah Al-Hadis Isi : Max 1997"
name="alhadis" value="{{ old('alhadis') }}" max="1997" required>
</div>
<div class="text-center">
<button type="submit" class="btn btn-primary">Hitung & Simpan</button>
@ -59,11 +59,11 @@
</form>
</div>
{{-- Bagian menampilkan hasil terakhir --}}
{{-- Bagian menampilkan hasil perhitungan terakhir --}}
@if($latest)
<div class="card-footer text-center p-4">
<h5 class="mb-3 fw-bold">Hasil Terakhir</h5>
<!-- Membuat tabel responsif -->
<!-- Tabel responsif -->
<div class="table-responsive">
<table class="table table-bordered text-start">
<tr>
@ -86,7 +86,6 @@
<th><i class="bx bx-line-chart"></i> Nilai (n)</th>
<td>
<strong>
{{-- Tampilkan 2 desimal + simbol persen --}}
{{ number_format($latest->nilai_n, 2) }}%
</strong>
</td>
@ -94,89 +93,111 @@
<tr>
<th><i class='bx bx-calculator'></i> Hasil</th>
<td>
<span class="badge
{{ $latest->status === 'Tercapai' ? 'bg-success' : 'bg-danger' }}">
<span
class="badge {{ $latest->status === 'Tercapai' ? 'bg-success' : 'bg-danger' }}">
{{ $latest->status }}
</span>
</td>
</tr>
{{-- Tambahan kolom baru untuk keterangan detail --}}
{{-- Perhitungan detail target keseluruhan --}}
@php
$start = \Carbon\Carbon::create($latest->tahun_angkatan, 1, 1);
$now = \Carbon\Carbon::today();
$x = $start->diffInDays($now);
$y = $latest->alquran + $latest->alhadis;
$targetSpeed = 2603 / 1095;
$start = \Carbon\Carbon::create($latest->tahun_angkatan, 1, 1);
$now = \Carbon\Carbon::today();
$x = $start->diffInDays($now);
$y = $latest->alquran + $latest->alhadis;
$targetSpeed = 2603 / 1095;
// nCheck = 0 sebagai default
$nCheck = 0;
// Hitung nilai kecepatan (nCheck) sebagai persentase
$nCheck = 0;
if ($y >= 2603) {
$nCheck = 100;
} elseif ($x > 0) {
$userSpeed = $y / $x;
$nCheck = ($userSpeed / $targetSpeed) * 100;
}
if ($y >= 2603) {
// Sudah pasti 'Sesuai Target'
$nCheck = 100;
} elseif ($x > 0) {
$userSpeed = $y / $x;
$nCheck = ($userSpeed / $targetSpeed) * 100;
// Tentukan status detail untuk target keseluruhan
$detailStatus = '';
$badgeClass = '';
if ($y >= 2603) {
$detailStatus = "Sesuai Target (Halaman penuh)";
$badgeClass = 'bg-success';
} elseif ($x == 0) {
$detailStatus = "Data belum berjalan (x=0)";
$badgeClass = 'bg-secondary';
} else {
if ($nCheck < 100) { $shortPages=($x * $targetSpeed) - $y; $shortPages=ceil($shortPages);
$detailStatus="Belum Target, kurang isi {$shortPages} halaman" ; $badgeClass='bg-danger'
; } elseif (abs($nCheck - 100) < 0.00001) { $detailStatus="Sesuai Target (100%)" ;
$badgeClass='bg-success' ; } elseif ($nCheck> 100) {
$detailStatus = "Lebih Target";
$badgeClass = 'bg-primary';
} else {
$detailStatus = "Data tidak valid";
$badgeClass = 'bg-secondary';
}
}
// Tentukan status detail
$detailStatus = '';
$badgeClass = '';
// Hitung kekurangan halaman untuk Quran dan Hadis
$quranShort = $latest->alquran < 606 ? (606 - $latest->alquran) : 0;
$hadisShort = $latest->alhadis < 1997 ? (1997 - $latest->alhadis) : 0;
$quranStatus = $latest->alquran >= 606 ? 'Khatam' : 'Belum Khatam';
$hadisStatus = $latest->alhadis >= 1997 ? 'Khatam' : 'Belum Khatam';
@endphp
// 1) Kalau y >= 2603: Sudah penuh => "Sesuai Target"
if ($y >= 2603) {
$detailStatus = "Sesuai Target (Halaman penuh)";
$badgeClass = 'bg-success';
}
// 2) Kalau x=0 dan y<2603
elseif ($x == 0) {
$detailStatus = "Data belum berjalan (x=0)";
$badgeClass = 'bg-secondary';
}
else {
// 3) Kalau x>0, cek nCheck
if ($nCheck < 100) {
// Hitung kekurangan
$shortPages = ($x * $targetSpeed) - $y;
$shortPages = ceil($shortPages);
$detailStatus = "Belum Target, kurang isi {$shortPages} halaman";
$badgeClass = 'bg-danger';
} elseif (abs($nCheck - 100) < 0.00001) {
// pas 100%
$detailStatus = "Sesuai Target (100%)";
$badgeClass = 'bg-success';
} elseif ($nCheck > 100) {
$detailStatus = "Lebih Target";
$badgeClass = 'bg-primary';
} else {
$detailStatus = "Data tidak valid";
$badgeClass = 'bg-secondary';
}
}
@endphp
<tr>
<th><i class="bx bx-info-circle"></i> Status Detail</th>
<td>
<span class="badge {{ $badgeClass }}">
{{ $detailStatus }}
</span>
</td>
</tr>
{{-- Kolom tambahan: Status Quran --}}
<tr>
<th><i class="bx bx-book"></i> Status Quran</th>
<td>
@if($quranStatus === 'Khatam')
<span class="badge bg-success">Khatam</span>
@else
<span class="badge bg-warning">
Belum Khatam, anda kurang {{ $quranShort }} halaman
</span>
@endif
</td>
</tr>
{{-- Kolom tambahan: Status Hadis --}}
<tr>
<th><i class="bx bx-book-open"></i> Status Hadis</th>
<td>
@if($hadisStatus === 'Khatam')
<span class="badge bg-success">Khatam</span>
@else
<span class="badge bg-warning">
Belum Khatam, anda kurang {{ $hadisShort }} halaman
</span>
@endif
</td>
</tr>
<tr>
<th><i class="bx bx-info-circle"></i> Status Detail</th>
<td>
<span class="badge {{ $badgeClass }}">
{{ $detailStatus }}
</span>
</td>
</tr>
</table>
</div>
</div>
{{-- Debug (opsional) --}}
{{-- <script>
{{--
<script>
alert("DEBUG:\n" +
"x = {{ $x }}\n" +
"y = {{ $y }}\n" +
"n (dari DB) = {{ $latest->nilai_n }}\n" +
"nCheck (dari Blade) = {{ number_format($nCheck,2) }}"
);
</script> --}}
"x = {{ $x }}\n" +
"y = {{ $y }}\n" +
"n (dari DB) = {{ $latest->nilai_n }}\n" +
"nCheck (dari Blade) = {{ number_format($nCheck,2) }}"
);
</script>
--}}
@else
<div class="card-footer text-center p-4">
<h5 class="fw-bold text-muted">Belum ada perhitungan</h5>

View File

@ -40,31 +40,36 @@
</div><!-- End Page Title -->
<!-- Munaqosah Card -->
<div class="col-12">
<div class="card info-card verification-card">
<div class="card-body">
<h5 class="card-title">Munaqosah <span>| Status</span></h5>
<div class="d-flex align-items-center">
<div class="card-icon rounded-circle d-flex align-items-center justify-content-center">
<i class='bx bx-shield'></i> <!-- Tambahkan ikon -->
</div>
<div class="ps-3">
@if($latestRiwayat)
@if($latestRiwayat->munaqosah_status === 'ditolak')
<h6 class="text-danger">Munaqosah ditolak</h6>
@elseif($latestRiwayat->munaqosah_status === 'verified')
<h6 class="text-success">Terverifikasi</h6>
@else
<h6 class="text-danger">Belum/Tidak Terverifikasi</h6>
@endif
@else
<h6>Belum ada data</h6>
@endif
<div class="col-12">
<div class="card info-card verification-card">
<div class="card-body">
<h5 class="card-title">Munaqosah <span>| Status</span></h5>
<div class="d-flex align-items-center">
<div class="card-icon rounded-circle d-flex align-items-center justify-content-center">
<i class='bx bx-shield'></i>
</div>
<div class="ps-3">
@if($latestRiwayat)
@if($latestRiwayat->munaqosah_status === 'Ditolak')
<h6 class="text-danger">Ditolak</h6>
@elseif($latestRiwayat->munaqosah_status === 'Terverifikasi')
<h6 class="text-success">Terverifikasi</h6>
<button class="btn btn-primary mt-2" onclick="generateQRCode()">Tampilkan QR</button>
<div id="qrcode" class="mt-3"></div>
<a id="downloadQR" class="btn btn-success mt-2 d-none" download="qrcode.pdf">Unduh PDF</a>
@else
<h6 class="text-warning">Belum Diverifikasi</h6>
@endif
@else
<h6>Belum ada data</h6>
@endif
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- End Munaqosah Card -->
<div class="col-12 dashboard">
@ -197,4 +202,64 @@ function updateTime() {
setInterval(updateTime, 1000);
updateTime();
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qrious/4.0.2/qrious.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<script>
function generateQRCode() {
// Menggunakan operator ternary untuk menghindari error jika $latestRiwayat null
const data = `Nama: {{ $user->name }}
NIS: {{ $user->nis }}
Status: {{ $latestRiwayat ? $latestRiwayat->status : 'Tidak Tersedia' }}
Tanggal: {{ now()->format('d-m-Y') }}`;
let qr = new QRious({
element: document.createElement('canvas'),
value: data,
size: 200
});
// Menampilkan QR Code
document.getElementById('qrcode').innerHTML = '';
document.getElementById('qrcode').appendChild(qr.canvas);
// Menampilkan tombol download
const link = document.getElementById('downloadQR');
link.classList.remove('d-none');
// Menambahkan event untuk mengunduh PDF
link.onclick = function () {
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// Menentukan font dan ukuran font
doc.setFont("helvetica");
doc.setFontSize(12);
// Menambahkan judul PDF dengan font tebal
doc.setFont("helvetica", "bold");
doc.text("QR Code Munaqosah", 20, 20);
// Menambahkan teks dengan font normal
doc.setFont("helvetica", "normal");
let y = 30; // Posisi Y dimulai dari sini
doc.text(`Nama: {{ $user->name }}`, 20, y);
y += 10;
doc.text(`NIS: {{ $user->nis }}`, 20, y);
y += 10;
doc.text(`Status: {{ $latestRiwayat ? $latestRiwayat->status : 'Tidak Tersedia' }}`, 20, y);
y += 10;
doc.text(`Tanggal: {{ now()->format('d-m-Y') }}`, 20, y);
// Memberi jarak antara teks dan QR Code
y += 20;
// Menambahkan QR Code ke PDF
doc.addImage(qr.canvas.toDataURL('image/png'), 'PNG', 20, y, 160, 160);
// Menyimpan file PDF dengan nama qrcode.pdf
doc.save("qrcode.pdf");
};
}
</script>
@endsection

View File

@ -39,6 +39,7 @@
<th>Al-Hadis Isi</th>
<th>Nilai N</th>
<th>Status</th>
<th>Review</th>
<!-- Kolom Aksi -->
<th>Aksi</th>
</tr>
@ -58,9 +59,19 @@
<span class="badge bg-danger">{{ $item->status }}</span>
@endif
</td>
<!-- Kolom Aksi -->
<td>
<!-- Tombol Hapus -->
@if($item->munaqosah_status === 'Terverifikasi')
<span class="badge bg-success">{{ $item->munaqosah_status }}</span>
@elseif($item->munaqosah_status === null)
<span class="badge bg-warning">Belum Diverifikasi</span>
@else
<span class="badge bg-info">{{ $item->munaqosah_status }}</span>
@endif
</td>
<!-- Kolom Aksi -->
<!-- Di dalam tabel, ganti tombol Kirim -->
<td>
<!-- Tombol Hapus (tetap) -->
<form action="{{ route('riwayat.destroy', $item->id) }}" method="POST"
style="display:inline;">
@csrf
@ -71,11 +82,13 @@
</button>
</form>
<!-- Tombol Kirim -->
<a href="{{ route('riwayat.send', $item->id) }}"
class="btn btn-primary btn-sm">
<!-- Tombol Kirim hanya muncul di data terakhir -->
@if($loop->first)
<button type="button" class="btn btn-primary btn-sm btn-send"
data-id="{{ $item->id }}">
<i class='bx bxs-send'></i> Kirim
</a>
</button>
@endif
</td>
</tr>
@endforeach
@ -115,4 +128,45 @@ class="btn btn-primary btn-sm">
</div>
</div>
</main>
<!-- Modal untuk memilih admin -->
<div class="modal fade" id="sendModal" tabindex="-1" aria-labelledby="sendModalLabel" aria-hidden="true">
<div class="modal-dialog">
<form id="sendForm" method="POST" action="">
@csrf
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="sendModalLabel">Pilih Wali Kelas</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label for="admin_id" class="form-label">Admin</label>
<select name="admin_id" id="admin_id" class="form-select" required>
<option value="">Pilih Wali Kelas</option>
@foreach($admins as $admin)
<option value="{{ $admin->id }}" style="color: black">{{ $admin->email }}</option>
@endforeach
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
<button type="submit" class="btn btn-primary">Kirim</button>
</div>
</div>
</form>
</div>
</div>
<script>
$(document).on('click', '.btn-send', function(){
var id = $(this).data('id');
// Set action form ke route /santri/riwayat/{id}/send
$('#sendForm').attr('action', '/santri/riwayat/' + id + '/send');
// Tampilkan modal
$('#sendModal').modal('show');
});
</script>
@endsection

View File

@ -6,8 +6,9 @@
<li class="nav-heading">Menu</li>
<li class="nav-item">
<a class="nav-link {{ Route::is('dashboardAdmin') ? '' : 'collapsed' }}" href="{{ route('dashboardAdmin') }}">
<i class="bi bi-grid"></i>
<a class="nav-link {{ Route::is('dashboardAdmin') ? '' : 'collapsed' }}"
href="{{ route('dashboardAdmin') }}">
<i class="bi bi-grid"></i>
<span>Dashboard</span>
</a>
</li>
@ -27,6 +28,38 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ Route::is('santri.add') ? '' : 'collapsed' }}" href="{{ route('santri.add') }}">
<i class='bx bx-child'></i>
<span>Kelola Santri</span>
</a>
</li>
<li class="nav-heading">Klasifikasi</li>
<li class="nav-item">
<a class="nav-link {{ Route::is('examData') ? '' : 'collapsed' }}" href="{{ route('examData') }}">
<i class='bx bx-data'></i>
<span>Data Latih</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ Route::is('trainData') ? '' : 'collapsed' }}" href="{{ route('trainData') }}">
<i class='bx bx-test-tube'></i>
<span>Data Uji</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ Route::is('classificationResult') ? '' : 'collapsed' }}"
href="{{ route('classificationResult') }}">
<i class='bx bx-bar-chart-alt-2'></i>
<span>Hasil Klasifikasi</span>
</a>
</li>
</ul>
</aside>

View File

@ -6,6 +6,7 @@
use App\Http\Controllers\SantriController;
use App\Http\Controllers\HitungController;
use App\Http\Controllers\MunaqosahController;
use App\Http\Controllers\ClassifiactionController;
/*
|--------------------------------------------------------------------------
| Web Routes
@ -50,6 +51,8 @@
Route::get('/admin/add', [AdminController::class, 'index'])->name('admin.add');
Route::post('/admin/add', [AdminController::class, 'store'])->name('admin.store');
Route::delete('/admin/{id}', [AdminController::class, 'destroy'])->name('admin.delete');
Route::get('/admin/santri', [AdminController::class, 'showSantri'])->name('santri.add');
Route::delete('/admin/santri/{id}', [AdminController::class, 'destroySantri'])->name('santri.delete');
Route::get('/admin/changePassword', [AdminController::class, 'showChangePassword'])
->name('changePassword');
Route::post('/admin/changePassword', [AdminController::class, 'changePassword'])
@ -57,8 +60,17 @@
Route::get('/admin/dataMunqosah', [MunaqosahController::class, 'showMunaqosah'])
->name('dataMunaqosah');
Route::get('/admin/dashboardAdmin', [AdminController::class, 'dashboard'])
->name('dashboardAdmin');
->name('dashboardAdmin');
Route::post('/admin/munaqosah/{id}/verify', [MunaqosahController::class, 'verify'])
->name('munaqosah.verify');
Route::post('/admin/munaqosah/{id}/reject', [MunaqosahController::class, 'reject'])
->name('munaqosah.reject');
Route::delete('/admin/munaqosah/{id}', [MunaqosahController::class, 'destroy'])
->name('munaqosah.destroy');
Route::get('/admin/examData', [ClassifiactionController::class, 'examData'])
->name('examData');
Route::get('/admin/trainData', [ClassifiactionController::class, 'trainData'])
->name('trainData');
Route::get('/admin/classificationResult', [ClassifiactionController::class, 'classificationResult'])
->name('classificationResult');
});