parent
4274e67e10
commit
c0d7a893cf
|
|
@ -29,35 +29,57 @@ public function login(Request $request)
|
||||||
|
|
||||||
if (Auth::attempt($credentials)) {
|
if (Auth::attempt($credentials)) {
|
||||||
|
|
||||||
|
$request->session()->regenerate();
|
||||||
|
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
|
||||||
// ================= WA =================
|
// 🔥 HANYA JIKA PASSWORD DEFAULT
|
||||||
$telepon = $user->getTeleponLengkap();
|
if ($user->is_default_password) {
|
||||||
|
|
||||||
if ($telepon) {
|
// ================= EMAIL =================
|
||||||
$no = preg_replace('/^0/', '62', $telepon);
|
Mail::to($user->email)->send(new LoginNotification($user));
|
||||||
|
|
||||||
$pesan = "🔐 LOGIN BERHASIL\n";
|
// ================= WHATSAPP =================
|
||||||
$pesan .= "User: {$user->name}\n";
|
$telepon = $user->getTeleponLengkap();
|
||||||
$pesan .= "Email: {$user->email}\n";
|
|
||||||
$pesan .= "Waktu: " . now();
|
|
||||||
|
|
||||||
Http::asForm()->withHeaders([
|
if ($telepon) {
|
||||||
'Authorization' => env('FONNTE_TOKEN')
|
|
||||||
])->post('https://api.fonnte.com/send', [
|
// normalisasi nomor
|
||||||
'target' => $no,
|
$no = preg_replace('/[^0-9]/', '', $telepon);
|
||||||
'message' => $pesan,
|
if (substr($no, 0, 1) == '0') {
|
||||||
]);
|
$no = '62' . substr($no, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pesan = "🔐 LOGIN PERTAMA\n";
|
||||||
|
$pesan .= "Nama: {$user->name}\n";
|
||||||
|
$pesan .= "Email: {$user->email}\n";
|
||||||
|
$pesan .= "Gunakan password default\n";
|
||||||
|
$pesan .= "Segera ganti password!\n";
|
||||||
|
$pesan .= "Waktu: " . now();
|
||||||
|
|
||||||
|
Http::asForm()->withHeaders([
|
||||||
|
'Authorization' => env('FONNTE_TOKEN')
|
||||||
|
])->post('https://api.fonnte.com/send', [
|
||||||
|
'target' => $no,
|
||||||
|
'message' => $pesan,
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================= REDIRECT ROLE =================
|
// 🔥 REDIRECT ROLE
|
||||||
if ($user->role == 'admin') {
|
if ($user->role == 'admin') {
|
||||||
return redirect('/admin');
|
return redirect()->route('admin.dashboard');
|
||||||
} elseif ($user->role == 'guru') {
|
|
||||||
return redirect('/guru');
|
|
||||||
} else {
|
|
||||||
return redirect('/siswa');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user->role == 'guru') {
|
||||||
|
return redirect()->route('guru.dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->role == 'siswa') {
|
||||||
|
return redirect()->route('siswa.dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
return back()->with('error', 'Email atau password salah');
|
return back()->with('error', 'Email atau password salah');
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ public function dashboard()
|
||||||
// ================= INDEX =================
|
// ================= INDEX =================
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$guru = Guru::with('user')->get();
|
$guru = Guru::with(['user', 'mapel'])->get();
|
||||||
return view('admin.guru.index', compact('guru'));
|
return view('admin.guru.index', compact('guru'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,42 +32,45 @@ public function create()
|
||||||
|
|
||||||
// ================= STORE =================
|
// ================= STORE =================
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
'nama' => 'required',
|
'nama' => 'required',
|
||||||
'nip' => 'required|unique:gurus,nip',
|
'nip' => 'required|unique:gurus,nip',
|
||||||
'mapel_id' => 'required',
|
'mapel_id' => 'required',
|
||||||
'alamat' => 'required',
|
'alamat' => 'required',
|
||||||
'telepon' => 'required',
|
'telepon' => 'required',
|
||||||
'email' => 'required|email|unique:users,email'
|
'email' => 'required|email|unique:users,email'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 🔥 SIMPAN GURU
|
// 🔥 CEK JIKA SUDAH ADA (ANTI DOUBLE INSERT)
|
||||||
$guru = Guru::create([
|
if (Guru::where('nip', $request->nip)->exists()) {
|
||||||
'nama' => $request->nama,
|
return back()->withErrors(['nip' => 'NIP sudah ada'])->withInput();
|
||||||
'nip' => $request->nip,
|
|
||||||
'mapel' => MataPelajaran::find($request->mapel_id)->nama_mapel,
|
|
||||||
'alamat' => $request->alamat,
|
|
||||||
'telepon' => $request->telepon,
|
|
||||||
'status' => 'aktif'
|
|
||||||
]);
|
|
||||||
|
|
||||||
// 🔥 SIMPAN USER (FIX TELEPON MASUK)
|
|
||||||
$user = User::create([
|
|
||||||
'name' => $request->nama,
|
|
||||||
'email' => $request->email,
|
|
||||||
'password' => Hash::make('12345678'),
|
|
||||||
'role' => 'guru',
|
|
||||||
'guru_id' => $guru->id,
|
|
||||||
'mapel_id' => $request->mapel_id,
|
|
||||||
'telepon' => $request->telepon, // ✅ INI YANG PENTING
|
|
||||||
'is_default_password' => true
|
|
||||||
]);
|
|
||||||
|
|
||||||
return redirect()->route('admin.guru.index')
|
|
||||||
->with('success', 'Guru berhasil ditambahkan');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$guru = Guru::create([
|
||||||
|
'nama' => $request->nama,
|
||||||
|
'nip' => $request->nip,
|
||||||
|
'mapel_id' => $request->mapel_id,
|
||||||
|
'alamat' => $request->alamat,
|
||||||
|
'telepon' => $request->telepon,
|
||||||
|
'status' => 'aktif'
|
||||||
|
]);
|
||||||
|
|
||||||
|
User::create([
|
||||||
|
'name' => $request->nama,
|
||||||
|
'email' => $request->email,
|
||||||
|
'password' => Hash::make('12345678'),
|
||||||
|
'role' => 'guru',
|
||||||
|
'guru_id' => $guru->id,
|
||||||
|
'mapel_id' => $request->mapel_id,
|
||||||
|
'telepon' => $request->telepon,
|
||||||
|
'is_default_password' => true
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('admin.guru.index')
|
||||||
|
->with('success', 'Guru berhasil ditambahkan');
|
||||||
|
}
|
||||||
|
|
||||||
// ================= EDIT =================
|
// ================= EDIT =================
|
||||||
public function edit(Guru $guru)
|
public function edit(Guru $guru)
|
||||||
{
|
{
|
||||||
|
|
@ -86,11 +89,10 @@ public function update(Request $request, Guru $guru)
|
||||||
'telepon' => 'required',
|
'telepon' => 'required',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// 🔥 UPDATE GURU
|
$guru->update([
|
||||||
$guru->update([
|
|
||||||
'nama' => $request->nama,
|
'nama' => $request->nama,
|
||||||
'nip' => $request->nip,
|
'nip' => $request->nip,
|
||||||
'mapel' => MataPelajaran::find($request->mapel_id)->nama_mapel,
|
'mapel_id' => $request->mapel_id, // 🔥 FIX
|
||||||
'alamat' => $request->alamat,
|
'alamat' => $request->alamat,
|
||||||
'telepon' => $request->telepon,
|
'telepon' => $request->telepon,
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
use App\Models\Kelas;
|
use App\Models\Kelas;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use App\Services\OtpService;
|
||||||
|
|
||||||
class SiswaController extends Controller
|
class SiswaController extends Controller
|
||||||
{
|
{
|
||||||
|
|
@ -37,16 +38,24 @@ public function create()
|
||||||
// ================= STORE =================
|
// ================= STORE =================
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
|
||||||
'nama' => 'required',
|
\Log::info('STORE DIPANGGIL');
|
||||||
'jenis_kelamin' => 'required',
|
|
||||||
'nama_ortu' => 'required',
|
$request->validate([
|
||||||
'nis' => 'required|unique:siswa,nis',
|
'nama' => 'required',
|
||||||
'kelas_id' => 'required',
|
'jenis_kelamin' => 'required',
|
||||||
'alamat' => 'required',
|
'nama_ortu' => 'required',
|
||||||
'telepon' => 'required',
|
'nis' => 'required|unique:siswa,nis',
|
||||||
'email' => 'required|email|unique:users,email',
|
'kelas_id' => 'required',
|
||||||
]);
|
'alamat' => 'required',
|
||||||
|
'telepon' => 'required',
|
||||||
|
'email' => 'required|email|unique:users,email',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 2. CEK TAMBAHAN (ANTI DOUBLE SUBMIT)
|
||||||
|
if (User::where('email', $request->email)->exists()) {
|
||||||
|
return back()->with('error', 'Email sudah digunakan!');
|
||||||
|
}
|
||||||
|
|
||||||
$siswa = Siswa::create([
|
$siswa = Siswa::create([
|
||||||
'nama' => $request->nama,
|
'nama' => $request->nama,
|
||||||
|
|
@ -60,7 +69,7 @@ public function store(Request $request)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// simpan user login
|
// simpan user login
|
||||||
User::create([
|
$user = User::create([
|
||||||
'name' => $request->nama,
|
'name' => $request->nama,
|
||||||
'email' => $request->email,
|
'email' => $request->email,
|
||||||
'password' => Hash::make('12345678'), // 🔥 default
|
'password' => Hash::make('12345678'), // 🔥 default
|
||||||
|
|
@ -69,6 +78,9 @@ public function store(Request $request)
|
||||||
'is_default_password' => true // 🔥 WAJIB
|
'is_default_password' => true // 🔥 WAJIB
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
app(OtpService::class)->send($user);
|
||||||
|
|
||||||
return redirect()->route('admin.siswa.index')
|
return redirect()->route('admin.siswa.index')
|
||||||
->with('success', 'Siswa + akun login berhasil dibuat');
|
->with('success', 'Siswa + akun login berhasil dibuat');
|
||||||
}
|
}
|
||||||
|
|
@ -120,11 +132,18 @@ public function destroy(Siswa $siswa)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================= NONAKTIF =================
|
// ================= NONAKTIF =================
|
||||||
public function nonaktif($id)
|
public function nonaktif(Request $request, $id)
|
||||||
{
|
{
|
||||||
|
$request->validate([
|
||||||
|
'alasan' => 'required|min:5'
|
||||||
|
]);
|
||||||
|
|
||||||
$siswa = Siswa::findOrFail($id);
|
$siswa = Siswa::findOrFail($id);
|
||||||
$siswa->status = 'nonaktif';
|
|
||||||
$siswa->save();
|
$siswa->update([
|
||||||
|
'status' => 'nonaktif',
|
||||||
|
'alasan_nonaktif' => $request->alasan
|
||||||
|
]);
|
||||||
|
|
||||||
return back()->with('success', 'Siswa dinonaktifkan');
|
return back()->with('success', 'Siswa dinonaktifkan');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Auth;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class OtpController extends Controller
|
||||||
|
{
|
||||||
|
// ================= KIRIM OTP =================
|
||||||
|
public function sendOtp(Request $request)
|
||||||
|
{
|
||||||
|
$user = User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return back()->with('error', 'Email tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
app(\App\Services\OtpService::class)->send($user);
|
||||||
|
|
||||||
|
return back()->with('success', 'OTP berhasil dikirim');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= LOGIN =================
|
||||||
|
public function loginOtp(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'email' => 'required|email',
|
||||||
|
'password' => 'required',
|
||||||
|
'otp' => 'nullable|digits:6'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user = \App\Models\User::where('email', $request->email)->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return back()->with('error', 'User tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔐 CEK PASSWORD
|
||||||
|
if (!\Hash::check($request->password, $user->password)) {
|
||||||
|
return back()->with('error', 'Password salah');
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 🔥 KHUSUS GURU & SISWA WAJIB OTP
|
||||||
|
// =========================
|
||||||
|
if (in_array($user->role, ['guru', 'siswa'])) {
|
||||||
|
|
||||||
|
if (!$request->otp) {
|
||||||
|
return back()->with('error', 'OTP wajib diisi');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$user->otp) {
|
||||||
|
return back()->with('error', 'OTP belum diminta');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((string)$request->otp !== (string)$user->otp) {
|
||||||
|
return back()->with('error', 'OTP salah');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$user->otp_expired_at || now()->gt($user->otp_expired_at)) {
|
||||||
|
return back()->with('error', 'OTP sudah kadaluarsa');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// ✅ LOGIN
|
||||||
|
// =========================
|
||||||
|
\Auth::login($user);
|
||||||
|
|
||||||
|
// 🔥 HAPUS OTP SETELAH DIPAKAI (hanya untuk guru & siswa)
|
||||||
|
if (in_array($user->role, ['guru', 'siswa'])) {
|
||||||
|
$user->update([
|
||||||
|
'otp' => null,
|
||||||
|
'otp_expired_at' => null
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// 🔁 REDIRECT ROLE
|
||||||
|
// =========================
|
||||||
|
if ($user->role == 'admin') {
|
||||||
|
return redirect()->route('admin.dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->role == 'guru') {
|
||||||
|
return redirect()->route('guru.dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($user->role == 'siswa') {
|
||||||
|
return redirect()->route('siswa.dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect('/');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,130 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers\guru;
|
namespace App\Http\Controllers\Guru;
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Absensi;
|
||||||
|
use App\Models\AbsensiDetail;
|
||||||
|
use App\Models\Kelas;
|
||||||
|
use App\Models\MataPelajaran;
|
||||||
|
use App\Models\Siswa;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class AbsensiController extends Controller
|
class AbsensiController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
return view('guru.absensi');
|
$kelas = Kelas::all();
|
||||||
|
$mapel = MataPelajaran::find(auth()->user()->guru->mapel_id);
|
||||||
|
// 🔥 VALIDASI DI SINI
|
||||||
|
if (!$mapel) {
|
||||||
|
return back()->with('error', 'Mapel guru belum diatur!');
|
||||||
}
|
}
|
||||||
|
$siswa = null;
|
||||||
|
$kelasAktif = null;
|
||||||
|
$riwayat = null;
|
||||||
|
|
||||||
|
if ($request->kelas_id && $request->mapel_id) {
|
||||||
|
|
||||||
|
$kelasAktif = Kelas::findOrFail($request->kelas_id);
|
||||||
|
|
||||||
|
$siswa = Siswa::where('kelas_id', $request->kelas_id)->get();
|
||||||
|
|
||||||
|
// 🔥 ambil absensi hari ini
|
||||||
|
$absensi = Absensi::where('kelas_id', $request->kelas_id)
|
||||||
|
->where('mapel_id', $request->mapel_id)
|
||||||
|
->whereDate('tanggal', now())
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if ($absensi) {
|
||||||
|
$riwayat = AbsensiDetail::with('siswa')
|
||||||
|
->where('absensi_id', $absensi->id)
|
||||||
|
->get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('guru.absensi.index', compact(
|
||||||
|
'kelas',
|
||||||
|
'mapel',
|
||||||
|
'siswa',
|
||||||
|
'kelasAktif',
|
||||||
|
'riwayat'
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buka(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'kelas_id' => 'required',
|
||||||
|
'mapel_id' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$absensi = Absensi::create([
|
||||||
|
'guru_id' => auth()->user()->guru->id,
|
||||||
|
'kelas_id' => $request->kelas_id,
|
||||||
|
'mapel_id' => $request->mapel_id,
|
||||||
|
'tanggal' => now(),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('guru.absensi.kelola', $absensi->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kelola($id)
|
||||||
|
{
|
||||||
|
$absensi = Absensi::findOrFail($id);
|
||||||
|
|
||||||
|
$siswa = Siswa::where('kelas_id', $absensi->kelas_id)->get();
|
||||||
|
|
||||||
|
return view('guru.absensi.kelola', compact('absensi', 'siswa'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpan(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'kelas_id' => 'required',
|
||||||
|
'mapel_id' => 'required',
|
||||||
|
'absensi' => 'required|array'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 🔥 CEK / BUAT absensi hari ini
|
||||||
|
$absensi = Absensi::firstOrCreate([
|
||||||
|
'kelas_id' => $request->kelas_id,
|
||||||
|
'mapel_id' => $request->mapel_id,
|
||||||
|
'tanggal' => now()->toDateString(),
|
||||||
|
], [
|
||||||
|
'guru_id' => auth()->user()->guru->id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 🔥 SIMPAN DETAIL
|
||||||
|
foreach ($request->absensi as $siswaId => $data) {
|
||||||
|
|
||||||
|
AbsensiDetail::updateOrCreate(
|
||||||
|
[
|
||||||
|
'absensi_id' => $absensi->id,
|
||||||
|
'siswa_id' => $siswaId
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'status' => $data['status'],
|
||||||
|
'keterangan' => $data['keterangan'] ?? null
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->back()->with('success', 'Absensi berhasil disimpan');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tutup($id)
|
||||||
|
{
|
||||||
|
Absensi::findOrFail($id)->update(['dibuka' => false]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Absensi ditutup');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete($id)
|
||||||
|
{
|
||||||
|
AbsensiDetail::findOrFail($id)->delete();
|
||||||
|
|
||||||
|
return back()->with('success', 'Data dihapus');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Guru;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Jadwal;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class MapelController extends Controller
|
||||||
|
{
|
||||||
|
public function getByKelas($id)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$mapel = Jadwal::where('kelas_id', $id)
|
||||||
|
->join('mata_pelajarans', 'jadwals.mata_pelajaran_id', '=', 'mata_pelajarans.id')
|
||||||
|
->select('mata_pelajarans.id', 'mata_pelajarans.nama_mapel')
|
||||||
|
->distinct()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json($mapel);
|
||||||
|
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return response()->json([
|
||||||
|
'error' => $e->getMessage()
|
||||||
|
], 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Guru;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Tugas;
|
||||||
|
use App\Models\Kelas;
|
||||||
|
use App\Models\MataPelajaran;
|
||||||
|
use App\Models\PengumpulanTugas;
|
||||||
|
use App\Models\Jadwal; // 🔥 WAJIB
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use App\Models\Siswa;
|
||||||
|
|
||||||
|
class TugasController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$guru = auth()->user()->guru;
|
||||||
|
|
||||||
|
$tugas = Tugas::with(['kelas', 'mapel'])
|
||||||
|
->withCount('pengumpulan') // 🔥 hitung jumlah yang kumpul
|
||||||
|
->where('guru_id', $guru->id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
// 🔥 tambahkan total siswa per kelas
|
||||||
|
foreach ($tugas as $t) {
|
||||||
|
$t->total_siswa = Siswa::where('kelas_id', $t->kelas_id)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('guru.tugas.index', compact('tugas'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$kelas = Kelas::all();
|
||||||
|
$guru = auth()->user()->guru;
|
||||||
|
|
||||||
|
$mapel = $guru->mapelRel;
|
||||||
|
|
||||||
|
return view('guru.tugas.create', compact('kelas', 'mapel'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$guru = auth()->user()->guru;
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'kelas_id' => 'required',
|
||||||
|
'judul' => 'required',
|
||||||
|
'deadline' => 'required',
|
||||||
|
'file' => 'nullable|mimes:pdf,doc,docx,ppt,pptx|max:2048'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$filePath = null;
|
||||||
|
|
||||||
|
// 🔥 INI BAGIAN PALING PENTING
|
||||||
|
if ($request->hasFile('file')) {
|
||||||
|
$filePath = $request->file('file')->store('tugas_file', 'public');
|
||||||
|
}
|
||||||
|
|
||||||
|
Tugas::create([
|
||||||
|
'guru_id' => $guru->id,
|
||||||
|
'kelas_id' => $request->kelas_id,
|
||||||
|
'mapel_id' => $guru->mapel_id,
|
||||||
|
'judul' => $request->judul,
|
||||||
|
'deskripsi' => $request->deskripsi,
|
||||||
|
'file' => $filePath,
|
||||||
|
'deadline' => str_replace('T', ' ', $request->deadline),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('guru.tugas.index')
|
||||||
|
->with('success', 'Tugas berhasil dibuat');
|
||||||
|
}
|
||||||
|
public function getMapelByKelas($id)
|
||||||
|
{
|
||||||
|
$guruId = auth()->user()->guru->id;
|
||||||
|
|
||||||
|
$mapel = Jadwal::where('kelas_id', $id)
|
||||||
|
->where('guru_id', $guruId)
|
||||||
|
->join('mata_pelajarans', 'jadwals.mata_pelajaran_id', '=', 'mata_pelajarans.id')
|
||||||
|
->select('mata_pelajarans.id', 'mata_pelajarans.nama_mapel')
|
||||||
|
->distinct()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
return response()->json($mapel);
|
||||||
|
}
|
||||||
|
public function show($id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::with(['kelas', 'mapel'])->findOrFail($id);
|
||||||
|
|
||||||
|
return view('guru.tugas.show', compact('tugas'));
|
||||||
|
}
|
||||||
|
public function edit($id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::findOrFail($id);
|
||||||
|
$kelas = Kelas::all();
|
||||||
|
|
||||||
|
return view('guru.tugas.edit', compact('tugas', 'kelas'));
|
||||||
|
}
|
||||||
|
public function update(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'judul' => 'required',
|
||||||
|
'kelas_id' => 'required',
|
||||||
|
'deadline' => 'required'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$tugas = Tugas::findOrFail($id);
|
||||||
|
|
||||||
|
$tugas->update([
|
||||||
|
'judul' => $request->judul,
|
||||||
|
'kelas_id' => $request->kelas_id,
|
||||||
|
'deskripsi' => $request->deskripsi,
|
||||||
|
'deadline' => $request->deadline,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('guru.tugas.index')
|
||||||
|
->with('success', 'Tugas berhasil diupdate');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function download($id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::findOrFail($id);
|
||||||
|
|
||||||
|
if (!$tugas->file) {
|
||||||
|
abort(404, 'File tidak ditemukan');
|
||||||
|
}
|
||||||
|
|
||||||
|
$path = storage_path('app/public/' . $tugas->file);
|
||||||
|
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
abort(404, 'File tidak ada di storage');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response()->download($path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pengumpulan($id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::with(['pengumpulan.siswa'])->findOrFail($id);
|
||||||
|
|
||||||
|
$deadline = Carbon::parse($tugas->deadline);
|
||||||
|
|
||||||
|
foreach ($tugas->pengumpulan as $p) {
|
||||||
|
$waktu = Carbon::parse($p->created_at);
|
||||||
|
|
||||||
|
if ($waktu->gt($deadline)) {
|
||||||
|
$p->status = 'telat';
|
||||||
|
} else {
|
||||||
|
$p->status = 'tepat';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('guru.tugas.pengumpulan', compact('tugas'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function nilai(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'nilai' => 'required|integer|min:0|max:100',
|
||||||
|
'komentar' => 'nullable'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$pengumpulan = \App\Models\PengumpulanTugas::findOrFail($id);
|
||||||
|
|
||||||
|
$pengumpulan->update([
|
||||||
|
'nilai' => $request->nilai,
|
||||||
|
'komentar' => $request->komentar
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Nilai berhasil disimpan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Guru;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Ujian;
|
||||||
|
use App\Models\Soal;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
class UjianController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$data = Ujian::where('guru_id', auth()->id())->latest()->get();
|
||||||
|
return view('guru.ujian.index', compact('data'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$user = Auth::user();
|
||||||
|
|
||||||
|
// safety check
|
||||||
|
if (!$user) {
|
||||||
|
abort(403, 'Belum login');
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapel = $user->mapel; // ✔ relasi sudah benar
|
||||||
|
|
||||||
|
return view('guru.ujian.create', compact('mapel'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'judul' => 'required',
|
||||||
|
'soal' => 'required|array'
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 🔥 SIMPAN UJIAN
|
||||||
|
$ujian = Ujian::create([
|
||||||
|
'judul' => $request->judul,
|
||||||
|
'durasi' => $request->durasi,
|
||||||
|
'mulai' => $request->mulai,
|
||||||
|
'selesai' => $request->selesai,
|
||||||
|
'guru_id' => auth()->user()->guru_id
|
||||||
|
]);
|
||||||
|
|
||||||
|
// 🔥 SIMPAN SOAL
|
||||||
|
foreach ($request->soal as $s) {
|
||||||
|
Soal::create([
|
||||||
|
'ujian_id' => $ujian->id,
|
||||||
|
'pertanyaan' => $s['pertanyaan'],
|
||||||
|
'a' => $s['a'],
|
||||||
|
'b' => $s['b'],
|
||||||
|
'c' => $s['c'],
|
||||||
|
'd' => $s['d'],
|
||||||
|
'jawaban_benar' => $s['jawaban'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('guru.ujian.index')
|
||||||
|
->with('success', 'Ujian + soal berhasil dibuat');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function soal($id)
|
||||||
|
{
|
||||||
|
$ujian = Ujian::findOrFail($id);
|
||||||
|
return view('guru.ujian.soal', compact('ujian'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storeSoal(Request $request, $id)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'soal' => 'required|array',
|
||||||
|
'soal.*.pertanyaan' => 'required|string',
|
||||||
|
'soal.*.a' => 'required|string',
|
||||||
|
'soal.*.b' => 'required|string',
|
||||||
|
'soal.*.c' => 'required|string',
|
||||||
|
'soal.*.d' => 'required|string',
|
||||||
|
'soal.*.jawaban' => 'required|in:a,b,c,d',
|
||||||
|
]);
|
||||||
|
|
||||||
|
foreach ($request->soal as $s) {
|
||||||
|
Soal::create([
|
||||||
|
'ujian_id' => $id,
|
||||||
|
'pertanyaan' => $s['pertanyaan'],
|
||||||
|
'a' => $s['a'],
|
||||||
|
'b' => $s['b'],
|
||||||
|
'c' => $s['c'],
|
||||||
|
'd' => $s['d'],
|
||||||
|
'jawaban_benar' => $s['jawaban'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return back()->with('success','Soal disimpan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +1,82 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Http\Controllers\Siswa;
|
namespace App\Http\Controllers\Siswa;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
use App\Models\Absensi;
|
use App\Models\Absensi;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use App\Models\AbsensiDetail;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class AbsensiController extends Controller
|
class AbsensiController extends Controller
|
||||||
{
|
{
|
||||||
public function index()
|
// 🔹 LIST ABSENSI AKTIF
|
||||||
{
|
public function index()
|
||||||
$user = Auth::user();
|
{
|
||||||
|
$siswa = auth()->user()->siswa;
|
||||||
|
|
||||||
$absensi = Absensi::where('siswa_id', $user->siswa_id)->get();
|
$absensis = Absensi::with(['mapel', 'guru'])
|
||||||
|
->where('kelas_id', $siswa->kelas_id)
|
||||||
|
->where('dibuka', true)
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->whereNull('waktu_selesai')
|
||||||
|
->orWhere('waktu_selesai', '>', now());
|
||||||
|
})
|
||||||
|
->latest()
|
||||||
|
->get();
|
||||||
|
|
||||||
return view('siswa.absensi.index', compact('absensi'));
|
// 🔥 GROUP BY MAPEL (INI YANG KURANG)
|
||||||
}
|
$groupedAbsensi = $absensis->groupBy(function ($item) {
|
||||||
|
return $item->mapel->nama_mapel ?? 'Tanpa Mapel';
|
||||||
|
});
|
||||||
|
|
||||||
|
// 🔥 CEK SUDAH ABSEN
|
||||||
|
$sudahAbsen = AbsensiDetail::where('siswa_id', $siswa->id)
|
||||||
|
->pluck('absensi_id')
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
return view('siswa.absensi.index', compact('groupedAbsensi', 'sudahAbsen'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔹 SCAN QR
|
||||||
|
public function scan($token)
|
||||||
|
{
|
||||||
|
$absensi = Absensi::where('token', $token)->firstOrFail();
|
||||||
|
|
||||||
|
return view('siswa.absensi.scan', compact('absensi'));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔹 SUBMIT HADIR
|
||||||
|
public function hadir(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'absensi_id' => 'required|exists:absensi,id'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$absensi = Absensi::findOrFail($request->absensi_id);
|
||||||
|
|
||||||
|
// 🔥 VALIDASI WAKTU
|
||||||
|
if ($absensi->waktu_selesai && now()->greaterThan($absensi->waktu_selesai)) {
|
||||||
|
return back()->with('error', 'Waktu absensi sudah habis!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$siswa = auth()->user()->siswa;
|
||||||
|
|
||||||
|
$cek = AbsensiDetail::where('absensi_id', $absensi->id)
|
||||||
|
->where('siswa_id', $siswa->id)
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
if ($cek) {
|
||||||
|
return back()->with('error', 'Kamu sudah absen!');
|
||||||
|
}
|
||||||
|
|
||||||
|
AbsensiDetail::create([
|
||||||
|
'absensi_id' => $absensi->id,
|
||||||
|
'siswa_id' => $siswa->id,
|
||||||
|
'status' => 'hadir',
|
||||||
|
'waktu_absen' => now()
|
||||||
|
]);
|
||||||
|
|
||||||
|
return back()->with('success', 'Absensi berhasil!');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Siswa;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Tugas;
|
||||||
|
use App\Models\PengumpulanTugas;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
class TugasController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$siswa = auth()->user()->siswa;
|
||||||
|
|
||||||
|
$tugas = Tugas::with('mapel')
|
||||||
|
->where('kelas_id', $siswa->kelas_id)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($tugas as $t) {
|
||||||
|
|
||||||
|
$pengumpulan = \App\Models\PengumpulanTugas::where('tugas_id', $t->id)
|
||||||
|
->where('siswa_id', $siswa->id)
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$deadline = \Carbon\Carbon::parse($t->deadline);
|
||||||
|
|
||||||
|
$t->waktu_kumpul = null;
|
||||||
|
$t->nilai = null;
|
||||||
|
$t->komentar = null;
|
||||||
|
$t->status = 'belum';
|
||||||
|
|
||||||
|
if ($pengumpulan) {
|
||||||
|
$t->waktu_kumpul = $pengumpulan->created_at;
|
||||||
|
$t->nilai = $pengumpulan->nilai;
|
||||||
|
$t->komentar = $pengumpulan->komentar;
|
||||||
|
|
||||||
|
if ($pengumpulan->created_at > $deadline) {
|
||||||
|
$t->status = 'telat';
|
||||||
|
} else {
|
||||||
|
$t->status = 'tepat';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (now()->gt($deadline)) {
|
||||||
|
$t->status = 'lewat';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('siswa.tugas.index', compact('tugas'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kumpul($id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::findOrFail($id);
|
||||||
|
|
||||||
|
if (now()->gt($tugas->deadline)) {
|
||||||
|
return redirect()->route('siswa.tugas.index')
|
||||||
|
->with('error', 'Deadline sudah lewat, tidak bisa mengumpulkan tugas');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('siswa.tugas.kumpul', compact('tugas'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request, $id)
|
||||||
|
{
|
||||||
|
$tugas = Tugas::findOrFail($id);
|
||||||
|
|
||||||
|
// 🔥 BLOCK UTAMA
|
||||||
|
if (now()->gt($tugas->deadline)) {
|
||||||
|
return redirect()->route('siswa.tugas.index')
|
||||||
|
->with('error', 'Tugas sudah melewati deadline');
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'file' => 'required|mimes:pdf,doc,docx|max:2048'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$filePath = $request->file('file')->store('jawaban_tugas', 'public');
|
||||||
|
|
||||||
|
PengumpulanTugas::create([
|
||||||
|
'tugas_id' => $id,
|
||||||
|
'siswa_id' => auth()->user()->siswa->id,
|
||||||
|
'file' => $filePath
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->route('siswa.tugas.index')
|
||||||
|
->with('success', 'Tugas berhasil dikumpulkan');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Siswa;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Models\Ujian;
|
||||||
|
use App\Models\Soal;
|
||||||
|
use App\Models\Jawaban;
|
||||||
|
use App\Models\Hasil;
|
||||||
|
|
||||||
|
class UjianController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$ujians = Ujian::all();
|
||||||
|
return view('siswa.ujian.index', compact('ujians'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kerjakan($id)
|
||||||
|
{
|
||||||
|
$ujian = Ujian::findOrFail($id);
|
||||||
|
$soals = Soal::where('ujian_id', $id)->get();
|
||||||
|
|
||||||
|
return view('siswa.ujian.kerjakan', compact('ujian','soals'));
|
||||||
|
}
|
||||||
|
public function submit(Request $request, $id)
|
||||||
|
{
|
||||||
|
$soals = Soal::where('ujian_id', $id)->get();
|
||||||
|
|
||||||
|
$benar = 0;
|
||||||
|
$total = $soals->count();
|
||||||
|
|
||||||
|
foreach ($soals as $s) {
|
||||||
|
$jawabanUser = $request->jawaban[$s->id] ?? null;
|
||||||
|
|
||||||
|
if ($jawabanUser == $s->jawaban_benar) {
|
||||||
|
$benar++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$nilai = ($benar / $total) * 100;
|
||||||
|
|
||||||
|
return view('siswa.ujian.hasil', [
|
||||||
|
'nilai' => $nilai,
|
||||||
|
'benar' => $benar,
|
||||||
|
'total' => $total
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class Absensi extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'absensi';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'guru_id',
|
||||||
|
'kelas_id',
|
||||||
|
'tanggal',
|
||||||
|
'token',
|
||||||
|
'dibuka',
|
||||||
|
'mapel_id',
|
||||||
|
'waktu_selesai'// 🔥 WAJIB TAMBAHKAN
|
||||||
|
];
|
||||||
|
|
||||||
|
// 🔥 RELASI
|
||||||
|
|
||||||
|
public function detail()
|
||||||
|
{
|
||||||
|
return $this->hasMany(AbsensiDetail::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guru()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Guru::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function kelas()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Kelas::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mapel()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MataPelajaran::class, 'mapel_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
|
||||||
|
class AbsensiDetail extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
protected $table = 'absensi_detail';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'absensi_id', // 🔥 WAJIB
|
||||||
|
'siswa_id', // 🔥 WAJIB
|
||||||
|
'status', // 🔥 hadir / izin / alpha
|
||||||
|
'waktu_absen' // 🔥 timestamp
|
||||||
|
];
|
||||||
|
|
||||||
|
public function absensi()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Absensi::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function siswa()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Siswa::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ class Guru extends Model
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $table = 'gurus'; // nama tabel
|
protected $table = 'gurus'; // nama tabel
|
||||||
protected $fillable = ['nama', 'nip', 'mapel','alamat','telepon','status'];
|
protected $fillable = ['nama', 'nip','alamat','telepon','status', 'mapel_id'];
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->hasOne(User::class, 'guru_id');
|
return $this->hasOne(User::class, 'guru_id');
|
||||||
|
|
@ -20,5 +20,15 @@ public function jadwal()
|
||||||
{
|
{
|
||||||
return $this->hasMany(\App\Models\Jadwal::class);
|
return $this->hasMany(\App\Models\Jadwal::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function mapel()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MataPelajaran::class, 'mapel_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mapelRel()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MataPelajaran::class, 'mapel_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Hasil extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['user_id','ujian_id','nilai'];
|
||||||
|
|
||||||
|
public function ujian()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Ujian::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model; // 🔥 INI WAJIB!
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class Jadwal extends Model
|
class Jadwal extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -25,8 +25,8 @@ public function mapel()
|
||||||
return $this->belongsTo(MataPelajaran::class, 'mata_pelajaran_id');
|
return $this->belongsTo(MataPelajaran::class, 'mata_pelajaran_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function guru()
|
public function guru()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Guru::class);
|
return $this->belongsTo(Guru::class, 'guru_id');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Jawaban extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['user_id','soal_id','jawaban'];
|
||||||
|
|
||||||
|
public function soal()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Soal::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,4 +13,9 @@ class MataPelajaran extends Model
|
||||||
'kode_mapel',
|
'kode_mapel',
|
||||||
'jam_pelajaran'
|
'jam_pelajaran'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public function jadwal()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Jadwal::class, 'mata_pelajaran_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Models\Tugas;
|
||||||
|
use App\Models\Siswa;
|
||||||
|
|
||||||
|
class PengumpulanTugas extends Model
|
||||||
|
{
|
||||||
|
protected $table = 'pengumpulan_tugas';
|
||||||
|
|
||||||
|
protected $fillable = [
|
||||||
|
'tugas_id',
|
||||||
|
'siswa_id',
|
||||||
|
'file',
|
||||||
|
'nilai',
|
||||||
|
'komentar'
|
||||||
|
];
|
||||||
|
|
||||||
|
// RELASI
|
||||||
|
public function siswa()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Siswa::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tugas()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Tugas::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,8 @@ class Siswa extends Model
|
||||||
'kelas_id',
|
'kelas_id',
|
||||||
'alamat',
|
'alamat',
|
||||||
'telepon',
|
'telepon',
|
||||||
'status'
|
'status',
|
||||||
|
'alasan_nonaktif'
|
||||||
];
|
];
|
||||||
|
|
||||||
public $timestamps = true;
|
public $timestamps = true;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Soal extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'ujian_id','pertanyaan','a','b','c','d','jawaban_benar'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function ujian()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Ujian::class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use App\Models\Guru;
|
||||||
|
use App\Models\Kelas;
|
||||||
|
use App\Models\MataPelajaran;
|
||||||
|
use App\Models\PengumpulanTugas;
|
||||||
|
|
||||||
|
class Tugas extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = [
|
||||||
|
'guru_id',
|
||||||
|
'kelas_id',
|
||||||
|
'mapel_id',
|
||||||
|
'judul',
|
||||||
|
'deskripsi',
|
||||||
|
'file', // 🔥 WAJIB ADA
|
||||||
|
'deadline'
|
||||||
|
];
|
||||||
|
|
||||||
|
// RELASI
|
||||||
|
public function kelas()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Kelas::class, 'kelas_id'); // 🔥 WAJIB ADA INI
|
||||||
|
}
|
||||||
|
|
||||||
|
public function mapel()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MataPelajaran::class, 'mapel_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guru()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Guru::class, 'guru_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pengumpulan()
|
||||||
|
{
|
||||||
|
return $this->hasMany(\App\Models\PengumpulanTugas::class, 'tugas_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
class Ujian extends Model
|
||||||
|
{ protected $fillable = ['judul','durasi','mulai','selesai','guru_id'];
|
||||||
|
|
||||||
|
public function soals()
|
||||||
|
{
|
||||||
|
return $this->hasMany(Soal::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function guru()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'guru_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,8 @@ class User extends Authenticatable
|
||||||
'siswa_id',
|
'siswa_id',
|
||||||
'mapel_id',
|
'mapel_id',
|
||||||
'photo',
|
'photo',
|
||||||
|
'otp',
|
||||||
|
'otp_expired_at',
|
||||||
'telepon', // 🔥 WAJIB TAMBAH INI
|
'telepon', // 🔥 WAJIB TAMBAH INI
|
||||||
'is_default_password'
|
'is_default_password'
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Illuminate\Support\Facades\Http;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
|
class OtpService
|
||||||
|
{
|
||||||
|
public function send(User $user)
|
||||||
|
{
|
||||||
|
$otp = rand(100000, 999999);
|
||||||
|
|
||||||
|
// simpan OTP
|
||||||
|
$user->update([
|
||||||
|
'otp' => $otp,
|
||||||
|
'otp_expired_at' => now()->addMinutes(5)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// ================= EMAIL =================
|
||||||
|
\Mail::raw("Kode OTP kamu: $otp", function ($msg) use ($user) {
|
||||||
|
$msg->to($user->email)
|
||||||
|
->subject('Kode OTP Login');
|
||||||
|
});
|
||||||
|
|
||||||
|
// ================= AMBIL TELEPON =================
|
||||||
|
$telepon = null;
|
||||||
|
|
||||||
|
if ($user->siswa && $user->siswa->telepon) {
|
||||||
|
$telepon = $user->siswa->telepon;
|
||||||
|
} elseif ($user->guru && $user->guru->telepon) {
|
||||||
|
$telepon = $user->guru->telepon;
|
||||||
|
} elseif ($user->telepon) {
|
||||||
|
$telepon = $user->telepon;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ================= KIRIM WA =================
|
||||||
|
if ($telepon) {
|
||||||
|
$this->sendWA($telepon, $otp);
|
||||||
|
} else {
|
||||||
|
\Log::error('NO HP TIDAK ADA UNTUK USER', [
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'role' => $user->role
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendWA($no, $otp)
|
||||||
|
{
|
||||||
|
$no = preg_replace('/[^0-9]/', '', $no);
|
||||||
|
|
||||||
|
if (substr($no, 0, 1) === '0') {
|
||||||
|
$no = '62' . substr($no, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = env('FONNTE_TOKEN');
|
||||||
|
|
||||||
|
$response = Http::asForm()->withHeaders([
|
||||||
|
'Authorization' => $token
|
||||||
|
])->post('https://api.fonnte.com/send', [
|
||||||
|
'target' => $no,
|
||||||
|
'message' => "Kode OTP kamu: $otp"
|
||||||
|
]);
|
||||||
|
|
||||||
|
Log::info('WA RESULT', [
|
||||||
|
'nomor' => $no,
|
||||||
|
'response' => $response->json()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,8 @@
|
||||||
"require": {
|
"require": {
|
||||||
"php": "^8.2",
|
"php": "^8.2",
|
||||||
"laravel/framework": "^11.31",
|
"laravel/framework": "^11.31",
|
||||||
"laravel/tinker": "^2.9"
|
"laravel/tinker": "^2.9",
|
||||||
|
"simplesoftwareio/simple-qrcode": "^4.2"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,68 @@
|
||||||
"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": "d6c083b04e73afd8ea1cc978bddab18d",
|
"content-hash": "ba0b871c4e08ecaa364989ce5e6f5138",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "bacon/bacon-qr-code",
|
||||||
|
"version": "2.0.8",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Bacon/BaconQrCode.git",
|
||||||
|
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/Bacon/BaconQrCode/zipball/8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||||
|
"reference": "8674e51bb65af933a5ffaf1c308a660387c35c22",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"dasprid/enum": "^1.0.3",
|
||||||
|
"ext-iconv": "*",
|
||||||
|
"php": "^7.1 || ^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phly/keep-a-changelog": "^2.1",
|
||||||
|
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^4.2.9",
|
||||||
|
"squizlabs/php_codesniffer": "^3.4"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-imagick": "to generate QR code images"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"BaconQrCode\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-2-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ben Scholzen 'DASPRiD'",
|
||||||
|
"email": "mail@dasprids.de",
|
||||||
|
"homepage": "https://dasprids.de/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "BaconQrCode is a QR code generator for PHP.",
|
||||||
|
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/Bacon/BaconQrCode/issues",
|
||||||
|
"source": "https://github.com/Bacon/BaconQrCode/tree/2.0.8"
|
||||||
|
},
|
||||||
|
"time": "2022-12-07T17:46:57+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
"version": "0.12.3",
|
"version": "0.12.3",
|
||||||
|
|
@ -135,6 +195,62 @@
|
||||||
],
|
],
|
||||||
"time": "2024-02-09T16:56:22+00:00"
|
"time": "2024-02-09T16:56:22+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "dasprid/enum",
|
||||||
|
"version": "1.0.7",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/DASPRiD/Enum.git",
|
||||||
|
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/DASPRiD/Enum/zipball/b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||||
|
"reference": "b5874fa9ed0043116c72162ec7f4fb50e02e7cce",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=7.1 <9.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^7 || ^8 || ^9 || ^10 || ^11",
|
||||||
|
"squizlabs/php_codesniffer": "*"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"DASPRiD\\Enum\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"BSD-2-Clause"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Ben Scholzen 'DASPRiD'",
|
||||||
|
"email": "mail@dasprids.de",
|
||||||
|
"homepage": "https://dasprids.de/",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP 7.1 enum implementation",
|
||||||
|
"keywords": [
|
||||||
|
"enum",
|
||||||
|
"map"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/DASPRiD/Enum/issues",
|
||||||
|
"source": "https://github.com/DASPRiD/Enum/tree/1.0.7"
|
||||||
|
},
|
||||||
|
"time": "2025-09-16T12:23:56+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "dflydev/dot-access-data",
|
"name": "dflydev/dot-access-data",
|
||||||
"version": "v3.0.3",
|
"version": "v3.0.3",
|
||||||
|
|
@ -3272,6 +3388,80 @@
|
||||||
},
|
},
|
||||||
"time": "2025-06-25T14:20:11+00:00"
|
"time": "2025-06-25T14:20:11+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "simplesoftwareio/simple-qrcode",
|
||||||
|
"version": "4.2.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/SimpleSoftwareIO/simple-qrcode.git",
|
||||||
|
"reference": "916db7948ca6772d54bb617259c768c9cdc8d537"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/SimpleSoftwareIO/simple-qrcode/zipball/916db7948ca6772d54bb617259c768c9cdc8d537",
|
||||||
|
"reference": "916db7948ca6772d54bb617259c768c9cdc8d537",
|
||||||
|
"shasum": "",
|
||||||
|
"mirrors": [
|
||||||
|
{
|
||||||
|
"url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%",
|
||||||
|
"preferred": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"bacon/bacon-qr-code": "^2.0",
|
||||||
|
"ext-gd": "*",
|
||||||
|
"php": ">=7.2|^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~1",
|
||||||
|
"phpunit/phpunit": "~9"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-imagick": "Allows the generation of PNG QrCodes.",
|
||||||
|
"illuminate/support": "Allows for use within Laravel."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"aliases": {
|
||||||
|
"QrCode": "SimpleSoftwareIO\\QrCode\\Facades\\QrCode"
|
||||||
|
},
|
||||||
|
"providers": [
|
||||||
|
"SimpleSoftwareIO\\QrCode\\QrCodeServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"SimpleSoftwareIO\\QrCode\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Simple Software LLC",
|
||||||
|
"email": "support@simplesoftware.io"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Simple QrCode is a QR code generator made for Laravel.",
|
||||||
|
"homepage": "https://www.simplesoftware.io/#/docs/simple-qrcode",
|
||||||
|
"keywords": [
|
||||||
|
"Simple",
|
||||||
|
"generator",
|
||||||
|
"laravel",
|
||||||
|
"qrcode",
|
||||||
|
"wrapper"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/SimpleSoftwareIO/simple-qrcode/issues",
|
||||||
|
"source": "https://github.com/SimpleSoftwareIO/simple-qrcode/tree/4.2.0"
|
||||||
|
},
|
||||||
|
"time": "2021-02-08T20:43:55+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
"version": "v7.3.0",
|
"version": "v7.3.0",
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'timezone' => env('APP_TIMEZONE', 'UTC'),
|
'timezone' => 'Asia/Jakarta',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Hasil>
|
||||||
|
*/
|
||||||
|
class HasilFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Jawaban>
|
||||||
|
*/
|
||||||
|
class JawabanFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Soal>
|
||||||
|
*/
|
||||||
|
class SoalFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Ujian>
|
||||||
|
*/
|
||||||
|
class UjianFactory extends Factory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?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('tugas', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('guru_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('kelas_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('mapel_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->string('judul');
|
||||||
|
$table->text('deskripsi');
|
||||||
|
$table->date('deadline');
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('tugas');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?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('pengumpulan_tugas', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('tugas_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreign('siswa_id')->references('id')->on('siswa')->onDelete('cascade');
|
||||||
|
$table->string('file')->nullable();
|
||||||
|
$table->integer('nilai')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('pengumpulan_tugas');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?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()
|
||||||
|
{
|
||||||
|
Schema::table('gurus', function (Blueprint $table) {
|
||||||
|
$table->string('mapel')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('gurus', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('mapel');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('tugas', function (Blueprint $table) {
|
||||||
|
$table->string('file')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('tugas', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('file');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?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()
|
||||||
|
{
|
||||||
|
Schema::table('tugas', function (Blueprint $table) {
|
||||||
|
$table->dateTime('deadline')->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('tugas', function (Blueprint $table) {
|
||||||
|
$table->date('deadline')->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?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()
|
||||||
|
{
|
||||||
|
Schema::table('pengumpulan_tugas', function (Blueprint $table) {
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('pengumpulan_tugas', 'komentar')) {
|
||||||
|
$table->text('komentar')->nullable();
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('pengumpulan_tugas', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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 {
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('absensi', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
|
||||||
|
$table->foreignId('guru_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('kelas_id')->constrained()->cascadeOnDelete();
|
||||||
|
$table->foreignId('mapel_id')->constrained()->cascadeOnDelete();
|
||||||
|
|
||||||
|
$table->date('tanggal');
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('absensi');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?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::create('absensi_detail', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
|
||||||
|
$table->foreignId('absensi_id')->constrained('absensi')->cascadeOnDelete();
|
||||||
|
$table->foreignId('siswa_id')->constrained()->cascadeOnDelete();
|
||||||
|
|
||||||
|
$table->enum('status', ['hadir', 'izin', 'sakit', 'alpha'])->default('hadir');
|
||||||
|
|
||||||
|
$table->text('keterangan')->nullable(); // 🔥 WAJIB
|
||||||
|
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('absensi_detail');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::table('siswa', function (Blueprint $table) {
|
||||||
|
$table->text('alasan_nonaktif')->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::table('siswa', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('jawabans', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('jawabans');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -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('ujians', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('ujians');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// database/migrations/xxxx_xx_xx_create_hasils_table.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::create('hasils', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
|
||||||
|
$table->foreignId('ujian_id')->constrained('ujians')->cascadeOnDelete();
|
||||||
|
$table->unsignedInteger('nilai');
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['user_id','ujian_id']); // 1 hasil per ujian
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public function down(): void {
|
||||||
|
Schema::dropIfExists('hasils');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// database/migrations/xxxx_xx_xx_create_jawabans_table.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::create('jawabans', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('user_id')->constrained('users')->cascadeOnDelete();
|
||||||
|
$table->foreignId('soal_id')->constrained('soals')->cascadeOnDelete();
|
||||||
|
$table->enum('jawaban', ['a','b','c','d'])->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->unique(['user_id','soal_id']); // 1 siswa 1 jawaban/soal
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public function down(): void {
|
||||||
|
Schema::dropIfExists('jawabans');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// database/migrations/xxxx_xx_xx_create_soals_table.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::create('soals', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('ujian_id')->constrained('ujians')->cascadeOnDelete();
|
||||||
|
$table->text('pertanyaan');
|
||||||
|
$table->string('a');
|
||||||
|
$table->string('b');
|
||||||
|
$table->string('c');
|
||||||
|
$table->string('d');
|
||||||
|
$table->enum('jawaban_benar', ['a','b','c','d']);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public function down(): void {
|
||||||
|
Schema::dropIfExists('soals');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// database/migrations/xxxx_xx_xx_create_ujians_table.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::create('ujians', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->string('judul');
|
||||||
|
$table->foreignId('guru_id')->constrained('users')->cascadeOnDelete();
|
||||||
|
$table->unsignedInteger('durasi')->nullable(); // menit
|
||||||
|
$table->timestamp('mulai')->nullable();
|
||||||
|
$table->timestamp('selesai')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public function down(): void {
|
||||||
|
Schema::dropIfExists('ujians');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -82,7 +82,7 @@
|
||||||
Kembali
|
Kembali
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<button class="btn btn-success">
|
<button type="submit" class="btn btn-success" onclick="this.disabled=true; this.form.submit();">
|
||||||
Simpan
|
Simpan
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<span class="badge badge-mapel">
|
<span class="badge badge-mapel">
|
||||||
{{ $g->mapel }}
|
{{ $g->mapel->nama_mapel ?? '-' }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,9 +89,10 @@
|
||||||
Kembali
|
Kembali
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<button class="btn btn-success">
|
<button type="submit" class="btn btn-success"
|
||||||
Simpan
|
onclick="this.disabled=true; this.innerText='Menyimpan...'; this.form.submit();">
|
||||||
</button>
|
Simpan
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
|
||||||
|
|
@ -251,10 +251,18 @@ class="btn btn-warning btn-sm">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
@if($item->status == 'aktif')
|
@if($item->status == 'aktif')
|
||||||
<a href="{{ route('admin.siswa.nonaktif', $item->id) }}"
|
<form action="{{ route('admin.siswa.nonaktif', $item->id) }}" method="POST" class="d-flex gap-1">
|
||||||
class="btn btn-danger btn-sm">
|
@csrf
|
||||||
Nonaktif
|
|
||||||
</a>
|
<input type="text" name="alasan"
|
||||||
|
placeholder="Alasan..."
|
||||||
|
required
|
||||||
|
style="width:120px; font-size:12px;">
|
||||||
|
|
||||||
|
<button class="btn btn-danger btn-sm">
|
||||||
|
Nonaktif
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
@else
|
@else
|
||||||
<a href="{{ route('admin.siswa.aktifkan', $item->id) }}"
|
<a href="{{ route('admin.siswa.aktifkan', $item->id) }}"
|
||||||
class="btn btn-success btn-sm">
|
class="btn btn-success btn-sm">
|
||||||
|
|
|
||||||
|
|
@ -242,19 +242,33 @@
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<form method="POST" action="/login">
|
{{-- FORM KIRIM OTP --}}
|
||||||
|
<form method="POST" action="{{ route('send.otp') }}">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<input type="email" name="email" placeholder="Enter Email" required>
|
<input type="email" name="email" placeholder="Email untuk OTP" required>
|
||||||
<input type="password" name="password" placeholder="Enter Password" required>
|
|
||||||
|
|
||||||
<button type="submit" class="btn-login">Login</button>
|
<button type="submit" style="margin-bottom:10px;">
|
||||||
|
🔑 Dapatkan OTP
|
||||||
<div class="forgot">
|
</button>
|
||||||
<a href="/forgot-password">Forgot Password?</a>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- FORM LOGIN --}}
|
||||||
|
<form method="POST" action="{{ route('login.otp') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<input type="email" name="email" placeholder="Email" required>
|
||||||
|
<input type="password" name="password" placeholder="Password" required>
|
||||||
|
<input type="text" name="otp" placeholder="Masukkan OTP">
|
||||||
|
|
||||||
|
<button type="submit">Login</button>
|
||||||
|
</form>
|
||||||
|
<div style="margin-top:10px;">
|
||||||
|
<a href="{{ route('password.request') }}" style="font-size:14px; color:#fff;">
|
||||||
|
Lupa Password?
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,14 +15,20 @@
|
||||||
<div class="alert alert-success">{{ session('success') }}</div>
|
<div class="alert alert-success">{{ session('success') }}</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<form method="POST" action="{{ route('reset.password') }}">
|
<form method="POST" action="{{ route('password.update') }}">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<input type="password" name="password" class="form-control mb-2" placeholder="Password baru" required>
|
<input type="hidden" name="email" value="{{ request('email') }}">
|
||||||
|
|
||||||
<input type="password" name="password_confirmation" class="form-control mb-3" placeholder="Konfirmasi password" required>
|
<div>
|
||||||
|
<input type="password" name="password" placeholder="Password baru" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-warning w-100">Reset Password</button>
|
<div>
|
||||||
|
<input type="password" name="password_confirmation" placeholder="Konfirmasi password" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit">Reset Password</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -63,20 +63,7 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- <li class="nav-item">
|
|
||||||
<a href="{{ route('admin.jadwal.grid') }}" class="nav-link">
|
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
<span>Jadwal Grid 🔥</span>
|
|
||||||
</a>
|
|
||||||
</li> -->
|
|
||||||
|
|
||||||
<!-- <li class="nav-item">
|
|
||||||
<a href="#" class="nav-link text-danger"
|
|
||||||
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
|
||||||
<i class="fas fa-sign-out-alt"></i>
|
|
||||||
<span>Logout</span>
|
|
||||||
</a>
|
|
||||||
</li> -->
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
@ -84,13 +71,13 @@
|
||||||
|
|
||||||
|
|
||||||
{{-- ================= GURU (NAVBAR MOBILE) ================= --}}
|
{{-- ================= GURU (NAVBAR MOBILE) ================= --}}
|
||||||
@if($role == 'guru')
|
@if(auth()->check() && auth()->user()->role == 'guru')
|
||||||
|
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-info shadow-sm fixed-top">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-info shadow-sm fixed-top">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
||||||
<!-- Brand -->
|
<!-- Brand -->
|
||||||
<a class="navbar-brand fw-bold" href="#">
|
<a class="navbar-brand fw-bold" href="{{ route('guru.dashboard') }}">
|
||||||
<i class="fas fa-school"></i> SMAN 1
|
<i class="fas fa-school"></i> SMAN 1
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
@ -104,35 +91,47 @@
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('guru.dashboard') }}">
|
<a class="nav-link {{ request()->routeIs('guru.dashboard') ? 'active' : '' }}"
|
||||||
|
href="{{ route('guru.dashboard') }}">
|
||||||
<i class="fas fa-home"></i> Dashboard
|
<i class="fas fa-home"></i> Dashboard
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('guru.jadwal') }}">
|
<a class="nav-link {{ request()->routeIs('guru.jadwal') ? 'active' : '' }}"
|
||||||
|
href="{{ route('guru.jadwal') }}">
|
||||||
<i class="fas fa-calendar"></i> Jadwal
|
<i class="fas fa-calendar"></i> Jadwal
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('guru.absensi') }}">
|
<a class="nav-link {{ request()->routeIs('guru.absensi*') ? 'active' : '' }}"
|
||||||
|
href="{{ route('guru.absensi') }}">
|
||||||
<i class="fas fa-user-check"></i> Absensi
|
<i class="fas fa-user-check"></i> Absensi
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('guru.nilai.index') }}">
|
<a class="nav-link {{ request()->routeIs('guru.nilai.*') ? 'active' : '' }}"
|
||||||
|
href="{{ route('guru.nilai.index') }}">
|
||||||
<i class="fas fa-clipboard-list"></i> Nilai
|
<i class="fas fa-clipboard-list"></i> Nilai
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- <li class="nav-item">
|
{{-- 🔥 MENU BARU: TUGAS --}}
|
||||||
<a class="nav-link text-warning" href="#"
|
<li class="nav-item">
|
||||||
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
<a class="nav-link {{ request()->routeIs('guru.tugas.*') ? 'active' : '' }}"
|
||||||
<i class="fas fa-sign-out-alt"></i> Logout
|
href="{{ route('guru.tugas.index') }}">
|
||||||
|
<i class="fas fa-tasks"></i> Tugas
|
||||||
</a>
|
</a>
|
||||||
</li> -->
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ route('guru.ujian.index') }}" class="nav-link">
|
||||||
|
<i class="fas fa-file-alt"></i>
|
||||||
|
<p>Ujian</p>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -170,39 +169,44 @@
|
||||||
<ul class="navbar-nav ms-auto">
|
<ul class="navbar-nav ms-auto">
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('siswa.dashboard') }}">
|
<a class="nav-link {{ request()->is('siswa/dashboard') ? 'active' : '' }}"
|
||||||
|
href="{{ route('siswa.dashboard') }}">
|
||||||
<i class="fas fa-home"></i> Dashboard
|
<i class="fas fa-home"></i> Dashboard
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('siswa.jadwal') }}">
|
<a class="nav-link {{ request()->is('siswa/jadwal') ? 'active' : '' }}"
|
||||||
|
href="{{ route('siswa.jadwal') }}">
|
||||||
<i class="fas fa-calendar"></i> Jadwal
|
<i class="fas fa-calendar"></i> Jadwal
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('siswa.nilai') }}">
|
<a class="nav-link {{ request()->is('siswa/nilai') ? 'active' : '' }}"
|
||||||
|
href="{{ route('siswa.nilai') }}">
|
||||||
<i class="fas fa-clipboard-list"></i> Nilai
|
<i class="fas fa-clipboard-list"></i> Nilai
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
<!-- ✅ TUGAS (SUDAH BENAR) -->
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('siswa.absensi') }}">
|
<a class="nav-link {{ request()->is('siswa/tugas*') ? 'active' : '' }}"
|
||||||
<i class="fas fa-user-check"></i> Absensi
|
href="{{ route('siswa.tugas.index') }}">
|
||||||
|
<i class="fas fa-tasks"></i> Tugas
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav-item">
|
||||||
|
<a href="{{ route('siswa.ujian.index') }}" class="nav-link">
|
||||||
|
<i class="fas fa-edit"></i> Ujian
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<!-- <li class="nav-item">
|
<!-- <li class="nav-item">
|
||||||
<a class="nav-link" href="{{ route('siswa.profile') }}">
|
<a class="nav-link {{ request()->routeIs('siswa.absensi*') ? 'active' : '' }}"
|
||||||
<i class="fas fa-user"></i> Profile
|
href="{{ route('siswa.absensi') }}">
|
||||||
</a>
|
<i class="fas fa-user-check"></i> Absensi
|
||||||
</li> -->
|
|
||||||
|
|
||||||
<!-- <li class="nav-item">
|
|
||||||
<a class="nav-link text-warning" href="#"
|
|
||||||
onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
|
||||||
<i class="fas fa-sign-out-alt"></i> Logout
|
|
||||||
</a>
|
</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
<h2>Login Berhasil</h2>
|
<h3>🔐 Login Pertama Akun</h3>
|
||||||
|
|
||||||
<p>Halo {{ $user->name }}</p>
|
<p>Halo {{ $user->name }},</p>
|
||||||
|
|
||||||
<p>Akun kamu baru saja login.</p>
|
<p>Akun Anda baru saja login menggunakan password default.</p>
|
||||||
|
|
||||||
<p><b>Waktu:</b> {{ now() }}</p>
|
<p><b>Email:</b> {{ $user->email }}</p>
|
||||||
|
|
||||||
<p>Jika bukan kamu, segera ubah password!</p>
|
<p>⚠️ Segera ubah password Anda demi keamanan.</p>
|
||||||
|
|
||||||
|
<p>Waktu: {{ now() }}</p>
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
@extends('layouts.app')
|
|
||||||
|
|
||||||
@section('content')
|
|
||||||
<div class="container-fluid px-4">
|
|
||||||
|
|
||||||
{{-- HEADER --}}
|
|
||||||
<div class="mb-4">
|
|
||||||
<h4 class="fw-bold mb-0">Absensi Guru</h4>
|
|
||||||
<small class="text-muted">
|
|
||||||
Lakukan absensi harian dengan kamera
|
|
||||||
</small>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
|
|
||||||
{{-- KAMERA --}}
|
|
||||||
<div class="col-md-8">
|
|
||||||
<div class="card border-0 shadow-sm">
|
|
||||||
<div class="card-body text-center">
|
|
||||||
|
|
||||||
<div id="camera-area" class="mb-3">
|
|
||||||
<video id="video" width="100%" height="350" autoplay class="rounded border"></video>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button id="start-camera" class="btn btn-primary px-4">
|
|
||||||
Aktifkan Kamera
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<button id="capture" class="btn btn-success px-4 d-none">
|
|
||||||
Ambil Foto
|
|
||||||
</button>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- INFO ABSENSI --}}
|
|
||||||
<div class="col-md-4">
|
|
||||||
<div class="card border-0 shadow-sm">
|
|
||||||
<div class="card-body">
|
|
||||||
|
|
||||||
<h6 class="fw-bold mb-3">Informasi</h6>
|
|
||||||
|
|
||||||
<ul class="list-group list-group-flush">
|
|
||||||
|
|
||||||
<li class="list-group-item d-flex justify-content-between">
|
|
||||||
<span>Nama</span>
|
|
||||||
<strong>{{ auth()->user()->name }}</strong>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="list-group-item d-flex justify-content-between">
|
|
||||||
<span>Tanggal</span>
|
|
||||||
<strong>{{ date('d M Y') }}</strong>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="list-group-item d-flex justify-content-between">
|
|
||||||
<span>Jam</span>
|
|
||||||
<strong id="jam"></strong>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="list-group-item d-flex justify-content-between">
|
|
||||||
<span>Status</span>
|
|
||||||
<span class="badge bg-secondary">Belum Absen</span>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- SCRIPT --}}
|
|
||||||
<script>
|
|
||||||
const video = document.getElementById('video');
|
|
||||||
const startBtn = document.getElementById('start-camera');
|
|
||||||
const captureBtn = document.getElementById('capture');
|
|
||||||
|
|
||||||
startBtn.addEventListener('click', async () => {
|
|
||||||
let stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
||||||
video.srcObject = stream;
|
|
||||||
|
|
||||||
startBtn.classList.add('d-none');
|
|
||||||
captureBtn.classList.remove('d-none');
|
|
||||||
});
|
|
||||||
|
|
||||||
// JAM REALTIME
|
|
||||||
setInterval(() => {
|
|
||||||
let now = new Date();
|
|
||||||
document.getElementById('jam').innerText =
|
|
||||||
now.getHours().toString().padStart(2, '0') + ':' +
|
|
||||||
now.getMinutes().toString().padStart(2, '0') + ':' +
|
|
||||||
now.getSeconds().toString().padStart(2, '0');
|
|
||||||
}, 1000);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
@endsection
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container mt-4">
|
||||||
|
|
||||||
|
<h4 class="fw-bold mb-4">📊 Manajemen Absensi Guru</h4>
|
||||||
|
|
||||||
|
<div class="card shadow p-4 mb-4">
|
||||||
|
|
||||||
|
<form method="GET" action="{{ route('guru.absensi') }}">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="fw-bold">Kelas</label>
|
||||||
|
<select name="kelas_id" class="form-control" required>
|
||||||
|
<option value="">-- Pilih Kelas --</option>
|
||||||
|
@foreach($kelas as $k)
|
||||||
|
<option value="{{ $k->id }}"
|
||||||
|
{{ request('kelas_id') == $k->id ? 'selected' : '' }}>
|
||||||
|
{{ $k->nama_kelas }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="fw-bold">Mapel</label>
|
||||||
|
|
||||||
|
<input type="hidden" name="mapel_id" value="{{ $mapel->id }}">
|
||||||
|
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
value="{{ $mapel->nama_mapel }}" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-primary w-100">
|
||||||
|
▶ Mulai Absensi
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- 🔥 TAMPIL FORM ABSENSI --}}
|
||||||
|
@if(isset($siswa))
|
||||||
|
|
||||||
|
<div class="card shadow p-4 mb-4">
|
||||||
|
|
||||||
|
<h5 class="fw-bold mb-3">
|
||||||
|
📋 Absensi Kelas {{ $kelasAktif->nama_kelas }}
|
||||||
|
</h5>
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('guru.absensi.simpan') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<input type="hidden" name="kelas_id" value="{{ $kelasAktif->id }}">
|
||||||
|
|
||||||
|
<input type="hidden" name="mapel_id" value="{{ $mapel->id }}">
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="fw-bold">Mapel</label>
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
value="{{ $mapel->nama_mapel }}" readonly>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<button type="button" class="btn btn-success btn-sm" onclick="setAll('hadir')">
|
||||||
|
✔ Semua Hadir
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nama</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Keterangan</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($siswa as $s)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $s->nama }}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<select name="absensi[{{ $s->id }}][status]" class="form-control status">
|
||||||
|
<option value="hadir">Hadir</option>
|
||||||
|
<option value="izin">Izin</option>
|
||||||
|
<option value="sakit">Sakit</option>
|
||||||
|
<option value="alpha">Alpha</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text"
|
||||||
|
name="absensi[{{ $s->id }}][keterangan]"
|
||||||
|
class="form-control"
|
||||||
|
placeholder="Opsional...">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<button class="btn btn-primary w-100 mt-3">
|
||||||
|
💾 Simpan Absensi
|
||||||
|
</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- 🔥 DATA ABSENSI --}}
|
||||||
|
@if(isset($riwayat))
|
||||||
|
|
||||||
|
<div class="card shadow p-4">
|
||||||
|
|
||||||
|
<h5 class="fw-bold mb-3">📊 Riwayat Absensi</h5>
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nama</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Keterangan</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@forelse($riwayat as $r)
|
||||||
|
<tr>
|
||||||
|
<td>{{ $r->siswa->nama }}</td>
|
||||||
|
<td>{{ ucfirst($r->status) }}</td>
|
||||||
|
<td>{{ $r->keterangan }}</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="3" class="text-center text-muted">Belum ada data</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endif
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function setAll(status) {
|
||||||
|
document.querySelectorAll('.status').forEach(el => {
|
||||||
|
el.value = status;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<h4 class="fw-bold mb-1">Tambah Tugas</h4>
|
||||||
|
<small class="text-muted">Isi data tugas yang akan diberikan kepada siswa</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card shadow-sm border-0">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<form action="{{ route('guru.tugas.store') }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label class="form-label">Judul Tugas</label>
|
||||||
|
<input type="text" name="judul" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<label class="form-label">Kelas</label>
|
||||||
|
<select name="kelas_id" class="form-select" required>
|
||||||
|
<option value="">-- Pilih Kelas --</option>
|
||||||
|
@foreach($kelas as $k)
|
||||||
|
<option value="{{ $k->id }}">{{ $k->nama_kelas }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-3 mb-3">
|
||||||
|
<label class="form-label">Mata Pelajaran</label>
|
||||||
|
|
||||||
|
@if($mapel)
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
value="{{ $mapel->nama_mapel }}"
|
||||||
|
readonly>
|
||||||
|
|
||||||
|
<input type="hidden" name="mapel_id" value="{{ $mapel->id }}">
|
||||||
|
@else
|
||||||
|
<input type="text" class="form-control"
|
||||||
|
value="Mapel belum diset di akun guru" readonly>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 mb-3">
|
||||||
|
<label class="form-label">Deskripsi</label>
|
||||||
|
<textarea name="deskripsi" rows="4" class="form-control"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 mb-3">
|
||||||
|
<label class="form-label">Upload File Tugas</label>
|
||||||
|
<input type="file" name="file" class="form-control"
|
||||||
|
accept=".pdf,.doc,.docx,.ppt,.pptx">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<label class="form-label">Deadline</label>
|
||||||
|
<input type="datetime-local" name="deadline" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 d-flex justify-content-end">
|
||||||
|
<a href="{{ route('guru.tugas.index') }}" class="btn btn-secondary me-2">
|
||||||
|
Kembali
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
Simpan Tugas
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>Edit Tugas</h4>
|
||||||
|
|
||||||
|
<form action="{{ route('guru.tugas.update', $tugas->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
|
||||||
|
{{-- ERROR --}}
|
||||||
|
@if ($errors->any())
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<div>{{ $error }}</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
{{-- JUDUL --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Judul</label>
|
||||||
|
<input type="text" name="judul" class="form-control" value="{{ $tugas->judul }}" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- KELAS --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Kelas</label>
|
||||||
|
<select name="kelas_id" class="form-control" required>
|
||||||
|
@foreach($kelas as $k)
|
||||||
|
<option value="{{ $k->id }}"
|
||||||
|
{{ $tugas->kelas_id == $k->id ? 'selected' : '' }}>
|
||||||
|
{{ $k->nama_kelas }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- DESKRIPSI --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Deskripsi</label>
|
||||||
|
<textarea name="deskripsi" class="form-control">{{ $tugas->deskripsi }}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- FILE LAMA --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>File Lama</label><br>
|
||||||
|
|
||||||
|
@if($tugas->file)
|
||||||
|
<a href="{{ asset('storage/' . $tugas->file) }}" target="_blank">
|
||||||
|
Lihat / Download File
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<span class="text-muted">Tidak ada file</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- GANTI FILE --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Ganti File (opsional)</label>
|
||||||
|
<input type="file" name="file" class="form-control"
|
||||||
|
accept=".pdf,.doc,.docx,.ppt,.pptx">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- DEADLINE (DATETIME) --}}
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Deadline</label>
|
||||||
|
<input type="datetime-local" name="deadline"
|
||||||
|
value="{{ \Carbon\Carbon::parse($tugas->deadline)->format('Y-m-d\TH:i') }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- BUTTON --}}
|
||||||
|
<button type="submit" class="btn btn-primary">Update</button>
|
||||||
|
<a href="{{ route('guru.tugas.index') }}" class="btn btn-secondary">Kembali</a>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<!-- HEADER -->
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<h4 class="mb-1 fw-bold">Manajemen Tugas</h4>
|
||||||
|
<small class="text-muted">Kelola dan pantau tugas yang diberikan kepada siswa</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<a href="{{ route('guru.tugas.create') }}" class="btn btn-primary">
|
||||||
|
<i class="fas fa-plus"></i> Tambah Tugas
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- CARD -->
|
||||||
|
<div class="card shadow-sm border-0">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-hover align-middle">
|
||||||
|
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th>Judul</th>
|
||||||
|
<th>Kelas</th>
|
||||||
|
<th>Mata Pelajaran</th>
|
||||||
|
<th>Pengumpulan</th> {{-- 🔥 baru --}}
|
||||||
|
<th>Status</th> {{-- 🔥 baru --}}
|
||||||
|
<th>File</th>
|
||||||
|
<th>Deadline</th>
|
||||||
|
<th class="text-center">Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@forelse($tugas as $t)
|
||||||
|
<tr>
|
||||||
|
<td class="fw-semibold">{{ $t->judul }}</td>
|
||||||
|
|
||||||
|
<td>{{ $t->kelas->nama_kelas ?? '-' }}</td>
|
||||||
|
|
||||||
|
<td>{{ $t->mapel->nama_mapel ?? '-' }}</td>
|
||||||
|
|
||||||
|
{{-- 🔥 JUMLAH PENGUMPULAN --}}
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-primary">
|
||||||
|
{{ $t->pengumpulan_count }} / {{ $t->total_siswa }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- 🔥 STATUS DEADLINE --}}
|
||||||
|
<td>
|
||||||
|
@if(now()->gt($t->deadline))
|
||||||
|
<span class="badge bg-danger">Lewat</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-success">Aktif</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- FILE --}}
|
||||||
|
<td>
|
||||||
|
@if($t->file)
|
||||||
|
<a href="{{ route('guru.tugas.download', $t->id) }}" class="btn btn-sm btn-success">
|
||||||
|
Download
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
-
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- DEADLINE --}}
|
||||||
|
<td>
|
||||||
|
<span class="badge bg-light text-dark">
|
||||||
|
{{ \Carbon\Carbon::parse($t->deadline)->format('d M Y H:i') }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- AKSI --}}
|
||||||
|
<td class="text-center">
|
||||||
|
|
||||||
|
<a href="{{ route('guru.tugas.pengumpulan', $t->id) }}"
|
||||||
|
class="btn btn-sm btn-primary mb-1">
|
||||||
|
Pengumpulan
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('guru.tugas.show', $t->id) }}"
|
||||||
|
class="btn btn-sm btn-info mb-1">
|
||||||
|
Detail
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="{{ route('guru.tugas.edit', $t->id) }}"
|
||||||
|
class="btn btn-sm btn-warning">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="8" class="text-center text-muted">
|
||||||
|
Belum ada tugas
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>Pengumpulan Tugas: {{ $tugas->judul }}</h4>
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nama Siswa</th>
|
||||||
|
<th>File</th>
|
||||||
|
<th>Waktu Kumpul</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Nilai</th>
|
||||||
|
<th>Komentar</th>
|
||||||
|
<th>Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($tugas->pengumpulan as $p)
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td>{{ $p->siswa->nama ?? '-' }}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<a href="{{ asset('storage/' . $p->file) }}" target="_blank">
|
||||||
|
Download
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{ \Carbon\Carbon::parse($p->created_at)->format('d M Y H:i') }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
@if($p->status == 'telat')
|
||||||
|
<span class="badge bg-warning text-dark">Telat</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-success">Tepat Waktu</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<!-- 🔥 FORM NILAI LANGSUNG -->
|
||||||
|
<form method="POST" action="{{ route('guru.tugas.nilai', $p->id) }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="number" name="nilai"
|
||||||
|
value="{{ $p->nilai }}"
|
||||||
|
class="form-control"
|
||||||
|
style="width:80px;">
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<input type="text" name="komentar"
|
||||||
|
value="{{ $p->komentar }}"
|
||||||
|
class="form-control">
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-success">
|
||||||
|
Simpan
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>Detail Tugas</h4>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
<p><b>Judul:</b> {{ $tugas->judul }}</p>
|
||||||
|
<p><b>Kelas:</b> {{ $tugas->kelas->nama_kelas }}</p>
|
||||||
|
<p><b>Mapel:</b> {{ $tugas->mapel->nama_mapel }}</p>
|
||||||
|
<p><b>Deskripsi:</b> {{ $tugas->deskripsi }}</p>
|
||||||
|
<p><b>Deadline:</b> {{ $tugas->deadline }}</p>
|
||||||
|
|
||||||
|
<a href="{{ route('guru.tugas.index') }}" class="btn btn-secondary">Kembali</a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<h2 class="mb-4 text-primary">📝 Buat Ujian + Soal</h2>
|
||||||
|
|
||||||
|
<div class="card shadow-sm border-0">
|
||||||
|
<div class="card-body">
|
||||||
|
|
||||||
|
@if(session('success'))
|
||||||
|
<div class="alert alert-success">{{ session('success') }}</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if($errors->any())
|
||||||
|
<div class="alert alert-danger">{{ $errors->first() }}</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('guru.ujian.store') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
{{-- ================= UJIAN ================= --}}
|
||||||
|
<h5 class="text-primary mb-3">📘 Data Ujian</h5>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label>Judul</label>
|
||||||
|
<input type="text" name="judul" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label>Durasi (menit)</label>
|
||||||
|
<input type="number" name="durasi" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label>Mulai</label>
|
||||||
|
<input type="datetime-local" name="mulai" class="form-control">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-6 mb-3">
|
||||||
|
<label>Selesai</label>
|
||||||
|
<input type="datetime-local" name="selesai" class="form-control">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
{{-- ================= SOAL ================= --}}
|
||||||
|
<h5 class="text-success mb-3">🧠 Soal Ujian</h5>
|
||||||
|
|
||||||
|
<div id="soal-container">
|
||||||
|
|
||||||
|
{{-- SOAL PERTAMA --}}
|
||||||
|
<div class="soal-item border p-3 mb-3 rounded">
|
||||||
|
|
||||||
|
<label>Pertanyaan</label>
|
||||||
|
<textarea name="soal[0][pertanyaan]" class="form-control" required></textarea>
|
||||||
|
|
||||||
|
<div class="row mt-2">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input name="soal[0][a]" class="form-control" placeholder="Pilihan A">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input name="soal[0][b]" class="form-control" placeholder="Pilihan B">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mt-2">
|
||||||
|
<input name="soal[0][c]" class="form-control" placeholder="Pilihan C">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6 mt-2">
|
||||||
|
<input name="soal[0][d]" class="form-control" placeholder="Pilihan D">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<select name="soal[0][jawaban]" class="form-control mt-2">
|
||||||
|
<option value="a">Jawaban A</option>
|
||||||
|
<option value="b">Jawaban B</option>
|
||||||
|
<option value="c">Jawaban C</option>
|
||||||
|
<option value="d">Jawaban D</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="button" class="btn btn-info mb-3" onclick="tambahSoal()">+ Tambah Soal</button>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<a href="{{ route('guru.ujian.index') }}" class="btn btn-secondary">
|
||||||
|
← Kembali
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button class="btn btn-success">
|
||||||
|
💾 Simpan Ujian + Soal
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
let index = 1;
|
||||||
|
|
||||||
|
function tambahSoal() {
|
||||||
|
let html = `
|
||||||
|
<div class="soal-item border p-3 mb-3 rounded">
|
||||||
|
<label>Pertanyaan</label>
|
||||||
|
<textarea name="soal[${index}][pertanyaan]" class="form-control"></textarea>
|
||||||
|
|
||||||
|
<input name="soal[${index}][a]" class="form-control mt-2" placeholder="A">
|
||||||
|
<input name="soal[${index}][b]" class="form-control mt-2" placeholder="B">
|
||||||
|
<input name="soal[${index}][c]" class="form-control mt-2" placeholder="C">
|
||||||
|
<input name="soal[${index}][d]" class="form-control mt-2" placeholder="D">
|
||||||
|
|
||||||
|
<select name="soal[${index}][jawaban]" class="form-control mt-2">
|
||||||
|
<option value="a">A</option>
|
||||||
|
<option value="b">B</option>
|
||||||
|
<option value="c">C</option>
|
||||||
|
<option value="d">D</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.getElementById('soal-container').insertAdjacentHTML('beforeend', html);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
<a href="{{ route('guru.ujian.create') }}">+ Buat Ujian</a>
|
||||||
|
<ul>
|
||||||
|
@foreach($data as $u)
|
||||||
|
<li>
|
||||||
|
{{ $u->judul }}
|
||||||
|
<a href="{{ route('guru.ujian.soal', $u->id) }}">Input Soal</a>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<h3>Input Soal: {{ $ujian->judul }}</h3>
|
||||||
|
|
||||||
|
@if(session('success')) <div>{{ session('success') }}</div> @endif
|
||||||
|
@if($errors->any()) <div>{{ $errors->first() }}</div> @endif
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('guru.ujian.storeSoal', $ujian->id) }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
@for($i=0; $i<5; $i++)
|
||||||
|
<p>Soal {{ $i+1 }}</p>
|
||||||
|
|
||||||
|
<input type="text" name="soal[{{ $i }}][pertanyaan]" placeholder="Pertanyaan" required><br>
|
||||||
|
|
||||||
|
<input type="text" name="soal[{{ $i }}][a]" placeholder="A" required><br>
|
||||||
|
<input type="text" name="soal[{{ $i }}][b]" placeholder="B" required><br>
|
||||||
|
<input type="text" name="soal[{{ $i }}][c]" placeholder="C" required><br>
|
||||||
|
<input type="text" name="soal[{{ $i }}][d]" placeholder="D" required><br>
|
||||||
|
|
||||||
|
<select name="soal[{{ $i }}][jawaban]" required>
|
||||||
|
<option value="a">A</option>
|
||||||
|
<option value="b">B</option>
|
||||||
|
<option value="c">C</option>
|
||||||
|
<option value="d">D</option>
|
||||||
|
</select>
|
||||||
|
<hr>
|
||||||
|
@endfor
|
||||||
|
|
||||||
|
<button>Simpan Soal</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -1,24 +1,104 @@
|
||||||
@extends('layouts.app')
|
@extends('layouts.app')
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="container">
|
<div class="container-fluid mt-4">
|
||||||
|
|
||||||
<h3>Absensi</h3>
|
<div class="row">
|
||||||
|
|
||||||
<table class="table table-bordered">
|
{{-- LEFT PANEL --}}
|
||||||
<tr>
|
<div class="col-md-3">
|
||||||
<th>Tanggal</th>
|
|
||||||
<th>Status</th>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
@foreach($absensi as $a)
|
<div class="card shadow-sm border-0 mb-3">
|
||||||
<tr>
|
<div class="card-body">
|
||||||
<td>{{ $a->tanggal }}</td>
|
<h6 class="text-muted mb-2">Informasi Siswa</h6>
|
||||||
<td>{{ $a->status }}</td>
|
<hr>
|
||||||
</tr>
|
<p class="mb-1"><b>Nama:</b> {{ auth()->user()->name }}</p>
|
||||||
@endforeach
|
<p class="mb-1"><b>Kelas:</b> {{ auth()->user()->siswa->kelas->nama_kelas ?? '-' }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</table>
|
<div class="card shadow-sm border-0 text-center">
|
||||||
|
<div class="card-body">
|
||||||
|
<h6 class="text-muted mb-3">Status Hari Ini</h6>
|
||||||
|
|
||||||
|
@if($sudahAbsen ?? false)
|
||||||
|
<span class="badge bg-success px-3 py-2">Sudah Hadir</span>
|
||||||
|
@else
|
||||||
|
<span class="badge bg-warning text-dark px-3 py-2">Belum Absen</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- MAIN --}}
|
||||||
|
<div class="col-md-9">
|
||||||
|
|
||||||
|
{{-- LIST ABSENSI PER MAPEL --}}
|
||||||
|
@forelse($groupedAbsensi as $namaMapel => $items)
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
|
||||||
|
{{-- HEADER MAPEL --}}
|
||||||
|
<h5 class="fw-bold text-primary">
|
||||||
|
📚 {{ $namaMapel }}
|
||||||
|
</h5>
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
@foreach($items as $absensi)
|
||||||
|
|
||||||
|
<div class="col-md-4 mb-3">
|
||||||
|
<div class="card shadow-sm border-0 h-100">
|
||||||
|
<div class="card-body text-center">
|
||||||
|
|
||||||
|
<i class="fas fa-user-check text-success mb-2"></i>
|
||||||
|
|
||||||
|
<h6 class="fw-bold">
|
||||||
|
{{ optional($absensi->guru)->nama ?? '-' }}
|
||||||
|
</h6>
|
||||||
|
|
||||||
|
<small class="text-muted d-block mb-2">
|
||||||
|
{{ \Carbon\Carbon::now()->translatedFormat('H:i') }}
|
||||||
|
</small>
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('siswa.absensi.hadir') }}">
|
||||||
|
@csrf
|
||||||
|
<input type="hidden" name="absensi_id" value="{{ $absensi->id }}">
|
||||||
|
|
||||||
|
@php
|
||||||
|
$sudah = \App\Models\AbsensiDetail::where('absensi_id', $absensi->id)
|
||||||
|
->where('siswa_id', auth()->user()->siswa->id)
|
||||||
|
->exists();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<button class="btn btn-success btn-sm rounded-pill"
|
||||||
|
@if($sudah) disabled @endif>
|
||||||
|
|
||||||
|
{{ $sudah ? 'Sudah Absen' : 'Hadir' }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@empty
|
||||||
|
<div class="text-center text-muted">
|
||||||
|
Tidak ada absensi aktif
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>Daftar Tugas</h4>
|
||||||
|
|
||||||
|
<table class="table table-bordered">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Judul</th>
|
||||||
|
<th>Mapel</th>
|
||||||
|
<th>Deadline</th>
|
||||||
|
<th>Waktu Kumpul</th>
|
||||||
|
<th>Nilai</th>
|
||||||
|
<th>Komentar</th>
|
||||||
|
<th>Status</th>
|
||||||
|
<th>Aksi</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
@foreach($tugas as $t)
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td>{{ $t->judul }}</td>
|
||||||
|
<td>{{ $t->mapel->nama_mapel ?? '-' }}</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{ \Carbon\Carbon::parse($t->deadline)->format('d M Y H:i') }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
@if($t->waktu_kumpul)
|
||||||
|
{{ \Carbon\Carbon::parse($t->waktu_kumpul)->format('d M Y H:i') }}
|
||||||
|
@else
|
||||||
|
-
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- NILAI --}}
|
||||||
|
<td>
|
||||||
|
{{ $t->nilai ?? '-' }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- KOMENTAR --}}
|
||||||
|
<td>
|
||||||
|
{{ $t->komentar ?? '-' }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- STATUS --}}
|
||||||
|
<td>
|
||||||
|
@if($t->status == 'tepat')
|
||||||
|
<span class="badge bg-success">Tepat</span>
|
||||||
|
|
||||||
|
@elseif($t->status == 'telat')
|
||||||
|
<span class="badge bg-warning text-dark">Telat</span>
|
||||||
|
|
||||||
|
@elseif($t->status == 'lewat')
|
||||||
|
<span class="badge bg-danger">Belum Kumpul</span>
|
||||||
|
|
||||||
|
@else
|
||||||
|
<span class="badge bg-secondary">Belum</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
{{-- AKSI --}}
|
||||||
|
<td>
|
||||||
|
@if($t->file)
|
||||||
|
<a href="{{ route('guru.tugas.download', $t->id) }}"
|
||||||
|
class="btn btn-sm btn-success">
|
||||||
|
Download
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if(!$t->waktu_kumpul && now()->lt($t->deadline))
|
||||||
|
<a href="{{ route('siswa.tugas.kumpul', $t->id) }}"
|
||||||
|
class="btn btn-sm btn-primary">
|
||||||
|
Kumpulkan
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<h4>Kumpulkan Tugas</h4>
|
||||||
|
|
||||||
|
<form action="{{ route('siswa.tugas.store', $tugas->id) }}" method="POST" enctype="multipart/form-data">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="mb-3">
|
||||||
|
<label>Upload Jawaban</label>
|
||||||
|
<input type="file" name="file" class="form-control" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button class="btn btn-success">Upload</button>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<h2>Hasil Ujian</h2>
|
||||||
|
|
||||||
|
<div class="card p-4">
|
||||||
|
<h3>Nilai: {{ $nilai }}</h3>
|
||||||
|
<p>Benar: {{ $benar }} / {{ $total }}</p>
|
||||||
|
|
||||||
|
<a href="{{ route('siswa.dashboard') }}" class="btn btn-primary">
|
||||||
|
Kembali ke Dashboard
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<h2>Ujian Tersedia</h2>
|
||||||
|
|
||||||
|
@foreach($ujians as $u)
|
||||||
|
<div class="card mb-2 p-3">
|
||||||
|
<h5>{{ $u->judul }}</h5>
|
||||||
|
<p>Durasi: {{ $u->durasi }} menit</p>
|
||||||
|
|
||||||
|
<a href="{{ route('siswa.ujian.kerjakan', $u->id) }}" class="btn btn-primary">
|
||||||
|
Kerjakan
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
@endsection
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
@extends('layouts.app')
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
|
||||||
|
<div class="container-fluid">
|
||||||
|
|
||||||
|
<h3 class="mb-3">{{ $ujian->judul }}</h3>
|
||||||
|
|
||||||
|
{{-- TIMER --}}
|
||||||
|
<div class="alert alert-info">
|
||||||
|
⏱ Sisa waktu: <b id="timer"></b>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('siswa.ujian.submit', $ujian->id) }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
{{-- ================= KIRI: SOAL ================= --}}
|
||||||
|
<div class="col-md-9">
|
||||||
|
|
||||||
|
@foreach($soals as $i => $s)
|
||||||
|
<div class="card mb-3 p-3" id="soal{{ $s->id }}">
|
||||||
|
|
||||||
|
<b>Soal {{ $loop->iteration }}</b><br>
|
||||||
|
{{ $s->pertanyaan }}
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="jawaban[{{ $s->id }}]" value="a">
|
||||||
|
{{ $s->a }}
|
||||||
|
</label><br>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="jawaban[{{ $s->id }}]" value="b">
|
||||||
|
{{ $s->b }}
|
||||||
|
</label><br>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="jawaban[{{ $s->id }}]" value="c">
|
||||||
|
{{ $s->c }}
|
||||||
|
</label><br>
|
||||||
|
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="jawaban[{{ $s->id }}]" value="d">
|
||||||
|
{{ $s->d }}
|
||||||
|
</label><br>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
{{-- BUTTON FINISH --}}
|
||||||
|
<div class="text-end mb-5">
|
||||||
|
<button class="btn btn-success btn-lg">
|
||||||
|
✅ Finish Ujian
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- ================= KANAN: DAFTAR SOAL ================= --}}
|
||||||
|
<div class="col-md-3">
|
||||||
|
|
||||||
|
<div class="card p-3">
|
||||||
|
|
||||||
|
<b>Daftar Soal</b>
|
||||||
|
|
||||||
|
<div class="d-flex flex-wrap mt-2">
|
||||||
|
@foreach($soals as $i => $s)
|
||||||
|
<a href="#soal{{ $s->id }}"
|
||||||
|
class="btn btn-sm btn-outline-primary m-1">
|
||||||
|
{{ $loop->iteration }}
|
||||||
|
</a>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- ================= TIMER SCRIPT ================= --}}
|
||||||
|
<script>
|
||||||
|
|
||||||
|
let waktu = {{ $ujian->durasi * 60 }};
|
||||||
|
|
||||||
|
let timer = setInterval(function() {
|
||||||
|
|
||||||
|
let menit = Math.floor(waktu / 60);
|
||||||
|
let detik = waktu % 60;
|
||||||
|
|
||||||
|
document.getElementById('timer').innerHTML =
|
||||||
|
menit + " : " + (detik < 10 ? "0" + detik : detik);
|
||||||
|
|
||||||
|
waktu--;
|
||||||
|
|
||||||
|
if (waktu < 0) {
|
||||||
|
clearInterval(timer);
|
||||||
|
alert("Waktu habis!");
|
||||||
|
document.querySelector('form').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
@endsection
|
||||||
441
routes/web.php
441
routes/web.php
|
|
@ -1,67 +1,87 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
use App\Http\Controllers\AuthController;
|
use App\Http\Controllers\AuthController;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Mail;
|
// ================= ADMIN =================
|
||||||
|
use App\Http\Controllers\Admin\DashboardController as AdminDashboard;
|
||||||
|
use App\Http\Controllers\Admin\GuruController;
|
||||||
|
use App\Http\Controllers\Admin\SiswaController;
|
||||||
|
use App\Http\Controllers\Admin\MataPelajaranController;
|
||||||
|
use App\Http\Controllers\Admin\KelasController;
|
||||||
|
use App\Http\Controllers\Admin\JadwalController as AdminJadwal;
|
||||||
|
use App\Http\Controllers\Admin\ProfileController;
|
||||||
|
|
||||||
Route::get('/login', [AuthController::class, 'showLogin'])->name('login');
|
// ================= GURU =================
|
||||||
Route::post('/login', [AuthController::class, 'login']);
|
use App\Http\Controllers\Guru\DashboardController as GuruDashboard;
|
||||||
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
|
use App\Http\Controllers\Guru\JadwalController as GuruJadwal;
|
||||||
// ================= FORGOT PASSWORD =================
|
use App\Http\Controllers\Guru\AbsensiController;
|
||||||
Route::prefix('auth')->middleware('guest')->group(function () {
|
use App\Http\Controllers\Guru\NilaiController as GuruNilai;
|
||||||
|
use App\Http\Controllers\Guru\TugasController;
|
||||||
|
use App\Models\Jadwal;
|
||||||
|
use App\Http\Controllers\Guru\MapelController;
|
||||||
|
|
||||||
// ================= FORGOT PASSWORD =================
|
|
||||||
|
|
||||||
Route::get('/forgot-password', [AuthController::class, 'showForgot'])
|
// ================= SISWA =================
|
||||||
->name('forgot.password');
|
use App\Http\Controllers\Siswa\DashboardController as SiswaDashboard;
|
||||||
|
use App\Http\Controllers\Siswa\JadwalController as SiswaJadwal;
|
||||||
|
use App\Http\Controllers\Siswa\AbsensiController as SiswaAbsensi;
|
||||||
|
use App\Http\Controllers\Siswa\NilaiController as SiswaNilai;
|
||||||
|
use App\Http\Controllers\Siswa\ProfileController as SiswaProfile;
|
||||||
|
use App\Http\Controllers\Siswa\AbsensiController as SiswaAbsensiController;
|
||||||
|
|
||||||
Route::post('/send-otp', [AuthController::class, 'sendOtp'])
|
//=================otp=================
|
||||||
->name('send.otp');
|
|
||||||
|
|
||||||
Route::get('/verify-otp', [AuthController::class, 'showVerifyOtp'])
|
use App\Http\Controllers\Auth\OtpController;
|
||||||
->name('verify.otp.form');
|
|
||||||
|
|
||||||
Route::post('/verify-otp', [AuthController::class, 'verifyOtp'])
|
use Illuminate\Support\Facades\Password;
|
||||||
->name('verify.otp');
|
use App\Http\Controllers\Auth\ForgotPasswordController;
|
||||||
|
use App\Http\Controllers\Auth\ResetPasswordController;
|
||||||
|
|
||||||
Route::get('/reset-password', [AuthController::class, 'showResetPassword'])
|
use App\Http\Controllers\Siswa\UjianController;
|
||||||
->name('reset.password.form');
|
|
||||||
|
|
||||||
Route::post('/reset-password', [AuthController::class, 'resetPassword'])
|
|
||||||
->name('reset.password');
|
|
||||||
|
|
||||||
Route::post('/send-otp', [AuthController::class, 'sendOtp'])->name('send.otp');
|
use App\Http\Controllers\Guru\UjianController as GuruUjian;
|
||||||
});
|
use App\Http\Controllers\Siswa\UjianController as SiswaUjian;
|
||||||
|
|
||||||
Route::get('/test-email', function () {
|
|
||||||
Mail::raw('Tes email berhasil', function ($message) {
|
|
||||||
$message->to('EMAIL_KAMU@gmail.com')
|
|
||||||
->subject('Test Email Laravel');
|
|
||||||
});
|
|
||||||
|
|
||||||
return 'Email terkirim!';
|
|
||||||
});
|
|
||||||
|
|
||||||
// ADMIN
|
|
||||||
Route::get('/admin', function () {
|
|
||||||
return view('admin.dashboard');
|
|
||||||
});
|
|
||||||
|
|
||||||
// GURU
|
|
||||||
Route::get('/guru', function () {
|
|
||||||
return view('guru.dashboard');
|
|
||||||
});
|
|
||||||
|
|
||||||
// SISWA
|
|
||||||
Route::get('/siswa', function () {
|
|
||||||
return view('siswa.dashboard');
|
|
||||||
});
|
|
||||||
/*
|
/*
|
||||||
|----------------------------------------
|
|----------------------------------------
|
||||||
| FORCE PASSWORD (LOGIN SAJA)
|
| ROOT
|
||||||
|
|----------------------------------------
|
||||||
|
*/
|
||||||
|
Route::get('/', function () {
|
||||||
|
return redirect()->route('login');
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
|----------------------------------------
|
||||||
|
| LOGIN
|
||||||
|
|----------------------------------------
|
||||||
|
*/
|
||||||
|
Route::get('/login', [AuthController::class, 'showLogin'])->name('login');
|
||||||
|
Route::post('/login', [AuthController::class, 'login'])->name('login.process');
|
||||||
|
|
||||||
|
/*
|
||||||
|
|----------------------------------------
|
||||||
|
| LOGOUT
|
||||||
|
|----------------------------------------
|
||||||
|
*/
|
||||||
|
Route::post('/logout', function () {
|
||||||
|
Auth::logout();
|
||||||
|
request()->session()->invalidate();
|
||||||
|
request()->session()->regenerateToken();
|
||||||
|
|
||||||
|
return redirect()->route('login');
|
||||||
|
})->name('logout');
|
||||||
|
|
||||||
|
/*
|
||||||
|
|----------------------------------------
|
||||||
|
| FORCE PASSWORD
|
||||||
|----------------------------------------
|
|----------------------------------------
|
||||||
*/
|
*/
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware('auth')->group(function () {
|
||||||
|
|
||||||
Route::get('/force-password', function () {
|
Route::get('/force-password', function () {
|
||||||
return view('auth.force-password');
|
return view('auth.force-password');
|
||||||
})->name('force.password');
|
})->name('force.password');
|
||||||
|
|
@ -72,176 +92,241 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|----------------------------------------
|
|----------------------------------------
|
||||||
| SEMUA HALAMAN (WAJIB FORCE PASSWORD)
|
|
||||||
|----------------------------------------
|
|
||||||
*/
|
|
||||||
Route::middleware(['auth', 'force.password'])->prefix('admin')->name('admin.')->group(function () {
|
|
||||||
|
|
||||||
Route::get('/dashboard', [AdminDashboard::class, 'index'])->name('dashboard');
|
|
||||||
|
|
||||||
Route::resource('guru', GuruController::class);
|
|
||||||
Route::resource('siswa', SiswaController::class);
|
|
||||||
Route::resource('mapel', MataPelajaranController::class);
|
|
||||||
Route::resource('kelas', KelasController::class);
|
|
||||||
Route::resource('jadwal', AdminJadwal::class);
|
|
||||||
|
|
||||||
Route::get('jadwal-grid', [AdminJadwal::class, 'grid'])->name('jadwal.grid');
|
|
||||||
|
|
||||||
Route::get('/profile', [ProfileController::class, 'index'])->name('profile');
|
|
||||||
Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update');
|
|
||||||
|
|
||||||
Route::get('/guru/{id}/nonaktif', [GuruController::class, 'nonaktif'])->name('guru.nonaktif');
|
|
||||||
Route::get('/guru/{id}/aktifkan', [GuruController::class, 'aktifkan'])->name('guru.aktifkan');
|
|
||||||
|
|
||||||
Route::get('/siswa/{id}/nonaktif', [SiswaController::class, 'nonaktif'])->name('siswa.nonaktif');
|
|
||||||
Route::get('/siswa/{id}/aktifkan', [SiswaController::class, 'aktifkan'])->name('siswa.aktifkan');
|
|
||||||
|
|
||||||
Route::post('/siswa/bulk/nonaktif', [SiswaController::class, 'bulkNonaktif'])
|
|
||||||
->name('siswa.bulkNonaktif');
|
|
||||||
|
|
||||||
});
|
|
||||||
// ================= FORGOT PASSWORD =================
|
|
||||||
Route::get('/forgot-password', function () {
|
|
||||||
return view('auth.forgot-password');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::post('/forgot-password', [AuthController::class, 'sendOtp']);
|
|
||||||
|
|
||||||
Route::get('/verify-otp', function () {
|
|
||||||
return view('auth.verify-otp');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::post('/verify-otp', [AuthController::class, 'verifyOtp']);
|
|
||||||
|
|
||||||
Route::get('/reset-password', function () {
|
|
||||||
return view('auth.reset-password');
|
|
||||||
});
|
|
||||||
|
|
||||||
Route::post('/reset-password', [AuthController::class, 'resetPassword']);
|
|
||||||
/*
|
|
||||||
|----------------------------------------
|
|
||||||
| ROOT
|
|
||||||
|----------------------------------------
|
|
||||||
*/
|
|
||||||
Route::get('/', function () {
|
|
||||||
return redirect()->route('login');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| ADMIN
|
| ADMIN
|
||||||
|--------------------------------------------------------------------------
|
|----------------------------------------
|
||||||
*/
|
*/
|
||||||
use App\Http\Controllers\Admin\DashboardController as AdminDashboard;
|
Route::middleware(['auth', 'force.password'])
|
||||||
use App\Http\Controllers\Admin\GuruController;
|
->prefix('admin')
|
||||||
use App\Http\Controllers\Admin\SiswaController;
|
->name('admin.')
|
||||||
use App\Http\Controllers\Admin\MataPelajaranController;
|
->group(function () {
|
||||||
use App\Http\Controllers\Admin\KelasController;
|
|
||||||
use App\Http\Controllers\Admin\JadwalController as AdminJadwal;
|
|
||||||
use App\Http\Controllers\Admin\ProfileController;
|
|
||||||
|
|
||||||
Route::middleware(['auth'])->prefix('admin')->name('admin.')->group(function () {
|
// 🔥 /admin langsung ke dashboard
|
||||||
|
Route::get('/', [AdminDashboard::class, 'index']);
|
||||||
|
|
||||||
Route::get('/dashboard', [AdminDashboard::class, 'index'])->name('dashboard');
|
Route::get('/dashboard', [AdminDashboard::class, 'index'])->name('dashboard');
|
||||||
|
|
||||||
Route::resource('guru', GuruController::class);
|
Route::resource('guru', GuruController::class);
|
||||||
Route::resource('siswa', SiswaController::class);
|
Route::resource('siswa', SiswaController::class);
|
||||||
Route::resource('mapel', MataPelajaranController::class);
|
Route::resource('mapel', MataPelajaranController::class);
|
||||||
Route::resource('kelas', KelasController::class);
|
Route::resource('kelas', KelasController::class);
|
||||||
Route::resource('jadwal', AdminJadwal::class);
|
Route::resource('jadwal', AdminJadwal::class);
|
||||||
|
|
||||||
Route::get('jadwal-grid', [AdminJadwal::class, 'grid'])->name('jadwal.grid');
|
// 🔥 route tambahan
|
||||||
|
Route::get('jadwal/grid', [AdminJadwal::class, 'grid'])->name('jadwal.grid');
|
||||||
|
|
||||||
// PROFILE
|
// PROFILE
|
||||||
Route::get('/profile', [ProfileController::class, 'index'])->name('profile');
|
Route::get('/profile', [ProfileController::class, 'index'])->name('profile');
|
||||||
Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update');
|
Route::post('/profile', [ProfileController::class, 'update'])->name('profile.update');
|
||||||
|
|
||||||
// GURU STATUS
|
// STATUS
|
||||||
Route::get('/guru/{id}/nonaktif', [GuruController::class, 'nonaktif'])->name('guru.nonaktif');
|
Route::get('/guru/{id}/nonaktif', [GuruController::class, 'nonaktif'])->name('guru.nonaktif');
|
||||||
Route::get('/guru/{id}/aktifkan', [GuruController::class, 'aktifkan'])->name('guru.aktifkan');
|
Route::get('/guru/{id}/aktifkan', [GuruController::class, 'aktifkan'])->name('guru.aktifkan');
|
||||||
|
|
||||||
// SISWA STATUS
|
// Route::get('/siswa/{id}/nonaktif', [SiswaController::class, 'nonaktif'])->name('siswa.nonaktif');
|
||||||
Route::get('/siswa/{id}/nonaktif', [SiswaController::class, 'nonaktif'])->name('siswa.nonaktif');
|
// Route::post('/nonaktif/{id}', [SiswaController::class, 'nonaktif'])
|
||||||
Route::get('/siswa/{id}/aktifkan', [SiswaController::class, 'aktifkan'])->name('siswa.aktifkan');
|
// ->name('admin.siswa.nonaktif');
|
||||||
|
// Route::get('/siswa/{id}/aktifkan', [SiswaController::class, 'aktifkan'])->name('siswa.aktifkan');
|
||||||
|
|
||||||
// 🔥 BULK (INI YANG KAMU BUTUHKAN)
|
Route::post('/siswa/bulk/nonaktif', [SiswaController::class, 'bulkNonaktif'])->name('siswa.bulkNonaktif');
|
||||||
Route::post('/siswa/bulk/nonaktif', [SiswaController::class, 'bulkNonaktif'])
|
});
|
||||||
->name('siswa.bulkNonaktif');
|
|
||||||
Route::get('/forgot-password', function () {
|
|
||||||
return view('auth.forgot-password');
|
|
||||||
})->name('forgot.password');
|
|
||||||
|
|
||||||
Route::post('/forgot-password', [AuthController::class, 'sendOtp']);
|
Route::prefix('admin')->name('admin.')->group(function () {
|
||||||
|
|
||||||
Route::get('/verify-otp', function () {
|
Route::post('/siswa/nonaktif/{id}', [SiswaController::class, 'nonaktif'])
|
||||||
return view('auth.verify-otp');
|
->name('siswa.nonaktif');
|
||||||
})->name('verify.otp');
|
|
||||||
|
Route::get('/siswa/aktifkan/{id}', [SiswaController::class, 'aktifkan'])
|
||||||
|
->name('siswa.aktifkan');
|
||||||
|
|
||||||
Route::post('/verify-otp', [AuthController::class, 'verifyOtp']);
|
|
||||||
|
|
||||||
Route::get('/reset-password', function () {
|
|
||||||
return view('auth.reset-password');
|
|
||||||
})->name('reset.password.form');
|
|
||||||
|
|
||||||
Route::post('/reset-password', [AuthController::class, 'resetPasswordOtp']);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|----------------------------------------
|
||||||
| GURU
|
| GURU
|
||||||
|--------------------------------------------------------------------------
|
|----------------------------------------
|
||||||
*/
|
*/
|
||||||
use App\Http\Controllers\Guru\DashboardController as GuruDashboard;
|
Route::middleware(['auth', 'force.password'])
|
||||||
use App\Http\Controllers\Guru\JadwalController as GuruJadwal;
|
->prefix('guru')
|
||||||
use App\Http\Controllers\Guru\AbsensiController as GuruAbsensi;
|
->name('guru.')
|
||||||
use App\Http\Controllers\Guru\NilaiController as GuruNilai;
|
->group(function () {
|
||||||
|
|
||||||
Route::middleware(['auth', 'force.password'])->prefix('guru')->name('guru.')->group(function () {
|
Route::get('/', [GuruDashboard::class, 'index']);
|
||||||
|
Route::get('/dashboard', [GuruDashboard::class, 'index'])->name('dashboard');
|
||||||
|
|
||||||
Route::get('/dashboard', [GuruDashboard::class, 'index'])->name('dashboard');
|
Route::get('/jadwal', [GuruJadwal::class, 'index'])->name('jadwal');
|
||||||
|
|
||||||
Route::get('/jadwal', [GuruJadwal::class, 'index'])->name('jadwal');
|
// =========================
|
||||||
|
// ✅ ABSENSI (FINAL)
|
||||||
|
// =========================
|
||||||
|
Route::get('/absensi', [AbsensiController::class, 'index'])
|
||||||
|
->name('absensi');
|
||||||
|
|
||||||
Route::get('/absensi', [GuruAbsensi::class, 'index'])->name('absensi');
|
Route::post('/absensi/simpan', [AbsensiController::class, 'simpan'])
|
||||||
|
->name('absensi.simpan');
|
||||||
|
|
||||||
// ================= NILAI =================
|
|
||||||
|
|
||||||
Route::get('/nilai', [GuruNilai::class, 'index'])->name('nilai.index');
|
// =========================
|
||||||
|
// NILAI
|
||||||
|
// =========================
|
||||||
|
Route::get('/nilai', [GuruNilai::class, 'index'])->name('nilai.index');
|
||||||
|
Route::get('/nilai/input', [GuruNilai::class, 'inputNilai'])->name('nilai.input');
|
||||||
|
Route::get('/get-siswa/{id}', [GuruNilai::class, 'getSiswaByKelas'])->name('get.siswa');
|
||||||
|
Route::post('/nilai/store-batch', [GuruNilai::class, 'storeBatch'])->name('nilai.storeBatch');
|
||||||
|
Route::get('/nilai/{id}/edit', [GuruNilai::class, 'edit'])->name('nilai.edit');
|
||||||
|
Route::put('/nilai/{id}', [GuruNilai::class, 'update'])->name('nilai.update');
|
||||||
|
|
||||||
Route::get('nilai/input', [GuruNilai::class, 'inputNilai'])->name('nilai.input');
|
// =========================
|
||||||
|
// TUGAS
|
||||||
|
// =========================
|
||||||
|
Route::resource('tugas', TugasController::class);
|
||||||
|
|
||||||
// 🔥 PERBAIKAN: kasih name route
|
Route::get('/tugas/{id}/download', [TugasController::class, 'download'])
|
||||||
Route::get('/get-siswa/{id}', [GuruNilai::class, 'getSiswaByKelas'])->name('get.siswa');
|
->name('tugas.download');
|
||||||
|
|
||||||
Route::post('/nilai/store-batch', [GuruNilai::class, 'storeBatch'])->name('nilai.storeBatch');
|
Route::get('/tugas/{id}/pengumpulan', [TugasController::class, 'pengumpulan'])
|
||||||
Route::get('/nilai/{id}/edit', [GuruNilai::class, 'edit'])->name('nilai.edit');
|
->name('tugas.pengumpulan');
|
||||||
Route::put('/nilai/{id}', [GuruNilai::class, 'update'])->name('nilai.update');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
Route::post('/pengumpulan/{id}/nilai', [TugasController::class, 'nilai'])
|
||||||
|
->name('tugas.nilai');
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// MAPEL
|
||||||
|
// =========================
|
||||||
|
Route::get('/get-mapel-by-kelas/{id}', [MapelController::class, 'getByKelas'])
|
||||||
|
->name('get.mapel');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//==================otp============
|
||||||
|
// Route::post('/send-otp', [OtpController::class, 'sendOtp'])->name('send.otp');
|
||||||
|
// Route::post('/login-otp', [OtpController::class, 'loginOtp'])->name('login.otp');
|
||||||
|
// Route::post('/send-otp-login', [OtpController::class, 'sendOtp'])
|
||||||
|
// ->name('send.otp.login');
|
||||||
|
Route::post('/send-otp', [OtpController::class, 'sendOtp'])->name('send.otp');
|
||||||
|
Route::post('/login-otp', [OtpController::class, 'loginOtp'])->name('login.otp');
|
||||||
|
|
||||||
|
// form email
|
||||||
|
Route::get('/forgot-password', [ForgotPasswordController::class, 'showLinkRequestForm'])
|
||||||
|
->name('password.request');
|
||||||
|
|
||||||
|
// kirim email
|
||||||
|
Route::post('/forgot-password', [ForgotPasswordController::class, 'sendResetLinkEmail'])
|
||||||
|
->name('password.email');
|
||||||
|
|
||||||
|
// form reset
|
||||||
|
Route::get('/reset-password/{token}', [ResetPasswordController::class, 'showResetForm'])
|
||||||
|
->name('password.reset');
|
||||||
|
|
||||||
|
// simpan password baru
|
||||||
|
Route::post('/reset-password', [ResetPasswordController::class, 'reset'])
|
||||||
|
->name('password.update');
|
||||||
|
|
||||||
|
|
||||||
|
Route::get('/forgot-password', function () {
|
||||||
|
return view('auth.forgot-password');
|
||||||
|
})->name('password.request');
|
||||||
|
|
||||||
|
Route::post('/forgot-password', [AuthController::class, 'sendOtp'])
|
||||||
|
->name('password.email');
|
||||||
|
Route::get('/verify-otp', [AuthController::class, 'showVerifyOtp'])
|
||||||
|
->name('verify.otp.form');
|
||||||
|
|
||||||
|
Route::post('/verify-otp', [AuthController::class, 'verifyOtp'])
|
||||||
|
->name('verify.otp');
|
||||||
|
|
||||||
|
// FORM RESET PASSWORD (GET)
|
||||||
|
Route::get('/reset-password', [AuthController::class, 'showResetPassword'])
|
||||||
|
->name('reset.password');
|
||||||
|
|
||||||
|
// PROSES RESET PASSWORD (POST)
|
||||||
|
Route::post('/reset-password', [AuthController::class, 'resetPassword'])
|
||||||
|
->name('password.update');
|
||||||
|
|
||||||
|
Route::post('/reset-password', [AuthController::class, 'resetPassword'])
|
||||||
|
->name('password.update');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|----------------------------------------
|
||||||
| SISWA
|
| SISWA
|
||||||
|--------------------------------------------------------------------------
|
|----------------------------------------
|
||||||
*/
|
*/
|
||||||
use App\Http\Controllers\Siswa\DashboardController as SiswaDashboard;
|
use App\Http\Controllers\Siswa\TugasController as SiswaTugasController;
|
||||||
use App\Http\Controllers\Siswa\JadwalController as SiswaJadwal;
|
|
||||||
use App\Http\Controllers\Siswa\AbsensiController as SiswaAbsensi;
|
|
||||||
use App\Http\Controllers\Siswa\NilaiController as SiswaNilai;
|
|
||||||
use App\Http\Controllers\Siswa\ProfileController as SiswaProfile;
|
|
||||||
|
|
||||||
Route::middleware(['auth', 'force.password'])->prefix('siswa')->name('siswa.')->group(function () {
|
Route::middleware(['auth', 'force.password'])
|
||||||
|
->prefix('siswa')
|
||||||
|
->name('siswa.')
|
||||||
|
->group(function () {
|
||||||
|
|
||||||
Route::get('/dashboard', [SiswaDashboard::class, 'index'])->name('dashboard');
|
Route::get('/', [SiswaDashboard::class, 'index']);
|
||||||
|
|
||||||
Route::get('/jadwal', [SiswaJadwal::class, 'index'])->name('jadwal');
|
Route::get('/dashboard', [SiswaDashboard::class, 'index'])->name('dashboard');
|
||||||
|
Route::get('/jadwal', [SiswaJadwal::class, 'index'])->name('jadwal');
|
||||||
|
Route::get('/absensi', [SiswaAbsensi::class, 'index'])->name('absensi');
|
||||||
|
Route::get('/nilai', [SiswaNilai::class, 'index'])->name('nilai');
|
||||||
|
|
||||||
Route::get('/absensi', [SiswaAbsensi::class, 'index'])->name('absensi');
|
Route::get('/profile', [SiswaProfile::class, 'index'])->name('profile');
|
||||||
|
Route::post('/profile', [SiswaProfile::class, 'update'])->name('profile.update');
|
||||||
|
|
||||||
Route::get('/nilai', [SiswaNilai::class, 'index'])->name('nilai');
|
// ✅ SCAN QR
|
||||||
|
Route::get('/absen/{token}', [SiswaAbsensi::class, 'scan'])
|
||||||
|
->name('absensi.scan');
|
||||||
|
|
||||||
|
// ✅ SUBMIT HADIR
|
||||||
|
Route::post('/absen/hadir', [SiswaAbsensi::class, 'hadir'])
|
||||||
|
->name('absensi.hadir');
|
||||||
|
|
||||||
|
// ================= TUGAS =================
|
||||||
|
Route::get('/tugas', [SiswaTugasController::class, 'index'])->name('tugas.index');
|
||||||
|
Route::get('/tugas/{id}/kumpul', [SiswaTugasController::class, 'kumpul'])->name('tugas.kumpul');
|
||||||
|
Route::post('/tugas/{id}/kumpul', [SiswaTugasController::class, 'store'])->name('tugas.store');
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::middleware(['auth'])->group(function () {
|
||||||
|
|
||||||
|
Route::prefix('guru')->name('guru.')->group(function () {
|
||||||
|
|
||||||
|
Route::get('/ujian', [\App\Http\Controllers\Guru\UjianController::class, 'index'])->name('ujian.index');
|
||||||
|
|
||||||
|
Route::get('/ujian/create', [\App\Http\Controllers\Guru\UjianController::class, 'create'])->name('ujian.create');
|
||||||
|
|
||||||
|
Route::post('/ujian/store', [\App\Http\Controllers\Guru\UjianController::class, 'store'])->name('ujian.store');
|
||||||
|
|
||||||
|
Route::get('/ujian/{id}/soal', [\App\Http\Controllers\Guru\UjianController::class, 'soal'])->name('ujian.soal');
|
||||||
|
|
||||||
|
Route::post('/ujian/{id}/soal', [\App\Http\Controllers\Guru\UjianController::class, 'storeSoal'])->name('ujian.storeSoal');
|
||||||
|
|
||||||
|
// Route::get('/guru/ujian/{id}/soal', [UjianController::class, 'soal']);
|
||||||
|
// Route::post('/guru/ujian/{id}/soal', [UjianController::class, 'storeSoal']);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
// PROFILE
|
});
|
||||||
Route::get('/profile', [SiswaProfile::class, 'index'])->name('profile');
|
|
||||||
Route::post('/profile', [SiswaProfile::class, 'update'])->name('profile.update');
|
Route::middleware(['auth'])->prefix('siswa')->group(function () {
|
||||||
|
|
||||||
|
Route::get('/ujian', [UjianController::class, 'index'])
|
||||||
|
->name('siswa.ujian.index');
|
||||||
|
|
||||||
|
Route::get('/ujian/{id}/kerjakan', [UjianController::class, 'kerjakan'])
|
||||||
|
->name('siswa.ujian.kerjakan');
|
||||||
|
|
||||||
|
Route::post('/ujian/{id}/submit', [UjianController::class, 'submit'])
|
||||||
|
->name('siswa.ujian.submit');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
|----------------------------------------
|
||||||
|
| TEST EMAIL
|
||||||
|
|----------------------------------------
|
||||||
|
*/
|
||||||
|
Route::get('/test-email', function () {
|
||||||
|
Mail::raw('Tes email berhasil', function ($message) {
|
||||||
|
$message->to('EMAIL_KAMU@gmail.com')
|
||||||
|
->subject('Test Email Laravel');
|
||||||
|
});
|
||||||
|
|
||||||
|
return 'Email terkirim!';
|
||||||
});
|
});
|
||||||
|
|
@ -0,0 +1,974 @@
|
||||||
|
-- phpMyAdmin SQL Dump
|
||||||
|
-- version 5.2.0
|
||||||
|
-- https://www.phpmyadmin.net/
|
||||||
|
--
|
||||||
|
-- Host: localhost:3306
|
||||||
|
-- Generation Time: May 03, 2026 at 02:21 AM
|
||||||
|
-- Server version: 8.0.30
|
||||||
|
-- PHP Version: 8.3.21
|
||||||
|
|
||||||
|
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
|
||||||
|
START TRANSACTION;
|
||||||
|
SET time_zone = "+00:00";
|
||||||
|
|
||||||
|
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||||
|
/*!40101 SET NAMES utf8mb4 */;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Database: `smasa`
|
||||||
|
--
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `absensi`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `absensi` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`guru_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`kelas_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`mapel_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`tanggal` date DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `absensi`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `absensi` (`id`, `guru_id`, `kelas_id`, `mapel_id`, `tanggal`, `created_at`, `updated_at`) VALUES
|
||||||
|
(1, 39, 6, 7, '2026-04-24', '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(2, 39, 8, 7, '2026-04-24', '2026-04-23 19:31:54', '2026-04-23 19:31:54');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `absensi_detail`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `absensi_detail` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`absensi_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`status` enum('hadir','izin','sakit','alpha') DEFAULT 'hadir',
|
||||||
|
`keterangan` text,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `absensi_detail`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `absensi_detail` (`id`, `absensi_id`, `siswa_id`, `status`, `keterangan`, `created_at`, `updated_at`) VALUES
|
||||||
|
(1, 1, 15, 'hadir', NULL, '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(2, 1, 16, 'hadir', NULL, '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(3, 1, 19, 'hadir', NULL, '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(4, 1, 22, 'hadir', NULL, '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(5, 1, 23, 'hadir', NULL, '2026-04-23 19:31:25', '2026-04-23 19:31:25'),
|
||||||
|
(6, 2, 17, 'izin', NULL, '2026-04-23 19:31:54', '2026-04-23 19:31:54'),
|
||||||
|
(7, 2, 20, 'hadir', NULL, '2026-04-23 19:31:54', '2026-04-23 19:31:54'),
|
||||||
|
(8, 2, 21, 'hadir', NULL, '2026-04-23 19:31:54', '2026-04-23 19:31:54');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `cache`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `cache` (
|
||||||
|
`key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`value` mediumtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`expiration` int NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `cache_locks`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `cache_locks` (
|
||||||
|
`key` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`owner` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`expiration` int NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `failed_jobs`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `failed_jobs` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`uuid` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`connection` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`queue` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`exception` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`failed_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `gurus`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `gurus` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`nip` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`alamat` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`telepon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`status` enum('aktif','nonaktif') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'aktif',
|
||||||
|
`mapel_id` bigint DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `gurus`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `gurus` (`id`, `nama`, `nip`, `alamat`, `telepon`, `created_at`, `updated_at`, `status`, `mapel_id`) VALUES
|
||||||
|
(36, 'zakaria', '242424213', 'jember', '089785463773', '2026-04-19 21:18:08', '2026-04-19 21:18:08', 'aktif', 2),
|
||||||
|
(37, 'Umam', '213213123', 'kembang', '0879635231', '2026-04-21 11:52:56', '2026-04-21 11:52:56', 'aktif', 3),
|
||||||
|
(39, 'Arengga', '2423123', 'Bondowoso', '6289504732922', '2026-04-22 02:17:14', '2026-04-22 02:47:48', 'aktif', 7);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `hasils`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `hasils` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`ujian_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`nilai` int DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `jadwals`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `jadwals` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`kelas_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`mata_pelajaran_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`hari` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`jam_mulai` time NOT NULL,
|
||||||
|
`jam_selesai` time NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`guru_id` bigint NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `jadwals`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `jadwals` (`id`, `kelas_id`, `mata_pelajaran_id`, `hari`, `jam_mulai`, `jam_selesai`, `created_at`, `updated_at`, `guru_id`) VALUES
|
||||||
|
(13, 6, 5, 'Senin', '07:00:00', '08:00:00', '2026-03-31 21:24:11', '2026-03-31 21:24:11', 14),
|
||||||
|
(14, 6, 2, 'Senin', '12:00:00', '13:00:00', '2026-03-31 21:26:45', '2026-03-31 21:26:45', 15),
|
||||||
|
(15, 6, 5, 'Selasa', '07:00:00', '08:00:00', '2026-03-31 21:27:12', '2026-03-31 21:27:12', 14),
|
||||||
|
(16, 6, 4, 'Selasa', '09:00:00', '10:00:00', '2026-03-31 21:27:30', '2026-03-31 21:27:30', 15),
|
||||||
|
(19, 6, 6, 'Rabu', '20:00:00', '22:00:00', '2026-04-17 02:26:01', '2026-04-17 02:26:01', 25),
|
||||||
|
(20, 6, 2, 'Rabu', '09:00:00', '10:00:00', '2026-04-17 02:28:19', '2026-04-17 02:28:19', 25);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `jawabans`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `jawabans` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`soal_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`jawaban` char(1) NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `jawaban_siswas`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `jawaban_siswas` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`soal_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`jawaban` enum('a','b','c','d') DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `jobs`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `jobs` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`queue` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`attempts` tinyint UNSIGNED NOT NULL,
|
||||||
|
`reserved_at` int UNSIGNED DEFAULT NULL,
|
||||||
|
`available_at` int UNSIGNED NOT NULL,
|
||||||
|
`created_at` int UNSIGNED NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `job_batches`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `job_batches` (
|
||||||
|
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`total_jobs` int NOT NULL,
|
||||||
|
`pending_jobs` int NOT NULL,
|
||||||
|
`failed_jobs` int NOT NULL,
|
||||||
|
`failed_job_ids` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`options` mediumtext COLLATE utf8mb4_unicode_ci,
|
||||||
|
`cancelled_at` int DEFAULT NULL,
|
||||||
|
`created_at` int NOT NULL,
|
||||||
|
`finished_at` int DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `kelas`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `kelas` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`nama_kelas` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`jurusan` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `kelas`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `kelas` (`id`, `nama_kelas`, `jurusan`, `created_at`, `updated_at`) VALUES
|
||||||
|
(6, 'X IPA 1', 'IPA', '2026-03-30 23:19:53', '2026-03-30 23:19:53'),
|
||||||
|
(7, 'X IPA 2', 'IPA', '2026-03-30 23:20:08', '2026-03-30 23:20:08'),
|
||||||
|
(8, 'X IPA 3', 'IPA', '2026-03-30 23:20:16', '2026-03-30 23:20:16'),
|
||||||
|
(9, 'X IPS 1', 'IPS', '2026-03-30 23:20:33', '2026-03-30 23:20:33'),
|
||||||
|
(10, 'X IPS 2', 'IPS', '2026-03-30 23:20:44', '2026-03-30 23:20:44'),
|
||||||
|
(11, 'X IPS 3', 'IPS', '2026-03-30 23:20:57', '2026-03-30 23:20:57');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `mata_pelajarans`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `mata_pelajarans` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`nama_mapel` varchar(255) NOT NULL,
|
||||||
|
`kode_mapel` varchar(100) DEFAULT NULL,
|
||||||
|
`jam_pelajaran` int DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `mata_pelajarans`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `mata_pelajarans` (`id`, `nama_mapel`, `kode_mapel`, `jam_pelajaran`, `created_at`, `updated_at`) VALUES
|
||||||
|
(1, 'Matematika', 'MTK', 2, '2026-04-30 10:25:15', '2026-04-30 10:25:15'),
|
||||||
|
(2, 'Bahasa Indonesia', 'IND', 2, '2026-04-30 10:25:15', '2026-04-30 10:25:15'),
|
||||||
|
(3, 'Bahasa Inggris', 'ENG', 2, '2026-04-30 10:25:15', '2026-04-30 10:25:15'),
|
||||||
|
(4, 'Desain Grafis', 'DG', 3, '2026-04-30 10:25:15', '2026-04-30 10:25:15');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `migrations`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `migrations` (
|
||||||
|
`id` int UNSIGNED NOT NULL,
|
||||||
|
`migration` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`batch` int NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `migrations`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `migrations` (`id`, `migration`, `batch`) VALUES
|
||||||
|
(1, '0001_01_01_000000_create_users_table', 1),
|
||||||
|
(2, '0001_01_01_000001_create_cache_table', 1),
|
||||||
|
(3, '0001_01_01_000002_create_jobs_table', 1),
|
||||||
|
(4, '2025_08_19_084855_create_gurus_table', 1),
|
||||||
|
(5, '2025_08_20_012827_create_siswa_table', 1),
|
||||||
|
(6, '2026_03_29_121631_create_mata_pelajarans_table', 1),
|
||||||
|
(7, '2026_03_29_131627_create_kelas_table', 1),
|
||||||
|
(8, '2026_03_29_132044_create_jadwals_table', 1),
|
||||||
|
(9, '2026_03_30_010154_add_role_to_users_table', 2),
|
||||||
|
(10, '2026_03_31_022301_create_nilai_table', 3),
|
||||||
|
(11, '2026_04_01_022443_add_photo_to_users_table', 4),
|
||||||
|
(12, '2026_04_13_142509_add_status_to_gurus_table', 5),
|
||||||
|
(13, '2026_04_13_145014_add_status_to_siswas_table', 6),
|
||||||
|
(14, '2026_04_13_154302_add_field_to_siswa_table', 7),
|
||||||
|
(15, '2026_04_13_155232_add_jenis_kelamin_to_siswa_table', 8),
|
||||||
|
(16, '2026_04_14_130307_add_is_default_password_to_users', 9),
|
||||||
|
(17, '2026_04_14_153904_add_otp_to_users_table', 10),
|
||||||
|
(19, '2026_04_17_084158_create_tugas_table', 1),
|
||||||
|
(21, '2026_04_16_041005_add_telepon_to_users_table', 10),
|
||||||
|
(22, '2026_04_17_084159_create_pengumpulan_tugas_table', 10),
|
||||||
|
(23, '2026_04_17_105854_add_mapel_to_gurus_table', 11),
|
||||||
|
(24, '2026_04_20_024223_add_file_to_tugas_table', 11),
|
||||||
|
(25, '2026_04_20_044829_update_deadline_to_datetime_in_tugas', 12),
|
||||||
|
(26, '2026_04_20_115943_add_komentar_to_pengumpulan_tugas', 13),
|
||||||
|
(27, '2026_04_20_123724_create_absensis_table', 14),
|
||||||
|
(28, '2026_04_20_123747_create_absensi_details_table', 14);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `nilai`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `nilai` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`mapel_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`nilai` int NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `nilai`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `nilai` (`id`, `siswa_id`, `mapel_id`, `nilai`, `created_at`, `updated_at`) VALUES
|
||||||
|
(14, 15, 4, 80, '2026-03-31 23:45:22', '2026-03-31 23:45:22'),
|
||||||
|
(15, 15, 5, 40, '2026-03-31 23:46:27', '2026-04-21 11:49:48'),
|
||||||
|
(16, 15, 2, 90, '2026-04-15 21:02:32', '2026-04-15 21:02:32'),
|
||||||
|
(17, 16, 2, 80, '2026-04-15 21:02:32', '2026-04-15 21:02:32'),
|
||||||
|
(18, 19, 2, 70, '2026-04-15 21:02:32', '2026-04-15 21:02:32'),
|
||||||
|
(19, 22, 2, 50, '2026-04-15 21:02:32', '2026-04-15 21:02:32'),
|
||||||
|
(20, 16, 5, 70, '2026-04-21 11:49:48', '2026-04-21 11:49:48'),
|
||||||
|
(21, 19, 5, 90, '2026-04-21 11:49:48', '2026-04-21 11:49:48'),
|
||||||
|
(22, 22, 5, 80, '2026-04-21 11:49:48', '2026-04-21 11:49:48'),
|
||||||
|
(23, 23, 5, 30, '2026-04-21 11:49:48', '2026-04-21 11:49:48');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `password_reset_tokens`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `password_reset_tokens` (
|
||||||
|
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`token` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `pengumpulan_tugas`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `pengumpulan_tugas` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`tugas_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`file` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`nilai` int DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`komentar` text COLLATE utf8mb4_unicode_ci
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `sessions`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `sessions` (
|
||||||
|
`id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`user_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`ip_address` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`user_agent` text COLLATE utf8mb4_unicode_ci,
|
||||||
|
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`last_activity` int NOT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `sessions`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `sessions` (`id`, `user_id`, `ip_address`, `user_agent`, `payload`, `last_activity`) VALUES
|
||||||
|
('8UFetMqwkKV2CYFII4GrKKnlo9ZrMrg01oUx17Zd', 44, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoiajdTc1BwbkdvRkxEQ3VWRG1UaW82eERMaXN4dFVYN2d2cU51YkRzaiI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6Mzk6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9ndXJ1L3VqaWFuL2NyZWF0ZSI7fXM6NTA6ImxvZ2luX3dlYl81OWJhMzZhZGRjMmIyZjk0MDE1ODBmMDE0YzdmNThlYTRlMzA5ODlkIjtpOjQ0O30=', 1777544964),
|
||||||
|
('qR6okGJIUFM6wIISXVaUCFxImbjsZ1LYQixVgnCO', 40, '127.0.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36 Edg/147.0.0.0', 'YTo0OntzOjY6Il90b2tlbiI7czo0MDoicmFKclU0TVo4d1dLY3BrOFA4bXNQQlRSN1hGRG16QWlSRXJFWnpGZCI7czo2OiJfZmxhc2giO2E6Mjp7czozOiJvbGQiO2E6MDp7fXM6MzoibmV3IjthOjA6e319czo5OiJfcHJldmlvdXMiO2E6MTp7czozOiJ1cmwiO3M6NDQ6Imh0dHA6Ly8xMjcuMC4wLjE6ODAwMC9zaXN3YS91amlhbi8xL2tlcmpha2FuIjt9czo1MDoibG9naW5fd2ViXzU5YmEzNmFkZGMyYjJmOTQwMTU4MGYwMTRjN2Y1OGVhNGUzMDk4OWQiO2k6NDA7fQ==', 1777545038);
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `siswa`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `siswa` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`nama` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`jenis_kelamin` enum('L','P') COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`nama_ortu` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`nis` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`alamat` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`telepon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`status` enum('aktif','nonaktif') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'aktif',
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`kelas_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`alasan_nonaktif` text COLLATE utf8mb4_unicode_ci
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `siswa`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `siswa` (`id`, `nama`, `jenis_kelamin`, `nama_ortu`, `nis`, `alamat`, `telepon`, `status`, `created_at`, `updated_at`, `kelas_id`, `alasan_nonaktif`) VALUES
|
||||||
|
(14, 'sipol', 'L', 'sipoladon', '212321321', 'Jember barat timur', '09897865464', 'nonaktif', '2026-03-31 21:13:11', '2026-04-15 21:00:43', 9, NULL),
|
||||||
|
(15, 'Fuad', 'L', '', '1213213', 'Jember barat timur', '09897865464', 'nonaktif', '2026-03-31 21:23:26', '2026-04-15 21:00:43', 6, NULL),
|
||||||
|
(16, 'ilham', 'L', '', '3243234', 'dsfdfs32', '234234124124124', 'nonaktif', '2026-04-13 07:20:20', '2026-04-15 21:00:43', 6, NULL),
|
||||||
|
(17, 'bayu akbar', 'L', '', '35423412', 'Bondowoso', '08976544534', 'nonaktif', '2026-04-13 08:32:46', '2026-04-15 21:00:43', 8, NULL),
|
||||||
|
(18, 'Gavin', 'L', 'Gavinaldo', '41412312', 'Bondowoso', '08931231252', 'nonaktif', '2026-04-13 08:53:17', '2026-04-15 21:00:43', 9, NULL),
|
||||||
|
(19, 'Irul', 'L', 'khoirul', '412421', 'Bondowoso', '08978675453', 'nonaktif', '2026-04-14 06:31:15', '2026-04-15 21:00:43', 6, NULL),
|
||||||
|
(20, 'Fauzi', 'L', 'Sukri', '758567', 'Bondowoso', '08975643221', 'nonaktif', '2026-04-14 06:51:57', '2026-04-15 21:00:43', 8, NULL),
|
||||||
|
(21, 'hardi', 'P', 'memo', '121312', 'Bondowoso', '0893723132', 'nonaktif', '2026-04-14 06:57:42', '2026-04-15 21:00:43', 8, NULL),
|
||||||
|
(22, 'Maulana', 'L', 'Gavinaldo', '21313', 'Surabaya', '08954224122', 'aktif', '2026-04-14 07:14:06', '2026-04-28 08:01:10', 6, NULL),
|
||||||
|
(23, 'Siswa Rengga', 'L', 'Andik', '345333242', 'Bondowoso', '08977654321233', 'aktif', '2026-04-19 21:55:36', '2026-04-19 21:55:36', 6, NULL),
|
||||||
|
(24, 'Bayu anggara', 'P', 'sipoladon', '3242341', 'Bondowoso', '08978546377332', 'aktif', '2026-04-20 04:33:22', '2026-04-20 04:33:22', 7, NULL),
|
||||||
|
(35, 'rayenn', 'L', 'Sudik', '35465686', 'surabaya', '6281252519535', 'nonaktif', '2026-04-23 22:22:03', '2026-04-28 08:30:41', 6, 'karena sudah di do');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `soals`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `soals` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`ujian_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`pertanyaan` text,
|
||||||
|
`a` text,
|
||||||
|
`b` text,
|
||||||
|
`c` text,
|
||||||
|
`d` text,
|
||||||
|
`jawaban_benar` enum('a','b','c','d') DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `soals`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `soals` (`id`, `ujian_id`, `pertanyaan`, `a`, `b`, `c`, `d`, `jawaban_benar`, `created_at`, `updated_at`) VALUES
|
||||||
|
(1, 1, 'rumah rengga dimana', 'kembang', 'sukowiryo', 'duko', 'nangkaan', 'a', '2026-04-30 09:06:48', '2026-04-30 09:06:48');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `tugas`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `tugas` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`guru_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`kelas_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`mapel_id` bigint UNSIGNED NOT NULL,
|
||||||
|
`judul` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`deskripsi` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`deadline` datetime NOT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`file` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `tugas`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `tugas` (`id`, `guru_id`, `kelas_id`, `mapel_id`, `judul`, `deskripsi`, `deadline`, `created_at`, `updated_at`, `file`) VALUES
|
||||||
|
(18, 39, 6, 7, 'minggu 10', 'adasdasdas', '2026-04-22 10:05:00', '2026-04-22 03:05:05', '2026-04-22 03:05:05', 'tugas_file/SKQvPt7XGSUxDILwzB1uPfhMYmHlTWFiVkC2tKpR.pdf'),
|
||||||
|
(19, 39, 7, 7, 'minggu 9', 'dwqdasd', '2026-04-22 10:06:00', '2026-04-22 03:06:13', '2026-04-22 03:06:13', 'tugas_file/KpYeWe5f60Awf51go9lw8DvFh3mC45Dlx8v0CkMm.pdf');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `ujians`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `ujians` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`judul` varchar(255) DEFAULT NULL,
|
||||||
|
`durasi` int DEFAULT NULL,
|
||||||
|
`mulai` datetime DEFAULT NULL,
|
||||||
|
`selesai` datetime DEFAULT NULL,
|
||||||
|
`guru_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `ujians`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `ujians` (`id`, `judul`, `durasi`, `mulai`, `selesai`, `guru_id`, `created_at`, `updated_at`) VALUES
|
||||||
|
(1, 'UTS Desain Grafis', 45, '2026-04-30 16:00:00', '2026-04-30 16:45:00', 39, '2026-04-30 09:06:48', '2026-04-30 09:06:48');
|
||||||
|
|
||||||
|
-- --------------------------------------------------------
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE `users` (
|
||||||
|
`id` bigint UNSIGNED NOT NULL,
|
||||||
|
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
`role` enum('admin','guru','siswa') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'siswa',
|
||||||
|
`guru_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`siswa_id` bigint UNSIGNED DEFAULT NULL,
|
||||||
|
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`created_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`updated_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`mapel_id` bigint DEFAULT NULL,
|
||||||
|
`photo` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`is_default_password` tinyint(1) NOT NULL DEFAULT '1',
|
||||||
|
`otp` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
`otp_expired_at` timestamp NULL DEFAULT NULL,
|
||||||
|
`telepon` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `users`
|
||||||
|
--
|
||||||
|
|
||||||
|
INSERT INTO `users` (`id`, `name`, `email`, `password`, `role`, `guru_id`, `siswa_id`, `remember_token`, `created_at`, `updated_at`, `mapel_id`, `photo`, `is_default_password`, `otp`, `otp_expired_at`, `telepon`) VALUES
|
||||||
|
(1, 'Admin', 'admin@gmail.com', '$2y$12$nYOJKfRSziDIvXdFLMSej.RrniIDukDG6Z6tNt6zmZ3pSGOmFPsn.', 'admin', 2, NULL, NULL, '2026-03-29 20:52:52', '2026-04-15 20:03:42', NULL, '1775011418.jpg', 0, NULL, NULL, NULL),
|
||||||
|
(4, 'Siswa 1', 'siswa@gmail.com', '$2y$12$sDRQgwkz34hk3ru6AitfBegN9mS30Z9BHZMw85f8QRxrQZcMgGeQ.', 'siswa', NULL, NULL, NULL, '2026-03-29 20:53:52', '2026-03-29 20:53:52', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(5, 'Ryan MAulana', 'guru1@gmail.com', '$2y$12$mLnhDhHvTnVCEMhFtPxCkeBFEfggfkCifZ6yrRt19QV06uF.nH2P6', 'guru', NULL, NULL, NULL, '2026-03-30 20:55:29', '2026-03-30 20:55:29', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(6, 'zakaria', 'zaka@gmail.com', '$2y$12$GCbsvTxo5x1s3J8Xm4Lnxe0AiLQCPpYgcgR5ZP4/xsjdROf/Z1pFe', 'guru', 3, NULL, NULL, '2026-03-30 21:17:29', '2026-03-30 21:17:29', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(7, 'adis bauk', 'adis12@gmail.com', '$2y$12$f2ezxB.v.z25y/Cz0JyfEun7Mh0JU9z/LXwF5pYy9ry.q.jfqviY.', 'guru', NULL, NULL, NULL, '2026-03-30 21:30:30', '2026-03-30 21:30:30', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(8, 'asca2421', 'erinefarah@gmail.com', '$2y$12$3kgiNhZ9cEOsomVLjo95guzCzo78aXWRoB.TYdwIzzNXQOZH39kCC', 'guru', NULL, NULL, NULL, '2026-03-30 21:33:42', '2026-03-30 21:33:42', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(9, 'Reyfandi', 'kelompok1@gmail.com', '$2y$12$4WkNPHZ7wThq9KVdY7FZLuCvDR.p1cqUsZdIyzxPQ2GlTxg/u5OFS', 'guru', 10, NULL, NULL, '2026-03-30 21:40:12', '2026-03-30 21:40:12', 2, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(16, 'sipol', 'sipol@gmail.com', '$2y$12$P19iPvgcI3nmTQjUItQOvu7krp9tt.8PIsbPzrv6A8u9Z9w0todQC', 'siswa', NULL, 14, NULL, '2026-03-31 21:13:11', '2026-03-31 21:13:11', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(17, 'Fuad', 'fuad@gmail.com', '$2y$12$vaMwtmvqbSK/rZ5XdA6K7.VW5WiCudpHfro0.OjZYFuBiMJ2DgDJi', 'siswa', NULL, 15, NULL, '2026-03-31 21:23:26', '2026-03-31 21:23:26', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(18, 'ilham', 'ilham@gmail.com', '$2y$12$MUBrQ7UGm1pP5Rb8mUVtMOjHaqKeeEh3etLcmwD.Krf4WPJQwwNz2', 'siswa', NULL, 16, NULL, '2026-04-13 07:20:21', '2026-04-13 07:20:21', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(19, 'bayu akbar', 'bayuakbar@gmail.com', '$2y$12$gq9mN9dlZdDLKwq1CgrpUO03hQYcV.UrwttALNo0sDb7nrvPP7P1K', 'siswa', NULL, 17, NULL, '2026-04-13 08:32:47', '2026-04-13 08:32:47', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(20, 'Gavin', 'gavin@gmail.com', '$2y$12$sNUy3C7bXC121Z8b4CP3HO91LiCNmQydgA.Bm4rt7ChUNw86UHdgG', 'siswa', NULL, 18, NULL, '2026-04-13 08:53:17', '2026-04-13 08:53:17', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(21, 'Irul', 'irul@gmail.com', '$2y$12$tWo5A.QaV4ROnck1WJ0qSucrAEIxKc1JYuxyGlYf9XZ7VjNvPh8fa', 'siswa', NULL, 19, NULL, '2026-04-14 06:31:15', '2026-04-14 06:41:38', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(22, 'Fauzi', 'fauzi@gmail.com', '$2y$12$LEnvbaAeEoMaK19M7GZCHeoaxgdLYkay58dtVI3Q8dm8rAHfNvSSK', 'siswa', NULL, 20, NULL, '2026-04-14 06:51:57', '2026-04-14 06:51:57', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(23, 'hardi', 'hardi@gmail.com', '$2y$12$RVSNOsL7WFRojnhfU6MMFOMD4tkAiv4YWG1pzZS0gFu5PFaHzC7v.', 'siswa', NULL, 21, NULL, '2026-04-14 06:57:42', '2026-04-14 07:03:41', NULL, NULL, 1, NULL, NULL, NULL),
|
||||||
|
(24, 'Maulana', 'maulana@gmail.com', '$2y$12$GsuWYF.uc0vdCITV8YuLDegOI58BEvJZ8XbIHN0ELi7GBQMjAqr5a', 'siswa', NULL, 22, NULL, '2026-04-14 07:14:06', '2026-04-14 07:14:37', NULL, NULL, 0, NULL, NULL, NULL),
|
||||||
|
(39, 'zakaria', 'mlnryan05@gmail.com', '$2y$12$yZ5p1XhIGhjdUxXNvyML5uVHNDfzMd4d95oI0T3iEvXZZ2f7RYaWq', 'guru', 36, NULL, NULL, '2026-04-19 21:18:08', '2026-04-19 21:18:08', 2, NULL, 1, NULL, NULL, '089785463773'),
|
||||||
|
(40, 'Siswa Rengga', 'renggalaviosa@gmail.com', '$2y$12$XI.nsw906.wBE8hvepLLr.oVzgpH/teA5Qlqp7eDQ1YiKNyQRKbLG', 'siswa', NULL, 23, NULL, '2026-04-19 21:55:37', '2026-04-30 09:15:59', NULL, NULL, 0, NULL, NULL, NULL),
|
||||||
|
(41, 'Bayu anggara', 'bayu@gmail.com', '$2y$12$TuNb6v/RBJF6TaIpFm0dFu9PTkrQrMvMcWq2QFoIck..uwvDsnLZC', 'siswa', NULL, 24, NULL, '2026-04-20 04:33:22', '2026-04-20 04:33:51', NULL, NULL, 0, NULL, NULL, NULL),
|
||||||
|
(42, 'Umam', 'umam@gmail.com', '$2y$12$psH1qXXs6kgk1jNJJ7Wpt.w7fPxm9wuSFUxWAT5m5GlO8UeIRHOta', 'guru', 37, NULL, NULL, '2026-04-21 11:52:56', '2026-04-21 11:53:39', 3, NULL, 0, NULL, NULL, '0879635231'),
|
||||||
|
(44, 'Arengga', 'renggalaviosa78@gmail.com', '$2y$12$0XiSSR2G/pmqIxMY7vNJPei0.w.3n/JgD0hnJ45Rikwl.0vwsTfpW', 'guru', 39, NULL, NULL, '2026-04-22 02:17:15', '2026-04-30 10:29:18', 7, NULL, 0, NULL, NULL, '6289504732922'),
|
||||||
|
(55, 'rayenn', 'nunieiffel@gmail.com', '$2y$12$gDoPf94nRLUr9gXKefPW4ereEctEZwJb3JzhUx6yJB5nEmnzGwh4O', 'siswa', NULL, 35, NULL, '2026-04-23 22:22:03', '2026-04-23 22:22:03', NULL, NULL, 1, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for dumped tables
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `absensi`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `guru_id` (`guru_id`),
|
||||||
|
ADD KEY `kelas_id` (`kelas_id`),
|
||||||
|
ADD KEY `mapel_id` (`mapel_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `absensi_detail`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi_detail`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `unique_absensi` (`absensi_id`,`siswa_id`),
|
||||||
|
ADD KEY `siswa_id` (`siswa_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `cache`
|
||||||
|
--
|
||||||
|
ALTER TABLE `cache`
|
||||||
|
ADD PRIMARY KEY (`key`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `cache_locks`
|
||||||
|
--
|
||||||
|
ALTER TABLE `cache_locks`
|
||||||
|
ADD PRIMARY KEY (`key`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `failed_jobs`
|
||||||
|
--
|
||||||
|
ALTER TABLE `failed_jobs`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `failed_jobs_uuid_unique` (`uuid`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `gurus`
|
||||||
|
--
|
||||||
|
ALTER TABLE `gurus`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `gurus_nip_unique` (`nip`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `hasils`
|
||||||
|
--
|
||||||
|
ALTER TABLE `hasils`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `ujian_id` (`ujian_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `jadwals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jadwals`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `jadwals_kelas_id_foreign` (`kelas_id`),
|
||||||
|
ADD KEY `jadwals_mata_pelajaran_id_foreign` (`mata_pelajaran_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `jawabans`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawabans`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `siswa_id` (`siswa_id`),
|
||||||
|
ADD KEY `soal_id` (`soal_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `jawaban_siswas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawaban_siswas`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `soal_id` (`soal_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `jobs`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jobs`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `jobs_queue_index` (`queue`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `job_batches`
|
||||||
|
--
|
||||||
|
ALTER TABLE `job_batches`
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `kelas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `kelas`
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `mata_pelajarans`
|
||||||
|
--
|
||||||
|
ALTER TABLE `mata_pelajarans`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `kode_mapel` (`kode_mapel`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `migrations`
|
||||||
|
--
|
||||||
|
ALTER TABLE `migrations`
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `nilai`
|
||||||
|
--
|
||||||
|
ALTER TABLE `nilai`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `nilai_siswa_id_foreign` (`siswa_id`),
|
||||||
|
ADD KEY `nilai_mapel_id_foreign` (`mapel_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `password_reset_tokens`
|
||||||
|
--
|
||||||
|
ALTER TABLE `password_reset_tokens`
|
||||||
|
ADD PRIMARY KEY (`email`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `pengumpulan_tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `pengumpulan_tugas`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `pengumpulan_tugas_tugas_id_foreign` (`tugas_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `sessions`
|
||||||
|
--
|
||||||
|
ALTER TABLE `sessions`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `sessions_user_id_index` (`user_id`),
|
||||||
|
ADD KEY `sessions_last_activity_index` (`last_activity`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `siswa`
|
||||||
|
--
|
||||||
|
ALTER TABLE `siswa`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `siswa_nis_unique` (`nis`),
|
||||||
|
ADD KEY `fk_kelas` (`kelas_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `soals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `soals`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `ujian_id` (`ujian_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `tugas`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD KEY `tugas_guru_id_foreign` (`guru_id`),
|
||||||
|
ADD KEY `tugas_kelas_id_foreign` (`kelas_id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `ujians`
|
||||||
|
--
|
||||||
|
ALTER TABLE `ujians`
|
||||||
|
ADD PRIMARY KEY (`id`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Indexes for table `users`
|
||||||
|
--
|
||||||
|
ALTER TABLE `users`
|
||||||
|
ADD PRIMARY KEY (`id`),
|
||||||
|
ADD UNIQUE KEY `users_email_unique` (`email`);
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for dumped tables
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `absensi`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `absensi_detail`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi_detail`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `failed_jobs`
|
||||||
|
--
|
||||||
|
ALTER TABLE `failed_jobs`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `gurus`
|
||||||
|
--
|
||||||
|
ALTER TABLE `gurus`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=40;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `hasils`
|
||||||
|
--
|
||||||
|
ALTER TABLE `hasils`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `jadwals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jadwals`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=21;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `jawabans`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawabans`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `jawaban_siswas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawaban_siswas`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `jobs`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jobs`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `kelas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `kelas`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `mata_pelajarans`
|
||||||
|
--
|
||||||
|
ALTER TABLE `mata_pelajarans`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `migrations`
|
||||||
|
--
|
||||||
|
ALTER TABLE `migrations`
|
||||||
|
MODIFY `id` int UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=29;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `nilai`
|
||||||
|
--
|
||||||
|
ALTER TABLE `nilai`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=24;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `pengumpulan_tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `pengumpulan_tugas`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=9;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `siswa`
|
||||||
|
--
|
||||||
|
ALTER TABLE `siswa`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=36;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `soals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `soals`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `tugas`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=20;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `ujians`
|
||||||
|
--
|
||||||
|
ALTER TABLE `ujians`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- AUTO_INCREMENT for table `users`
|
||||||
|
--
|
||||||
|
ALTER TABLE `users`
|
||||||
|
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=56;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for dumped tables
|
||||||
|
--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `absensi`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi`
|
||||||
|
ADD CONSTRAINT `absensi_ibfk_1` FOREIGN KEY (`guru_id`) REFERENCES `gurus` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `absensi_ibfk_2` FOREIGN KEY (`kelas_id`) REFERENCES `kelas` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `absensi_ibfk_3` FOREIGN KEY (`mapel_id`) REFERENCES `mata_pelajarans` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `absensi_detail`
|
||||||
|
--
|
||||||
|
ALTER TABLE `absensi_detail`
|
||||||
|
ADD CONSTRAINT `absensi_detail_ibfk_1` FOREIGN KEY (`absensi_id`) REFERENCES `absensi` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `absensi_detail_ibfk_2` FOREIGN KEY (`siswa_id`) REFERENCES `siswa` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `hasils`
|
||||||
|
--
|
||||||
|
ALTER TABLE `hasils`
|
||||||
|
ADD CONSTRAINT `hasils_ibfk_1` FOREIGN KEY (`ujian_id`) REFERENCES `ujians` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `jadwals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jadwals`
|
||||||
|
ADD CONSTRAINT `jadwals_kelas_id_foreign` FOREIGN KEY (`kelas_id`) REFERENCES `kelas` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `jadwals_mata_pelajaran_id_foreign` FOREIGN KEY (`mata_pelajaran_id`) REFERENCES `mata_pelajarans` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `jawabans`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawabans`
|
||||||
|
ADD CONSTRAINT `jawabans_ibfk_1` FOREIGN KEY (`siswa_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `jawabans_ibfk_2` FOREIGN KEY (`soal_id`) REFERENCES `soals` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `jawaban_siswas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `jawaban_siswas`
|
||||||
|
ADD CONSTRAINT `jawaban_siswas_ibfk_1` FOREIGN KEY (`soal_id`) REFERENCES `soals` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `nilai`
|
||||||
|
--
|
||||||
|
ALTER TABLE `nilai`
|
||||||
|
ADD CONSTRAINT `nilai_mapel_id_foreign` FOREIGN KEY (`mapel_id`) REFERENCES `mata_pelajarans` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `nilai_siswa_id_foreign` FOREIGN KEY (`siswa_id`) REFERENCES `siswa` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `pengumpulan_tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `pengumpulan_tugas`
|
||||||
|
ADD CONSTRAINT `pengumpulan_tugas_tugas_id_foreign` FOREIGN KEY (`tugas_id`) REFERENCES `tugas` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `siswa`
|
||||||
|
--
|
||||||
|
ALTER TABLE `siswa`
|
||||||
|
ADD CONSTRAINT `fk_kelas` FOREIGN KEY (`kelas_id`) REFERENCES `kelas` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `soals`
|
||||||
|
--
|
||||||
|
ALTER TABLE `soals`
|
||||||
|
ADD CONSTRAINT `soals_ibfk_1` FOREIGN KEY (`ujian_id`) REFERENCES `ujians` (`id`) ON DELETE CASCADE;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Constraints for table `tugas`
|
||||||
|
--
|
||||||
|
ALTER TABLE `tugas`
|
||||||
|
ADD CONSTRAINT `tugas_guru_id_foreign` FOREIGN KEY (`guru_id`) REFERENCES `gurus` (`id`) ON DELETE CASCADE,
|
||||||
|
ADD CONSTRAINT `tugas_kelas_id_foreign` FOREIGN KEY (`kelas_id`) REFERENCES `kelas` (`id`) ON DELETE CASCADE;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||||
|
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||||
|
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||||
Loading…
Reference in New Issue