[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')); 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() public function dashboard()
{ {
@ -63,6 +72,15 @@ public function destroy($id)
return redirect()->route('admin.add')->with('success', 'Admin berhasil dihapus.'); 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). * 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 App\Models\Riwayat;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Models\User;
class HitungController extends Controller class HitungController extends Controller
{ {
@ -29,28 +30,28 @@ public function processCounting(Request $request)
{ {
$request->validate([ $request->validate([
'year' => 'required|integer', 'year' => 'required|integer',
'alquran' => 'required|integer|min:0', 'alquran' => 'required|integer|min:0|max:606', // maksimal 606 halaman
'alhadis' => 'required|integer|min:0', '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 $start = Carbon::create($request->year, 1, 1); // 1 Jan tahun angkatan
$now = Carbon::today(); // Hari ini (tanggal saja) $now = Carbon::today(); // Hari ini (tanggal saja)
$x = $start->diffInDays($now); $x = $start->diffInDays($now);
// Jumlah halaman diisi // Jumlah halaman yang diisi (alquran + alhadis)
$y = $request->alquran + $request->alhadis; $y = $request->alquran + $request->alhadis;
// Default nilai n dan status // Default nilai n dan status
$n = 0; $n = 0;
$status = 'Tidak Tercapai'; $status = 'Tidak Tercapai';
// 1) Jika y >= 2603, langsung "Tercapai" // 1) Jika jumlah halaman (y) >= 2603, langsung "Tercapai"
if ($y >= 2603) { if ($y >= 2603) {
$n = 100; // atau nilai lain yang Anda inginkan $n = 100; // Anda dapat mengganti nilai sesuai kebutuhan
$status = 'Tercapai'; $status = 'Tercapai';
} }
// 2) Jika y < 2603 dan x > 0, hitung kecepatan // 2) Jika y < 2603 dan x > 0, hitung kecepatan pencapaian
elseif ($x > 0) { elseif ($x > 0) {
$userSpeed = $y / $x; $userSpeed = $y / $x;
$targetSpeed = 2603 / 1095; $targetSpeed = 2603 / 1095;
@ -69,11 +70,6 @@ public function processCounting(Request $request)
'status' => $status, '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 // Kembali ke halaman counting dengan pesan sukses
return redirect()->route('countingSantri') return redirect()->route('countingSantri')
->with('success', 'Data berhasil dihitung dan disimpan!'); ->with('success', 'Data berhasil dihitung dan disimpan!');
@ -89,6 +85,9 @@ public function history()
->orderBy('created_at', 'desc') ->orderBy('created_at', 'desc')
->get(); ->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 class MunaqosahController extends Controller
{ {
/** // Method untuk menghapus data riwayat (digunakan di admin dan santri)
* Hapus data riwayat berdasarkan ID.
*/
public function destroy($id) public function destroy($id)
{ {
// Cari data Riwayat
$riwayat = Riwayat::findOrFail($id); $riwayat = Riwayat::findOrFail($id);
// Hapus
$riwayat->delete(); $riwayat->delete();
// Redirect balik dengan pesan sukses
return redirect()->back()->with('success', 'Data riwayat berhasil dihapus.'); 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 $request->validate([
$riwayat = Riwayat::findOrFail($id); '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 $riwayat = Riwayat::findOrFail($id);
// Contoh: kita set "sent_at" menjadi sekarang $riwayat->admin_id = $request->admin_id;
$riwayat->sent_at = now(); $riwayat->sent_at = now();
$riwayat->munaqosah_status = 'Sedang di Verifikasi';
$riwayat->save(); $riwayat->save();
// Redirect balik dengan pesan sukses
return redirect()->back()->with('success', 'Data berhasil dikirim ke admin.'); return redirect()->back()->with('success', 'Data berhasil dikirim ke admin.');
} }
// Contoh: Tampilkan semua Riwayat yang "sent_at" != null /**
public function showMunaqosah() * Tampilkan data munaqosah untuk admin.
{ */
$riwayat = Riwayat::whereNotNull('sent_at') public function showMunaqosah()
->orderBy('created_at', 'desc') {
->get(); $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', 'nilai_n',
'status', 'status',
'sent_at', 'sent_at',
'admin_id',
'munaqosah_status',
]; ];
/** /**

View File

@ -9,7 +9,8 @@
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^10.10", "laravel/framework": "^10.10",
"laravel/sanctum": "^3.3", "laravel/sanctum": "^3.3",
"laravel/tinker": "^2.8" "laravel/tinker": "^2.8",
"maatwebsite/excel": "^3.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.9.1", "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", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "9c491b8531eec05ba41a11d9276a5749", "content-hash": "fd4872b22b5625c027fc603f79579a78",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@ -135,6 +135,166 @@
], ],
"time": "2023-12-11T17:09:12+00:00" "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", "name": "dflydev/dot-access-data",
"version": "v3.0.3", "version": "v3.0.3",
@ -506,6 +666,67 @@
], ],
"time": "2023-10-06T06:47:41+00:00" "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", "name": "fruitcake/php-cors",
"version": "v1.3.0", "version": "v1.3.0",
@ -1884,6 +2105,272 @@
], ],
"time": "2024-09-21T08:32:55+00:00" "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", "name": "monolog/monolog",
"version": "3.7.0", "version": "3.7.0",
@ -2384,6 +2871,112 @@
], ],
"time": "2023-02-08T01:06:31+00:00" "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", "name": "phpoption/phpoption",
"version": "1.9.3", "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([ User::create([
'name' => null, // admin tidak butuh name, boleh dikosongi 'name' => null, // admin tidak butuh name, boleh dikosongi
'nis' => null, // admin tidak butuh NIS 'nis' => null, // admin tidak butuh NIS
'email' => 'admin@example.com', 'email' => 'muhammadfirdaus@gmail.com',
'password' => Hash::make('123456'), // password: 123456 'password' => Hash::make('123456'), // password: 123456
'role' => 'admin' 'role' => 'admin'
]); ]);
// Santri account // Santri account
User::create([ User::create([
'name' => 'Santri Testing', 'name' => 'Zhaqian',
'nis' => '12345', 'nis' => 'A13411',
'email' => 'santri@example.com', 'email' => 'santri@gmail.com',
'password' => Hash::make('123456'), // password: 123456 'password' => Hash::make('123456'), // password: 123456
'role' => 'santri', 'role' => 'santri',
'jenis_kelamin' => 'Laki-laki', 'jenis_kelamin' => 'Laki-laki',

View File

@ -22,7 +22,11 @@
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Data Admin</h5> <h5 class="card-title">Data Admin</h5>
@if(session('success'))
<div class="alert alert-success">
{{ session('success') }}
</div>
@endif
{{-- Tabel Admin --}} {{-- Tabel Admin --}}
<table id="addAdminTable" class="table"> <table id="addAdminTable" class="table">
<thead> <thead>
@ -37,16 +41,33 @@
<tr> <tr>
<td>{{ $index+1 }}</td> <td>{{ $index+1 }}</td>
<td>{{ $admin->email }}</td> <td>{{ $admin->email }}</td>
<td> <td>
<form action="{{ route('admin.delete', $admin->id) }}" method="POST" <form action="{{ route('admin.delete', $admin->id) }}" method="POST" id="deleteForm{{ $admin->id }}">
onsubmit="return confirm('Yakin ingin menghapus admin ini?')"> @csrf
@csrf @method('DELETE')
@method('DELETE') <button class="btn btn-danger btn-sm" type="button" onclick="confirmDelete({{ $admin->id }})">
<button class="btn btn-danger btn-sm" type="submit"> <i class='bx bx-trash'></i>
<i class='bx bx-trash'></i> </button>
</button> </form>
</form> </td>
</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> </tr>
@endforeach @endforeach
</tbody> </tbody>
@ -56,6 +77,9 @@
href="https://cdn.datatables.net/1.13.6/css/jquery.dataTables.min.css"> 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://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 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> <script>
$(document).ready(function () { $(document).ready(function () {
$('#addAdminTable').DataTable({ $('#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="col-12 dashboard">
<div class="row"> <div class="row">
@if(session('success')) @if(session('success'))
<div class="alert alert-success"> <div class="alert alert-success">
{{ session('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> </div>
@endif </div>
<!-- Waktu Card -->
<div class="col-xxl-12 col-md-12"> <div class="col-xxl-12 col-md-12">
<div class="row"> <div class="row">
<!-- Card Tanggal --> <!-- Card Tanggal -->

View File

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

View File

@ -40,31 +40,36 @@
</div><!-- End Page Title --> </div><!-- End Page Title -->
<!-- Munaqosah Card --> <!-- Munaqosah Card -->
<div class="col-12"> <div class="col-12">
<div class="card info-card verification-card"> <div class="card info-card verification-card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Munaqosah <span>| Status</span></h5> <h5 class="card-title">Munaqosah <span>| Status</span></h5>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<div class="card-icon rounded-circle d-flex align-items-center justify-content-center"> <div class="card-icon rounded-circle d-flex align-items-center justify-content-center">
<i class='bx bx-shield'></i> <!-- Tambahkan ikon --> <i class='bx bx-shield'></i>
</div> </div>
<div class="ps-3"> <div class="ps-3">
@if($latestRiwayat) @if($latestRiwayat)
@if($latestRiwayat->munaqosah_status === 'ditolak') @if($latestRiwayat->munaqosah_status === 'Ditolak')
<h6 class="text-danger">Munaqosah ditolak</h6> <h6 class="text-danger">Ditolak</h6>
@elseif($latestRiwayat->munaqosah_status === 'verified') @elseif($latestRiwayat->munaqosah_status === 'Terverifikasi')
<h6 class="text-success">Terverifikasi</h6> <h6 class="text-success">Terverifikasi</h6>
@else <button class="btn btn-primary mt-2" onclick="generateQRCode()">Tampilkan QR</button>
<h6 class="text-danger">Belum/Tidak Terverifikasi</h6> <div id="qrcode" class="mt-3"></div>
@endif <a id="downloadQR" class="btn btn-success mt-2 d-none" download="qrcode.pdf">Unduh PDF</a>
@else @else
<h6>Belum ada data</h6> <h6 class="text-warning">Belum Diverifikasi</h6>
@endif @endif
@else
<h6>Belum ada data</h6>
@endif
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
</div>
<!-- End Munaqosah Card --> <!-- End Munaqosah Card -->
<div class="col-12 dashboard"> <div class="col-12 dashboard">
@ -197,4 +202,64 @@ function updateTime() {
setInterval(updateTime, 1000); setInterval(updateTime, 1000);
updateTime(); updateTime();
</script> </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 @endsection

View File

@ -39,6 +39,7 @@
<th>Al-Hadis Isi</th> <th>Al-Hadis Isi</th>
<th>Nilai N</th> <th>Nilai N</th>
<th>Status</th> <th>Status</th>
<th>Review</th>
<!-- Kolom Aksi --> <!-- Kolom Aksi -->
<th>Aksi</th> <th>Aksi</th>
</tr> </tr>
@ -58,9 +59,19 @@
<span class="badge bg-danger">{{ $item->status }}</span> <span class="badge bg-danger">{{ $item->status }}</span>
@endif @endif
</td> </td>
<!-- Kolom Aksi -->
<td> <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" <form action="{{ route('riwayat.destroy', $item->id) }}" method="POST"
style="display:inline;"> style="display:inline;">
@csrf @csrf
@ -71,11 +82,13 @@
</button> </button>
</form> </form>
<!-- Tombol Kirim --> <!-- Tombol Kirim hanya muncul di data terakhir -->
<a href="{{ route('riwayat.send', $item->id) }}" @if($loop->first)
class="btn btn-primary btn-sm"> <button type="button" class="btn btn-primary btn-sm btn-send"
data-id="{{ $item->id }}">
<i class='bx bxs-send'></i> Kirim <i class='bx bxs-send'></i> Kirim
</a> </button>
@endif
</td> </td>
</tr> </tr>
@endforeach @endforeach
@ -115,4 +128,45 @@ class="btn btn-primary btn-sm">
</div> </div>
</div> </div>
</main> </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 @endsection

View File

@ -6,8 +6,9 @@
<li class="nav-heading">Menu</li> <li class="nav-heading">Menu</li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link {{ Route::is('dashboardAdmin') ? '' : 'collapsed' }}" href="{{ route('dashboardAdmin') }}"> <a class="nav-link {{ Route::is('dashboardAdmin') ? '' : 'collapsed' }}"
<i class="bi bi-grid"></i> href="{{ route('dashboardAdmin') }}">
<i class="bi bi-grid"></i>
<span>Dashboard</span> <span>Dashboard</span>
</a> </a>
</li> </li>
@ -27,6 +28,38 @@
</a> </a>
</li> </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> </ul>
</aside> </aside>

View File

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