Compare commits
No commits in common. "main" and "android" have entirely different histories.
|
@ -1,18 +0,0 @@
|
||||||
root = true
|
|
||||||
|
|
||||||
[*]
|
|
||||||
charset = utf-8
|
|
||||||
end_of_line = lf
|
|
||||||
indent_size = 4
|
|
||||||
indent_style = space
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
[*.md]
|
|
||||||
trim_trailing_whitespace = false
|
|
||||||
|
|
||||||
[*.{yml,yaml}]
|
|
||||||
indent_size = 2
|
|
||||||
|
|
||||||
[docker-compose.yml]
|
|
||||||
indent_size = 4
|
|
|
@ -1,11 +0,0 @@
|
||||||
* text=auto eol=lf
|
|
||||||
|
|
||||||
*.blade.php diff=html
|
|
||||||
*.css diff=css
|
|
||||||
*.html diff=html
|
|
||||||
*.md diff=markdown
|
|
||||||
*.php diff=php
|
|
||||||
|
|
||||||
/.github export-ignore
|
|
||||||
CHANGELOG.md export-ignore
|
|
||||||
.styleci.yml export-ignore
|
|
|
@ -1,23 +1,75 @@
|
||||||
/.phpunit.cache
|
### Flutter/Dart ###
|
||||||
/node_modules
|
# Core Flutter/Dart files to ignore
|
||||||
/public/build
|
.dart_tool/
|
||||||
/public/hot
|
.flutter-plugins
|
||||||
/public/storage
|
.flutter-plugins-dependencies
|
||||||
/storage/*.key
|
.pub-cache/
|
||||||
/storage/pail
|
.pub/
|
||||||
/vendor
|
/build/
|
||||||
|
*.dart.js
|
||||||
|
*.js.map
|
||||||
|
*.info.json
|
||||||
|
**/.last_build_id
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
**/doc/api/
|
||||||
|
*.symbols
|
||||||
|
*.map.json
|
||||||
|
|
||||||
|
### Platform Specific ###
|
||||||
|
# Android
|
||||||
|
/android/
|
||||||
|
/local.properties
|
||||||
|
**/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# iOS
|
||||||
|
/ios/
|
||||||
|
**/Podfile.lock
|
||||||
|
**/Pods/
|
||||||
|
|
||||||
|
# Web
|
||||||
|
/web/
|
||||||
|
|
||||||
|
# Desktop
|
||||||
|
/windows/
|
||||||
|
/linux/
|
||||||
|
/macos/
|
||||||
|
|
||||||
|
### Build Directories ###
|
||||||
|
**/debug/
|
||||||
|
**/profile/
|
||||||
|
**/release/
|
||||||
|
**/test/coverage/
|
||||||
|
|
||||||
|
### IDE ###
|
||||||
|
# IntelliJ/Android Studio
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# VS Code (uncomment if needed)
|
||||||
|
#.vscode/
|
||||||
|
|
||||||
|
### Environment ###
|
||||||
.env
|
.env
|
||||||
.env.backup
|
.env*
|
||||||
.env.production
|
.env.local
|
||||||
.phpactor.json
|
.env.*.local
|
||||||
.phpunit.result.cache
|
|
||||||
Homestead.json
|
### System Files ###
|
||||||
Homestead.yaml
|
.DS_Store
|
||||||
npm-debug.log
|
Thumbs.db
|
||||||
yarn-error.log
|
*.swp
|
||||||
/auth.json
|
*.log
|
||||||
/.fleet
|
|
||||||
/.idea
|
### Version Control ###
|
||||||
/.nova
|
.svn/
|
||||||
/.vscode
|
.history/
|
||||||
/.zed
|
migrate_working_dir/
|
||||||
|
|
||||||
|
### Miscellaneous ###
|
||||||
|
*.class
|
||||||
|
*.pyc
|
||||||
|
.atom/
|
||||||
|
.buildlog/
|
|
@ -0,0 +1,30 @@
|
||||||
|
# This file tracks properties of this Flutter project.
|
||||||
|
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||||
|
#
|
||||||
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
|
version:
|
||||||
|
revision: "c23637390482d4cf9598c3ce3f2be31aa7332daf"
|
||||||
|
channel: "stable"
|
||||||
|
|
||||||
|
project_type: app
|
||||||
|
|
||||||
|
# Tracks metadata for the flutter migrate command
|
||||||
|
migration:
|
||||||
|
platforms:
|
||||||
|
- platform: root
|
||||||
|
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
|
||||||
|
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
|
||||||
|
- platform: android
|
||||||
|
create_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
|
||||||
|
base_revision: c23637390482d4cf9598c3ce3f2be31aa7332daf
|
||||||
|
|
||||||
|
# User provided section
|
||||||
|
|
||||||
|
# List of Local paths (relative to this file) that should be
|
||||||
|
# ignored by the migrate tool.
|
||||||
|
#
|
||||||
|
# Files that are not part of the templates will be ignored by default.
|
||||||
|
unmanaged_files:
|
||||||
|
- 'lib/main.dart'
|
||||||
|
- 'ios/Runner.xcodeproj/project.pbxproj'
|
|
@ -0,0 +1,148 @@
|
||||||
|
# Ringkasan Implementasi Quiz Auto-Stop
|
||||||
|
|
||||||
|
## ✅ Implementasi Selesai
|
||||||
|
|
||||||
|
Implementasi fitur quiz auto-stop ketika soal habis di level tertentu telah berhasil diselesaikan. Berikut adalah ringkasan lengkap:
|
||||||
|
|
||||||
|
## 📁 File yang Dimodifikasi
|
||||||
|
|
||||||
|
### 1. `lib/views/siswa/quiz/controllers/quiz_question_controller.dart`
|
||||||
|
|
||||||
|
**Perubahan:**
|
||||||
|
|
||||||
|
- ✅ Menambahkan penanganan khusus untuk response 404 dengan pesan soal habis
|
||||||
|
- ✅ Menambahkan penanganan untuk response 204 No Content
|
||||||
|
- ✅ Menambahkan pengecekan pesan dalam response 200
|
||||||
|
- ✅ Menambahkan method `handleQuestionsExhausted()`
|
||||||
|
- ✅ Menambahkan method `autoFinishQuiz()`
|
||||||
|
|
||||||
|
### 2. `lib/views/siswa/quiz/controllers/quiz_attempt_controller.dart`
|
||||||
|
|
||||||
|
**Perubahan:**
|
||||||
|
|
||||||
|
- ✅ Menambahkan method `stopQuizTimer()` untuk menghentikan timer quiz
|
||||||
|
|
||||||
|
## 🔧 Fitur yang Diimplementasikan
|
||||||
|
|
||||||
|
### 1. Deteksi Soal Habis
|
||||||
|
|
||||||
|
Sistem dapat mendeteksi soal habis melalui:
|
||||||
|
|
||||||
|
- **Status Code 404** dengan pesan "Tidak ada soal lagi di level ini"
|
||||||
|
- **Status Code 204** (No Content)
|
||||||
|
- **Status Code 200** dengan pesan soal habis dalam response body
|
||||||
|
|
||||||
|
### 2. Penanganan Otomatis
|
||||||
|
|
||||||
|
Ketika soal habis terdeteksi:
|
||||||
|
|
||||||
|
1. **Timer Berhenti**: Timer quiz dihentikan secara otomatis
|
||||||
|
2. **Pesan User**: Dialog "Soal sudah habis di level ini, quiz selesai" ditampilkan
|
||||||
|
3. **Auto Finish**: Quiz diselesaikan otomatis dengan mengirim jawaban kosong untuk soal yang belum dijawab
|
||||||
|
4. **Redirect**: User diarahkan ke halaman hasil quiz
|
||||||
|
|
||||||
|
### 3. Error Handling
|
||||||
|
|
||||||
|
- **Network Error**: Menampilkan dialog error koneksi dengan opsi kembali ke dashboard
|
||||||
|
- **Auto-Finish Failure**: Menampilkan dialog error dengan opsi kembali ke dashboard
|
||||||
|
- **Fallback**: Langsung redirect ke halaman quiz selesai jika terjadi error
|
||||||
|
|
||||||
|
## 🎯 Alur Kerja Lengkap
|
||||||
|
|
||||||
|
```
|
||||||
|
1. User mengerjakan quiz
|
||||||
|
↓
|
||||||
|
2. Sistem memanggil API next-question
|
||||||
|
↓
|
||||||
|
3. Backend mengembalikan 404/204/200 dengan pesan soal habis
|
||||||
|
↓
|
||||||
|
4. Frontend mendeteksi soal habis
|
||||||
|
↓
|
||||||
|
5. Timer quiz dihentikan
|
||||||
|
↓
|
||||||
|
6. Dialog pesan ditampilkan ke user
|
||||||
|
↓
|
||||||
|
7. Auto-finish quiz dipanggil
|
||||||
|
↓
|
||||||
|
8. Jawaban kosong dikirim untuk soal yang belum dijawab
|
||||||
|
↓
|
||||||
|
9. Endpoint auto-finish dipanggil
|
||||||
|
↓
|
||||||
|
10. User diarahkan ke halaman hasil quiz
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📝 Pesan yang Didukung
|
||||||
|
|
||||||
|
Sistem mendeteksi soal habis berdasarkan pesan berikut:
|
||||||
|
|
||||||
|
- "Tidak ada soal lagi di level ini"
|
||||||
|
- "Soal habis"
|
||||||
|
- "Questions exhausted"
|
||||||
|
- "No more questions"
|
||||||
|
|
||||||
|
## 🔍 Logging
|
||||||
|
|
||||||
|
Sistem menambahkan logging detail untuk debugging:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
log("404 - Soal habis di level ini detected");
|
||||||
|
log("Confirmed: Questions exhausted at this level");
|
||||||
|
log("Quiz timer stopped");
|
||||||
|
log("Auto finishing quiz for attempt ID: $attemptId");
|
||||||
|
log("Auto finish success: $json");
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✅ Test Cases yang Harus Diuji
|
||||||
|
|
||||||
|
1. **Response 404 dengan pesan soal habis**
|
||||||
|
|
||||||
|
- Backend: 404 + "Tidak ada soal lagi di level ini"
|
||||||
|
- Expected: Timer berhenti, dialog muncul, auto-finish
|
||||||
|
|
||||||
|
2. **Response 204 No Content**
|
||||||
|
|
||||||
|
- Backend: 204
|
||||||
|
- Expected: Timer berhenti, auto-finish
|
||||||
|
|
||||||
|
3. **Response 200 dengan pesan soal habis**
|
||||||
|
|
||||||
|
- Backend: 200 + message soal habis
|
||||||
|
- Expected: Timer berhenti, auto-finish
|
||||||
|
|
||||||
|
4. **Response 404 tanpa pesan soal habis**
|
||||||
|
|
||||||
|
- Backend: 404 tanpa pesan khusus
|
||||||
|
- Expected: Error dialog umum, tidak auto-finish
|
||||||
|
|
||||||
|
5. **Network error saat auto-finish**
|
||||||
|
- Simulasi: Network error
|
||||||
|
- Expected: Error dialog koneksi, opsi kembali ke dashboard
|
||||||
|
|
||||||
|
## 🚀 Cara Penggunaan
|
||||||
|
|
||||||
|
Implementasi ini sudah terintegrasi otomatis dalam sistem quiz. Tidak ada konfigurasi tambahan yang diperlukan. Sistem akan:
|
||||||
|
|
||||||
|
1. **Otomatis mendeteksi** ketika backend mengembalikan response yang mengindikasikan soal habis
|
||||||
|
2. **Otomatis menghentikan** timer quiz
|
||||||
|
3. **Otomatis menampilkan** pesan ke user
|
||||||
|
4. **Otomatis menyelesaikan** quiz dan mengarahkan ke halaman hasil
|
||||||
|
|
||||||
|
## 📋 Checklist Implementasi
|
||||||
|
|
||||||
|
- ✅ Penanganan response 404 dengan pesan soal habis
|
||||||
|
- ✅ Penanganan response 204 No Content
|
||||||
|
- ✅ Penanganan response 200 dengan pesan soal habis
|
||||||
|
- ✅ Method untuk menghentikan timer quiz
|
||||||
|
- ✅ Method untuk auto-finish quiz
|
||||||
|
- ✅ Dialog pesan untuk user
|
||||||
|
- ✅ Error handling untuk network error
|
||||||
|
- ✅ Error handling untuk auto-finish failure
|
||||||
|
- ✅ Fallback mechanism
|
||||||
|
- ✅ Logging untuk debugging
|
||||||
|
- ✅ Dokumentasi lengkap
|
||||||
|
|
||||||
|
## 🎉 Hasil Akhir
|
||||||
|
|
||||||
|
Dengan implementasi ini, quiz akan **otomatis berhenti** dan **tidak akan stuck** ketika soal habis di level manapun. User akan mendapat pengalaman yang smooth dengan notifikasi yang jelas dan sistem yang robust dalam menangani berbagai skenario error.
|
||||||
|
|
||||||
|
**Implementasi selesai dan siap untuk digunakan!** 🚀
|
|
@ -0,0 +1,196 @@
|
||||||
|
# Implementasi Quiz Auto-Stop ketika Soal Habis di Level
|
||||||
|
|
||||||
|
## Deskripsi
|
||||||
|
|
||||||
|
Implementasi ini menambahkan fitur untuk menghentikan quiz otomatis ketika soal habis di level tertentu. Sistem akan mendeteksi response 404 atau pesan khusus dari backend dan secara otomatis menghentikan timer, menampilkan pesan ke user, dan menyelesaikan quiz.
|
||||||
|
|
||||||
|
## File yang Dimodifikasi
|
||||||
|
|
||||||
|
### 1. `lib/views/siswa/quiz/controllers/quiz_question_controller.dart`
|
||||||
|
|
||||||
|
#### Perubahan Utama:
|
||||||
|
|
||||||
|
- **Penanganan Response 404**: Menambahkan logika khusus untuk mendeteksi ketika soal habis di level tertentu
|
||||||
|
- **Penanganan Response 204**: Menambahkan penanganan untuk status 204 No Content
|
||||||
|
- **Pengecekan Pesan Response**: Memeriksa pesan dalam response body untuk mendeteksi soal habis
|
||||||
|
- **Method `handleQuestionsExhausted()`**: Method baru untuk menangani ketika soal habis
|
||||||
|
- **Method `autoFinishQuiz()`**: Method untuk menyelesaikan quiz otomatis
|
||||||
|
|
||||||
|
#### Logika Deteksi Soal Habis:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
// Cek status code 404
|
||||||
|
if (response.statusCode == 404) {
|
||||||
|
String responseBody = response.body.toLowerCase();
|
||||||
|
if (responseBody.contains("tidak ada soal lagi di level ini") ||
|
||||||
|
responseBody.contains("soal habis") ||
|
||||||
|
responseBody.contains("questions exhausted")) {
|
||||||
|
await handleQuestionsExhausted(attemptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cek status code 204
|
||||||
|
if (response.statusCode == 204) {
|
||||||
|
await handleQuestionsExhausted(attemptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cek pesan dalam response 200
|
||||||
|
if (json.containsKey('message')) {
|
||||||
|
String message = json['message'].toString().toLowerCase();
|
||||||
|
if (message.contains("tidak ada soal lagi di level ini") ||
|
||||||
|
message.contains("soal habis") ||
|
||||||
|
message.contains("questions exhausted") ||
|
||||||
|
message.contains("no more questions")) {
|
||||||
|
await handleQuestionsExhausted(attemptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. `lib/views/siswa/quiz/controllers/quiz_attempt_controller.dart`
|
||||||
|
|
||||||
|
#### Perubahan Utama:
|
||||||
|
|
||||||
|
- **Method `stopQuizTimer()`**: Method baru untuk menghentikan timer quiz yang dapat dipanggil dari controller lain
|
||||||
|
|
||||||
|
## Alur Kerja
|
||||||
|
|
||||||
|
### 1. Deteksi Soal Habis
|
||||||
|
|
||||||
|
Sistem akan mendeteksi soal habis melalui:
|
||||||
|
|
||||||
|
- **Status Code 404** dengan pesan "Tidak ada soal lagi di level ini"
|
||||||
|
- **Status Code 204** (No Content)
|
||||||
|
- **Status Code 200** dengan pesan soal habis dalam response body
|
||||||
|
|
||||||
|
### 2. Penanganan Soal Habis
|
||||||
|
|
||||||
|
Ketika soal habis terdeteksi:
|
||||||
|
|
||||||
|
1. **Hentikan Timer**: Memanggil `stopQuizTimer()` untuk menghentikan countdown
|
||||||
|
2. **Tampilkan Pesan**: Menampilkan dialog "Soal sudah habis di level ini, quiz selesai"
|
||||||
|
3. **Auto Finish Quiz**:
|
||||||
|
- Kirim jawaban kosong untuk soal yang belum dijawab
|
||||||
|
- Panggil endpoint auto-finish quiz
|
||||||
|
- Redirect ke halaman hasil quiz
|
||||||
|
|
||||||
|
### 3. Auto Finish Process
|
||||||
|
|
||||||
|
```dart
|
||||||
|
Future<void> autoFinishQuiz(String attemptId) async {
|
||||||
|
// 1. Kirim jawaban kosong untuk soal yang belum dijawab
|
||||||
|
for (String qid in quizAttemptC.allQuestionIds) {
|
||||||
|
if (!quizAttemptC.answeredQuestions.containsKey(qid)) {
|
||||||
|
await quizAttemptC.postQuizAttemptAnswer(
|
||||||
|
quizAttemptId: attemptId,
|
||||||
|
questionId: qid,
|
||||||
|
jawabanSiswa: "",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Panggil endpoint auto-finish
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse("${ApiConstants.quizAutoFinishEnpoint}/$attemptId"),
|
||||||
|
headers: headers,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Redirect ke halaman hasil
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
Get.offAllNamed('/quiz-selesai', arguments: {'quiz_id': quizId});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pesan yang Didukung
|
||||||
|
|
||||||
|
Sistem akan mendeteksi soal habis berdasarkan pesan berikut dalam response:
|
||||||
|
|
||||||
|
- "Tidak ada soal lagi di level ini"
|
||||||
|
- "Soal habis"
|
||||||
|
- "Questions exhausted"
|
||||||
|
- "No more questions"
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### 1. Network Error
|
||||||
|
|
||||||
|
Jika terjadi error koneksi saat auto-finish:
|
||||||
|
|
||||||
|
- Tampilkan dialog error koneksi
|
||||||
|
- Berikan opsi untuk kembali ke dashboard
|
||||||
|
|
||||||
|
### 2. Auto-Finish Failure
|
||||||
|
|
||||||
|
Jika auto-finish gagal:
|
||||||
|
|
||||||
|
- Tampilkan dialog error
|
||||||
|
- Berikan opsi untuk kembali ke dashboard
|
||||||
|
|
||||||
|
### 3. Fallback
|
||||||
|
|
||||||
|
Jika terjadi error dalam penanganan soal habis:
|
||||||
|
|
||||||
|
- Langsung redirect ke halaman quiz selesai
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Test Cases yang Harus Diuji:
|
||||||
|
|
||||||
|
1. **Response 404 dengan pesan soal habis**
|
||||||
|
|
||||||
|
- Backend mengembalikan 404 + "Tidak ada soal lagi di level ini"
|
||||||
|
- Timer harus berhenti
|
||||||
|
- Dialog pesan harus muncul
|
||||||
|
- Quiz harus auto-finish
|
||||||
|
|
||||||
|
2. **Response 204 No Content**
|
||||||
|
|
||||||
|
- Backend mengembalikan 204
|
||||||
|
- Timer harus berhenti
|
||||||
|
- Quiz harus auto-finish
|
||||||
|
|
||||||
|
3. **Response 200 dengan pesan soal habis**
|
||||||
|
|
||||||
|
- Backend mengembalikan 200 + message soal habis
|
||||||
|
- Timer harus berhenti
|
||||||
|
- Quiz harus auto-finish
|
||||||
|
|
||||||
|
4. **Response 404 tanpa pesan soal habis**
|
||||||
|
|
||||||
|
- Backend mengembalikan 404 tanpa pesan khusus
|
||||||
|
- Tampilkan error dialog umum
|
||||||
|
- Tidak auto-finish
|
||||||
|
|
||||||
|
5. **Network error saat auto-finish**
|
||||||
|
- Simulasi network error
|
||||||
|
- Tampilkan error dialog
|
||||||
|
- Berikan opsi kembali ke dashboard
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
Sistem menambahkan logging yang detail untuk debugging:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
log("404 - Soal habis di level ini detected");
|
||||||
|
log("Confirmed: Questions exhausted at this level");
|
||||||
|
log("Quiz timer stopped");
|
||||||
|
log("Auto finishing quiz for attempt ID: $attemptId");
|
||||||
|
log("Auto finish success: $json");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
Implementasi ini menggunakan:
|
||||||
|
|
||||||
|
- `GetX` untuk state management dan navigation
|
||||||
|
- `http` package untuk API calls
|
||||||
|
- `shared_preferences` untuk menyimpan data lokal
|
||||||
|
- `dart:async` untuk timer management
|
||||||
|
|
||||||
|
## Catatan Penting
|
||||||
|
|
||||||
|
1. **Timer Management**: Timer quiz akan dihentikan secara otomatis ketika soal habis terdeteksi
|
||||||
|
2. **User Experience**: User akan mendapat notifikasi yang jelas bahwa quiz selesai karena soal habis
|
||||||
|
3. **Data Integrity**: Semua soal yang belum dijawab akan dikirim dengan jawaban kosong
|
||||||
|
4. **Error Recovery**: Sistem memiliki fallback untuk menangani berbagai jenis error
|
||||||
|
5. **Logging**: Semua proses dicatat dengan detail untuk memudahkan debugging
|
|
@ -0,0 +1,16 @@
|
||||||
|
# ui
|
||||||
|
|
||||||
|
A new Flutter project.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
This project is a starting point for a Flutter application.
|
||||||
|
|
||||||
|
A few resources to get you started if this is your first Flutter project:
|
||||||
|
|
||||||
|
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
|
||||||
|
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
|
||||||
|
|
||||||
|
For help getting started with Flutter development, view the
|
||||||
|
[online documentation](https://docs.flutter.dev/), which offers tutorials,
|
||||||
|
samples, guidance on mobile development, and a full API reference.
|
|
@ -0,0 +1,28 @@
|
||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at https://dart.dev/lints.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
|
rules:
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
|
@ -1,14 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Exports;
|
|
||||||
|
|
||||||
use Illuminate\Contracts\View\View;
|
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
|
||||||
|
|
||||||
class QuizExport implements FromView
|
|
||||||
{
|
|
||||||
public function view(): View
|
|
||||||
{
|
|
||||||
return view('pages.role_guru.quiz.excel_export_quiz');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Exports;
|
|
||||||
|
|
||||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
||||||
|
|
||||||
class RekapExport implements FromCollection, WithHeadings
|
|
||||||
{
|
|
||||||
protected $rekap;
|
|
||||||
|
|
||||||
public function __construct($rekap)
|
|
||||||
{
|
|
||||||
$this->rekap = $rekap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function collection()
|
|
||||||
{
|
|
||||||
return collect($this->rekap)->map(function ($item) {
|
|
||||||
return [
|
|
||||||
$item['matapelajaran'],
|
|
||||||
$item['judul_quiz'],
|
|
||||||
$item['nama_siswa'],
|
|
||||||
$item['tahun_ajaran'],
|
|
||||||
$item['kelas'],
|
|
||||||
$item['total_skor'],
|
|
||||||
$item['kkm'],
|
|
||||||
$item['persentase'],
|
|
||||||
$item['persentase'] >= $item['kkm'] ? 'Lulus' : 'Tidak Lulus',
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public function headings(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'Mata Pelajaran',
|
|
||||||
'Judul Quiz',
|
|
||||||
'Nama Siswa',
|
|
||||||
'Tahun Ajaran',
|
|
||||||
'Kelas',
|
|
||||||
'Total Skor',
|
|
||||||
'KKM',
|
|
||||||
'Nilai (%)',
|
|
||||||
'Status',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,107 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Exports;
|
|
||||||
|
|
||||||
use App\Models\SubmitTugas;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
|
|
||||||
class TugasDetailExport implements FromCollection, WithHeadings, WithMapping, WithStyles
|
|
||||||
{
|
|
||||||
protected $selectedKelas;
|
|
||||||
protected $selectedMatpel;
|
|
||||||
|
|
||||||
public function __construct($selectedKelas = null, $selectedMatpel = null)
|
|
||||||
{
|
|
||||||
$this->selectedKelas = $selectedKelas;
|
|
||||||
$this->selectedMatpel = $selectedMatpel;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \Illuminate\Support\Collection
|
|
||||||
*/
|
|
||||||
public function collection()
|
|
||||||
{
|
|
||||||
$guruNip = Auth::user()->guru->nip;
|
|
||||||
|
|
||||||
$query = SubmitTugas::with(['siswa', 'tugas.mataPelajaran'])
|
|
||||||
->whereHas('tugas', function ($q) use ($guruNip) {
|
|
||||||
$q->where('guru_nip', $guruNip);
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($this->selectedKelas) {
|
|
||||||
$query->whereHas('tugas', function ($q) {
|
|
||||||
$q->where('kelas', $this->selectedKelas);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->selectedMatpel) {
|
|
||||||
$query->whereHas('tugas', function ($q) {
|
|
||||||
$q->where('matapelajaran_id', $this->selectedMatpel);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return $query->orderBy('created_at', 'desc')->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function headings(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'No',
|
|
||||||
'Nama Tugas',
|
|
||||||
'Mata Pelajaran',
|
|
||||||
'Kelas',
|
|
||||||
'Nama Siswa',
|
|
||||||
'NISN',
|
|
||||||
'Tanggal Submit',
|
|
||||||
'Nilai',
|
|
||||||
'Status Nilai',
|
|
||||||
'Tenggat Waktu',
|
|
||||||
'Status Tenggat',
|
|
||||||
'Deskripsi Tugas'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function map($submitTugas): array
|
|
||||||
{
|
|
||||||
static $no = 1;
|
|
||||||
|
|
||||||
$tugas = $submitTugas->tugas;
|
|
||||||
$siswa = $submitTugas->siswa;
|
|
||||||
|
|
||||||
$statusNilai = $submitTugas->nilai !== null ? 'Sudah Dinilai' : 'Belum Dinilai';
|
|
||||||
$statusTenggat = \Carbon\Carbon::parse($tugas->tenggat)->isPast() ? 'Lewat Tenggat' : 'Masih Aktif';
|
|
||||||
|
|
||||||
return [
|
|
||||||
$no++,
|
|
||||||
$tugas->nama,
|
|
||||||
$tugas->mataPelajaran->nama ?? '-',
|
|
||||||
$tugas->kelas,
|
|
||||||
$siswa->nama ?? 'Siswa tidak ditemukan',
|
|
||||||
$submitTugas->nisn,
|
|
||||||
\Carbon\Carbon::parse($submitTugas->tanggal)->format('d/m/Y H:i'),
|
|
||||||
$submitTugas->nilai ?? '-',
|
|
||||||
$statusNilai,
|
|
||||||
\Carbon\Carbon::parse($tugas->tenggat)->format('d/m/Y'),
|
|
||||||
$statusTenggat,
|
|
||||||
$tugas->deskripsi ?? '-'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function styles(Worksheet $sheet)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
1 => [
|
|
||||||
'font' => ['bold' => true],
|
|
||||||
'fill' => [
|
|
||||||
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
||||||
'startColor' => ['rgb' => 'E2E8F0']
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,100 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Exports;
|
|
||||||
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Maatwebsite\Excel\Concerns\FromCollection;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithHeadings;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithMapping;
|
|
||||||
use Maatwebsite\Excel\Concerns\WithStyles;
|
|
||||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
|
||||||
|
|
||||||
class TugasExport implements FromCollection, WithHeadings, WithMapping, WithStyles
|
|
||||||
{
|
|
||||||
protected $selectedKelas;
|
|
||||||
protected $selectedMatpel;
|
|
||||||
|
|
||||||
public function __construct($selectedKelas = null, $selectedMatpel = null)
|
|
||||||
{
|
|
||||||
$this->selectedKelas = $selectedKelas;
|
|
||||||
$this->selectedMatpel = $selectedMatpel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function collection()
|
|
||||||
{
|
|
||||||
$guruNip = Auth::user()->guru->nip;
|
|
||||||
|
|
||||||
$query = Tugas::with(['mataPelajaran', 'submitTugas.siswa'])
|
|
||||||
->where('guru_nip', $guruNip);
|
|
||||||
|
|
||||||
if ($this->selectedKelas) {
|
|
||||||
$query->where('kelas', $this->selectedKelas);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->selectedMatpel) {
|
|
||||||
$query->where('matapelajaran_id', $this->selectedMatpel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $query->orderBy('created_at', 'desc')->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function headings(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'No',
|
|
||||||
'Nama Tugas',
|
|
||||||
'Mata Pelajaran',
|
|
||||||
'Kelas',
|
|
||||||
'Tanggal Dibuat',
|
|
||||||
'Tenggat Waktu',
|
|
||||||
'Jumlah Submit',
|
|
||||||
'Sudah Dinilai',
|
|
||||||
'Belum Dinilai',
|
|
||||||
'Rata-rata Nilai',
|
|
||||||
'Status Tenggat'
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function map($tugas): array
|
|
||||||
{
|
|
||||||
static $no = 1;
|
|
||||||
|
|
||||||
$submitTugas = $tugas->submitTugas ?: collect();
|
|
||||||
$sudahDinilai = $submitTugas->whereNotNull('nilai')->count();
|
|
||||||
$totalSubmit = $submitTugas->count();
|
|
||||||
$belumDinilai = $totalSubmit - $sudahDinilai;
|
|
||||||
$rataRataNilai = $submitTugas->whereNotNull('nilai')->count() > 0
|
|
||||||
? number_format($submitTugas->whereNotNull('nilai')->avg('nilai'), 1)
|
|
||||||
: '-';
|
|
||||||
|
|
||||||
$statusTenggat = \Carbon\Carbon::parse($tugas->tenggat)->isPast() ? 'Lewat Tenggat' : 'Masih Aktif';
|
|
||||||
|
|
||||||
return [
|
|
||||||
$no++,
|
|
||||||
$tugas->nama,
|
|
||||||
$tugas->mataPelajaran->nama ?? '-',
|
|
||||||
$tugas->kelas,
|
|
||||||
\Carbon\Carbon::parse($tugas->tanggal)->format('d/m/Y'),
|
|
||||||
\Carbon\Carbon::parse($tugas->tenggat)->format('d/m/Y'),
|
|
||||||
$totalSubmit,
|
|
||||||
$sudahDinilai,
|
|
||||||
$belumDinilai,
|
|
||||||
$rataRataNilai,
|
|
||||||
$statusTenggat
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function styles(Worksheet $sheet)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
1 => [
|
|
||||||
'font' => ['bold' => true],
|
|
||||||
'fill' => [
|
|
||||||
'fillType' => \PhpOffice\PhpSpreadsheet\Style\Fill::FILL_SOLID,
|
|
||||||
'startColor' => ['rgb' => 'E2E8F0']
|
|
||||||
]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,193 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Admin;
|
|
||||||
use App\Repositories\AdminRepository;
|
|
||||||
use App\Repositories\UserRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use App\Models\AuditLog;
|
|
||||||
|
|
||||||
class AdminController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
protected $paramUser;
|
|
||||||
|
|
||||||
public function __construct(AdminRepository $admin, UserRepository $user)
|
|
||||||
{
|
|
||||||
$this->param = $admin;
|
|
||||||
$this->paramUser = $user;
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$admin = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.admin.index", compact("admin"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view("pages.role_admin.admin.create");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
'role' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nip' => 'required|string|size:18|unique:guru,nip',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (Admin::where('nip', $data['nip'])->exists()) {
|
|
||||||
Alert::error("Terjadi Kesalahan", "NIP sudah terdaftar.");
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
$dataUser['pass'] = $request->nip;
|
|
||||||
$user = $this->paramUser->store($dataUser);
|
|
||||||
|
|
||||||
$data["user_id"] = $user->id;
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("admin");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$admin = $this->param->find($id);
|
|
||||||
return view("pages.role_admin.admin.edit", compact("admin"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nip' => 'required|string|size:18',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->paramUser->update($dataUser, $request->user_id);
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
return redirect()->route("admin");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$this->param->destroy($request->formid);
|
|
||||||
$this->paramUser->destroy($request->user_id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Hapus.");
|
|
||||||
return redirect()->route("admin");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Menampilkan halaman form pemindahan data
|
|
||||||
public function pindahDataPage()
|
|
||||||
{
|
|
||||||
$mataPelajaran = MataPelajaran::all();
|
|
||||||
$guru = Guru::all();
|
|
||||||
return view('pages.role_admin.pindah_data', compact('mataPelajaran', 'guru'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Proses pemindahan data guru
|
|
||||||
public function pindahGuruMatpel(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'mata_pelajaran_id' => 'required|exists:matapelajaran,id',
|
|
||||||
'guru_lama_nip' => 'required|exists:guru,nip',
|
|
||||||
'guru_baru_nip' => 'required|exists:guru,nip',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($request->guru_lama_nip == $request->guru_baru_nip) {
|
|
||||||
Alert::error('Gagal', 'Guru lama dan guru baru tidak boleh sama.');
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
$mapel = MataPelajaran::where('id', $request->mata_pelajaran_id)
|
|
||||||
->where('guru_nip', $request->guru_lama_nip)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if (!$mapel) {
|
|
||||||
Alert::error('Gagal', 'Guru lama bukan pengampu mata pelajaran yang dipilih.');
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update tugas
|
|
||||||
Tugas::where('guru_nip', $request->guru_lama_nip)
|
|
||||||
->where('matapelajaran_id', $request->mata_pelajaran_id)
|
|
||||||
->update(['guru_nip' => $request->guru_baru_nip]);
|
|
||||||
|
|
||||||
// Update guru pengampu pada tabel matapelajaran
|
|
||||||
MataPelajaran::where('id', $request->mata_pelajaran_id)
|
|
||||||
->where('guru_nip', $request->guru_lama_nip)
|
|
||||||
->update(['guru_nip' => $request->guru_baru_nip]);
|
|
||||||
|
|
||||||
Alert::success('Berhasil', 'Data guru berhasil dipindahkan.');
|
|
||||||
return redirect()->route('admin.pindah-data');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function auditLogPage()
|
|
||||||
{
|
|
||||||
$logs = AuditLog::with('user')->orderBy('created_at', 'desc')->paginate(30);
|
|
||||||
return view('pages.role_admin.audit_log', compact('logs'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\Admin;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\DB;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
|
|
||||||
class AuthController extends Controller
|
|
||||||
{
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function login(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
"login" => "required|string",
|
|
||||||
"password" => "required|string",
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Temukan user berdasarkan email atau NIP
|
|
||||||
$login = $request->login;
|
|
||||||
$user = User::where('email', $login)->first();
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
$siswa = Siswa::where('nisn', $login)->first();
|
|
||||||
if ($siswa)
|
|
||||||
$user = $siswa->user;
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
$guru = Guru::where('nip', $login)->first();
|
|
||||||
if ($guru)
|
|
||||||
$user = $guru->user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// $token = DB::table('personal_access_tokens')->where('tokenable_id', $user->id)->first();
|
|
||||||
// if (!is_null($token)) {
|
|
||||||
// return $this->errorApiResponse("User sudah login di device lain. Harap logout terlebih dahulu.");
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// Jika user ditemukan dan password cocok
|
|
||||||
if ($user && Hash::check($request->password, $user->password)) {
|
|
||||||
$token = $user->createToken('Mobile')->plainTextToken;
|
|
||||||
$user = $user->role == "siswa" ? $siswa : $guru;
|
|
||||||
|
|
||||||
return $this->okApiResponse([
|
|
||||||
'token' => $token,
|
|
||||||
'user' => $user,
|
|
||||||
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->errorApiResponse('Login gagal. Cek kembali kredensial Anda.');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function logout(Request $request)
|
|
||||||
{
|
|
||||||
$request->user()->currentAccessToken()->delete();
|
|
||||||
return $this->okApiResponse([], 'Berhsasil Logout.');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function user(Request $request)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
$user = $request->user();
|
|
||||||
if ($user->role == 'siswa') {
|
|
||||||
$data = Siswa::where('user_id', $user->id);
|
|
||||||
} else {
|
|
||||||
$data = Guru::where('user_id', $user->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $data->with('user')->first();
|
|
||||||
|
|
||||||
return $this->okApiResponse([
|
|
||||||
'user' => $data,
|
|
||||||
]);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class KelasContoller extends Controller
|
|
||||||
{
|
|
||||||
use ApiResponse;
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$kelas = Kelas::orderBy("nama", "ASC")->get();
|
|
||||||
return $this->okApiResponse($kelas);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\Materi;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class MataPelajaranController extends Controller
|
|
||||||
{
|
|
||||||
use ApiResponse;
|
|
||||||
public function getMatpel(Request $request)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
$query = [];
|
|
||||||
$user = $request->user();
|
|
||||||
if ($user->role == 'siswa') {
|
|
||||||
$data = Siswa::where('user_id', $user->id);
|
|
||||||
} else {
|
|
||||||
$data = Guru::where('user_id', $user->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $data->with('user')->first();
|
|
||||||
|
|
||||||
if ($data->user->role == "siswa") {
|
|
||||||
$query = MataPelajaran::where(function ($query) use ($data) {
|
|
||||||
$query->where('kelas', $data->kelas)
|
|
||||||
->where('tahun_ajaran', $data->tahun_ajaran);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query = MataPelajaran::where(function ($query) use ($data, $request) {
|
|
||||||
$query->where('guru_nip', $data->nip)
|
|
||||||
->where("kelas", $request->kelas)
|
|
||||||
->where("tahun_ajaran", $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$query = $query->with(['guru', 'materi'])->get();
|
|
||||||
|
|
||||||
$result = $query->map(function ($item) {
|
|
||||||
$materi = $item->materi ?? collect();
|
|
||||||
|
|
||||||
$jumlahBuku = $materi->where('type', 'buku')->count();
|
|
||||||
$jumlahVideo = $materi->where('type', 'video')->count();
|
|
||||||
|
|
||||||
return array_merge(
|
|
||||||
$item->toArray(),
|
|
||||||
[
|
|
||||||
'jumlah_buku' => $jumlahBuku,
|
|
||||||
'jumlah_video' => $jumlahVideo,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $this->okApiResponse($result);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMatpelSimple(Request $request)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
$query = [];
|
|
||||||
$user = $request->user();
|
|
||||||
if ($user->role == 'siswa') {
|
|
||||||
$data = Siswa::where('user_id', $user->id);
|
|
||||||
} else {
|
|
||||||
$data = Guru::where('user_id', $user->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $data->with('user')->first();
|
|
||||||
|
|
||||||
if ($data->user->role == "siswa") {
|
|
||||||
$query = MataPelajaran::where(function ($query) use ($data) {
|
|
||||||
$query->where('kelas', $data->kelas)
|
|
||||||
->where('tahun_ajaran', $data->tahun_ajaran);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query = MataPelajaran::where(function ($query) use ($data) {
|
|
||||||
$query->where('guru_nip', $data->nip);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$query = $query->with('guru')->get();
|
|
||||||
|
|
||||||
return $this->okApiResponse($query);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Repositories\MateriRepository;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class MateriController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function __construct(MateriRepository $materi)
|
|
||||||
{
|
|
||||||
$this->param = $materi;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMateri(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = [];
|
|
||||||
$user = $request->user();
|
|
||||||
if ($user->role == 'siswa') {
|
|
||||||
$data = Siswa::where('user_id', $user->id);
|
|
||||||
} else {
|
|
||||||
$data = Guru::where('user_id', $user->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $data->with('user')->first();
|
|
||||||
|
|
||||||
$result = $this->param->getDataApi($request->id_matpel, $request->semester, $request->type, $data);
|
|
||||||
return $this->okApiResponse($result);
|
|
||||||
} catch (Exception $e) {
|
|
||||||
return $this->errorApiResponse("Terjadi Kesalahan " . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class QuizAnalysisController extends Controller
|
|
||||||
{
|
|
||||||
static function getSkor($first)
|
|
||||||
{
|
|
||||||
$quizId = $first->quiz_id;
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $quizId)->first();
|
|
||||||
$jumlahSoalPerLevel = json_decode($quizLevelSettings->jumlah_soal_per_level, true);
|
|
||||||
$totalSkorLevel = 0;
|
|
||||||
|
|
||||||
foreach (json_decode($quizLevelSettings->skor_level) as $key => $value) {
|
|
||||||
$totalSkorLevel += $value * (int) $jumlahSoalPerLevel[$key];
|
|
||||||
}
|
|
||||||
return $totalSkorLevel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function analisis(Request $request)
|
|
||||||
{
|
|
||||||
$user = Auth::user()->siswa;
|
|
||||||
|
|
||||||
// Ambil semua attempt dengan relasi quizzes dan mata pelajaran
|
|
||||||
$attempts = QuizAttempts::where('nisn', $user->nisn)
|
|
||||||
->with(['quizzes.mataPelajaran'])
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Kelompokkan berdasarkan mata_pelajaran_id dan hitung rata-rata skor
|
|
||||||
$grouped = $attempts->groupBy(function ($item) {
|
|
||||||
return $item->quizzes->mataPelajaran->id;
|
|
||||||
});
|
|
||||||
|
|
||||||
$avgScores = $grouped->map(function ($items) {
|
|
||||||
$first = $items->first(); // untuk ambil info nama mapel
|
|
||||||
$avg = $items->avg('skor');
|
|
||||||
|
|
||||||
return [
|
|
||||||
'mapel_id' => $first->quizzes->mataPelajaran->id,
|
|
||||||
'mapel' => $first->quizzes->mataPelajaran->nama,
|
|
||||||
'rata_rata_skor' => $avg,
|
|
||||||
'persentase' => round(($avg / $this->getSkor($first)) * 100),
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
// Urutkan berdasarkan skor rata-rata (desc dan asc)
|
|
||||||
$kelebihan = $avgScores->sortByDesc('rata_rata_skor')->take(2);
|
|
||||||
$kelebihanMapelIds = $kelebihan->pluck('mapel_id')->toArray();
|
|
||||||
|
|
||||||
$kekurangan = $avgScores->whereNotIn('mapel_id', $kelebihanMapelIds)
|
|
||||||
->sortBy('rata_rata_skor')
|
|
||||||
->take(2);
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'kelebihan' => array_values($kelebihan->toArray()),
|
|
||||||
'kekurangan' => array_values($kekurangan->toArray())
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,222 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\QuizAttemptAnswers;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use App\Models\QuizQuestions;
|
|
||||||
use App\Repositories\QuizRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class QuizController extends Controller
|
|
||||||
{
|
|
||||||
use ApiResponse;
|
|
||||||
protected $param;
|
|
||||||
public function __construct(QuizRepository $quizzes)
|
|
||||||
{
|
|
||||||
$this->param = $quizzes;
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$data = $this->param->apiGetQuizzes($request->matapelajaran_id);
|
|
||||||
return $this->okApiResponse($data);
|
|
||||||
}
|
|
||||||
public function quizGuru(Request $request)
|
|
||||||
{
|
|
||||||
$data = $this->param->apiGetQuizzesGuru($request, $request->matapelajaran_id);
|
|
||||||
return $this->okApiResponse($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function start(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'quiz_id' => 'required|exists:quizzes,id',
|
|
||||||
'nisn' => 'required|string',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $request->quiz_id)->first();
|
|
||||||
$level = [];
|
|
||||||
foreach (json_decode($quizLevelSettings->jumlah_soal_per_level) as $key => $value) {
|
|
||||||
$lvlNumber = preg_replace('/[^0-9]/', '', $key);
|
|
||||||
$level['fase' . $lvlNumber] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
$attempt = QuizAttempts::create([
|
|
||||||
'quiz_id' => $request->quiz_id,
|
|
||||||
'nisn' => $request->nisn,
|
|
||||||
'skor' => 0,
|
|
||||||
'level_akhir' => $quizLevelSettings->level_awal,
|
|
||||||
'fase' => $quizLevelSettings->level_awal,
|
|
||||||
'benar' => json_encode($level),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'attempt_id' => $attempt->id,
|
|
||||||
'message' => 'Quiz dimulai.',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function nextQuestion($attempt_id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $this->param->nextQuestion($attempt_id);
|
|
||||||
return $this->okApiResponse($data);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->errorApiResponse($e->getMessage(), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function answer(Request $request, $attempt_id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $this->param->answer($request, $attempt_id);
|
|
||||||
return $this->okApiResponse($data);
|
|
||||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
|
||||||
return $this->errorApiResponse('Validation error: ' . $e->getMessage(), 422);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->errorApiResponse($e->getMessage(), 400);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFinishQuiz(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
return $this->param->getFinishQuiz($request->quiz_id);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->errorApiResponse($e->getMessage(), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTopFive(Request $request)
|
|
||||||
{
|
|
||||||
|
|
||||||
$query = QuizAttempts::with('siswa')
|
|
||||||
->where('quiz_id', $request->quiz_id)
|
|
||||||
->orderByDesc('skor')
|
|
||||||
->take(5)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
$skorMe = QuizAttempts::select('skor')
|
|
||||||
->where('nisn', Auth::user()->siswa->nisn)
|
|
||||||
->where('quiz_id', $request->quiz_id)
|
|
||||||
->orderByDesc('skor')->first();
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'skor_me' => $skorMe,
|
|
||||||
'data' => $query,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static function getNilai($first)
|
|
||||||
{
|
|
||||||
$quizId = $first->quiz_id;
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $quizId)->first();
|
|
||||||
$jumlahSoalPerLevel = json_decode($quizLevelSettings->jumlah_soal_per_level, true);
|
|
||||||
$totalSkorLevel = 0;
|
|
||||||
|
|
||||||
foreach (json_decode($quizLevelSettings->skor_level) as $key => $value) {
|
|
||||||
$totalSkorLevel += $value * (int) $jumlahSoalPerLevel[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
"total_skor_level" => $totalSkorLevel,
|
|
||||||
"kkm" => $quizLevelSettings->kkm,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getApiQuizGuru(Request $request)
|
|
||||||
{
|
|
||||||
$query = QuizAttempts::with(['quizzes', 'siswa'])
|
|
||||||
->where(function ($q) use ($request) {
|
|
||||||
$q->where('quiz_id', $request->quiz_id);
|
|
||||||
})->whereHas('siswa', function ($q) use ($request) {
|
|
||||||
$q->where('kelas', $request->kelas)
|
|
||||||
->where('tahun_ajaran', $request->tahun_ajaran);
|
|
||||||
})->get();
|
|
||||||
|
|
||||||
$avgScores = $query->map(function ($items) {
|
|
||||||
$first = $items->first(); // untuk ambil info nama mapel
|
|
||||||
$avg = $items->avg('skor');
|
|
||||||
|
|
||||||
return [
|
|
||||||
'nama' => $first->siswa->nama,
|
|
||||||
'mapel_id' => $first->quizzes->mataPelajaran->id,
|
|
||||||
'mapel' => $first->quizzes->mataPelajaran->nama,
|
|
||||||
'skor' => $first->skor,
|
|
||||||
'persentase' => round(($avg / $this->getNilai($first)['total_skor_level']) * 100),
|
|
||||||
'kkm' => $this->getNilai($first)['kkm'],
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
return $this->okApiResponse($avgScores);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function debugQuiz($attempt_id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$attempt = QuizAttempts::findOrFail($attempt_id);
|
|
||||||
$questions = QuizQuestions::where('quiz_id', $attempt->quiz_id)->get();
|
|
||||||
$answeredQuestions = QuizAttemptAnswers::where('attempt_id', $attempt_id)->get();
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'attempt' => $attempt,
|
|
||||||
'total_questions' => $questions->count(),
|
|
||||||
'answered_questions' => $answeredQuestions->count(),
|
|
||||||
'questions_by_level' => $questions->groupBy('level'),
|
|
||||||
'answered_question_ids' => $answeredQuestions->pluck('question_id'),
|
|
||||||
'current_level' => $attempt->level_akhir,
|
|
||||||
'current_fase' => $attempt->fase,
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->errorApiResponse($e->getMessage(), 500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function autoFinish($attempt_id)
|
|
||||||
{
|
|
||||||
$attempt = \App\Models\QuizAttempts::findOrFail($attempt_id);
|
|
||||||
|
|
||||||
// Ambil semua soal quiz
|
|
||||||
$allQuestions = \App\Models\QuizQuestions::where('quiz_id', $attempt->quiz_id)->pluck('id')->toArray();
|
|
||||||
|
|
||||||
// Ambil semua question_id yang sudah dijawab
|
|
||||||
$answered = \App\Models\QuizAttemptAnswers::where('attempt_id', $attempt_id)->pluck('question_id')->toArray();
|
|
||||||
|
|
||||||
// Cari soal yang belum dijawab
|
|
||||||
$unanswered = array_diff($allQuestions, $answered);
|
|
||||||
|
|
||||||
foreach ($unanswered as $questionId) {
|
|
||||||
\App\Models\QuizAttemptAnswers::create([
|
|
||||||
'attempt_id' => $attempt->id,
|
|
||||||
'question_id' => $questionId,
|
|
||||||
'jawaban_siswa' => '',
|
|
||||||
'benar' => 0,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hitung penilaian berdasarkan jawaban yang benar-benar dikerjakan
|
|
||||||
$jawaban_benar = \App\Models\QuizAttemptAnswers::where('attempt_id', $attempt->id)->where('benar', 1)->count();
|
|
||||||
$jawaban_salah = \App\Models\QuizAttemptAnswers::where('attempt_id', $attempt->id)->where('benar', 0)->count();
|
|
||||||
$total_dikerjakan = $jawaban_benar + $jawaban_salah;
|
|
||||||
$skor = $attempt->skor;
|
|
||||||
$persentase = $total_dikerjakan > 0 ? round(($jawaban_benar / $total_dikerjakan) * 100) : 0;
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'status' => true,
|
|
||||||
'message' => 'Quiz auto-finished successfully',
|
|
||||||
'data' => [
|
|
||||||
'jawaban_benar' => $jawaban_benar,
|
|
||||||
'jawaban_salah' => $jawaban_salah,
|
|
||||||
'total_dikerjakan' => $total_dikerjakan,
|
|
||||||
'skor' => $skor,
|
|
||||||
'persentase' => $persentase,
|
|
||||||
'attempt' => $attempt
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,49 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Http\Resources\SubmitTugasResource;
|
|
||||||
use App\Repositories\ApiSubmitTugasRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class SubmitTugasController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function __construct(ApiSubmitTugasRepository $submitTugas)
|
|
||||||
{
|
|
||||||
$this->param = $submitTugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
$data = $this->param->store($request);
|
|
||||||
return $this->okApiResponse(new SubmitTugasResource($data), "Submit Tugas Berhasil");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function detail(Request $request)
|
|
||||||
{
|
|
||||||
$data = $this->param->detail($request);
|
|
||||||
return $this->okApiResponse(new SubmitTugasResource($data), "Berhasil get submit tugas");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(Request $request)
|
|
||||||
{
|
|
||||||
$data = $this->param->update($request);
|
|
||||||
return $this->okApiResponse(new SubmitTugasResource($data), "Update Tugas Berhasil");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateNilai(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'id' => 'required|exists:submit_tugas,id',
|
|
||||||
'nilai' => 'required|integer|min:0|max:100'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $this->param->update($request);
|
|
||||||
return $this->okApiResponse(new SubmitTugasResource($data), "Nilai berhasil diperbarui");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class TahunAjaranController extends Controller
|
|
||||||
{
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function getTahunAjaran(Request $request)
|
|
||||||
{
|
|
||||||
$data = TahunAjaran::where("status", "aktif")->get();
|
|
||||||
return $this->okApiResponse($data);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Api;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Repositories\ApiTugasRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class TugasController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function __construct(ApiTugasRepository $tugas)
|
|
||||||
{
|
|
||||||
$this->param = $tugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getTugas(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = [];
|
|
||||||
$user = $request->user();
|
|
||||||
if ($user->role == 'siswa') {
|
|
||||||
$data = Siswa::where('user_id', $user->id);
|
|
||||||
} else {
|
|
||||||
$data = Guru::where('user_id', $user->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = $data->with('user')->first();
|
|
||||||
|
|
||||||
$result = $this->param->getDataApi($data, $request);
|
|
||||||
return $this->okApiResponse($result);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
return $this->errorApiResponse("Error : " . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSubmitTugasSiswa(Request $request)
|
|
||||||
{
|
|
||||||
$result = $this->param->getSubmitTugasSiswa($request);
|
|
||||||
return $this->okApiResponse($result);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,79 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Admin;
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\User;
|
|
||||||
use Exception;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
|
|
||||||
class AuthController extends Controller
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Display a listing of the resource.
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
return view("pages.auth.index");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function login(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request->validate([
|
|
||||||
"login" => "required|string",
|
|
||||||
"password" => "required|string",
|
|
||||||
]);
|
|
||||||
|
|
||||||
$login = $request->login;
|
|
||||||
$user = User::where('email', $login)->first();
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
$admin = Admin::where('nip', $login)->first();
|
|
||||||
if ($admin) {
|
|
||||||
$user = $admin->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$user) {
|
|
||||||
$guru = Guru::where('nip', $login)->first();
|
|
||||||
if ($guru) {
|
|
||||||
$user = $guru->user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($user && Hash::check($request->password, $user->password)) {
|
|
||||||
Auth::login($user);
|
|
||||||
$request->session()->regenerate();
|
|
||||||
|
|
||||||
if ($user->role == 'admin') {
|
|
||||||
return redirect()->route('/');
|
|
||||||
} elseif ($user->role == 'guru') {
|
|
||||||
return redirect()->route('dashboard.guru');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect()->route('login')->with('error', "Nip atau Password anda salah!");
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Log::error("Error saat login: " . $e->getMessage());
|
|
||||||
return redirect()->route("login")->with("error", "Terjadi kesalahan sistem. Silahkan coba lagi. $e");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function logout(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
Auth::logout();
|
|
||||||
$request->session()->invalidate();
|
|
||||||
// DB::table('sessions')->where('user_id', Auth::user()->nip)->delete();
|
|
||||||
$request->session()->regenerateToken();
|
|
||||||
return redirect()->route('login');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
Log::error("Error saat login: " . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
abstract class Controller
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
|
@ -1,78 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Repositories\DashboardRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class DashboardController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(DashboardRepository $dashboard)
|
|
||||||
{
|
|
||||||
$this->param = $dashboard;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$tahunAjaran = $request->get('tahun_ajaran');
|
|
||||||
$kelas = $request->get('kelas');
|
|
||||||
$dashboard = $this->param->getData($tahunAjaran, $kelas);
|
|
||||||
return view('pages.role_admin.admin_dashboard.index', compact('dashboard'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function indexAdmin()
|
|
||||||
{
|
|
||||||
$dashboard = $this->param->getData();
|
|
||||||
return view("pages.role_guru.dashboard.index", compact("dashboard"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,160 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\AuditLog;
|
|
||||||
use App\Repositories\GuruRepository;
|
|
||||||
use App\Repositories\UserRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class GuruController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
protected $param2;
|
|
||||||
|
|
||||||
public function __construct(GuruRepository $guru, UserRepository $userRepository)
|
|
||||||
{
|
|
||||||
$this->param = $guru;
|
|
||||||
$this->param2 = $userRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$guru = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.guru.index", compact("guru"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view("pages.role_admin.guru.create");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
'role' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nip' => 'required|string|size:18|unique:guru,nip',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (Guru::where('nip', $data['nip'])->exists()) {
|
|
||||||
Alert::error("Terjadi Kesalahan", "NIP sudah terdaftar.");
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
$dataUser['pass'] = $request->nip;
|
|
||||||
$user = $this->param2->store($dataUser);
|
|
||||||
|
|
||||||
$data["user_id"] = $user->id;
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("guru");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$guru = $this->param->find($id);
|
|
||||||
return view("pages.role_admin.guru.edit", compact("guru"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nip' => 'required|string|size:18',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param2->update($dataUser, $request->user_id);
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
return redirect()->route("guru");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$guru = Guru::find($request->formid);
|
|
||||||
if (!$guru) {
|
|
||||||
Alert::error('Gagal', 'Guru tidak ditemukan.');
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
$nip = trim(strtoupper($guru->nip));
|
|
||||||
// Cek apakah guru masih menjadi wali kelas (robust, ignore case & space)
|
|
||||||
$isWali = Kelas::whereRaw('TRIM(UPPER(nip_wali)) = ?', [$nip])->exists();
|
|
||||||
if ($isWali) {
|
|
||||||
Alert::error('Gagal', 'Tidak dapat menghapus guru karena masih menjadi wali kelas. Silakan ganti wali kelas terlebih dahulu.');
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
$this->param->destroy($request->formid);
|
|
||||||
$this->param2->destroy($request->user_id);
|
|
||||||
// Audit log
|
|
||||||
AuditLog::create([
|
|
||||||
'user_id' => Auth::id(),
|
|
||||||
'action' => 'delete_guru',
|
|
||||||
'description' => 'Menghapus guru: ' . $guru->nama . ' (' . $guru->nip . ')',
|
|
||||||
]);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di hapus data.");
|
|
||||||
return redirect()->route("guru");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Repositories\GuruDashboardRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class GuruDashboardController extends Controller
|
|
||||||
{
|
|
||||||
protected $guruDashboardRepository;
|
|
||||||
|
|
||||||
public function __construct(GuruDashboardRepository $guruDashboardRepository)
|
|
||||||
{
|
|
||||||
$this->guruDashboardRepository = $guruDashboardRepository;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$tahunAjaran = $request->get('tahun_ajaran', 'all');
|
|
||||||
$kelas = $request->get('kelas', 'all');
|
|
||||||
$quizStatus = $request->get('quiz_status', 'all');
|
|
||||||
|
|
||||||
$dashboard = $this->guruDashboardRepository->getDashboardData($tahunAjaran, $kelas, $quizStatus);
|
|
||||||
|
|
||||||
return view('pages.role_admin.guru_dashboard.index', compact('dashboard'));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,113 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Repositories\KelasRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class KelasContoller extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
protected $paramUser;
|
|
||||||
|
|
||||||
public function __construct(KelasRepository $kelas)
|
|
||||||
{
|
|
||||||
$this->param = $kelas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$kelas = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.kelas.index", compact("kelas"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view("pages.role_admin.kelas.create");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'nama' => 'required|string',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("kelas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
// $kelas = Kelas::find($id);
|
|
||||||
// return view("pages.role_admin.kelas.edit", compact("kelas"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
// try {
|
|
||||||
|
|
||||||
// $data = $request->validate([
|
|
||||||
// 'nama' => 'required|string',
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
// $this->param->update($data, $id);
|
|
||||||
// Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
// return redirect()->route("kelas");
|
|
||||||
// } catch (\Exception $e) {
|
|
||||||
// Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
// return back()->withInput();
|
|
||||||
// } catch (QueryException $e) {
|
|
||||||
// Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
// return back()->withInput();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$this->param->destroy($request->formkelas);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Hapus.");
|
|
||||||
return redirect()->route("kelas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Models\AuditLog;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use App\Repositories\MataPelajaranRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class MataPelajaranController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(MataPelajaranRepository $mataPelajaran)
|
|
||||||
{
|
|
||||||
$this->param = $mataPelajaran;
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$mataPelajaran = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.mata_pelajaran.index", compact("mataPelajaran"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$guru = Guru::all();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view("pages.role_admin.mata_pelajaran.create", compact("guru", "kelas", "tahunAjaran"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'nama' => 'required',
|
|
||||||
'guru_nip' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Tambahkan.");
|
|
||||||
return redirect()->route("mata-pelajaran");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$mataPelajaran = $this->param->find($id);
|
|
||||||
$guru = Guru::all();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view("pages.role_admin.mata_pelajaran.edit", compact(["mataPelajaran", "guru", "kelas", "tahunAjaran"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'nama' => 'required',
|
|
||||||
'guru_nip' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$old = $this->param->find($id);
|
|
||||||
$isManual = $old->guru_nip !== $data['guru_nip'];
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
// Audit log
|
|
||||||
AuditLog::create([
|
|
||||||
'user_id' => Auth::id(),
|
|
||||||
'action' => 'update_pengampu_mapel',
|
|
||||||
'description' => 'Update pengampu mapel: ' . $old->nama . ' (' . $old->id . ') dari ' . $old->guru_nip . ' ke ' . $data['guru_nip'],
|
|
||||||
]);
|
|
||||||
if ($isManual) {
|
|
||||||
Alert::warning('Perhatian', 'Anda mengganti pengampu mata pelajaran tanpa fitur pemindahan data. Data tugas dan submit tugas lama tetap milik guru sebelumnya.');
|
|
||||||
} else {
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Ubah.");
|
|
||||||
}
|
|
||||||
return redirect()->route("mata-pelajaran");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,232 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\Materi;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Repositories\MateriRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class MateriController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(MateriRepository $materi)
|
|
||||||
{
|
|
||||||
$this->param = $materi;
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$materi = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_guru.materi.index", compact("materi"));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function detail($id)
|
|
||||||
{
|
|
||||||
$materiDetail = Materi::find($id);
|
|
||||||
return view("pages.role_guru.materi.detail", compact("materiDetail"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
$matpel = MataPelajaran::where('guru_nip', Auth::user()->guru->nip)->get();
|
|
||||||
return view("pages.role_guru.materi.create", compact('matpel', 'tahunAjaran'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$tanggal = $request->input('tanggal');
|
|
||||||
$guruNip = $request->user()->guru->nip;
|
|
||||||
|
|
||||||
// dd($request->file('path'));
|
|
||||||
|
|
||||||
if ($request->type == "buku") {
|
|
||||||
// Validasi untuk buku (file PDF)
|
|
||||||
$validated = $request->validate([
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'semester' => 'required',
|
|
||||||
'type' => 'required',
|
|
||||||
'judul_materi' => 'required',
|
|
||||||
'deskripsi' => 'required',
|
|
||||||
'path' => 'required|file|mimes:pdf|max:5120',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$judul = Str::slug(Str::limit($request->judul_materi, 50));
|
|
||||||
$ext = $request->file('path')->getClientOriginalExtension();
|
|
||||||
$namaFile = "{$guruNip}_{$tanggal}_{$judul}.{$ext}";
|
|
||||||
|
|
||||||
$path = $request->file('path')->storeAs('materi', $namaFile, 'public');
|
|
||||||
$validated['path'] = $path;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// Validasi untuk video (link video)
|
|
||||||
$validated = $request->validate([
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'semester' => 'required',
|
|
||||||
'type' => 'required',
|
|
||||||
'judul_materi' => 'required',
|
|
||||||
'deskripsi' => 'required',
|
|
||||||
'path' => 'required|string', // path link video
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$validated['tanggal'] = $tanggal;
|
|
||||||
|
|
||||||
$this->param->store($validated);
|
|
||||||
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("materi");
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
if ($e instanceof \Illuminate\Validation\ValidationException) {
|
|
||||||
$errors = $e->validator->errors()->all();
|
|
||||||
Alert::error("Validasi Gagal", implode("\n", $errors));
|
|
||||||
} else {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
}
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
$matpel = MataPelajaran::where('guru_nip', Auth::user()->guru->nip)->get();
|
|
||||||
$materi = $this->param->find($id);
|
|
||||||
return view("pages.role_guru.materi.edit", compact(["tahunAjaran", "matpel", "materi"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$tanggal = $request->input('tanggal');
|
|
||||||
$guruNip = $request->user()->guru->nip;
|
|
||||||
|
|
||||||
$materi = $this->param->find($id);
|
|
||||||
|
|
||||||
if (!$materi) {
|
|
||||||
Alert::error("Tidak ditemukan", "Data materi tidak ditemukan.");
|
|
||||||
return redirect()->route("materi");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->type == "buku") {
|
|
||||||
$validated = $request->validate([
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'semester' => 'required',
|
|
||||||
'type' => 'required',
|
|
||||||
'judul_materi' => 'required',
|
|
||||||
'deskripsi' => 'required',
|
|
||||||
'path' => 'nullable|file|mimes:pdf|max:5120', // Boleh kosong saat update
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Jika ada file baru diunggah
|
|
||||||
if ($request->hasFile('path')) {
|
|
||||||
// Hapus file lama jika ada
|
|
||||||
if ($materi->path && Storage::disk('public')->exists($materi->path)) {
|
|
||||||
Storage::disk('public')->delete($materi->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
$judul = Str::slug(Str::limit($request->judul_materi, 50));
|
|
||||||
$ext = $request->file('path')->getClientOriginalExtension();
|
|
||||||
$namaFile = "{$guruNip}_{$tanggal}_{$judul}.{$ext}";
|
|
||||||
|
|
||||||
$path = $request->file('path')->storeAs('materi', $namaFile, 'public');
|
|
||||||
$validated['path'] = $path;
|
|
||||||
} else {
|
|
||||||
$validated['path'] = $materi->path;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
$validated = $request->validate([
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'semester' => 'required',
|
|
||||||
'type' => 'required',
|
|
||||||
'judul_materi' => 'required',
|
|
||||||
'deskripsi' => 'required',
|
|
||||||
'path' => 'required|string', // Link video
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
$validated['tanggal'] = $tanggal;
|
|
||||||
|
|
||||||
$this->param->update($validated, $id);
|
|
||||||
|
|
||||||
Alert::success("Berhasil", "Data berhasil diperbarui.");
|
|
||||||
return redirect()->route("materi");
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
if ($e instanceof \Illuminate\Validation\ValidationException) {
|
|
||||||
$errors = $e->validator->errors()->all();
|
|
||||||
Alert::error("Validasi Gagal", implode("\n", $errors));
|
|
||||||
} else {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
}
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$materi = $this->param->find($request->formid);
|
|
||||||
|
|
||||||
if ($materi->type === 'buku' && $materi->path) {
|
|
||||||
// Hapus file PDF dari storage/public/materi
|
|
||||||
Storage::disk('public')->delete($materi->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->param->destroy($materi->id);
|
|
||||||
Alert::success("Berhasil", "Data berhasil dihapus.");
|
|
||||||
return redirect()->route("materi"); // sesuaikan dengan route kamu
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,503 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Exports\QuizExport;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use App\Models\QuizQuestions;
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Notifications\QuizBaruNotification;
|
|
||||||
use App\Repositories\QuizRepository;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\Session;
|
|
||||||
use Maatwebsite\Excel\Concerns\FromView;
|
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class QuizController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(QuizRepository $quiz)
|
|
||||||
{
|
|
||||||
$this->param = $quiz;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$nip = Auth::user()->guru->nip;
|
|
||||||
$matpel = MataPelajaran::where('guru_nip', $nip)->get();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
|
|
||||||
// Get quizzes created by this teacher
|
|
||||||
$quiz = Quizzes::with(['mataPelajaran', 'quizLevelSetting'])
|
|
||||||
->whereHas('mataPelajaran', function ($q) use ($nip) {
|
|
||||||
$q->where('guru_nip', $nip);
|
|
||||||
})
|
|
||||||
->orderBy('created_at', 'desc')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return view("pages.role_guru.quiz.index", compact(['matpel', 'kelas', 'tahunAjaran', 'quiz']));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getQuizByMatpel($id)
|
|
||||||
{
|
|
||||||
$nip = Auth::user()->guru->nip;
|
|
||||||
$quizzes = Quizzes::where('matapelajaran_id', $id)
|
|
||||||
->whereHas('mataPelajaran', function ($q) use ($nip) {
|
|
||||||
$q->where('guru_nip', $nip);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return response()->json($quizzes);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public function excelDownload()
|
|
||||||
{
|
|
||||||
return Excel::download(new QuizExport, "format_excel_untuk_quiz.xlsx");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function preview(Request $request)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'file' => 'required|mimes:xlsx,xls'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = Excel::toArray([], $request->file('file'));
|
|
||||||
|
|
||||||
// Ambil sheet pertama
|
|
||||||
$rows = $data[0];
|
|
||||||
|
|
||||||
$filteredRows = [];
|
|
||||||
$jumlahSoalPerLevel = [];
|
|
||||||
$totalSoalPeLevel = [];
|
|
||||||
$batasNaikLevel = [];
|
|
||||||
$skorLevel = [];
|
|
||||||
|
|
||||||
foreach ($rows as $index => $row) {
|
|
||||||
if ($index == 0 || !empty($row[1])) {
|
|
||||||
$filteredRows[] = $row;
|
|
||||||
|
|
||||||
$level = $row[3];
|
|
||||||
$skor = $row[8];
|
|
||||||
if (!empty($level) && $index != 0) {
|
|
||||||
$key = 'level' . $level;
|
|
||||||
if (!isset($jumlahSoalPerLevel[$key])) {
|
|
||||||
$jumlahSoalPerLevel[$key] = 0;
|
|
||||||
$totalSoalPeLevel[$key] = 0;
|
|
||||||
}
|
|
||||||
$jumlahSoalPerLevel[$key]++;
|
|
||||||
$totalSoalPeLevel[$key]++;
|
|
||||||
$skorLevel[$key] = $skor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hitung batas naik level = 50% dari jumlah soal di level tersebut
|
|
||||||
foreach ($jumlahSoalPerLevel as $key => $jumlah) {
|
|
||||||
// Ambil level dari key, contoh: 'level2' → 2
|
|
||||||
$level = str_replace('level', '', $key);
|
|
||||||
$keyFase = 'fase' . $level;
|
|
||||||
|
|
||||||
// Hitung 50% lalu dibulatkan ke atas (ceil)
|
|
||||||
$batasNaikLevel[$keyFase] = (int) ceil($jumlah * 0.5);
|
|
||||||
|
|
||||||
$jumlahSoalPerLevel[$key] = (int) ceil($jumlah * 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$soalCount = count($filteredRows) - 1;
|
|
||||||
|
|
||||||
// Simpan preview dan jumlah soal ke session
|
|
||||||
Session::put('judul', $request->judul);
|
|
||||||
Session::put('deskripsi', $request->deskripsi);
|
|
||||||
Session::put('matapelajaran_id', $request->matapelajaran_id);
|
|
||||||
Session::put('waktu', $request->waktu);
|
|
||||||
Session::put('preview_soal', $filteredRows);
|
|
||||||
Session::put('total_soal', $soalCount);
|
|
||||||
Session::put('total_soal_tampil', $request->total_soal_tampil ?? 20);
|
|
||||||
Session::put('uploaded_filename', $request->file('file')->getClientOriginalName());
|
|
||||||
|
|
||||||
// quiz level settings
|
|
||||||
Session::put('total_soal_per_level', $totalSoalPeLevel);
|
|
||||||
Session::put('jumlah_soal_per_level', $jumlahSoalPerLevel);
|
|
||||||
Session::put('level_awal', $request->level_awal);
|
|
||||||
Session::put('batas_naik_level', $batasNaikLevel);
|
|
||||||
Session::put('skor_level', $skorLevel);
|
|
||||||
Session::put('kkm', $request->kkm);
|
|
||||||
|
|
||||||
return redirect()->back();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function removeSession()
|
|
||||||
{
|
|
||||||
session()->forget('judul');
|
|
||||||
session()->forget('deskripsi');
|
|
||||||
session()->forget('matapelajaran_id');
|
|
||||||
session()->forget('waktu');
|
|
||||||
session()->forget('preview_soal');
|
|
||||||
session()->forget('total_soal');
|
|
||||||
session()->forget('total_soal_tampil');
|
|
||||||
session()->forget('uploaded_filename');
|
|
||||||
|
|
||||||
// quiz level settings
|
|
||||||
session()->forget('total_soal_per_level');
|
|
||||||
session()->forget('jumlah_soal_per_level');
|
|
||||||
session()->forget('level_awal');
|
|
||||||
session()->forget('batas_naik_level');
|
|
||||||
session()->forget('skor_level');
|
|
||||||
session()->forget('kkm');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function resetPreview()
|
|
||||||
{
|
|
||||||
$this->removeSession();
|
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Data preview berhasil direset.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$nip = Auth::user()->guru->nip;
|
|
||||||
$matpel = MataPelajaran::where("guru_nip", $nip)->get();
|
|
||||||
$naik_level = json_encode(session('batas_naik_level') ?? []);
|
|
||||||
return view("pages.role_guru.quiz.create", compact(['matpel', 'naik_level']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
$preview = session('preview_soal');
|
|
||||||
if (!is_array($preview)) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error',
|
|
||||||
'message' => 'Data soal tidak ditemukan atau session sudah habis. Silakan ulangi proses import/preview quiz.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
array_shift($preview);
|
|
||||||
|
|
||||||
if (!$preview || count($preview) <= 1) {
|
|
||||||
\Log::error('Quiz Import Error: Tidak ada data untuk disimpan');
|
|
||||||
Alert::error("Terjadi Kesalahan", "Tidak ada data untuk disimpan.");
|
|
||||||
return redirect()->back();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->total_soal_tampil < 10) {
|
|
||||||
\Log::error('Quiz Import Error: Jumlah soal minimal 10');
|
|
||||||
Alert::error("Terjadi Kesalahan", "Jumlah soal minimal 10.");
|
|
||||||
return redirect()->back();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// VALIDASI KETAT UNTUK MENCEGAH BUG QUIZ
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
// 1. VALIDASI: Total soal per level harus sama dengan total soal tampil
|
|
||||||
$totalSoalPerLevel = 0;
|
|
||||||
foreach ($request->jumlah_soal_per_level as $key => $value) {
|
|
||||||
$totalSoalPerLevel += (int) $value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($totalSoalPerLevel != $request->total_soal_tampil) {
|
|
||||||
\Log::error('Quiz Import Error: Total soal per level tidak sama dengan total soal tampil');
|
|
||||||
\Log::error('Detail: Total soal per level = ' . $totalSoalPerLevel . ', Total soal tampil = ' . $request->total_soal_tampil);
|
|
||||||
\Log::error('Detail per level: ' . json_encode($request->jumlah_soal_per_level));
|
|
||||||
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Total soal per level ($totalSoalPerLevel) harus sama dengan total soal tampil ({$request->total_soal_tampil}).<br><br><strong>POTENSI BUG:</strong> Jika tidak sama, siswa bisa stuck di level tertentu karena soal tidak cukup.<br><strong>CATATAN:</strong> Pastikan jumlah soal per level dijumlahkan sama dengan total soal tampil."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. VALIDASI: Hitung jumlah soal yang tersedia per level dari data import
|
|
||||||
$levelCounts = [];
|
|
||||||
foreach ($preview as $row) {
|
|
||||||
if (!empty($row[3])) { // level
|
|
||||||
$level = $row[3];
|
|
||||||
$levelCounts[$level] = ($levelCounts[$level] ?? 0) + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. VALIDASI: Jumlah soal per level tidak boleh melebihi soal yang tersedia
|
|
||||||
foreach ($request->jumlah_soal_per_level as $key => $value) {
|
|
||||||
$level = str_replace('level', '', $key);
|
|
||||||
$availableInLevel = $levelCounts[$level] ?? 0;
|
|
||||||
|
|
||||||
if ($value > $availableInLevel) {
|
|
||||||
\Log::error('Quiz Import Error: Jumlah soal setting melebihi soal yang tersedia');
|
|
||||||
\Log::error('Detail: Level ' . $level . ' - Setting: ' . $value . ', Tersedia: ' . $availableInLevel);
|
|
||||||
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Setting $value soal, tapi hanya ada $availableInLevel soal tersedia.<br><br><strong>POTENSI BUG:</strong> Sistem akan stuck karena tidak ada cukup soal di level tersebut.<br><strong>CATATAN:</strong> Kurangi jumlah soal setting atau tambah soal di level tersebut."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. VALIDASI: Batas naik level tidak boleh melebihi jumlah soal di level tersebut
|
|
||||||
foreach ($request->batas_naik_level as $key => $value) {
|
|
||||||
$level = str_replace('fase', '', $key);
|
|
||||||
$soalInLevel = $request->jumlah_soal_per_level["level$level"] ?? 0;
|
|
||||||
|
|
||||||
// VALIDASI BARU: Batas naik level tidak boleh sama atau lebih besar dari jumlah soal di level
|
|
||||||
if ($value >= $soalInLevel) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Syarat naik level ($value) tidak boleh sama atau lebih besar dari jumlah soal ($soalInLevel).<br><br><strong>POTENSI BUG:</strong> Jika siswa salah satu saja, quiz akan stuck di level ini.<br><strong>CATATAN:</strong> Kurangi syarat naik level atau tambah jumlah soal di level ini."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($value > $soalInLevel) {
|
|
||||||
\Log::error('Quiz Import Error: Batas naik level melebihi jumlah soal di level');
|
|
||||||
\Log::error('Detail: Level ' . $level . ' - Batas naik: ' . $value . ', Soal di level: ' . $soalInLevel);
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Batas naik level ($value) tidak boleh melebihi jumlah soal ($soalInLevel).<br><br><strong>POTENSI BUG:</strong> Siswa tidak akan pernah naik level karena batas terlalu tinggi.<br><strong>CATATAN:</strong> Batas naik level harus ≤ jumlah soal di level tersebut."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. VALIDASI: Pastikan ada soal di setiap level yang di-setting
|
|
||||||
foreach ($request->jumlah_soal_per_level as $key => $value) {
|
|
||||||
$level = str_replace('level', '', $key);
|
|
||||||
$availableInLevel = $levelCounts[$level] ?? 0;
|
|
||||||
|
|
||||||
if ($availableInLevel == 0) {
|
|
||||||
\Log::error('Quiz Import Error: Tidak ada soal di level yang di-setting');
|
|
||||||
\Log::error('Detail: Level ' . $level . ' tidak memiliki soal di data import');
|
|
||||||
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Tidak ada soal tersedia di level ini.<br><br><strong>POTENSI BUG:</strong> Sistem akan stuck karena tidak ada soal di level tersebut.<br><strong>CATATAN:</strong> Pastikan data import memiliki soal dengan level $level atau hapus setting level ini."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. VALIDASI: Level harus berurutan (1, 2, 3, dst)
|
|
||||||
$levels = array_keys($request->jumlah_soal_per_level);
|
|
||||||
sort($levels);
|
|
||||||
$expectedLevels = [];
|
|
||||||
for ($i = 1; $i <= count($levels); $i++) {
|
|
||||||
$expectedLevels[] = "level$i";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($levels !== $expectedLevels) {
|
|
||||||
\Log::error('Quiz Import Error: Level tidak berurutan');
|
|
||||||
\Log::error('Detail: Level yang ada = ' . json_encode($levels) . ', Level yang diharapkan = ' . json_encode($expectedLevels));
|
|
||||||
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level harus berurutan (Level 1, Level 2, Level 3, dst).<br><br><strong>POTENSI BUG:</strong> Sistem adaptive learning akan bingung dengan level yang tidak berurutan.<br><strong>CATATAN:</strong> Pastikan level di data import berurutan dari 1, 2, 3, dst."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update session dengan nilai total_soal_tampil yang baru
|
|
||||||
Session::put('total_soal_tampil', $request->total_soal_tampil);
|
|
||||||
|
|
||||||
// VALIDASI: Jumlah soal yang harus dikerjakan per level tidak boleh melebihi jumlah soal di bank soal
|
|
||||||
$totalSoalPerLevel = 0;
|
|
||||||
foreach ($request->jumlah_soal_per_level as $key => $value) {
|
|
||||||
$level = str_replace('level', '', $key);
|
|
||||||
$soalTersedia = $request->total_soal_per_level["level$level"] ?? 0;
|
|
||||||
if ($value > $soalTersedia) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Jumlah soal yang dikerjakan ($value) tidak boleh lebih besar dari jumlah soal di bank soal ($soalTersedia)."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$totalSoalPerLevel += (int) $value;
|
|
||||||
}
|
|
||||||
// VALIDASI: Total soal yang harus dikerjakan (semua level) harus sama dengan total soal tampil
|
|
||||||
if ($totalSoalPerLevel != $request->total_soal_tampil) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Total soal yang harus dikerjakan ($totalSoalPerLevel) tidak sama dengan total soal tampil ({$request->total_soal_tampil}).<br><br><strong>POTENSI BUG:</strong> Quiz bisa stuck atau soal tidak cukup.<br><strong>CATATAN:</strong> Sesuaikan jumlah soal per level agar totalnya sama dengan total soal tampil."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// VALIDASI: Cegah quiz stuck jika syarat naik level tidak tercapai dan soal habis
|
|
||||||
foreach ($request->batas_naik_level as $key => $value) {
|
|
||||||
$level = str_replace('fase', '', $key);
|
|
||||||
$jumlah_soal = $request->jumlah_soal_per_level["level$level"] ?? 0;
|
|
||||||
$batas_naik = $value;
|
|
||||||
// Jika syarat naik lebih besar dari jumlah soal, mustahil
|
|
||||||
if ($batas_naik > $jumlah_soal) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Error Validasi',
|
|
||||||
'message' => "Level $level: Syarat naik level ($batas_naik) tidak boleh lebih besar dari jumlah soal yang dikerjakan ($jumlah_soal)."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
// Jika syarat naik level terlalu rendah, tetap valid, tapi cek kemungkinan stuck
|
|
||||||
// Simulasi: Jika siswa menjawab semua soal tapi benar kurang dari syarat naik, quiz stuck
|
|
||||||
// Contoh: syarat naik 3 dari 10, jika siswa hanya benar 2, quiz stuck
|
|
||||||
// Validasi: syarat naik level harus bisa dicapai dengan minimal 1 benar di setiap soal
|
|
||||||
// (tidak perlu, karena sudah dicegah oleh logika di atas)
|
|
||||||
// Namun, jika syarat naik terlalu rendah, warning saja (tidak error)
|
|
||||||
// Jika syarat naik terlalu tinggi, error
|
|
||||||
// Jika syarat naik level tidak tercapai dan soal habis, quiz stuck
|
|
||||||
// (Sudah dicegah oleh validasi di atas)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VALIDASI: Cegah quiz stuck jika siswa gagal naik level dan soal habis
|
|
||||||
/*
|
|
||||||
$levelKeys = array_keys($request->jumlah_soal_per_level);
|
|
||||||
$levelCount = count($levelKeys);
|
|
||||||
for ($i = 0; $i < $levelCount - 1; $i++) { // Kecuali level terakhir
|
|
||||||
$currentLevelKey = $levelKeys[$i];
|
|
||||||
$nextLevelKeys = array_slice($levelKeys, $i + 1);
|
|
||||||
$soalDiLevelIni = (int) $request->jumlah_soal_per_level[$currentLevelKey];
|
|
||||||
$soalDiLevelBerikutnya = 0;
|
|
||||||
foreach ($nextLevelKeys as $k) {
|
|
||||||
$soalDiLevelBerikutnya += (int) $request->jumlah_soal_per_level[$k];
|
|
||||||
}
|
|
||||||
$totalSoalTampil = (int) $request->total_soal_tampil;
|
|
||||||
$batasNaik = (int) ($request->batas_naik_level['fase' . ($i + 1)] ?? 0);
|
|
||||||
// Jika semua soal di level ini habis, dan siswa gagal naik (benar < batas naik), quiz stuck
|
|
||||||
// Kondisi: soal di level ini = total soal tampil - soal di level berikutnya
|
|
||||||
if ($soalDiLevelIni === $totalSoalTampil - $soalDiLevelBerikutnya && $soalDiLevelIni > 0 && $batasNaik > 0) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Konfigurasi Quiz Tidak Valid',
|
|
||||||
'message' => "Quiz tidak bisa disimpan karena pada fase " . ($i + 1) . ", siswa yang gagal naik ke level berikutnya akan kehabisan soal. Mohon ulangi konfigurasi quiz agar lebih seimbang dan baik."
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Simpan quiz dan soalnya ke DB
|
|
||||||
$quiz = Quizzes::create([
|
|
||||||
'judul' => $request->judul,
|
|
||||||
'deskripsi' => $request->deskripsi,
|
|
||||||
'matapelajaran_id' => $request->matapelajaran_id,
|
|
||||||
'total_soal' => $request->total_soal,
|
|
||||||
'total_soal_tampil' => $request->total_soal_tampil,
|
|
||||||
'waktu' => $request->waktu,
|
|
||||||
]);
|
|
||||||
|
|
||||||
QuizLevelSetting::create([
|
|
||||||
'quiz_id' => $quiz->id,
|
|
||||||
'jumlah_soal_per_level' => json_encode($request->jumlah_soal_per_level),
|
|
||||||
'level_awal' => session('level_awal') ?? 1,
|
|
||||||
'batas_naik_level' => json_encode($request->batas_naik_level),
|
|
||||||
'skor_level' => json_encode(session('skor_level')),
|
|
||||||
'kkm' => session('kkm') ?? 75,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Menampung data dalam array sebelum disimpan
|
|
||||||
$quizQuestionsData = [];
|
|
||||||
|
|
||||||
foreach ($preview as $row) {
|
|
||||||
$jawabanBenar = strtolower(trim($row[2]));
|
|
||||||
// Menyiapkan data untuk disimpan
|
|
||||||
$quizQuestionsData[] = [
|
|
||||||
'quiz_id' => $quiz->id,
|
|
||||||
'pertanyaan' => $row[1],
|
|
||||||
'opsi_a' => $row[4],
|
|
||||||
'opsi_b' => $row[5],
|
|
||||||
'opsi_c' => $row[6],
|
|
||||||
'opsi_d' => $row[7],
|
|
||||||
'jawaban_benar' => $jawabanBenar,
|
|
||||||
'level' => $row[3],
|
|
||||||
'skor' => $row[8],
|
|
||||||
'created_at' => now(),
|
|
||||||
'updated_at' => now(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simpan semua data sekali gus menggunakan insert
|
|
||||||
if (!empty($quizQuestionsData)) {
|
|
||||||
QuizQuestions::insert($quizQuestionsData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hapus session
|
|
||||||
$this->removeSession();
|
|
||||||
|
|
||||||
$matpel = MataPelajaran::findOrFail($request->matapelajaran_id);
|
|
||||||
// Cari siswa berdasarkan kelas dan tahun ajaran
|
|
||||||
$siswas = Siswa::where('kelas', $matpel['kelas'])
|
|
||||||
->where('tahun_ajaran', $matpel['tahun_ajaran'])
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Kirim notifikasi ke setiap siswa
|
|
||||||
foreach ($siswas as $siswa) {
|
|
||||||
$siswa->notify(new QuizBaruNotification($quiz));
|
|
||||||
}
|
|
||||||
|
|
||||||
\Log::info('Quiz berhasil diimport: ' . $request->judul);
|
|
||||||
return redirect()->route('quiz')->with('success_message', [
|
|
||||||
'title' => 'Berhasil',
|
|
||||||
'message' => 'Data quiz berhasil disimpan dan notifikasi telah dikirim ke siswa.'
|
|
||||||
]);
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
\Log::error('Quiz Import Error: ' . $e->getMessage());
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Terjadi Kesalahan',
|
|
||||||
'message' => 'Gagal menyimpan data quiz: ' . $e->getMessage()
|
|
||||||
]);
|
|
||||||
} catch (\Illuminate\Database\QueryException $e) {
|
|
||||||
\Log::error('Quiz Import Error: Database error - ' . $e->getMessage());
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Terjadi Kesalahan',
|
|
||||||
'message' => 'Gagal menyimpan data quiz. Silakan coba lagi.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$quiz = Quizzes::findOrFail($request->formid);
|
|
||||||
$quiz->delete();
|
|
||||||
return redirect()->back()->with('success_message', [
|
|
||||||
'title' => 'Berhasil',
|
|
||||||
'message' => 'Data quiz berhasil dihapus.'
|
|
||||||
]);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
return redirect()->back()->with('validation_error', [
|
|
||||||
'title' => 'Terjadi Kesalahan',
|
|
||||||
'message' => 'Gagal menghapus data quiz: ' . $th->getMessage()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class QuizRankingController extends Controller
|
|
||||||
{
|
|
||||||
// GET /quiz/{quizId}/ranking
|
|
||||||
public function ranking($quizId)
|
|
||||||
{
|
|
||||||
// Ambil attempt terbaru per siswa untuk quiz ini
|
|
||||||
$latestAttempts = QuizAttempts::where('quiz_id', $quizId)
|
|
||||||
->selectRaw('MAX(id) as id')
|
|
||||||
->groupBy('nisn')
|
|
||||||
->pluck('id');
|
|
||||||
|
|
||||||
$ranking = QuizAttempts::with('siswa')
|
|
||||||
->whereIn('id', $latestAttempts)
|
|
||||||
->get()
|
|
||||||
->map(function($attempt) {
|
|
||||||
return [
|
|
||||||
'nama' => $attempt->siswa->nama ?? '-',
|
|
||||||
'nisn' => $attempt->nisn,
|
|
||||||
'skor' => (int) $attempt->skor,
|
|
||||||
'waktu_selesai' => $attempt->updated_at,
|
|
||||||
];
|
|
||||||
})
|
|
||||||
->sortByDesc('skor')
|
|
||||||
->values()
|
|
||||||
->take(5);
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'success' => true,
|
|
||||||
'ranking' => $ranking
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET /quiz/{quizId}/skor-saya
|
|
||||||
public function skorSaya($quizId)
|
|
||||||
{
|
|
||||||
$nisn = auth()->user()->siswa->nisn ?? null;
|
|
||||||
if (!$nisn) {
|
|
||||||
return response()->json(['success' => false, 'message' => 'User bukan siswa.']);
|
|
||||||
}
|
|
||||||
$attempt = QuizAttempts::where('quiz_id', $quizId)
|
|
||||||
->where('nisn', $nisn)
|
|
||||||
->orderByDesc('id')
|
|
||||||
->first();
|
|
||||||
if (!$attempt) {
|
|
||||||
return response()->json(['success' => false, 'message' => 'Belum ada attempt.']);
|
|
||||||
}
|
|
||||||
return response()->json([
|
|
||||||
'success' => true,
|
|
||||||
'skor' => $attempt->skor,
|
|
||||||
'waktu_selesai' => $attempt->updated_at,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Exports\RekapExport;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
|
||||||
|
|
||||||
class RekapQuizController extends Controller
|
|
||||||
{
|
|
||||||
static function getNilai($first)
|
|
||||||
{
|
|
||||||
$quizId = $first->quiz_id;
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $quizId)->first();
|
|
||||||
$jumlahSoalPerLevel = json_decode($quizLevelSettings->jumlah_soal_per_level, true);
|
|
||||||
$totalSkorLevel = 0;
|
|
||||||
|
|
||||||
foreach (json_decode($quizLevelSettings->skor_level) as $key => $value) {
|
|
||||||
$totalSkorLevel += $value * (int) $jumlahSoalPerLevel[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
"total_skor_level" => $totalSkorLevel,
|
|
||||||
"kkm" => $quizLevelSettings->kkm,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$nip = Auth::user()->guru->nip;
|
|
||||||
$matpel = MataPelajaran::where('guru_nip', $nip)->get();
|
|
||||||
$judulQuiz = Quizzes::where('judul', $request->judul)->first();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
|
|
||||||
$query = QuizAttempts::with(['quizzes', 'siswa'])
|
|
||||||
->whereHas('quizzes', function ($q) use ($request) {
|
|
||||||
$q->where('judul', $request->judul);
|
|
||||||
})->whereHas('siswa', function ($q) use ($request) {
|
|
||||||
$q->where('kelas', $request->kelas)
|
|
||||||
->where('tahun_ajaran', $request->tahun_ajaran);
|
|
||||||
})->get();
|
|
||||||
|
|
||||||
$rekap = $query->map(function ($item) use ($request) {
|
|
||||||
$nilaiData = $this->getNilai($item);
|
|
||||||
|
|
||||||
return [
|
|
||||||
'matapelajaran' => $item->quizzes->mataPelajaran->nama,
|
|
||||||
'judul_quiz' => $item->quizzes->judul,
|
|
||||||
'nama_siswa' => $item->siswa->nama,
|
|
||||||
'tahun_ajaran' => $request->tahun_ajaran,
|
|
||||||
'kelas' => $request->kelas,
|
|
||||||
'mapel_id' => $item->quizzes->mataPelajaran->id,
|
|
||||||
'total_skor' => $item->skor,
|
|
||||||
'persentase' => round(($item->skor / $nilaiData['total_skor_level']) * 100),
|
|
||||||
'kkm' => $nilaiData['kkm'],
|
|
||||||
];
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($request->input('action') === 'download') {
|
|
||||||
return Excel::download(new RekapExport($rekap), 'rekap-quiz' . $request->kelas . '.xlsx');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert $rekap to array to prevent automatic JSON conversion
|
|
||||||
$rekapArray = $rekap->toArray();
|
|
||||||
return view("pages.role_guru.quiz.rekap-quiz", compact(['matpel', 'judulQuiz', 'kelas', 'tahunAjaran', 'rekapArray']));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Exports\TugasDetailExport;
|
|
||||||
use App\Exports\TugasExport;
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\SubmitTugas;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class RekapTugasController extends Controller
|
|
||||||
{
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$guruNip = Auth::user()->guru->nip;
|
|
||||||
|
|
||||||
// Get mata pelajaran yang diajar oleh guru
|
|
||||||
$mataPelajaran = MataPelajaran::where('guru_nip', $guruNip)->get();
|
|
||||||
|
|
||||||
// Get kelas yang diajar oleh guru
|
|
||||||
$kelasList = Kelas::whereIn('nama', $mataPelajaran->pluck('kelas'))->get();
|
|
||||||
|
|
||||||
// Filter parameters
|
|
||||||
$selectedKelas = $request->get('kelas');
|
|
||||||
$selectedMatpel = $request->get('matpel');
|
|
||||||
$search = $request->get('search');
|
|
||||||
|
|
||||||
// Query untuk mendapatkan tugas yang dibuat oleh guru
|
|
||||||
$query = Tugas::with(['mataPelajaran', 'submitTugas.siswa'])
|
|
||||||
->where('guru_nip', $guruNip);
|
|
||||||
|
|
||||||
// Apply filters
|
|
||||||
if ($selectedKelas) {
|
|
||||||
$query->where('kelas', $selectedKelas);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($selectedMatpel) {
|
|
||||||
$query->where('matapelajaran_id', $selectedMatpel);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($search) {
|
|
||||||
$query->where('nama', 'like', '%' . $search . '%');
|
|
||||||
}
|
|
||||||
|
|
||||||
$tugas = $query->orderBy('created_at', 'desc')->paginate(10);
|
|
||||||
|
|
||||||
// Ensure submitTugas is always a collection
|
|
||||||
$tugas->getCollection()->transform(function ($t) {
|
|
||||||
if (!$t->submitTugas) {
|
|
||||||
$t->setRelation('submitTugas', collect());
|
|
||||||
}
|
|
||||||
return $t;
|
|
||||||
});
|
|
||||||
|
|
||||||
return view('pages.role_guru.rekap_tugas.index', compact(
|
|
||||||
'tugas',
|
|
||||||
'kelasList',
|
|
||||||
'mataPelajaran',
|
|
||||||
'selectedKelas',
|
|
||||||
'selectedMatpel',
|
|
||||||
'search'
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function detail($id)
|
|
||||||
{
|
|
||||||
$tugas = Tugas::with(['mataPelajaran', 'submitTugas.siswa'])
|
|
||||||
->where('guru_nip', Auth::user()->guru->nip)
|
|
||||||
->findOrFail($id);
|
|
||||||
|
|
||||||
$submitTugas = SubmitTugas::with('siswa')
|
|
||||||
->where('tugas_id', $id)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return view('pages.role_guru.rekap_tugas.detail', compact('tugas', 'submitTugas'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updateNilai(Request $request, $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request->validate([
|
|
||||||
'nilai' => 'required|numeric|min:0|max:100'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$submitTugas = SubmitTugas::findOrFail($id);
|
|
||||||
|
|
||||||
// Check if the task belongs to the teacher
|
|
||||||
$tugas = Tugas::where('id', $submitTugas->tugas_id)
|
|
||||||
->where('guru_nip', Auth::user()->guru->nip)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if (!$tugas) {
|
|
||||||
if ($request->ajax()) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'Anda tidak memiliki akses untuk menilai tugas ini.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
Alert::error("Error", "Anda tidak memiliki akses untuk menilai tugas ini.");
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
|
|
||||||
$submitTugas->update([
|
|
||||||
'nilai' => $request->nilai
|
|
||||||
]);
|
|
||||||
|
|
||||||
if ($request->ajax()) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => true,
|
|
||||||
'message' => 'Nilai berhasil diperbarui.'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Alert::success("Berhasil", "Nilai berhasil diperbarui.");
|
|
||||||
return back();
|
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
if ($request->ajax()) {
|
|
||||||
return response()->json([
|
|
||||||
'success' => false,
|
|
||||||
'message' => 'Terjadi kesalahan: ' . $e->getMessage()
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Alert::error("Error", "Terjadi kesalahan: " . $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function export(Request $request)
|
|
||||||
{
|
|
||||||
$selectedKelas = $request->get('kelas');
|
|
||||||
$selectedMatpel = $request->get('matpel');
|
|
||||||
|
|
||||||
$filename = 'rekap_tugas_' . date('Y-m-d_H-i-s') . '.xlsx';
|
|
||||||
|
|
||||||
return Excel::download(
|
|
||||||
new TugasExport($selectedKelas, $selectedMatpel),
|
|
||||||
$filename
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function exportDetail(Request $request)
|
|
||||||
{
|
|
||||||
$selectedKelas = $request->get('kelas');
|
|
||||||
$selectedMatpel = $request->get('matpel');
|
|
||||||
|
|
||||||
$filename = 'detail_tugas_' . date('Y-m-d_H-i-s') . '.xlsx';
|
|
||||||
|
|
||||||
return Excel::download(
|
|
||||||
new TugasDetailExport($selectedKelas, $selectedMatpel),
|
|
||||||
$filename
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,154 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\RoleGuru;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Controller;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use App\Repositories\TugasRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class TugasController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(TugasRepository $tugas)
|
|
||||||
{
|
|
||||||
$this->param = $tugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dateFormat($date)
|
|
||||||
{
|
|
||||||
return date('Y-m-d H:i:s', strtotime($date));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dataRequirement()
|
|
||||||
{
|
|
||||||
$mataPelajaran = MataPelajaran::where('guru_nip', Auth::user()->guru->nip)->get();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
|
|
||||||
return [$mataPelajaran, $kelas, $tahunAjaran];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$tugas = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_guru.tugas.index", compact("tugas"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$mataPelajaran = MataPelajaran::where('guru_nip', Auth::user()->guru->nip)->get();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view("pages.role_guru.tugas.create", compact(["mataPelajaran", "kelas", "tahunAjaran"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request['tanggal'] = $this->dateFormat($request->input('tanggal'));
|
|
||||||
$request['tenggat'] = $this->dateFormat($request->input('tenggat'));
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'tanggal' => 'required',
|
|
||||||
'tenggat' => 'required',
|
|
||||||
'nama' => 'required',
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
'deskripsi' => 'nullable|string',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("tugas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$tugas = $this->param->find($id);
|
|
||||||
$mataPelajaran = MataPelajaran::where('guru_nip', Auth::user()->guru->nip)->get();
|
|
||||||
$kelas = Kelas::all();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view("pages.role_guru.tugas.edit", compact(["tugas", "mataPelajaran", "kelas", "tahunAjaran"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request['tanggal'] = $this->dateFormat($request->input('tanggal'));
|
|
||||||
$request['tenggat'] = $this->dateFormat($request->input('tenggat'));
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'tanggal' => 'required',
|
|
||||||
'tenggat' => 'required',
|
|
||||||
'nama' => 'required',
|
|
||||||
'matapelajaran_id' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
'deskripsi' => 'nullable|string',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
return redirect()->route("tugas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$this->param->destroy($request->formid);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di hapus.");
|
|
||||||
return redirect()->route("tugas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Repositories\SiswaRepository;
|
|
||||||
use App\Repositories\UserRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class SiswaController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
protected $paramUser;
|
|
||||||
|
|
||||||
public function __construct(SiswaRepository $siswa, UserRepository $user)
|
|
||||||
{
|
|
||||||
$this->param = $siswa;
|
|
||||||
$this->paramUser = $user;
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$siswa = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.siswa.index", compact("siswa"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$kelas = Kelas::get();
|
|
||||||
$tahunAjaran = TahunAjaran::get();
|
|
||||||
return view("pages.role_admin.siswa.create", compact("kelas", 'tahunAjaran'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
'role' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nisn' => 'required|string|size:10|unique:siswa,nisn',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (Siswa::where('nisn', $data['nisn'])->exists()) {
|
|
||||||
Alert::error("Terjadi Kesalahan", "NISN sudah terdaftar.");
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
$dataUser['pass'] = $request->nisn;
|
|
||||||
$user = $this->paramUser->store($dataUser);
|
|
||||||
|
|
||||||
$data["user_id"] = $user->id;
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di simpan.");
|
|
||||||
return redirect()->route("siswa");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$kelas = Kelas::get();
|
|
||||||
$tahunAjaran = TahunAjaran::get();
|
|
||||||
$siswa = Siswa::find($id);
|
|
||||||
return view("pages.role_admin.siswa.edit", compact(["kelas", "siswa", "tahunAjaran"]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$dataUser = $request->validate([
|
|
||||||
'email' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'nisn' => 'required|string|size:10',
|
|
||||||
'nama' => 'required|string',
|
|
||||||
'jk' => 'required',
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->paramUser->update($dataUser, $request->user_id);
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
return redirect()->route("siswa");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$this->param->destroy($request->formid);
|
|
||||||
$this->paramUser->destroy($request->user_id);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Hapus.");
|
|
||||||
return redirect()->route("siswa");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
|
|
||||||
class SiswaNotifikasiController extends Controller
|
|
||||||
{
|
|
||||||
public function notifCount(Request $request)
|
|
||||||
{
|
|
||||||
$siswa = $request->user()->siswa;
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'unread_count' => $siswa->unreadNotifications->count(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$siswa = $request->user()->siswa;
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'notifications' => $siswa->notifications->map(function ($notif) {
|
|
||||||
return [
|
|
||||||
'id' => $notif->id,
|
|
||||||
'type' => $notif->data['type'],
|
|
||||||
'judul' => $notif->data['judul'] ?? '-',
|
|
||||||
'tenggat' => $notif->data['tenggat'] ?? null,
|
|
||||||
'matapelajaran_id' => $notif->data['matapelajaran_id'] ?? null,
|
|
||||||
'matapelajaran_nama' => $notif->data['matapelajaran_nama'] ?? null,
|
|
||||||
'tugas_id' => $notif->data['tugas_id'] ?? null,
|
|
||||||
'quiz_id' => $notif->data['quiz_id'] ?? null,
|
|
||||||
'read_at' => $notif->read_at,
|
|
||||||
'created_at' => $notif->created_at->toDateTimeString(),
|
|
||||||
'is_active' => $notif->read_at == null,
|
|
||||||
];
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tandai notifikasi sebagai sudah dibaca
|
|
||||||
public function markAsRead(Request $request, $id)
|
|
||||||
{
|
|
||||||
$notif = $request->user()->siswa->notifications()->findOrFail($id);
|
|
||||||
$notif->markAsRead();
|
|
||||||
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Notifikasi ditandai sebagai dibaca.',
|
|
||||||
'id' => $id,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Repositories\TahunAjaranRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class TahunAjaranController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(TahunAjaranRepository $tahunAjaran)
|
|
||||||
{
|
|
||||||
$this->param = $tahunAjaran;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$tahunAjaran = $this->param->getData($search, $limit);
|
|
||||||
return view("pages.role_admin.tahun_ajaran.index", compact("tahunAjaran"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
return view("pages.role_admin.tahun_ajaran.create");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'tahun' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->store($data);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Tambahkan.");
|
|
||||||
return redirect()->route("tahun-ajaran");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(Request $request)
|
|
||||||
{
|
|
||||||
$tahun = urldecode($request->tahun_ajaran);
|
|
||||||
$tahunAjaran = TahunAjaran::where('tahun', $tahun)->firstOrFail();
|
|
||||||
return view('pages.role_admin.tahun_ajaran.edit', compact('tahunAjaran'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$tahun = urldecode($request->tahun_ajaran);
|
|
||||||
|
|
||||||
$data = $request->validate([
|
|
||||||
'status' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->update($data, $tahun);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Ubah.");
|
|
||||||
return redirect()->route("tahun-ajaran");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$tahun = $request->input('tahun');
|
|
||||||
$this->param->destroy($tahun);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Hapus.");
|
|
||||||
return redirect()->route("tahun-ajaran");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers\Traits;
|
|
||||||
|
|
||||||
use Illuminate\Http\JsonResponse;
|
|
||||||
|
|
||||||
trait ApiResponse
|
|
||||||
{
|
|
||||||
protected function okApiResponse($data, $message = 'Success'): JsonResponse
|
|
||||||
{
|
|
||||||
return response()->json([
|
|
||||||
'status' => true,
|
|
||||||
'message' => $message,
|
|
||||||
'data' => $data
|
|
||||||
], 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response error (400/500 Internal Server Error)
|
|
||||||
*/
|
|
||||||
protected function errorApiResponse($message = 'Something went wrong', $statusCode = 500): JsonResponse
|
|
||||||
{
|
|
||||||
return response()->json([
|
|
||||||
'status' => false,
|
|
||||||
'message' => $message,
|
|
||||||
], $statusCode);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Illuminate\Support\Facades\Hash;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class UserController extends Controller
|
|
||||||
{
|
|
||||||
public function change()
|
|
||||||
{
|
|
||||||
return view("pages.auth.change_password");
|
|
||||||
}
|
|
||||||
public function changePassword(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request->validate([
|
|
||||||
'old_password' => ['required'],
|
|
||||||
'new_password' => ['required', 'min:8', 'confirmed'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$user = Auth::user();
|
|
||||||
|
|
||||||
if (!Hash::check($request->old_password, $user->password)) {
|
|
||||||
Alert::error("Terjadi Kesalahan", "Password lama salah.");
|
|
||||||
return redirect()->back();
|
|
||||||
}
|
|
||||||
|
|
||||||
User::where('id', $user->id)->update(['password' => Hash::make($request->new_password)]);
|
|
||||||
Alert::success('Berhasil', 'Password berhasil diubah.');
|
|
||||||
if ($user->role == "guru") {
|
|
||||||
return redirect()->route("dashboard.guru");
|
|
||||||
} else {
|
|
||||||
return redirect()->route("/");
|
|
||||||
}
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
Alert::error($th->getMessage());
|
|
||||||
return redirect()->back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function changePasswordApi(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$request->validate([
|
|
||||||
'old_password' => ['required'],
|
|
||||||
'new_password' => ['required', 'min:8', 'confirmed'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
$user = Auth::user();
|
|
||||||
|
|
||||||
if (!Hash::check($request->old_password, $user->password)) {
|
|
||||||
return response()->json([
|
|
||||||
'status' => false,
|
|
||||||
'message' => "Password lama salah.",
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
User::where('id', $user->id)->update(['password' => Hash::make($request->new_password)]);
|
|
||||||
return response()->json([
|
|
||||||
'status' => true,
|
|
||||||
'message' => "Password berhasil diubah.",
|
|
||||||
]);
|
|
||||||
} catch (\Throwable $th) {
|
|
||||||
return response()->json([
|
|
||||||
"status" => false,
|
|
||||||
'message' => $th->getMessage(),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,142 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Controllers;
|
|
||||||
|
|
||||||
use App\Models\Guru;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Models\AuditLog;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use App\Repositories\WaliKelasRepository;
|
|
||||||
use Illuminate\Database\QueryException;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use RealRashid\SweetAlert\Facades\Alert;
|
|
||||||
|
|
||||||
class WaliKelasController extends Controller
|
|
||||||
{
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(WaliKelasRepository $waliKelas)
|
|
||||||
{
|
|
||||||
$this->param = $waliKelas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index(Request $request)
|
|
||||||
{
|
|
||||||
$limit = $request->has('page_length') ? $request->get('page_length') : 10;
|
|
||||||
$search = $request->has('search') ? $request->get('search') : null;
|
|
||||||
$waliKelas = $this->param->getData($search, $limit);
|
|
||||||
return view('pages.role_admin.wali_kelas.index', compact('waliKelas'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for creating a new resource.
|
|
||||||
*/
|
|
||||||
public function create()
|
|
||||||
{
|
|
||||||
$kelas = Kelas::get();
|
|
||||||
$guru = Guru::get();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view('pages.role_admin.wali_kelas.create', compact(['kelas', 'guru', 'tahunAjaran']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Store a newly created resource in storage.
|
|
||||||
*/
|
|
||||||
public function store(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
'wali_nip' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->store($data);
|
|
||||||
// Update kolom nip_wali pada tabel kelas
|
|
||||||
Kelas::where('nama', $data['kelas'])->update(['nip_wali' => $data['wali_nip']]);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di Tambahkan.");
|
|
||||||
return redirect()->route("wali-kelas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the specified resource.
|
|
||||||
*/
|
|
||||||
public function show(string $id)
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the form for editing the specified resource.
|
|
||||||
*/
|
|
||||||
public function edit(string $id)
|
|
||||||
{
|
|
||||||
$waliKelas = $this->param->find($id);
|
|
||||||
$kelas = Kelas::get();
|
|
||||||
$guru = Guru::get();
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->get();
|
|
||||||
return view('pages.role_admin.wali_kelas.edit', compact(['waliKelas', 'kelas', 'guru', 'tahunAjaran']));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the specified resource in storage.
|
|
||||||
*/
|
|
||||||
public function update(Request $request, string $id)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$data = $request->validate([
|
|
||||||
'kelas' => 'required',
|
|
||||||
'tahun_ajaran' => 'required',
|
|
||||||
'wali_nip' => 'required',
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->param->update($data, $id);
|
|
||||||
// Update kolom nip_wali pada tabel kelas
|
|
||||||
Kelas::where('nama', $data['kelas'])->update(['nip_wali' => $data['wali_nip']]);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di ubah.");
|
|
||||||
return redirect()->route("wali-kelas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
} catch (QueryException $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back()->withInput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove the specified resource from storage.
|
|
||||||
*/
|
|
||||||
public function destroy(Request $request)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
$wali = $this->param->find($request->formid);
|
|
||||||
// Cek apakah wali kelas masih aktif di tabel kelas
|
|
||||||
$isWali = Kelas::where('nip_wali', $wali->wali_nip)->exists();
|
|
||||||
if ($isWali) {
|
|
||||||
Alert::error('Gagal', 'Tidak dapat menghapus wali kelas karena masih aktif di kelas. Silakan ganti wali kelas terlebih dahulu.');
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
$this->param->destroy($request->formid);
|
|
||||||
// Audit log
|
|
||||||
AuditLog::create([
|
|
||||||
'user_id' => Auth::id(),
|
|
||||||
'action' => 'delete_wali_kelas',
|
|
||||||
'description' => 'Menghapus wali kelas: ' . $wali->wali_nip,
|
|
||||||
]);
|
|
||||||
Alert::success("Berhasil", "Data Berhasil di hapus.");
|
|
||||||
return redirect()->route("wali-kelas");
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
Alert::error("Terjadi Kesalahan", $e->getMessage());
|
|
||||||
return back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Sanctum\PersonalAccessToken;
|
|
||||||
|
|
||||||
class CheckApiToken
|
|
||||||
{
|
|
||||||
public function handle(Request $request, Closure $next)
|
|
||||||
{
|
|
||||||
$header = $request->header('Authorization');
|
|
||||||
|
|
||||||
if (!$header || !str_starts_with($header, 'Bearer ')) {
|
|
||||||
return response()->json(['message' => 'Token tidak ditemukan.'], 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
$accessToken = str_replace('Bearer ', '', $header);
|
|
||||||
|
|
||||||
$token = PersonalAccessToken::findToken($accessToken);
|
|
||||||
|
|
||||||
if (!$token) {
|
|
||||||
return response()->json(['message' => 'Token tidak valid.'], 401);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set user yang sedang login (penting)
|
|
||||||
$request->merge(['user' => $token->tokenable]);
|
|
||||||
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Middleware;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
|
||||||
|
|
||||||
class RoleMiddleware
|
|
||||||
{
|
|
||||||
public function handle(Request $request, Closure $next, ...$roles): Response
|
|
||||||
{
|
|
||||||
if (!Auth::check()) {
|
|
||||||
return redirect('/login');
|
|
||||||
}
|
|
||||||
|
|
||||||
$user = Auth::user();
|
|
||||||
|
|
||||||
if (in_array($user->role, $roles)) {
|
|
||||||
return $next($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
abort(403, 'Unauthorized');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,17 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Requests;
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
|
||||||
|
|
||||||
class ChangePasswordRequest extends FormRequest
|
|
||||||
{
|
|
||||||
public function rules()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'old_password' => ['required'],
|
|
||||||
'new_password' => ['required', 'min:8', 'confirmed'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
class SubmitTugasResource extends JsonResource
|
|
||||||
{
|
|
||||||
public function toArray($request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => $this->id,
|
|
||||||
'tanggal' => $this->tanggal ? Carbon::parse($this->tanggal)->format('Y-m-d H:i:s') : null,
|
|
||||||
'nisn' => $this->nisn,
|
|
||||||
'tugas_id' => $this->tugas_id,
|
|
||||||
'text' => $this->text,
|
|
||||||
'file' => $this->file,
|
|
||||||
'nilai' => $this->nilai,
|
|
||||||
'created_at' => $this->created_at ? $this->created_at->format('Y-m-d H:i:s') : null,
|
|
||||||
'updated_at' => $this->updated_at ? $this->updated_at->format('Y-m-d H:i:s') : null,
|
|
||||||
'siswa' => $this->whenLoaded('siswa', function () {
|
|
||||||
return [
|
|
||||||
'nisn' => $this->siswa->nisn,
|
|
||||||
'nama' => $this->siswa->nama,
|
|
||||||
];
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
|
||||||
|
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
|
|
||||||
class TugasResource extends JsonResource
|
|
||||||
{
|
|
||||||
public function toArray($request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'id' => $this->id,
|
|
||||||
'nama' => $this->nama,
|
|
||||||
'deskripsi' => $this->deskripsi,
|
|
||||||
'tanggal' => $this->tanggal ? Carbon::parse($this->tanggal)->format('Y-m-d H:i:s') : null,
|
|
||||||
'tenggat' => $this->tenggat ? Carbon::parse($this->tenggat)->format('Y-m-d H:i:s') : null,
|
|
||||||
'guru_nip' => $this->guru_nip,
|
|
||||||
'matapelajaran_id' => $this->matapelajaran_id,
|
|
||||||
'kelas' => $this->kelas,
|
|
||||||
'tahun_ajaran' => $this->tahun_ajaran,
|
|
||||||
'mata_pelajaran' => $this->whenLoaded('mataPelajaran', function () {
|
|
||||||
return [
|
|
||||||
'id' => $this->mataPelajaran->id,
|
|
||||||
'nama' => $this->mataPelajaran->nama,
|
|
||||||
];
|
|
||||||
}),
|
|
||||||
'submit_tugas' => SubmitTugasResource::collection($this->whenLoaded('submitTugas')),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Imports;
|
|
||||||
|
|
||||||
use App\Models\QuizQuestions;
|
|
||||||
use Maatwebsite\Excel\Concerns\ToModel;
|
|
||||||
|
|
||||||
class QuizImport implements ToModel
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param array $row
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Database\Eloquent\Model|null
|
|
||||||
*/
|
|
||||||
public function model(array $row)
|
|
||||||
{
|
|
||||||
return new QuizQuestions([
|
|
||||||
//
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Admin extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'admin';
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'id',
|
|
||||||
'user_id',
|
|
||||||
'nip',
|
|
||||||
'nama',
|
|
||||||
'jk',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class AuditLog extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'audit_logs';
|
|
||||||
protected $fillable = [
|
|
||||||
'user_id', 'action', 'description'
|
|
||||||
];
|
|
||||||
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Guru extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'guru';
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'id',
|
|
||||||
'user_id',
|
|
||||||
'nip',
|
|
||||||
'nama',
|
|
||||||
'jk',
|
|
||||||
];
|
|
||||||
|
|
||||||
// public function kelas()
|
|
||||||
// {
|
|
||||||
// return $this->hasOne(Kelas::class, 'nip_wali', 'nip');
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function mataPelajaran()
|
|
||||||
{
|
|
||||||
return $this->hasOne(MataPelajaran::class, 'guru_nip', 'nip');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Kelas extends Model
|
|
||||||
{
|
|
||||||
protected $table = "kelas";
|
|
||||||
protected $fillable = [
|
|
||||||
"nama",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function siswa()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Siswa::class, 'kelas', 'nama');
|
|
||||||
}
|
|
||||||
|
|
||||||
// public function guru()
|
|
||||||
// {
|
|
||||||
// return $this->belongsTo(Guru::class, 'nip_wali', 'nip');
|
|
||||||
// }
|
|
||||||
|
|
||||||
public function mataPelajaran()
|
|
||||||
{
|
|
||||||
return $this->hasMany(MataPelajaran::class, 'kelas', 'nama');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class MataPelajaran extends Model
|
|
||||||
{
|
|
||||||
protected $table = 'matapelajaran';
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"nama",
|
|
||||||
"guru_nip",
|
|
||||||
"kelas",
|
|
||||||
"tahun_ajaran",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function materi()
|
|
||||||
{
|
|
||||||
return $this->hasMany(Materi::class, "matapelajaran_id", "id");
|
|
||||||
}
|
|
||||||
public function guru()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Guru::class, "guru_nip", "nip");
|
|
||||||
}
|
|
||||||
public function kelas()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Kelas::class, "kelas", "nama");
|
|
||||||
}
|
|
||||||
public function tahunAjaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TahunAjaran::class, "tahun_ajaran", "tahun");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Materi extends Model
|
|
||||||
{
|
|
||||||
protected $table = "materi";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"tanggal",
|
|
||||||
"matapelajaran_id",
|
|
||||||
"semester",
|
|
||||||
"type",
|
|
||||||
"judul_materi",
|
|
||||||
"deskripsi",
|
|
||||||
"path",
|
|
||||||
"tahun_ajaran"
|
|
||||||
];
|
|
||||||
|
|
||||||
public function mataPelajaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(MataPelajaran::class, "matapelajaran_id", "id");
|
|
||||||
}
|
|
||||||
public function tahunAjaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TahunAjaran::class, "tahun_ajaran", "tahun");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class QuizAttemptAnswers extends Model
|
|
||||||
{
|
|
||||||
protected $table = "quiz_attempt_answers";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"attempt_id",
|
|
||||||
"question_id",
|
|
||||||
"jawaban_siswa",
|
|
||||||
"benar",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function quizAttempt()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(QuizAttempts::class, "attempt_id", "id");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function quizQuestion()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(QuizQuestions::class, "question_id", "id");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class QuizAttempts extends Model
|
|
||||||
{
|
|
||||||
protected $table = "quiz_attempts";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"quiz_id",
|
|
||||||
"nisn",
|
|
||||||
"skor",
|
|
||||||
"level_akhir",
|
|
||||||
"jumlah_soal_dijawab",
|
|
||||||
"benar",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function attemptAnswers()
|
|
||||||
{
|
|
||||||
return $this->hasMany(QuizAttemptAnswers::class, 'attempt_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function jumlahJawaban()
|
|
||||||
{
|
|
||||||
return $this->hasMany(QuizAttemptAnswers::class, 'attempt_id')->count();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function quizzes()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Quizzes::class, "quiz_id", "id");
|
|
||||||
}
|
|
||||||
public function siswa()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Siswa::class, "nisn", "nisn");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class QuizLevelSetting extends Model
|
|
||||||
{
|
|
||||||
protected $table = "quiz_level_settings";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'quiz_id',
|
|
||||||
'jumlah_soal_per_level',
|
|
||||||
'level_awal',
|
|
||||||
'batas_naik_level',
|
|
||||||
'skor_level',
|
|
||||||
'kkm',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function quiz()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Quizzes::class);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class QuizQuestions extends Model
|
|
||||||
{
|
|
||||||
protected $table = "quiz_questions";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"quiz_id",
|
|
||||||
"pertanyaan",
|
|
||||||
"opsi_a",
|
|
||||||
"opsi_b",
|
|
||||||
"opsi_c",
|
|
||||||
"opsi_d",
|
|
||||||
"jawaban_bener",
|
|
||||||
"level",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function attemptAnswers()
|
|
||||||
{
|
|
||||||
return $this->hasMany(QuizAttemptAnswers::class, 'question_id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function quiz()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Quizzes::class, "quiz_id", "id");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Quizzes extends Model
|
|
||||||
{
|
|
||||||
protected $table = "quizzes";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"judul",
|
|
||||||
"deskripsi",
|
|
||||||
"total_soal",
|
|
||||||
"total_soal_tampil",
|
|
||||||
"waktu",
|
|
||||||
"matapelajaran_id",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function levelSetting()
|
|
||||||
{
|
|
||||||
return $this->hasOne(QuizLevelSetting::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function quizAttempt()
|
|
||||||
{
|
|
||||||
return $this->hasOne(QuizAttempts::class, "quiz_id", "id");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function quizLevelSetting()
|
|
||||||
{
|
|
||||||
return $this->hasOne(QuizLevelSetting::class, 'quiz_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function mataPelajaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(MataPelajaran::class, "matapelajaran_id", "id");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Notifications\Notifiable;
|
|
||||||
|
|
||||||
class Siswa extends Model
|
|
||||||
{
|
|
||||||
use Notifiable;
|
|
||||||
protected $table = "siswa";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"user_id",
|
|
||||||
"nisn",
|
|
||||||
"nama",
|
|
||||||
"jk",
|
|
||||||
"kelas",
|
|
||||||
"tahun_ajaran",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function submitTugas()
|
|
||||||
{
|
|
||||||
return $this->hasOne(SubmitTugas::class, "nisn", "nisn");
|
|
||||||
}
|
|
||||||
public function user()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(User::class, "user_id", "id");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function kelas()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Kelas::class, "kelas", "nama");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tahunAjaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TahunAjaran::class, "tahun_ajaran", "tahun");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class SubmitTugas extends Model
|
|
||||||
{
|
|
||||||
protected $table = "submit_tugas";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"id",
|
|
||||||
"tanggal",
|
|
||||||
"nisn",
|
|
||||||
"tugas_id",
|
|
||||||
"text",
|
|
||||||
"file",
|
|
||||||
"nilai"
|
|
||||||
];
|
|
||||||
|
|
||||||
public function siswa()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Siswa::class, "nisn", "nisn");
|
|
||||||
}
|
|
||||||
public function tugas()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Tugas::class, "tugas_id", "id");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class TahunAjaran extends Model
|
|
||||||
{
|
|
||||||
protected $table = "tahun_ajaran";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"tahun",
|
|
||||||
"status",
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Tugas extends Model
|
|
||||||
{
|
|
||||||
protected $table = "tugas";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"tanggal",
|
|
||||||
"tenggat",
|
|
||||||
"guru_nip",
|
|
||||||
"nama",
|
|
||||||
"matapelajaran_id",
|
|
||||||
"kelas",
|
|
||||||
"tahun_ajaran",
|
|
||||||
'deskripsi',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function submitTugas()
|
|
||||||
{
|
|
||||||
return $this->hasMany(SubmitTugas::class, "tugas_id", "id");
|
|
||||||
}
|
|
||||||
public function guru()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Guru::class, "guru_nip", "nip");
|
|
||||||
}
|
|
||||||
public function mataPelajaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(MataPelajaran::class, "matapelajaran_id", "id");
|
|
||||||
}
|
|
||||||
public function tahunAjaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TahunAjaran::class, "tahun_ajaran", "id");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,50 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
|
||||||
use Illuminate\Notifications\Notifiable;
|
|
||||||
use Laravel\Sanctum\HasApiTokens;
|
|
||||||
|
|
||||||
class User extends Authenticatable
|
|
||||||
{
|
|
||||||
use HasFactory, Notifiable, HasApiTokens;
|
|
||||||
|
|
||||||
protected $table = 'users';
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
'id',
|
|
||||||
'email',
|
|
||||||
'password',
|
|
||||||
'role',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected $hidden = [
|
|
||||||
'password',
|
|
||||||
];
|
|
||||||
|
|
||||||
protected function casts(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'password' => 'hashed',
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function admin()
|
|
||||||
{
|
|
||||||
return $this->hasOne(Admin::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function guru()
|
|
||||||
{
|
|
||||||
return $this->hasOne(Guru::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function siswa()
|
|
||||||
{
|
|
||||||
return $this->hasOne(Siswa::class, 'user_id', 'id');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Models;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class WaliKelas extends Model
|
|
||||||
{
|
|
||||||
protected $table = "riwayat_kelas";
|
|
||||||
|
|
||||||
protected $fillable = [
|
|
||||||
"kelas",
|
|
||||||
"tahun_ajaran",
|
|
||||||
"wali_nip",
|
|
||||||
];
|
|
||||||
|
|
||||||
public function kelas()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Kelas::class, 'kelas', 'nama');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function guru()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(Guru::class, 'wali_nip', 'nip');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function tahunAjaran()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(TahunAjaran::class, 'tahun_ajaran', 'tahun');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Notifications;
|
|
||||||
|
|
||||||
use App\Models\Materi;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
|
||||||
use Illuminate\Notifications\Notification;
|
|
||||||
|
|
||||||
class MateriBaruNotification extends Notification
|
|
||||||
{
|
|
||||||
use Queueable;
|
|
||||||
|
|
||||||
protected $materi;
|
|
||||||
|
|
||||||
public function __construct(Materi $materi)
|
|
||||||
{
|
|
||||||
$this->materi = $materi;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function via(object $notifiable): array
|
|
||||||
{
|
|
||||||
return ['database'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toDatabase($notifiable): array
|
|
||||||
{
|
|
||||||
$this->materi->loadMissing('mataPelajaran');
|
|
||||||
return [
|
|
||||||
'judul' => $this->materi->judul_materi,
|
|
||||||
'type' => "Materi",
|
|
||||||
'matapelajaran_id' => $this->materi->matapelajaran_id,
|
|
||||||
'matapelajaran_nama' => $this->materi->mataPelajaran->nama ?? null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Notifications;
|
|
||||||
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
|
||||||
use Illuminate\Notifications\Notification;
|
|
||||||
|
|
||||||
class QuizBaruNotification extends Notification
|
|
||||||
{
|
|
||||||
use Queueable;
|
|
||||||
|
|
||||||
protected $param;
|
|
||||||
|
|
||||||
public function __construct(Quizzes $quizzes)
|
|
||||||
{
|
|
||||||
$this->param = $quizzes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function via(object $notifiable): array
|
|
||||||
{
|
|
||||||
return ['database'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toDatabase($notifiable): array
|
|
||||||
{
|
|
||||||
$this->param->loadMissing('mataPelajaran');
|
|
||||||
return [
|
|
||||||
'judul' => $this->param->judul,
|
|
||||||
'type' => "Quiz",
|
|
||||||
'matapelajaran_id' => $this->param->matapelajaran_id,
|
|
||||||
'matapelajaran_nama' => $this->param->mataPelajaran->nama ?? null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,38 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Notifications;
|
|
||||||
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use Illuminate\Bus\Queueable;
|
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
|
||||||
use Illuminate\Notifications\Messages\MailMessage;
|
|
||||||
use Illuminate\Notifications\Notification;
|
|
||||||
|
|
||||||
class TugasBaruNotification extends Notification
|
|
||||||
{
|
|
||||||
use Queueable;
|
|
||||||
|
|
||||||
protected $tugas;
|
|
||||||
|
|
||||||
public function __construct(Tugas $tugas)
|
|
||||||
{
|
|
||||||
$this->tugas = $tugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function via(object $notifiable): array
|
|
||||||
{
|
|
||||||
return ['database'];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toDatabase($notifiable): array
|
|
||||||
{
|
|
||||||
// Pastikan relasi sudah di-load
|
|
||||||
$this->tugas->loadMissing('mataPelajaran');
|
|
||||||
return [
|
|
||||||
'judul' => $this->tugas->nama,
|
|
||||||
'type' => "Tugas",
|
|
||||||
'matapelajaran_id' => $this->tugas->matapelajaran_id,
|
|
||||||
'matapelajaran_nama' => $this->tugas->mataPelajaran->nama ?? null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Providers;
|
|
||||||
|
|
||||||
use Illuminate\Support\ServiceProvider;
|
|
||||||
|
|
||||||
class AppServiceProvider extends ServiceProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Register any application services.
|
|
||||||
*/
|
|
||||||
public function register(): void
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bootstrap any application services.
|
|
||||||
*/
|
|
||||||
public function boot(): void
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Admin;
|
|
||||||
|
|
||||||
class AdminRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Admin $guru)
|
|
||||||
{
|
|
||||||
$this->model = $guru;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('user')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%")
|
|
||||||
->orWhere("nip", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("user", function ($query) use ($search) {
|
|
||||||
$query->where("email", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"user_id" => $data["user_id"],
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,99 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\SubmitTugas;
|
|
||||||
use Illuminate\Support\Facades\Storage;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
|
|
||||||
class ApiSubmitTugasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(SubmitTugas $submitTugas)
|
|
||||||
{
|
|
||||||
$this->model = $submitTugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($request)
|
|
||||||
{
|
|
||||||
$tanggal = now(); // Ubah agar menyimpan datetime lengkap
|
|
||||||
$request->validate([
|
|
||||||
'tugas_id' => 'required|exists:tugas,id',
|
|
||||||
'nisn' => 'required|string|max:12',
|
|
||||||
'text' => 'nullable|required_without:file|string',
|
|
||||||
'file' => 'nullable|required_without:text|file|mimes:pdf,jpg,png',
|
|
||||||
'nilai' => 'nullable|integer|min:0|max:100'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$filePath = null;
|
|
||||||
|
|
||||||
if ($request->hasFile('file')) {
|
|
||||||
$filename = Str::uuid() . '.' . $request->file->extension();
|
|
||||||
$filePath = $request->file->storeAs('tugas/submit_tugas', $filename, 'public');
|
|
||||||
}
|
|
||||||
|
|
||||||
$submit = SubmitTugas::create([
|
|
||||||
'tugas_id' => $request->tugas_id,
|
|
||||||
'nisn' => $request->nisn,
|
|
||||||
'tanggal' => $tanggal, // simpan datetime lengkap
|
|
||||||
'text' => $request->text,
|
|
||||||
'file' => $filePath,
|
|
||||||
'nilai' => $request->nilai
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $submit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function detail($request)
|
|
||||||
{
|
|
||||||
// Cek jika ada parameter submit_id, maka ambil berdasarkan id
|
|
||||||
if ($request->has('submit_id')) {
|
|
||||||
$query = $this->model->with('siswa')->find($request->submit_id);
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Default: cari berdasarkan nisn dan tugas_id
|
|
||||||
$query = $this->model->with('siswa')->where(function ($q) use ($request) {
|
|
||||||
$q->where('nisn', $request->nisn)
|
|
||||||
->where('tugas_id', $request->tugas_id);
|
|
||||||
})->first();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($request)
|
|
||||||
{
|
|
||||||
$tanggal = now(); // Ubah agar menyimpan datetime lengkap
|
|
||||||
|
|
||||||
$request->validate([
|
|
||||||
'id' => 'required|exists:submit_tugas,id',
|
|
||||||
'nisn' => 'required|string|max:12',
|
|
||||||
'text' => 'nullable|string',
|
|
||||||
'nilai' => 'nullable|integer|min:0|max:100'
|
|
||||||
]);
|
|
||||||
|
|
||||||
$submit = $this->model->findOrFail($request->id);
|
|
||||||
|
|
||||||
$filePath = $submit->file;
|
|
||||||
|
|
||||||
if ($request->hasFile('file')) {
|
|
||||||
if ($filePath && Storage::disk('public')->exists($filePath)) {
|
|
||||||
Storage::disk('public')->delete($filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
$filename = Str::uuid() . '.' . $request->file->extension();
|
|
||||||
$filePath = $request->file->storeAs('tugas/submit_tugas', $filename, 'public');
|
|
||||||
}
|
|
||||||
|
|
||||||
$submit->update([
|
|
||||||
'nisn' => $request->nisn,
|
|
||||||
'tanggal' => $tanggal, // simpan datetime lengkap
|
|
||||||
'text' => $request->text,
|
|
||||||
'file' => $filePath,
|
|
||||||
'nilai' => $request->nilai
|
|
||||||
]);
|
|
||||||
|
|
||||||
return $submit;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\SubmitTugas;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use App\Http\Resources\TugasResource;
|
|
||||||
use GuzzleHttp\Psr7\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class ApiTugasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Tugas $tugas)
|
|
||||||
{
|
|
||||||
$this->model = $tugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDataApi($request, $param)
|
|
||||||
{
|
|
||||||
$query = $this->model->with(['mataPelajaran', 'submitTugas']);
|
|
||||||
|
|
||||||
if ($request->user->role == "siswa") {
|
|
||||||
if ($param->type_tugas == "selesai") {
|
|
||||||
$query->withWhereHas("submitTugas", function ($q) use ($request) {
|
|
||||||
$q->where('nisn', $request->nisn);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query->whereDoesntHave("submitTugas", function ($q) use ($request) {
|
|
||||||
$q->where('nisn', $request->nisn);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$query->where(function ($q) use ($request) {
|
|
||||||
$q->where("kelas", $request->kelas)
|
|
||||||
->where("tahun_ajaran", $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query->where(function ($q) use ($request, $param) {
|
|
||||||
$q->where("guru_nip", $request->nip)
|
|
||||||
->where('kelas', $param->kelas)
|
|
||||||
->where('tahun_ajaran', $param->tahun_ajaran);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$query->where('matapelajaran_id', $param->id_matpel);
|
|
||||||
|
|
||||||
$data = $query->get();
|
|
||||||
|
|
||||||
return TugasResource::collection($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getSubmitTugasSiswa($request)
|
|
||||||
{
|
|
||||||
$query = Siswa::where(function ($q) use ($request) {
|
|
||||||
$q->where("kelas", $request->kelas)
|
|
||||||
->where("tahun_ajaran", $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
|
|
||||||
if ($request->type_tugas == "selesai") {
|
|
||||||
$query->withWhereHas("submitTugas", function ($q) use ($request) {
|
|
||||||
$q->where("tugas_id", $request->tugas_id);
|
|
||||||
})->with([
|
|
||||||
'submitTugas' => function ($q) use ($request) {
|
|
||||||
$q->where("tugas_id", $request->tugas_id)
|
|
||||||
->with('tugas');
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
$query->with('submitTugas')
|
|
||||||
->whereDoesntHave("submitTugas", function ($q) use ($request) {
|
|
||||||
$q->where("tugas_id", $request->tugas_id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$data = $query->get();
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Models\WaliKelas;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
|
|
||||||
class DashboardRepository
|
|
||||||
{
|
|
||||||
public function getData($tahunAjaran = null, $kelas = null)
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
|
|
||||||
// Get active academic year if not specified
|
|
||||||
if (!$tahunAjaran) {
|
|
||||||
$tahunAjaran = TahunAjaran::where('status', 'aktif')->first();
|
|
||||||
if ($tahunAjaran) {
|
|
||||||
$tahunAjaran = $tahunAjaran->tahun;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get all academic years for dropdown
|
|
||||||
$data['tahun_ajaran_list'] = TahunAjaran::select('tahun')->get()->pluck('tahun');
|
|
||||||
// Get all classes for dropdown
|
|
||||||
$data['kelas_list'] = Kelas::select('nama')->get()->pluck('nama');
|
|
||||||
|
|
||||||
// User statistics (not affected by academic year or class)
|
|
||||||
$data['admin'] = User::where('role', "admin")->count();
|
|
||||||
$data['guru'] = User::where('role', "guru")->count();
|
|
||||||
|
|
||||||
// Academic statistics with year and class filter
|
|
||||||
$siswaQuery = Siswa::query();
|
|
||||||
$mataPelajaranQuery = MataPelajaran::query();
|
|
||||||
$waliKelasQuery = WaliKelas::query();
|
|
||||||
|
|
||||||
if ($tahunAjaran && $tahunAjaran !== 'all') {
|
|
||||||
$siswaQuery->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
$mataPelajaranQuery->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
$waliKelasQuery->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($kelas && $kelas !== 'all') {
|
|
||||||
$siswaQuery->where('kelas', $kelas);
|
|
||||||
$mataPelajaranQuery->where('kelas', $kelas);
|
|
||||||
$waliKelasQuery->where('kelas', $kelas);
|
|
||||||
}
|
|
||||||
|
|
||||||
$data['siswa'] = $siswaQuery->count();
|
|
||||||
// Kelas count needs special handling as it's not directly tied to siswa by year/class but to the existing classes
|
|
||||||
// If filtering by class, we only count that specific class, otherwise all classes
|
|
||||||
$data['kelas'] = ($kelas && $kelas !== 'all') ? 1 : Kelas::count();
|
|
||||||
$data['mata_pelajaran'] = $mataPelajaranQuery->count();
|
|
||||||
$data['wali_kelas'] = $waliKelasQuery->count();
|
|
||||||
|
|
||||||
// Get active academic year info
|
|
||||||
$activeYear = TahunAjaran::where('status', 'aktif')->first();
|
|
||||||
if ($activeYear) {
|
|
||||||
$data['tahun_ajaran_aktif'] = $activeYear->tahun;
|
|
||||||
} else {
|
|
||||||
$data['tahun_ajaran_aktif'] = 'Belum ada tahun ajaran aktif';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store selected year and class
|
|
||||||
$data['selected_year'] = $tahunAjaran;
|
|
||||||
$data['selected_kelas'] = $kelas;
|
|
||||||
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,243 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Kelas;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
use App\Models\Materi;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\SubmitTugas;
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class GuruDashboardRepository
|
|
||||||
{
|
|
||||||
public function getDashboardData($tahunAjaran = 'all', $kelas = 'all', $quizStatus = 'all')
|
|
||||||
{
|
|
||||||
$guru = Auth::user()->guru;
|
|
||||||
|
|
||||||
// Get all academic years for filter based on guru's subjects
|
|
||||||
$tahunAjaranList = MataPelajaran::where('guru_nip', $guru->nip)
|
|
||||||
->distinct('tahun_ajaran')
|
|
||||||
->pluck('tahun_ajaran')
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
// Get all classes for filter based on guru's subjects
|
|
||||||
$kelasList = MataPelajaran::where('guru_nip', $guru->nip)
|
|
||||||
->distinct('kelas')
|
|
||||||
->pluck('kelas')
|
|
||||||
->toArray();
|
|
||||||
|
|
||||||
// Get active academic year
|
|
||||||
$tahunAjaranAktif = TahunAjaran::where('status', 'aktif')->first();
|
|
||||||
|
|
||||||
// Get relevant MataPelajaran first based on guru_nip and tahun_ajaran
|
|
||||||
$guruMataPelajaranQuery = MataPelajaran::where('guru_nip', $guru->nip);
|
|
||||||
|
|
||||||
if ($tahunAjaran !== 'all') {
|
|
||||||
$guruMataPelajaranQuery->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
}
|
|
||||||
if ($kelas !== 'all') {
|
|
||||||
$guruMataPelajaranQuery->where('kelas', $kelas);
|
|
||||||
}
|
|
||||||
$guruMataPelajaranIds = $guruMataPelajaranQuery->pluck('id')->toArray();
|
|
||||||
$guruMataPelajaranClasses = $guruMataPelajaranQuery->pluck('kelas')->unique()->toArray();
|
|
||||||
|
|
||||||
// Now build the kelasQuery based on these class names
|
|
||||||
$kelasQuery = Kelas::whereIn('nama', $guruMataPelajaranClasses);
|
|
||||||
|
|
||||||
// Get subjects taught by this teacher (this query already correctly uses guru_nip)
|
|
||||||
$mataPelajaranQuery = MataPelajaran::where('guru_nip', $guru->nip);
|
|
||||||
|
|
||||||
// Apply filters if not 'all'
|
|
||||||
if ($tahunAjaran !== 'all') {
|
|
||||||
$mataPelajaranQuery->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($kelas !== 'all') {
|
|
||||||
$kelasQuery->where('nama', $kelas);
|
|
||||||
$mataPelajaranQuery->where('kelas', $kelas);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get counts
|
|
||||||
$kelasCount = $kelasQuery->count();
|
|
||||||
$mataPelajaranCount = $mataPelajaranQuery->count();
|
|
||||||
|
|
||||||
// Get total students from these classes
|
|
||||||
$siswaCount = Siswa::whereIn('kelas', $kelasQuery->pluck('nama'))->count();
|
|
||||||
|
|
||||||
// New features: Total Tugas, Materi, Quiz
|
|
||||||
$totalTugas = Tugas::where('guru_nip', $guru->nip)
|
|
||||||
->when($tahunAjaran !== 'all', function ($query) use ($tahunAjaran) {
|
|
||||||
return $query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
})
|
|
||||||
->when($kelas !== 'all', function ($query) use ($kelas) {
|
|
||||||
return $query->where('kelas', $kelas);
|
|
||||||
})
|
|
||||||
->count();
|
|
||||||
|
|
||||||
$totalMateri = Materi::whereIn('matapelajaran_id', $guruMataPelajaranIds)
|
|
||||||
->when($tahunAjaran !== 'all', function ($query) use ($tahunAjaran) {
|
|
||||||
return $query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
})
|
|
||||||
->count();
|
|
||||||
|
|
||||||
$totalQuiz = Quizzes::whereIn('matapelajaran_id', $guruMataPelajaranIds)
|
|
||||||
->count();
|
|
||||||
|
|
||||||
// Quiz Results (Passed/Failed)
|
|
||||||
$passedQuizzes = 0;
|
|
||||||
$failedQuizzes = 0;
|
|
||||||
|
|
||||||
$quizAttempts = QuizAttempts::whereHas('quizzes.mataPelajaran', function ($query) use ($guru, $tahunAjaran, $kelas) {
|
|
||||||
$query->where('guru_nip', $guru->nip);
|
|
||||||
if ($tahunAjaran !== 'all') {
|
|
||||||
$query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
}
|
|
||||||
if ($kelas !== 'all') {
|
|
||||||
$query->where('kelas', $kelas);
|
|
||||||
}
|
|
||||||
})->get();
|
|
||||||
|
|
||||||
foreach ($quizAttempts as $attempt) {
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $attempt->quiz_id)->first();
|
|
||||||
if ($quizLevelSettings) {
|
|
||||||
$jumlahSoalPerLevel = json_decode($quizLevelSettings->jumlah_soal_per_level, true);
|
|
||||||
$totalSkorLevel = 0;
|
|
||||||
foreach (json_decode($quizLevelSettings->skor_level) as $key => $value) {
|
|
||||||
$totalSkorLevel += $value * (int) $jumlahSoalPerLevel[$key];
|
|
||||||
}
|
|
||||||
|
|
||||||
$persentase = ($totalSkorLevel > 0) ? round(($attempt->skor / $totalSkorLevel) * 100) : 0;
|
|
||||||
$kkm = $quizLevelSettings->kkm;
|
|
||||||
|
|
||||||
if ($persentase >= $kkm) {
|
|
||||||
$passedQuizzes++;
|
|
||||||
} else {
|
|
||||||
$failedQuizzes++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare data for Mata Pelajaran Distribution Chart
|
|
||||||
$mataPelajaranChartLabels = [];
|
|
||||||
$mataPelajaranChartData = [];
|
|
||||||
$mataPelajaranWithClasses = MataPelajaran::where('guru_nip', $guru->nip)
|
|
||||||
->when($tahunAjaran !== 'all', function ($query) use ($tahunAjaran) {
|
|
||||||
return $query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
})
|
|
||||||
->when($kelas !== 'all', function ($query) use ($kelas) {
|
|
||||||
return $query->where('kelas', $kelas);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
foreach ($mataPelajaranWithClasses as $mp) {
|
|
||||||
$studentsInClass = Siswa::where('kelas', $mp->kelas)->count();
|
|
||||||
$mataPelajaranChartLabels[] = $mp->nama; // Assuming 'nama' is the subject name
|
|
||||||
$mataPelajaranChartData[] = $studentsInClass; // Count students in the associated class
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare data for Siswa per Kelas Chart
|
|
||||||
$kelasChartLabels = [];
|
|
||||||
$kelasChartData = [];
|
|
||||||
$guruClasses = Kelas::whereIn('nama', $guruMataPelajaranClasses)
|
|
||||||
->when($kelas !== 'all', function ($query) use ($kelas) {
|
|
||||||
return $query->where('nama', $kelas);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
foreach ($guruClasses as $k) {
|
|
||||||
$siswaInKelasCount = Siswa::where('kelas', $k->nama)->count();
|
|
||||||
$kelasChartLabels[] = $k->nama;
|
|
||||||
$kelasChartData[] = $siswaInKelasCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare data for Nilai Rata-rata Tugas per Mata Pelajaran dan Kelas Chart
|
|
||||||
$tugasChartLabels = [];
|
|
||||||
$tugasChartData = [];
|
|
||||||
$tugasChartDataPerTugas = [];
|
|
||||||
|
|
||||||
// Get all mata pelajaran that the teacher teaches with filters
|
|
||||||
$mataPelajaranQuery = MataPelajaran::where('guru_nip', $guru->nip)
|
|
||||||
->when($tahunAjaran !== 'all', function ($query) use ($tahunAjaran) {
|
|
||||||
return $query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
})
|
|
||||||
->when($kelas !== 'all', function ($query) use ($kelas) {
|
|
||||||
return $query->where('kelas', $kelas);
|
|
||||||
})
|
|
||||||
->orderBy('nama', 'asc');
|
|
||||||
|
|
||||||
$mataPelajaranList = $mataPelajaranQuery->get();
|
|
||||||
|
|
||||||
foreach ($mataPelajaranList as $matpel) {
|
|
||||||
// Get all tasks for this mata pelajaran and class
|
|
||||||
$tugasForMatpel = Tugas::where('guru_nip', $guru->nip)
|
|
||||||
->where('matapelajaran_id', $matpel->id)
|
|
||||||
->where('kelas', $matpel->kelas)
|
|
||||||
->when($tahunAjaran !== 'all', function ($query) use ($tahunAjaran) {
|
|
||||||
return $query->where('tahun_ajaran', $tahunAjaran);
|
|
||||||
})
|
|
||||||
->orderBy('created_at', 'desc')
|
|
||||||
->get();
|
|
||||||
|
|
||||||
foreach ($tugasForMatpel as $tugas) {
|
|
||||||
// Get average score for this task
|
|
||||||
$avgNilai = SubmitTugas::where('tugas_id', $tugas->id)
|
|
||||||
->whereNotNull('nilai')
|
|
||||||
->avg('nilai');
|
|
||||||
|
|
||||||
if ($avgNilai !== null) {
|
|
||||||
$tugasChartLabels[] = "{$matpel->nama} ({$matpel->kelas}) - {$tugas->nama}";
|
|
||||||
$tugasChartData[] = round($avgNilai, 1);
|
|
||||||
|
|
||||||
$tugasChartDataPerTugas[] = [
|
|
||||||
'id_tugas' => $tugas->id,
|
|
||||||
'nama_tugas' => $tugas->nama,
|
|
||||||
'mata_pelajaran' => $matpel->nama,
|
|
||||||
'kelas' => $matpel->kelas,
|
|
||||||
'rata_rata' => round($avgNilai, 1),
|
|
||||||
'jumlah_submit' => SubmitTugas::where('tugas_id', $tugas->id)->count(),
|
|
||||||
'jumlah_dinilai' => SubmitTugas::where('tugas_id', $tugas->id)->whereNotNull('nilai')->count(),
|
|
||||||
'tanggal_tugas' => $tugas->tanggal,
|
|
||||||
'tenggat_waktu' => $tugas->tenggat
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
|
||||||
'selected_year' => $tahunAjaran,
|
|
||||||
'selected_kelas' => $kelas,
|
|
||||||
'selected_quiz_status' => $quizStatus,
|
|
||||||
'tahun_ajaran_list' => $tahunAjaranList,
|
|
||||||
'kelas_list' => $kelasList,
|
|
||||||
'tahun_ajaran_aktif' => $tahunAjaranAktif ? $tahunAjaranAktif->tahun : '-',
|
|
||||||
'kelas' => $kelasCount,
|
|
||||||
'mata_pelajaran' => $mataPelajaranCount,
|
|
||||||
'siswa' => $siswaCount,
|
|
||||||
'total_tugas' => $totalTugas,
|
|
||||||
'total_materi' => $totalMateri,
|
|
||||||
'total_quiz' => $totalQuiz,
|
|
||||||
'passed_quizzes' => $passedQuizzes,
|
|
||||||
'failed_quizzes' => $failedQuizzes,
|
|
||||||
'mata_pelajaran_chart' => [
|
|
||||||
'labels' => $mataPelajaranChartLabels,
|
|
||||||
'data' => $mataPelajaranChartData,
|
|
||||||
],
|
|
||||||
'kelas_chart' => [
|
|
||||||
'labels' => $kelasChartLabels,
|
|
||||||
'data' => $kelasChartData,
|
|
||||||
],
|
|
||||||
'tugas_chart' => [
|
|
||||||
'labels' => $tugasChartLabels,
|
|
||||||
'data' => $tugasChartData,
|
|
||||||
'data_per_tugas' => $tugasChartDataPerTugas,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Guru;
|
|
||||||
|
|
||||||
class GuruRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Guru $guru)
|
|
||||||
{
|
|
||||||
$this->model = $guru;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('user')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("user", function ($query) use ($search) {
|
|
||||||
$query->where("email", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"user_id" => $data["user_id"],
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Kelas;
|
|
||||||
|
|
||||||
class KelasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Kelas $kelas)
|
|
||||||
{
|
|
||||||
$this->model = $kelas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
// return $this->model->where('id', $id)->update([
|
|
||||||
// "nama" => $data["nama"],
|
|
||||||
// ]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($kelas)
|
|
||||||
{
|
|
||||||
return $this->model->where('nama', $kelas)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Admin;
|
|
||||||
use App\Models\MataPelajaran;
|
|
||||||
|
|
||||||
class MataPelajaranRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(MataPelajaran $mataPelajaran)
|
|
||||||
{
|
|
||||||
$this->model = $mataPelajaran;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with(["guru", "kelas", "tahunAjaran"])->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%")
|
|
||||||
->orWhere("kelas", "like", "%" . $search . "%")
|
|
||||||
->orWhere("tahun_ajaran", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("guru", function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"guru_nip" => $data["guru_nip"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"guru_nip" => $data["guru_nip"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
// return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,115 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Materi;
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Notifications\MateriBaruNotification;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class MateriRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Materi $materi)
|
|
||||||
{
|
|
||||||
$this->model = $materi;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('mataPelajaran')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDataApi($matapelajaranId, $semester = 1, $type = "buku", $request)
|
|
||||||
{
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($matapelajaranId, $semester, $type) {
|
|
||||||
$query->where("matapelajaran_id", $matapelajaranId)
|
|
||||||
->where("semester", $semester)
|
|
||||||
->where("type", $type);
|
|
||||||
})
|
|
||||||
->with("mataPelajaran");
|
|
||||||
|
|
||||||
if ($request->user->role == "siswa") {
|
|
||||||
$query->where(function ($query) use ($request) {
|
|
||||||
$query->where("tahun_ajaran", $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query->whereHas("mataPelajaran", function ($query) use ($request) {
|
|
||||||
$query->where("guru_nip", $request->nip);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$query = $query->get();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$guru = Auth::user()->guru;
|
|
||||||
$query = $this->model->with('mataPelajaran')
|
|
||||||
->whereHas('mataPelajaran', function ($query) use ($guru) {
|
|
||||||
$query->where('guru_nip', $guru->nip);
|
|
||||||
})
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("semester", "like", "%" . $search . "%")
|
|
||||||
->orWhere("type", "like", "%" . $search . "%")
|
|
||||||
->orWhere("judul_materi", "like", "%" . $search . "%")
|
|
||||||
->orWhere("tahun_ajaran", "like", "%" . $search . "%")
|
|
||||||
->orWhereHas("mataPelajaran", function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
$materi = $this->model->create([
|
|
||||||
"tanggal" => $data["tanggal"],
|
|
||||||
"matapelajaran_id" => $data["matapelajaran_id"],
|
|
||||||
"semester" => $data["semester"],
|
|
||||||
"type" => $data["type"],
|
|
||||||
"judul_materi" => $data["judul_materi"],
|
|
||||||
"deskripsi" => $data["deskripsi"],
|
|
||||||
"path" => $data["path"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Cari siswa berdasarkan kelas dan tahun ajaran
|
|
||||||
$siswas = Siswa::where('tahun_ajaran', $data['tahun_ajaran'])->get();
|
|
||||||
|
|
||||||
// Kirim notifikasi ke setiap siswa
|
|
||||||
$materi->load('mataPelajaran');
|
|
||||||
foreach ($siswas as $siswa) {
|
|
||||||
$siswa->notify(new MateriBaruNotification($materi));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $materi;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"tanggal" => $data["tanggal"],
|
|
||||||
"matapelajaran_id" => $data["matapelajaran_id"],
|
|
||||||
"semester" => $data["semester"],
|
|
||||||
"type" => $data["type"],
|
|
||||||
"judul_materi" => $data["judul_materi"],
|
|
||||||
"deskripsi" => $data["deskripsi"],
|
|
||||||
"path" => $data["path"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,219 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Http\Controllers\Traits\ApiResponse;
|
|
||||||
use App\Models\QuizAttemptAnswers;
|
|
||||||
use App\Models\QuizAttempts;
|
|
||||||
use App\Models\QuizLevelSetting;
|
|
||||||
use App\Models\QuizQuestions;
|
|
||||||
use App\Models\Quizzes;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class QuizRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
protected $modelQuizzes;
|
|
||||||
|
|
||||||
use ApiResponse;
|
|
||||||
|
|
||||||
public function __construct(QuizQuestions $quizQuestions, Quizzes $quizzes)
|
|
||||||
{
|
|
||||||
$this->model = $quizQuestions;
|
|
||||||
$this->modelQuizzes = $quizzes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function apiGetQuizzes($id)
|
|
||||||
{
|
|
||||||
$nisn = Auth::user()->siswa->nisn;
|
|
||||||
$query = Quizzes::where('matapelajaran_id', $id)
|
|
||||||
->with([
|
|
||||||
'quizAttempt' => function ($q) use ($nisn) {
|
|
||||||
$q->where('nisn', $nisn);
|
|
||||||
}
|
|
||||||
])
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function apiGetQuizzesGuru($request, $id)
|
|
||||||
{
|
|
||||||
$query = Quizzes::where('matapelajaran_id', $id)
|
|
||||||
->whereHas('mataPelajaran', function ($q) use ($request) {
|
|
||||||
$q->where('kelas', $request->kelas)
|
|
||||||
->where('tahun_ajaran', $request->tahun_ajaran);
|
|
||||||
})
|
|
||||||
->get();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($request)
|
|
||||||
{
|
|
||||||
$query = $this->model->with('quiz')
|
|
||||||
->whereHas('quiz', function ($q) use ($request) {
|
|
||||||
$q->where('matapelajaran_id', $request->matapelajaran_id)
|
|
||||||
->where('judul', $request->judul);
|
|
||||||
})
|
|
||||||
->whereHas('quiz.mataPelajaran', function ($q) use ($request) {
|
|
||||||
$q->where('kelas', $request->kelas)
|
|
||||||
->where('tahun_ajaran', $request->tahun_ajaran);
|
|
||||||
})->get();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function nextQuestion($attempt_id)
|
|
||||||
{
|
|
||||||
$attempt = QuizAttempts::findOrFail((int) $attempt_id);
|
|
||||||
|
|
||||||
// Ambil total soal tampil dari quiz
|
|
||||||
$quiz = Quizzes::findOrFail((int) $attempt->quiz_id);
|
|
||||||
|
|
||||||
// Kalau sudah mencapai total soal tampil, jangan kasih soal lagi
|
|
||||||
if ($attempt->jumlahJawaban() >= $quiz->total_soal_tampil) {
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Semua soal sudah dijawab.',
|
|
||||||
], 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Kalau belum, ambil 1 soal random di level sekarang
|
|
||||||
// Find the attempt by given ID
|
|
||||||
$question = QuizQuestions::where('quiz_id', $attempt->quiz_id)
|
|
||||||
->where('level', $attempt->level_akhir)
|
|
||||||
// Get the total soal tampil from the quiz
|
|
||||||
->whereDoesntHave('attemptAnswers', function ($q) use ($attempt_id) {
|
|
||||||
$q->where('attempt_id', $attempt_id);
|
|
||||||
})
|
|
||||||
->inRandomOrder()
|
|
||||||
->first();
|
|
||||||
|
|
||||||
$quizAttemptAnswer = QuizAttemptAnswers::where('attempt_id', $attempt_id)->count();
|
|
||||||
|
|
||||||
if (!$question) {
|
|
||||||
return response()->json([
|
|
||||||
'message' => 'Tidak ada soal lagi di level ini.',
|
|
||||||
], 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$question['pertanyaan'] = $quizAttemptAnswer + 1 . ". " . $question->pertanyaan;
|
|
||||||
|
|
||||||
return $question;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function answer($request, $attempt_id)
|
|
||||||
{
|
|
||||||
$request->validate([
|
|
||||||
'question_id' => 'required|integer',
|
|
||||||
// Hilangkan validasi in:a,b,c,d agar jawaban_siswa boleh kosong
|
|
||||||
'jawaban_siswa' => 'nullable',
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Validasi attempt
|
|
||||||
$attempt = QuizAttempts::findOrFail($attempt_id);
|
|
||||||
|
|
||||||
// Validasi question exists dan belongs to the correct quiz
|
|
||||||
$question = QuizQuestions::where('id', $request->question_id)
|
|
||||||
->where('quiz_id', $attempt->quiz_id)
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if (!$question) {
|
|
||||||
throw new \Exception('The selected question is invalid or does not belong to this quiz.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$quizzes = Quizzes::findOrFail($attempt->quiz_id);
|
|
||||||
$quizLevelSettings = QuizLevelSetting::where('quiz_id', $attempt->quiz_id)->first();
|
|
||||||
|
|
||||||
$jumlahSoalPerLevel = json_decode($quizLevelSettings->jumlah_soal_per_level, true);
|
|
||||||
$batasNaikLevel = json_decode($quizLevelSettings->batas_naik_level, true);
|
|
||||||
|
|
||||||
// Jika jawaban kosong, otomatis salah
|
|
||||||
$isCorrect = ($request->jawaban_siswa && $request->jawaban_siswa == $question->jawaban_benar) ? 1 : 0;
|
|
||||||
|
|
||||||
// Hitung skor tambahan
|
|
||||||
$skor_tambahan = 0;
|
|
||||||
if ($isCorrect) {
|
|
||||||
$skor_tambahan = $question->skor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tambahkan skor ke attempt
|
|
||||||
$attempt->skor += $skor_tambahan;
|
|
||||||
|
|
||||||
// Simpan jawaban (jika kosong, simpan string kosong)
|
|
||||||
QuizAttemptAnswers::create([
|
|
||||||
'attempt_id' => $attempt->id,
|
|
||||||
'question_id' => $question->id,
|
|
||||||
'jawaban_siswa' => $request->jawaban_siswa ?? '',
|
|
||||||
'benar' => $isCorrect,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Update jumlah soal dijawab
|
|
||||||
$attempt->jumlah_soal_dijawab++;
|
|
||||||
|
|
||||||
// cek fase
|
|
||||||
foreach ($jumlahSoalPerLevel as $key => $value) {
|
|
||||||
$lvlNumber = preg_replace('/[^0-9]/', '', $key);
|
|
||||||
|
|
||||||
|
|
||||||
if ($attempt->fase == $lvlNumber) {
|
|
||||||
$benar = json_decode($attempt->benar, true) ?? [];
|
|
||||||
$jumlahFase = count($jumlahSoalPerLevel);
|
|
||||||
$isLastFase = $attempt->fase == $jumlahFase;
|
|
||||||
|
|
||||||
if (!$isLastFase && $isCorrect) {
|
|
||||||
$benar['fase' . $lvlNumber] = ($benar['fase' . $lvlNumber] ?? 0) + ($isCorrect ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
$attempt->benar = json_encode($benar);
|
|
||||||
|
|
||||||
if ($attempt->jumlah_soal_dijawab == $value) {
|
|
||||||
if ($benar['fase' . $lvlNumber] >= $batasNaikLevel['fase' . $lvlNumber]) {
|
|
||||||
// if ($attempt->level_akhir < $lvlNumber) {
|
|
||||||
$attempt->level_akhir += 1;
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
$attempt->level_akhir;
|
|
||||||
}
|
|
||||||
|
|
||||||
$attempt->fase += 1;
|
|
||||||
$attempt->jumlah_soal_dijawab = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$attempt->save();
|
|
||||||
|
|
||||||
$jumlah_jawaban = QuizAttemptAnswers::where('attempt_id', $attempt->id)->count();
|
|
||||||
$total_soal_tampil = $quizzes->total_soal_tampil;
|
|
||||||
$selesai = $jumlah_jawaban >= $total_soal_tampil;
|
|
||||||
|
|
||||||
return [
|
|
||||||
'quiz_id' => $attempt->quiz_id,
|
|
||||||
'correct' => $isCorrect,
|
|
||||||
'fase' => $attempt->fase,
|
|
||||||
'new_level' => $attempt->level_akhir,
|
|
||||||
'skor_sementara' => $attempt->skor,
|
|
||||||
'selesai' => $selesai,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFinishQuiz($quizId)
|
|
||||||
{
|
|
||||||
$attempt = QuizAttempts::where('quiz_id', $quizId)
|
|
||||||
->where('nisn', Auth::user()->siswa->nisn)
|
|
||||||
->orderByDesc('id') // ambil attempt terbaru
|
|
||||||
->first();
|
|
||||||
|
|
||||||
if (!$attempt) {
|
|
||||||
return $this->errorApiResponse('Data tidak ditemukan', 404);
|
|
||||||
}
|
|
||||||
|
|
||||||
$attempt->jumlah_soal = $attempt->quizzes()->first()->total_soal_tampil;
|
|
||||||
$attempt->jawaban_benar = (string) QuizAttemptAnswers::where('attempt_id', $attempt->id)->where('benar', 1)->count();
|
|
||||||
$attempt->jawaban_salah = (string) QuizAttemptAnswers::where('attempt_id', $attempt->id)->where('benar', "0")->count();
|
|
||||||
|
|
||||||
return $this->okApiResponse($attempt);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Siswa;
|
|
||||||
|
|
||||||
class SiswaRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Siswa $siswa)
|
|
||||||
{
|
|
||||||
$this->model = $siswa;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('user')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%")
|
|
||||||
->orWhere("nisn", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("user", function ($query) use ($search) {
|
|
||||||
$query->where("email", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"user_id" => $data["user_id"],
|
|
||||||
"nisn" => $data["nisn"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"nisn" => $data["nisn"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Guru;
|
|
||||||
|
|
||||||
class SubmitTugasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(Guru $guru)
|
|
||||||
{
|
|
||||||
$this->model = $guru;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('user')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("user", function ($query) use ($search) {
|
|
||||||
$query->where("email", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"user_id" => $data["user_id"],
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"nip" => $data["nip"],
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"jk" => $data["jk"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\TahunAjaran;
|
|
||||||
|
|
||||||
class TahunAjaranRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(TahunAjaran $tahunAjaran)
|
|
||||||
{
|
|
||||||
$this->model = $tahunAjaran;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("tahun", "like", "%" . $search . "%")
|
|
||||||
->orWhere("status", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"tahun" => $data["tahun"],
|
|
||||||
"status" => "aktif",
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $tahun)
|
|
||||||
{
|
|
||||||
return $this->model->where('tahun', $tahun)->update([
|
|
||||||
"status" => $data["status"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($tahun)
|
|
||||||
{
|
|
||||||
return $this->model->where('tahun', $tahun)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,111 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\Siswa;
|
|
||||||
use App\Models\Tugas;
|
|
||||||
use App\Notifications\TugasBaruNotification;
|
|
||||||
use GuzzleHttp\Psr7\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
|
||||||
|
|
||||||
class TugasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
protected $nipUser;
|
|
||||||
|
|
||||||
public function __construct(Tugas $tugas)
|
|
||||||
{
|
|
||||||
$this->model = $tugas;
|
|
||||||
$this->nipUser = Auth::user()->guru->nip;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDataApi($request)
|
|
||||||
{
|
|
||||||
$query = $this->model->with('mataPelajaran');
|
|
||||||
|
|
||||||
if ($request->user->role == "siswa") {
|
|
||||||
$query->where(function ($query) use ($request) {
|
|
||||||
$query->where("kelas", $request->kelas)
|
|
||||||
->where("tahun_ajaran", $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$query->where(function ($query) use ($request) {
|
|
||||||
$query->where("guru_nip", $request->nip)
|
|
||||||
->orWhere('kelas', $request->kelas)
|
|
||||||
->orWhere('kelas', $request->tahun_ajaran);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$query = $query->get();
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with('mataPelajaran')->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$nipGuru = Auth::user()->guru->nip;
|
|
||||||
$query = $this->model->where('guru_nip', $nipGuru)
|
|
||||||
->where(function ($query) use ($search, $nipGuru) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%")
|
|
||||||
->orWhere("kelas", "like", "%" . $search . "%")
|
|
||||||
->orWhere("tahun_ajaran", "like", "%" . $search . "%")
|
|
||||||
->orWhereHas("mataPelajaran", function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
});
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
$tugas = $this->model->create([
|
|
||||||
"tanggal" => $data["tanggal"],
|
|
||||||
"tenggat" => $data["tenggat"],
|
|
||||||
"guru_nip" => $this->nipUser,
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"matapelajaran_id" => $data["matapelajaran_id"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
"deskripsi" => $data["deskripsi"] ?? null,
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Cari siswa berdasarkan kelas dan tahun ajaran
|
|
||||||
$siswas = Siswa::where('kelas', $data['kelas'])
|
|
||||||
->where('tahun_ajaran', $data['tahun_ajaran'])
|
|
||||||
->get();
|
|
||||||
|
|
||||||
// Kirim notifikasi ke setiap siswa
|
|
||||||
foreach ($siswas as $siswa) {
|
|
||||||
$siswa->notify(new TugasBaruNotification($tugas));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tugas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"tanggal" => $data["tanggal"],
|
|
||||||
"tenggat" => $data["tenggat"],
|
|
||||||
"guru_nip" => $this->nipUser,
|
|
||||||
"nama" => $data["nama"],
|
|
||||||
"matapelajaran_id" => $data["matapelajaran_id"],
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
"deskripsi" => $data["deskripsi"] ?? null,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,42 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\User;
|
|
||||||
|
|
||||||
class UserRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(User $user)
|
|
||||||
{
|
|
||||||
$this->model = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"email" => $data["email"],
|
|
||||||
"password" => $data["pass"],
|
|
||||||
"role" => $data["role"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"email" => $data["email"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Repositories;
|
|
||||||
|
|
||||||
use App\Models\WaliKelas;
|
|
||||||
|
|
||||||
class WaliKelasRepository
|
|
||||||
{
|
|
||||||
protected $model;
|
|
||||||
|
|
||||||
public function __construct(WaliKelas $waliKelas)
|
|
||||||
{
|
|
||||||
$this->model = $waliKelas;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function find($id)
|
|
||||||
{
|
|
||||||
return $this->model->with(["guru", "kelas"])->find($id);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getData($search, $limit = 10)
|
|
||||||
{
|
|
||||||
$search = strtolower($search);
|
|
||||||
$query = $this->model
|
|
||||||
->where(function ($query) use ($search) {
|
|
||||||
$query->where("tahun_ajaran", "like", "%" . $search . "%")
|
|
||||||
->orWhere("kelas", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->orWhereHas("guru", function ($query) use ($search) {
|
|
||||||
$query->where("nama", "like", "%" . $search . "%");
|
|
||||||
})
|
|
||||||
->paginate($limit);
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function store($data)
|
|
||||||
{
|
|
||||||
return $this->model->create([
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
"wali_nip" => $data["wali_nip"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update($data, $id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->update([
|
|
||||||
"kelas" => $data["kelas"],
|
|
||||||
"tahun_ajaran" => $data["tahun_ajaran"],
|
|
||||||
"wali_nip" => $data["wali_nip"],
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function destroy($id)
|
|
||||||
{
|
|
||||||
return $this->model->where('id', $id)->delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
namespace App\View\Components;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Illuminate\Contracts\View\View;
|
|
||||||
use Illuminate\View\Component;
|
|
||||||
|
|
||||||
class Icon extends Component
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Create a new component instance.
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the view / contents that represent the component.
|
|
||||||
*/
|
|
||||||
public function render(): View|Closure|string
|
|
||||||
{
|
|
||||||
return view('components.icon');
|
|
||||||
}
|
|
||||||
}
|
|
15
artisan
|
@ -1,15 +0,0 @@
|
||||||
#!/usr/bin/env php
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Symfony\Component\Console\Input\ArgvInput;
|
|
||||||
|
|
||||||
define('LARAVEL_START', microtime(true));
|
|
||||||
|
|
||||||
// Register the Composer autoloader...
|
|
||||||
require __DIR__.'/vendor/autoload.php';
|
|
||||||
|
|
||||||
// Bootstrap Laravel and handle the command...
|
|
||||||
$status = (require_once __DIR__.'/bootstrap/app.php')
|
|
||||||
->handleCommand(new ArgvInput);
|
|
||||||
|
|
||||||
exit($status);
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"kelas": "VI",
|
||||||
|
"mapel": [
|
||||||
|
{
|
||||||
|
"nama": "Matematika",
|
||||||
|
"materi": [
|
||||||
|
{"id": 1, "judul": "Materi 1", "url": "url_materi_1"},
|
||||||
|
{"id": 2, "judul": "Materi 2", "url": "url_materi_2"},
|
||||||
|
{"id": 3, "judul": "Materi 3", "url": "url_materi_3"}
|
||||||
|
],
|
||||||
|
"video": [
|
||||||
|
{"id": 1, "judul": "Video 1", "url": "url_video_1"},
|
||||||
|
{"id": 2, "judul": "Video 2", "url": "url_video_2"},
|
||||||
|
{"id": 3, "judul": "Video 3", "url": "url_video_3"}
|
||||||
|
],
|
||||||
|
"update": "8 Agustus",
|
||||||
|
"semester": "1 & 2",
|
||||||
|
"guru": "Bu Siti"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nama": "Bahasa Inggris",
|
||||||
|
"materi": [
|
||||||
|
{"id": 1, "judul": "Materi 1", "url": "url_materi_1"},
|
||||||
|
{"id": 2, "judul": "Materi 2", "url": "url_materi_2"},
|
||||||
|
{"id": 3, "judul": "Materi 3", "url": "url_materi_3"}
|
||||||
|
],
|
||||||
|
"video": [
|
||||||
|
{"id": 1, "judul": "Video 1", "url": "url_video_1"},
|
||||||
|
{"id": 2, "judul": "Video 2", "url": "url_video_2"}
|
||||||
|
],
|
||||||
|
"update": "2 Agustus",
|
||||||
|
"semester": "1 & 2",
|
||||||
|
"guru": "Mrs. Ratna"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"nama": "Bahasa Indonesia",
|
||||||
|
"materi": [
|
||||||
|
{"id": 1, "judul": "Materi 1", "url": "url_materi_1"},
|
||||||
|
{"id": 2, "judul": "Materi 2", "url": "url_materi_2"},
|
||||||
|
{"id": 3, "judul": "Materi 3", "url": "url_materi_3"}
|
||||||
|
],
|
||||||
|
"video": [
|
||||||
|
{"id": 1, "judul": "Video 1", "url": "url_video_1"},
|
||||||
|
{"id": 2, "judul": "Video 2", "url": "url_video_2"}
|
||||||
|
],
|
||||||
|
"update": "2 Agustus",
|
||||||
|
"semester": "1 & 2",
|
||||||
|
"guru": "Mrs. Ratna"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
After Width: | Height: | Size: 558 B |
After Width: | Height: | Size: 8.6 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 167 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -1,21 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Foundation\Application;
|
|
||||||
use Illuminate\Foundation\Configuration\Exceptions;
|
|
||||||
use Illuminate\Foundation\Configuration\Middleware;
|
|
||||||
|
|
||||||
return Application::configure(basePath: dirname(__DIR__))
|
|
||||||
->withRouting(
|
|
||||||
web: __DIR__ . '/../routes/web.php',
|
|
||||||
api: __DIR__ . '/../routes/api.php',
|
|
||||||
commands: __DIR__ . '/../routes/console.php',
|
|
||||||
health: '/up',
|
|
||||||
)
|
|
||||||
->withMiddleware(function (Middleware $middleware) {
|
|
||||||
$middleware->alias([
|
|
||||||
'role' => \App\Http\Middleware\RoleMiddleware::class,
|
|
||||||
]);
|
|
||||||
})
|
|
||||||
->withExceptions(function (Exceptions $exceptions) {
|
|
||||||
//
|
|
||||||
})->create();
|
|
|
@ -1,2 +0,0 @@
|
||||||
*
|
|
||||||
!.gitignore
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
return [
|
|
||||||
App\Providers\AppServiceProvider::class,
|
|
||||||
];
|
|
|
@ -1,77 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://getcomposer.org/schema.json",
|
|
||||||
"name": "laravel/laravel",
|
|
||||||
"type": "project",
|
|
||||||
"description": "The skeleton application for the Laravel framework.",
|
|
||||||
"keywords": [
|
|
||||||
"laravel",
|
|
||||||
"framework"
|
|
||||||
],
|
|
||||||
"license": "MIT",
|
|
||||||
"require": {
|
|
||||||
"php": "^8.2",
|
|
||||||
"laravel/framework": "^11.31",
|
|
||||||
"laravel/sanctum": "^4.0",
|
|
||||||
"laravel/tinker": "^2.9",
|
|
||||||
"maatwebsite/excel": "^3.1",
|
|
||||||
"realrashid/sweet-alert": "^7.2"
|
|
||||||
},
|
|
||||||
"require-dev": {
|
|
||||||
"fakerphp/faker": "^1.23",
|
|
||||||
"laravel/pail": "^1.1",
|
|
||||||
"laravel/pint": "^1.13",
|
|
||||||
"laravel/sail": "^1.26",
|
|
||||||
"mockery/mockery": "^1.6",
|
|
||||||
"nunomaduro/collision": "^8.1",
|
|
||||||
"phpunit/phpunit": "^11.0.1"
|
|
||||||
},
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"App\\": "app/",
|
|
||||||
"Database\\Factories\\": "database/factories/",
|
|
||||||
"Database\\Seeders\\": "database/seeders/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload-dev": {
|
|
||||||
"psr-4": {
|
|
||||||
"Tests\\": "tests/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"post-autoload-dump": [
|
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
|
||||||
"@php artisan package:discover --ansi"
|
|
||||||
],
|
|
||||||
"post-update-cmd": [
|
|
||||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
|
|
||||||
],
|
|
||||||
"post-root-package-install": [
|
|
||||||
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
|
|
||||||
],
|
|
||||||
"post-create-project-cmd": [
|
|
||||||
"@php artisan key:generate --ansi",
|
|
||||||
"@php -r \"file_exists('database/database.sqlite') || touch('database/database.sqlite');\"",
|
|
||||||
"@php artisan migrate --graceful --ansi"
|
|
||||||
],
|
|
||||||
"dev": [
|
|
||||||
"Composer\\Config::disableProcessTimeout",
|
|
||||||
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"extra": {
|
|
||||||
"laravel": {
|
|
||||||
"dont-discover": []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"config": {
|
|
||||||
"optimize-autoloader": true,
|
|
||||||
"preferred-install": "dist",
|
|
||||||
"sort-packages": true,
|
|
||||||
"allow-plugins": {
|
|
||||||
"pestphp/pest-plugin": true,
|
|
||||||
"php-http/discovery": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"minimum-stability": "stable",
|
|
||||||
"prefer-stable": true
|
|
||||||
}
|
|