a lot things added and fixed
This commit is contained in:
parent
67dacd6671
commit
5785ad88fc
|
|
@ -38,8 +38,8 @@ public function store(Request $request)
|
|||
'judul_challenge' => 'required|string|max:200',
|
||||
'deskripsi' => 'nullable|string',
|
||||
'exp' => 'required|integer|min:0',
|
||||
'id_badge' => 'nullable|exists:badges,id_badge',
|
||||
'tenggat_waktu' => 'required|date|after:now',
|
||||
'durasi_pengerjaan' => 'required|integer|min:1|max:360',
|
||||
'id_kelas' => 'required|array|min:1',
|
||||
'id_kelas.*' => 'exists:kelas,id_kelas',
|
||||
// Soal
|
||||
|
|
@ -67,11 +67,14 @@ public function store(Request $request)
|
|||
'exp' => $request->exp,
|
||||
'id_badge' => $request->id_badge,
|
||||
'tenggat_waktu' => $request->tenggat_waktu,
|
||||
'durasi_pengerjaan' => $request->durasi_pengerjaan,
|
||||
]);
|
||||
|
||||
// Attach ke kelas
|
||||
$challenge->kelas()->sync($request->id_kelas);
|
||||
|
||||
$challenge->soal()->delete();
|
||||
|
||||
// Simpan soal
|
||||
foreach ($request->pertanyaan as $i => $pertanyaan) {
|
||||
SoalChallenge::create([
|
||||
|
|
@ -113,8 +116,8 @@ public function update(Request $request, $id)
|
|||
'judul_challenge' => 'required|string|max:200',
|
||||
'deskripsi' => 'nullable|string',
|
||||
'exp' => 'required|integer|min:0',
|
||||
'id_badge' => 'nullable|exists:badges,id_badge',
|
||||
'tenggat_waktu' => 'required|date',
|
||||
'durasi_pengerjaan' => 'required|integer|min:1|max:360',
|
||||
'id_kelas' => 'required|array|min:1',
|
||||
'id_kelas.*' => 'exists:kelas,id_kelas',
|
||||
'pertanyaan' => 'required|array|min:1',
|
||||
|
|
@ -134,6 +137,7 @@ public function update(Request $request, $id)
|
|||
'exp' => $request->exp,
|
||||
'id_badge' => $request->id_badge,
|
||||
'tenggat_waktu' => $request->tenggat_waktu,
|
||||
'durasi_pengerjaan' => $request->durasi_pengerjaan,
|
||||
]);
|
||||
|
||||
$challenge->kelas()->sync($request->id_kelas);
|
||||
|
|
@ -178,8 +182,8 @@ public function editData($id)
|
|||
'judul_challenge' => $challenge->judul_challenge,
|
||||
'deskripsi' => $challenge->deskripsi,
|
||||
'exp' => $challenge->exp,
|
||||
'id_badge' => $challenge->id_badge,
|
||||
'tenggat_waktu' => $challenge->tenggat_waktu,
|
||||
'durasi_pengerjaan' => $challenge->durasi_pengerjaan,
|
||||
'kelas' => $challenge->kelas->pluck('id_kelas'),
|
||||
'soal' => $challenge->soal,
|
||||
]);
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
use App\Models\Mengajar;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class GuruController extends Controller
|
||||
{
|
||||
|
|
@ -148,6 +149,58 @@ public function destroy(string $id)
|
|||
->with('success', 'Data guru berhasil dihapus.');
|
||||
}
|
||||
|
||||
public function downloadPdf(Request $request)
|
||||
{
|
||||
$query = Guru::with('mengajars.mapel', 'mengajars.kelas');
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama', 'like', "%$search%")
|
||||
->orWhere('nip', 'like', "%$search%");
|
||||
});
|
||||
}
|
||||
$gurus = $query->get();
|
||||
|
||||
$pdf = Pdf::loadView('admin.guru.pdf', compact('gurus'))
|
||||
->setPaper('a4', 'landscape');
|
||||
|
||||
return $pdf->download('daftar-guru-' . date('Ymd') . '.pdf');
|
||||
}
|
||||
|
||||
public function downloadExcel(Request $request)
|
||||
{
|
||||
$query = Guru::with('mengajars.mapel', 'mengajars.kelas');
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where(function($q) use ($search) {
|
||||
$q->where('nama', 'like', "%$search%")
|
||||
->orWhere('nip', 'like', "%$search%");
|
||||
});
|
||||
}
|
||||
$gurus = $query->get();
|
||||
|
||||
$filename = 'daftar-guru-' . date('Ymd') . '.csv';
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => "attachment; filename=\"$filename\"",
|
||||
];
|
||||
|
||||
$callback = function () use ($gurus) {
|
||||
$file = fopen('php://output', 'w');
|
||||
// BOM agar Excel bisa baca UTF-8
|
||||
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
fputcsv($file, ['No', 'Nama', 'NIP', 'Mata Pelajaran', 'Kelas']);
|
||||
foreach ($gurus as $i => $guru) {
|
||||
$mapels = $guru->mengajars->map(fn($m) => optional($m->mapel)->nama_mapel ?? '-')->join(', ');
|
||||
$kelas = $guru->mengajars->map(fn($m) => (optional($m->kelas)->tingkat . ' ' . optional($m->kelas)->nama_kelas))->join(', ');
|
||||
fputcsv($file, [$i + 1, $guru->nama, $guru->nip, $mapels, $kelas]);
|
||||
}
|
||||
fclose($file);
|
||||
};
|
||||
|
||||
return response()->stream($callback, 200, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* API: Ambil kelas yang memiliki mapel tertentu (lewat tabel mengajars)
|
||||
* Dipanggil via AJAX saat admin pilih mapel di modal
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
use App\Models\Kelas;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
|
||||
class KelasController extends Controller
|
||||
|
|
@ -88,4 +89,49 @@ public function destroy($id_kelas)
|
|||
return redirect()->route('admin.kelas.index')
|
||||
->with('success', 'Data kelas berhasil dihapus!');
|
||||
}
|
||||
|
||||
public function downloadPdf(Request $request)
|
||||
{
|
||||
$query = Kelas::query();
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where('nama_kelas', 'like', "%$search%")
|
||||
->orWhere('id_kelas', 'like', "%$search%");
|
||||
}
|
||||
$kelass = $query->get();
|
||||
|
||||
$pdf = Pdf::loadView('admin.kelas.pdf', compact('kelass'))
|
||||
->setPaper('a4', 'portrait');
|
||||
|
||||
return $pdf->download('daftar-kelas-' . date('Ymd') . '.pdf');
|
||||
}
|
||||
|
||||
public function downloadExcel(Request $request)
|
||||
{
|
||||
$query = Kelas::query();
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where('nama_kelas', 'like', "%$search%")
|
||||
->orWhere('id_kelas', 'like', "%$search%");
|
||||
}
|
||||
$kelass = $query->get();
|
||||
|
||||
$filename = 'daftar-kelas-' . date('Ymd') . '.csv';
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => "attachment; filename=\"$filename\"",
|
||||
];
|
||||
|
||||
$callback = function () use ($kelass) {
|
||||
$file = fopen('php://output', 'w');
|
||||
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
fputcsv($file, ['No', 'ID Kelas', 'Nama Kelas', 'Tingkat']);
|
||||
foreach ($kelass as $i => $kelas) {
|
||||
fputcsv($file, [$i + 1, $kelas->id_kelas, $kelas->nama_kelas, $kelas->tingkat]);
|
||||
}
|
||||
fclose($file);
|
||||
};
|
||||
|
||||
return response()->stream($callback, 200, $headers);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
use App\Models\Kelas;
|
||||
use App\Models\Mengajar;
|
||||
use Illuminate\Http\Request;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class MapelController extends Controller
|
||||
{
|
||||
|
|
@ -116,8 +117,6 @@ public function update(Request $request, $id)
|
|||
->with('success', 'Data mata pelajaran berhasil diupdate!');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function destroy($id)
|
||||
{
|
||||
|
||||
|
|
@ -130,4 +129,62 @@ public function destroy($id)
|
|||
return redirect()->route('admin.mapel.index')
|
||||
->with('success', 'Data mata pelajaran berhasil dihapus!');
|
||||
}
|
||||
|
||||
public function downloadPdf(Request $request)
|
||||
{
|
||||
$query = Mapel::with('kelas');
|
||||
if ($request->filled('search')) {
|
||||
$query->where(function($q) use ($request) {
|
||||
$q->where('nama_mapel', 'like', "%$request->search%")
|
||||
->orWhere('id_mapel', 'like', "%$request->search%");
|
||||
});
|
||||
}
|
||||
if ($request->filled('filter_kelas')) {
|
||||
$query->whereHas('kelas', function($q) use ($request) {
|
||||
$q->where('kelas.id_kelas', $request->filter_kelas);
|
||||
});
|
||||
}
|
||||
$mapels = $query->get();
|
||||
|
||||
$pdf = Pdf::loadView('admin.mapel.pdf', compact('mapels'))
|
||||
->setPaper('a4', 'portrait');
|
||||
|
||||
return $pdf->download('daftar-mapel-' . date('Ymd') . '.pdf');
|
||||
}
|
||||
|
||||
public function downloadExcel(Request $request)
|
||||
{
|
||||
$query = Mapel::with('kelas');
|
||||
if ($request->filled('search')) {
|
||||
$query->where(function($q) use ($request) {
|
||||
$q->where('nama_mapel', 'like', "%$request->search%")
|
||||
->orWhere('id_mapel', 'like', "%$request->search%");
|
||||
});
|
||||
}
|
||||
if ($request->filled('filter_kelas')) {
|
||||
$query->whereHas('kelas', function($q) use ($request) {
|
||||
$q->where('kelas.id_kelas', $request->filter_kelas);
|
||||
});
|
||||
}
|
||||
$mapels = $query->get();
|
||||
|
||||
$filename = 'daftar-mapel-' . date('Ymd') . '.csv';
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => "attachment; filename=\"$filename\"",
|
||||
];
|
||||
|
||||
$callback = function () use ($mapels) {
|
||||
$file = fopen('php://output', 'w');
|
||||
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
fputcsv($file, ['No', 'ID Mapel', 'Nama Mata Pelajaran', 'Kelas']);
|
||||
foreach ($mapels as $i => $mapel) {
|
||||
$kelas = $mapel->kelas->map(fn($k) => $k->tingkat . ' ' . $k->nama_kelas)->join(', ');
|
||||
fputcsv($file, [$i + 1, $mapel->id_mapel, $mapel->nama_mapel, $kelas]);
|
||||
}
|
||||
fclose($file);
|
||||
};
|
||||
|
||||
return response()->stream($callback, 200, $headers);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
use App\Models\Kelas;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
|
||||
class SiswaController extends Controller
|
||||
{
|
||||
|
|
@ -113,4 +114,62 @@ public function destroy($id)
|
|||
return redirect()->route('admin.siswa.index')
|
||||
->with('success', 'Data siswa berhasil dihapus!');
|
||||
}
|
||||
|
||||
public function downloadPdf(Request $request)
|
||||
{
|
||||
$query = Siswa::with('kelas');
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where('nama', 'like', "%$search%")
|
||||
->orWhere('nisn', 'like', "%$search%");
|
||||
}
|
||||
if ($request->filled('filter_kelas')) {
|
||||
$query->where('id_kelas', $request->filter_kelas);
|
||||
}
|
||||
$siswas = $query->get();
|
||||
|
||||
$pdf = Pdf::loadView('admin.siswa.pdf', compact('siswas'))
|
||||
->setPaper('a4', 'landscape');
|
||||
|
||||
return $pdf->download('daftar-siswa-' . date('Ymd') . '.pdf');
|
||||
}
|
||||
|
||||
public function downloadExcel(Request $request)
|
||||
{
|
||||
$query = Siswa::with('kelas');
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->search;
|
||||
$query->where('nama', 'like', "%$search%")
|
||||
->orWhere('nisn', 'like', "%$search%");
|
||||
}
|
||||
if ($request->filled('filter_kelas')) {
|
||||
$query->where('id_kelas', $request->filter_kelas);
|
||||
}
|
||||
$siswas = $query->get();
|
||||
|
||||
$filename = 'daftar-siswa-' . date('Ymd') . '.csv';
|
||||
$headers = [
|
||||
'Content-Type' => 'text/csv',
|
||||
'Content-Disposition' => "attachment; filename=\"$filename\"",
|
||||
];
|
||||
|
||||
$callback = function () use ($siswas) {
|
||||
$file = fopen('php://output', 'w');
|
||||
fprintf($file, chr(0xEF).chr(0xBB).chr(0xBF));
|
||||
fputcsv($file, ['No', 'NISN', 'Nama', 'Tempat Lahir', 'Tanggal Lahir', 'Kelas']);
|
||||
foreach ($siswas as $i => $siswa) {
|
||||
fputcsv($file, [
|
||||
$i + 1,
|
||||
$siswa->nisn,
|
||||
$siswa->nama,
|
||||
$siswa->tempat_lahir,
|
||||
\Carbon\Carbon::parse($siswa->tanggal_lahir)->format('d M Y'),
|
||||
$siswa->kelas->tingkat . ' - ' . $siswa->kelas->nama_kelas,
|
||||
]);
|
||||
}
|
||||
fclose($file);
|
||||
};
|
||||
|
||||
return response()->stream($callback, 200, $headers);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,12 @@ class Challenge extends Model
|
|||
'deskripsi',
|
||||
'exp',
|
||||
'id_badge',
|
||||
'durasi_pengerjaan',
|
||||
'tenggat_waktu',
|
||||
];
|
||||
protected $casts = [
|
||||
'durasi_pengerjaan' => 'integer',
|
||||
];
|
||||
|
||||
public function kelas()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,22 +3,17 @@
|
|||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*/
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
Paginator::defaultView('vendor.pagination.bootstrap-5');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"barryvdh/laravel-dompdf": "^3.1",
|
||||
"doctrine/dbal": "^4.4",
|
||||
"laravel/framework": "^12.0",
|
||||
"laravel/tinker": "^2.10.1"
|
||||
|
|
|
|||
|
|
@ -4,8 +4,85 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "b431c9cde1a46957fa68826ee65622af",
|
||||
"content-hash": "ff0b1f9e9305b6ad7e2e60e462da8ee3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "barryvdh/laravel-dompdf",
|
||||
"version": "v3.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/barryvdh/laravel-dompdf.git",
|
||||
"reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/ee3b72b19ccdf57d0243116ecb2b90261344dedc",
|
||||
"reference": "ee3b72b19ccdf57d0243116ecb2b90261344dedc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dompdf/dompdf": "^3.0",
|
||||
"illuminate/support": "^9|^10|^11|^12|^13.0",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"larastan/larastan": "^2.7|^3.0",
|
||||
"orchestra/testbench": "^7|^8|^9.16|^10|^11.0",
|
||||
"phpro/grumphp": "^2.5",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"aliases": {
|
||||
"PDF": "Barryvdh\\DomPDF\\Facade\\Pdf",
|
||||
"Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf"
|
||||
},
|
||||
"providers": [
|
||||
"Barryvdh\\DomPDF\\ServiceProvider"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Barryvdh\\DomPDF\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Barry vd. Heuvel",
|
||||
"email": "barryvdh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A DOMPDF Wrapper for Laravel",
|
||||
"keywords": [
|
||||
"dompdf",
|
||||
"laravel",
|
||||
"pdf"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/barryvdh/laravel-dompdf/issues",
|
||||
"source": "https://github.com/barryvdh/laravel-dompdf/tree/v3.1.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://fruitcake.nl",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/barryvdh",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-21T08:51:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "brick/math",
|
||||
"version": "0.14.0",
|
||||
|
|
@ -531,6 +608,161 @@
|
|||
],
|
||||
"time": "2024-02-05T11:56:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dompdf/dompdf",
|
||||
"version": "v3.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/dompdf.git",
|
||||
"reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/dompdf/zipball/f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496",
|
||||
"reference": "f11ead23a8a76d0ff9bbc6c7c8fd7e05ca328496",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dompdf/php-font-lib": "^1.0.0",
|
||||
"dompdf/php-svg-lib": "^1.0.0",
|
||||
"ext-dom": "*",
|
||||
"ext-mbstring": "*",
|
||||
"masterminds/html5": "^2.0",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-gd": "*",
|
||||
"ext-json": "*",
|
||||
"ext-zip": "*",
|
||||
"mockery/mockery": "^1.3",
|
||||
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"symfony/process": "^4.4 || ^5.4 || ^6.2 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "Needed to process images",
|
||||
"ext-gmagick": "Improves image processing performance",
|
||||
"ext-imagick": "Improves image processing performance",
|
||||
"ext-zlib": "Needed for pdf stream compression"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dompdf\\": "src/"
|
||||
},
|
||||
"classmap": [
|
||||
"lib/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "The Dompdf Community",
|
||||
"homepage": "https://github.com/dompdf/dompdf/blob/master/AUTHORS.md"
|
||||
}
|
||||
],
|
||||
"description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter",
|
||||
"homepage": "https://github.com/dompdf/dompdf",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/dompdf/issues",
|
||||
"source": "https://github.com/dompdf/dompdf/tree/v3.1.5"
|
||||
},
|
||||
"time": "2026-03-03T13:54:37+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dompdf/php-font-lib",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-font-lib.git",
|
||||
"reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-font-lib/zipball/a6e9a688a2a80016ac080b97be73d3e10c444c9a",
|
||||
"reference": "a6e9a688a2a80016ac080b97be73d3e10c444c9a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11 || ^12"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"FontLib\\": "src/FontLib"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-2.1-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "The FontLib Community",
|
||||
"homepage": "https://github.com/dompdf/php-font-lib/blob/master/AUTHORS.md"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse, export and make subsets of different types of font files.",
|
||||
"homepage": "https://github.com/dompdf/php-font-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-font-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-font-lib/tree/1.0.2"
|
||||
},
|
||||
"time": "2026-01-20T14:10:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dompdf/php-svg-lib",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dompdf/php-svg-lib.git",
|
||||
"reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dompdf/php-svg-lib/zipball/8259ffb930817e72b1ff1caef5d226501f3dfeb1",
|
||||
"reference": "8259ffb930817e72b1ff1caef5d226501f3dfeb1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"php": "^7.1 || ^8.0",
|
||||
"sabberworm/php-css-parser": "^8.4 || ^9.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5 || ^8 || ^9 || ^10 || ^11"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Svg\\": "src/Svg"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"LGPL-3.0-or-later"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "The SvgLib Community",
|
||||
"homepage": "https://github.com/dompdf/php-svg-lib/blob/master/AUTHORS.md"
|
||||
}
|
||||
],
|
||||
"description": "A library to read, parse and export to PDF SVG files.",
|
||||
"homepage": "https://github.com/dompdf/php-svg-lib",
|
||||
"support": {
|
||||
"issues": "https://github.com/dompdf/php-svg-lib/issues",
|
||||
"source": "https://github.com/dompdf/php-svg-lib/tree/1.0.2"
|
||||
},
|
||||
"time": "2026-01-02T16:01:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dragonmantank/cron-expression",
|
||||
"version": "v3.4.0",
|
||||
|
|
@ -2163,6 +2395,73 @@
|
|||
],
|
||||
"time": "2024-12-08T08:18:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "masterminds/html5",
|
||||
"version": "2.10.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Masterminds/html5-php.git",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Masterminds/html5-php/zipball/fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"reference": "fcf91eb64359852f00d921887b219479b4f21251",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-dom": "*",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7 || ^8 || ^9"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Masterminds\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Matt Butcher",
|
||||
"email": "technosophos@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Matt Farina",
|
||||
"email": "matt@mattfarina.com"
|
||||
},
|
||||
{
|
||||
"name": "Asmir Mustafic",
|
||||
"email": "goetas@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "An HTML5 parser and serializer.",
|
||||
"homepage": "http://masterminds.github.io/html5-php",
|
||||
"keywords": [
|
||||
"HTML5",
|
||||
"dom",
|
||||
"html",
|
||||
"parser",
|
||||
"querypath",
|
||||
"serializer",
|
||||
"xml"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Masterminds/html5-php/issues",
|
||||
"source": "https://github.com/Masterminds/html5-php/tree/2.10.0"
|
||||
},
|
||||
"time": "2025-07-25T09:04:22+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
"version": "3.9.0",
|
||||
|
|
@ -3479,6 +3778,86 @@
|
|||
},
|
||||
"time": "2025-09-04T20:59:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "sabberworm/php-css-parser",
|
||||
"version": "v9.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/MyIntervals/PHP-CSS-Parser.git",
|
||||
"reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/MyIntervals/PHP-CSS-Parser/zipball/88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949",
|
||||
"reference": "88dbd0f7f91abbfe4402d0a3071e9ff4d81ed949",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"php": "^7.2.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0 || ~8.5.0",
|
||||
"thecodingmachine/safe": "^1.3 || ^2.5 || ^3.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-parallel-lint/php-parallel-lint": "1.4.0",
|
||||
"phpstan/extension-installer": "1.4.3",
|
||||
"phpstan/phpstan": "1.12.32 || 2.1.32",
|
||||
"phpstan/phpstan-phpunit": "1.4.2 || 2.0.8",
|
||||
"phpstan/phpstan-strict-rules": "1.6.2 || 2.0.7",
|
||||
"phpunit/phpunit": "8.5.52",
|
||||
"rawr/phpunit-data-provider": "3.3.1",
|
||||
"rector/rector": "1.2.10 || 2.2.8",
|
||||
"rector/type-perfect": "1.0.0 || 2.1.0",
|
||||
"squizlabs/php_codesniffer": "4.0.1",
|
||||
"thecodingmachine/phpstan-safe-rule": "1.2.0 || 1.4.1"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "for parsing UTF-8 CSS"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "9.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/Rule/Rule.php",
|
||||
"src/RuleSet/RuleContainer.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Sabberworm\\CSS\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Raphael Schweikert"
|
||||
},
|
||||
{
|
||||
"name": "Oliver Klee",
|
||||
"email": "github@oliverklee.de"
|
||||
},
|
||||
{
|
||||
"name": "Jake Hotson",
|
||||
"email": "jake.github@qzdesign.co.uk"
|
||||
}
|
||||
],
|
||||
"description": "Parser for CSS Files written in PHP",
|
||||
"homepage": "https://www.sabberworm.com/blog/2010/6/10/php-css-parser",
|
||||
"keywords": [
|
||||
"css",
|
||||
"parser",
|
||||
"stylesheet"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/MyIntervals/PHP-CSS-Parser/issues",
|
||||
"source": "https://github.com/MyIntervals/PHP-CSS-Parser/tree/v9.3.0"
|
||||
},
|
||||
"time": "2026-03-03T17:31:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.3.0",
|
||||
|
|
@ -5956,6 +6335,149 @@
|
|||
],
|
||||
"time": "2025-09-11T10:12:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "thecodingmachine/safe",
|
||||
"version": "v3.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thecodingmachine/safe.git",
|
||||
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thecodingmachine/safe/zipball/705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||
"reference": "705683a25bacf0d4860c7dea4d7947bfd09eea19",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-parallel-lint/php-parallel-lint": "^1.4",
|
||||
"phpstan/phpstan": "^2",
|
||||
"phpunit/phpunit": "^10",
|
||||
"squizlabs/php_codesniffer": "^3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/special_cases.php",
|
||||
"generated/apache.php",
|
||||
"generated/apcu.php",
|
||||
"generated/array.php",
|
||||
"generated/bzip2.php",
|
||||
"generated/calendar.php",
|
||||
"generated/classobj.php",
|
||||
"generated/com.php",
|
||||
"generated/cubrid.php",
|
||||
"generated/curl.php",
|
||||
"generated/datetime.php",
|
||||
"generated/dir.php",
|
||||
"generated/eio.php",
|
||||
"generated/errorfunc.php",
|
||||
"generated/exec.php",
|
||||
"generated/fileinfo.php",
|
||||
"generated/filesystem.php",
|
||||
"generated/filter.php",
|
||||
"generated/fpm.php",
|
||||
"generated/ftp.php",
|
||||
"generated/funchand.php",
|
||||
"generated/gettext.php",
|
||||
"generated/gmp.php",
|
||||
"generated/gnupg.php",
|
||||
"generated/hash.php",
|
||||
"generated/ibase.php",
|
||||
"generated/ibmDb2.php",
|
||||
"generated/iconv.php",
|
||||
"generated/image.php",
|
||||
"generated/imap.php",
|
||||
"generated/info.php",
|
||||
"generated/inotify.php",
|
||||
"generated/json.php",
|
||||
"generated/ldap.php",
|
||||
"generated/libxml.php",
|
||||
"generated/lzf.php",
|
||||
"generated/mailparse.php",
|
||||
"generated/mbstring.php",
|
||||
"generated/misc.php",
|
||||
"generated/mysql.php",
|
||||
"generated/mysqli.php",
|
||||
"generated/network.php",
|
||||
"generated/oci8.php",
|
||||
"generated/opcache.php",
|
||||
"generated/openssl.php",
|
||||
"generated/outcontrol.php",
|
||||
"generated/pcntl.php",
|
||||
"generated/pcre.php",
|
||||
"generated/pgsql.php",
|
||||
"generated/posix.php",
|
||||
"generated/ps.php",
|
||||
"generated/pspell.php",
|
||||
"generated/readline.php",
|
||||
"generated/rnp.php",
|
||||
"generated/rpminfo.php",
|
||||
"generated/rrd.php",
|
||||
"generated/sem.php",
|
||||
"generated/session.php",
|
||||
"generated/shmop.php",
|
||||
"generated/sockets.php",
|
||||
"generated/sodium.php",
|
||||
"generated/solr.php",
|
||||
"generated/spl.php",
|
||||
"generated/sqlsrv.php",
|
||||
"generated/ssdeep.php",
|
||||
"generated/ssh2.php",
|
||||
"generated/stream.php",
|
||||
"generated/strings.php",
|
||||
"generated/swoole.php",
|
||||
"generated/uodbc.php",
|
||||
"generated/uopz.php",
|
||||
"generated/url.php",
|
||||
"generated/var.php",
|
||||
"generated/xdiff.php",
|
||||
"generated/xml.php",
|
||||
"generated/xmlrpc.php",
|
||||
"generated/yaml.php",
|
||||
"generated/yaz.php",
|
||||
"generated/zip.php",
|
||||
"generated/zlib.php"
|
||||
],
|
||||
"classmap": [
|
||||
"lib/DateTime.php",
|
||||
"lib/DateTimeImmutable.php",
|
||||
"lib/Exceptions/",
|
||||
"generated/Exceptions/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHP core functions that throw exceptions instead of returning FALSE on error",
|
||||
"support": {
|
||||
"issues": "https://github.com/thecodingmachine/safe/issues",
|
||||
"source": "https://github.com/thecodingmachine/safe/tree/v3.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/OskarStark",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/shish",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/silasjoisten",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/staabm",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-02-04T18:08:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
"version": "v2.3.0",
|
||||
|
|
|
|||
|
|
@ -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('challenges', function (Blueprint $table) {
|
||||
// Simpan dalam menit, nullable agar data lama tidak error
|
||||
$table->unsignedSmallInteger('durasi_pengerjaan')->nullable()->after('tenggat_waktu')
|
||||
->comment('Durasi pengerjaan dalam menit. NULL = tidak ada batas durasi.');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('challenges', function (Blueprint $table) {
|
||||
$table->dropColumn('durasi_pengerjaan');
|
||||
});
|
||||
}
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -170,14 +170,12 @@
|
|||
<img src="{{ asset('images/icon/main/add.png') }}" width="18" height="18" alt="Tambah">
|
||||
Tambah Data
|
||||
</button>
|
||||
<button class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download">
|
||||
Download PDF
|
||||
</button>
|
||||
<button class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download">
|
||||
Download Excel
|
||||
</button>
|
||||
<a href="{{ route('admin.guru.downloadPdf', request()->query()) }}" target="_blank" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download PDF
|
||||
</a>
|
||||
<a href="{{ route('admin.guru.downloadExcel', request()->query()) }}" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download Excel
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="GET" action="{{ route('admin.guru.index') }}">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Daftar Guru</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: DejaVu Sans, sans-serif; font-size: 12px; color: #1e293b; padding: 24px; }
|
||||
.header { text-align: center; margin-bottom: 20px; }
|
||||
.header h2 { font-size: 16px; font-weight: 800; margin-bottom: 4px; }
|
||||
.header p { font-size: 11px; color: #64748b; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead tr { background-color: #a5e6ba; }
|
||||
th, td { border: 1px solid #cbd5e1; padding: 7px 9px; text-align: left; }
|
||||
th { font-weight: 700; font-size: 11px; }
|
||||
td { font-size: 11px; }
|
||||
tr:nth-child(even) { background-color: #f8fafc; }
|
||||
.footer { margin-top: 16px; font-size: 10px; color: #94a3b8; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
<h2>DAFTAR GURU</h2>
|
||||
<p>Dicetak pada {{ now()->format('d M Y, H:i') }}</p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">No</th>
|
||||
<th>Nama Lengkap</th>
|
||||
<th>NIP</th>
|
||||
<th>Mata Pelajaran</th>
|
||||
<th>Kelas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($gurus as $i => $guru)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
<td>{{ $guru->nama }}</td>
|
||||
<td>{{ $guru->nip }}</td>
|
||||
<td>
|
||||
@foreach($guru->mengajars as $m)
|
||||
<div>{{ optional($m->mapel)->nama_mapel ?? '-' }}</div>
|
||||
@endforeach
|
||||
</td>
|
||||
<td>
|
||||
@foreach($guru->mengajars as $m)
|
||||
<div>{{ optional($m->kelas)->tingkat }} {{ optional($m->kelas)->nama_kelas }}</div>
|
||||
@endforeach
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="footer">Total: {{ count($gurus) }} guru</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -111,11 +111,18 @@
|
|||
<div class="custom-card">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#modalTambah">
|
||||
<img src="{{ asset('images/icon/main/add.png') }}" width="18">
|
||||
Tambah Data
|
||||
</button>
|
||||
<a href="{{ route('admin.kelas.downloadPdf', request()->query()) }}" target="_blank" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download PDF
|
||||
</a>
|
||||
<a href="{{ route('admin.kelas.downloadExcel', request()->query()) }}" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download Excel
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="GET">
|
||||
<div class="search-box">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Daftar Kelas</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: DejaVu Sans, sans-serif; font-size: 12px; color: #1e293b; padding: 24px; }
|
||||
.header { text-align: center; margin-bottom: 20px; }
|
||||
.header h2 { font-size: 16px; font-weight: 800; margin-bottom: 4px; }
|
||||
.header p { font-size: 11px; color: #64748b; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead tr { background-color: #a5e6ba; }
|
||||
th, td { border: 1px solid #cbd5e1; padding: 7px 9px; text-align: left; }
|
||||
th { font-weight: 700; font-size: 11px; }
|
||||
td { font-size: 11px; }
|
||||
tr:nth-child(even) { background-color: #f8fafc; }
|
||||
.footer { margin-top: 16px; font-size: 10px; color: #94a3b8; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
<h2>DAFTAR KELAS</h2>
|
||||
<p>Dicetak pada {{ now()->format('d M Y, H:i') }}</p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">No</th>
|
||||
<th>ID Kelas</th>
|
||||
<th>Nama Kelas</th>
|
||||
<th>Tingkat</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($kelass as $i => $kelas)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
<td>{{ $kelas->id_kelas }}</td>
|
||||
<td>{{ $kelas->nama_kelas }}</td>
|
||||
<td>{{ $kelas->tingkat }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="footer">Total: {{ count($kelass) }} kelas</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -101,12 +101,18 @@
|
|||
<div class="custom-card">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#modalTambah">
|
||||
<img src="{{ asset('images/icon/main/add.png') }}" width="18">
|
||||
Tambah Data
|
||||
</button>
|
||||
|
||||
<a href="{{ route('admin.mapel.downloadPdf', request()->query()) }}" target="_blank" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download PDF
|
||||
</a>
|
||||
<a href="{{ route('admin.mapel.downloadExcel', request()->query()) }}" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download Excel
|
||||
</a>
|
||||
</div>
|
||||
<form method="GET">
|
||||
<div class="search-box">
|
||||
<input type="text" name="search" placeholder="Cari" value="{{ request('search') }}">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Daftar Mata Pelajaran</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: DejaVu Sans, sans-serif; font-size: 12px; color: #1e293b; padding: 24px; }
|
||||
.header { text-align: center; margin-bottom: 20px; }
|
||||
.header h2 { font-size: 16px; font-weight: 800; margin-bottom: 4px; }
|
||||
.header p { font-size: 11px; color: #64748b; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead tr { background-color: #a5e6ba; }
|
||||
th, td { border: 1px solid #cbd5e1; padding: 7px 9px; text-align: left; }
|
||||
th { font-weight: 700; font-size: 11px; }
|
||||
td { font-size: 11px; }
|
||||
tr:nth-child(even) { background-color: #f8fafc; }
|
||||
.footer { margin-top: 16px; font-size: 10px; color: #94a3b8; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
<h2>DAFTAR MATA PELAJARAN</h2>
|
||||
<p>Dicetak pada {{ now()->format('d M Y, H:i') }}</p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">No</th>
|
||||
<th>ID Mapel</th>
|
||||
<th>Nama Mata Pelajaran</th>
|
||||
<th>Kelas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($mapels as $i => $mapel)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
<td>{{ $mapel->id_mapel }}</td>
|
||||
<td>{{ $mapel->nama_mapel }}</td>
|
||||
<td>
|
||||
@foreach($mapel->kelas as $k)
|
||||
<span>{{ $k->tingkat }} {{ $k->nama_kelas }}</span>@unless($loop->last), @endunless
|
||||
@endforeach
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="footer">Total: {{ count($mapels) }} mata pelajaran</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -110,11 +110,18 @@
|
|||
<div class="custom-card">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<button class="btn-primary-custom" data-bs-toggle="modal" data-bs-target="#modalTambah">
|
||||
<img src="{{ asset('images/icon/main/add.png') }}" width="18">
|
||||
Tambah Data
|
||||
</button>
|
||||
<a href="{{ route('admin.siswa.downloadPdf', request()->query()) }}" target="_blank" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download PDF
|
||||
</a>
|
||||
<a href="{{ route('admin.siswa.downloadExcel', request()->query()) }}" class="btn-primary-custom">
|
||||
<img src="{{ asset('images/icon/main/download.png') }}" width="18" height="18" alt="Download"> Download Excel
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="GET">
|
||||
<div class="search-box">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="id">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Daftar Siswa</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: DejaVu Sans, sans-serif; font-size: 12px; color: #1e293b; padding: 24px; }
|
||||
.header { text-align: center; margin-bottom: 20px; }
|
||||
.header h2 { font-size: 16px; font-weight: 800; margin-bottom: 4px; }
|
||||
.header p { font-size: 11px; color: #64748b; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
thead tr { background-color: #a5e6ba; }
|
||||
th, td { border: 1px solid #cbd5e1; padding: 7px 9px; text-align: left; }
|
||||
th { font-weight: 700; font-size: 11px; }
|
||||
td { font-size: 11px; }
|
||||
tr:nth-child(even) { background-color: #f8fafc; }
|
||||
.footer { margin-top: 16px; font-size: 10px; color: #94a3b8; text-align: right; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="header">
|
||||
<h2>DAFTAR SISWA</h2>
|
||||
<p>Dicetak pada {{ now()->format('d M Y, H:i') }}</p>
|
||||
</div>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:40px">No</th>
|
||||
<th>NISN</th>
|
||||
<th>Nama</th>
|
||||
<th>Tempat Lahir</th>
|
||||
<th>Tanggal Lahir</th>
|
||||
<th>Kelas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($siswas as $i => $siswa)
|
||||
<tr>
|
||||
<td>{{ $i + 1 }}</td>
|
||||
<td>{{ $siswa->nisn }}</td>
|
||||
<td>{{ $siswa->nama }}</td>
|
||||
<td>{{ $siswa->tempat_lahir }}</td>
|
||||
<td>{{ \Carbon\Carbon::parse($siswa->tanggal_lahir)->format('d M Y') }}</td>
|
||||
<td>{{ $siswa->kelas->tingkat }} - {{ $siswa->kelas->nama_kelas }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="footer">Total: {{ count($siswas) }} siswa</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -4,46 +4,29 @@
|
|||
|
||||
@push('styles')
|
||||
<style>
|
||||
/* ─────────────────────────────────────────
|
||||
SEMBUNYIKAN SIDEBAR APP + TOGGLE
|
||||
Hanya sembunyikan elemen navigasi,
|
||||
bukan semua .sidebar agar tidak rusak
|
||||
───────────────────────────────────────── */
|
||||
.siswa-wrapper .sidebar,
|
||||
.siswa-wrapper [class*="sidebar"]:not(.quiz-sidebar-panel),
|
||||
.sidebar-toggle-btn {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Paksa main content pakai full width */
|
||||
/* Sembunyikan sidebar navigasi app */
|
||||
.siswa-wrapper .nav-sidebar,
|
||||
.siswa-wrapper aside.sidebar,
|
||||
.sidebar-toggle-btn { display: none !important; }
|
||||
.siswa-wrapper .main,
|
||||
.siswa-wrapper .main-content,
|
||||
.siswa-wrapper > div:not(.sidebar):not([class*="sidebar"]) {
|
||||
.siswa-wrapper .main-content {
|
||||
margin-left: 0 !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
/* Paksa .content tidak punya padding aneh */
|
||||
.content {
|
||||
padding: 16px 20px 40px !important;
|
||||
}
|
||||
|
||||
/* ─────────────────────────────────────────
|
||||
LAYOUT UTAMA — 2 KOLOM
|
||||
LAYOUT
|
||||
───────────────────────────────────────── */
|
||||
.quiz-page {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 272px;
|
||||
gap: 20px;
|
||||
max-width: 1100px;
|
||||
max-width: 1080px;
|
||||
margin: 0 auto;
|
||||
padding: 20px 16px 48px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
/* ─────────────────────────────────────────
|
||||
KOLOM KIRI
|
||||
───────────────────────────────────────── */
|
||||
.quiz-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
|
@ -70,7 +53,6 @@
|
|||
gap: 8px;
|
||||
}
|
||||
.quiz-title img { width: 22px; height: 22px; object-fit: contain; }
|
||||
|
||||
.quiz-meta {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
|
@ -91,6 +73,20 @@
|
|||
}
|
||||
.quiz-meta img { width: 13px; height: 13px; object-fit: contain; }
|
||||
|
||||
/* Durasi badge di header */
|
||||
.durasi-meta-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #5b21b6;
|
||||
background: #ede9fe;
|
||||
border: 1px solid #c4b5fd;
|
||||
border-radius: 99px;
|
||||
padding: 4px 12px;
|
||||
}
|
||||
|
||||
/* Progress */
|
||||
.progress-card {
|
||||
background: #fff;
|
||||
|
|
@ -131,7 +127,6 @@
|
|||
display: none;
|
||||
}
|
||||
.soal-card.active { display: block; }
|
||||
|
||||
.soal-number {
|
||||
display: inline-block;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
|
|
@ -149,8 +144,6 @@
|
|||
line-height: 1.7;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* Opsi */
|
||||
.opsi-list { display: flex; flex-direction: column; gap: 9px; }
|
||||
.opsi-item {
|
||||
display: flex;
|
||||
|
|
@ -174,7 +167,6 @@
|
|||
font-weight: 600;
|
||||
}
|
||||
.opsi-item input[type="radio"] { display: none; }
|
||||
|
||||
.opsi-label-circle {
|
||||
width: 30px; height: 30px;
|
||||
border-radius: 50%;
|
||||
|
|
@ -186,7 +178,7 @@
|
|||
}
|
||||
.opsi-item.selected .opsi-label-circle { background: #667eea; color: #fff; }
|
||||
|
||||
/* Tombol navigasi */
|
||||
/* Nav buttons */
|
||||
.nav-buttons-card {
|
||||
background: #fff;
|
||||
border: 1.5px solid #e2e8f0;
|
||||
|
|
@ -210,7 +202,6 @@
|
|||
transition: all 0.18s;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
.btn-nav img { width: 15px; height: 15px; object-fit: contain; }
|
||||
.btn-prev { background: #f1f5f9; color: #475569; }
|
||||
.btn-prev:hover:not(:disabled) { background: #e2e8f0; }
|
||||
.btn-prev:disabled { opacity: 0.4; cursor: not-allowed; }
|
||||
|
|
@ -218,6 +209,7 @@
|
|||
.btn-next:hover { opacity: 0.88; }
|
||||
.btn-submit { background: linear-gradient(135deg, #22c55e, #16a34a); color: #fff; display: none; }
|
||||
.btn-submit:hover { opacity: 0.88; }
|
||||
.target-selesai{ width: 15px; height: 15px; object-fit: contain; }
|
||||
|
||||
/* Warning */
|
||||
.warning-box {
|
||||
|
|
@ -236,7 +228,7 @@
|
|||
.warning-box img { width: 15px; height: 15px; object-fit: contain; flex-shrink: 0; }
|
||||
|
||||
/* ─────────────────────────────────────────
|
||||
KOLOM KANAN — SIDEBAR QUIZ
|
||||
SIDEBAR QUIZ
|
||||
───────────────────────────────────────── */
|
||||
.quiz-sidebar-panel {
|
||||
display: flex;
|
||||
|
|
@ -260,13 +252,22 @@
|
|||
color: #94a3b8;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.timer-label img { width: 13px; height: 13px; object-fit: contain; }
|
||||
|
||||
/* Baris total durasi (kecil, di bawah label) */
|
||||
.timer-total-info {
|
||||
font-size: 11px;
|
||||
color: #a78bfa;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.timer-display {
|
||||
font-size: 34px;
|
||||
font-weight: 800;
|
||||
|
|
@ -305,23 +306,18 @@
|
|||
padding: 18px 20px;
|
||||
}
|
||||
.nav-card-label {
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
font-size: 10px; font-weight: 700;
|
||||
color: #94a3b8;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
display: flex; align-items: center; gap: 6px;
|
||||
}
|
||||
.nav-card-label img { width: 13px; height: 13px; object-fit: contain; }
|
||||
|
||||
.nav-summary {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 8px;
|
||||
margin-bottom: 14px;
|
||||
gap: 8px; margin-bottom: 14px;
|
||||
}
|
||||
.summary-item {
|
||||
text-align: center;
|
||||
|
|
@ -334,59 +330,40 @@
|
|||
.summary-label { font-size: 10px; color: #94a3b8; font-weight: 500; margin-top: 2px; }
|
||||
.summary-item.answered-sum .summary-num { color: #22c55e; }
|
||||
.summary-item.unanswered-sum .summary-num { color: #94a3b8; }
|
||||
|
||||
.nav-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 7px;
|
||||
margin-bottom: 14px;
|
||||
gap: 7px; margin-bottom: 14px;
|
||||
}
|
||||
.nav-btn {
|
||||
aspect-ratio: 1;
|
||||
border-radius: 9px;
|
||||
border: 1.5px solid #e2e8f0;
|
||||
background: #f8fafc;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #64748b;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 12px; font-weight: 700;
|
||||
color: #64748b; cursor: pointer;
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
transition: all 0.15s;
|
||||
font-family: 'Poppins', sans-serif;
|
||||
}
|
||||
.nav-btn:hover { border-color: #667eea; background: #f0eeff; color: #667eea; }
|
||||
.nav-btn.active { background: #667eea; border-color: #667eea; color: #fff; }
|
||||
.nav-btn.answered { background: #dcfce7; border-color: #22c55e; color: #16a34a; }
|
||||
.nav-btn.active.answered { background: #22c55e; border-color: #22c55e; color: #fff; }
|
||||
|
||||
.nav-btn:hover { border-color: #667eea; background: #f0eeff; color: #667eea; }
|
||||
.nav-btn.active { background: #667eea; border-color: #667eea; color: #fff; }
|
||||
.nav-btn.answered { background: #dcfce7; border-color: #22c55e; color: #16a34a; }
|
||||
.nav-btn.active.answered { background: #22c55e; border-color: #22c55e; color: #fff; }
|
||||
.nav-legend {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding-top: 12px;
|
||||
display: flex; flex-direction: column;
|
||||
gap: 5px; padding-top: 12px;
|
||||
border-top: 1px solid #f1f5f9;
|
||||
}
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
font-size: 11px;
|
||||
color: #64748b;
|
||||
}
|
||||
.legend-dot {
|
||||
width: 13px; height: 13px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
display: flex; align-items: center;
|
||||
gap: 7px; font-size: 11px; color: #64748b;
|
||||
}
|
||||
.legend-dot { width: 13px; height: 13px; border-radius: 4px; flex-shrink: 0; }
|
||||
.legend-dot.current { background: #667eea; }
|
||||
.legend-dot.done { background: #dcfce7; border: 1.5px solid #22c55e; }
|
||||
.legend-dot.undone { background: #f8fafc; border: 1.5px solid #e2e8f0; }
|
||||
|
||||
/* ─────────────────────────────────────────
|
||||
RESPONSIVE
|
||||
───────────────────────────────────────── */
|
||||
@media (max-width: 768px) {
|
||||
.quiz-page { grid-template-columns: 1fr; }
|
||||
.quiz-sidebar-panel { position: static; order: -1; }
|
||||
|
|
@ -399,29 +376,33 @@
|
|||
|
||||
<div class="quiz-page">
|
||||
|
||||
{{-- ══════════════════════════════
|
||||
KOLOM KIRI — Soal
|
||||
══════════════════════════════ --}}
|
||||
{{-- KOLOM KIRI --}}
|
||||
<div class="quiz-main">
|
||||
|
||||
<div class="quiz-header">
|
||||
<div class="quiz-title">
|
||||
<img src="{{ asset('images/icon/siswac/piala.png') }}" alt="Ikon piala">
|
||||
<img src="{{ asset('images/icon/siswac/piala.png') }}" alt="">
|
||||
{{ $challenge->judul_challenge }}
|
||||
</div>
|
||||
<div class="quiz-meta">
|
||||
<span>
|
||||
<img src="{{ asset('images/icon/siswac/buku1.png') }}" alt="Jumlah soal">
|
||||
<img src="{{ asset('images/icon/siswac/buku1.png') }}" alt="">
|
||||
{{ $challenge->soal->count() }} Soal
|
||||
</span>
|
||||
<span>
|
||||
<img src="{{ asset('images/icon/siswac/star.png') }}" alt="EXP">
|
||||
<img src="{{ asset('images/icon/siswac/star.png') }}" alt="">
|
||||
{{ $challenge->exp }} EXP
|
||||
</span>
|
||||
<span>
|
||||
<img src="{{ asset('images/icon/siswac/alarm.png') }}" alt="Tenggat waktu">
|
||||
<img src="{{ asset('images/icon/siswac/alarm.png') }}" alt="">
|
||||
Tenggat: {{ \Carbon\Carbon::parse($challenge->tenggat_waktu)->format('d M Y, H:i') }}
|
||||
</span>
|
||||
{{-- Badge durasi --}}
|
||||
@if($challenge->durasi_pengerjaan)
|
||||
<span class="durasi-meta-badge">
|
||||
⏱ {{ $challenge->durasi_pengerjaan }} menit pengerjaan
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -460,7 +441,7 @@
|
|||
@endforeach
|
||||
|
||||
<div class="warning-box" id="warningBox">
|
||||
<img src="{{ asset('images/icon/siswac/alert.png') }}" alt="Peringatan">
|
||||
<img src="{{ asset('images/icon/siswac/alert.png') }}" alt="">
|
||||
Masih ada <span id="warningCount"></span> soal yang belum dijawab. Yakin ingin submit?
|
||||
</div>
|
||||
|
||||
|
|
@ -471,7 +452,7 @@
|
|||
onclick="nextSoal()">Selanjutnya →</button>
|
||||
<button type="submit" class="btn-nav btn-submit" id="btnSubmit"
|
||||
onclick="return konfirmasiSubmit()">
|
||||
<img src="{{ asset('images/icon/siswac/target.png') }}" alt="Submit">
|
||||
<img src="{{ asset('images/icon/siswac/target.png') }}" class="target-selesai" alt="Submit">
|
||||
Selesai & Submit
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -480,16 +461,20 @@
|
|||
</div>{{-- /quiz-main --}}
|
||||
|
||||
|
||||
{{-- ══════════════════════════════
|
||||
KOLOM KANAN — Sidebar Quiz
|
||||
══════════════════════════════ --}}
|
||||
{{-- KOLOM KANAN --}}
|
||||
<div class="quiz-sidebar-panel">
|
||||
|
||||
<div class="timer-card">
|
||||
<div class="timer-label">
|
||||
<img src="{{ asset('images/icon/siswac/alarm.png') }}" alt="Timer">
|
||||
<img src="{{ asset('images/icon/siswac/alarm.png') }}" alt="">
|
||||
Sisa Waktu
|
||||
</div>
|
||||
{{-- Info total durasi --}}
|
||||
@if($challenge->durasi_pengerjaan)
|
||||
<div class="timer-total-info">
|
||||
dari {{ $challenge->durasi_pengerjaan }} menit
|
||||
</div>
|
||||
@endif
|
||||
<div class="timer-display" id="timerDisplay">--:--</div>
|
||||
<div class="timer-bar-wrap">
|
||||
<div class="timer-bar-fill" id="timerBar" style="width:100%"></div>
|
||||
|
|
@ -498,10 +483,9 @@
|
|||
|
||||
<div class="nav-card">
|
||||
<div class="nav-card-label">
|
||||
<img src="{{ asset('images/icon/siswac/buku1.png') }}" alt="Navigasi soal">
|
||||
<img src="{{ asset('images/icon/siswac/buku1.png') }}" alt="">
|
||||
Navigasi Soal
|
||||
</div>
|
||||
|
||||
<div class="nav-summary">
|
||||
<div class="summary-item answered-sum">
|
||||
<div class="summary-num" id="summaryAnswered">0</div>
|
||||
|
|
@ -512,7 +496,6 @@
|
|||
<div class="summary-label">Belum</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-grid" id="navGrid">
|
||||
@foreach($challenge->soal as $i => $soal)
|
||||
<button type="button"
|
||||
|
|
@ -523,20 +506,10 @@ class="nav-btn {{ $i === 0 ? 'active' : '' }}"
|
|||
</button>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<div class="nav-legend">
|
||||
<div class="legend-item">
|
||||
<div class="legend-dot current"></div>
|
||||
<span>Soal aktif</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-dot done"></div>
|
||||
<span>Sudah dijawab</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<div class="legend-dot undone"></div>
|
||||
<span>Belum dijawab</span>
|
||||
</div>
|
||||
<div class="legend-item"><div class="legend-dot current"></div><span>Soal aktif</span></div>
|
||||
<div class="legend-item"><div class="legend-dot done"></div><span>Sudah dijawab</span></div>
|
||||
<div class="legend-item"><div class="legend-dot undone"></div><span>Belum dijawab</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -552,23 +525,46 @@ class="nav-btn {{ $i === 0 ? 'active' : '' }}"
|
|||
let currentSoal = 0;
|
||||
let jawaban = {};
|
||||
|
||||
// ══════════════════════════════════════════════════════════
|
||||
// FIX TIMER — pakai timestamp detik dari server, kalikan
|
||||
// 1000 di JS. Ini cara paling reliable lintas timezone.
|
||||
// Carbon::parse()->timestamp = Unix timestamp dalam DETIK
|
||||
// ══════════════════════════════════════════════════════════
|
||||
const tenggatMs = {{ \Carbon\Carbon::parse($challenge->tenggat_waktu)->timestamp }} * 1000;
|
||||
const totalDetik = Math.max(0, Math.floor((tenggatMs - Date.now()) / 1000));
|
||||
let sisaDetik = totalDetik;
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// TIMER — menggunakan durasi_pengerjaan (menit) dari database
|
||||
//
|
||||
// Logika:
|
||||
// 1. Jika ada durasi_pengerjaan → hitung mundur dari durasi tsb
|
||||
// 2. Jika tidak ada durasi_pengerjaan (null) → fallback ke tenggat
|
||||
// 3. Ambil waktu mulai dari sessionStorage agar konsisten
|
||||
// jika halaman di-refresh (timer tidak reset)
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
@if($challenge->durasi_pengerjaan)
|
||||
// Durasi dalam detik
|
||||
const DURASI_DETIK = {{ (int)$challenge->durasi_pengerjaan * 60 }};
|
||||
|
||||
// Simpan waktu mulai ke sessionStorage agar tidak reset saat refresh
|
||||
const SESSION_KEY = 'quiz_start_{{ $challenge->id_challenge }}';
|
||||
let startTime = parseInt(sessionStorage.getItem(SESSION_KEY) || '0');
|
||||
if (!startTime) {
|
||||
startTime = Date.now();
|
||||
sessionStorage.setItem(SESSION_KEY, startTime);
|
||||
}
|
||||
|
||||
// Hitung sisa detik berdasarkan waktu mulai
|
||||
const totalDetik = DURASI_DETIK;
|
||||
let sisaDetik = Math.max(0, DURASI_DETIK - Math.floor((Date.now() - startTime) / 1000));
|
||||
|
||||
@else
|
||||
// Fallback: pakai tenggat waktu
|
||||
const tenggatMs = {{ \Carbon\Carbon::parse($challenge->tenggat_waktu)->timestamp }} * 1000;
|
||||
const totalDetik = Math.max(0, Math.floor((tenggatMs - Date.now()) / 1000));
|
||||
let sisaDetik = totalDetik;
|
||||
@endif
|
||||
|
||||
const elTimer = document.getElementById('timerDisplay');
|
||||
const elTimerBar = document.getElementById('timerBar');
|
||||
|
||||
function formatWaktu(s) {
|
||||
if (s <= 0) return '00:00';
|
||||
const j = Math.floor(s / 3600);
|
||||
const m = Math.floor((s % 3600) / 60);
|
||||
const d = s % 60;
|
||||
const j = Math.floor(s / 3600);
|
||||
const m = Math.floor((s % 3600) / 60);
|
||||
const d = s % 60;
|
||||
const mm = String(m).padStart(2, '0');
|
||||
const ss = String(d).padStart(2, '0');
|
||||
if (j > 0) return `${String(j).padStart(2,'0')}:${mm}:${ss}`;
|
||||
|
|
@ -578,15 +574,14 @@ function formatWaktu(s) {
|
|||
function updateTimer() {
|
||||
elTimer.textContent = formatWaktu(sisaDetik);
|
||||
|
||||
// Progress bar timer
|
||||
const pct = totalDetik > 0 ? (sisaDetik / totalDetik) * 100 : 0;
|
||||
elTimerBar.style.width = pct + '%';
|
||||
|
||||
// State warna
|
||||
if (sisaDetik <= 60) {
|
||||
elTimer.className = 'timer-display danger';
|
||||
elTimerBar.className = 'timer-bar-fill danger';
|
||||
} else if (sisaDetik <= 300) {
|
||||
} else if (sisaDetik <= Math.floor(totalDetik * 0.25)) {
|
||||
// Kuning saat sisa ≤ 25% dari total durasi
|
||||
elTimer.className = 'timer-display warning';
|
||||
elTimerBar.className = 'timer-bar-fill warning';
|
||||
} else {
|
||||
|
|
@ -597,6 +592,9 @@ function updateTimer() {
|
|||
if (sisaDetik <= 0) {
|
||||
clearInterval(timerInterval);
|
||||
elTimer.textContent = '00:00';
|
||||
@if($challenge->durasi_pengerjaan)
|
||||
sessionStorage.removeItem('quiz_start_{{ $challenge->id_challenge }}');
|
||||
@endif
|
||||
alert('Waktu habis! Jawaban kamu akan otomatis dikumpulkan.');
|
||||
document.getElementById('quizForm').submit();
|
||||
return;
|
||||
|
|
@ -608,18 +606,15 @@ function updateTimer() {
|
|||
const timerInterval = setInterval(updateTimer, 1000);
|
||||
|
||||
|
||||
// ══════════════════════════════════════════
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
// NAVIGASI SOAL
|
||||
// ══════════════════════════════════════════
|
||||
// ═══════════════════════════════════════════════════════════════════
|
||||
function goToSoal(index) {
|
||||
document.getElementById(`soal-${currentSoal}`).classList.remove('active');
|
||||
document.getElementById(`navBtn-${currentSoal}`).classList.remove('active');
|
||||
|
||||
currentSoal = index;
|
||||
|
||||
document.getElementById(`soal-${currentSoal}`).classList.add('active');
|
||||
document.getElementById(`navBtn-${currentSoal}`).classList.add('active');
|
||||
|
||||
updateNav();
|
||||
updateProgress();
|
||||
}
|
||||
|
|
@ -629,14 +624,12 @@ function prevSoal() { if (currentSoal > 0) goToSoal(currentSoal - 1)
|
|||
|
||||
function pilihJawaban(soalIndex, opsi, idSoal) {
|
||||
jawaban[soalIndex] = opsi;
|
||||
|
||||
['A','B','C','D'].forEach(o => {
|
||||
document.getElementById(`label-${soalIndex}-${o}`)?.classList.remove('selected');
|
||||
});
|
||||
document.getElementById(`label-${soalIndex}-${opsi}`)?.classList.add('selected');
|
||||
document.getElementById(`radio-${soalIndex}-${opsi}`).checked = true;
|
||||
document.getElementById(`navBtn-${soalIndex}`)?.classList.add('answered');
|
||||
|
||||
updateProgress();
|
||||
updateSummary();
|
||||
}
|
||||
|
|
@ -645,9 +638,7 @@ function updateNav() {
|
|||
const btnPrev = document.getElementById('btnPrev');
|
||||
const btnNext = document.getElementById('btnNext');
|
||||
const btnSubmit = document.getElementById('btnSubmit');
|
||||
|
||||
btnPrev.disabled = (currentSoal === 0);
|
||||
|
||||
if (currentSoal === totalSoal - 1) {
|
||||
btnNext.style.display = 'none';
|
||||
btnSubmit.style.display = 'inline-flex';
|
||||
|
|
@ -678,6 +669,10 @@ function konfirmasiSubmit() {
|
|||
document.getElementById('warningBox').style.display = 'flex';
|
||||
return confirm(`Masih ada ${belum} soal yang belum dijawab. Yakin ingin submit?`);
|
||||
}
|
||||
@if($challenge->durasi_pengerjaan)
|
||||
// Bersihkan session timer setelah submit
|
||||
sessionStorage.removeItem('quiz_start_{{ $challenge->id_challenge }}');
|
||||
@endif
|
||||
return confirm('Yakin ingin submit jawaban? Jawaban tidak bisa diubah setelah submit.');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span class="page-link">{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
|
||||
@else
|
||||
<li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav class="d-flex justify-items-center justify-content-between align-items-center mt-2">
|
||||
|
||||
{{-- Info teks --}}
|
||||
<p style="font-size:13px;color:#64748b;margin:0">
|
||||
Menampilkan
|
||||
<span style="font-weight:700;color:#1e293b">{{ $paginator->firstItem() }}</span>
|
||||
–
|
||||
<span style="font-weight:700;color:#1e293b">{{ $paginator->lastItem() }}</span>
|
||||
dari
|
||||
<span style="font-weight:700;color:#1e293b">{{ $paginator->total() }}</span>
|
||||
data
|
||||
</p>
|
||||
|
||||
{{-- Tombol pagination --}}
|
||||
<ul style="display:flex;align-items:center;gap:6px;list-style:none;margin:0;padding:0">
|
||||
|
||||
{{-- Prev --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li>
|
||||
<span style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#f1f5f9;color:#cbd5e1;
|
||||
font-size:16px;font-weight:700;cursor:not-allowed;
|
||||
border:1.5px solid #e2e8f0;
|
||||
">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#fff;color:#2b8ef3;
|
||||
font-size:16px;font-weight:700;
|
||||
border:1.5px solid #2b8ef3;
|
||||
text-decoration:none;transition:all 0.2s;
|
||||
"
|
||||
onmouseover="this.style.background='#2b8ef3';this.style.color='#fff'"
|
||||
onmouseout="this.style.background='#fff';this.style.color='#2b8ef3'"
|
||||
>‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Nomor halaman --}}
|
||||
@foreach ($elements as $element)
|
||||
@if (is_string($element))
|
||||
<li>
|
||||
<span style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#f1f5f9;color:#94a3b8;
|
||||
font-size:13px;font-weight:700;
|
||||
border:1.5px solid #e2e8f0;
|
||||
">…</span>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li>
|
||||
<span style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#2b8ef3;color:#fff;
|
||||
font-size:13px;font-weight:700;
|
||||
border:1.5px solid #2b8ef3;
|
||||
">{{ $page }}</span>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<a href="{{ $url }}" style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#fff;color:#475569;
|
||||
font-size:13px;font-weight:600;
|
||||
border:1.5px solid #e2e8f0;
|
||||
text-decoration:none;transition:all 0.2s;
|
||||
"
|
||||
onmouseover="this.style.background='#e6f0ff';this.style.borderColor='#2b8ef3';this.style.color='#2b8ef3'"
|
||||
onmouseout="this.style.background='#fff';this.style.borderColor='#e2e8f0';this.style.color='#475569'"
|
||||
>{{ $page }}</a>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li>
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#fff;color:#2b8ef3;
|
||||
font-size:16px;font-weight:700;
|
||||
border:1.5px solid #2b8ef3;
|
||||
text-decoration:none;transition:all 0.2s;
|
||||
"
|
||||
onmouseover="this.style.background='#2b8ef3';this.style.color='#fff'"
|
||||
onmouseout="this.style.background='#fff';this.style.color='#2b8ef3'"
|
||||
>›</a>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<span style="
|
||||
display:inline-flex;align-items:center;justify-content:center;
|
||||
width:34px;height:34px;border-radius:10px;
|
||||
background:#f1f5f9;color:#cbd5e1;
|
||||
font-size:16px;font-weight:700;cursor:not-allowed;
|
||||
border:1.5px solid #e2e8f0;
|
||||
">›</span>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
|
||||
<span aria-hidden="true">‹</span>
|
||||
</li>
|
||||
@else
|
||||
<li>
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">‹</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="disabled" aria-disabled="true"><span>{{ $element }}</span></li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="active" aria-current="page"><span>{{ $page }}</span></li>
|
||||
@else
|
||||
<li><a href="{{ $url }}">{{ $page }}</a></li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li>
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">›</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
|
||||
<span aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
@if ($paginator->hasPages())
|
||||
<div class="ui pagination menu" role="navigation">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')"> <i class="left chevron icon"></i> </a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<a class="icon item disabled" aria-disabled="true">{{ $element }}</a>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<a class="item active" href="{{ $url }}" aria-current="page">{{ $page }}</a>
|
||||
@else
|
||||
<a class="item" href="{{ $url }}">{{ $page }}</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a class="icon item" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
|
||||
@else
|
||||
<a class="icon item disabled" aria-disabled="true" aria-label="@lang('pagination.next')"> <i class="right chevron icon"></i> </a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.previous')</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">@lang('pagination.next')</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="{!! __('Pagination Navigation') !!}">
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.previous') !!}</span>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next">{!! __('pagination.next') !!}</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" aria-disabled="true">
|
||||
<span class="page-link">{!! __('pagination.next') !!}</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.previous')</span></li>
|
||||
@else
|
||||
<li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">@lang('pagination.previous')</a></li>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li><a href="{{ $paginator->nextPageUrl() }}" rel="next">@lang('pagination.next')</a></li>
|
||||
@else
|
||||
<li class="disabled" aria-disabled="true"><span>@lang('pagination.next')</span></li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="{!! __('Pagination Navigation') !!}" class="flex justify-between">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav role="navigation" aria-label="{{ __('Pagination Navigation') }}" class="flex items-center justify-between">
|
||||
<div class="flex justify-between flex-1 sm:hidden">
|
||||
@if ($paginator->onFirstPage())
|
||||
<span class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.previous') !!}
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.previous') !!}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-300 dark:focus:border-blue-700 dark:active:bg-gray-700 dark:active:text-gray-300">
|
||||
{!! __('pagination.next') !!}
|
||||
</a>
|
||||
@else
|
||||
<span class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md dark:text-gray-600 dark:bg-gray-800 dark:border-gray-600">
|
||||
{!! __('pagination.next') !!}
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-700 leading-5 dark:text-gray-400">
|
||||
{!! __('Showing') !!}
|
||||
@if ($paginator->firstItem())
|
||||
<span class="font-medium">{{ $paginator->firstItem() }}</span>
|
||||
{!! __('to') !!}
|
||||
<span class="font-medium">{{ $paginator->lastItem() }}</span>
|
||||
@else
|
||||
{{ $paginator->count() }}
|
||||
@endif
|
||||
{!! __('of') !!}
|
||||
<span class="font-medium">{{ $paginator->total() }}</span>
|
||||
{!! __('results') !!}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="relative z-0 inline-flex rtl:flex-row-reverse shadow-sm rounded-md">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.previous') }}">
|
||||
<span class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $paginator->previousPageUrl() }}" rel="prev" class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.previous') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<span aria-disabled="true">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600">{{ $element }}</span>
|
||||
</span>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<span aria-current="page">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 dark:bg-gray-800 dark:border-gray-600">{{ $page }}</span>
|
||||
</span>
|
||||
@else
|
||||
<a href="{{ $url }}" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400 dark:hover:text-gray-300 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('Go to page :page', ['page' => $page]) }}">
|
||||
{{ $page }}
|
||||
</a>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<a href="{{ $paginator->nextPageUrl() }}" rel="next" class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150 dark:bg-gray-800 dark:border-gray-600 dark:active:bg-gray-700 dark:focus:border-blue-800" aria-label="{{ __('pagination.next') }}">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</a>
|
||||
@else
|
||||
<span aria-disabled="true" aria-label="{{ __('pagination.next') }}">
|
||||
<span class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5 dark:bg-gray-800 dark:border-gray-600" aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
@endif
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@endif
|
||||
|
|
@ -85,20 +85,32 @@
|
|||
Route::middleware(['auth:admin'])->prefix('admin')->name('admin.')->group(function () {
|
||||
|
||||
// DASHBOARD
|
||||
Route::get('/dashboard', [AdminController::class, 'dashboard'])->name('dashboard');
|
||||
Route::get('/dashboard',[AdminController::class, 'dashboard'])->name('dashboard');
|
||||
|
||||
// PROFILE
|
||||
Route::get('/profile', [AdminProfileController::class, 'edit'])->name('profile.edit');
|
||||
Route::post('/profile', [AdminProfileController::class, 'updateAjax'])->name('profile.update');
|
||||
Route::get('/profile', [AdminProfileController::class, 'edit'])->name('profile.edit');
|
||||
Route::post('/profile',[AdminProfileController::class, 'updateAjax'])->name('profile.update');
|
||||
|
||||
//GURU
|
||||
// GURU
|
||||
Route::get('/guru/kelas-by-mapel', [AdminGuruController::class, 'getKelasByMapel'])
|
||||
->name('guru.kelasByMapel');
|
||||
Route::get('guru/download-pdf', [AdminGuruController::class, 'downloadPdf'])->name('guru.downloadPdf');
|
||||
Route::get('guru/download-excel', [AdminGuruController::class, 'downloadExcel'])->name('guru.downloadExcel');
|
||||
Route::resource('guru', AdminGuruController::class);
|
||||
|
||||
//SISWA KELAS DAN MAPEL
|
||||
// SISWA
|
||||
Route::get('siswa/download-pdf', [AdminSiswaController::class, 'downloadPdf'])->name('siswa.downloadPdf');
|
||||
Route::get('siswa/download-excel', [AdminSiswaController::class, 'downloadExcel'])->name('siswa.downloadExcel');
|
||||
Route::resource('siswa', AdminSiswaController::class);
|
||||
|
||||
// KELAS
|
||||
Route::get('kelas/download-pdf', [AdminKelasController::class, 'downloadPdf'])->name('kelas.downloadPdf');
|
||||
Route::get('kelas/download-excel', [AdminKelasController::class, 'downloadExcel'])->name('kelas.downloadExcel');
|
||||
Route::resource('kelas', AdminKelasController::class);
|
||||
|
||||
// MAPEL
|
||||
Route::get('mapel/download-pdf', [AdminMapelController::class, 'downloadPdf'])->name('mapel.downloadPdf');
|
||||
Route::get('mapel/download-excel', [AdminMapelController::class, 'downloadExcel'])->name('mapel.downloadExcel');
|
||||
Route::resource('mapel', AdminMapelController::class);
|
||||
|
||||
//HISTORI MATERI
|
||||
|
|
@ -106,12 +118,12 @@
|
|||
Route::delete('/materi/{id}', [AdminMateriTugasController::class, 'destroyMateri'])->name('materi.destroy');
|
||||
|
||||
//HISTRORY TUGAS
|
||||
Route::get('/tugas/history', [AdminMateriTugasController::class, 'historyTugas'])->name('tugas.history');
|
||||
Route::get('/tugas/{id}/detail', [AdminMateriTugasController::class, 'detailTugas'])->name('tugas.detail');
|
||||
Route::delete('/tugas/{id}', [AdminMateriTugasController::class, 'destroyTugas'])->name('tugas.destroy');
|
||||
Route::get('/tugas/history',[AdminMateriTugasController::class, 'historyTugas'])->name('tugas.history');
|
||||
Route::get('/tugas/{id}/detail',[AdminMateriTugasController::class, 'detailTugas'])->name('tugas.detail');
|
||||
Route::delete('/tugas/{id}',[AdminMateriTugasController::class, 'destroyTugas'])->name('tugas.destroy');
|
||||
|
||||
//CHALLENGE
|
||||
Route::get('/challenge/{id}/edit-data', [AdminChallengeController::class, 'editData'])
|
||||
Route::get('/challenge/{id}/edit-data',[AdminChallengeController::class, 'editData'])
|
||||
->name('challenge.editData');
|
||||
Route::resource('challenge', AdminChallengeController::class);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue